From: Owen Avery Date: Sun, 22 Mar 2026 22:48:57 +0000 (-0400) Subject: gccrs: Disambiguate identifier and path patterns X-Git-Tag: basepoints/gcc-17~171 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=9d80cc3487731ccbee7e76141aee25bc90f1cec4;p=thirdparty%2Fgcc.git gccrs: Disambiguate identifier and path patterns gcc/rust/ChangeLog: * Make-lang.in (GRS_OBJS): Add rust-identifier-path.o. * resolve/rust-early-name-resolver-2.0.cc: Include "rust-identifier-path.h". (Early::go): Use IdentifierPathPass. (Early::visit): Handle identifier patterns which should be path patterns. * resolve/rust-early-name-resolver-2.0.h: Include "rust-pattern.h". (Early::visit): Add visiting function declaration for IdentifierPattern. (Early::ident_path_to_convert): New member variable. * resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::visit): Call Mappings::add_function_node. * util/rust-hir-map.cc (Mappings::add_function_node): New member function definition. (Mappings::is_function_node): Likewise. * util/rust-hir-map.h (Mappings::add_function_node): New member function declaration. (Mappings::is_function_node): Likewise. (Mappings::function_nodes): New member variable. * resolve/rust-identifier-path.cc: New file. * resolve/rust-identifier-path.h: New file. gcc/testsuite/ChangeLog: * rust/execute/ident_pat_vs_path_1.rs: New test. * rust/execute/ident_pat_vs_path_2.rs: New test. Signed-off-by: Owen Avery --- diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index bd5646f7c37..4c394d39c0b 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -146,6 +146,7 @@ GRS_OBJS = \ rust/rust-finalize-imports-2.0.o \ rust/rust-ice-finalizer.o \ rust/rust-late-name-resolver-2.0.o \ + rust/rust-identifier-path.o \ rust/rust-immutable-name-resolution-context.o \ rust/rust-name-resolver.o \ rust/rust-resolve-builtins.o \ diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc index df29a55c8fb..91ad82c8966 100644 --- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc @@ -27,6 +27,7 @@ #include "rust-attributes.h" #include "rust-finalize-imports-2.0.h" #include "rust-attribute-values.h" +#include "rust-identifier-path.h" namespace Rust { namespace Resolver2_0 { @@ -70,6 +71,9 @@ Early::go (AST::Crate &crate) visit (crate); textual_scope.pop (); + + // handle IdentifierPattern vs PathInExpression disambiguation + IdentifierPathPass::go (crate, ctx, std::move (ident_path_to_convert)); } bool @@ -543,5 +547,29 @@ Early::visit (AST::UseTreeList &use_list) DefaultResolver::visit (use_list); } +void +Early::visit (AST::IdentifierPattern &identifier) +{ + // check if this is *really* a path pattern + if (!identifier.get_is_ref () && !identifier.get_is_mut () + && !identifier.has_subpattern ()) + { + auto res = ctx.values.get (identifier.get_ident ()); + if (res) + { + if (res->is_ambiguous ()) + rust_error_at (identifier.get_locus (), ErrorCode::E0659, + "%qs is ambiguous", + identifier.get_ident ().as_string ().c_str ()); + else + { + // HACK: bail out if the definition is a function + if (!ctx.mappings.is_function_node (res->get_node_id ())) + ident_path_to_convert.insert (identifier.get_node_id ()); + } + } + } +} + } // namespace Resolver2_0 } // namespace Rust diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.h b/gcc/rust/resolve/rust-early-name-resolver-2.0.h index bd9ccf66dec..0fdf1436cbd 100644 --- a/gcc/rust/resolve/rust-early-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.h @@ -26,6 +26,7 @@ #include "rust-default-resolver.h" #include "rust-rib.h" #include "rust-toplevel-name-resolver-2.0.h" +#include "rust-pattern.h" namespace Rust { namespace Resolver2_0 { @@ -67,6 +68,8 @@ public: void visit (AST::Attribute &) override; + void visit (AST::IdentifierPattern &) override; + struct ImportData { enum class Kind @@ -266,6 +269,9 @@ private: const Early::ImportPair &mapping); void finalize_rebind_import (const Early::ImportPair &mapping); + + /* used to help conversion from IdentifierPattern to PathInExpression */ + std::set ident_path_to_convert; }; } // namespace Resolver2_0 diff --git a/gcc/rust/resolve/rust-identifier-path.cc b/gcc/rust/resolve/rust-identifier-path.cc new file mode 100644 index 00000000000..30223a7b3d6 --- /dev/null +++ b/gcc/rust/resolve/rust-identifier-path.cc @@ -0,0 +1,61 @@ +// Copyright (C) 2026 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// . + +#include "rust-system.h" +#include "rust-identifier-path.h" +#include "rust-pattern.h" + +namespace Rust { +namespace Resolver2_0 { + +IdentifierPathPass::IdentifierPathPass (NameResolutionContext &ctx, + std::set ident_path_to_convert) + : ctx (&ctx), ident_path_to_convert (std::move (ident_path_to_convert)) +{} + +void +IdentifierPathPass::go (AST::Crate &crate, NameResolutionContext &ctx, + std::set ident_path_to_convert) +{ + IdentifierPathPass pass (ctx, std::move (ident_path_to_convert)); + pass.visit (crate); +} + +void +IdentifierPathPass::reseat (std::unique_ptr &ptr) +{ + AST::IdentifierPattern *ident_pat; + if (ptr->get_pattern_kind () == AST::Pattern::Kind::Identifier) + ident_pat = static_cast (ptr.get ()); + else + return; + + if (ident_path_to_convert.find (ident_pat->get_node_id ()) + != ident_path_to_convert.end ()) + { + std::vector segments; + segments.emplace_back (ident_pat->get_ident ().as_string (), + ident_pat->get_locus ()); + ptr = std::make_unique ( + std::move (segments), std::vector (), + ident_pat->get_locus ()); + } +} + +} // namespace Resolver2_0 +} // namespace Rust diff --git a/gcc/rust/resolve/rust-identifier-path.h b/gcc/rust/resolve/rust-identifier-path.h new file mode 100644 index 00000000000..5363a5e87ef --- /dev/null +++ b/gcc/rust/resolve/rust-identifier-path.h @@ -0,0 +1,50 @@ +// Copyright (C) 2026 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// . + +#ifndef RUST_RESOLVE_IDENTIFIER_PATH_H +#define RUST_RESOLVE_IDENTIFIER_PATH_H + +#include "rust-ast-pointer-visitor.h" +#include "rust-name-resolution-context.h" + +namespace Rust { +namespace Resolver2_0 { + +// changes IdentifierPattern instances to PathInExpression instances +class IdentifierPathPass : public AST::PointerVisitor +{ +public: + IdentifierPathPass (NameResolutionContext &ctx, + std::set ident_path_to_convert); + + static void go (AST::Crate &crate, NameResolutionContext &ctx, + std::set ident_path_to_convert); + + using AST::PointerVisitor::reseat; + + void reseat (std::unique_ptr &ptr) override; + +private: + NameResolutionContext *ctx; + std::set ident_path_to_convert; +}; + +} // namespace Resolver2_0 +} // namespace Rust + +#endif // ! RUST_RESOLVE_IDENTIFIER_PATH_H diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc index 2002df54596..630b5ab8b95 100644 --- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc @@ -241,6 +241,8 @@ TopLevel::visit (AST::Function &function) insert_or_error_out (function.get_function_name (), function, Namespace::Values); + Analysis::Mappings::get ().add_function_node (function.get_node_id ()); + DefaultResolver::visit (function); } diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc index a58fef00d46..89b95647861 100644 --- a/gcc/rust/util/rust-hir-map.cc +++ b/gcc/rust/util/rust-hir-map.cc @@ -1382,5 +1382,17 @@ Mappings::is_derived_node (NodeId node_id) return derived_nodes.find (node_id) != derived_nodes.end (); } +void +Mappings::add_function_node (NodeId node_id) +{ + function_nodes.insert (node_id); +} + +bool +Mappings::is_function_node (NodeId node_id) +{ + return function_nodes.find (node_id) != function_nodes.end (); +} + } // namespace Analysis } // namespace Rust diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h index c04e2efb7a4..7012dd5c2e0 100644 --- a/gcc/rust/util/rust-hir-map.h +++ b/gcc/rust/util/rust-hir-map.h @@ -353,6 +353,9 @@ public: void add_derived_node (NodeId node_id); bool is_derived_node (NodeId node_id); + void add_function_node (NodeId node_id); + bool is_function_node (NodeId node_id); + private: Mappings (); @@ -450,6 +453,8 @@ private: std::unordered_map> captures; std::set derived_nodes; + + std::set function_nodes; }; } // namespace Analysis diff --git a/gcc/testsuite/rust/execute/ident_pat_vs_path_1.rs b/gcc/testsuite/rust/execute/ident_pat_vs_path_1.rs new file mode 100644 index 00000000000..479e8700bac --- /dev/null +++ b/gcc/testsuite/rust/execute/ident_pat_vs_path_1.rs @@ -0,0 +1,27 @@ +// { dg-additional-options "-w" } +#![feature(no_core)] +#![no_core] + +enum E { + A, + B, + C +} + +fn main() -> i32 { + use E::C; + + let v1 = match E::A { + C => 1, + E::A => 0, + E::B => 1 + }; + + let v2 = match E::A { + B => 0, + E::A => 1, + C => 1 + }; + + v1 + v2 +} diff --git a/gcc/testsuite/rust/execute/ident_pat_vs_path_2.rs b/gcc/testsuite/rust/execute/ident_pat_vs_path_2.rs new file mode 100644 index 00000000000..bb6841f0ae4 --- /dev/null +++ b/gcc/testsuite/rust/execute/ident_pat_vs_path_2.rs @@ -0,0 +1,18 @@ +// { dg-additional-options "-w" } +#![feature(no_core)] +#![no_core] + +enum E { + A, + B, + C +} + +fn main() -> i32 { + use E::*; + + match A { + C => 1, + _ => 0 + } +}