https://gcc.gnu.org/g:9d6c9f1517299df224212974bacf0f1d9685740b
commit r17-1865-g9d6c9f1517299df224212974bacf0f1d9685740b Author: Yap Zhi Heng <[email protected]> Date: Tue Jun 2 20:45:18 2026 +0800 gccrs: Make `extern crate self` resolve to current crate gcc/rust/ChangeLog: * resolve/rust-default-resolver.h (DefaultResolver): Add new visited_crates member for recursion protection. * resolve/rust-default-resolver.cc (DefaultResolver::visit(ExternCrate)): Make references of `self` resolve to the current crate. Signed-off-by: Yap Zhi Heng <[email protected]> Diff: --- gcc/rust/resolve/rust-default-resolver.cc | 15 +++++++++++++-- gcc/rust/resolve/rust-default-resolver.h | 3 +++ gcc/testsuite/rust/compile/extern_crate_self.rs | 6 ++++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/gcc/rust/resolve/rust-default-resolver.cc b/gcc/rust/resolve/rust-default-resolver.cc index 098c81e9b17e..3b724c9e6e74 100644 --- a/gcc/rust/resolve/rust-default-resolver.cc +++ b/gcc/rust/resolve/rust-default-resolver.cc @@ -31,6 +31,11 @@ namespace Resolver2_0 { void DefaultResolver::visit (AST::Crate &crate) { + // Guard against infinite recursion: `extern crate self;` resolves to the + // current crate, causing visit(AST::Crate) to call itself infinitely. + if (!visited_crates.insert (crate.get_node_id ()).second) + return; + auto inner_fn = [this, &crate] () { AST::DefaultASTVisitor::visit (crate); }; auto &mappings = Analysis::Mappings::get (); @@ -444,7 +449,11 @@ void DefaultResolver::visit (AST::ExternCrate &crate) { auto &mappings = Analysis::Mappings::get (); - auto num_opt = mappings.lookup_crate_name (crate.get_referenced_crate ()); + tl::optional<CrateNum> num_opt; + if (crate.get_referenced_crate () == "self") + num_opt = mappings.get_current_crate (); + else + num_opt = mappings.lookup_crate_name (crate.get_referenced_crate ()); if (!num_opt) { @@ -462,7 +471,9 @@ DefaultResolver::visit (AST::ExternCrate &crate) auto sub_visitor_2 = [&] () { ctx.canonical_ctx.scope_crate (referenced_crate.get_node_id (), - crate.get_referenced_crate (), + crate.get_referenced_crate () == "self" + ? mappings.get_current_crate_name () + : crate.get_referenced_crate (), std::move (sub_visitor_1)); }; diff --git a/gcc/rust/resolve/rust-default-resolver.h b/gcc/rust/resolve/rust-default-resolver.h index 55ae2b15f235..d3e4e17f882f 100644 --- a/gcc/rust/resolve/rust-default-resolver.h +++ b/gcc/rust/resolve/rust-default-resolver.h @@ -20,6 +20,7 @@ #ifndef RUST_AST_DEFAULT_RESOLVER_H #define RUST_AST_DEFAULT_RESOLVER_H +#include "rust-system.h" #include "rust-ast-visitor.h" #include "rust-name-resolution-context.h" @@ -89,6 +90,8 @@ protected: DefaultResolver (NameResolutionContext &ctx) : ctx (ctx) {} NameResolutionContext &ctx; + + std::set<NodeId> visited_crates; }; } // namespace Resolver2_0 diff --git a/gcc/testsuite/rust/compile/extern_crate_self.rs b/gcc/testsuite/rust/compile/extern_crate_self.rs new file mode 100644 index 000000000000..920e52f1ef83 --- /dev/null +++ b/gcc/testsuite/rust/compile/extern_crate_self.rs @@ -0,0 +1,6 @@ +#![feature(no_core)] +#![no_core] + +fn main() { + extern crate self as my_crate; +}
