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 \
#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 {
visit (crate);
textual_scope.pop ();
+
+ // handle IdentifierPattern vs PathInExpression disambiguation
+ IdentifierPathPass::go (crate, ctx, std::move (ident_path_to_convert));
}
bool
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
#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 {
void visit (AST::Attribute &) override;
+ void visit (AST::IdentifierPattern &) override;
+
struct ImportData
{
enum class Kind
const Early::ImportPair &mapping);
void finalize_rebind_import (const Early::ImportPair &mapping);
+
+ /* used to help conversion from IdentifierPattern to PathInExpression */
+ std::set<NodeId> ident_path_to_convert;
};
} // namespace Resolver2_0
--- /dev/null
+// 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
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-system.h"
+#include "rust-identifier-path.h"
+#include "rust-pattern.h"
+
+namespace Rust {
+namespace Resolver2_0 {
+
+IdentifierPathPass::IdentifierPathPass (NameResolutionContext &ctx,
+ std::set<NodeId> 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<NodeId> ident_path_to_convert)
+{
+ IdentifierPathPass pass (ctx, std::move (ident_path_to_convert));
+ pass.visit (crate);
+}
+
+void
+IdentifierPathPass::reseat (std::unique_ptr<AST::Pattern> &ptr)
+{
+ AST::IdentifierPattern *ident_pat;
+ if (ptr->get_pattern_kind () == AST::Pattern::Kind::Identifier)
+ ident_pat = static_cast<AST::IdentifierPattern *> (ptr.get ());
+ else
+ return;
+
+ if (ident_path_to_convert.find (ident_pat->get_node_id ())
+ != ident_path_to_convert.end ())
+ {
+ std::vector<AST::PathExprSegment> segments;
+ segments.emplace_back (ident_pat->get_ident ().as_string (),
+ ident_pat->get_locus ());
+ ptr = std::make_unique<AST::PathInExpression> (
+ std::move (segments), std::vector<AST::Attribute> (),
+ ident_pat->get_locus ());
+ }
+}
+
+} // namespace Resolver2_0
+} // namespace Rust
--- /dev/null
+// 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
+// <http://www.gnu.org/licenses/>.
+
+#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<NodeId> ident_path_to_convert);
+
+ static void go (AST::Crate &crate, NameResolutionContext &ctx,
+ std::set<NodeId> ident_path_to_convert);
+
+ using AST::PointerVisitor::reseat;
+
+ void reseat (std::unique_ptr<AST::Pattern> &ptr) override;
+
+private:
+ NameResolutionContext *ctx;
+ std::set<NodeId> ident_path_to_convert;
+};
+
+} // namespace Resolver2_0
+} // namespace Rust
+
+#endif // ! RUST_RESOLVE_IDENTIFIER_PATH_H
insert_or_error_out (function.get_function_name (), function,
Namespace::Values);
+ Analysis::Mappings::get ().add_function_node (function.get_node_id ());
+
DefaultResolver::visit (function);
}
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
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 ();
std::unordered_map<NodeId, std::vector<NodeId>> captures;
std::set<NodeId> derived_nodes;
+
+ std::set<NodeId> function_nodes;
};
} // namespace Analysis
--- /dev/null
+// { 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
+}
--- /dev/null
+// { dg-additional-options "-w" }
+#![feature(no_core)]
+#![no_core]
+
+enum E {
+ A,
+ B,
+ C
+}
+
+fn main() -> i32 {
+ use E::*;
+
+ match A {
+ C => 1,
+ _ => 0
+ }
+}