diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 06673379a5e9f..c1fb1ecc7797e 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -27,7 +27,7 @@ use crate::diagnostics::{ }; use crate::{ AllowReturnTypeNotation, GenericArgsMode, ImplTraitContext, ImplTraitPosition, LoweringContext, - ParamMode, ResolverAstLoweringExt, TryBlockScope, + ParamMode, TryBlockScope, }; pub(super) struct WillCreateDefIdsVisitor; @@ -211,8 +211,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } ExprKind::Tup(elts) => hir::ExprKind::Tup(self.lower_exprs(elts)), ExprKind::Call(f, args) => { - if let Some(legacy_args) = self.resolver.legacy_const_generic_args(f, self.tcx) - { + if let Some(legacy_args) = self.owner.legacy_const_generic_args(f, self.tcx) { self.lower_legacy_const_generics((**f).clone(), args.clone(), &legacy_args) } else { let f = self.lower_expr(f); diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 7e9827c4e494c..ad7bcf5b062bf 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -672,7 +672,6 @@ impl<'hir> LoweringContext<'_, 'hir> { // Add all the nested `PathListItem`s to the HIR. for &(ref use_tree, id) in trees { let owner_id = self.owner_id(id); - // Each `use` import is an item and thus are owners of the // names in the path. Up to this point the nested import is // the current owner, since we want each desugared import to diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index f04b5cfc92724..98a0a5e07396e 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -60,10 +60,9 @@ use rustc_hir::definitions::PerParentDisambiguatorState; use rustc_hir::lints::DelayedLint; use rustc_hir::{ self as hir, AngleBrackets, ConstArg, GenericArg, HirId, ItemLocalMap, LifetimeSource, - LifetimeSyntax, MissingLifetimeKind, ParamName, Target, TraitCandidate, find_attr, + LifetimeSyntax, MissingLifetimeKind, ParamName, Target, TraitCandidate, }; use rustc_index::{Idx, IndexVec}; -use rustc_macros::extension; use rustc_middle::queries::Providers; use rustc_middle::span_bug; use rustc_middle::ty::{PerOwnerResolverData, ResolverAstLowering, TyCtxt}; @@ -319,40 +318,6 @@ impl SpanLowerer { } } -#[extension(trait ResolverAstLoweringExt<'tcx>)] -impl<'tcx> ResolverAstLowering<'tcx> { - fn legacy_const_generic_args(&self, expr: &Expr, tcx: TyCtxt<'tcx>) -> Option> { - let ExprKind::Path(None, path) = &expr.kind else { - return None; - }; - - // Don't perform legacy const generics rewriting if the path already - // has generic arguments. - if path.segments.last().unwrap().args.is_some() { - return None; - } - - // We do not need to look at `partial_res_overrides`. That map only contains overrides for - // `self_param` locals. And here we are looking for the function definition that `expr` - // resolves to. - let def_id = self.partial_res_map.get(&expr.id)?.full_res()?.opt_def_id()?; - - // We only support cross-crate argument rewriting. Uses - // within the same crate should be updated to use the new - // const generics style. - if def_id.is_local() { - return None; - } - - // we can use parsed attrs here since for other crates they're already available - find_attr!( - tcx, def_id, - RustcLegacyConstGenerics{fn_indexes,..} => fn_indexes - ) - .map(|fn_indexes| fn_indexes.iter().map(|(num, _)| *num).collect()) - } -} - /// How relaxed bounds `?Trait` should be treated. /// /// Relaxed bounds should only be allowed in places where we later @@ -799,7 +764,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn get_partial_res(&self, id: NodeId) -> Option { match self.partial_res_overrides.get(&id) { Some(self_param_id) => Some(PartialRes::new(Res::Local(*self_param_id))), - None => self.resolver.partial_res_map.get(&id).copied(), + None => self.owner.partial_res_map.get(&id).copied(), } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 9b582eeb2c520..84200336ce695 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -228,6 +228,9 @@ pub struct PerOwnerResolverData<'tcx> { /// Lifetime parameters that lowering will have to introduce. pub extra_lifetime_params_map: NodeMap> = Default::default(), + /// Resolutions for nodes that have a single resolution. + pub partial_res_map: NodeMap = Default::default(), + /// The id of the owner pub id: ast::NodeId, /// The `DefId` of the owner, can't be found in `node_id_to_def_id`. @@ -259,15 +262,47 @@ impl<'tcx> PerOwnerResolverData<'tcx> { pub fn extra_lifetime_params(&self, id: NodeId) -> &[(Ident, NodeId, MissingLifetimeKind)] { self.extra_lifetime_params_map.get(&id).map_or(&[], |v| &v[..]) } + + pub fn legacy_const_generic_args( + &self, + expr: &ast::Expr, + tcx: TyCtxt<'tcx>, + ) -> Option> { + let ast::ExprKind::Path(None, path) = &expr.kind else { + return None; + }; + + // Don't perform legacy const generics rewriting if the path already + // has generic arguments. + if path.segments.last().unwrap().args.is_some() { + return None; + } + + // We do not need to look at `partial_res_overrides`. That map only contains overrides for + // `self_param` locals. And here we are looking for the function definition that `expr` + // resolves to. + let def_id = self.partial_res_map.get(&expr.id)?.full_res()?.opt_def_id()?; + + // We only support cross-crate argument rewriting. Uses + // within the same crate should be updated to use the new + // const generics style. + if def_id.is_local() { + return None; + } + + // we can use parsed attrs here since for other crates they're already available + find_attr!( + tcx, def_id, + RustcLegacyConstGenerics{fn_indexes,..} => fn_indexes + ) + .map(|fn_indexes| fn_indexes.iter().map(|(num, _)| *num).collect()) + } } /// Resolutions that should only be used for lowering. /// This struct is meant to be consumed by lowering. #[derive(Debug)] pub struct ResolverAstLowering<'tcx> { - /// Resolutions for nodes that have a single resolution. - pub partial_res_map: NodeMap, - pub next_node_id: ast::NodeId, pub owners: NodeMap>, diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 8f8b2807522e0..091f4a51a6560 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -491,6 +491,7 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { vis: vis.clone(), parent_scope: self.parent_scope, error, + owner: self.r.current_owner.id, }); Visibility::Public } diff --git a/compiler/rustc_resolve/src/diagnostics/impls.rs b/compiler/rustc_resolve/src/diagnostics/impls.rs index 0b6b9899f48a6..80231af0ac749 100644 --- a/compiler/rustc_resolve/src/diagnostics/impls.rs +++ b/compiler/rustc_resolve/src/diagnostics/impls.rs @@ -56,7 +56,7 @@ use crate::{ DelayedVisResolutionError, Finalize, ForwardGenericParamBanReason, HasGenericParams, IdentKey, LateDecl, MacroRulesScope, Module, ModuleKind, ModuleOrUniformRoot, ParentScope, PathResult, PrivacyError, Res, ResolutionError, Resolver, Scope, ScopeSet, Segment, UseError, Used, - VisResolutionError, path_names_to_string, + VisResolutionError, path_names_to_string, with_owner, }; /// A vector of spans and replacements, a message and applicability. @@ -381,13 +381,15 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } fn report_delayed_vis_resolution_errors(&mut self) { - for DelayedVisResolutionError { vis, parent_scope, error } in + for DelayedVisResolutionError { vis, parent_scope, error, owner } in mem::take(&mut self.delayed_vis_resolution_errors) { - match self.try_resolve_visibility(&parent_scope, &vis, true) { - Ok(_) => self.report_vis_error(error), - Err(error) => self.report_vis_error(error), - }; + with_owner(self, owner, |this| { + match this.try_resolve_visibility(&parent_scope, &vis, true) { + Ok(_) => this.report_vis_error(error), + Err(error) => this.report_vis_error(error), + } + }); } } diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 3f2e24995deab..43b297a3b0b8b 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -37,7 +37,7 @@ use crate::{ AmbiguityError, BindingKey, CmResolver, Decl, DeclData, DeclKind, Determinacy, Finalize, IdentKey, ImportSuggestion, ImportSummary, LocalModule, ModuleOrUniformRoot, ParentScope, PathResult, PerNS, Res, ResolutionError, Resolver, ScopeSet, Segment, Used, module_to_string, - names_to_string, + names_to_string, with_owner, }; /// A potential import declaration in the process of being planted into a module. @@ -906,7 +906,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { .expect("planting a glob cannot fail"); } - self.record_partial_res(*id, PartialRes::new(module.res().unwrap())); + with_owner(self, *id, |this| { + this.record_partial_res(*id, PartialRes::new(module.res().unwrap())) + }); } // Something weird happened, which shouldn't have happened. @@ -936,7 +938,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { .map(|i| (false, i)) .chain(indeterminate_imports.iter().map(|(i, _, _)| (true, i))) { - let unresolved_import_error = self.finalize_import(*import); + let unresolved_import_error = + with_owner(self, import.id().unwrap(), |this| this.finalize_import(*import)); // If this import is unresolved then create a dummy import // resolution for it so that later resolve stages won't complain. self.import_dummy_binding(*import, is_indeterminate); @@ -1319,8 +1322,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { PathResult::Indeterminate => unreachable!(), }; - let (ident, target, bindings, import_id) = match import.kind { - ImportKind::Single { source, target, ref decls, id, .. } => (source, target, decls, id), + let (ident, target, bindings) = match import.kind { + ImportKind::Single { source, target, ref decls, .. } => (source, target, decls), ImportKind::Glob { ref max_vis, id, def_id } => { if import.module_path.len() <= 1 { // HACK(eddyb) `lint_if_path_starts_with_module` needs at least @@ -1644,7 +1647,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // purposes it's good enough to just favor one over the other. self.per_ns(|this, ns| { if let Some(binding) = bindings[ns].get().decl().map(|b| b.import_source()) { - this.owners.get_mut(&import_id).unwrap().import_res[ns] = Some(binding.res()); + this.current_owner.import_res[ns] = Some(binding.res()); } }); diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 2726598c40894..57fac031a0fc6 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1521,6 +1521,10 @@ impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tc self.resolve_anon_const(v, AnonConstKind::FieldDefaultValue); } } + + fn visit_nested_use_tree(&mut self, use_tree: &'ast UseTree, id: NodeId) { + with_owner(self, id, |this| visit::walk_use_tree(this, use_tree)) + } } impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { @@ -5030,7 +5034,10 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { // Fix up partial res of segment from `resolve_path` call. if let Some(id) = path[0].id { - self.r.partial_res_map.insert(id, PartialRes::new(Res::PrimTy(prim))); + let res = PartialRes::new(Res::PrimTy(prim)); + self.r.partial_res_map.insert(id, res); + self.r.current_owner.partial_res_map.insert(id, res); + assert_ne!(self.r.current_owner.id, DUMMY_NODE_ID); } PartialRes::with_unresolved_segments(Res::PrimTy(prim), path.len() - 1) @@ -5319,7 +5326,11 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ExprKind::Call(ref callee, ref arguments) => { self.resolve_expr(callee, Some(expr)); - let const_args = self.r.legacy_const_generic_args(callee).unwrap_or_default(); + let const_args = self + .r + .current_owner + .legacy_const_generic_args(callee, self.r.tcx) + .unwrap_or_default(); for (idx, argument) in arguments.iter().enumerate() { // Constant arguments need to be treated as AnonConst since // that is how they will be later lowered to HIR. diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 111eae6a4134f..c125babba2a83 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -40,8 +40,8 @@ use macros::{MacroRulesDecl, MacroRulesScope, MacroRulesScopeRef}; use rustc_arena::{DroplessArena, TypedArena}; use rustc_ast::node_id::NodeMap; use rustc_ast::{ - self as ast, AngleBracketedArg, CRATE_NODE_ID, Crate, DUMMY_NODE_ID, Expr, ExprKind, - GenericArg, GenericArgs, Generics, NodeId, Path, attr, + self as ast, AngleBracketedArg, CRATE_NODE_ID, Crate, DUMMY_NODE_ID, GenericArg, GenericArgs, + Generics, NodeId, Path, attr, }; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet, default}; use rustc_data_structures::intern::Interned; @@ -58,7 +58,7 @@ use rustc_hir::def::{ }; use rustc_hir::def_id::{CRATE_DEF_ID, CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalDefIdMap}; use rustc_hir::definitions::{PerParentDisambiguatorState, PerParentDisambiguatorsMap}; -use rustc_hir::{PrimTy, TraitCandidate, find_attr}; +use rustc_hir::{PrimTy, TraitCandidate}; use rustc_index::bit_set::DenseBitSet; use rustc_metadata::creader::CStore; use rustc_middle::metadata::{AmbigModChild, ModChild, Reexport}; @@ -1061,6 +1061,7 @@ struct DelayedVisResolutionError<'ra> { vis: ast::Visibility, parent_scope: ParentScope<'ra>, error: VisResolutionError, + owner: NodeId, } #[derive(Clone, Copy, PartialEq, Debug)] @@ -1962,7 +1963,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { delegation_infos: self.delegation_infos, }; let ast_lowering = ty::ResolverAstLowering { - partial_res_map: self.partial_res_map, next_node_id: self.next_node_id, owners: self.owners, lint_buffer: Steal::new(self.lint_buffer), @@ -2361,9 +2361,17 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { fn record_partial_res(&mut self, node_id: NodeId, resolution: PartialRes) { debug!("(recording res) recording {:?} for {}", resolution, node_id); + // We insert into both the global and the owner-local partial res map. + // The global one is needed for many diagnostics, and looking it up in the owner is not always feasible, + // as we regularly look at e.g. the parent's ast and resolve some ids there. + // We want to keep doing that lazily instead of eagerly, as we only need the information in the error path. if let Some(prev_res) = self.partial_res_map.insert(node_id, resolution) { panic!("path resolved multiple times ({prev_res:?} before, {resolution:?} now)"); } + assert_ne!(self.current_owner.id, DUMMY_NODE_ID); + if let Some(prev_res) = self.current_owner.partial_res_map.insert(node_id, resolution) { + panic!("path resolved multiple times ({prev_res:?} before, {resolution:?} now)"); + } } fn record_pat_span(&mut self, node: NodeId, span: Span) { @@ -2552,36 +2560,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } - /// Checks if an expression refers to a function marked with - /// `#[rustc_legacy_const_generics]` and returns the argument index list - /// from the attribute. - fn legacy_const_generic_args(&mut self, expr: &Expr) -> Option> { - let ExprKind::Path(None, path) = &expr.kind else { - return None; - }; - // Don't perform legacy const generics rewriting if the path already - // has generic arguments. - if path.segments.last().unwrap().args.is_some() { - return None; - } - - let def_id = self.partial_res_map.get(&expr.id)?.full_res()?.opt_def_id()?; - - // We only support cross-crate argument rewriting. Uses - // within the same crate should be updated to use the new - // const generics style. - if def_id.is_local() { - return None; - } - - find_attr!( - // we can use parsed attrs here since for other crates they're already available - self.tcx, def_id, - RustcLegacyConstGenerics{fn_indexes,..} => fn_indexes - ) - .map(|fn_indexes| fn_indexes.iter().map(|(num, _)| *num).collect()) - } - fn resolve_main(&mut self) { let any_exe = self.tcx.crate_types().contains(&CrateType::Executable); // Don't try to resolve main unless it's an executable diff --git a/src/tools/clippy/tests/ui/std_instead_of_core_unfixable.rs b/src/tools/clippy/tests/ui/std_instead_of_core_unfixable.rs index 66d834b5e4279..762f3630e655c 100644 --- a/src/tools/clippy/tests/ui/std_instead_of_core_unfixable.rs +++ b/src/tools/clippy/tests/ui/std_instead_of_core_unfixable.rs @@ -1,27 +1,28 @@ #![warn(clippy::std_instead_of_core)] #![warn(clippy::std_instead_of_alloc)] #![allow(unused_imports)] +//@no-rustfix #[rustfmt::skip] fn issue14982() { + // FIXME(oli-obk): make this report again use std::{collections::HashMap, hash::Hash}; - //~^ std_instead_of_core } #[rustfmt::skip] fn issue15143() { + // FIXME(oli-obk): make this report again per violation use std::{error::Error, vec::Vec, fs::File}; //~^ std_instead_of_core - //~| std_instead_of_alloc } #[rustfmt::skip] fn pr16964() { use std::{ - borrow::Cow, //~^ std_instead_of_alloc + // FIXME(oli-obk): make this report again + borrow::Cow, collections::BTreeSet, - //~^ std_instead_of_alloc ffi::OsString, }; } diff --git a/src/tools/clippy/tests/ui/std_instead_of_core_unfixable.stderr b/src/tools/clippy/tests/ui/std_instead_of_core_unfixable.stderr index 6fa8f47a4d6f4..355422053330d 100644 --- a/src/tools/clippy/tests/ui/std_instead_of_core_unfixable.stderr +++ b/src/tools/clippy/tests/ui/std_instead_of_core_unfixable.stderr @@ -1,46 +1,20 @@ error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core_unfixable.rs:7:43 + --> tests/ui/std_instead_of_core_unfixable.rs:15:9 | -LL | use std::{collections::HashMap, hash::Hash}; - | ^^^^ +LL | use std::{error::Error, vec::Vec, fs::File}; + | ^^^ help: consider importing the item from `core`: `core` | - = help: consider importing the item from `core` = note: `-D clippy::std-instead-of-core` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::std_instead_of_core)]` -error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core_unfixable.rs:13:22 - | -LL | use std::{error::Error, vec::Vec, fs::File}; - | ^^^^^ - | - = help: consider importing the item from `core` - error: used import from `std` instead of `alloc` - --> tests/ui/std_instead_of_core_unfixable.rs:13:34 + --> tests/ui/std_instead_of_core_unfixable.rs:21:9 | -LL | use std::{error::Error, vec::Vec, fs::File}; - | ^^^ +LL | use std::{ + | ^^^ help: consider importing the item from `alloc`: `alloc` | - = help: consider importing the item from `alloc` = note: `-D clippy::std-instead-of-alloc` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::std_instead_of_alloc)]` -error: used import from `std` instead of `alloc` - --> tests/ui/std_instead_of_core_unfixable.rs:21:17 - | -LL | borrow::Cow, - | ^^^ - | - = help: consider importing the item from `alloc` - -error: used import from `std` instead of `alloc` - --> tests/ui/std_instead_of_core_unfixable.rs:23:22 - | -LL | collections::BTreeSet, - | ^^^^^^^^ - | - = help: consider importing the item from `alloc` - -error: aborting due to 5 previous errors +error: aborting due to 2 previous errors