diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 57db765c07e55..78bd3c4e49f2e 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -965,6 +965,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) { @@ -979,15 +994,25 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // named imports. continue; } + let Some(module) = single_import.imported_module.get() else { return Err((Undetermined, Weak::No)); }; - let ImportKind::Single { source: ident, .. } = single_import.kind else { + let ImportKind::Single { source: ident, source_bindings, .. } = &single_import.kind + else { unreachable!(); }; + if binding.map_or(false, |binding| binding.module().is_some()) + && source_bindings.iter().all(|binding| matches!(binding.get(), Err(Undetermined))) + { + // This branch allows the binding to be defined or updated later, + // avoiding module inconsistency between the resolve process and the finalize process. + // See more details in #124840 + return Err((Undetermined, Weak::No)); + } match self.resolve_ident_in_module( module, - ident, + *ident, ns, &single_import.parent_scope, None, diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 6bbde26db3443..27ea7760f5893 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -352,9 +352,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, 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/crashes/125013-1.rs b/tests/crashes/125013-1.rs deleted file mode 100644 index ae66d7a146698..0000000000000 --- a/tests/crashes/125013-1.rs +++ /dev/null @@ -1,5 +0,0 @@ -//@ known-bug: rust-lang/rust#125013 -//@ edition:2021 -use io::{self as std}; -use std::ops::Deref::{self as io}; -pub fn main() {} diff --git a/tests/crashes/125013-2.rs b/tests/crashes/125013-2.rs deleted file mode 100644 index a14c8a76b63ee..0000000000000 --- a/tests/crashes/125013-2.rs +++ /dev/null @@ -1,16 +0,0 @@ -//@ known-bug: rust-lang/rust#125013 -//@ edition:2021 -mod a { - pub mod b { - pub mod c { - pub trait D {} - } - } -} - -use a::*; - -use e as b; -use b::c::D as e; - -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`.