diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 650a0dc82ce2..7485dd51863b 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -298,7 +298,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { &segments, Some(TypeNS), parent_scope, - if finalize { Finalize::SimplePath(id, path.span) } else { Finalize::No }, + finalize.then(|| Finalize::new(id, path.span)), None, ) { PathResult::Module(ModuleOrUniformRoot::Module(module)) => { diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index e0a83ba8c0d4..981d60db2f38 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -417,15 +417,12 @@ impl<'a> Resolver<'a> { crate fn lint_if_path_starts_with_module( &mut self, - finalize: Finalize, + finalize: Option, path: &[Segment], second_binding: Option<&NameBinding<'_>>, ) { - let (diag_id, diag_span) = match finalize { - Finalize::No => return, - Finalize::SimplePath(id, path_span) => (id, path_span), - Finalize::UsePath { root_id, root_span, .. } => (root_id, root_span), - Finalize::QPathTrait { qpath_id, qpath_span, .. } => (qpath_id, qpath_span), + let Some(Finalize { node_id, root_span, .. }) = finalize else { + return; }; let first_name = match path.get(0) { @@ -463,11 +460,11 @@ impl<'a> Resolver<'a> { } } - let diag = BuiltinLintDiagnostics::AbsPathWithModule(diag_span); + let diag = BuiltinLintDiagnostics::AbsPathWithModule(root_span); self.lint_buffer.buffer_lint_with_diagnostic( ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, - diag_id, - diag_span, + node_id, + root_span, "absolute paths must start with `self`, `super`, \ `crate`, or an external crate name in the 2018 edition", diag, @@ -1873,7 +1870,7 @@ impl<'a> Resolver<'a> { ident, ns_to_try, parent_scope, - Finalize::No, + None, &ribs[ns_to_try], unusable_binding, ) { @@ -1921,7 +1918,7 @@ impl<'a> Resolver<'a> { ident, ValueNS, parent_scope, - Finalize::No, + None, &ribs[ValueNS], unusable_binding, ) diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 84fe0ec83d26..48a052dd2f07 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -279,7 +279,7 @@ impl<'a> Resolver<'a> { mut ident: Ident, ns: Namespace, parent_scope: &ParentScope<'a>, - finalize_full: Finalize, + finalize_full: Option, ribs: &[Rib<'a>], unusable_binding: Option<&'a NameBinding<'a>>, ) -> Option> { @@ -302,7 +302,7 @@ impl<'a> Resolver<'a> { let normalized_ident = Ident { span: normalized_span, ..ident }; // Walk backwards up the ribs in scope. - let finalize = finalize_full.path_span(); + let finalize = finalize_full.map(|finalize| finalize.path_span); let mut module = self.graph_root; for i in (0..ribs.len()).rev() { debug!("walk rib\n{:?}", ribs[i].bindings); @@ -354,7 +354,7 @@ impl<'a> Resolver<'a> { } self.early_resolve_ident_in_lexical_scope( orig_ident, - ScopeSet::Late(ns, module, finalize_full.node_id()), + ScopeSet::Late(ns, module, finalize_full.map(|finalize| finalize.node_id)), parent_scope, finalize, finalize.is_some(), @@ -1371,7 +1371,7 @@ impl<'a> Resolver<'a> { opt_ns: Option, // `None` indicates a module path in import parent_scope: &ParentScope<'a>, ) -> PathResult<'a> { - self.resolve_path_with_ribs(path, opt_ns, parent_scope, Finalize::No, None, None) + self.resolve_path_with_ribs(path, opt_ns, parent_scope, None, None, None) } #[tracing::instrument(level = "debug", skip(self))] @@ -1380,7 +1380,7 @@ impl<'a> Resolver<'a> { path: &[Segment], opt_ns: Option, // `None` indicates a module path in import parent_scope: &ParentScope<'a>, - finalize: Finalize, + finalize: Option, unusable_binding: Option<&'a NameBinding<'a>>, ) -> PathResult<'a> { self.resolve_path_with_ribs(path, opt_ns, parent_scope, finalize, None, unusable_binding) @@ -1391,13 +1391,13 @@ impl<'a> Resolver<'a> { path: &[Segment], opt_ns: Option, // `None` indicates a module path in import parent_scope: &ParentScope<'a>, - finalize_full: Finalize, + finalize_full: Option, ribs: Option<&PerNS>>>, unusable_binding: Option<&'a NameBinding<'a>>, ) -> PathResult<'a> { debug!("resolve_path(path={:?}, opt_ns={:?}, finalize={:?})", path, opt_ns, finalize_full); - let finalize = finalize_full.path_span(); + let finalize = finalize_full.map(|finalize| finalize.path_span); let mut module = None; let mut allow_super = true; let mut second_binding = None; diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 01dc727737a5..3d6ad8a42b89 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -594,11 +594,8 @@ impl<'a, 'b> ImportResolver<'a, 'b> { _ => None, }; let prev_ambiguity_errors_len = self.r.ambiguity_errors.len(); - let finalize = Finalize::UsePath { - root_id: import.root_id, - root_span: import.root_span, - path_span: import.span, - }; + let finalize = + Some(Finalize::with_root_span(import.root_id, import.span, import.root_span)); let path_res = self.r.resolve_path( &import.module_path, None, diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 53bd589fdcde..106c6a2d4ec3 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -578,7 +578,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { .resolve_ident_in_lexical_scope( self_ty, TypeNS, - Finalize::SimplePath(ty.id, ty.span), + Some(Finalize::new(ty.id, ty.span)), None, ) .map_or(Res::Err, |d| d.res()); @@ -958,7 +958,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { ident, ns, &self.parent_scope, - Finalize::No, + None, &self.ribs[ns], None, ) @@ -968,7 +968,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { &mut self, ident: Ident, ns: Namespace, - finalize: Finalize, + finalize: Option, unusable_binding: Option<&'a NameBinding<'a>>, ) -> Option> { self.r.resolve_ident_in_lexical_scope( @@ -985,7 +985,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { &mut self, path: &[Segment], opt_ns: Option, // `None` indicates a module path in import - finalize: Finalize, + finalize: Option, ) -> PathResult<'a> { self.r.resolve_path_with_ribs( path, @@ -1299,11 +1299,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { partial_res: PartialRes, path: &[Segment], source: PathSource<'_>, - finalize: Finalize, + path_span: Span, ) { - let Some(path_span) = finalize.path_span() else { - return; - }; let proj_start = path.len() - partial_res.unresolved_segments(); for (i, segment) in path.iter().enumerate() { if segment.has_lifetime_args { @@ -1576,8 +1573,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { report_error(self, ns); } Some(LexicalScopeBinding::Item(binding)) => { - if let Some(LexicalScopeBinding::Res(..)) = self - .resolve_ident_in_lexical_scope(ident, ns, Finalize::No, Some(binding)) + if let Some(LexicalScopeBinding::Res(..)) = + self.resolve_ident_in_lexical_scope(ident, ns, None, Some(binding)) { report_error(self, ns); } @@ -1979,7 +1976,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { None, &path, PathSource::Trait(AliasPossibility::No), - Finalize::SimplePath(trait_ref.ref_id, trait_ref.path.span), + Finalize::new(trait_ref.ref_id, trait_ref.path.span), ); if let Some(def_id) = res.base_res().opt_def_id() { new_id = Some(def_id); @@ -2653,7 +2650,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { qself, &Segment::from_path(path), source, - Finalize::SimplePath(id, path.span), + Finalize::new(id, path.span), ); } @@ -2672,8 +2669,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { ); let ns = source.namespace(); - let (id, path_span) = - finalize.node_id_and_path_span().expect("unexpected speculative resolution"); + let Finalize { node_id, path_span, .. } = finalize; let report_errors = |this: &mut Self, res: Option| { if this.should_report_errs() { let (err, candidates) = @@ -2787,7 +2783,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { if ns == ValueNS { let item_name = path.last().unwrap().ident; let traits = self.traits_in_scope(item_name, ns); - self.r.trait_map.insert(id, traits); + self.r.trait_map.insert(node_id, traits); } if PrimTy::from_name(path[0].ident.name).is_some() { @@ -2796,7 +2792,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { std_path.push(Segment::from_ident(Ident::with_dummy_span(sym::std))); std_path.extend(path); if let PathResult::Module(_) | PathResult::NonModule(_) = - self.resolve_path(&std_path, Some(ns), Finalize::No) + self.resolve_path(&std_path, Some(ns), None) { // Check if we wrote `str::from_utf8` instead of `std::str::from_utf8` let item_span = @@ -2823,8 +2819,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { if !matches!(source, PathSource::TraitItem(..)) { // Avoid recording definition of `A::B` in `::B::C`. - self.r.record_partial_res(id, partial_res); - self.resolve_elided_lifetimes_in_path(id, partial_res, path, source, finalize); + self.r.record_partial_res(node_id, partial_res); + self.resolve_elided_lifetimes_in_path(node_id, partial_res, path, source, path_span); } partial_res @@ -2932,21 +2928,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { // the trait (the slice upto and including // `qself.position`). And then we recursively resolve that, // but with `qself` set to `None`. - // - // However, setting `qself` to none (but not changing the - // span) loses the information about where this path - // *actually* appears, so for the purposes of the crate - // lint we pass along information that this is the trait - // name from a fully qualified path, and this also - // contains the full span (the `Finalize::QPathTrait`). let ns = if qself.position + 1 == path.len() { ns } else { TypeNS }; let partial_res = self.smart_resolve_path_fragment( None, &path[..=qself.position], PathSource::TraitItem(ns), - finalize.node_id_and_path_span().map_or(Finalize::No, |(qpath_id, path_span)| { - Finalize::QPathTrait { qpath_id, qpath_span: qself.path_span, path_span } - }), + Finalize::with_root_span(finalize.node_id, finalize.path_span, qself.path_span), ); // The remaining segments (the `C` in our example) will @@ -2958,7 +2945,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { ))); } - let result = match self.resolve_path(&path, Some(ns), finalize) { + let result = match self.resolve_path(&path, Some(ns), Some(finalize)) { PathResult::NonModule(path_res) => path_res, PathResult::Module(ModuleOrUniformRoot::Module(module)) if !module.is_normal() => { PartialRes::new(module.res().unwrap()) @@ -2996,10 +2983,9 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { && result.base_res() != Res::Err && path[0].ident.name != kw::PathRoot && path[0].ident.name != kw::DollarCrate - && let Some((id, path_span)) = finalize.node_id_and_path_span() { let unqualified_result = { - match self.resolve_path(&[*path.last().unwrap()], Some(ns), Finalize::No) { + match self.resolve_path(&[*path.last().unwrap()], Some(ns), None) { PathResult::NonModule(path_res) => path_res.base_res(), PathResult::Module(ModuleOrUniformRoot::Module(module)) => { module.res().unwrap() @@ -3009,7 +2995,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { }; if result.base_res() == unqualified_result { let lint = lint::builtin::UNUSED_QUALIFICATIONS; - self.r.lint_buffer.buffer_lint(lint, id, path_span, "unnecessary qualification") + self.r.lint_buffer.buffer_lint( + lint, + finalize.node_id, + finalize.path_span, + "unnecessary qualification", + ) } } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index a5243bf8ac3f..3076cc113170 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -3,7 +3,7 @@ use crate::late::lifetimes::{ElisionFailureInfo, LifetimeContext}; use crate::late::{AliasPossibility, LateResolutionVisitor, RibKind}; use crate::late::{LifetimeBinderKind, LifetimeRibKind}; use crate::path_names_to_string; -use crate::{Finalize, Module, ModuleKind, ModuleOrUniformRoot}; +use crate::{Module, ModuleKind, ModuleOrUniformRoot}; use crate::{PathResult, PathSource, Segment}; use rustc_ast::visit::FnKind; @@ -189,7 +189,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { (String::new(), "the crate root".to_string()) } else { let mod_path = &path[..path.len() - 1]; - let mod_prefix = match self.resolve_path(mod_path, Some(TypeNS), Finalize::No) { + let mod_prefix = match self.resolve_path(mod_path, Some(TypeNS), None) { PathResult::Module(ModuleOrUniformRoot::Module(module)) => module.res(), _ => None, } @@ -648,7 +648,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { if let crate::PathSource::TraitItem(_) = source { let mod_path = &path[..path.len() - 1]; if let PathResult::Module(ModuleOrUniformRoot::Module(module)) = - self.resolve_path(mod_path, None, Finalize::No) + self.resolve_path(mod_path, None, None) { let resolutions = self.r.resolutions(module).borrow(); let targets: Vec<_> = @@ -1362,7 +1362,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { // Search in module. let mod_path = &path[..path.len() - 1]; if let PathResult::Module(ModuleOrUniformRoot::Module(module)) = - self.resolve_path(mod_path, Some(TypeNS), Finalize::No) + self.resolve_path(mod_path, Some(TypeNS), None) { self.r.add_module_candidates(module, &mut names, &filter_fn); } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index dbc4f337ad3b..330636fe5432 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -2044,42 +2044,24 @@ fn module_to_string(module: Module<'_>) -> Option { } #[derive(Copy, Clone, Debug)] -enum Finalize { - /// Do not issue the lint. - No, - - /// This lint applies to some arbitrary path; e.g., `impl ::foo::Bar`. - /// In this case, we can take the span of that path. - SimplePath(NodeId, Span), - - /// This lint comes from a `use` statement. In this case, what we - /// care about really is the *root* `use` statement; e.g., if we - /// have nested things like `use a::{b, c}`, we care about the - /// `use a` part. - UsePath { root_id: NodeId, root_span: Span, path_span: Span }, - - /// This is the "trait item" from a fully qualified path. For example, - /// we might be resolving `X::Y::Z` from a path like `::Z`. - /// The `path_span` is the span of the to the trait itself (`X::Y`). - QPathTrait { qpath_id: NodeId, qpath_span: Span, path_span: Span }, +struct Finalize { + /// Node ID for linting. + node_id: NodeId, + /// Span of the whole path or some its characteristic fragment. + /// E.g. span of `b` in `foo::{a, b, c}`, or full span for regular paths. + path_span: Span, + /// Span of the path start, suitable for prepending something to to it. + /// E.g. span of `foo` in `foo::{a, b, c}`, or full span for regular paths. + root_span: Span, } impl Finalize { - fn node_id_and_path_span(&self) -> Option<(NodeId, Span)> { - match *self { - Finalize::No => None, - Finalize::SimplePath(id, path_span) - | Finalize::UsePath { root_id: id, path_span, .. } - | Finalize::QPathTrait { qpath_id: id, path_span, .. } => Some((id, path_span)), - } + fn new(node_id: NodeId, path_span: Span) -> Finalize { + Finalize { node_id, path_span, root_span: path_span } } - fn node_id(&self) -> Option { - self.node_id_and_path_span().map(|(id, _)| id) - } - - fn path_span(&self) -> Option { - self.node_id_and_path_span().map(|(_, path_span)| path_span) + fn with_root_span(node_id: NodeId, path_span: Span, root_span: Span) -> Finalize { + Finalize { node_id, path_span, root_span } } } diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 01f0b11f1ac3..e1aa22765669 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -673,7 +673,7 @@ impl<'a> Resolver<'a> { &path, Some(MacroNS), &parent_scope, - Finalize::SimplePath(ast::CRATE_NODE_ID, path_span), + Some(Finalize::new(ast::CRATE_NODE_ID, path_span)), None, ) { PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 => {