From: Yap Zhi Heng <[email protected]>

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]>
---
This change was merged into the gccrs repository and is posted here for
upstream visibility and potential drive-by review, as requested by GCC
release managers.
Each commit email contains a link to its details on github from where you can
find the Pull-Request and associated discussions.


Commit on github: 
https://github.com/Rust-GCC/gccrs/commit/367269fd522a923bd1e8de3f58f7228d6f45bc35

The commit has NOT been mentioned in any issue.

The commit has been mentioned in the following pull-request(s):
 - https://github.com/Rust-GCC/gccrs/pull/4570

 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(-)
 create mode 100644 gcc/testsuite/rust/compile/extern_crate_self.rs

diff --git a/gcc/rust/resolve/rust-default-resolver.cc 
b/gcc/rust/resolve/rust-default-resolver.cc
index 098c81e9b..3b724c9e6 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 55ae2b15f..d3e4e17f8 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 000000000..920e52f1e
--- /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;
+}

base-commit: 16a37ba94b143f0f1e9987d0380fca1ae309406f
-- 
2.54.0

Reply via email to