https://gcc.gnu.org/g:b6a0e55603f4497210ccbf9b49f18db1901cc68b

commit r17-5706-gb6a0e55603f4497210ccbf9b49f18db1901cc68b
Author: Utkarsh Bahuguna <[email protected]>
Date:   Sat Oct 3 13:31:45 2026 +0530

    gccrs: Resolve 2015 use paths from the crate root
    
    In the 2015 edition use paths start at the crate root, but we resolved
    them from the current module, so `use foo::bar` in a submodule failed.
    Work out the resolution mode of each import path and pass it to
    resolve_path.
    
    Fixes Rust-GCC/gccrs#4589
    
    Assisted-by: Claude Opus 5.5 (Anthropic)
    
    gcc/rust/ChangeLog:
    
            * resolve/rust-early-name-resolver-2.0.h
            (Early::import_resolution_mode): Declare.
            (Early::resolve_path_in_all_ns): Use it.
            * resolve/rust-early-name-resolver-2.0.cc
            (Early::import_resolution_mode): New function.
            (Early::resolve_glob_import): Use it.
    
    gcc/testsuite/ChangeLog:
    
            * rust/compile/issue-4589.rs: New test.
    
    Signed-off-by: Utkarsh Bahuguna <[email protected]>

Diff:
---
 gcc/rust/resolve/rust-early-name-resolver-2.0.cc | 26 ++++++++++++++-
 gcc/rust/resolve/rust-early-name-resolver-2.0.h  | 16 +++++++--
 gcc/testsuite/rust/compile/issue-4589.rs         | 41 ++++++++++++++++++++++++
 3 files changed, 79 insertions(+), 4 deletions(-)

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 4860163beb64..1422a300d5d6 100644
--- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
@@ -31,6 +31,7 @@
 #include "rust-attribute-values.h"
 #include "rust-identifier-path.h"
 #include "rust-session-manager.h"
+#include "rust-edition.h"
 
 namespace Rust {
 namespace Resolver2_0 {
@@ -86,10 +87,33 @@ Early::go (AST::Crate &crate)
   IdentifierPathPass::go (crate, ctx, std::move (ident_path_to_convert));
 }
 
+ResolutionMode
+Early::import_resolution_mode (const AST::SimplePath &path)
+{
+  bool is_2015 = get_rust_edition () == Edition::E2015;
+
+  if (path.has_opening_scope_resolution ())
+    return is_2015 ? ResolutionMode::FromRoot : ResolutionMode::FromExtern;
+
+  if (!is_2015)
+    return ResolutionMode::Normal;
+
+  // `use *;` has no segments, and imports from the crate root as well
+  auto &segments = path.get_segments ();
+  if (!segments.empty ()
+      && (segments.front ().is_lower_self_seg ()
+         || segments.front ().is_super_path_seg ()))
+    return ResolutionMode::Normal;
+
+  return ResolutionMode::FromRoot;
+}
+
 bool
 Early::resolve_glob_import (NodeId use_dec_id, TopLevel::ImportKind &&glob)
 {
-  auto resolved = ctx.resolve_path (glob.to_resolve, Namespace::Types);
+  auto resolved = ctx.resolve_path (glob.to_resolve.get_segments (),
+                                   import_resolution_mode (glob.to_resolve),
+                                   Namespace::Types);
   if (!resolved.has_value ())
     return false;
 
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 f2297d58eb8e..c8cfe38911c5 100644
--- a/gcc/rust/resolve/rust-early-name-resolver-2.0.h
+++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.h
@@ -212,10 +212,17 @@ private:
   bool resolve_glob_import (NodeId use_dec_id, TopLevel::ImportKind &&import);
   bool resolve_rebind_import (NodeId use_dec_id, TopLevel::ImportKind 
&&import);
 
+  // In the 2015 edition, a use path is relative to the crate root unless it
+  // starts with self or super.
+  static ResolutionMode import_resolution_mode (const AST::SimplePath &path);
+
   template <typename P>
   std::vector<NameResolutionContext::NamespacedDefinition>
   resolve_path_in_all_ns (const P &path)
   {
+    auto &segments = path.get_segments ();
+    auto mode = import_resolution_mode (path);
+
     std::vector<NameResolutionContext::NamespacedDefinition> resolved;
 
     std::vector<Error> value_errors;
@@ -227,9 +234,12 @@ private:
          resolved.emplace_back (new_def);
        };
 
-    ctx.resolve_path (path, value_errors, Namespace::Values).map (resolved_fn);
-    ctx.resolve_path (path, type_errors, Namespace::Types).map (resolved_fn);
-    ctx.resolve_path (path, macro_errors, Namespace::Macros).map (resolved_fn);
+    ctx.resolve_path (segments, mode, value_errors, Namespace::Values)
+      .map (resolved_fn);
+    ctx.resolve_path (segments, mode, type_errors, Namespace::Types)
+      .map (resolved_fn);
+    ctx.resolve_path (segments, mode, macro_errors, Namespace::Macros)
+      .map (resolved_fn);
 
     if (!value_errors.empty () && !type_errors.empty ()
        && !macro_errors.empty ())
diff --git a/gcc/testsuite/rust/compile/issue-4589.rs 
b/gcc/testsuite/rust/compile/issue-4589.rs
new file mode 100644
index 000000000000..b218b1896efd
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-4589.rs
@@ -0,0 +1,41 @@
+// { dg-additional-options "-frust-edition=2015" }
+
+#![feature(no_core)]
+#![no_core]
+
+pub mod foo {
+    pub fn bar() {}
+}
+
+pub mod baz {
+    pub use foo::bar;
+
+    pub mod inner {
+        pub use self::nested::f;
+        pub use super::bar as g;
+
+        pub mod nested {
+            pub fn f() {}
+        }
+    }
+}
+
+pub mod qux {
+    pub use foo::*;
+}
+
+pub mod quux {
+    use *;
+
+    pub fn h() {
+        foo::bar();
+    }
+}
+
+fn main() {
+    baz::bar();
+    baz::inner::f();
+    baz::inner::g();
+    qux::bar();
+    quux::h();
+}

Reply via email to