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;
+}

Reply via email to