From: Utkarsh Bahuguna <[email protected]>
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]>
---
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/7db682a89f216f2ee95989cc486505969a164169
The commit has been mentioned in the following issue(s):
- Rust-GCC/gccrs#4589: https://github.com/Rust-GCC/gccrs/issues/4589
The commit has been mentioned in the following pull-request(s):
- https://github.com/Rust-GCC/gccrs/pull/4954
.../resolve/rust-early-name-resolver-2.0.cc | 26 +++++++++++-
.../resolve/rust-early-name-resolver-2.0.h | 16 ++++++--
gcc/testsuite/rust/compile/issue-4589.rs | 41 +++++++++++++++++++
3 files changed, 79 insertions(+), 4 deletions(-)
create mode 100644 gcc/testsuite/rust/compile/issue-4589.rs
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 4860163be..1422a300d 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 f2297d58e..c8cfe3891 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 000000000..b218b1896
--- /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();
+}
base-commit: f42ee1fd2b71c2865ed579c1547adbeb26a700ae
--
2.55.0