From 89bf3ed6501f3a65d697de5d8e139ecad249aa19 Mon Sep 17 00:00:00 2001 From: LorrensP-2158466 Date: Fri, 8 Aug 2025 17:47:25 +0200 Subject: [PATCH 1/8] Resolver: Batched import resolution. Collect side effects from the current set of undetermined imports and only apply them at the end. --- compiler/rustc_hir/src/def.rs | 18 ++ compiler/rustc_resolve/src/imports.rs | 200 ++++++++++++------ compiler/rustc_resolve/src/lib.rs | 6 - fail.rs | 30 +++ tests/ui/imports/ambiguous-9.rs | 8 +- tests/ui/imports/ambiguous-9.stderr | 52 ++--- .../ui/imports/glob-conflict-cross-crate-1.rs | 2 +- .../glob-conflict-cross-crate-1.stderr | 16 +- tests/ui/imports/reexports.stderr | 20 +- .../shadowed/shadowed-use-visibility.stderr | 32 +-- 10 files changed, 244 insertions(+), 140 deletions(-) create mode 100644 fail.rs diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 8af4740f376b6..cb06d8165c58d 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -722,6 +722,24 @@ impl PerNS { pub fn iter(&self) -> IntoIter<&T, 3> { [&self.value_ns, &self.type_ns, &self.macro_ns].into_iter() } + + pub fn into_iter_with(self) -> IntoIter<(Namespace, T), 3> { + [ + (Namespace::TypeNS, self.type_ns), + (Namespace::ValueNS, self.value_ns), + (Namespace::MacroNS, self.macro_ns), + ] + .into_iter() + } + + pub fn iter_with(&self) -> IntoIter<(Namespace, &T), 3> { + [ + (Namespace::TypeNS, &self.type_ns), + (Namespace::ValueNS, &self.value_ns), + (Namespace::MacroNS, &self.macro_ns), + ] + .into_iter() + } } impl ::std::ops::Index for PerNS { diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index d7fc028287ff5..e2d4d2ddb2917 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -2,6 +2,7 @@ use std::cell::Cell; use std::mem; +use std::ops::Deref; use rustc_ast::NodeId; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; @@ -41,6 +42,96 @@ use crate::{ type Res = def::Res; +struct ImportResolver<'r, 'ra, 'tcx> { + r: CmResolver<'r, 'ra, 'tcx>, // always immutable + outputs: ImportResolutionOutputs<'ra>, +} + +enum SideEffect<'ra> { + None, + Single { import_bindings: PerNS> }, + Glob { import_bindings: Vec<(NameBinding<'ra>, BindingKey, bool /* warn_ambiguity */)> }, +} + +#[derive(Default)] +struct ImportResolutionOutputs<'ra> { + indeterminate_imports: Vec>, + determined_imports: Vec<(Import<'ra>, SideEffect<'ra>)>, +} + +impl<'ra> ImportResolutionOutputs<'ra> { + fn commit<'tcx>(self, r: &mut Resolver<'ra, 'tcx>) { + r.indeterminate_imports = self.indeterminate_imports; + r.determined_imports.reserve(self.determined_imports.len()); + + for (import, side_effect) in self.determined_imports { + r.determined_imports.push(import); + + let parent = import.parent_scope.module; + match (&import.kind, side_effect) { + ( + ImportKind::Single { target, bindings, .. }, + SideEffect::Single { import_bindings }, + ) => { + for (ns, pending_binding) in import_bindings.into_iter_with() { + match pending_binding { + PendingBinding::Ready(Some(binding)) => { + r.define_binding_local(parent, *target, ns, binding); + } + PendingBinding::Ready(None) => { + let key = BindingKey::new(*target, ns); + r.update_local_resolution(parent, key, false, |_, resolution| { + resolution.single_imports.swap_remove(&import); + }); + } + _ => {} + } + bindings[ns].set(pending_binding); + } + } + (ImportKind::Glob { id, .. }, SideEffect::Glob { import_bindings }) => { + let ModuleOrUniformRoot::Module(module) = import.imported_module.get().unwrap() + else { + unreachable!(); + }; + + module.glob_importers.borrow_mut().push(import); + + for (binding, key, warn_ambiguity) in import_bindings { + let _ = r.try_define_local( + parent, + key.ident.0, + key.ns, + binding, + warn_ambiguity, + ); + } + + r.record_partial_res(*id, PartialRes::new(module.res().unwrap())); + } + + (_, SideEffect::None) => {} + // Something weird happened, which shouldn't have happened. + _ => unreachable!("Mismatched import kind and side effect"), + } + } + } +} + +impl<'r, 'ra, 'tcx> Deref for ImportResolver<'r, 'ra, 'tcx> { + type Target = Resolver<'ra, 'tcx>; + + fn deref(&self) -> &Self::Target { + self.r.deref() + } +} + +impl<'r, 'ra, 'tcx> AsRef> for ImportResolver<'r, 'ra, 'tcx> { + fn as_ref(&self) -> &Resolver<'ra, 'tcx> { + self.r.as_ref() + } +} + /// A [`NameBinding`] in the process of being resolved. #[derive(Clone, Copy, Default, PartialEq)] pub(crate) enum PendingBinding<'ra> { @@ -551,22 +642,34 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// Resolves all imports for the crate. This method performs the fixed- /// point iteration. pub(crate) fn resolve_imports(&mut self) { - self.assert_speculative = true; let mut prev_indeterminate_count = usize::MAX; let mut indeterminate_count = self.indeterminate_imports.len() * 3; while indeterminate_count < prev_indeterminate_count { prev_indeterminate_count = indeterminate_count; - indeterminate_count = 0; - for import in mem::take(&mut self.indeterminate_imports) { - let import_indeterminate_count = self.cm().resolve_import(import); - indeterminate_count += import_indeterminate_count; - match import_indeterminate_count { - 0 => self.determined_imports.push(import), - _ => self.indeterminate_imports.push(import), - } + let batch = mem::take(&mut self.indeterminate_imports); + self.assert_speculative = true; + let (outputs, count) = + ImportResolver { r: self.cm(), outputs: Default::default() }.resolve_batch(batch); + self.assert_speculative = false; + indeterminate_count = count; + outputs.commit(self); + } + } + + fn resolve_batch<'r>( + mut self: ImportResolver<'r, 'ra, 'tcx>, + batch: Vec>, + ) -> (ImportResolutionOutputs<'ra>, usize) { + let mut indeterminate_count = 0; + for import in batch { + let (side_effect, import_indeterminate_count) = self.resolve_import(import); + indeterminate_count += import_indeterminate_count; + match import_indeterminate_count { + 0 => self.outputs.determined_imports.push((import, side_effect)), + _ => self.outputs.indeterminate_imports.push(import), } } - self.assert_speculative = false; + (self.outputs, indeterminate_count) } pub(crate) fn finalize_imports(&mut self) { @@ -839,7 +942,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// /// Meanwhile, if resolve successful, the resolved bindings are written /// into the module. - fn resolve_import<'r>(mut self: CmResolver<'r, 'ra, 'tcx>, import: Import<'ra>) -> usize { + fn resolve_import<'r>( + self: &mut ImportResolver<'r, 'ra, 'tcx>, + import: Import<'ra>, + ) -> (SideEffect<'ra>, usize) { debug!( "(resolving import for module) resolving import `{}::...` in `{}`", Segment::names_to_string(&import.module_path), @@ -848,7 +954,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let module = if let Some(module) = import.imported_module.get() { module } else { - let path_res = self.reborrow().maybe_resolve_path( + let path_res = self.r.reborrow().maybe_resolve_path( &import.module_path, None, &import.parent_scope, @@ -857,8 +963,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { match path_res { PathResult::Module(module) => module, - PathResult::Indeterminate => return 3, - PathResult::NonModule(..) | PathResult::Failed { .. } => return 0, + PathResult::Indeterminate => return (SideEffect::None, 3), + PathResult::NonModule(..) | PathResult::Failed { .. } => { + return (SideEffect::None, 0); + } } }; @@ -868,16 +976,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { (source, target, bindings, type_ns_only) } ImportKind::Glob { .. } => { - // FIXME: Use mutable resolver directly as a hack, this should be an output of - // speculative resolution. - self.get_mut_unchecked().resolve_glob_import(import); - return 0; + return (self.resolve_glob_import(import), 0); } _ => unreachable!(), }; + let mut import_bindings = PerNS::default(); let mut indeterminate_count = 0; - self.per_ns_cm(|this, ns| { + self.r.reborrow().per_ns_cm(|this, ns| { if !type_ns_only || ns == TypeNS { if bindings[ns].get() != PendingBinding::Pending { return; @@ -889,8 +995,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { &import.parent_scope, Some(import), ); - let parent = import.parent_scope.module; - let binding = match binding_result { + let pending_binding = match binding_result { Ok(binding) => { if binding.is_assoc_item() && !this.tcx.features().import_trait_associated_functions() @@ -905,43 +1010,25 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } // We need the `target`, `source` can be extracted. let imported_binding = this.import(binding, import); - // FIXME: Use mutable resolver directly as a hack, this should be an output of - // speculative resolution. - this.get_mut_unchecked().define_binding_local( - parent, - target, - ns, - imported_binding, - ); PendingBinding::Ready(Some(imported_binding)) } Err(Determinacy::Determined) => { // Don't remove underscores from `single_imports`, they were never added. - if target.name != kw::Underscore { - let key = BindingKey::new(target, ns); - // FIXME: Use mutable resolver directly as a hack, this should be an output of - // speculative resolution. - this.get_mut_unchecked().update_local_resolution( - parent, - key, - false, - |_, resolution| { - resolution.single_imports.swap_remove(&import); - }, - ); + if target.name == kw::Underscore { + return; } PendingBinding::Ready(None) } Err(Determinacy::Undetermined) => { indeterminate_count += 1; - PendingBinding::Pending + return; } }; - bindings[ns].set(binding); + import_bindings[ns] = pending_binding; } }); - indeterminate_count + (SideEffect::Single { import_bindings }, indeterminate_count) } /// Performs final import resolution, consistency checks and error reporting. @@ -1484,13 +1571,16 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { false } - fn resolve_glob_import(&mut self, import: Import<'ra>) { + fn resolve_glob_import<'r>( + self: &mut ImportResolver<'r, 'ra, 'tcx>, + import: Import<'ra>, + ) -> SideEffect<'ra> { // This function is only called for glob imports. - let ImportKind::Glob { id, .. } = import.kind else { unreachable!() }; + let ImportKind::Glob { .. } = import.kind else { unreachable!() }; let ModuleOrUniformRoot::Module(module) = import.imported_module.get().unwrap() else { self.dcx().emit_err(CannotGlobImportAllCrates { span: import.span }); - return; + return SideEffect::None; }; if module.is_trait() && !self.tcx.features().import_trait_associated_functions() { @@ -1504,12 +1594,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } if module == import.parent_scope.module { - return; + return SideEffect::None; } - // Add to module's glob_importers - module.glob_importers.borrow_mut().push(import); - // Ensure that `resolutions` isn't borrowed during `try_define`, // since it might get updated via a glob cycle. let bindings = self @@ -1520,6 +1607,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { resolution.borrow().binding().map(|binding| (*key, binding)) }) .collect::>(); + let mut import_bindings = Vec::with_capacity(bindings.len()); for (mut key, binding) in bindings { let scope = match key.ident.0.span.reverse_glob_adjust(module.expansion, import.span) { Some(Some(def)) => self.expn_def_scope(def), @@ -1532,18 +1620,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { .resolution(import.parent_scope.module, key) .and_then(|r| r.binding()) .is_some_and(|binding| binding.warn_ambiguity_recursive()); - let _ = self.try_define_local( - import.parent_scope.module, - key.ident.0, - key.ns, - imported_binding, - warn_ambiguity, - ); + import_bindings.push((imported_binding, key, warn_ambiguity)); } } // Record the destination of this import - self.record_partial_res(id, PartialRes::new(module.res().unwrap())); + SideEffect::Glob { import_bindings } } // Miscellaneous post-processing, including recording re-exports, diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 2afb52ef4d4be..6d42ec7b4aba4 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -2541,12 +2541,6 @@ mod ref_mut { true => self.p, } } - - /// Returns a mutable reference to the inner value without checking if - /// it's in a mutable state. - pub(crate) fn get_mut_unchecked(&mut self) -> &mut T { - self.p - } } } diff --git a/fail.rs b/fail.rs new file mode 100644 index 0000000000000..114e05ed76072 --- /dev/null +++ b/fail.rs @@ -0,0 +1,30 @@ +#![no_core] +#![feature(no_core)] +#![allow(internal_features)] +#![feature(lang_items)] + +#[lang = "sized"] +pub trait Sized: MetaSized {} + +#[lang = "meta_sized"] +pub trait MetaSized: PointeeSized {} + +#[lang = "pointee_sized"] +pub trait PointeeSized {} + +mod core_simd { + mod vector { + pub struct Simd {} + } + pub mod simd { + pub use crate::core_simd::vector::*; + } +} + +pub mod simd { + pub use crate::core_simd::simd::*; +} + +mod fail { + use crate::simd::Simd; +} diff --git a/tests/ui/imports/ambiguous-9.rs b/tests/ui/imports/ambiguous-9.rs index c10b1268060ce..cb352668e7599 100644 --- a/tests/ui/imports/ambiguous-9.rs +++ b/tests/ui/imports/ambiguous-9.rs @@ -4,7 +4,7 @@ pub mod dsl { mod range { pub fn date_range() {} } - pub use self::range::*; //~ WARNING ambiguous glob re-exports + pub use self::range::*; use super::prelude::*; } @@ -12,8 +12,8 @@ pub mod prelude { mod t { pub fn date_range() {} } - pub use self::t::*; //~ WARNING ambiguous glob re-exports - pub use super::dsl::*; + pub use self::t::*; + pub use super::dsl::*; //~ WARNING ambiguous glob re-exports } use dsl::*; @@ -23,6 +23,4 @@ fn main() { date_range(); //~^ ERROR `date_range` is ambiguous //~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - //~| ERROR `date_range` is ambiguous - //~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! } diff --git a/tests/ui/imports/ambiguous-9.stderr b/tests/ui/imports/ambiguous-9.stderr index 800a2e10c9d78..9222f3f99c1e3 100644 --- a/tests/ui/imports/ambiguous-9.stderr +++ b/tests/ui/imports/ambiguous-9.stderr @@ -1,10 +1,10 @@ warning: ambiguous glob re-exports - --> $DIR/ambiguous-9.rs:7:13 + --> $DIR/ambiguous-9.rs:16:13 | -LL | pub use self::range::*; - | ^^^^^^^^^^^^^^ the name `date_range` in the value namespace is first re-exported here -LL | use super::prelude::*; - | ----------------- but the name `date_range` in the value namespace is also re-exported here +LL | pub use self::t::*; + | ---------- but the name `date_range` in the value namespace is also re-exported here +LL | pub use super::dsl::*; + | ^^^^^^^^^^^^^ the name `date_range` in the value namespace is first re-exported here | = note: `#[warn(ambiguous_glob_reexports)]` on by default @@ -18,10 +18,10 @@ LL | date_range(); = note: for more information, see issue #114095 = note: ambiguous because of multiple glob imports of a name in the same module note: `date_range` could refer to the function imported here - --> $DIR/ambiguous-9.rs:7:13 + --> $DIR/ambiguous-9.rs:16:13 | -LL | pub use self::range::*; - | ^^^^^^^^^^^^^^ +LL | pub use super::dsl::*; + | ^^^^^^^^^^^^^ = help: consider adding an explicit import of `date_range` to disambiguate note: `date_range` could also refer to the function imported here --> $DIR/ambiguous-9.rs:8:9 @@ -35,33 +35,11 @@ warning: ambiguous glob re-exports --> $DIR/ambiguous-9.rs:15:13 | LL | pub use self::t::*; - | ^^^^^^^^^^ the name `date_range` in the value namespace is first re-exported here -LL | pub use super::dsl::*; - | ------------- but the name `date_range` in the value namespace is also re-exported here - -error: `date_range` is ambiguous - --> $DIR/ambiguous-9.rs:23:5 - | -LL | date_range(); - | ^^^^^^^^^^ ambiguous name - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #114095 - = note: ambiguous because of multiple glob imports of a name in the same module -note: `date_range` could refer to the function imported here - --> $DIR/ambiguous-9.rs:19:5 - | -LL | use dsl::*; - | ^^^^^^ - = help: consider adding an explicit import of `date_range` to disambiguate -note: `date_range` could also refer to the function imported here - --> $DIR/ambiguous-9.rs:20:5 - | -LL | use prelude::*; - | ^^^^^^^^^^ + | ^^^^^^^^^^ = help: consider adding an explicit import of `date_range` to disambiguate + = note: `#[deny(ambiguous_glob_imports)]` on by default -error: aborting due to 2 previous errors; 2 warnings emitted +error: aborting due to 1 previous error; 1 warning emitted Future incompatibility report: Future breakage diagnostic: error: `date_range` is ambiguous @@ -74,13 +52,13 @@ LL | date_range(); = note: for more information, see issue #114095 = note: ambiguous because of multiple glob imports of a name in the same module note: `date_range` could refer to the function imported here - --> $DIR/ambiguous-9.rs:7:13 + --> $DIR/ambiguous-9.rs:16:13 | -LL | pub use self::range::*; - | ^^^^^^^^^^^^^^ +LL | pub use super::dsl::*; + | ^^^^^^^^^^^^^ = help: consider adding an explicit import of `date_range` to disambiguate note: `date_range` could also refer to the function imported here - --> $DIR/ambiguous-9.rs:8:9 + --> $DIR/ambiguous-9.rs:15:13 | LL | use super::prelude::*; | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/imports/glob-conflict-cross-crate-1.rs b/tests/ui/imports/glob-conflict-cross-crate-1.rs index 5f0433d13fcfd..4ea6e131d2400 100644 --- a/tests/ui/imports/glob-conflict-cross-crate-1.rs +++ b/tests/ui/imports/glob-conflict-cross-crate-1.rs @@ -6,7 +6,7 @@ fn main() { glob_conflict::f(); //~ ERROR cannot find function `f` in crate `glob_conflict` //^ FIXME: `glob_conflict::f` should raise an // ambiguity error instead of a not found error. - glob_conflict::glob::f(); //~ ERROR cannot find function `f` in module `glob_conflict::glob` + glob_conflict::glob::f(); //^ FIXME: `glob_conflict::glob::f` should raise an // ambiguity error instead of a not found error. } diff --git a/tests/ui/imports/glob-conflict-cross-crate-1.stderr b/tests/ui/imports/glob-conflict-cross-crate-1.stderr index 758087107f397..1f1217c25e626 100644 --- a/tests/ui/imports/glob-conflict-cross-crate-1.stderr +++ b/tests/ui/imports/glob-conflict-cross-crate-1.stderr @@ -3,13 +3,17 @@ error[E0425]: cannot find function `f` in crate `glob_conflict` | LL | glob_conflict::f(); | ^ not found in `glob_conflict` - -error[E0425]: cannot find function `f` in module `glob_conflict::glob` - --> $DIR/glob-conflict-cross-crate-1.rs:9:26 | -LL | glob_conflict::glob::f(); - | ^ not found in `glob_conflict::glob` +help: consider importing this function + | +LL + use glob_conflict::glob::f; + | +help: if you import `f`, refer to it directly + | +LL - glob_conflict::f(); +LL + f(); + | -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/imports/reexports.stderr b/tests/ui/imports/reexports.stderr index 0ebcf8e58d627..dec8a60f93ca0 100644 --- a/tests/ui/imports/reexports.stderr +++ b/tests/ui/imports/reexports.stderr @@ -11,16 +11,16 @@ LL | pub use super::foo; | ^^^^^^^^^^ error[E0603]: module import `foo` is private - --> $DIR/reexports.rs:36:22 + --> $DIR/reexports.rs:37:22 | -LL | use crate::b::a::foo::S; +LL | use crate::b::b::foo::S as T; | ^^^ private module import | note: the module import `foo` is defined here... - --> $DIR/reexports.rs:24:17 + --> $DIR/reexports.rs:29:17 | -LL | pub use super::foo; // This is OK since the value `foo` is visible enough. - | ^^^^^^^^^^ +LL | pub use super::*; // This is also OK since the value `foo` is visible enough. + | ^^^^^^^^ note: ...and refers to the module `foo` which is defined here --> $DIR/reexports.rs:19:5 | @@ -28,16 +28,16 @@ LL | mod foo { | ^^^^^^^ error[E0603]: module import `foo` is private - --> $DIR/reexports.rs:37:22 + --> $DIR/reexports.rs:36:22 | -LL | use crate::b::b::foo::S as T; +LL | use crate::b::a::foo::S; | ^^^ private module import | note: the module import `foo` is defined here... - --> $DIR/reexports.rs:29:17 + --> $DIR/reexports.rs:24:17 | -LL | pub use super::*; // This is also OK since the value `foo` is visible enough. - | ^^^^^^^^ +LL | pub use super::foo; // This is OK since the value `foo` is visible enough. + | ^^^^^^^^^^ note: ...and refers to the module `foo` which is defined here --> $DIR/reexports.rs:19:5 | diff --git a/tests/ui/shadowed/shadowed-use-visibility.stderr b/tests/ui/shadowed/shadowed-use-visibility.stderr index b062341dc8be8..f3b81fcac99e0 100644 --- a/tests/ui/shadowed/shadowed-use-visibility.stderr +++ b/tests/ui/shadowed/shadowed-use-visibility.stderr @@ -1,31 +1,31 @@ -error[E0603]: module import `bar` is private - --> $DIR/shadowed-use-visibility.rs:9:21 +error[E0603]: module import `f` is private + --> $DIR/shadowed-use-visibility.rs:15:10 | -LL | use crate::foo::bar::f as g; - | ^^^ private module import +LL | use bar::f::f; + | ^ private module import | -note: the module import `bar` is defined here... - --> $DIR/shadowed-use-visibility.rs:4:9 +note: the module import `f` is defined here... + --> $DIR/shadowed-use-visibility.rs:11:9 | -LL | use crate::foo as bar; - | ^^^^^^^^^^^^^^^^^ +LL | use crate::foo as f; + | ^^^^^^^^^^^^^^^ note: ...and refers to the module `foo` which is defined here --> $DIR/shadowed-use-visibility.rs:1:1 | LL | mod foo { | ^^^^^^^ -error[E0603]: module import `f` is private - --> $DIR/shadowed-use-visibility.rs:15:10 +error[E0603]: module import `bar` is private + --> $DIR/shadowed-use-visibility.rs:9:21 | -LL | use bar::f::f; - | ^ private module import +LL | use crate::foo::bar::f as g; + | ^^^ private module import | -note: the module import `f` is defined here... - --> $DIR/shadowed-use-visibility.rs:11:9 +note: the module import `bar` is defined here... + --> $DIR/shadowed-use-visibility.rs:4:9 | -LL | use crate::foo as f; - | ^^^^^^^^^^^^^^^ +LL | use crate::foo as bar; + | ^^^^^^^^^^^^^^^^^ note: ...and refers to the module `foo` which is defined here --> $DIR/shadowed-use-visibility.rs:1:1 | From 8499dd2e58a346834f34dadf5b37adb71df5d25e Mon Sep 17 00:00:00 2001 From: LorrensP-2158466 Date: Tue, 19 Aug 2025 12:14:06 +0200 Subject: [PATCH 2/8] Several logical changes. --- compiler/rustc_hir/src/def.rs | 18 -- compiler/rustc_resolve/src/imports.rs | 363 +++++++++++++------------- fail.rs | 30 --- 3 files changed, 184 insertions(+), 227 deletions(-) delete mode 100644 fail.rs diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index cb06d8165c58d..8af4740f376b6 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -722,24 +722,6 @@ impl PerNS { pub fn iter(&self) -> IntoIter<&T, 3> { [&self.value_ns, &self.type_ns, &self.macro_ns].into_iter() } - - pub fn into_iter_with(self) -> IntoIter<(Namespace, T), 3> { - [ - (Namespace::TypeNS, self.type_ns), - (Namespace::ValueNS, self.value_ns), - (Namespace::MacroNS, self.macro_ns), - ] - .into_iter() - } - - pub fn iter_with(&self) -> IntoIter<(Namespace, &T), 3> { - [ - (Namespace::TypeNS, &self.type_ns), - (Namespace::ValueNS, &self.value_ns), - (Namespace::MacroNS, &self.macro_ns), - ] - .into_iter() - } } impl ::std::ops::Index for PerNS { diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index e2d4d2ddb2917..06942851457a1 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -2,7 +2,6 @@ use std::cell::Cell; use std::mem; -use std::ops::Deref; use rustc_ast::NodeId; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; @@ -42,98 +41,30 @@ use crate::{ type Res = def::Res; -struct ImportResolver<'r, 'ra, 'tcx> { - r: CmResolver<'r, 'ra, 'tcx>, // always immutable - outputs: ImportResolutionOutputs<'ra>, -} - -enum SideEffect<'ra> { +/// The the side effect made when resolving the bindings for an underterminate import. +enum SideEffectBindings<'ra> { None, - Single { import_bindings: PerNS> }, - Glob { import_bindings: Vec<(NameBinding<'ra>, BindingKey, bool /* warn_ambiguity */)> }, -} - -#[derive(Default)] -struct ImportResolutionOutputs<'ra> { - indeterminate_imports: Vec>, - determined_imports: Vec<(Import<'ra>, SideEffect<'ra>)>, -} - -impl<'ra> ImportResolutionOutputs<'ra> { - fn commit<'tcx>(self, r: &mut Resolver<'ra, 'tcx>) { - r.indeterminate_imports = self.indeterminate_imports; - r.determined_imports.reserve(self.determined_imports.len()); - - for (import, side_effect) in self.determined_imports { - r.determined_imports.push(import); - - let parent = import.parent_scope.module; - match (&import.kind, side_effect) { - ( - ImportKind::Single { target, bindings, .. }, - SideEffect::Single { import_bindings }, - ) => { - for (ns, pending_binding) in import_bindings.into_iter_with() { - match pending_binding { - PendingBinding::Ready(Some(binding)) => { - r.define_binding_local(parent, *target, ns, binding); - } - PendingBinding::Ready(None) => { - let key = BindingKey::new(*target, ns); - r.update_local_resolution(parent, key, false, |_, resolution| { - resolution.single_imports.swap_remove(&import); - }); - } - _ => {} - } - bindings[ns].set(pending_binding); - } - } - (ImportKind::Glob { id, .. }, SideEffect::Glob { import_bindings }) => { - let ModuleOrUniformRoot::Module(module) = import.imported_module.get().unwrap() - else { - unreachable!(); - }; - - module.glob_importers.borrow_mut().push(import); - - for (binding, key, warn_ambiguity) in import_bindings { - let _ = r.try_define_local( - parent, - key.ident.0, - key.ns, - binding, - warn_ambiguity, - ); - } - - r.record_partial_res(*id, PartialRes::new(module.res().unwrap())); - } - - (_, SideEffect::None) => {} - // Something weird happened, which shouldn't have happened. - _ => unreachable!("Mismatched import kind and side effect"), - } - } - } -} - -impl<'r, 'ra, 'tcx> Deref for ImportResolver<'r, 'ra, 'tcx> { - type Target = Resolver<'ra, 'tcx>; - - fn deref(&self) -> &Self::Target { - self.r.deref() - } + /// Side effect that should be applied to the field `bindings` of `ImportKind::Single`. + /// + /// The inner `Option` is the actual side effect, it tells us whether we found a binding + /// when resolving the import in this particular namespace. + /// The outer `Option` tells us if this side effect is present. + Single { + import_bindings: PerNS>>>, + }, + Glob { + import_bindings: Vec<(NameBinding<'ra>, BindingKey, bool /* warn_ambiguity */)>, + }, } -impl<'r, 'ra, 'tcx> AsRef> for ImportResolver<'r, 'ra, 'tcx> { - fn as_ref(&self) -> &Resolver<'ra, 'tcx> { - self.r.as_ref() - } +/// The side effect made when resolving an undeterminate import. +struct SideEffect<'ra> { + imported_module: ModuleOrUniformRoot<'ra>, + bindings: SideEffectBindings<'ra>, } /// A [`NameBinding`] in the process of being resolved. -#[derive(Clone, Copy, Default, PartialEq)] +#[derive(Clone, Copy, Default, PartialEq, Debug)] pub(crate) enum PendingBinding<'ra> { Ready(Option>), #[default] @@ -633,11 +564,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // Import resolution // - // This is a fixed-point algorithm. We resolve imports until our efforts - // are stymied by an unresolved import; then we bail out of the current - // module and continue. We terminate successfully once no more imports - // remain or unsuccessfully when no forward progress in resolving imports - // is made. + // This is a batched fixed-point algorithm. Each import is resolved in + // isolation, with any side effects collected for later. + // After a full pass over the current set of `indeterminate_imports`, + // the collected side effects are committed together. The process + // repeats until either no imports remain or no further progress can + // be made. /// Resolves all imports for the crate. This method performs the fixed- /// point iteration. @@ -646,30 +578,124 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let mut indeterminate_count = self.indeterminate_imports.len() * 3; while indeterminate_count < prev_indeterminate_count { prev_indeterminate_count = indeterminate_count; - let batch = mem::take(&mut self.indeterminate_imports); + indeterminate_count = 0; + let mut side_effects = Vec::new(); self.assert_speculative = true; - let (outputs, count) = - ImportResolver { r: self.cm(), outputs: Default::default() }.resolve_batch(batch); + for import in mem::take(&mut self.indeterminate_imports) { + let (side_effect, import_indeterminate_count) = self.cm().resolve_import(import); + indeterminate_count += import_indeterminate_count; + match import_indeterminate_count { + 0 => self.determined_imports.push(import), + _ => self.indeterminate_imports.push(import), + } + if let Some(side_effect) = side_effect { + side_effects.push((import, side_effect)); + } + } self.assert_speculative = false; - indeterminate_count = count; - outputs.commit(self); + self.commit_import_resolutions(side_effects); } } - fn resolve_batch<'r>( - mut self: ImportResolver<'r, 'ra, 'tcx>, - batch: Vec>, - ) -> (ImportResolutionOutputs<'ra>, usize) { - let mut indeterminate_count = 0; - for import in batch { - let (side_effect, import_indeterminate_count) = self.resolve_import(import); - indeterminate_count += import_indeterminate_count; - match import_indeterminate_count { - 0 => self.outputs.determined_imports.push((import, side_effect)), - _ => self.outputs.indeterminate_imports.push(import), + fn commit_import_resolutions( + &mut self, + import_resolutions: Vec<(Import<'ra>, SideEffect<'ra>)>, + ) { + self.determined_imports.reserve(self.determined_imports.len()); + for (import, side_effect) in import_resolutions.iter() { + self.determined_imports.push(*import); + let SideEffect { imported_module, .. } = side_effect; + import.imported_module.set(Some(*imported_module)); + + if import.is_glob() + && let ModuleOrUniformRoot::Module(module) = imported_module + && import.parent_scope.module != *module + { + module.glob_importers.borrow_mut().push(*import); + } + } + + for (import, side_effect) in import_resolutions { + let SideEffect { imported_module, bindings: side_effect_bindings } = side_effect; + let parent = import.parent_scope.module; + + match (&import.kind, side_effect_bindings) { + ( + ImportKind::Single { target, bindings, .. }, + SideEffectBindings::Single { import_bindings }, + ) => { + self.per_ns(|this, ns| { + match import_bindings[ns] { + Some(Some(binding)) => { + if binding.is_assoc_item() + && !this.tcx.features().import_trait_associated_functions() + { + feature_err( + this.tcx.sess, + sym::import_trait_associated_functions, + import.span, + "`use` associated items of traits is unstable", + ) + .emit(); + } + this.define_binding_local(parent, *target, ns, binding); + bindings[ns].set(PendingBinding::Ready(Some(binding))); + } + Some(None) => { + // Don't remove underscores from `single_imports`, they were never added. + if target.name != kw::Underscore { + let key = BindingKey::new(*target, ns); + this.update_local_resolution( + parent, + key, + false, + |_, resolution| { + resolution.single_imports.swap_remove(&import); + }, + ); + } + bindings[ns].set(PendingBinding::Ready(None)); + } + None => {} + } + }); + } + (ImportKind::Glob { id, .. }, SideEffectBindings::Glob { import_bindings }) => { + let ModuleOrUniformRoot::Module(module) = imported_module else { + self.dcx().emit_err(CannotGlobImportAllCrates { span: import.span }); + continue; + }; + + if module.is_trait() && !self.tcx.features().import_trait_associated_functions() + { + feature_err( + self.tcx.sess, + sym::import_trait_associated_functions, + import.span, + "`use` associated items of traits is unstable", + ) + .emit(); + } + + for (binding, key, warn_ambiguity) in import_bindings { + let _ = self.try_define_local( + parent, + key.ident.0, + key.ns, + binding, + warn_ambiguity, + ); + } + + self.record_partial_res(*id, PartialRes::new(module.res().unwrap())); + } + + (_, SideEffectBindings::None) => {} + + // Something weird happened, which shouldn't have happened. + _ => unreachable!("Mismatched import kind and side effect"), } } - (self.outputs, indeterminate_count) } pub(crate) fn finalize_imports(&mut self) { @@ -940,12 +966,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// - `0` means its resolution is determined. /// - Other values mean that indeterminate exists under certain namespaces. /// - /// Meanwhile, if resolve successful, the resolved bindings are written - /// into the module. + /// Meanwhile, if resolution is successful, the side effect of the resolution is returned. fn resolve_import<'r>( - self: &mut ImportResolver<'r, 'ra, 'tcx>, + self: &mut CmResolver<'r, 'ra, 'tcx>, import: Import<'ra>, - ) -> (SideEffect<'ra>, usize) { + ) -> (Option>, usize) { debug!( "(resolving import for module) resolving import `{}::...` in `{}`", Segment::names_to_string(&import.module_path), @@ -954,7 +979,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let module = if let Some(module) = import.imported_module.get() { module } else { - let path_res = self.r.reborrow().maybe_resolve_path( + let path_res = self.reborrow().maybe_resolve_path( &import.module_path, None, &import.parent_scope, @@ -963,27 +988,32 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { match path_res { PathResult::Module(module) => module, - PathResult::Indeterminate => return (SideEffect::None, 3), + PathResult::Indeterminate => return (None, 3), PathResult::NonModule(..) | PathResult::Failed { .. } => { - return (SideEffect::None, 0); + return (None, 0); } } }; - import.imported_module.set(Some(module)); - let (source, target, bindings, type_ns_only) = match import.kind { + let (source, _, bindings, type_ns_only) = match import.kind { ImportKind::Single { source, target, ref bindings, type_ns_only, .. } => { (source, target, bindings, type_ns_only) } ImportKind::Glob { .. } => { - return (self.resolve_glob_import(import), 0); + return ( + Some(SideEffect { + imported_module: module, + bindings: self.resolve_glob_import(import, module), + }), + 0, + ); } _ => unreachable!(), }; let mut import_bindings = PerNS::default(); let mut indeterminate_count = 0; - self.r.reborrow().per_ns_cm(|this, ns| { + self.reborrow().per_ns_cm(|this, ns| { if !type_ns_only || ns == TypeNS { if bindings[ns].get() != PendingBinding::Pending { return; @@ -997,38 +1027,27 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ); let pending_binding = match binding_result { Ok(binding) => { - if binding.is_assoc_item() - && !this.tcx.features().import_trait_associated_functions() - { - feature_err( - this.tcx.sess, - sym::import_trait_associated_functions, - import.span, - "`use` associated items of traits is unstable", - ) - .emit(); - } // We need the `target`, `source` can be extracted. let imported_binding = this.import(binding, import); - PendingBinding::Ready(Some(imported_binding)) - } - Err(Determinacy::Determined) => { - // Don't remove underscores from `single_imports`, they were never added. - if target.name == kw::Underscore { - return; - } - PendingBinding::Ready(None) + Some(Some(imported_binding)) } + Err(Determinacy::Determined) => Some(None), Err(Determinacy::Undetermined) => { indeterminate_count += 1; - return; + None } }; import_bindings[ns] = pending_binding; } }); - (SideEffect::Single { import_bindings }, indeterminate_count) + ( + Some(SideEffect { + imported_module: module, + bindings: SideEffectBindings::Single { import_bindings }, + }), + indeterminate_count, + ) } /// Performs final import resolution, consistency checks and error reporting. @@ -1572,60 +1591,46 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } fn resolve_glob_import<'r>( - self: &mut ImportResolver<'r, 'ra, 'tcx>, + self: &mut CmResolver<'r, 'ra, 'tcx>, import: Import<'ra>, - ) -> SideEffect<'ra> { + imported_module: ModuleOrUniformRoot<'ra>, + ) -> SideEffectBindings<'ra> { // This function is only called for glob imports. let ImportKind::Glob { .. } = import.kind else { unreachable!() }; - let ModuleOrUniformRoot::Module(module) = import.imported_module.get().unwrap() else { - self.dcx().emit_err(CannotGlobImportAllCrates { span: import.span }); - return SideEffect::None; + let ModuleOrUniformRoot::Module(module) = imported_module else { + return SideEffectBindings::None; }; - if module.is_trait() && !self.tcx.features().import_trait_associated_functions() { - feature_err( - self.tcx.sess, - sym::import_trait_associated_functions, - import.span, - "`use` associated items of traits is unstable", - ) - .emit(); - } - if module == import.parent_scope.module { - return SideEffect::None; + return SideEffectBindings::None; } - // Ensure that `resolutions` isn't borrowed during `try_define`, - // since it might get updated via a glob cycle. - let bindings = self + let import_bindings = self .resolutions(module) .borrow() .iter() .filter_map(|(key, resolution)| { - resolution.borrow().binding().map(|binding| (*key, binding)) + let binding = resolution.borrow().binding()?; + let mut key = *key; + let scope = + match key.ident.0.span.reverse_glob_adjust(module.expansion, import.span) { + Some(Some(def)) => self.expn_def_scope(def), + Some(None) => import.parent_scope.module, + None => return None, + }; + self.is_accessible_from(binding.vis, scope).then(|| { + let imported_binding = self.import(binding, import); + let warn_ambiguity = self + .resolution(import.parent_scope.module, key) + .and_then(|r| r.binding()) + .is_some_and(|binding| binding.warn_ambiguity_recursive()); + (imported_binding, key, warn_ambiguity) + }) }) .collect::>(); - let mut import_bindings = Vec::with_capacity(bindings.len()); - for (mut key, binding) in bindings { - let scope = match key.ident.0.span.reverse_glob_adjust(module.expansion, import.span) { - Some(Some(def)) => self.expn_def_scope(def), - Some(None) => import.parent_scope.module, - None => continue, - }; - if self.is_accessible_from(binding.vis, scope) { - let imported_binding = self.import(binding, import); - let warn_ambiguity = self - .resolution(import.parent_scope.module, key) - .and_then(|r| r.binding()) - .is_some_and(|binding| binding.warn_ambiguity_recursive()); - import_bindings.push((imported_binding, key, warn_ambiguity)); - } - } - // Record the destination of this import - SideEffect::Glob { import_bindings } + SideEffectBindings::Glob { import_bindings } } // Miscellaneous post-processing, including recording re-exports, diff --git a/fail.rs b/fail.rs deleted file mode 100644 index 114e05ed76072..0000000000000 --- a/fail.rs +++ /dev/null @@ -1,30 +0,0 @@ -#![no_core] -#![feature(no_core)] -#![allow(internal_features)] -#![feature(lang_items)] - -#[lang = "sized"] -pub trait Sized: MetaSized {} - -#[lang = "meta_sized"] -pub trait MetaSized: PointeeSized {} - -#[lang = "pointee_sized"] -pub trait PointeeSized {} - -mod core_simd { - mod vector { - pub struct Simd {} - } - pub mod simd { - pub use crate::core_simd::vector::*; - } -} - -pub mod simd { - pub use crate::core_simd::simd::*; -} - -mod fail { - use crate::simd::Simd; -} From ac733171ce414e68f26e391286147c502b82e5a8 Mon Sep 17 00:00:00 2001 From: LorrensP-2158466 Date: Wed, 27 Aug 2025 13:50:31 +0200 Subject: [PATCH 3/8] Report glob errors in first phase of commit. --- compiler/rustc_resolve/src/imports.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 06942851457a1..b8a8a4a2f12b4 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -607,11 +607,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let SideEffect { imported_module, .. } = side_effect; import.imported_module.set(Some(*imported_module)); - if import.is_glob() - && let ModuleOrUniformRoot::Module(module) = imported_module - && import.parent_scope.module != *module - { - module.glob_importers.borrow_mut().push(*import); + if import.is_glob() { + let ModuleOrUniformRoot::Module(module) = imported_module else { + self.dcx().emit_err(CannotGlobImportAllCrates { span: import.span }); + continue; + }; + if import.parent_scope.module != *module { + module.glob_importers.borrow_mut().push(*import); + } } } @@ -662,7 +665,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } (ImportKind::Glob { id, .. }, SideEffectBindings::Glob { import_bindings }) => { let ModuleOrUniformRoot::Module(module) = imported_module else { - self.dcx().emit_err(CannotGlobImportAllCrates { span: import.span }); continue; }; From c7f94d901a36d9383979a7385c43fb7ebce4780a Mon Sep 17 00:00:00 2001 From: LorrensP-2158466 Date: Wed, 27 Aug 2025 17:39:37 +0200 Subject: [PATCH 4/8] fix duplicate errors --- compiler/rustc_resolve/src/imports.rs | 76 +++++++++++++-------------- 1 file changed, 36 insertions(+), 40 deletions(-) diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index b8a8a4a2f12b4..dc93c2fc454f0 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -53,7 +53,7 @@ enum SideEffectBindings<'ra> { import_bindings: PerNS>>>, }, Glob { - import_bindings: Vec<(NameBinding<'ra>, BindingKey, bool /* warn_ambiguity */)>, + import_bindings: Vec<(NameBinding<'ra>, BindingKey)>, }, } @@ -601,9 +601,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { &mut self, import_resolutions: Vec<(Import<'ra>, SideEffect<'ra>)>, ) { - self.determined_imports.reserve(self.determined_imports.len()); for (import, side_effect) in import_resolutions.iter() { - self.determined_imports.push(*import); let SideEffect { imported_module, .. } = side_effect; import.imported_module.set(Some(*imported_module)); @@ -679,12 +677,17 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { .emit(); } - for (binding, key, warn_ambiguity) in import_bindings { + for (binding, key) in import_bindings { + let imported_binding = self.import(binding, import); + let warn_ambiguity = self + .resolution(import.parent_scope.module, key) + .and_then(|r| r.binding()) + .is_some_and(|binding| binding.warn_ambiguity_recursive()); let _ = self.try_define_local( parent, key.ident.0, key.ns, - binding, + imported_binding, warn_ambiguity, ); } @@ -1592,47 +1595,40 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { false } - fn resolve_glob_import<'r>( - self: &mut CmResolver<'r, 'ra, 'tcx>, + fn resolve_glob_import( + &self, import: Import<'ra>, imported_module: ModuleOrUniformRoot<'ra>, ) -> SideEffectBindings<'ra> { - // This function is only called for glob imports. - let ImportKind::Glob { .. } = import.kind else { unreachable!() }; + match imported_module { + ModuleOrUniformRoot::Module(module) if module != import.parent_scope.module => { + let import_bindings = self + .resolutions(module) + .borrow() + .iter() + .filter_map(|(key, resolution)| { + let binding = resolution.borrow().binding()?; + let mut key = *key; + let scope = match key + .ident + .0 + .span + .reverse_glob_adjust(module.expansion, import.span) + { + Some(Some(def)) => self.expn_def_scope(def), + Some(None) => import.parent_scope.module, + None => return None, + }; + self.is_accessible_from(binding.vis, scope).then(|| (binding, key)) + }) + .collect::>(); - let ModuleOrUniformRoot::Module(module) = imported_module else { - return SideEffectBindings::None; - }; + SideEffectBindings::Glob { import_bindings } + } - if module == import.parent_scope.module { - return SideEffectBindings::None; + // Errors are reported in `commit_imports_resolutions` + _ => SideEffectBindings::None, } - - let import_bindings = self - .resolutions(module) - .borrow() - .iter() - .filter_map(|(key, resolution)| { - let binding = resolution.borrow().binding()?; - let mut key = *key; - let scope = - match key.ident.0.span.reverse_glob_adjust(module.expansion, import.span) { - Some(Some(def)) => self.expn_def_scope(def), - Some(None) => import.parent_scope.module, - None => return None, - }; - self.is_accessible_from(binding.vis, scope).then(|| { - let imported_binding = self.import(binding, import); - let warn_ambiguity = self - .resolution(import.parent_scope.module, key) - .and_then(|r| r.binding()) - .is_some_and(|binding| binding.warn_ambiguity_recursive()); - (imported_binding, key, warn_ambiguity) - }) - }) - .collect::>(); - - SideEffectBindings::Glob { import_bindings } } // Miscellaneous post-processing, including recording re-exports, From 3289351819639cdbb602b083b8691b366851eaaf Mon Sep 17 00:00:00 2001 From: LorrensP-2158466 Date: Wed, 27 Aug 2025 17:40:08 +0200 Subject: [PATCH 5/8] Adress review. --- compiler/rustc_resolve/src/imports.rs | 16 +++++++++------- compiler/rustc_resolve/src/lib.rs | 9 --------- 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index dc93c2fc454f0..eb08db0401ae5 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -973,7 +973,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// /// Meanwhile, if resolution is successful, the side effect of the resolution is returned. fn resolve_import<'r>( - self: &mut CmResolver<'r, 'ra, 'tcx>, + mut self: CmResolver<'r, 'ra, 'tcx>, import: Import<'ra>, ) -> (Option>, usize) { debug!( @@ -1018,12 +1018,15 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let mut import_bindings = PerNS::default(); let mut indeterminate_count = 0; - self.reborrow().per_ns_cm(|this, ns| { + + // HACK: Use array of namespaces in the same order as `per_ns_mut`. + // We can't use `per_ns_cm` because of the invariance on CmResolver (RefOrMut). + for ns in [TypeNS, ValueNS, MacroNS] { if !type_ns_only || ns == TypeNS { if bindings[ns].get() != PendingBinding::Pending { - return; + continue; }; - let binding_result = this.reborrow().maybe_resolve_ident_in_module( + let binding_result = self.reborrow().maybe_resolve_ident_in_module( module, source, ns, @@ -1033,7 +1036,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let pending_binding = match binding_result { Ok(binding) => { // We need the `target`, `source` can be extracted. - let imported_binding = this.import(binding, import); + let imported_binding = self.import(binding, import); Some(Some(imported_binding)) } Err(Determinacy::Determined) => Some(None), @@ -1044,8 +1047,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { }; import_bindings[ns] = pending_binding; } - }); - + } ( Some(SideEffect { imported_module: module, diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 6d42ec7b4aba4..6073d26b21ca6 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1823,15 +1823,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { f(self, MacroNS); } - fn per_ns_cm<'r, F: FnMut(&mut CmResolver<'r, 'ra, 'tcx>, Namespace)>( - mut self: CmResolver<'r, 'ra, 'tcx>, - mut f: F, - ) { - f(&mut self, TypeNS); - f(&mut self, ValueNS); - f(&mut self, MacroNS); - } - fn is_builtin_macro(&self, res: Res) -> bool { self.get_macro(res).is_some_and(|macro_data| macro_data.ext.builtin_name.is_some()) } From 42f3d7f822f29098595feb1b07ebdaf6a885e365 Mon Sep 17 00:00:00 2001 From: LorrensP-2158466 Date: Wed, 27 Aug 2025 18:10:42 +0200 Subject: [PATCH 6/8] bless correct tests --- tests/ui/imports/import-loop-2.rs | 4 ++-- tests/ui/imports/import-loop-2.stderr | 8 ++++---- tests/ui/imports/reexports.stderr | 20 ++++++++++---------- tests/ui/privacy/privacy1.stderr | 24 ++++++++++++------------ 4 files changed, 28 insertions(+), 28 deletions(-) diff --git a/tests/ui/imports/import-loop-2.rs b/tests/ui/imports/import-loop-2.rs index 42f9a07fff389..af5c6509d38b6 100644 --- a/tests/ui/imports/import-loop-2.rs +++ b/tests/ui/imports/import-loop-2.rs @@ -1,9 +1,9 @@ mod a { - pub use crate::b::x; + pub use crate::b::x; //~ ERROR unresolved import `crate::b::x` } mod b { - pub use crate::a::x; //~ ERROR unresolved import `crate::a::x` + pub use crate::a::x; fn main() { let y = x; } } diff --git a/tests/ui/imports/import-loop-2.stderr b/tests/ui/imports/import-loop-2.stderr index 2ef40c4e21829..dfa7cf35eaac2 100644 --- a/tests/ui/imports/import-loop-2.stderr +++ b/tests/ui/imports/import-loop-2.stderr @@ -1,8 +1,8 @@ -error[E0432]: unresolved import `crate::a::x` - --> $DIR/import-loop-2.rs:6:13 +error[E0432]: unresolved import `crate::b::x` + --> $DIR/import-loop-2.rs:2:13 | -LL | pub use crate::a::x; - | ^^^^^^^^^^^ no `x` in `a` +LL | pub use crate::b::x; + | ^^^^^^^^^^^ no `x` in `b` error: aborting due to 1 previous error diff --git a/tests/ui/imports/reexports.stderr b/tests/ui/imports/reexports.stderr index dec8a60f93ca0..0ebcf8e58d627 100644 --- a/tests/ui/imports/reexports.stderr +++ b/tests/ui/imports/reexports.stderr @@ -11,16 +11,16 @@ LL | pub use super::foo; | ^^^^^^^^^^ error[E0603]: module import `foo` is private - --> $DIR/reexports.rs:37:22 + --> $DIR/reexports.rs:36:22 | -LL | use crate::b::b::foo::S as T; +LL | use crate::b::a::foo::S; | ^^^ private module import | note: the module import `foo` is defined here... - --> $DIR/reexports.rs:29:17 + --> $DIR/reexports.rs:24:17 | -LL | pub use super::*; // This is also OK since the value `foo` is visible enough. - | ^^^^^^^^ +LL | pub use super::foo; // This is OK since the value `foo` is visible enough. + | ^^^^^^^^^^ note: ...and refers to the module `foo` which is defined here --> $DIR/reexports.rs:19:5 | @@ -28,16 +28,16 @@ LL | mod foo { | ^^^^^^^ error[E0603]: module import `foo` is private - --> $DIR/reexports.rs:36:22 + --> $DIR/reexports.rs:37:22 | -LL | use crate::b::a::foo::S; +LL | use crate::b::b::foo::S as T; | ^^^ private module import | note: the module import `foo` is defined here... - --> $DIR/reexports.rs:24:17 + --> $DIR/reexports.rs:29:17 | -LL | pub use super::foo; // This is OK since the value `foo` is visible enough. - | ^^^^^^^^^^ +LL | pub use super::*; // This is also OK since the value `foo` is visible enough. + | ^^^^^^^^ note: ...and refers to the module `foo` which is defined here --> $DIR/reexports.rs:19:5 | diff --git a/tests/ui/privacy/privacy1.stderr b/tests/ui/privacy/privacy1.stderr index 98750cee610e4..3dd4d29f3da0e 100644 --- a/tests/ui/privacy/privacy1.stderr +++ b/tests/ui/privacy/privacy1.stderr @@ -23,18 +23,6 @@ LL | mod baz { | ^^^^^^^ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0603]: module `baz` is private - --> $DIR/privacy1.rs:147:18 - | -LL | use bar::baz; - | ^^^ private module - | -note: the module `baz` is defined here - --> $DIR/privacy1.rs:56:5 - | -LL | mod baz { - | ^^^^^^^ - error[E0603]: module `i` is private --> $DIR/privacy1.rs:171:20 | @@ -47,6 +35,18 @@ note: the module `i` is defined here LL | mod i { | ^^^^^ +error[E0603]: module `baz` is private + --> $DIR/privacy1.rs:147:18 + | +LL | use bar::baz; + | ^^^ private module + | +note: the module `baz` is defined here + --> $DIR/privacy1.rs:56:5 + | +LL | mod baz { + | ^^^^^^^ + error[E0603]: module `baz` is private --> $DIR/privacy1.rs:110:21 | From c334245364460afb414e860648ec4dc1a776e74b Mon Sep 17 00:00:00 2001 From: LorrensP-2158466 Date: Wed, 27 Aug 2025 18:10:56 +0200 Subject: [PATCH 7/8] bless other tests --- tests/ui/imports/ambiguous-9.stderr | 38 +++-------------------------- tests/ui/imports/import4.rs | 3 +-- tests/ui/imports/import4.stderr | 13 +++++++--- 3 files changed, 13 insertions(+), 41 deletions(-) diff --git a/tests/ui/imports/ambiguous-9.stderr b/tests/ui/imports/ambiguous-9.stderr index 9222f3f99c1e3..6446f2129c60b 100644 --- a/tests/ui/imports/ambiguous-9.stderr +++ b/tests/ui/imports/ambiguous-9.stderr @@ -24,20 +24,12 @@ LL | pub use super::dsl::*; | ^^^^^^^^^^^^^ = help: consider adding an explicit import of `date_range` to disambiguate note: `date_range` could also refer to the function imported here - --> $DIR/ambiguous-9.rs:8:9 - | -LL | use super::prelude::*; - | ^^^^^^^^^^^^^^^^^ - = help: consider adding an explicit import of `date_range` to disambiguate - = note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default - -warning: ambiguous glob re-exports --> $DIR/ambiguous-9.rs:15:13 | LL | pub use self::t::*; | ^^^^^^^^^^ = help: consider adding an explicit import of `date_range` to disambiguate - = note: `#[deny(ambiguous_glob_imports)]` on by default + = note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default error: aborting due to 1 previous error; 1 warning emitted @@ -60,32 +52,8 @@ LL | pub use super::dsl::*; note: `date_range` could also refer to the function imported here --> $DIR/ambiguous-9.rs:15:13 | -LL | use super::prelude::*; - | ^^^^^^^^^^^^^^^^^ - = help: consider adding an explicit import of `date_range` to disambiguate - = note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default - -Future breakage diagnostic: -error: `date_range` is ambiguous - --> $DIR/ambiguous-9.rs:23:5 - | -LL | date_range(); - | ^^^^^^^^^^ ambiguous name - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #114095 - = note: ambiguous because of multiple glob imports of a name in the same module -note: `date_range` could refer to the function imported here - --> $DIR/ambiguous-9.rs:19:5 - | -LL | use dsl::*; - | ^^^^^^ - = help: consider adding an explicit import of `date_range` to disambiguate -note: `date_range` could also refer to the function imported here - --> $DIR/ambiguous-9.rs:20:5 - | -LL | use prelude::*; - | ^^^^^^^^^^ +LL | pub use self::t::*; + | ^^^^^^^^^^ = help: consider adding an explicit import of `date_range` to disambiguate = note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default diff --git a/tests/ui/imports/import4.rs b/tests/ui/imports/import4.rs index f670cc06201c0..9a23696a8416f 100644 --- a/tests/ui/imports/import4.rs +++ b/tests/ui/imports/import4.rs @@ -1,4 +1,3 @@ -mod a { pub use crate::b::foo; } -mod b { pub use crate::a::foo; } //~ ERROR unresolved import `crate::a::foo` +mod a { pub use crate::b::foo; } //~ ERROR unresolved import `crate::b` fn main() { println!("loop"); } diff --git a/tests/ui/imports/import4.stderr b/tests/ui/imports/import4.stderr index 4faa5f0520a9d..f28d0481155c3 100644 --- a/tests/ui/imports/import4.stderr +++ b/tests/ui/imports/import4.stderr @@ -1,8 +1,13 @@ -error[E0432]: unresolved import `crate::a::foo` - --> $DIR/import4.rs:2:17 +error[E0432]: unresolved import `crate::b` + --> $DIR/import4.rs:1:24 + | +LL | mod a { pub use crate::b::foo; } + | ^ use of unresolved module or unlinked crate `b` + | +help: you might be missing a crate named `b`, add it to your project and import it in your code + | +LL + extern crate b; | -LL | mod b { pub use crate::a::foo; } - | ^^^^^^^^^^^^^ no `foo` in `a` error: aborting due to 1 previous error From c6078220ed71ef0630aad7217f4978f1d2d94f12 Mon Sep 17 00:00:00 2001 From: LorrensP-2158466 Date: Wed, 27 Aug 2025 18:21:55 +0200 Subject: [PATCH 8/8] fix oopsie --- tests/ui/imports/import4.rs | 3 ++- tests/ui/imports/import4.stderr | 11 +++-------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/tests/ui/imports/import4.rs b/tests/ui/imports/import4.rs index 9a23696a8416f..76a9887534c34 100644 --- a/tests/ui/imports/import4.rs +++ b/tests/ui/imports/import4.rs @@ -1,3 +1,4 @@ -mod a { pub use crate::b::foo; } //~ ERROR unresolved import `crate::b` +mod a { pub use crate::b::foo; } //~ ERROR unresolved import `crate::b::foo` +mod b { pub use crate::a::foo; } fn main() { println!("loop"); } diff --git a/tests/ui/imports/import4.stderr b/tests/ui/imports/import4.stderr index f28d0481155c3..07fdc6a3d0ced 100644 --- a/tests/ui/imports/import4.stderr +++ b/tests/ui/imports/import4.stderr @@ -1,13 +1,8 @@ -error[E0432]: unresolved import `crate::b` - --> $DIR/import4.rs:1:24 +error[E0432]: unresolved import `crate::b::foo` + --> $DIR/import4.rs:1:17 | LL | mod a { pub use crate::b::foo; } - | ^ use of unresolved module or unlinked crate `b` - | -help: you might be missing a crate named `b`, add it to your project and import it in your code - | -LL + extern crate b; - | + | ^^^^^^^^^^^^^ no `foo` in `b` error: aborting due to 1 previous error