From ebc10a44555d968d232b9ba6525df5a890b9ae4c Mon Sep 17 00:00:00 2001 From: bohan Date: Tue, 7 May 2024 16:12:58 +0800 Subject: [PATCH] resolve: mark it undetermined if single import is not has any bindings --- .../rustc_resolve/src/build_reduced_graph.rs | 4 +++ compiler/rustc_resolve/src/ident.rs | 21 +++++++++++++++ compiler/rustc_resolve/src/imports.rs | 11 ++++++-- tests/crashes/124490.rs | 16 ------------ .../imports/cycle-import-in-diff-module-0.rs | 14 ++++++++++ .../imports/cycle-import-in-diff-module-1.rs | 14 ++++++++++ .../shadow-glob-module-resolution-1.rs | 17 ++++++++++++ .../shadow-glob-module-resolution-1.stderr | 23 ++++++++++++++++ .../shadow-glob-module-resolution-2.rs | 19 ++++++++++++++ .../shadow-glob-module-resolution-2.stderr | 26 +++++++++++++++++++ 10 files changed, 147 insertions(+), 18 deletions(-) delete mode 100644 tests/crashes/124490.rs create mode 100644 tests/ui/imports/cycle-import-in-diff-module-0.rs create mode 100644 tests/ui/imports/cycle-import-in-diff-module-1.rs create mode 100644 tests/ui/imports/shadow-glob-module-resolution-1.rs create mode 100644 tests/ui/imports/shadow-glob-module-resolution-1.stderr create mode 100644 tests/ui/imports/shadow-glob-module-resolution-2.rs create mode 100644 tests/ui/imports/shadow-glob-module-resolution-2.stderr diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 3e9aa3e0a6f21..292702761b9b9 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -355,6 +355,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { parent_scope: self.parent_scope, module_path, imported_module: Cell::new(None), + indeterminate: Cell::new(true), span, use_span: item.span, use_span_with_attributes: item.span_with_attributes(), @@ -871,6 +872,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { root_id: item.id, parent_scope: self.parent_scope, imported_module: Cell::new(module), + indeterminate: Cell::new(false), has_attributes: !item.attrs.is_empty(), use_span_with_attributes: item.span_with_attributes(), use_span: item.span, @@ -1072,6 +1074,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { root_id: item.id, parent_scope: this.parent_scope, imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))), + indeterminate: Cell::new(false), use_span_with_attributes: item.span_with_attributes(), has_attributes: !item.attrs.is_empty(), use_span: item.span, @@ -1236,6 +1239,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { root_id: item.id, parent_scope: self.parent_scope, imported_module: Cell::new(None), + indeterminate: Cell::new(false), has_attributes: false, use_span_with_attributes: span, use_span: span, diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 43a43e01a9adf..d0cea731422a0 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -967,6 +967,21 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // if it can then our result is not determined and can be invalidated. for single_import in &resolution.single_imports { let Some(import_vis) = single_import.vis.get() else { + // This branch handles a cycle in single imports, which occurs + // when we've previously captured the `vis` value during an import + // process. + // + // For example: + // ``` + // use a::b; + // use b as a; + // ``` + // 1. Steal the `vis` in `use a::b` and attempt to locate `a` in the + // current module. + // 2. Encounter the import `use b as a`, which is a `single_import` for `a`, + // and try to find `b` in the current module. + // 3. Re-encounter the `use a::b` import since it's a `single_import` of `b`. + // This leads to entering this branch. continue; }; if !self.is_accessible_from(import_vis, parent_scope.module) { @@ -981,6 +996,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // named imports. continue; } + + if single_import.indeterminate.get() + && binding.map_or(false, |binding| binding.module().is_some()) + { + return Err((Undetermined, Weak::No)); + } let Some(module) = single_import.imported_module.get() else { return Err((Undetermined, Weak::No)); }; diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 3d9380a3ebd35..632e089598c07 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -173,6 +173,8 @@ pub(crate) struct ImportData<'a> { pub module_path: Vec, /// The resolution of `module_path`. pub imported_module: Cell>>, + /// `true` if this import is indeterminate in all namespaces. + pub indeterminate: Cell, pub vis: Cell>, pub used: Cell>, } @@ -351,9 +353,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { (old_glob @ true, false) | (old_glob @ false, true) => { let (glob_binding, nonglob_binding) = if old_glob { (old_binding, binding) } else { (binding, old_binding) }; - if glob_binding.res() != nonglob_binding.res() - && key.ns == MacroNS + if key.ns == MacroNS && nonglob_binding.expansion != LocalExpnId::ROOT + && glob_binding.res() != nonglob_binding.res() { resolution.binding = Some(this.ambiguity( AmbiguityKind::GlobVsExpanded, @@ -794,6 +796,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { .. } => (source, target, source_bindings, target_bindings, type_ns_only), ImportKind::Glob { .. } => { + import.indeterminate.set(false); self.resolve_glob_import(import); return 0; } @@ -844,6 +847,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } }); + if indeterminate_count < 3 { + import.indeterminate.set(false); + } + indeterminate_count } diff --git a/tests/crashes/124490.rs b/tests/crashes/124490.rs deleted file mode 100644 index 9f605c32cf261..0000000000000 --- a/tests/crashes/124490.rs +++ /dev/null @@ -1,16 +0,0 @@ -//@ known-bug: rust-lang/rust#124490 -use io::{self as std}; -use std::collections::{self as io}; - -mod a { - pub mod b { - pub mod c {} - } -} - -use a::*; - -use b::c; -use c as b; - -fn main() {} diff --git a/tests/ui/imports/cycle-import-in-diff-module-0.rs b/tests/ui/imports/cycle-import-in-diff-module-0.rs new file mode 100644 index 0000000000000..962603a89716c --- /dev/null +++ b/tests/ui/imports/cycle-import-in-diff-module-0.rs @@ -0,0 +1,14 @@ +//@ check-pass + +// https://github.com/rust-lang/rust/pull/124840#issuecomment-2098148587 + +mod a { + pub(crate) use crate::S; +} +mod b { + pub struct S; +} +use self::a::S; +use self::b::*; + +fn main() {} diff --git a/tests/ui/imports/cycle-import-in-diff-module-1.rs b/tests/ui/imports/cycle-import-in-diff-module-1.rs new file mode 100644 index 0000000000000..8c67df376c3f9 --- /dev/null +++ b/tests/ui/imports/cycle-import-in-diff-module-1.rs @@ -0,0 +1,14 @@ +//@ check-pass + +// similar `cycle-import-in-diff-module-0.rs` + +mod a { + pub(crate) use crate::s; +} +mod b { + pub mod s {} +} +use self::b::*; +use self::a::s; + +fn main() {} diff --git a/tests/ui/imports/shadow-glob-module-resolution-1.rs b/tests/ui/imports/shadow-glob-module-resolution-1.rs new file mode 100644 index 0000000000000..ba1e65cddc652 --- /dev/null +++ b/tests/ui/imports/shadow-glob-module-resolution-1.rs @@ -0,0 +1,17 @@ +// https://github.com/rust-lang/rust/issues/124490 + +mod a { + pub mod b { + pub mod c {} + } +} + +use a::*; + +use b::c; +//~^ ERROR: cannot determine resolution for the import +//~| ERROR: cannot determine resolution for the import +//~| ERROR: unresolved import `b::c` +use c as b; + +fn main() {} diff --git a/tests/ui/imports/shadow-glob-module-resolution-1.stderr b/tests/ui/imports/shadow-glob-module-resolution-1.stderr new file mode 100644 index 0000000000000..f9135963fe99e --- /dev/null +++ b/tests/ui/imports/shadow-glob-module-resolution-1.stderr @@ -0,0 +1,23 @@ +error: cannot determine resolution for the import + --> $DIR/shadow-glob-module-resolution-1.rs:11:5 + | +LL | use b::c; + | ^^^^ + +error: cannot determine resolution for the import + --> $DIR/shadow-glob-module-resolution-1.rs:11:5 + | +LL | use b::c; + | ^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0432]: unresolved import `b::c` + --> $DIR/shadow-glob-module-resolution-1.rs:11:5 + | +LL | use b::c; + | ^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/shadow-glob-module-resolution-2.rs b/tests/ui/imports/shadow-glob-module-resolution-2.rs new file mode 100644 index 0000000000000..36bd72658ae84 --- /dev/null +++ b/tests/ui/imports/shadow-glob-module-resolution-2.rs @@ -0,0 +1,19 @@ +// https://github.com/rust-lang/rust/issues/125013 + +mod a { + pub mod b { + pub mod c { + pub trait D {} + } + } +} + +use a::*; + +use e as b; +//~^ ERROR: unresolved import `e` +use b::c::D as e; +//~^ ERROR: cannot determine resolution for the import +//~| ERROR: cannot determine resolution for the import + +fn main() { } diff --git a/tests/ui/imports/shadow-glob-module-resolution-2.stderr b/tests/ui/imports/shadow-glob-module-resolution-2.stderr new file mode 100644 index 0000000000000..644fcb8416289 --- /dev/null +++ b/tests/ui/imports/shadow-glob-module-resolution-2.stderr @@ -0,0 +1,26 @@ +error: cannot determine resolution for the import + --> $DIR/shadow-glob-module-resolution-2.rs:15:5 + | +LL | use b::c::D as e; + | ^^^^^^^^^^^^ + +error: cannot determine resolution for the import + --> $DIR/shadow-glob-module-resolution-2.rs:15:5 + | +LL | use b::c::D as e; + | ^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0432]: unresolved import `e` + --> $DIR/shadow-glob-module-resolution-2.rs:13:5 + | +LL | use e as b; + | -^^^^^ + | | + | no `e` in the root + | help: a similar name exists in the module: `a` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0432`.