Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use crate::diagnostics::{
};
use crate::{
AllowReturnTypeNotation, GenericArgsMode, ImplTraitContext, ImplTraitPosition, LoweringContext,
ParamMode, ResolverAstLoweringExt, TryBlockScope,
ParamMode, TryBlockScope,
};

pub(super) struct WillCreateDefIdsVisitor;
Expand Down Expand Up @@ -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);
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
39 changes: 2 additions & 37 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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<Vec<usize>> {
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
Expand Down Expand Up @@ -799,7 +764,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn get_partial_res(&self, id: NodeId) -> Option<PartialRes> {
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(),
}
}

Expand Down
41 changes: 38 additions & 3 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,9 @@ pub struct PerOwnerResolverData<'tcx> {
/// Lifetime parameters that lowering will have to introduce.
pub extra_lifetime_params_map: NodeMap<Vec<(Ident, ast::NodeId, MissingLifetimeKind)>> = Default::default(),

/// Resolutions for nodes that have a single resolution.
pub partial_res_map: NodeMap<hir::def::PartialRes> = 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`.
Expand Down Expand Up @@ -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<Vec<usize>> {
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<hir::def::PartialRes>,

pub next_node_id: ast::NodeId,

pub owners: NodeMap<PerOwnerResolverData<'tcx>>,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_resolve/src/build_reduced_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
14 changes: 8 additions & 6 deletions compiler/rustc_resolve/src/diagnostics/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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),
}
});
}
}

Expand Down
15 changes: 9 additions & 6 deletions compiler/rustc_resolve/src/imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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());
}
});

Expand Down
15 changes: 13 additions & 2 deletions compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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.
Expand Down
46 changes: 12 additions & 34 deletions compiler/rustc_resolve/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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};
Expand Down Expand Up @@ -1061,6 +1061,7 @@ struct DelayedVisResolutionError<'ra> {
vis: ast::Visibility,
parent_scope: ParentScope<'ra>,
error: VisResolutionError,
owner: NodeId,
}

#[derive(Clone, Copy, PartialEq, Debug)]
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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<Vec<usize>> {
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
Expand Down
9 changes: 5 additions & 4 deletions src/tools/clippy/tests/ui/std_instead_of_core_unfixable.rs
Original file line number Diff line number Diff line change
@@ -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,
};
}
Loading
Loading