Auto merge of #139689 - jhpratt:rollup-wlkdyjg, r=jhpratt

Rollup of 7 pull requests

Successful merges:

 - #137835 (Use `BinOp::Cmp` for `iNN::signum`)
 - #139584 (Avoid a reverse map that is only used in diagnostics paths)
 - #139638 (Cleanup the `InstSimplify` MIR transformation)
 - #139653 (Handle a negated literal in `eat_token_lit`.)
 - #139662 (Tweak `DefPathData`)
 - #139664 (Reuse address-space computation from global alloc)
 - #139687 (Add spastorino to users_on_vacation)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2025-04-11 20:06:06 +00:00
commit d2b3dd7c17
36 changed files with 241 additions and 222 deletions

View File

@ -4397,7 +4397,6 @@ dependencies = [
"rustc_feature",
"rustc_fluent_macro",
"rustc_hir",
"rustc_index",
"rustc_macros",
"rustc_metadata",
"rustc_middle",

View File

@ -4,8 +4,8 @@ use std::borrow::Borrow;
use libc::{c_char, c_uint};
use rustc_abi as abi;
use rustc_abi::HasDataLayout;
use rustc_abi::Primitive::Pointer;
use rustc_abi::{AddressSpace, HasDataLayout};
use rustc_ast::Mutability;
use rustc_codegen_ssa::common::TypeKind;
use rustc_codegen_ssa::traits::*;
@ -269,7 +269,8 @@ impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> {
}
Scalar::Ptr(ptr, _size) => {
let (prov, offset) = ptr.into_parts();
let (base_addr, base_addr_space) = match self.tcx.global_alloc(prov.alloc_id()) {
let global_alloc = self.tcx.global_alloc(prov.alloc_id());
let base_addr = match global_alloc {
GlobalAlloc::Memory(alloc) => {
// For ZSTs directly codegen an aligned pointer.
// This avoids generating a zero-sized constant value and actually needing a
@ -301,12 +302,10 @@ impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> {
format!("alloc_{hash:032x}").as_bytes(),
);
}
(value, AddressSpace::DATA)
value
}
}
GlobalAlloc::Function { instance, .. } => {
(self.get_fn_addr(instance), self.data_layout().instruction_address_space)
}
GlobalAlloc::Function { instance, .. } => self.get_fn_addr(instance),
GlobalAlloc::VTable(ty, dyn_ty) => {
let alloc = self
.tcx
@ -319,14 +318,15 @@ impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> {
.unwrap_memory();
let init = const_alloc_to_llvm(self, alloc, /*static*/ false);
let value = self.static_addr_of_impl(init, alloc.inner().align, None);
(value, AddressSpace::DATA)
value
}
GlobalAlloc::Static(def_id) => {
assert!(self.tcx.is_static(def_id));
assert!(!self.tcx.is_thread_local_static(def_id));
(self.get_static(def_id), AddressSpace::DATA)
self.get_static(def_id)
}
};
let base_addr_space = global_alloc.address_space(self);
let llval = unsafe {
llvm::LLVMConstInBoundsGEP2(
self.type_i8(),

View File

@ -109,6 +109,16 @@ impl<T, I: Iterator<Item = T>> UnordItems<T, I> {
pub fn collect<C: From<UnordItems<T, I>>>(self) -> C {
self.into()
}
/// If the iterator has only one element, returns it, otherwise returns `None`.
#[track_caller]
pub fn get_only(mut self) -> Option<T> {
let item = self.0.next();
if self.0.next().is_some() {
return None;
}
item
}
}
impl<T> UnordItems<T, std::iter::Empty<T>> {

View File

@ -267,11 +267,16 @@ impl DefKind {
| DefKind::ForeignTy
| DefKind::TraitAlias
| DefKind::TyParam
| DefKind::ExternCrate => DefPathData::TypeNs(Some(name.unwrap())),
| DefKind::ExternCrate => DefPathData::TypeNs(name.unwrap()),
// An associated type names will be missing for an RPITIT. It will
// later be given a name with `synthetic` in it, if necessary.
DefKind::AssocTy => DefPathData::TypeNs(name),
// An associated type name will be missing for an RPITIT.
DefKind::AssocTy => {
if let Some(name) = name {
DefPathData::TypeNs(name)
} else {
DefPathData::AnonAssocTy
}
}
// It's not exactly an anon const, but wrt DefPathData, there
// is no difference.

View File

@ -271,9 +271,8 @@ pub enum DefPathData {
Use,
/// A global asm item.
GlobalAsm,
/// Something in the type namespace. Will be empty for RPITIT associated
/// types, which are given a synthetic name later, if necessary.
TypeNs(Option<Symbol>),
/// Something in the type namespace.
TypeNs(Symbol),
/// Something in the value namespace.
ValueNs(Symbol),
/// Something in the macro namespace.
@ -291,6 +290,8 @@ pub enum DefPathData {
/// An existential `impl Trait` type node.
/// Argument position `impl Trait` have a `TypeNs` with their pretty-printed name.
OpaqueTy,
/// An anonymous associated type from an RPITIT.
AnonAssocTy,
/// A synthetic body for a coroutine's by-move body.
SyntheticCoroutineBody,
}
@ -413,9 +414,7 @@ impl DefPathData {
pub fn get_opt_name(&self) -> Option<Symbol> {
use self::DefPathData::*;
match *self {
TypeNs(name) => name,
ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name),
TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name),
Impl
| ForeignMod
@ -426,6 +425,7 @@ impl DefPathData {
| Ctor
| AnonConst
| OpaqueTy
| AnonAssocTy
| SyntheticCoroutineBody => None,
}
}
@ -433,14 +433,9 @@ impl DefPathData {
pub fn name(&self) -> DefPathDataName {
use self::DefPathData::*;
match *self {
TypeNs(name) => {
if let Some(name) = name {
DefPathDataName::Named(name)
} else {
DefPathDataName::Anon { namespace: sym::synthetic }
}
TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => {
DefPathDataName::Named(name)
}
ValueNs(name) | MacroNs(name) | LifetimeNs(name) => DefPathDataName::Named(name),
// Note that this does not show up in user print-outs.
CrateRoot => DefPathDataName::Anon { namespace: kw::Crate },
Impl => DefPathDataName::Anon { namespace: kw::Impl },
@ -451,6 +446,7 @@ impl DefPathData {
Ctor => DefPathDataName::Anon { namespace: sym::constructor },
AnonConst => DefPathDataName::Anon { namespace: sym::constant },
OpaqueTy => DefPathDataName::Anon { namespace: sym::opaque },
AnonAssocTy => DefPathDataName::Anon { namespace: sym::anon_assoc },
SyntheticCoroutineBody => DefPathDataName::Anon { namespace: sym::synthetic },
}
}

View File

@ -620,7 +620,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
// the children of the visible parent (as was done when computing
// `visible_parent_map`), looking for the specific child we currently have and then
// have access to the re-exported name.
DefPathData::TypeNs(Some(ref mut name)) if Some(visible_parent) != actual_parent => {
DefPathData::TypeNs(ref mut name) if Some(visible_parent) != actual_parent => {
// Item might be re-exported several times, but filter for the one
// that's public and whose identifier isn't `_`.
let reexport = self
@ -641,7 +641,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
}
// Re-exported `extern crate` (#43189).
DefPathData::CrateRoot => {
data = DefPathData::TypeNs(Some(self.tcx().crate_name(def_id.krate)));
data = DefPathData::TypeNs(self.tcx().crate_name(def_id.krate));
}
_ => {}
}

View File

@ -26,7 +26,7 @@ fn true_significant_drop_ty<'tcx>(
name_rev.push(tcx.crate_name(did.krate));
}
rustc_hir::definitions::DefPathData::TypeNs(symbol) => {
name_rev.push(symbol.unwrap());
name_rev.push(symbol);
}
_ => return None,
}

View File

@ -39,26 +39,26 @@ impl<'tcx> crate::MirPass<'tcx> for InstSimplify {
attr::contains_name(tcx.hir_krate_attrs(), sym::rustc_preserve_ub_checks);
for block in body.basic_blocks.as_mut() {
for statement in block.statements.iter_mut() {
match statement.kind {
StatementKind::Assign(box (_place, ref mut rvalue)) => {
if !preserve_ub_checks {
ctx.simplify_ub_check(rvalue);
}
ctx.simplify_bool_cmp(rvalue);
ctx.simplify_ref_deref(rvalue);
ctx.simplify_ptr_aggregate(rvalue);
ctx.simplify_cast(rvalue);
ctx.simplify_repeated_aggregate(rvalue);
ctx.simplify_repeat_once(rvalue);
}
_ => {}
let StatementKind::Assign(box (.., rvalue)) = &mut statement.kind else {
continue;
};
if !preserve_ub_checks {
ctx.simplify_ub_check(rvalue);
}
ctx.simplify_bool_cmp(rvalue);
ctx.simplify_ref_deref(rvalue);
ctx.simplify_ptr_aggregate(rvalue);
ctx.simplify_cast(rvalue);
ctx.simplify_repeated_aggregate(rvalue);
ctx.simplify_repeat_once(rvalue);
}
ctx.simplify_primitive_clone(block.terminator.as_mut().unwrap(), &mut block.statements);
ctx.simplify_intrinsic_assert(block.terminator.as_mut().unwrap());
ctx.simplify_nounwind_call(block.terminator.as_mut().unwrap());
simplify_duplicate_switch_targets(block.terminator.as_mut().unwrap());
let terminator = block.terminator.as_mut().unwrap();
ctx.simplify_primitive_clone(terminator, &mut block.statements);
ctx.simplify_intrinsic_assert(terminator);
ctx.simplify_nounwind_call(terminator);
simplify_duplicate_switch_targets(terminator);
}
}
@ -105,43 +105,34 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> {
/// Transform boolean comparisons into logical operations.
fn simplify_bool_cmp(&self, rvalue: &mut Rvalue<'tcx>) {
match rvalue {
Rvalue::BinaryOp(op @ (BinOp::Eq | BinOp::Ne), box (a, b)) => {
let new = match (op, self.try_eval_bool(a), self.try_eval_bool(b)) {
// Transform "Eq(a, true)" ==> "a"
(BinOp::Eq, _, Some(true)) => Some(Rvalue::Use(a.clone())),
let Rvalue::BinaryOp(op @ (BinOp::Eq | BinOp::Ne), box (a, b)) = &*rvalue else { return };
*rvalue = match (op, self.try_eval_bool(a), self.try_eval_bool(b)) {
// Transform "Eq(a, true)" ==> "a"
(BinOp::Eq, _, Some(true)) => Rvalue::Use(a.clone()),
// Transform "Ne(a, false)" ==> "a"
(BinOp::Ne, _, Some(false)) => Some(Rvalue::Use(a.clone())),
// Transform "Ne(a, false)" ==> "a"
(BinOp::Ne, _, Some(false)) => Rvalue::Use(a.clone()),
// Transform "Eq(true, b)" ==> "b"
(BinOp::Eq, Some(true), _) => Some(Rvalue::Use(b.clone())),
// Transform "Eq(true, b)" ==> "b"
(BinOp::Eq, Some(true), _) => Rvalue::Use(b.clone()),
// Transform "Ne(false, b)" ==> "b"
(BinOp::Ne, Some(false), _) => Some(Rvalue::Use(b.clone())),
// Transform "Ne(false, b)" ==> "b"
(BinOp::Ne, Some(false), _) => Rvalue::Use(b.clone()),
// Transform "Eq(false, b)" ==> "Not(b)"
(BinOp::Eq, Some(false), _) => Some(Rvalue::UnaryOp(UnOp::Not, b.clone())),
// Transform "Eq(false, b)" ==> "Not(b)"
(BinOp::Eq, Some(false), _) => Rvalue::UnaryOp(UnOp::Not, b.clone()),
// Transform "Ne(true, b)" ==> "Not(b)"
(BinOp::Ne, Some(true), _) => Some(Rvalue::UnaryOp(UnOp::Not, b.clone())),
// Transform "Ne(true, b)" ==> "Not(b)"
(BinOp::Ne, Some(true), _) => Rvalue::UnaryOp(UnOp::Not, b.clone()),
// Transform "Eq(a, false)" ==> "Not(a)"
(BinOp::Eq, _, Some(false)) => Some(Rvalue::UnaryOp(UnOp::Not, a.clone())),
// Transform "Eq(a, false)" ==> "Not(a)"
(BinOp::Eq, _, Some(false)) => Rvalue::UnaryOp(UnOp::Not, a.clone()),
// Transform "Ne(a, true)" ==> "Not(a)"
(BinOp::Ne, _, Some(true)) => Some(Rvalue::UnaryOp(UnOp::Not, a.clone())),
// Transform "Ne(a, true)" ==> "Not(a)"
(BinOp::Ne, _, Some(true)) => Rvalue::UnaryOp(UnOp::Not, a.clone()),
_ => None,
};
if let Some(new) = new {
*rvalue = new;
}
}
_ => {}
}
_ => return,
};
}
fn try_eval_bool(&self, a: &Operand<'_>) -> Option<bool> {
@ -151,64 +142,58 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> {
/// Transform `&(*a)` ==> `a`.
fn simplify_ref_deref(&self, rvalue: &mut Rvalue<'tcx>) {
if let Rvalue::Ref(_, _, place) | Rvalue::RawPtr(_, place) = rvalue {
if let Some((base, ProjectionElem::Deref)) = place.as_ref().last_projection() {
if rvalue.ty(self.local_decls, self.tcx) != base.ty(self.local_decls, self.tcx).ty {
return;
}
*rvalue = Rvalue::Use(Operand::Copy(Place {
local: base.local,
projection: self.tcx.mk_place_elems(base.projection),
}));
}
if let Rvalue::Ref(_, _, place) | Rvalue::RawPtr(_, place) = rvalue
&& let Some((base, ProjectionElem::Deref)) = place.as_ref().last_projection()
&& rvalue.ty(self.local_decls, self.tcx) == base.ty(self.local_decls, self.tcx).ty
{
*rvalue = Rvalue::Use(Operand::Copy(Place {
local: base.local,
projection: self.tcx.mk_place_elems(base.projection),
}));
}
}
/// Transform `Aggregate(RawPtr, [p, ()])` ==> `Cast(PtrToPtr, p)`.
fn simplify_ptr_aggregate(&self, rvalue: &mut Rvalue<'tcx>) {
if let Rvalue::Aggregate(box AggregateKind::RawPtr(pointee_ty, mutability), fields) = rvalue
&& let meta_ty = fields.raw[1].ty(self.local_decls, self.tcx)
&& meta_ty.is_unit()
{
let meta_ty = fields.raw[1].ty(self.local_decls, self.tcx);
if meta_ty.is_unit() {
// The mutable borrows we're holding prevent printing `rvalue` here
let mut fields = std::mem::take(fields);
let _meta = fields.pop().unwrap();
let data = fields.pop().unwrap();
let ptr_ty = Ty::new_ptr(self.tcx, *pointee_ty, *mutability);
*rvalue = Rvalue::Cast(CastKind::PtrToPtr, data, ptr_ty);
}
// The mutable borrows we're holding prevent printing `rvalue` here
let mut fields = std::mem::take(fields);
let _meta = fields.pop().unwrap();
let data = fields.pop().unwrap();
let ptr_ty = Ty::new_ptr(self.tcx, *pointee_ty, *mutability);
*rvalue = Rvalue::Cast(CastKind::PtrToPtr, data, ptr_ty);
}
}
fn simplify_ub_check(&self, rvalue: &mut Rvalue<'tcx>) {
if let Rvalue::NullaryOp(NullOp::UbChecks, _) = *rvalue {
let const_ = Const::from_bool(self.tcx, self.tcx.sess.ub_checks());
let constant = ConstOperand { span: DUMMY_SP, const_, user_ty: None };
*rvalue = Rvalue::Use(Operand::Constant(Box::new(constant)));
}
let Rvalue::NullaryOp(NullOp::UbChecks, _) = *rvalue else { return };
let const_ = Const::from_bool(self.tcx, self.tcx.sess.ub_checks());
let constant = ConstOperand { span: DUMMY_SP, const_, user_ty: None };
*rvalue = Rvalue::Use(Operand::Constant(Box::new(constant)));
}
fn simplify_cast(&self, rvalue: &mut Rvalue<'tcx>) {
if let Rvalue::Cast(kind, operand, cast_ty) = rvalue {
let operand_ty = operand.ty(self.local_decls, self.tcx);
if operand_ty == *cast_ty {
*rvalue = Rvalue::Use(operand.clone());
} else if *kind == CastKind::Transmute {
// Transmuting an integer to another integer is just a signedness cast
if let (ty::Int(int), ty::Uint(uint)) | (ty::Uint(uint), ty::Int(int)) =
(operand_ty.kind(), cast_ty.kind())
&& int.bit_width() == uint.bit_width()
{
// The width check isn't strictly necessary, as different widths
// are UB and thus we'd be allowed to turn it into a cast anyway.
// But let's keep the UB around for codegen to exploit later.
// (If `CastKind::Transmute` ever becomes *not* UB for mismatched sizes,
// then the width check is necessary for big-endian correctness.)
*kind = CastKind::IntToInt;
return;
}
}
let Rvalue::Cast(kind, operand, cast_ty) = rvalue else { return };
let operand_ty = operand.ty(self.local_decls, self.tcx);
if operand_ty == *cast_ty {
*rvalue = Rvalue::Use(operand.clone());
} else if *kind == CastKind::Transmute
// Transmuting an integer to another integer is just a signedness cast
&& let (ty::Int(int), ty::Uint(uint)) | (ty::Uint(uint), ty::Int(int)) =
(operand_ty.kind(), cast_ty.kind())
&& int.bit_width() == uint.bit_width()
{
// The width check isn't strictly necessary, as different widths
// are UB and thus we'd be allowed to turn it into a cast anyway.
// But let's keep the UB around for codegen to exploit later.
// (If `CastKind::Transmute` ever becomes *not* UB for mismatched sizes,
// then the width check is necessary for big-endian correctness.)
*kind = CastKind::IntToInt;
}
}
@ -277,7 +262,7 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> {
}
fn simplify_nounwind_call(&self, terminator: &mut Terminator<'tcx>) {
let TerminatorKind::Call { func, unwind, .. } = &mut terminator.kind else {
let TerminatorKind::Call { ref func, ref mut unwind, .. } = terminator.kind else {
return;
};
@ -290,7 +275,7 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> {
ty::FnDef(..) => body_ty.fn_sig(self.tcx).abi(),
ty::Closure(..) => ExternAbi::RustCall,
ty::Coroutine(..) => ExternAbi::Rust,
_ => bug!("unexpected body ty: {:?}", body_ty),
_ => bug!("unexpected body ty: {body_ty:?}"),
};
if !layout::fn_can_unwind(self.tcx, Some(def_id), body_abi) {
@ -299,10 +284,9 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> {
}
fn simplify_intrinsic_assert(&self, terminator: &mut Terminator<'tcx>) {
let TerminatorKind::Call { func, target, .. } = &mut terminator.kind else {
return;
};
let Some(target_block) = target else {
let TerminatorKind::Call { ref func, target: ref mut target @ Some(target_block), .. } =
terminator.kind
else {
return;
};
let func_ty = func.ty(self.local_decls, self.tcx);
@ -310,12 +294,10 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> {
return;
};
// The intrinsics we are interested in have one generic parameter
if args.is_empty() {
return;
}
let [arg, ..] = args[..] else { return };
let known_is_valid =
intrinsic_assert_panics(self.tcx, self.typing_env, args[0], intrinsic_name);
intrinsic_assert_panics(self.tcx, self.typing_env, arg, intrinsic_name);
match known_is_valid {
// We don't know the layout or it's not validity assertion at all, don't touch it
None => {}
@ -325,7 +307,7 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> {
}
Some(false) => {
// If we know the assert does not panic, turn the call into a Goto
terminator.kind = TerminatorKind::Goto { target: *target_block };
terminator.kind = TerminatorKind::Goto { target: target_block };
}
}
}
@ -346,9 +328,7 @@ fn resolve_rust_intrinsic<'tcx>(
tcx: TyCtxt<'tcx>,
func_ty: Ty<'tcx>,
) -> Option<(Symbol, GenericArgsRef<'tcx>)> {
if let ty::FnDef(def_id, args) = *func_ty.kind() {
let intrinsic = tcx.intrinsic(def_id)?;
return Some((intrinsic.name, args));
}
None
let ty::FnDef(def_id, args) = *func_ty.kind() else { return None };
let intrinsic = tcx.intrinsic(def_id)?;
Some((intrinsic.name, args))
}

View File

@ -2166,10 +2166,15 @@ impl<'a> Parser<'a> {
let expr = self
.eat_metavar_seq(mv_kind, |this| this.parse_expr())
.expect("metavar seq expr");
let ast::ExprKind::Lit(token_lit) = expr.kind else {
panic!("didn't reparse an expr");
};
Some(token_lit)
if let ast::ExprKind::Lit(token_lit) = expr.kind {
Some(token_lit)
} else if let ast::ExprKind::Unary(UnOp::Neg, inner) = &expr.kind
&& let ast::Expr { kind: ast::ExprKind::Lit(_), .. } = **inner
{
None
} else {
panic!("unexpected reparsed expr: {:?}", expr.kind);
}
}
_ => None,
}

View File

@ -18,7 +18,6 @@ rustc_expand = { path = "../rustc_expand" }
rustc_feature = { path = "../rustc_feature" }
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_hir = { path = "../rustc_hir" }
rustc_index = { path = "../rustc_index" }
rustc_macros = { path = "../rustc_macros" }
rustc_metadata = { path = "../rustc_metadata" }
rustc_middle = { path = "../rustc_middle" }

View File

@ -1207,7 +1207,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
for (rule_i, rule_span) in &self.r.macro_map[&def_id.to_def_id()].rule_spans {
self.r
.unused_macro_rules
.entry(def_id)
.entry(node_id)
.or_default()
.insert(*rule_i, (ident, *rule_span));
}

View File

@ -170,10 +170,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
fn report_with_use_injections(&mut self, krate: &Crate) {
for UseError { mut err, candidates, def_id, instead, suggestion, path, is_call } in
self.use_injections.drain(..)
std::mem::take(&mut self.use_injections)
{
let (span, found_use) = if let Some(def_id) = def_id.as_local() {
UsePlacementFinder::check(krate, self.def_id_to_node_id[def_id])
UsePlacementFinder::check(krate, self.def_id_to_node_id(def_id))
} else {
(None, FoundUse::No)
};
@ -1435,7 +1435,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
let import_suggestions =
self.lookup_import_candidates(ident, Namespace::MacroNS, parent_scope, is_expected);
let (span, found_use) = match parent_scope.module.nearest_parent_mod().as_local() {
Some(def_id) => UsePlacementFinder::check(krate, self.def_id_to_node_id[def_id]),
Some(def_id) => UsePlacementFinder::check(krate, self.def_id_to_node_id(def_id)),
None => (None, FoundUse::No),
};
show_candidates(

View File

@ -639,38 +639,38 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
}
if let Some(glob_binding) = resolution.shadowed_glob {
let binding_id = match binding.kind {
NameBindingKind::Res(res) => {
Some(self.def_id_to_node_id[res.def_id().expect_local()])
}
NameBindingKind::Module(module) => {
Some(self.def_id_to_node_id[module.def_id().expect_local()])
}
NameBindingKind::Import { import, .. } => import.id(),
};
if binding.res() != Res::Err
&& glob_binding.res() != Res::Err
&& let NameBindingKind::Import { import: glob_import, .. } =
glob_binding.kind
&& let Some(binding_id) = binding_id
&& let Some(glob_import_id) = glob_import.id()
&& let glob_import_def_id = self.local_def_id(glob_import_id)
&& self.effective_visibilities.is_exported(glob_import_def_id)
&& glob_binding.vis.is_public()
&& !binding.vis.is_public()
{
self.lint_buffer.buffer_lint(
HIDDEN_GLOB_REEXPORTS,
binding_id,
binding.span,
BuiltinLintDiag::HiddenGlobReexports {
name: key.ident.name.to_string(),
namespace: key.ns.descr().to_owned(),
glob_reexport_span: glob_binding.span,
private_item_span: binding.span,
},
);
let binding_id = match binding.kind {
NameBindingKind::Res(res) => {
Some(self.def_id_to_node_id(res.def_id().expect_local()))
}
NameBindingKind::Module(module) => {
Some(self.def_id_to_node_id(module.def_id().expect_local()))
}
NameBindingKind::Import { import, .. } => import.id(),
};
if let Some(binding_id) = binding_id {
self.lint_buffer.buffer_lint(
HIDDEN_GLOB_REEXPORTS,
binding_id,
binding.span,
BuiltinLintDiag::HiddenGlobReexports {
name: key.ident.name.to_string(),
namespace: key.ns.descr().to_owned(),
glob_reexport_span: glob_binding.span,
private_item_span: binding.span,
},
);
}
}
}
}

View File

@ -5007,8 +5007,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
return false;
}
let Some(local_did) = did.as_local() else { return true };
let Some(node_id) = self.r.def_id_to_node_id.get(local_did) else { return true };
!self.r.proc_macros.contains(node_id)
!self.r.proc_macros.contains(&local_did)
}
fn resolve_doc_links(&mut self, attrs: &[Attribute], maybe_exported: MaybeExported<'_>) {

View File

@ -56,7 +56,6 @@ use rustc_hir::def::{
};
use rustc_hir::def_id::{CRATE_DEF_ID, CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalDefIdMap};
use rustc_hir::{PrimTy, TraitCandidate};
use rustc_index::IndexVec;
use rustc_metadata::creader::{CStore, CrateLoader};
use rustc_middle::metadata::ModChild;
use rustc_middle::middle::privacy::EffectiveVisibilities;
@ -1141,7 +1140,7 @@ pub struct Resolver<'ra, 'tcx> {
ast_transform_scopes: FxHashMap<LocalExpnId, Module<'ra>>,
unused_macros: FxIndexMap<LocalDefId, (NodeId, Ident)>,
/// A map from the macro to all its potentially unused arms.
unused_macro_rules: FxIndexMap<LocalDefId, UnordMap<usize, (Ident, Span)>>,
unused_macro_rules: FxIndexMap<NodeId, UnordMap<usize, (Ident, Span)>>,
proc_macro_stubs: FxHashSet<LocalDefId>,
/// Traces collected during macro resolution and validated when it's complete.
single_segment_macro_resolutions:
@ -1184,7 +1183,6 @@ pub struct Resolver<'ra, 'tcx> {
next_node_id: NodeId,
node_id_to_def_id: NodeMap<Feed<'tcx, LocalDefId>>,
def_id_to_node_id: IndexVec<LocalDefId, ast::NodeId>,
/// Indices of unnamed struct or variant fields with unresolved attributes.
placeholder_field_indices: FxHashMap<NodeId, usize>,
@ -1202,7 +1200,7 @@ pub struct Resolver<'ra, 'tcx> {
trait_impls: FxIndexMap<DefId, Vec<LocalDefId>>,
/// A list of proc macro LocalDefIds, written out in the order in which
/// they are declared in the static array generated by proc_macro_harness.
proc_macros: Vec<NodeId>,
proc_macros: Vec<LocalDefId>,
confused_type_with_std_module: FxIndexMap<Span, Span>,
/// Whether lifetime elision was successful.
lifetime_elision_allowed: FxHashSet<NodeId>,
@ -1339,12 +1337,12 @@ impl<'tcx> Resolver<'_, 'tcx> {
expn_id: ExpnId,
span: Span,
) -> TyCtxtFeed<'tcx, LocalDefId> {
let data = def_kind.def_path_data(name);
assert!(
!self.node_id_to_def_id.contains_key(&node_id),
"adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}",
"adding a def for node-id {:?}, name {:?}, data {:?} but a previous def exists: {:?}",
node_id,
data,
name,
def_kind,
self.tcx.definitions_untracked().def_key(self.node_id_to_def_id[&node_id].key()),
);
@ -1369,7 +1367,6 @@ impl<'tcx> Resolver<'_, 'tcx> {
debug!("create_def: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id);
self.node_id_to_def_id.insert(node_id, feed.downgrade());
}
assert_eq!(self.def_id_to_node_id.push(node_id), def_id);
feed
}
@ -1385,6 +1382,19 @@ impl<'tcx> Resolver<'_, 'tcx> {
pub fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
/// This function is very slow, as it iterates over the entire
/// [Resolver::node_id_to_def_id] map just to find the [NodeId]
/// that corresponds to the given [LocalDefId]. Only use this in
/// diagnostics code paths.
fn def_id_to_node_id(&self, def_id: LocalDefId) -> NodeId {
self.node_id_to_def_id
.items()
.filter(|(_, v)| v.key() == def_id)
.map(|(k, _)| *k)
.get_only()
.unwrap()
}
}
impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
@ -1417,8 +1427,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
&mut Default::default(),
);
let mut def_id_to_node_id = IndexVec::default();
assert_eq!(def_id_to_node_id.push(CRATE_NODE_ID), CRATE_DEF_ID);
let mut node_id_to_def_id = NodeMap::default();
let crate_feed = tcx.create_local_crate_def_id(crate_span);
@ -1553,7 +1561,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
lint_buffer: LintBuffer::default(),
next_node_id: CRATE_NODE_ID,
node_id_to_def_id,
def_id_to_node_id,
placeholder_field_indices: Default::default(),
invocation_parents,
legacy_const_generic_args: Default::default(),
@ -1633,7 +1640,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
}
pub fn into_outputs(self) -> ResolverOutputs {
let proc_macros = self.proc_macros.iter().map(|id| self.local_def_id(*id)).collect();
let proc_macros = self.proc_macros;
let expn_that_defined = self.expn_that_defined;
let extern_crate_map = self.extern_crate_map;
let maybe_unused_trait_imports = self.maybe_unused_trait_imports;

View File

@ -323,8 +323,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> {
}
fn record_macro_rule_usage(&mut self, id: NodeId, rule_i: usize) {
let did = self.local_def_id(id);
if let Some(rules) = self.unused_macro_rules.get_mut(&did) {
if let Some(rules) = self.unused_macro_rules.get_mut(&id) {
rules.remove(&rule_i);
}
}
@ -337,15 +336,12 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> {
ident.span,
BuiltinLintDiag::UnusedMacroDefinition(ident.name),
);
// Do not report unused individual rules if the entire macro is unused
self.unused_macro_rules.swap_remove(&node_id);
}
for (&def_id, unused_arms) in self.unused_macro_rules.iter() {
for (&node_id, unused_arms) in self.unused_macro_rules.iter() {
for (&arm_i, &(ident, rule_span)) in unused_arms.to_sorted_stable_ord() {
if self.unused_macros.contains_key(&def_id) {
// We already lint the entire macro as unused
continue;
}
let node_id = self.def_id_to_node_id[def_id];
self.lint_buffer.buffer_lint(
UNUSED_MACRO_RULES,
node_id,
@ -466,7 +462,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> {
}
fn declare_proc_macro(&mut self, id: NodeId) {
self.proc_macros.push(id)
self.proc_macros.push(self.local_def_id(id))
}
fn append_stripped_cfg_item(&mut self, parent_node: NodeId, ident: Ident, cfg: ast::MetaItem) {
@ -932,7 +928,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
.invocation_parents
.get(&parent_scope.expansion)
.map_or(ast::CRATE_NODE_ID, |parent| {
self.def_id_to_node_id[parent.parent_def]
self.def_id_to_node_id(parent.parent_def)
});
self.lint_buffer.buffer_lint(
LEGACY_DERIVE_HELPERS,

View File

@ -721,7 +721,8 @@ fn encode_ty_name(tcx: TyCtxt<'_>, def_id: DefId) -> String {
| hir::definitions::DefPathData::Use
| hir::definitions::DefPathData::GlobalAsm
| hir::definitions::DefPathData::MacroNs(..)
| hir::definitions::DefPathData::LifetimeNs(..) => {
| hir::definitions::DefPathData::LifetimeNs(..)
| hir::definitions::DefPathData::AnonAssocTy => {
bug!("encode_ty_name: unexpected `{:?}`", disambiguated_data.data);
}
});

View File

@ -454,6 +454,7 @@ symbols! {
and_then,
anon,
anon_adt,
anon_assoc,
anonymous_lifetime_in_impl_trait,
any,
append_const_msg,

View File

@ -858,7 +858,8 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
| DefPathData::GlobalAsm
| DefPathData::Impl
| DefPathData::MacroNs(_)
| DefPathData::LifetimeNs(_) => {
| DefPathData::LifetimeNs(_)
| DefPathData::AnonAssocTy => {
bug!("symbol_names: unexpected DefPathData: {:?}", disambiguated_data.data)
}
};

View File

@ -252,7 +252,7 @@ fn associated_type_for_impl_trait_in_trait(
assert_eq!(tcx.def_kind(trait_def_id), DefKind::Trait);
let span = tcx.def_span(opaque_ty_def_id);
// No name because this is a synthetic associated type.
// No name because this is an anonymous associated type.
let trait_assoc_ty = tcx.at(span).create_def(trait_def_id, None, DefKind::AssocTy);
let local_def_id = trait_assoc_ty.def_id();
@ -305,7 +305,7 @@ fn associated_type_for_impl_trait_in_impl(
hir::FnRetTy::DefaultReturn(_) => tcx.def_span(impl_fn_def_id),
hir::FnRetTy::Return(ty) => ty.span,
};
// No name because this is a synthetic associated type.
// No name because this is an anonymous associated type.
let impl_assoc_ty = tcx.at(span).create_def(impl_local_def_id, None, DefKind::AssocTy);
let local_def_id = impl_assoc_ty.def_id();

View File

@ -2628,13 +2628,15 @@ pub const fn bswap<T: Copy>(x: T) -> T;
#[rustc_intrinsic]
pub const fn bitreverse<T: Copy>(x: T) -> T;
/// Does a three-way comparison between the two integer arguments.
/// Does a three-way comparison between the two arguments,
/// which must be of character or integer (signed or unsigned) type.
///
/// This is included as an intrinsic as it's useful to let it be one thing
/// in MIR, rather than the multiple checks and switches that make its IR
/// large and difficult to optimize.
/// This was originally added because it greatly simplified the MIR in `cmp`
/// implementations, and then LLVM 20 added a backend intrinsic for it too.
///
/// The stabilized version of this intrinsic is [`Ord::cmp`].
#[rustc_intrinsic_const_stable_indirect]
#[rustc_nounwind]
#[rustc_intrinsic]
pub const fn three_way_compare<T: Copy>(lhs: T, rhss: T) -> crate::cmp::Ordering;

View File

@ -3571,10 +3571,7 @@ macro_rules! int_impl {
// so delegate it to `Ord` which is already producing -1/0/+1
// exactly like we need and can be the place to deal with the complexity.
// FIXME(const-hack): replace with cmp
if self < 0 { -1 }
else if self == 0 { 0 }
else { 1 }
crate::intrinsics::three_way_compare(self, 0) as Self
}
/// Returns `true` if `self` is positive and `false` if the number is zero or

View File

@ -3504,7 +3504,7 @@ fn maybe_get_relative_path(from: &DefPath, to: &DefPath, max_super: usize) -> St
// a::b::c ::d::sym refers to
// e::f::sym:: ::
// result should be super::super::super::super::e::f
if let DefPathData::TypeNs(Some(s)) = l {
if let DefPathData::TypeNs(s) = l {
path.push(s.to_string());
}
if let DefPathData::TypeNs(_) = r {
@ -3515,7 +3515,7 @@ fn maybe_get_relative_path(from: &DefPath, to: &DefPath, max_super: usize) -> St
// a::b::sym:: :: refers to
// c::d::e ::f::sym
// when looking at `f`
Left(DefPathData::TypeNs(Some(sym))) => path.push(sym.to_string()),
Left(DefPathData::TypeNs(sym)) => path.push(sym.to_string()),
// consider:
// a::b::c ::d::sym refers to
// e::f::sym:: ::
@ -3529,7 +3529,7 @@ fn maybe_get_relative_path(from: &DefPath, to: &DefPath, max_super: usize) -> St
// `super` chain would be too long, just use the absolute path instead
once(String::from("crate"))
.chain(to.data.iter().filter_map(|el| {
if let DefPathData::TypeNs(Some(sym)) = el.data {
if let DefPathData::TypeNs(sym) = el.data {
Some(sym.to_string())
} else {
None

View File

@ -18,7 +18,7 @@
_4 = copy _1;
StorageLive(_5);
_5 = copy _2;
- _3 = three_way_compare::<char>(move _4, move _5) -> [return: bb1, unwind continue];
- _3 = three_way_compare::<char>(move _4, move _5) -> [return: bb1, unwind unreachable];
+ _3 = Cmp(move _4, move _5);
+ goto -> bb1;
}

View File

@ -15,7 +15,7 @@
_4 = copy _1;
StorageLive(_5);
_5 = copy _2;
- _3 = three_way_compare::<i16>(move _4, move _5) -> [return: bb1, unwind continue];
- _3 = three_way_compare::<i16>(move _4, move _5) -> [return: bb1, unwind unreachable];
+ _3 = Cmp(move _4, move _5);
+ goto -> bb1;
}

View File

@ -18,7 +18,7 @@
_4 = copy _1;
StorageLive(_5);
_5 = copy _2;
- _3 = three_way_compare::<u32>(move _4, move _5) -> [return: bb1, unwind continue];
- _3 = three_way_compare::<u32>(move _4, move _5) -> [return: bb1, unwind unreachable];
+ _3 = Cmp(move _4, move _5);
+ goto -> bb1;
}

View File

@ -51,7 +51,7 @@ fn test_assoc_items() -> ControlFlow<()> {
check_items(
&trait_assoc_item_defs,
&[
"ATrait::{synthetic#0}",
"ATrait::{anon_assoc#0}",
"ATrait::rpitit",
"ATrait::Assoc",
"ATrait::assoc_fn_no_self",
@ -64,7 +64,7 @@ fn test_assoc_items() -> ControlFlow<()> {
check_items(
&impl_assoc_item_defs,
&[
"<AStruct as ATrait>::{synthetic#0}",
"<AStruct as ATrait>::{anon_assoc#0}",
"<AStruct as ATrait>::rpitit",
"<AStruct as ATrait>::Assoc",
"<AStruct as ATrait>::assoc_fn_no_self",

View File

@ -1,4 +1,4 @@
error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/unsupported.rs:21:5: 21:24>::{synthetic#0}`
error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/unsupported.rs:21:5: 21:24>::{anon_assoc#0}`
--> $DIR/unsupported.rs:22:25
|
LL | reuse to_reuse::opaque_ret;
@ -9,7 +9,7 @@ note: ...which requires comparing an impl and trait method signature, inferring
|
LL | reuse to_reuse::opaque_ret;
| ^^^^^^^^^^
= note: ...which again requires computing type of `opaque::<impl at $DIR/unsupported.rs:21:5: 21:24>::{synthetic#0}`, completing the cycle
= note: ...which again requires computing type of `opaque::<impl at $DIR/unsupported.rs:21:5: 21:24>::{anon_assoc#0}`, completing the cycle
note: cycle used when checking that `opaque::<impl at $DIR/unsupported.rs:21:5: 21:24>` is well-formed
--> $DIR/unsupported.rs:21:5
|
@ -17,7 +17,7 @@ LL | impl ToReuse for u8 {
| ^^^^^^^^^^^^^^^^^^^
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/unsupported.rs:24:5: 24:25>::{synthetic#0}`
error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/unsupported.rs:24:5: 24:25>::{anon_assoc#0}`
--> $DIR/unsupported.rs:25:24
|
LL | reuse ToReuse::opaque_ret;
@ -28,7 +28,7 @@ note: ...which requires comparing an impl and trait method signature, inferring
|
LL | reuse ToReuse::opaque_ret;
| ^^^^^^^^^^
= note: ...which again requires computing type of `opaque::<impl at $DIR/unsupported.rs:24:5: 24:25>::{synthetic#0}`, completing the cycle
= note: ...which again requires computing type of `opaque::<impl at $DIR/unsupported.rs:24:5: 24:25>::{anon_assoc#0}`, completing the cycle
note: cycle used when checking that `opaque::<impl at $DIR/unsupported.rs:24:5: 24:25>` is well-formed
--> $DIR/unsupported.rs:24:5
|

View File

@ -6,11 +6,11 @@ LL | fn bar() -> () {}
|
= help: the trait `std::fmt::Display` is not implemented for `()`
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
note: required by a bound in `Foo::{synthetic#0}`
note: required by a bound in `Foo::{anon_assoc#0}`
--> $DIR/doesnt-satisfy.rs:2:22
|
LL | fn bar() -> impl std::fmt::Display;
| ^^^^^^^^^^^^^^^^^ required by this bound in `Foo::{synthetic#0}`
| ^^^^^^^^^^^^^^^^^ required by this bound in `Foo::{anon_assoc#0}`
error: aborting due to 1 previous error

View File

@ -8,7 +8,7 @@ trait Foo {
}
fn hello<'s, T: Foo>(x: &'s T) -> impl Sized + use<'s, T> {
//~^ ERROR <T as Foo>::{synthetic#0}<'s/#1>
//~^ ERROR <T as Foo>::{anon_assoc#0}<'s/#1>
x.hello()
}

View File

@ -1,4 +1,4 @@
error: <T as Foo>::{synthetic#0}<'s/#1>
error: <T as Foo>::{anon_assoc#0}<'s/#1>
--> $DIR/dump.rs:10:35
|
LL | fn hello<'s, T: Foo>(x: &'s T) -> impl Sized + use<'s, T> {

View File

@ -14,11 +14,11 @@ LL | fn foo<F2: Foo<u8>>(self) -> impl Foo<u8> {
| ^^^^^^^^^^^^ the trait `Foo<char>` is not implemented for `impl Foo<u8>`
|
= help: the trait `Foo<char>` is implemented for `Bar`
note: required by a bound in `Foo::{synthetic#0}`
note: required by a bound in `Foo::{anon_assoc#0}`
--> $DIR/return-dont-satisfy-bounds.rs:2:30
|
LL | fn foo<F2>(self) -> impl Foo<T>;
| ^^^^^^ required by this bound in `Foo::{synthetic#0}`
| ^^^^^^ required by this bound in `Foo::{anon_assoc#0}`
error[E0277]: the trait bound `Bar: Foo<u8>` is not satisfied
--> $DIR/return-dont-satisfy-bounds.rs:8:34

View File

@ -0,0 +1,7 @@
macro_rules! m {
($abi : expr) => { extern $abi } //~ ERROR expected expression, found keyword `extern`
}
fn main() {
m!(-2)
}

View File

@ -0,0 +1,13 @@
error: expected expression, found keyword `extern`
--> $DIR/reparse-expr-issue-139495.rs:2:22
|
LL | ($abi : expr) => { extern $abi }
| ^^^^^^ expected expression
...
LL | m!(-2)
| ------ in this macro invocation
|
= note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 1 previous error

View File

@ -4,11 +4,11 @@ error[E0277]: the trait bound `Something: Termination` is not satisfied
LL | fn main() -> Something {
| ^^^^^^^^^ the trait `Termination` is not implemented for `Something`
|
note: required by a bound in `Main::{synthetic#0}`
note: required by a bound in `Main::{anon_assoc#0}`
--> $DIR/issue-103052-2.rs:3:27
|
LL | fn main() -> impl std::process::Termination;
| ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Main::{synthetic#0}`
| ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Main::{anon_assoc#0}`
error: aborting due to 1 previous error

View File

@ -1126,6 +1126,7 @@ users_on_vacation = [
"fmease",
"jyn514",
"Noratrieb",
"spastorino",
]
[[assign.warn_non_default_branch.exceptions]]