mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-15 05:26:47 +00:00
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:
commit
d2b3dd7c17
@ -4397,7 +4397,6 @@ dependencies = [
|
||||
"rustc_feature",
|
||||
"rustc_fluent_macro",
|
||||
"rustc_hir",
|
||||
"rustc_index",
|
||||
"rustc_macros",
|
||||
"rustc_metadata",
|
||||
"rustc_middle",
|
||||
|
@ -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(),
|
||||
|
@ -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>> {
|
||||
|
@ -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.
|
||||
|
@ -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 },
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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))
|
||||
}
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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" }
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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(
|
||||
|
@ -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,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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<'_>) {
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
});
|
||||
|
@ -454,6 +454,7 @@ symbols! {
|
||||
and_then,
|
||||
anon,
|
||||
anon_adt,
|
||||
anon_assoc,
|
||||
anonymous_lifetime_in_impl_trait,
|
||||
any,
|
||||
append_const_msg,
|
||||
|
@ -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)
|
||||
}
|
||||
};
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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",
|
||||
|
@ -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
|
||||
|
|
||||
|
@ -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
|
||||
|
||||
|
@ -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()
|
||||
}
|
||||
|
||||
|
@ -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> {
|
||||
|
@ -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
|
||||
|
7
tests/ui/macros/reparse-expr-issue-139495.rs
Normal file
7
tests/ui/macros/reparse-expr-issue-139495.rs
Normal file
@ -0,0 +1,7 @@
|
||||
macro_rules! m {
|
||||
($abi : expr) => { extern $abi } //~ ERROR expected expression, found keyword `extern`
|
||||
}
|
||||
|
||||
fn main() {
|
||||
m!(-2)
|
||||
}
|
13
tests/ui/macros/reparse-expr-issue-139495.stderr
Normal file
13
tests/ui/macros/reparse-expr-issue-139495.stderr
Normal 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
|
||||
|
@ -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
|
||||
|
||||
|
@ -1126,6 +1126,7 @@ users_on_vacation = [
|
||||
"fmease",
|
||||
"jyn514",
|
||||
"Noratrieb",
|
||||
"spastorino",
|
||||
]
|
||||
|
||||
[[assign.warn_non_default_branch.exceptions]]
|
||||
|
Loading…
Reference in New Issue
Block a user