From e07272ab38beb5423cd134e6e1aeeb2261bc4551 Mon Sep 17 00:00:00 2001 From: LorrensP-2158466 Date: Fri, 8 Aug 2025 17:47:25 +0200 Subject: [PATCH 01/21] design of ImportResolver, which does the batched resolution --- compiler/rustc_resolve/src/imports.rs | 88 ++++++++++++++++++++++----- compiler/rustc_resolve/src/macros.rs | 2 +- 2 files changed, 74 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index d3790394d2a9a..efce677afabee 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,53 @@ use crate::{ type Res = def::Res; +pub(crate) struct ImportResolver<'r, 'ra, 'tcx> { + r: CmResolver<'r, 'ra, 'tcx>, // always immutable + batch: Vec>, // a.k.a. indeterminate_imports, also treated as output + + // outputs + determined_imports: Vec>, +} + +struct ImportResolutionOutputs<'ra> { + indeterminate_imports: Vec>, + determined_imports: Vec>, +} + +impl<'r, 'ra, 'tcx> ImportResolver<'r, 'ra, 'tcx> { + pub(crate) fn new(cmr: CmResolver<'r, 'ra, 'tcx>, batch: Vec>) -> Self { + ImportResolver { r: cmr, batch, determined_imports: Vec::new() } + } + + fn into_outputs(self) -> ImportResolutionOutputs<'ra> { + ImportResolutionOutputs { + indeterminate_imports: self.batch, + determined_imports: self.determined_imports, + } + } +} + +impl<'ra> ImportResolutionOutputs<'ra> { + fn commit<'tcx>(self, r: &mut Resolver<'ra, 'tcx>) { + r.indeterminate_imports = self.indeterminate_imports; + r.determined_imports.extend(self.determined_imports); + } +} + +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 +599,32 @@ 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 { + self.assert_speculative = true; 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); + let (outputs, count) = ImportResolver::new(self.cm(), batch).resolve_batch(); + indeterminate_count = count; + self.assert_speculative = false; + outputs.commit(self); + } + } + + fn resolve_batch<'r>( + mut self: ImportResolver<'r, 'ra, 'tcx>, + ) -> (ImportResolutionOutputs<'ra>, usize) { + let mut indeterminate_count = 0; + for import in mem::take(&mut self.batch) { + let import_indeterminate_count = self.resolve_import(import); + indeterminate_count += import_indeterminate_count; + match import_indeterminate_count { + 0 => self.determined_imports.push(import), + _ => self.batch.push(import), } } - self.assert_speculative = false; + (self.into_outputs(), indeterminate_count) } pub(crate) fn finalize_imports(&mut self) { @@ -839,7 +897,7 @@ 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>) -> usize { debug!( "(resolving import for module) resolving import `{}::...` in `{}`", Segment::names_to_string(&import.module_path), @@ -848,7 +906,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, @@ -869,15 +927,15 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } 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); + // specualtive resolution. + self.r.get_mut_unchecked().resolve_glob_import(import); return 0; } _ => unreachable!(), }; 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; diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 72ed899024168..e7ffa3a84de55 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -234,7 +234,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { } fn resolve_imports(&mut self) { - self.resolve_imports() + self.resolve_imports(); } fn resolve_macro_invocation( From 713fb32fe03a20ca9a4a442182551ddcbc40508f Mon Sep 17 00:00:00 2001 From: LorrensP-2158466 Date: Fri, 8 Aug 2025 17:59:37 +0200 Subject: [PATCH 02/21] isolate glob imports --- compiler/rustc_resolve/src/imports.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index efce677afabee..691ad301642d1 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -48,22 +48,25 @@ pub(crate) struct ImportResolver<'r, 'ra, 'tcx> { // outputs determined_imports: Vec>, + glob_imports: Vec>, } struct ImportResolutionOutputs<'ra> { indeterminate_imports: Vec>, determined_imports: Vec>, + glob_imports: Vec>, } impl<'r, 'ra, 'tcx> ImportResolver<'r, 'ra, 'tcx> { pub(crate) fn new(cmr: CmResolver<'r, 'ra, 'tcx>, batch: Vec>) -> Self { - ImportResolver { r: cmr, batch, determined_imports: Vec::new() } + ImportResolver { r: cmr, batch, determined_imports: Vec::new(), glob_imports: Vec::new() } } fn into_outputs(self) -> ImportResolutionOutputs<'ra> { ImportResolutionOutputs { indeterminate_imports: self.batch, determined_imports: self.determined_imports, + glob_imports: self.glob_imports, } } } @@ -72,6 +75,9 @@ impl<'ra> ImportResolutionOutputs<'ra> { fn commit<'tcx>(self, r: &mut Resolver<'ra, 'tcx>) { r.indeterminate_imports = self.indeterminate_imports; r.determined_imports.extend(self.determined_imports); + for glob in self.glob_imports { + r.resolve_glob_import(glob); + } } } @@ -926,9 +932,7 @@ 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 - // specualtive resolution. - self.r.get_mut_unchecked().resolve_glob_import(import); + self.glob_imports.push(import); return 0; } _ => unreachable!(), From 2de1b436b1c86795d21b372334d57b93ad8b7f47 Mon Sep 17 00:00:00 2001 From: LorrensP-2158466 Date: Fri, 8 Aug 2025 18:17:06 +0200 Subject: [PATCH 03/21] isolate single import --- compiler/rustc_hir/src/def.rs | 18 ++++++++ compiler/rustc_resolve/src/imports.rs | 61 ++++++++++++++++----------- compiler/rustc_resolve/src/lib.rs | 2 +- 3 files changed, 56 insertions(+), 25 deletions(-) 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 691ad301642d1..a5de8219b4452 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -49,17 +49,25 @@ pub(crate) struct ImportResolver<'r, 'ra, 'tcx> { // outputs determined_imports: Vec>, glob_imports: Vec>, + import_bindings: PerNS, Import<'ra>, PendingBinding<'ra>)>>, } struct ImportResolutionOutputs<'ra> { indeterminate_imports: Vec>, determined_imports: Vec>, glob_imports: Vec>, + import_bindings: PerNS, Import<'ra>, PendingBinding<'ra>)>>, } impl<'r, 'ra, 'tcx> ImportResolver<'r, 'ra, 'tcx> { pub(crate) fn new(cmr: CmResolver<'r, 'ra, 'tcx>, batch: Vec>) -> Self { - ImportResolver { r: cmr, batch, determined_imports: Vec::new(), glob_imports: Vec::new() } + ImportResolver { + r: cmr, + batch, + determined_imports: Vec::new(), + glob_imports: Vec::new(), + import_bindings: PerNS::default(), + } } fn into_outputs(self) -> ImportResolutionOutputs<'ra> { @@ -67,6 +75,7 @@ impl<'r, 'ra, 'tcx> ImportResolver<'r, 'ra, 'tcx> { indeterminate_imports: self.batch, determined_imports: self.determined_imports, glob_imports: self.glob_imports, + import_bindings: self.import_bindings, } } } @@ -78,6 +87,27 @@ impl<'ra> ImportResolutionOutputs<'ra> { for glob in self.glob_imports { r.resolve_glob_import(glob); } + + for (ns, import_bindings) in self.import_bindings.into_iter_with() { + for (parent, import, pending_binding) in import_bindings { + let ImportKind::Single { target, ref bindings, .. } = import.kind else { + unreachable!(); + }; + 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); + } + } } } @@ -926,6 +956,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } }; + // FIXME: isolate if not a cache. import.imported_module.set(Some(module)); let (source, target, bindings, type_ns_only) = match import.kind { ImportKind::Single { source, target, ref bindings, type_ns_only, .. } => { @@ -952,7 +983,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { 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() @@ -967,39 +998,21 @@ 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); + self.import_bindings[ns].push((parent, import, pending_binding)); } }); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 2063c46124c29..552fbd8a03a48 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -2533,7 +2533,7 @@ mod ref_mut { /// 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 { + pub(crate) fn _get_mut_unchecked(&mut self) -> &mut T { self.p } } From 661d7bd1672bf7c8cd52961f59b5688a2ce15133 Mon Sep 17 00:00:00 2001 From: LorrensP-2158466 Date: Fri, 8 Aug 2025 20:14:14 +0200 Subject: [PATCH 04/21] bless tests --- ...e-import-trait-associated-functions.stderr | 20 ++++++------ tests/ui/imports/reexports.stderr | 20 ++++++------ .../shadowed/shadowed-use-visibility.stderr | 32 +++++++++---------- 3 files changed, 36 insertions(+), 36 deletions(-) diff --git a/tests/ui/feature-gates/feature-gate-import-trait-associated-functions.stderr b/tests/ui/feature-gates/feature-gate-import-trait-associated-functions.stderr index fca3cef3e203d..0d3cd2c1170b6 100644 --- a/tests/ui/feature-gates/feature-gate-import-trait-associated-functions.stderr +++ b/tests/ui/feature-gates/feature-gate-import-trait-associated-functions.stderr @@ -18,16 +18,6 @@ LL | use A::{DEFAULT, new}; = help: add `#![feature(import_trait_associated_functions)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: `use` associated items of traits is unstable - --> $DIR/feature-gate-import-trait-associated-functions.rs:7:5 - | -LL | use Default::default; - | ^^^^^^^^^^^^^^^^ - | - = note: see issue #134691 for more information - = help: add `#![feature(import_trait_associated_functions)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - error[E0658]: `use` associated items of traits is unstable --> $DIR/feature-gate-import-trait-associated-functions.rs:27:26 | @@ -58,6 +48,16 @@ LL | use Glob::*; = help: add `#![feature(import_trait_associated_functions)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +error[E0658]: `use` associated items of traits is unstable + --> $DIR/feature-gate-import-trait-associated-functions.rs:7:5 + | +LL | use Default::default; + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #134691 for more information + = help: add `#![feature(import_trait_associated_functions)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0658`. 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 1ff85c36ddf2d000eb70882b6230eb68b3aac39e Mon Sep 17 00:00:00 2001 From: LorrensP-2158466 Date: Fri, 8 Aug 2025 20:55:57 +0200 Subject: [PATCH 05/21] nits --- compiler/rustc_resolve/src/imports.rs | 2 +- compiler/rustc_resolve/src/macros.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index a5de8219b4452..4113b5ea7b697 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -84,6 +84,7 @@ impl<'ra> ImportResolutionOutputs<'ra> { fn commit<'tcx>(self, r: &mut Resolver<'ra, 'tcx>) { r.indeterminate_imports = self.indeterminate_imports; r.determined_imports.extend(self.determined_imports); + for glob in self.glob_imports { r.resolve_glob_import(glob); } @@ -956,7 +957,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } }; - // FIXME: isolate if not a cache. import.imported_module.set(Some(module)); let (source, target, bindings, type_ns_only) = match import.kind { ImportKind::Single { source, target, ref bindings, type_ns_only, .. } => { diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index e7ffa3a84de55..72ed899024168 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -234,7 +234,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { } fn resolve_imports(&mut self) { - self.resolve_imports(); + self.resolve_imports() } fn resolve_macro_invocation( From a7f64a4e188398c28d4d0a6538f4259ff7ea775b Mon Sep 17 00:00:00 2001 From: LorrensP-2158466 Date: Sun, 10 Aug 2025 23:58:49 +0200 Subject: [PATCH 06/21] bless test --- ...e-import-trait-associated-functions.stderr | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/ui/feature-gates/feature-gate-import-trait-associated-functions.stderr b/tests/ui/feature-gates/feature-gate-import-trait-associated-functions.stderr index 0d3cd2c1170b6..fca3cef3e203d 100644 --- a/tests/ui/feature-gates/feature-gate-import-trait-associated-functions.stderr +++ b/tests/ui/feature-gates/feature-gate-import-trait-associated-functions.stderr @@ -18,6 +18,16 @@ LL | use A::{DEFAULT, new}; = help: add `#![feature(import_trait_associated_functions)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +error[E0658]: `use` associated items of traits is unstable + --> $DIR/feature-gate-import-trait-associated-functions.rs:7:5 + | +LL | use Default::default; + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #134691 for more information + = help: add `#![feature(import_trait_associated_functions)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + error[E0658]: `use` associated items of traits is unstable --> $DIR/feature-gate-import-trait-associated-functions.rs:27:26 | @@ -48,16 +58,6 @@ LL | use Glob::*; = help: add `#![feature(import_trait_associated_functions)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: `use` associated items of traits is unstable - --> $DIR/feature-gate-import-trait-associated-functions.rs:7:5 - | -LL | use Default::default; - | ^^^^^^^^^^^^^^^^ - | - = note: see issue #134691 for more information - = help: add `#![feature(import_trait_associated_functions)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0658`. From 1dbcd635ac66063d377103f9cf3f786d3063e2cc Mon Sep 17 00:00:00 2001 From: LorrensP-2158466 Date: Mon, 11 Aug 2025 10:36:33 +0200 Subject: [PATCH 07/21] work around prelude hack --- compiler/rustc_resolve/src/diagnostics.rs | 2 +- compiler/rustc_resolve/src/ident.rs | 2 +- compiler/rustc_resolve/src/imports.rs | 31 ++++++++++++++--------- compiler/rustc_resolve/src/lib.rs | 6 ++--- 4 files changed, 24 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 64641ecc0807e..13c1e38c67298 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1090,7 +1090,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ); } Scope::StdLibPrelude => { - if let Some(prelude) = this.prelude { + if let Some(prelude) = this.prelude.get() { let mut tmp_suggestions = Vec::new(); this.add_module_candidates(prelude, &mut tmp_suggestions, filter_fn, None); suggestions.extend( diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 650154d586fae..8bfb0d99172d1 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -584,7 +584,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { }, Scope::StdLibPrelude => { let mut result = Err(Determinacy::Determined); - if let Some(prelude) = this.prelude + if let Some(prelude) = this.prelude.get() && let Ok(binding) = this.reborrow().resolve_ident_in_module_unadjusted( ModuleOrUniformRoot::Module(prelude), ident, diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 4113b5ea7b697..6d80f579cc903 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -48,14 +48,16 @@ pub(crate) struct ImportResolver<'r, 'ra, 'tcx> { // outputs determined_imports: Vec>, - glob_imports: Vec>, + glob_import_outputs: Vec<(Module<'ra>, BindingKey, NameBinding<'ra>, bool)>, + glob_res_outputs: Vec<(NodeId, PartialRes)>, import_bindings: PerNS, Import<'ra>, PendingBinding<'ra>)>>, } struct ImportResolutionOutputs<'ra> { indeterminate_imports: Vec>, determined_imports: Vec>, - glob_imports: Vec>, + glob_import_outputs: Vec<(Module<'ra>, BindingKey, NameBinding<'ra>, bool)>, + glob_res_outputs: Vec<(NodeId, PartialRes)>, import_bindings: PerNS, Import<'ra>, PendingBinding<'ra>)>>, } @@ -65,8 +67,9 @@ impl<'r, 'ra, 'tcx> ImportResolver<'r, 'ra, 'tcx> { r: cmr, batch, determined_imports: Vec::new(), - glob_imports: Vec::new(), import_bindings: PerNS::default(), + glob_import_outputs: Vec::new(), + glob_res_outputs: Vec::new(), } } @@ -74,8 +77,9 @@ impl<'r, 'ra, 'tcx> ImportResolver<'r, 'ra, 'tcx> { ImportResolutionOutputs { indeterminate_imports: self.batch, determined_imports: self.determined_imports, - glob_imports: self.glob_imports, import_bindings: self.import_bindings, + glob_import_outputs: self.glob_import_outputs, + glob_res_outputs: self.glob_res_outputs, } } } @@ -85,8 +89,12 @@ impl<'ra> ImportResolutionOutputs<'ra> { r.indeterminate_imports = self.indeterminate_imports; r.determined_imports.extend(self.determined_imports); - for glob in self.glob_imports { - r.resolve_glob_import(glob); + for (module, key, binding, warn_ambiguity) in self.glob_import_outputs { + let _ = r.try_define_local(module, key.ident.0, key.ns, binding, warn_ambiguity); + } + + for (id, res) in self.glob_res_outputs { + r.record_partial_res(id, res); } for (ns, import_bindings) in self.import_bindings.into_iter_with() { @@ -1559,7 +1567,7 @@ 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>) { // This function is only called for glob imports. let ImportKind::Glob { id, .. } = import.kind else { unreachable!() }; @@ -1607,18 +1615,17 @@ 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( + self.glob_import_outputs.push(( import.parent_scope.module, - key.ident.0, - key.ns, + key, imported_binding, warn_ambiguity, - ); + )); } } // Record the destination of this import - self.record_partial_res(id, PartialRes::new(module.res().unwrap())); + self.glob_res_outputs.push((id, PartialRes::new(module.res().unwrap()))); } // Miscellaneous post-processing, including recording re-exports, diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 552fbd8a03a48..930458cf32d7e 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1559,7 +1559,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // AST. graph_root, assert_speculative: false, // Only set/cleared in Resolver::resolve_imports for now - prelude: None, + prelude: Cell::new(None), extern_prelude, field_names: Default::default(), @@ -1894,7 +1894,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { this.get_mut().traits_in_module(module, assoc_item, &mut found_traits); } Scope::StdLibPrelude => { - if let Some(module) = this.prelude { + if let Some(module) = this.prelude.get() { this.get_mut().traits_in_module(module, assoc_item, &mut found_traits); } } @@ -2040,7 +2040,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { if let ImportKind::MacroUse { warn_private: true } = import.kind { // Do not report the lint if the macro name resolves in stdlib prelude // even without the problematic `macro_use` import. - let found_in_stdlib_prelude = self.prelude.is_some_and(|prelude| { + let found_in_stdlib_prelude = self.prelude.get().is_some_and(|prelude| { let empty_module = self.empty_module; let arenas = self.arenas; self.cm() From 8472171312c37728e115abad72e84dabca1dbdef Mon Sep 17 00:00:00 2001 From: LorrensP-2158466 Date: Mon, 11 Aug 2025 21:19:07 +0200 Subject: [PATCH 08/21] address review --- compiler/rustc_resolve/src/diagnostics.rs | 2 +- compiler/rustc_resolve/src/ident.rs | 2 +- compiler/rustc_resolve/src/imports.rs | 46 ++++++++++++++++------- compiler/rustc_resolve/src/lib.rs | 12 ++---- 4 files changed, 37 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 13c1e38c67298..64641ecc0807e 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1090,7 +1090,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ); } Scope::StdLibPrelude => { - if let Some(prelude) = this.prelude.get() { + if let Some(prelude) = this.prelude { let mut tmp_suggestions = Vec::new(); this.add_module_candidates(prelude, &mut tmp_suggestions, filter_fn, None); suggestions.extend( diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 8bfb0d99172d1..650154d586fae 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -584,7 +584,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { }, Scope::StdLibPrelude => { let mut result = Err(Determinacy::Determined); - if let Some(prelude) = this.prelude.get() + if let Some(prelude) = this.prelude && let Ok(binding) = this.reborrow().resolve_ident_in_module_unadjusted( ModuleOrUniformRoot::Module(prelude), ident, diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 6d80f579cc903..917244785d118 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -5,7 +5,7 @@ use std::mem; use std::ops::Deref; use rustc_ast::NodeId; -use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; +use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::intern::Interned; use rustc_errors::codes::*; use rustc_errors::{Applicability, MultiSpan, pluralize, struct_span_code_err}; @@ -47,16 +47,20 @@ pub(crate) struct ImportResolver<'r, 'ra, 'tcx> { batch: Vec>, // a.k.a. indeterminate_imports, also treated as output // outputs + prelude: Option>, determined_imports: Vec>, - glob_import_outputs: Vec<(Module<'ra>, BindingKey, NameBinding<'ra>, bool)>, + module_glob_importers: FxIndexMap, Vec>>, + glob_import_bindings: Vec<(Module<'ra>, BindingKey, NameBinding<'ra>, bool)>, glob_res_outputs: Vec<(NodeId, PartialRes)>, import_bindings: PerNS, Import<'ra>, PendingBinding<'ra>)>>, } struct ImportResolutionOutputs<'ra> { + prelude: Option>, indeterminate_imports: Vec>, determined_imports: Vec>, - glob_import_outputs: Vec<(Module<'ra>, BindingKey, NameBinding<'ra>, bool)>, + module_glob_importers: FxIndexMap, Vec>>, + glob_import_bindings: Vec<(Module<'ra>, BindingKey, NameBinding<'ra>, bool)>, glob_res_outputs: Vec<(NodeId, PartialRes)>, import_bindings: PerNS, Import<'ra>, PendingBinding<'ra>)>>, } @@ -66,20 +70,24 @@ impl<'r, 'ra, 'tcx> ImportResolver<'r, 'ra, 'tcx> { ImportResolver { r: cmr, batch, - determined_imports: Vec::new(), - import_bindings: PerNS::default(), - glob_import_outputs: Vec::new(), - glob_res_outputs: Vec::new(), + prelude: None, + determined_imports: Default::default(), + module_glob_importers: Default::default(), + glob_import_bindings: Default::default(), + glob_res_outputs: Default::default(), + import_bindings: Default::default(), } } fn into_outputs(self) -> ImportResolutionOutputs<'ra> { ImportResolutionOutputs { + prelude: self.prelude, indeterminate_imports: self.batch, determined_imports: self.determined_imports, - import_bindings: self.import_bindings, - glob_import_outputs: self.glob_import_outputs, + module_glob_importers: self.module_glob_importers, + glob_import_bindings: self.glob_import_bindings, glob_res_outputs: self.glob_res_outputs, + import_bindings: self.import_bindings, } } } @@ -89,7 +97,17 @@ impl<'ra> ImportResolutionOutputs<'ra> { r.indeterminate_imports = self.indeterminate_imports; r.determined_imports.extend(self.determined_imports); - for (module, key, binding, warn_ambiguity) in self.glob_import_outputs { + // It's possible this particular round didn't set the prelude, so we should not + // unset it in the main resolver. + if self.prelude.is_some() { + r.prelude = self.prelude; + } + + for (module, glob_importers) in self.module_glob_importers { + module.glob_importers.borrow_mut().extend(glob_importers); + } + + for (module, key, binding, warn_ambiguity) in self.glob_import_bindings { let _ = r.try_define_local(module, key.ident.0, key.ns, binding, warn_ambiguity); } @@ -647,12 +665,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let mut prev_indeterminate_count = usize::MAX; let mut indeterminate_count = self.indeterminate_imports.len() * 3; while indeterminate_count < prev_indeterminate_count { - self.assert_speculative = true; prev_indeterminate_count = indeterminate_count; let batch = mem::take(&mut self.indeterminate_imports); + self.assert_speculative = true; let (outputs, count) = ImportResolver::new(self.cm(), batch).resolve_batch(); - indeterminate_count = count; self.assert_speculative = false; + indeterminate_count = count; outputs.commit(self); } } @@ -1591,7 +1609,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } // Add to module's glob_importers - module.glob_importers.borrow_mut().push(import); + self.module_glob_importers.entry(module).or_default().push(import); // Ensure that `resolutions` isn't borrowed during `try_define`, // since it might get updated via a glob cycle. @@ -1615,7 +1633,7 @@ 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()); - self.glob_import_outputs.push(( + self.glob_import_bindings.push(( import.parent_scope.module, key, imported_binding, diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 930458cf32d7e..f8f3271c4c172 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1559,7 +1559,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // AST. graph_root, assert_speculative: false, // Only set/cleared in Resolver::resolve_imports for now - prelude: Cell::new(None), + prelude: None, extern_prelude, field_names: Default::default(), @@ -1894,7 +1894,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { this.get_mut().traits_in_module(module, assoc_item, &mut found_traits); } Scope::StdLibPrelude => { - if let Some(module) = this.prelude.get() { + if let Some(module) = this.prelude { this.get_mut().traits_in_module(module, assoc_item, &mut found_traits); } } @@ -2040,7 +2040,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { if let ImportKind::MacroUse { warn_private: true } = import.kind { // Do not report the lint if the macro name resolves in stdlib prelude // even without the problematic `macro_use` import. - let found_in_stdlib_prelude = self.prelude.get().is_some_and(|prelude| { + let found_in_stdlib_prelude = self.prelude.is_some_and(|prelude| { let empty_module = self.empty_module; let arenas = self.arenas; self.cm() @@ -2530,12 +2530,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 - } } } From eee1707af0a3d47e3f973c718586468bbacef4d5 Mon Sep 17 00:00:00 2001 From: LorrensP-2158466 Date: Mon, 11 Aug 2025 21:28:42 +0200 Subject: [PATCH 09/21] refactor usage of ImportResolutionOutputs --- compiler/rustc_resolve/src/imports.rs | 62 +++++++++------------------ 1 file changed, 20 insertions(+), 42 deletions(-) diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 917244785d118..87d51f89f727c 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -44,51 +44,28 @@ type Res = def::Res; pub(crate) struct ImportResolver<'r, 'ra, 'tcx> { r: CmResolver<'r, 'ra, 'tcx>, // always immutable - batch: Vec>, // a.k.a. indeterminate_imports, also treated as output - - // outputs - prelude: Option>, - determined_imports: Vec>, - module_glob_importers: FxIndexMap, Vec>>, - glob_import_bindings: Vec<(Module<'ra>, BindingKey, NameBinding<'ra>, bool)>, - glob_res_outputs: Vec<(NodeId, PartialRes)>, - import_bindings: PerNS, Import<'ra>, PendingBinding<'ra>)>>, + outputs: ImportResolutionOutputs<'ra>, } +#[derive(Default)] struct ImportResolutionOutputs<'ra> { prelude: Option>, indeterminate_imports: Vec>, determined_imports: Vec>, module_glob_importers: FxIndexMap, Vec>>, - glob_import_bindings: Vec<(Module<'ra>, BindingKey, NameBinding<'ra>, bool)>, - glob_res_outputs: Vec<(NodeId, PartialRes)>, - import_bindings: PerNS, Import<'ra>, PendingBinding<'ra>)>>, + glob_import_bindings: + Vec<(Module<'ra>, BindingKey, NameBinding<'ra>, bool /* warn_ambiguity */)>, + glob_path_res: Vec<(NodeId, PartialRes)>, + single_import_bindings: PerNS, Import<'ra>, PendingBinding<'ra>)>>, } impl<'r, 'ra, 'tcx> ImportResolver<'r, 'ra, 'tcx> { - pub(crate) fn new(cmr: CmResolver<'r, 'ra, 'tcx>, batch: Vec>) -> Self { - ImportResolver { - r: cmr, - batch, - prelude: None, - determined_imports: Default::default(), - module_glob_importers: Default::default(), - glob_import_bindings: Default::default(), - glob_res_outputs: Default::default(), - import_bindings: Default::default(), - } + pub(crate) fn new(cmr: CmResolver<'r, 'ra, 'tcx>) -> Self { + ImportResolver { r: cmr, outputs: Default::default() } } fn into_outputs(self) -> ImportResolutionOutputs<'ra> { - ImportResolutionOutputs { - prelude: self.prelude, - indeterminate_imports: self.batch, - determined_imports: self.determined_imports, - module_glob_importers: self.module_glob_importers, - glob_import_bindings: self.glob_import_bindings, - glob_res_outputs: self.glob_res_outputs, - import_bindings: self.import_bindings, - } + self.outputs } } @@ -111,11 +88,11 @@ impl<'ra> ImportResolutionOutputs<'ra> { let _ = r.try_define_local(module, key.ident.0, key.ns, binding, warn_ambiguity); } - for (id, res) in self.glob_res_outputs { + for (id, res) in self.glob_path_res { r.record_partial_res(id, res); } - for (ns, import_bindings) in self.import_bindings.into_iter_with() { + for (ns, import_bindings) in self.single_import_bindings.into_iter_with() { for (parent, import, pending_binding) in import_bindings { let ImportKind::Single { target, ref bindings, .. } = import.kind else { unreachable!(); @@ -668,7 +645,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { prev_indeterminate_count = indeterminate_count; let batch = mem::take(&mut self.indeterminate_imports); self.assert_speculative = true; - let (outputs, count) = ImportResolver::new(self.cm(), batch).resolve_batch(); + let (outputs, count) = ImportResolver::new(self.cm()).resolve_batch(batch); self.assert_speculative = false; indeterminate_count = count; outputs.commit(self); @@ -677,14 +654,15 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { fn resolve_batch<'r>( mut self: ImportResolver<'r, 'ra, 'tcx>, + batch: Vec>, ) -> (ImportResolutionOutputs<'ra>, usize) { let mut indeterminate_count = 0; - for import in mem::take(&mut self.batch) { + for import in batch { let import_indeterminate_count = self.resolve_import(import); indeterminate_count += import_indeterminate_count; match import_indeterminate_count { - 0 => self.determined_imports.push(import), - _ => self.batch.push(import), + 0 => self.outputs.determined_imports.push(import), + _ => self.outputs.indeterminate_imports.push(import), } } (self.into_outputs(), indeterminate_count) @@ -1038,7 +1016,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { return; } }; - self.import_bindings[ns].push((parent, import, pending_binding)); + self.outputs.single_import_bindings[ns].push((parent, import, pending_binding)); } }); @@ -1609,7 +1587,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } // Add to module's glob_importers - self.module_glob_importers.entry(module).or_default().push(import); + self.outputs.module_glob_importers.entry(module).or_default().push(import); // Ensure that `resolutions` isn't borrowed during `try_define`, // since it might get updated via a glob cycle. @@ -1633,7 +1611,7 @@ 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()); - self.glob_import_bindings.push(( + self.outputs.glob_import_bindings.push(( import.parent_scope.module, key, imported_binding, @@ -1643,7 +1621,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } // Record the destination of this import - self.glob_res_outputs.push((id, PartialRes::new(module.res().unwrap()))); + self.outputs.glob_path_res.push((id, PartialRes::new(module.res().unwrap()))); } // Miscellaneous post-processing, including recording re-exports, From 813e06ab3490bfb80b1204cdc4e7a273f6315c2a Mon Sep 17 00:00:00 2001 From: LorrensP-2158466 Date: Tue, 12 Aug 2025 07:12:18 +0200 Subject: [PATCH 10/21] update tests --- 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 +++--- 5 files changed, 59 insertions(+), 49 deletions(-) create mode 100644 fail.rs 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`. From ffab60c37715a4989d6da03bb2c812e5692575ce Mon Sep 17 00:00:00 2001 From: LorrensP-2158466 Date: Tue, 12 Aug 2025 20:25:25 +0200 Subject: [PATCH 11/21] address review --- compiler/rustc_resolve/src/imports.rs | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 87d51f89f727c..b7709c7b6a32a 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -42,7 +42,7 @@ use crate::{ type Res = def::Res; -pub(crate) struct ImportResolver<'r, 'ra, 'tcx> { +struct ImportResolver<'r, 'ra, 'tcx> { r: CmResolver<'r, 'ra, 'tcx>, // always immutable outputs: ImportResolutionOutputs<'ra>, } @@ -59,16 +59,6 @@ struct ImportResolutionOutputs<'ra> { single_import_bindings: PerNS, Import<'ra>, PendingBinding<'ra>)>>, } -impl<'r, 'ra, 'tcx> ImportResolver<'r, 'ra, 'tcx> { - pub(crate) fn new(cmr: CmResolver<'r, 'ra, 'tcx>) -> Self { - ImportResolver { r: cmr, outputs: Default::default() } - } - - fn into_outputs(self) -> ImportResolutionOutputs<'ra> { - self.outputs - } -} - impl<'ra> ImportResolutionOutputs<'ra> { fn commit<'tcx>(self, r: &mut Resolver<'ra, 'tcx>) { r.indeterminate_imports = self.indeterminate_imports; @@ -645,7 +635,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { prev_indeterminate_count = indeterminate_count; let batch = mem::take(&mut self.indeterminate_imports); self.assert_speculative = true; - let (outputs, count) = ImportResolver::new(self.cm()).resolve_batch(batch); + let (outputs, count) = + ImportResolver { r: self.cm(), outputs: Default::default() }.resolve_batch(batch); self.assert_speculative = false; indeterminate_count = count; outputs.commit(self); @@ -665,7 +656,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { _ => self.outputs.indeterminate_imports.push(import), } } - (self.into_outputs(), indeterminate_count) + (self.outputs, indeterminate_count) } pub(crate) fn finalize_imports(&mut self) { From 8b4d0bbd33289921986f8d33c3320b529eae6aa6 Mon Sep 17 00:00:00 2001 From: LorrensP-2158466 Date: Tue, 12 Aug 2025 21:11:02 +0200 Subject: [PATCH 12/21] refactor ImportResolutionOutputs to use SideEffect --- compiler/rustc_resolve/src/imports.rs | 167 ++++++++++++++++---------- 1 file changed, 102 insertions(+), 65 deletions(-) diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index b7709c7b6a32a..9f255d83112b5 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -5,7 +5,7 @@ use std::mem; use std::ops::Deref; use rustc_ast::NodeId; -use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; +use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_data_structures::intern::Interned; use rustc_errors::codes::*; use rustc_errors::{Applicability, MultiSpan, pluralize, struct_span_code_err}; @@ -47,59 +47,89 @@ struct ImportResolver<'r, 'ra, 'tcx> { outputs: ImportResolutionOutputs<'ra>, } +enum SideEffect<'ra> { + None, + Prelude, + Single { + parent: Module<'ra>, + import_bindings: PerNS>, + }, + Glob { + parent: Module<'ra>, + import_bindings: Vec<(NameBinding<'ra>, BindingKey, bool /* warn_ambiguity */)>, + path_res: PartialRes, + }, +} + #[derive(Default)] struct ImportResolutionOutputs<'ra> { - prelude: Option>, indeterminate_imports: Vec>, - determined_imports: Vec>, - module_glob_importers: FxIndexMap, Vec>>, - glob_import_bindings: - Vec<(Module<'ra>, BindingKey, NameBinding<'ra>, bool /* warn_ambiguity */)>, - glob_path_res: Vec<(NodeId, PartialRes)>, - single_import_bindings: PerNS, Import<'ra>, PendingBinding<'ra>)>>, + 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.extend(self.determined_imports); - - // It's possible this particular round didn't set the prelude, so we should not - // unset it in the main resolver. - if self.prelude.is_some() { - r.prelude = self.prelude; - } - - for (module, glob_importers) in self.module_glob_importers { - module.glob_importers.borrow_mut().extend(glob_importers); - } - - for (module, key, binding, warn_ambiguity) in self.glob_import_bindings { - let _ = r.try_define_local(module, key.ident.0, key.ns, binding, warn_ambiguity); - } + r.determined_imports.reserve(self.determined_imports.len()); + + for (import, side_effect) in self.determined_imports { + r.determined_imports.push(import); + + match (&import.kind, side_effect) { + ( + ImportKind::Single { target, bindings, .. }, + SideEffect::Single { parent, 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 { parent, import_bindings, path_res }, + ) => { + let ModuleOrUniformRoot::Module(module) = import.imported_module.get().unwrap() + else { + unreachable!(); + }; - for (id, res) in self.glob_path_res { - r.record_partial_res(id, res); - } + module.glob_importers.borrow_mut().push(import); - for (ns, import_bindings) in self.single_import_bindings.into_iter_with() { - for (parent, import, pending_binding) in import_bindings { - let ImportKind::Single { target, ref bindings, .. } = import.kind else { - unreachable!(); - }; - 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); - }); + 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, path_res); + } + (ImportKind::Glob { is_prelude: true, .. }, SideEffect::Prelude) => { + let ModuleOrUniformRoot::Module(module) = import.imported_module.get().unwrap() + else { + unreachable!() + }; + r.prelude = Some(module); } - bindings[ns].set(pending_binding); + + (_, SideEffect::None) => {} + // Something weird happened, which shouldn't have happened. + _ => unreachable!("Mismatched import kind and side effect"), } } } @@ -649,10 +679,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ) -> (ImportResolutionOutputs<'ra>, usize) { let mut indeterminate_count = 0; for import in batch { - let import_indeterminate_count = self.resolve_import(import); + 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), + 0 => self.outputs.determined_imports.push((import, side_effect)), _ => self.outputs.indeterminate_imports.push(import), } } @@ -929,7 +959,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// /// Meanwhile, if resolve successful, the resolved bindings are written /// into the module. - fn resolve_import<'r>(self: &mut ImportResolver<'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), @@ -947,8 +980,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); + } } }; @@ -958,12 +993,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { (source, target, bindings, type_ns_only) } ImportKind::Glob { .. } => { - self.glob_imports.push(import); - return 0; + return (self.resolve_glob_import(import), 0); } _ => unreachable!(), }; + let mut import_bindings = PerNS::default(); let mut indeterminate_count = 0; self.r.reborrow().per_ns_cm(|this, ns| { if !type_ns_only || ns == TypeNS { @@ -977,7 +1012,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { &import.parent_scope, Some(import), ); - let parent = import.parent_scope.module; let pending_binding = match binding_result { Ok(binding) => { if binding.is_assoc_item() @@ -1007,11 +1041,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { return; } }; - self.outputs.single_import_bindings[ns].push((parent, import, pending_binding)); + import_bindings[ns] = pending_binding; } }); - indeterminate_count + ( + SideEffect::Single { parent: import.parent_scope.module, import_bindings }, + indeterminate_count, + ) } /// Performs final import resolution, consistency checks and error reporting. @@ -1554,13 +1591,16 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { false } - fn resolve_glob_import<'r>(self: &mut ImportResolver<'r, 'ra, 'tcx>, 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 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() { @@ -1574,12 +1614,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } if module == import.parent_scope.module { - return; + return SideEffect::None; } - // Add to module's glob_importers - self.outputs.module_glob_importers.entry(module).or_default().push(import); - // Ensure that `resolutions` isn't borrowed during `try_define`, // since it might get updated via a glob cycle. let bindings = self @@ -1590,6 +1627,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), @@ -1602,17 +1640,16 @@ 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()); - self.outputs.glob_import_bindings.push(( - import.parent_scope.module, - key, - imported_binding, - warn_ambiguity, - )); + import_bindings.push((imported_binding, key, warn_ambiguity)); } } // Record the destination of this import - self.outputs.glob_path_res.push((id, PartialRes::new(module.res().unwrap()))); + SideEffect::Glob { + parent: import.parent_scope.module, + import_bindings, + path_res: PartialRes::new(module.res().unwrap()), + } } // Miscellaneous post-processing, including recording re-exports, From c5154ecd813150ca2f0b705f3419209b8c03bedc Mon Sep 17 00:00:00 2001 From: LorrensP-2158466 Date: Sun, 17 Aug 2025 09:00:15 +0200 Subject: [PATCH 13/21] remove things forgotten in rebase --- compiler/rustc_resolve/src/imports.rs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 9f255d83112b5..6189b734cc9bd 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -49,7 +49,6 @@ struct ImportResolver<'r, 'ra, 'tcx> { enum SideEffect<'ra> { None, - Prelude, Single { parent: Module<'ra>, import_bindings: PerNS>, @@ -119,13 +118,6 @@ impl<'ra> ImportResolutionOutputs<'ra> { r.record_partial_res(*id, path_res); } - (ImportKind::Glob { is_prelude: true, .. }, SideEffect::Prelude) => { - let ModuleOrUniformRoot::Module(module) = import.imported_module.get().unwrap() - else { - unreachable!() - }; - r.prelude = Some(module); - } (_, SideEffect::None) => {} // Something weird happened, which shouldn't have happened. @@ -1596,7 +1588,7 @@ impl<'ra, 'tcx> Resolver<'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 }); From 0d66eee8489083b7e3956d45f35b929229b34f64 Mon Sep 17 00:00:00 2001 From: LorrensP-2158466 Date: Sun, 17 Aug 2025 22:52:45 +0200 Subject: [PATCH 14/21] simplify SideEffect --- compiler/rustc_resolve/src/imports.rs | 32 +++++++-------------------- 1 file changed, 8 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 6189b734cc9bd..4882c9357567f 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -49,15 +49,8 @@ struct ImportResolver<'r, 'ra, 'tcx> { enum SideEffect<'ra> { None, - Single { - parent: Module<'ra>, - import_bindings: PerNS>, - }, - Glob { - parent: Module<'ra>, - import_bindings: Vec<(NameBinding<'ra>, BindingKey, bool /* warn_ambiguity */)>, - path_res: PartialRes, - }, + Single { import_bindings: PerNS> }, + Glob { import_bindings: Vec<(NameBinding<'ra>, BindingKey, bool /* warn_ambiguity */)> }, } #[derive(Default)] @@ -74,10 +67,11 @@ impl<'ra> ImportResolutionOutputs<'ra> { 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 { parent, import_bindings }, + SideEffect::Single { import_bindings }, ) => { for (ns, pending_binding) in import_bindings.into_iter_with() { match pending_binding { @@ -95,10 +89,7 @@ impl<'ra> ImportResolutionOutputs<'ra> { bindings[ns].set(pending_binding); } } - ( - ImportKind::Glob { id, .. }, - SideEffect::Glob { parent, import_bindings, path_res }, - ) => { + (ImportKind::Glob { id, .. }, SideEffect::Glob { import_bindings }) => { let ModuleOrUniformRoot::Module(module) = import.imported_module.get().unwrap() else { unreachable!(); @@ -116,7 +107,7 @@ impl<'ra> ImportResolutionOutputs<'ra> { ); } - r.record_partial_res(*id, path_res); + r.record_partial_res(*id, PartialRes::new(module.res().unwrap())); } (_, SideEffect::None) => {} @@ -1037,10 +1028,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } }); - ( - SideEffect::Single { parent: import.parent_scope.module, import_bindings }, - indeterminate_count, - ) + (SideEffect::Single { import_bindings }, indeterminate_count) } /// Performs final import resolution, consistency checks and error reporting. @@ -1637,11 +1625,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } // Record the destination of this import - SideEffect::Glob { - parent: import.parent_scope.module, - import_bindings, - path_res: PartialRes::new(module.res().unwrap()), - } + SideEffect::Glob { import_bindings } } // Miscellaneous post-processing, including recording re-exports, From ca821fd03713f0cd14c05650a5b05b7dc5f46019 Mon Sep 17 00:00:00 2001 From: LorrensP-2158466 Date: Tue, 19 Aug 2025 12:14:06 +0200 Subject: [PATCH 15/21] refactor out ImportResolver --- compiler/rustc_resolve/src/imports.rs | 64 ++++++++------------------- 1 file changed, 18 insertions(+), 46 deletions(-) diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 4882c9357567f..c4d34438cef10 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,11 +41,6 @@ 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> }, @@ -60,6 +54,10 @@ struct ImportResolutionOutputs<'ra> { } impl<'ra> ImportResolutionOutputs<'ra> { + fn new() -> Self { + Default::default() + } + fn commit<'tcx>(self, r: &mut Resolver<'ra, 'tcx>) { r.indeterminate_imports = self.indeterminate_imports; r.determined_imports.reserve(self.determined_imports.len()); @@ -118,20 +116,6 @@ impl<'ra> ImportResolutionOutputs<'ra> { } } -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> { @@ -646,32 +630,21 @@ 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); + let mut outputs = ImportResolutionOutputs::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 => outputs.determined_imports.push((import, side_effect)), + _ => outputs.indeterminate_imports.push(import), + } + } 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.outputs, indeterminate_count) - } - pub(crate) fn finalize_imports(&mut self) { for module in self.arenas.local_modules().iter() { self.finalize_resolutions_in(*module); @@ -940,10 +913,9 @@ 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) { debug!( @@ -954,7 +926,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, @@ -983,7 +955,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { 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; @@ -1572,7 +1544,7 @@ 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> { // This function is only called for glob imports. From a206ca5d561e4200d27361ac7fdaf00ced835ffc Mon Sep 17 00:00:00 2001 From: LorrensP-2158466 Date: Tue, 19 Aug 2025 13:06:40 +0200 Subject: [PATCH 16/21] imported_module is a side effect as well. --- compiler/rustc_resolve/src/imports.rs | 62 +++++++++++++++++++-------- 1 file changed, 43 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index c4d34438cef10..f1754624e28f4 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -41,16 +41,21 @@ use crate::{ type Res = def::Res; -enum SideEffect<'ra> { +enum SideEffectBindings<'ra> { None, Single { import_bindings: PerNS> }, Glob { import_bindings: Vec<(NameBinding<'ra>, BindingKey, bool /* warn_ambiguity */)> }, } +struct SideEffect<'ra> { + imported_module: ModuleOrUniformRoot<'ra>, + bindings: SideEffectBindings<'ra>, +} + #[derive(Default)] struct ImportResolutionOutputs<'ra> { indeterminate_imports: Vec>, - determined_imports: Vec<(Import<'ra>, SideEffect<'ra>)>, + determined_imports: Vec<(Import<'ra>, Option>)>, } impl<'ra> ImportResolutionOutputs<'ra> { @@ -65,11 +70,17 @@ impl<'ra> ImportResolutionOutputs<'ra> { for (import, side_effect) in self.determined_imports { r.determined_imports.push(import); + let Some(SideEffect { imported_module, bindings: side_effect_bindings }) = side_effect + else { + return; + }; + import.imported_module.set(Some(imported_module)); let parent = import.parent_scope.module; - match (&import.kind, side_effect) { + + match (&import.kind, side_effect_bindings) { ( ImportKind::Single { target, bindings, .. }, - SideEffect::Single { import_bindings }, + SideEffectBindings::Single { import_bindings }, ) => { for (ns, pending_binding) in import_bindings.into_iter_with() { match pending_binding { @@ -87,10 +98,11 @@ impl<'ra> ImportResolutionOutputs<'ra> { bindings[ns].set(pending_binding); } } - (ImportKind::Glob { id, .. }, SideEffect::Glob { import_bindings }) => { + (ImportKind::Glob { id, .. }, SideEffectBindings::Glob { import_bindings }) => { let ModuleOrUniformRoot::Module(module) = import.imported_module.get().unwrap() else { - unreachable!(); + r.dcx().emit_err(CannotGlobImportAllCrates { span: import.span }); + continue; }; module.glob_importers.borrow_mut().push(import); @@ -108,7 +120,8 @@ impl<'ra> ImportResolutionOutputs<'ra> { r.record_partial_res(*id, PartialRes::new(module.res().unwrap())); } - (_, SideEffect::None) => {} + (_, SideEffectBindings::None) => {} + // Something weird happened, which shouldn't have happened. _ => unreachable!("Mismatched import kind and side effect"), } @@ -917,7 +930,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { fn resolve_import<'r>( 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), @@ -935,20 +948,25 @@ 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 { 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!(), }; @@ -1000,7 +1018,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } }); - (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. @@ -1546,13 +1570,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { fn resolve_glob_import<'r>( 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() { @@ -1566,7 +1590,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } if module == import.parent_scope.module { - return SideEffect::None; + return SideEffectBindings::None; } // Ensure that `resolutions` isn't borrowed during `try_define`, @@ -1597,7 +1621,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } // Record the destination of this import - SideEffect::Glob { import_bindings } + SideEffectBindings::Glob { import_bindings } } // Miscellaneous post-processing, including recording re-exports, From 9f0a292c9c5a50a50402aa15db6c0911df8b8ad2 Mon Sep 17 00:00:00 2001 From: LorrensP-2158466 Date: Tue, 19 Aug 2025 13:10:03 +0200 Subject: [PATCH 17/21] report errors in the commit phase --- compiler/rustc_resolve/src/imports.rs | 42 +++++++++++++-------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index f1754624e28f4..596a6ff304869 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -85,6 +85,17 @@ impl<'ra> ImportResolutionOutputs<'ra> { for (ns, pending_binding) in import_bindings.into_iter_with() { match pending_binding { PendingBinding::Ready(Some(binding)) => { + if binding.is_assoc_item() + && !r.tcx.features().import_trait_associated_functions() + { + feature_err( + r.tcx.sess, + sym::import_trait_associated_functions, + import.span, + "`use` associated items of traits is unstable", + ) + .emit(); + } r.define_binding_local(parent, *target, ns, binding); } PendingBinding::Ready(None) => { @@ -105,6 +116,16 @@ impl<'ra> ImportResolutionOutputs<'ra> { continue; }; + if module.is_trait() && !r.tcx.features().import_trait_associated_functions() { + feature_err( + r.tcx.sess, + sym::import_trait_associated_functions, + import.span, + "`use` associated items of traits is unstable", + ) + .emit(); + } + module.glob_importers.borrow_mut().push(import); for (binding, key, warn_ambiguity) in import_bindings { @@ -987,17 +1008,6 @@ 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)) @@ -1579,16 +1589,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { 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 SideEffectBindings::None; } From d283efee43f9a0a1f7f1d1c5f50b09a7d646b259 Mon Sep 17 00:00:00 2001 From: LorrensP-2158466 Date: Tue, 19 Aug 2025 13:33:31 +0200 Subject: [PATCH 18/21] correct assignment of bindings and remove `PerNs::into_iter_(with)` --- compiler/rustc_hir/src/def.rs | 18 ----------- compiler/rustc_resolve/src/imports.rs | 44 ++++++++++++++------------- 2 files changed, 23 insertions(+), 39 deletions(-) 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 596a6ff304869..8f057892415a7 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -82,32 +82,40 @@ impl<'ra> ImportResolutionOutputs<'ra> { ImportKind::Single { target, bindings, .. }, SideEffectBindings::Single { import_bindings }, ) => { - for (ns, pending_binding) in import_bindings.into_iter_with() { - match pending_binding { + r.per_ns(|this, ns| { + match import_bindings[ns] { PendingBinding::Ready(Some(binding)) => { if binding.is_assoc_item() - && !r.tcx.features().import_trait_associated_functions() + && !this.tcx.features().import_trait_associated_functions() { feature_err( - r.tcx.sess, + this.tcx.sess, sym::import_trait_associated_functions, import.span, "`use` associated items of traits is unstable", ) .emit(); } - r.define_binding_local(parent, *target, ns, binding); + this.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); - }); + // 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(pending_binding); - } + bindings[ns].set(import_bindings[ns]); + }); } (ImportKind::Glob { id, .. }, SideEffectBindings::Glob { import_bindings }) => { let ModuleOrUniformRoot::Module(module) = import.imported_module.get().unwrap() @@ -976,7 +984,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } }; - 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) } @@ -992,7 +1000,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { _ => unreachable!(), }; - let mut import_bindings = PerNS::default(); + let mut import_bindings = bindings.clone().map(|b| b.get()); let mut indeterminate_count = 0; self.reborrow().per_ns_cm(|this, ns| { if !type_ns_only || ns == TypeNS { @@ -1012,16 +1020,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { 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) - } + Err(Determinacy::Determined) => PendingBinding::Ready(None), Err(Determinacy::Undetermined) => { indeterminate_count += 1; - return; + PendingBinding::Pending } }; import_bindings[ns] = pending_binding; From 8ca8d760aaa4937ffe2052a1e04be317da2a2bc1 Mon Sep 17 00:00:00 2001 From: LorrensP-2158466 Date: Tue, 19 Aug 2025 20:55:29 +0200 Subject: [PATCH 19/21] address review --- compiler/rustc_resolve/src/imports.rs | 286 +++++++++++++------------- 1 file changed, 143 insertions(+), 143 deletions(-) diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 8f057892415a7..0b7fdbba8f747 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -41,125 +41,30 @@ use crate::{ type Res = def::Res; +/// 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 */)> }, + /// Side effect that should be applied to the field `bindings` of `ImportKind::Single`. + /// + /// The inner `Option` is the actual side effect, it tells us wether 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 */)>, + }, } +/// The side effect made when resolving an undeterminate import. struct SideEffect<'ra> { imported_module: ModuleOrUniformRoot<'ra>, bindings: SideEffectBindings<'ra>, } -#[derive(Default)] -struct ImportResolutionOutputs<'ra> { - indeterminate_imports: Vec>, - determined_imports: Vec<(Import<'ra>, Option>)>, -} - -impl<'ra> ImportResolutionOutputs<'ra> { - fn new() -> Self { - Default::default() - } - - 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 Some(SideEffect { imported_module, bindings: side_effect_bindings }) = side_effect - else { - return; - }; - import.imported_module.set(Some(imported_module)); - let parent = import.parent_scope.module; - - match (&import.kind, side_effect_bindings) { - ( - ImportKind::Single { target, bindings, .. }, - SideEffectBindings::Single { import_bindings }, - ) => { - r.per_ns(|this, ns| { - match import_bindings[ns] { - PendingBinding::Ready(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); - } - PendingBinding::Ready(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(import_bindings[ns]); - }); - } - (ImportKind::Glob { id, .. }, SideEffectBindings::Glob { import_bindings }) => { - let ModuleOrUniformRoot::Module(module) = import.imported_module.get().unwrap() - else { - r.dcx().emit_err(CannotGlobImportAllCrates { span: import.span }); - continue; - }; - - if module.is_trait() && !r.tcx.features().import_trait_associated_functions() { - feature_err( - r.tcx.sess, - sym::import_trait_associated_functions, - import.span, - "`use` associated items of traits is unstable", - ) - .emit(); - } - - 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())); - } - - (_, SideEffectBindings::None) => {} - - // Something weird happened, which shouldn't have happened. - _ => unreachable!("Mismatched import kind and side effect"), - } - } - } -} - /// 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] @@ -659,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. @@ -672,18 +578,116 @@ 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 mut outputs = ImportResolutionOutputs::new(); + indeterminate_count = 0; + let mut import_resolutions = Vec::new(); self.assert_speculative = true; 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 => outputs.determined_imports.push((import, side_effect)), - _ => outputs.indeterminate_imports.push(import), + 0 => import_resolutions.push((import, side_effect)), + _ => self.indeterminate_imports.push(import), } } self.assert_speculative = false; - outputs.commit(self); + self.commit_import_resolutions(import_resolutions); + } + } + + fn commit_import_resolutions( + &mut self, + import_resolutions: Vec<(Import<'ra>, Option>)>, + ) { + self.determined_imports.reserve(self.determined_imports.len()); + + for (import, side_effect) in import_resolutions { + self.determined_imports.push(import); + + let Some(SideEffect { imported_module, bindings: side_effect_bindings }) = side_effect + else { + return; + }; + import.imported_module.set(Some(imported_module)); + 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 => return, + } + }); + } + (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(); + } + + module.glob_importers.borrow_mut().push(import); + + 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"), + } } } @@ -1000,7 +1004,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { _ => unreachable!(), }; - let mut import_bindings = bindings.clone().map(|b| b.get()); + let mut import_bindings = PerNS::default(); let mut indeterminate_count = 0; self.reborrow().per_ns_cm(|this, ns| { if !type_ns_only || ns == TypeNS { @@ -1018,12 +1022,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { Ok(binding) => { // We need the `target`, `source` can be extracted. let imported_binding = this.import(binding, import); - PendingBinding::Ready(Some(imported_binding)) + Some(Some(imported_binding)) } - Err(Determinacy::Determined) => PendingBinding::Ready(None), + Err(Determinacy::Determined) => Some(None), Err(Determinacy::Undetermined) => { indeterminate_count += 1; - PendingBinding::Pending + None } }; import_bindings[ns] = pending_binding; @@ -1595,34 +1599,30 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { 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 SideEffectBindings::Glob { import_bindings } } From c32f608391e190aa3baf953369d6009989cc6708 Mon Sep 17 00:00:00 2001 From: LorrensP-2158466 Date: Tue, 19 Aug 2025 21:10:22 +0200 Subject: [PATCH 20/21] typo --- compiler/rustc_resolve/src/imports.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 0b7fdbba8f747..affd93f72e870 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -46,7 +46,7 @@ enum SideEffectBindings<'ra> { None, /// Side effect that should be applied to the field `bindings` of `ImportKind::Single`. /// - /// The inner `Option` is the actual side effect, it tells us wether we found a binding + /// 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 { From 4efdee856a310506ad624f2bfe1d282f09b55638 Mon Sep 17 00:00:00 2001 From: LorrensP-2158466 Date: Thu, 21 Aug 2025 17:05:41 +0200 Subject: [PATCH 21/21] establish links of glob importers + possible bug fix --- compiler/rustc_resolve/src/imports.rs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index affd93f72e870..7dcd153dda2d2 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -599,15 +599,25 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { import_resolutions: Vec<(Import<'ra>, Option>)>, ) { self.determined_imports.reserve(self.determined_imports.len()); + for (import, side_effect) in import_resolutions.iter() { + self.determined_imports.push(*import); + let Some(SideEffect { imported_module, .. }) = side_effect else { + continue; + }; + import.imported_module.set(Some(*imported_module)); - for (import, side_effect) in import_resolutions { - self.determined_imports.push(import); + if import.is_glob() + && let ModuleOrUniformRoot::Module(module) = imported_module + { + module.glob_importers.borrow_mut().push(*import); + } + } + for (import, side_effect) in import_resolutions { let Some(SideEffect { imported_module, bindings: side_effect_bindings }) = side_effect else { - return; + continue; }; - import.imported_module.set(Some(imported_module)); let parent = import.parent_scope.module; match (&import.kind, side_effect_bindings) { @@ -668,8 +678,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { .emit(); } - module.glob_importers.borrow_mut().push(import); - for (binding, key, warn_ambiguity) in import_bindings { let _ = self.try_define_local( parent,