diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 2201d493f2de5..a583adcb7efb8 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -619,6 +619,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 403d440bee786..da233a85ee673 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,90 @@ 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>, + 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(), + import_bindings: PerNS::default(), + } + } + + fn into_outputs(self) -> ImportResolutionOutputs<'ra> { + ImportResolutionOutputs { + indeterminate_imports: self.batch, + determined_imports: self.determined_imports, + glob_imports: self.glob_imports, + import_bindings: self.import_bindings, + } + } +} + +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); + } + + 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); + } + } + } +} + +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> { @@ -552,22 +637,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) { @@ -840,7 +935,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), @@ -849,7 +944,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,16 +964,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { (source, target, bindings, type_ns_only) } ImportKind::Glob { .. } => { - // FIXME: Use mutable resolver directly as a hack, this should be an output of - // specualtive resolution. - self.get_mut_unchecked().resolve_glob_import(import); + self.glob_imports.push(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; @@ -891,7 +984,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() @@ -906,39 +999,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 - // specualtive 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 - // specualtive 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 e5df23a86cb9f..a7b04e5db68e4 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -2504,7 +2504,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 } } 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 |