diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 21ca92d46d1c6..253dff6f8e75c 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1000,20 +1000,6 @@ pub enum AlignFromBytesError { TooLarge(u64), } -impl AlignFromBytesError { - pub fn diag_ident(self) -> &'static str { - match self { - Self::NotPowerOfTwo(_) => "not_power_of_two", - Self::TooLarge(_) => "too_large", - } - } - - pub fn align(self) -> u64 { - let (Self::NotPowerOfTwo(align) | Self::TooLarge(align)) = self; - align - } -} - impl fmt::Debug for AlignFromBytesError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(self, f) @@ -1023,8 +1009,8 @@ impl fmt::Debug for AlignFromBytesError { impl fmt::Display for AlignFromBytesError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - AlignFromBytesError::NotPowerOfTwo(align) => write!(f, "`{align}` is not a power of 2"), - AlignFromBytesError::TooLarge(align) => write!(f, "`{align}` is too large"), + AlignFromBytesError::NotPowerOfTwo(align) => write!(f, "{align} is not a power of 2"), + AlignFromBytesError::TooLarge(align) => write!(f, "{align} is too large"), } } } diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 54253babafa78..89e008f06ebc8 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -990,30 +990,25 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { let bind_to = &self.body.local_decls[*local]; let binding_span = bind_to.source_info.span; - if j == 0 { - err.span_label(binding_span, "data moved here"); - } else { - err.span_label(binding_span, "...and here"); - } - if binds_to.len() == 1 { let place_desc = self.local_name(*local).map(|sym| format!("`{sym}`")); + err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::LabelMovedHere { + ty: bind_to.ty, + place: place_desc.as_deref().unwrap_or("the place"), + span: binding_span, + }); + if !desugar_spans.contains(&binding_span) && let Some(expr) = self.find_expr(binding_span) { - // The binding_span doesn't correspond to a let binding desugaring - // and is an expression where calling `.clone()` would be valid. let local_place: PlaceRef<'tcx> = (*local).into(); self.suggest_cloning(err, local_place, bind_to.ty, expr, None); } - - err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label { - is_partial_move: false, - ty: bind_to.ty, - place: place_desc.as_deref().unwrap_or("the place"), - span: binding_span, - }); + } else if j == 0 { + err.span_label(binding_span, "data moved here"); + } else { + err.span_label(binding_span, "...and here"); } } diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs index fea5c2b990372..b2f33d64f0d9e 100644 --- a/compiler/rustc_borrowck/src/session_diagnostics.rs +++ b/compiler/rustc_borrowck/src/session_diagnostics.rs @@ -570,6 +570,16 @@ pub(crate) enum TypeNoCopy<'a, 'tcx> { #[primary_span] span: Span, }, + #[label( + "data moved here because {$place} has type `{$ty}`, which does not implement the `Copy` \ + trait" + )] + LabelMovedHere { + ty: Ty<'tcx>, + place: &'a str, + #[primary_span] + span: Span, + }, #[note( "{$is_partial_move -> [true] partial move diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs index 5423ee5390fe5..64ab92b3a914b 100644 --- a/compiler/rustc_codegen_gcc/src/context.rs +++ b/compiler/rustc_codegen_gcc/src/context.rs @@ -538,7 +538,7 @@ impl<'gcc, 'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> { | LayoutError::InvalidSimd { .. } | LayoutError::ReferencesError(_) = err { - self.tcx.dcx().emit_fatal(respan(span, err.into_diagnostic())) + self.tcx.dcx().span_fatal(span, err.to_string()) } else { self.tcx.dcx().emit_fatal(ssa_errors::FailedToGetLayout { span, ty, err }) } diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 28aa12cc83dc5..545a9add911d4 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -1135,7 +1135,7 @@ impl<'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'_, 'tcx> { | LayoutError::ReferencesError(_) | LayoutError::InvalidSimd { .. } = err { - self.tcx.dcx().emit_fatal(Spanned { span, node: err.into_diagnostic() }) + self.tcx.dcx().span_fatal(span, err.to_string()) } else { self.tcx.dcx().emit_fatal(ssa_errors::FailedToGetLayout { span, ty, err }) } diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index d3b2caca4742d..d207cdca4d4bb 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -95,7 +95,7 @@ fn push_debuginfo_type_name<'tcx>( // Computing the layout can still fail here, e.g. if the target architecture // cannot represent the type. See // https://github.com/rust-lang/rust/issues/94961. - tcx.dcx().emit_fatal(e.into_diagnostic()); + tcx.dcx().fatal(e.to_string()); } } } else { diff --git a/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs b/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs index f41b68bb1f7ed..7c5f867929f04 100644 --- a/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs @@ -25,17 +25,8 @@ pub macro throw_machine_stop_str($($tt:tt)*) {{ write!(f, $($tt)*) } } + impl rustc_middle::mir::interpret::MachineStopType for Zst {} - impl rustc_middle::mir::interpret::MachineStopType for Zst { - fn diagnostic_message(&self) -> rustc_errors::DiagMessage { - self.to_string().into() - } - - fn add_args( - self: Box, - _: &mut dyn FnMut(rustc_errors::DiagArgName, rustc_errors::DiagArgValue), - ) {} - } throw_machine_stop!(Zst) }} diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs index 41d21bd74f98c..61e8e433d5178 100644 --- a/compiler/rustc_const_eval/src/const_eval/error.rs +++ b/compiler/rustc_const_eval/src/const_eval/error.rs @@ -1,15 +1,17 @@ -use std::mem; +use std::{fmt, mem}; -use rustc_errors::{Diag, DiagArgName, DiagArgValue, DiagMessage, IntoDiagArg}; +use rustc_errors::Diag; use rustc_middle::mir::AssertKind; -use rustc_middle::mir::interpret::{AllocId, Provenance, ReportedErrorInfo, UndefinedBehaviorInfo}; +use rustc_middle::mir::interpret::{ + AllocId, Provenance, ReportedErrorInfo, UndefinedBehaviorInfo, UnsupportedOpInfo, +}; use rustc_middle::query::TyCtxtAt; use rustc_middle::ty::ConstInt; use rustc_middle::ty::layout::LayoutError; use rustc_span::{Span, Symbol}; use super::CompileTimeMachine; -use crate::errors::{self, FrameNote, ReportErrorExt}; +use crate::errors::{self, FrameNote}; use crate::interpret::{ CtfeProvenance, ErrorHandled, Frame, InterpCx, InterpErrorInfo, InterpErrorKind, MachineStopType, Pointer, err_inval, err_machine_stop, @@ -40,65 +42,49 @@ pub enum ConstEvalErrKind { ConstMakeGlobalWithOffset(Pointer>), } -impl MachineStopType for ConstEvalErrKind { - fn diagnostic_message(&self) -> DiagMessage { +impl fmt::Display for ConstEvalErrKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { use ConstEvalErrKind::*; - use rustc_errors::msg; - match self { - ConstAccessesMutGlobal => "constant accesses mutable global memory".into(), + ConstAccessesMutGlobal => write!(f, "constant accesses mutable global memory"), ModifiedGlobal => { - "modifying a static's initial value from another static's initializer".into() + write!(f, "modifying a static's initial value from another static's initializer") } - Panic { .. } => msg!("evaluation panicked: {$msg}"), + Panic { msg, .. } => write!(f, "evaluation panicked: {msg}"), RecursiveStatic => { - "encountered static that tried to access itself during initialization".into() + write!(f, "encountered static that tried to access itself during initialization") } - AssertFailure(x) => x.diagnostic_message(), + AssertFailure(x) => write!(f, "{x}"), WriteThroughImmutablePointer => { - msg!( + write!( + f, "writing through a pointer that was derived from a shared (immutable) reference" ) } - ConstMakeGlobalPtrAlreadyMadeGlobal { .. } => { - msg!("attempting to call `const_make_global` twice on the same allocation {$alloc}") - } - ConstMakeGlobalPtrIsNonHeap(_) => { - msg!( - "pointer passed to `const_make_global` does not point to a heap allocation: {$ptr}" + ConstMakeGlobalPtrAlreadyMadeGlobal(alloc) => { + write!( + f, + "attempting to call `const_make_global` twice on the same allocation {alloc}" ) } - ConstMakeGlobalWithDanglingPtr(_) => { - msg!("pointer passed to `const_make_global` is dangling: {$ptr}") - } - ConstMakeGlobalWithOffset(_) => { - msg!("making {$ptr} global which does not point to the beginning of an object") - } - } - } - fn add_args(self: Box, adder: &mut dyn FnMut(DiagArgName, DiagArgValue)) { - use ConstEvalErrKind::*; - match *self { - RecursiveStatic - | ConstAccessesMutGlobal - | ModifiedGlobal - | WriteThroughImmutablePointer => {} - AssertFailure(kind) => kind.add_args(adder), - Panic { msg, .. } => { - adder("msg".into(), msg.into_diag_arg(&mut None)); + ConstMakeGlobalPtrIsNonHeap(ptr) => { + write!( + f, + "pointer passed to `const_make_global` does not point to a heap allocation: {ptr}" + ) } - ConstMakeGlobalPtrIsNonHeap(ptr) - | ConstMakeGlobalWithOffset(ptr) - | ConstMakeGlobalWithDanglingPtr(ptr) => { - adder("ptr".into(), format!("{ptr:?}").into_diag_arg(&mut None)); + ConstMakeGlobalWithDanglingPtr(ptr) => { + write!(f, "pointer passed to `const_make_global` is dangling: {ptr}") } - ConstMakeGlobalPtrAlreadyMadeGlobal(alloc) => { - adder("alloc".into(), alloc.into_diag_arg(&mut None)); + ConstMakeGlobalWithOffset(ptr) => { + write!(f, "making {ptr} global which does not point to the beginning of an object") } } } } +impl MachineStopType for ConstEvalErrKind {} + /// The errors become [`InterpErrorKind::MachineStop`] when being raised. impl<'tcx> Into> for ConstEvalErrKind { fn into(self) -> InterpErrorInfo<'tcx> { @@ -207,14 +193,20 @@ where _ => { let (our_span, frames) = get_span_and_frames(); let span = span.substitute_dummy(our_span); - let mut err = tcx.dcx().struct_span_err(our_span, error.diagnostic_message()); - // We allow invalid programs in infallible promoteds since invalid layouts can occur - // anyway (e.g. due to size overflow). And we allow OOM as that can happen any time. - let allowed_in_infallible = matches!( + let mut err = tcx.dcx().struct_span_err(our_span, error.to_string()); + if matches!( error, - InterpErrorKind::ResourceExhaustion(_) | InterpErrorKind::InvalidProgram(_) - ); - + InterpErrorKind::UndefinedBehavior(UndefinedBehaviorInfo::ValidationError { + ptr_bytes_warning: true, + .. + }) | InterpErrorKind::Unsupported( + UnsupportedOpInfo::ReadPointerAsInt(..) + | UnsupportedOpInfo::ReadPartialPointer(..) + ) + ) { + err.help("this code performed an operation that depends on the underlying bytes representing a pointer"); + err.help("the absolute address of a pointer is not known at compile-time, so such operations are not supported"); + } if let InterpErrorKind::UndefinedBehavior(UndefinedBehaviorInfo::InvalidUninitBytes( Some((alloc_id, _access)), )) = error @@ -229,7 +221,12 @@ where err.subdiagnostic(raw_bytes); } - error.add_args(&mut err); + // We allow invalid programs in infallible promoteds since invalid layouts can occur + // anyway (e.g. due to size overflow). And we allow OOM as that can happen any time. + let allowed_in_infallible = matches!( + error, + InterpErrorKind::ResourceExhaustion(_) | InterpErrorKind::InvalidProgram(_) + ); mk(&mut err, span, frames); let g = err.emit(); diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index e88123334dd52..a19bf0b4da8be 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -5,7 +5,6 @@ use std::hash::Hash; use rustc_abi::{Align, FIRST_VARIANT, Size}; use rustc_ast::Mutability; use rustc_data_structures::fx::{FxHashMap, FxIndexMap, IndexEntry}; -use rustc_errors::msg; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::{self as hir, CRATE_HIR_ID, LangItem, find_attr}; use rustc_middle::mir::AssertMessage; @@ -24,7 +23,7 @@ use crate::interpret::{ self, AllocId, AllocInit, AllocRange, ConstAllocation, CtfeProvenance, FnArg, Frame, GlobalAlloc, ImmTy, InterpCx, InterpResult, OpTy, PlaceTy, Pointer, RangeSet, Scalar, compile_time_machine, ensure_monomorphic_enough, err_inval, interp_ok, throw_exhaust, - throw_inval, throw_ub, throw_ub_custom, throw_unsup, throw_unsup_format, + throw_inval, throw_ub, throw_ub_format, throw_unsup, throw_unsup_format, type_implements_dyn_trait, }; @@ -489,18 +488,9 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { let align = match Align::from_bytes(align) { Ok(a) => a, - Err(err) => throw_ub_custom!( - msg!( - "invalid align passed to `{$name}`: {$align} is {$err_kind -> - [not_power_of_two] not a power of 2 - [too_large] too large - *[other] {\"\"} - }" - ), - name = "const_allocate", - err_kind = err.diag_ident(), - align = err.align() - ), + Err(err) => { + throw_ub_format!("invalid align passed to `const_allocate`: {err}") + } }; let ptr = ecx.allocate_ptr( @@ -519,18 +509,9 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { let size = Size::from_bytes(size); let align = match Align::from_bytes(align) { Ok(a) => a, - Err(err) => throw_ub_custom!( - msg!( - "invalid align passed to `{$name}`: {$align} is {$err_kind -> - [not_power_of_two] not a power of 2 - [too_large] too large - *[other] {\"\"} - }" - ), - name = "const_deallocate", - err_kind = err.diag_ident(), - align = err.align() - ), + Err(err) => { + throw_ub_format!("invalid align passed to `const_deallocate`: {err}") + } }; // If an allocation is created in an another const, diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index 07d001e9d847f..3943be0cf15ef 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -1,22 +1,11 @@ use std::borrow::Cow; -use std::fmt::Write; -use either::Either; -use rustc_abi::WrappingRange; use rustc_errors::codes::*; use rustc_errors::formatting::DiagMessageAddArg; -use rustc_errors::{ - Diag, DiagArgMap, DiagArgValue, DiagMessage, Diagnostic, EmissionGuarantee, Level, MultiSpan, - Subdiagnostic, format_diag_message, msg, -}; +use rustc_errors::{Diag, DiagArgValue, EmissionGuarantee, MultiSpan, Subdiagnostic, msg}; use rustc_hir::ConstContext; use rustc_macros::{Diagnostic, Subdiagnostic}; -use rustc_middle::mir::interpret::{ - CtfeProvenance, ExpectedKind, InterpErrorKind, InvalidMetaKind, InvalidProgramInfo, - Misalignment, Pointer, PointerKind, ResourceExhaustionInfo, UndefinedBehaviorInfo, - UnsupportedOpInfo, ValidationErrorInfo, -}; -use rustc_middle::ty::{self, Mutability, Ty}; +use rustc_middle::ty::{Mutability, Ty}; use rustc_span::{Span, Symbol}; use crate::interpret::InternKind; @@ -394,8 +383,6 @@ pub struct RawBytesNote { pub bytes: String, } -// FIXME(fee1-dead) do not use stringly typed `ConstContext` - #[derive(Diagnostic)] #[diag( r#"cannot match on `{$ty}` in {$kind -> @@ -609,699 +596,6 @@ pub struct LiveDrop<'tcx> { pub dropped_at: Span, } -pub trait ReportErrorExt { - /// Returns the diagnostic message for this error. - fn diagnostic_message(&self) -> DiagMessage; - fn add_args(self, diag: &mut Diag<'_, G>); - - fn debug(self) -> String - where - Self: Sized, - { - ty::tls::with(move |tcx| { - let dcx = tcx.dcx(); - let mut diag = dcx.struct_allow(DiagMessage::Str(String::new().into())); - let message = self.diagnostic_message(); - self.add_args(&mut diag); - let s = format_diag_message(&message, &diag.args).into_owned(); - diag.cancel(); - s - }) - } -} - -impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> { - fn diagnostic_message(&self) -> DiagMessage { - use UndefinedBehaviorInfo::*; - - match self { - Ub(msg) => msg.clone().into(), - Custom(x) => (x.msg)(), - ValidationError(e) => e.diagnostic_message(), - - Unreachable => "entering unreachable code".into(), - BoundsCheckFailed { .. } => msg!("indexing out of bounds: the len is {$len} but the index is {$index}"), - DivisionByZero => "dividing by zero".into(), - RemainderByZero => "calculating the remainder with a divisor of zero".into(), - DivisionOverflow => "overflow in signed division (dividing MIN by -1)".into(), - RemainderOverflow => "overflow in signed remainder (dividing MIN by -1)".into(), - PointerArithOverflow => "overflowing pointer arithmetic: the total offset in bytes does not fit in an `isize`".into(), - ArithOverflow { .. } => msg!("arithmetic overflow in `{$intrinsic}`"), - ShiftOverflow { .. } => msg!("overflowing shift by {$shift_amount} in `{$intrinsic}`"), - InvalidMeta(InvalidMetaKind::SliceTooBig) => "invalid metadata in wide pointer: slice is bigger than largest supported object".into(), - InvalidMeta(InvalidMetaKind::TooBig) => "invalid metadata in wide pointer: total size is bigger than largest supported object".into(), - UnterminatedCString(_) => "reading a null-terminated string starting at {$pointer} with no null found before end of allocation".into(), - PointerUseAfterFree(_, _) => msg!( - "{$operation -> - [MemoryAccess] memory access failed - [InboundsPointerArithmetic] in-bounds pointer arithmetic failed - *[Dereferenceable] pointer not dereferenceable - }: {$alloc_id} has been freed, so this pointer is dangling" - ), - PointerOutOfBounds { .. } => msg!( - "{$operation -> - [MemoryAccess] memory access failed - [InboundsPointerArithmetic] in-bounds pointer arithmetic failed - *[Dereferenceable] pointer not dereferenceable - }: {$operation -> - [MemoryAccess] attempting to access {$inbounds_size -> - [1] 1 byte - *[x] {$inbounds_size} bytes - } - [InboundsPointerArithmetic] attempting to offset pointer by {$inbounds_size -> - [1] 1 byte - *[x] {$inbounds_size} bytes - } - *[Dereferenceable] pointer must {$inbounds_size -> - [0] point to some allocation - [1] be dereferenceable for 1 byte - *[x] be dereferenceable for {$inbounds_size} bytes - } - }, but got {$pointer} which {$ptr_offset_is_neg -> - [true] points to before the beginning of the allocation - *[false] {$inbounds_size_is_neg -> - [false] {$alloc_size_minus_ptr_offset -> - [0] is at or beyond the end of the allocation of size {$alloc_size -> - [1] 1 byte - *[x] {$alloc_size} bytes - } - [1] is only 1 byte from the end of the allocation - *[x] is only {$alloc_size_minus_ptr_offset} bytes from the end of the allocation - } - *[true] {$ptr_offset_abs -> - [0] is at the beginning of the allocation - *[other] is only {$ptr_offset_abs} bytes from the beginning of the allocation - } - } - }" - ), - DanglingIntPointer { addr: 0, .. } => msg!( - "{$operation -> - [MemoryAccess] memory access failed - [InboundsPointerArithmetic] in-bounds pointer arithmetic failed - *[Dereferenceable] pointer not dereferenceable - }: {$operation -> - [MemoryAccess] attempting to access {$inbounds_size -> - [1] 1 byte - *[x] {$inbounds_size} bytes - } - [InboundsPointerArithmetic] attempting to offset pointer by {$inbounds_size -> - [1] 1 byte - *[x] {$inbounds_size} bytes - } - *[Dereferenceable] pointer must {$inbounds_size -> - [0] point to some allocation - [1] be dereferenceable for 1 byte - *[x] be dereferenceable for {$inbounds_size} bytes - } - }, but got null pointer"), - DanglingIntPointer { .. } => msg!( - "{$operation -> - [MemoryAccess] memory access failed - [InboundsPointerArithmetic] in-bounds pointer arithmetic failed - *[Dereferenceable] pointer not dereferenceable - }: {$operation -> - [MemoryAccess] attempting to access {$inbounds_size -> - [1] 1 byte - *[x] {$inbounds_size} bytes - } - [InboundsPointerArithmetic] attempting to offset pointer by {$inbounds_size -> - [1] 1 byte - *[x] {$inbounds_size} bytes - } - *[Dereferenceable] pointer must {$inbounds_size -> - [0] point to some allocation - [1] be dereferenceable for 1 byte - *[x] be dereferenceable for {$inbounds_size} bytes - } - }, but got {$pointer} which is a dangling pointer (it has no provenance)"), - AlignmentCheckFailed { .. } => msg!( - "{$msg -> - [AccessedPtr] accessing memory - *[other] accessing memory based on pointer - } with alignment {$has}, but alignment {$required} is required" - ), - WriteToReadOnly(_) => msg!("writing to {$allocation} which is read-only"), - DerefFunctionPointer(_) => msg!("accessing {$allocation} which contains a function"), - DerefVTablePointer(_) => msg!("accessing {$allocation} which contains a vtable"), - DerefVaListPointer(_) => msg!("accessing {$allocation} which contains a variable argument list"), - DerefTypeIdPointer(_) => msg!("accessing {$allocation} which contains a `TypeId`"), - InvalidBool(_) => msg!("interpreting an invalid 8-bit value as a bool: 0x{$value}"), - InvalidChar(_) => msg!("interpreting an invalid 32-bit value as a char: 0x{$value}"), - InvalidTag(_) => msg!("enum value has invalid tag: {$tag}"), - InvalidFunctionPointer(_) => msg!("using {$pointer} as function pointer but it does not point to a function"), - InvalidVaListPointer(_) => msg!("using {$pointer} as variable argument list pointer but it does not point to a variable argument list"), - InvalidVTablePointer(_) => msg!("using {$pointer} as vtable pointer but it does not point to a vtable"), - InvalidVTableTrait { .. } => msg!("using vtable for `{$vtable_dyn_type}` but `{$expected_dyn_type}` was expected"), - InvalidStr(_) => msg!("this string is not valid UTF-8: {$err}"), - InvalidUninitBytes(None) => "using uninitialized data, but this operation requires initialized memory".into(), - InvalidUninitBytes(Some(_)) => msg!("reading memory at {$alloc}{$access}, but memory is uninitialized at {$uninit}, and this operation requires initialized memory"), - DeadLocal => "accessing a dead local variable".into(), - ScalarSizeMismatch(_) => msg!("scalar size mismatch: expected {$target_size} bytes but got {$data_size} bytes instead"), - UninhabitedEnumVariantWritten(_) => "writing discriminant of an uninhabited enum variant".into(), - UninhabitedEnumVariantRead(_) => "read discriminant of an uninhabited enum variant".into(), - InvalidNichedEnumVariantWritten { .. } => { - msg!("trying to set discriminant of a {$ty} to the niched variant, but the value does not match") - } - AbiMismatchArgument { .. } => msg!("calling a function whose parameter #{$arg_idx} has type {$callee_ty} passing argument of type {$caller_ty}"), - AbiMismatchReturn { .. } => msg!("calling a function with return type {$callee_ty} passing return place of type {$caller_ty}"), - VaArgOutOfBounds => "more C-variadic arguments read than were passed".into(), - CVariadicMismatch { ..} => "calling a function where the caller and callee disagree on whether the function is C-variadic".into(), - CVariadicFixedCountMismatch { .. } => msg!("calling a C-variadic function with {$caller} fixed arguments, but the function expects {$callee}"), - } - } - - fn add_args(self, diag: &mut Diag<'_, G>) { - use UndefinedBehaviorInfo::*; - match self { - Ub(_) => {} - Custom(custom) => { - (custom.add_args)(&mut |name, value| { - diag.arg(name, value); - }); - } - ValidationError(e) => e.add_args(diag), - - Unreachable - | DivisionByZero - | RemainderByZero - | DivisionOverflow - | RemainderOverflow - | PointerArithOverflow - | InvalidMeta(InvalidMetaKind::SliceTooBig) - | InvalidMeta(InvalidMetaKind::TooBig) - | InvalidUninitBytes(None) - | DeadLocal - | VaArgOutOfBounds - | UninhabitedEnumVariantWritten(_) - | UninhabitedEnumVariantRead(_) => {} - - ArithOverflow { intrinsic } => { - diag.arg("intrinsic", intrinsic); - } - ShiftOverflow { intrinsic, shift_amount } => { - diag.arg("intrinsic", intrinsic); - diag.arg( - "shift_amount", - match shift_amount { - Either::Left(v) => v.to_string(), - Either::Right(v) => v.to_string(), - }, - ); - } - BoundsCheckFailed { len, index } => { - diag.arg("len", len); - diag.arg("index", index); - } - UnterminatedCString(ptr) - | InvalidFunctionPointer(ptr) - | InvalidVaListPointer(ptr) - | InvalidVTablePointer(ptr) => { - diag.arg("pointer", ptr); - } - InvalidVTableTrait { expected_dyn_type, vtable_dyn_type } => { - diag.arg("expected_dyn_type", expected_dyn_type.to_string()); - diag.arg("vtable_dyn_type", vtable_dyn_type.to_string()); - } - PointerUseAfterFree(alloc_id, msg) => { - diag.arg("alloc_id", alloc_id).arg("operation", format!("{:?}", msg)); - } - PointerOutOfBounds { alloc_id, alloc_size, ptr_offset, inbounds_size, msg } => { - diag.arg("alloc_size", alloc_size.bytes()); - diag.arg("pointer", { - let mut out = format!("{:?}", alloc_id); - if ptr_offset > 0 { - write!(out, "+{:#x}", ptr_offset).unwrap(); - } else if ptr_offset < 0 { - write!(out, "-{:#x}", ptr_offset.unsigned_abs()).unwrap(); - } - out - }); - diag.arg("inbounds_size", inbounds_size); - diag.arg("inbounds_size_is_neg", inbounds_size < 0); - diag.arg("inbounds_size_abs", inbounds_size.unsigned_abs()); - diag.arg("ptr_offset", ptr_offset); - diag.arg("ptr_offset_is_neg", ptr_offset < 0); - diag.arg("ptr_offset_abs", ptr_offset.unsigned_abs()); - diag.arg( - "alloc_size_minus_ptr_offset", - alloc_size.bytes().saturating_sub(ptr_offset as u64), - ); - diag.arg("operation", format!("{:?}", msg)); - } - DanglingIntPointer { addr, inbounds_size, msg } => { - if addr != 0 { - diag.arg( - "pointer", - Pointer::>::without_provenance(addr).to_string(), - ); - } - - diag.arg("inbounds_size", inbounds_size); - diag.arg("inbounds_size_is_neg", inbounds_size < 0); - diag.arg("inbounds_size_abs", inbounds_size.unsigned_abs()); - diag.arg("operation", format!("{:?}", msg)); - } - AlignmentCheckFailed(Misalignment { required, has }, msg) => { - diag.arg("required", required.bytes()); - diag.arg("has", has.bytes()); - diag.arg("msg", format!("{msg:?}")); - } - WriteToReadOnly(alloc) - | DerefFunctionPointer(alloc) - | DerefVTablePointer(alloc) - | DerefVaListPointer(alloc) - | DerefTypeIdPointer(alloc) => { - diag.arg("allocation", alloc); - } - InvalidBool(b) => { - diag.arg("value", format!("{b:02x}")); - } - InvalidChar(c) => { - diag.arg("value", format!("{c:08x}")); - } - InvalidTag(tag) => { - diag.arg("tag", format!("{tag:x}")); - } - InvalidStr(err) => { - diag.arg("err", format!("{err}")); - } - InvalidUninitBytes(Some((alloc, info))) => { - diag.arg("alloc", alloc); - diag.arg("access", info.access); - diag.arg("uninit", info.bad); - } - ScalarSizeMismatch(info) => { - diag.arg("target_size", info.target_size); - diag.arg("data_size", info.data_size); - } - InvalidNichedEnumVariantWritten { enum_ty } => { - diag.arg("ty", enum_ty); - } - AbiMismatchArgument { arg_idx, caller_ty, callee_ty } => { - diag.arg("arg_idx", arg_idx + 1); // adjust for 1-indexed lists in output - diag.arg("caller_ty", caller_ty); - diag.arg("callee_ty", callee_ty); - } - AbiMismatchReturn { caller_ty, callee_ty } => { - diag.arg("caller_ty", caller_ty); - diag.arg("callee_ty", callee_ty); - } - CVariadicMismatch { caller_is_c_variadic, callee_is_c_variadic } => { - diag.arg("caller_is_c_variadic", caller_is_c_variadic); - diag.arg("callee_is_c_variadic", callee_is_c_variadic); - } - CVariadicFixedCountMismatch { caller, callee } => { - diag.arg("caller", caller); - diag.arg("callee", callee); - } - } - } -} - -impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { - fn diagnostic_message(&self) -> DiagMessage { - use rustc_middle::mir::interpret::ValidationErrorKind::*; - - match self.kind { - PtrToUninhabited { ptr_kind: PointerKind::Box, .. } => { - msg!("{$front_matter}: encountered a box pointing to uninhabited type {$ty}") - } - PtrToUninhabited { ptr_kind: PointerKind::Ref(_), .. } => { - msg!("{$front_matter}: encountered a reference pointing to uninhabited type {$ty}") - } - - PointerAsInt { .. } => { - msg!("{$front_matter}: encountered a pointer, but {$expected}") - } - PartialPointer => { - msg!("{$front_matter}: encountered a partial pointer or a mix of pointers") - } - MutableRefToImmutable => { - msg!( - "{$front_matter}: encountered mutable reference or box pointing to read-only memory" - ) - } - NullFnPtr { .. } => { - msg!( - "{$front_matter}: encountered a {$maybe -> - [true] maybe-null - *[false] null - } function pointer" - ) - } - NeverVal => { - msg!("{$front_matter}: encountered a value of the never type `!`") - } - NonnullPtrMaybeNull { .. } => { - msg!( - "{$front_matter}: encountered a maybe-null pointer, but expected something that is definitely non-zero" - ) - } - PtrOutOfRange { .. } => { - msg!( - "{$front_matter}: encountered a pointer with unknown absolute address, but expected something that is definitely {$in_range}" - ) - } - OutOfRange { .. } => { - msg!("{$front_matter}: encountered {$value}, but expected something {$in_range}") - } - UnsafeCellInImmutable => { - msg!("{$front_matter}: encountered `UnsafeCell` in read-only memory") - } - UninhabitedVal { .. } => { - msg!("{$front_matter}: encountered a value of uninhabited type `{$ty}`") - } - InvalidEnumTag { .. } => { - msg!("{$front_matter}: encountered {$value}, but expected a valid enum tag") - } - UninhabitedEnumVariant => { - msg!("{$front_matter}: encountered an uninhabited enum variant") - } - Uninit { .. } => { - msg!("{$front_matter}: encountered uninitialized memory, but {$expected}") - } - InvalidVTablePtr { .. } => { - msg!("{$front_matter}: encountered {$value}, but expected a vtable pointer") - } - InvalidMetaWrongTrait { .. } => { - msg!( - "{$front_matter}: wrong trait in wide pointer vtable: expected `{$expected_dyn_type}`, but encountered `{$vtable_dyn_type}`" - ) - } - InvalidMetaSliceTooLarge { ptr_kind: PointerKind::Box } => { - msg!( - "{$front_matter}: encountered invalid box metadata: slice is bigger than largest supported object" - ) - } - InvalidMetaSliceTooLarge { ptr_kind: PointerKind::Ref(_) } => { - msg!( - "{$front_matter}: encountered invalid reference metadata: slice is bigger than largest supported object" - ) - } - - InvalidMetaTooLarge { ptr_kind: PointerKind::Box } => { - msg!( - "{$front_matter}: encountered invalid box metadata: total size is bigger than largest supported object" - ) - } - InvalidMetaTooLarge { ptr_kind: PointerKind::Ref(_) } => { - msg!( - "{$front_matter}: encountered invalid reference metadata: total size is bigger than largest supported object" - ) - } - UnalignedPtr { ptr_kind: PointerKind::Ref(_), .. } => { - msg!( - "{$front_matter}: encountered an unaligned reference (required {$required_bytes} byte alignment but found {$found_bytes})" - ) - } - UnalignedPtr { ptr_kind: PointerKind::Box, .. } => { - msg!( - "{$front_matter}: encountered an unaligned box (required {$required_bytes} byte alignment but found {$found_bytes})" - ) - } - - NullPtr { ptr_kind: PointerKind::Box, .. } => { - msg!( - "{$front_matter}: encountered a {$maybe -> - [true] maybe-null - *[false] null - } box" - ) - } - NullPtr { ptr_kind: PointerKind::Ref(_), .. } => { - msg!( - "{$front_matter}: encountered a {$maybe -> - [true] maybe-null - *[false] null - } reference" - ) - } - DanglingPtrNoProvenance { ptr_kind: PointerKind::Box, .. } => { - msg!("{$front_matter}: encountered a dangling box ({$pointer} has no provenance)") - } - DanglingPtrNoProvenance { ptr_kind: PointerKind::Ref(_), .. } => { - msg!( - "{$front_matter}: encountered a dangling reference ({$pointer} has no provenance)" - ) - } - DanglingPtrOutOfBounds { ptr_kind: PointerKind::Box } => { - msg!( - "{$front_matter}: encountered a dangling box (going beyond the bounds of its allocation)" - ) - } - DanglingPtrOutOfBounds { ptr_kind: PointerKind::Ref(_) } => { - msg!( - "{$front_matter}: encountered a dangling reference (going beyond the bounds of its allocation)" - ) - } - DanglingPtrUseAfterFree { ptr_kind: PointerKind::Box } => { - msg!("{$front_matter}: encountered a dangling box (use-after-free)") - } - DanglingPtrUseAfterFree { ptr_kind: PointerKind::Ref(_) } => { - msg!("{$front_matter}: encountered a dangling reference (use-after-free)") - } - InvalidBool { .. } => { - msg!("{$front_matter}: encountered {$value}, but expected a boolean") - } - InvalidChar { .. } => { - msg!( - "{$front_matter}: encountered {$value}, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)" - ) - } - InvalidFnPtr { .. } => { - msg!("{$front_matter}: encountered {$value}, but expected a function pointer") - } - } - } - - fn add_args(self, err: &mut Diag<'_, G>) { - use rustc_errors::msg; - use rustc_middle::mir::interpret::ValidationErrorKind::*; - - if let PointerAsInt { .. } | PartialPointer = self.kind { - err.help(msg!("this code performed an operation that depends on the underlying bytes representing a pointer")); - err.help(msg!("the absolute address of a pointer is not known at compile-time, so such operations are not supported")); - } - - let message = if let Some(path) = self.path { - format_diag_message( - &msg!("constructing invalid value at {$path}"), - &DiagArgMap::from_iter([("path".into(), DiagArgValue::Str(path.into()))]), - ) - } else { - Cow::Borrowed("constructing invalid value") - }; - - err.arg("front_matter", message); - - fn add_range_arg( - r: WrappingRange, - max_hi: u128, - err: &mut Diag<'_, G>, - ) { - let WrappingRange { start: lo, end: hi } = r; - assert!(hi <= max_hi); - let msg = if lo > hi { - msg!("less or equal to {$hi}, or greater or equal to {$lo}") - } else if lo == hi { - msg!("equal to {$lo}") - } else if lo == 0 { - assert!(hi < max_hi, "should not be printing if the range covers everything"); - msg!("less or equal to {$hi}") - } else if hi == max_hi { - assert!(lo > 0, "should not be printing if the range covers everything"); - msg!("greater or equal to {$lo}") - } else { - msg!("in the range {$lo}..={$hi}") - }; - - let message = format_diag_message( - &msg, - &DiagArgMap::from_iter([ - ("lo".into(), DiagArgValue::Str(lo.to_string().into())), - ("hi".into(), DiagArgValue::Str(hi.to_string().into())), - ]), - ); - err.arg("in_range", message); - } - - match self.kind { - PtrToUninhabited { ty, .. } | UninhabitedVal { ty } => { - err.arg("ty", ty); - } - PointerAsInt { expected } | Uninit { expected } => { - let msg = match expected { - ExpectedKind::Reference => "expected a reference", - ExpectedKind::Box => "expected a box", - ExpectedKind::RawPtr => "expected a raw pointer", - ExpectedKind::InitScalar => "expected initialized scalar value", - ExpectedKind::Bool => "expected a boolean", - ExpectedKind::Char => "expected a unicode scalar value", - ExpectedKind::Float => "expected a floating point number", - ExpectedKind::Int => "expected an integer", - ExpectedKind::FnPtr => "expected a function pointer", - ExpectedKind::EnumTag => "expected a valid enum tag", - ExpectedKind::Str => "expected a string", - }; - err.arg("expected", msg); - } - InvalidEnumTag { value } - | InvalidVTablePtr { value } - | InvalidBool { value } - | InvalidChar { value } - | InvalidFnPtr { value } => { - err.arg("value", value); - } - PtrOutOfRange { range, max_value } => add_range_arg(range, max_value, err), - OutOfRange { range, max_value, value } => { - err.arg("value", value); - add_range_arg(range, max_value, err); - } - UnalignedPtr { required_bytes, found_bytes, .. } => { - err.arg("required_bytes", required_bytes); - err.arg("found_bytes", found_bytes); - } - DanglingPtrNoProvenance { pointer, .. } => { - err.arg("pointer", pointer); - } - InvalidMetaWrongTrait { vtable_dyn_type, expected_dyn_type } => { - err.arg("vtable_dyn_type", vtable_dyn_type.to_string()); - err.arg("expected_dyn_type", expected_dyn_type.to_string()); - } - NullPtr { maybe, .. } | NullFnPtr { maybe } => { - err.arg("maybe", maybe); - } - MutableRefToImmutable - | NonnullPtrMaybeNull - | NeverVal - | UnsafeCellInImmutable - | InvalidMetaSliceTooLarge { .. } - | InvalidMetaTooLarge { .. } - | DanglingPtrUseAfterFree { .. } - | DanglingPtrOutOfBounds { .. } - | UninhabitedEnumVariant - | PartialPointer => {} - } - } -} - -impl ReportErrorExt for UnsupportedOpInfo { - fn diagnostic_message(&self) -> DiagMessage { - match self { - UnsupportedOpInfo::Unsupported(s) => s.clone().into(), - UnsupportedOpInfo::ExternTypeField => { - "`extern type` field does not have a known offset".into() - } - UnsupportedOpInfo::UnsizedLocal => "unsized locals are not supported".into(), - UnsupportedOpInfo::ReadPartialPointer(_) => { - msg!("unable to read parts of a pointer from memory at {$ptr}") - } - UnsupportedOpInfo::ReadPointerAsInt(_) => "unable to turn pointer into integer".into(), - UnsupportedOpInfo::ThreadLocalStatic(_) => { - msg!("cannot access thread local static `{$did}`") - } - UnsupportedOpInfo::ExternStatic(_) => { - msg!("cannot access extern static `{$did}`") - } - } - .into() - } - - fn add_args(self, diag: &mut Diag<'_, G>) { - use UnsupportedOpInfo::*; - - if let ReadPointerAsInt(_) | ReadPartialPointer(_) = self { - diag.help("this code performed an operation that depends on the underlying bytes representing a pointer"); - diag.help("the absolute address of a pointer is not known at compile-time, so such operations are not supported"); - } - match self { - // `ReadPointerAsInt(Some(info))` is never printed anyway, it only serves as an error to - // be further processed by validity checking which then turns it into something nice to - // print. So it's not worth the effort of having diagnostics that can print the `info`. - UnsizedLocal - | UnsupportedOpInfo::ExternTypeField - | Unsupported(_) - | ReadPointerAsInt(_) => {} - ReadPartialPointer(ptr) => { - diag.arg("ptr", ptr); - } - ThreadLocalStatic(did) | ExternStatic(did) => rustc_middle::ty::tls::with(|tcx| { - diag.arg("did", tcx.def_path_str(did)); - }), - } - } -} - -impl<'tcx> ReportErrorExt for InterpErrorKind<'tcx> { - fn diagnostic_message(&self) -> DiagMessage { - match self { - InterpErrorKind::UndefinedBehavior(ub) => ub.diagnostic_message(), - InterpErrorKind::Unsupported(e) => e.diagnostic_message(), - InterpErrorKind::InvalidProgram(e) => e.diagnostic_message(), - InterpErrorKind::ResourceExhaustion(e) => e.diagnostic_message(), - InterpErrorKind::MachineStop(e) => e.diagnostic_message(), - } - } - fn add_args(self, diag: &mut Diag<'_, G>) { - match self { - InterpErrorKind::UndefinedBehavior(ub) => ub.add_args(diag), - InterpErrorKind::Unsupported(e) => e.add_args(diag), - InterpErrorKind::InvalidProgram(e) => e.add_args(diag), - InterpErrorKind::ResourceExhaustion(e) => e.add_args(diag), - InterpErrorKind::MachineStop(e) => e.add_args(&mut |name, value| { - diag.arg(name, value); - }), - } - } -} - -impl<'tcx> ReportErrorExt for InvalidProgramInfo<'tcx> { - fn diagnostic_message(&self) -> DiagMessage { - match self { - InvalidProgramInfo::TooGeneric => "encountered overly generic constant".into(), - InvalidProgramInfo::AlreadyReported(_) => { - "an error has already been reported elsewhere (this should not usually be printed)" - .into() - } - InvalidProgramInfo::Layout(e) => e.diagnostic_message(), - } - } - fn add_args(self, diag: &mut Diag<'_, G>) { - match self { - InvalidProgramInfo::TooGeneric | InvalidProgramInfo::AlreadyReported(_) => {} - InvalidProgramInfo::Layout(e) => { - // The level doesn't matter, `dummy_diag` is consumed without it being used. - let dummy_level = Level::Bug; - let dummy_diag: Diag<'_, ()> = e.into_diagnostic().into_diag(diag.dcx, dummy_level); - for (name, val) in dummy_diag.args.iter() { - diag.arg(name.clone(), val.clone()); - } - dummy_diag.cancel(); - } - } - } -} - -impl ReportErrorExt for ResourceExhaustionInfo { - fn diagnostic_message(&self) -> DiagMessage { - match self { - ResourceExhaustionInfo::StackFrameLimitReached => { - "reached the configured maximum number of stack frames" - } - ResourceExhaustionInfo::MemoryExhausted => { - "tried to allocate more memory than available to compiler" - } - ResourceExhaustionInfo::AddressSpaceFull => { - "there are no more free addresses in the address space" - } - ResourceExhaustionInfo::Interrupted => "compilation was interrupted", - } - .into() - } - fn add_args(self, _: &mut Diag<'_, G>) {} -} - impl rustc_errors::IntoDiagArg for InternKind { fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::Str(Cow::Borrowed(match self { diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs index b207244349d8f..0381571ef6dae 100644 --- a/compiler/rustc_const_eval/src/interpret/call.rs +++ b/compiler/rustc_const_eval/src/interpret/call.rs @@ -6,7 +6,6 @@ use std::borrow::Cow; use either::{Left, Right}; use rustc_abi::{self as abi, ExternAbi, FieldIdx, Integer, VariantIdx}; -use rustc_errors::msg; use rustc_hir::def_id::DefId; use rustc_hir::find_attr; use rustc_middle::ty::layout::{IntegerExt, TyAndLayout}; @@ -19,7 +18,7 @@ use tracing::{info, instrument, trace}; use super::{ CtfeProvenance, FnVal, ImmTy, InterpCx, InterpResult, MPlaceTy, Machine, OpTy, PlaceTy, Projectable, Provenance, ReturnAction, ReturnContinuation, Scalar, interp_ok, throw_ub, - throw_ub_custom, + throw_ub_format, }; use crate::enter_trace_span; use crate::interpret::EnteredTraceSpan; @@ -293,7 +292,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } // Find next caller arg. let Some((caller_arg, caller_abi)) = caller_args.next() else { - throw_ub_custom!(msg!("calling a function with fewer arguments than it requires")); + throw_ub_format!("calling a function with fewer arguments than it requires"); }; assert_eq!(caller_arg.layout().layout, caller_abi.layout.layout); // Sadly we cannot assert that `caller_arg.layout().ty` and `caller_abi.layout.ty` are @@ -364,12 +363,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let callee_fn_abi = self.fn_abi_of_instance_no_deduced_attrs(instance, extra_tys)?; if caller_fn_abi.conv != callee_fn_abi.conv { - throw_ub_custom!( - rustc_errors::msg!( - "calling a function with calling convention \"{$callee_conv}\" using calling convention \"{$caller_conv}\"" - ), - callee_conv = format!("{}", callee_fn_abi.conv), - caller_conv = format!("{}", caller_fn_abi.conv), + throw_ub_format!( + "calling a function with calling convention \"{callee_conv}\" using calling convention \"{caller_conv}\"", + callee_conv = callee_fn_abi.conv, + caller_conv = caller_fn_abi.conv, ) } @@ -544,7 +541,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { "mismatch between callee ABI and callee body arguments" ); if caller_args.next().is_some() { - throw_ub_custom!(msg!("calling a function with more arguments than it expected")); + throw_ub_format!("calling a function with more arguments than it expected"); } // Don't forget to check the return type! if !self.check_argument_compat(&caller_fn_abi.ret, &callee_fn_abi.ret)? { @@ -744,9 +741,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let vtable_entries = self.vtable_entries(receiver_trait.principal(), dyn_ty); let Some(ty::VtblEntry::Method(fn_inst)) = vtable_entries.get(idx).copied() else { // FIXME(fee1-dead) these could be variants of the UB info enum instead of this - throw_ub_custom!(msg!( - "`dyn` call trying to call something that is not a method" - )); + throw_ub_format!("`dyn` call trying to call something that is not a method"); }; trace!("Virtual call dispatches to {fn_inst:#?}"); // We can also do the lookup based on `def_id` and `dyn_ty`, and check that that @@ -952,7 +947,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } ); if unwinding && self.frame_idx() == 0 { - throw_ub_custom!(msg!("unwinding past the topmost frame of the stack")); + throw_ub_format!("unwinding past the topmost frame of the stack"); } // Get out the return value. Must happen *before* the frame is popped as we have to get the diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index 6972a79226f33..faef782534280 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -3,7 +3,6 @@ use std::assert_matches; use rustc_abi::{FieldIdx, Integer}; use rustc_apfloat::ieee::{Double, Half, Quad, Single}; use rustc_apfloat::{Float, FloatConvert}; -use rustc_errors::msg; use rustc_middle::mir::CastKind; use rustc_middle::mir::interpret::{InterpResult, PointerArithmetic, Scalar}; use rustc_middle::ty::adjustment::PointerCoercion; @@ -15,7 +14,7 @@ use tracing::trace; use super::util::ensure_monomorphic_enough; use super::{ FnVal, ImmTy, Immediate, InterpCx, Machine, OpTy, PlaceTy, err_inval, interp_ok, throw_ub, - throw_ub_custom, + throw_ub_format, }; use crate::enter_trace_span; use crate::interpret::Writeable; @@ -139,10 +138,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { assert!(dest.layout.is_sized()); assert_eq!(cast_ty, dest.layout.ty); // we otherwise ignore `cast_ty` enirely... if src.layout.size != dest.layout.size { - throw_ub_custom!( - msg!( - "transmuting from {$src_bytes}-byte type to {$dest_bytes}-byte type: `{$src}` -> `{$dest}`" - ), + throw_ub_format!( + "transmuting from {src_bytes}-byte type to {dest_bytes}-byte type: `{src}` -> `{dest}`", src_bytes = src.layout.size.bytes(), dest_bytes = dest.layout.size.bytes(), src = src.layout.ty, diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 956be147d7486..0bfe012bfe7a4 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -2,7 +2,6 @@ use std::debug_assert_matches; use either::{Left, Right}; use rustc_abi::{Align, HasDataLayout, Size, TargetDataLayout}; -use rustc_errors::{DiagCtxtHandle, format_diag_message, msg}; use rustc_hir::def_id::DefId; use rustc_hir::limit::Limit; use rustc_middle::mir::interpret::{ErrorHandled, InvalidMetaKind, ReportedErrorInfo}; @@ -22,9 +21,9 @@ use tracing::{debug, trace}; use super::{ Frame, FrameInfo, GlobalId, InterpErrorInfo, InterpErrorKind, InterpResult, MPlaceTy, Machine, MemPlaceMeta, Memory, OpTy, Place, PlaceTy, PointerArithmetic, Projectable, Provenance, - err_inval, interp_ok, throw_inval, throw_ub, throw_ub_custom, + err_inval, interp_ok, throw_inval, throw_ub, throw_ub_format, }; -use crate::{ReportErrorExt, enter_trace_span, util}; +use crate::{enter_trace_span, util}; pub struct InterpCx<'tcx, M: Machine<'tcx>> { /// Stores the `Machine` instance. @@ -228,17 +227,10 @@ pub(super) fn from_known_layout<'tcx>( /// /// This is NOT the preferred way to render an error; use `report` from `const_eval` instead. /// However, this is useful when error messages appear in ICEs. -pub fn format_interp_error<'tcx>(dcx: DiagCtxtHandle<'_>, e: InterpErrorInfo<'tcx>) -> String { +pub fn format_interp_error<'tcx>(e: InterpErrorInfo<'tcx>) -> String { let (e, backtrace) = e.into_parts(); backtrace.print_backtrace(); - // FIXME(fee1-dead), HACK: we want to use the error as title therefore we can just extract the - // label and arguments from the InterpError. - let mut diag = dcx.struct_allow(""); - let msg = e.diagnostic_message(); - e.add_args(&mut diag); - let msg = format_diag_message(&msg, &diag.args).into_owned(); - diag.cancel(); - msg + e.to_string() } impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { @@ -556,9 +548,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { mir::UnwindAction::Cleanup(block) => Left(mir::Location { block, statement_index: 0 }), mir::UnwindAction::Continue => Right(self.frame_mut().body.span), mir::UnwindAction::Unreachable => { - throw_ub_custom!(msg!( - "unwinding past a stack frame that does not allow unwinding" - )); + throw_ub_format!("unwinding past a stack frame that does not allow unwinding"); } mir::UnwindAction::Terminate(reason) => { self.frame_mut().loc = Right(self.frame_mut().body.span); diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index c9106d691f7ce..7f7c69adf4f84 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -8,7 +8,6 @@ use std::assert_matches; use rustc_abi::{FieldIdx, HasDataLayout, Size, VariantIdx}; use rustc_apfloat::ieee::{Double, Half, Quad, Single}; -use rustc_errors::msg; use rustc_middle::mir::interpret::{CTFE_ALLOC_SALT, read_target_uint, write_target_uint}; use rustc_middle::mir::{self, BinOp, ConstValue, NonDivergingIntrinsic}; use rustc_middle::ty::layout::TyAndLayout; @@ -21,8 +20,8 @@ use super::memory::MemoryKind; use super::util::ensure_monomorphic_enough; use super::{ AllocId, CheckInAllocMsg, ImmTy, InterpCx, InterpResult, Machine, OpTy, PlaceTy, Pointer, - PointerArithmetic, Projectable, Provenance, Scalar, err_ub_custom, err_unsup_format, interp_ok, - throw_inval, throw_ub, throw_ub_custom, throw_ub_format, throw_unsup_format, + PointerArithmetic, Projectable, Provenance, Scalar, err_ub_format, err_unsup_format, interp_ok, + throw_inval, throw_ub, throw_ub_format, throw_unsup_format, }; use crate::interpret::Writeable; @@ -402,10 +401,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } _ => { // Not into the same allocation -- this is UB. - throw_ub_custom!( - msg!( - "`{$name}` called on two different pointers that are not both derived from the same allocation" - ), + throw_ub_format!( + "`{name}` called on two different pointers that are not both derived from the same allocation", name = intrinsic_name, ); } @@ -425,16 +422,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { if overflowed.to_bool()? { // a < b if intrinsic_name == sym::ptr_offset_from_unsigned { - throw_ub_custom!( - msg!( - "`ptr_offset_from_unsigned` called when first pointer has smaller {$is_addr -> - [true] address - *[false] offset - } than second: {$a_offset} < {$b_offset}" - ), + throw_ub_format!( + "`ptr_offset_from_unsigned` called when first pointer has smaller {is_addr} than second: {a_offset} < {b_offset}", a_offset = a_offset, b_offset = b_offset, - is_addr = is_addr, + is_addr = if is_addr { "address" } else { "offset" }, ); } // The signed form of the intrinsic allows this. If we interpret the @@ -442,11 +434,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // seems *positive* or equal to isize::MIN, they were more than isize::MAX apart. let dist = val.to_target_isize(self)?; if dist >= 0 || i128::from(dist) == self.pointer_size().signed_int_min() { - throw_ub_custom!( - msg!( - "`{$name}` called when first pointer is too far before second" - ), - name = intrinsic_name, + throw_ub_format!( + "`{intrinsic_name}` called when first pointer is too far before second" ); } dist @@ -456,11 +445,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // If converting to isize produced a *negative* result, we had an overflow // because they were more than isize::MAX apart. if dist < 0 { - throw_ub_custom!( - msg!( - "`{$name}` called when first pointer is too far ahead of second" - ), - name = intrinsic_name, + throw_ub_format!( + "`{intrinsic_name}` called when first pointer is too far ahead of second" ); } dist @@ -477,14 +463,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { && let Ok((b_alloc_id, ..)) = self.ptr_try_get_alloc_id(b, 0) && a_alloc_id == b_alloc_id { - err_ub_custom!( - msg!("`{$name}` called on two different pointers where the memory range between them is not in-bounds of an allocation"), - name = intrinsic_name, + err_ub_format!( + "`{intrinsic_name}` called on two different pointers where the memory range between them is not in-bounds of an allocation" ) } else { - err_ub_custom!( - msg!("`{$name}` called on two different pointers that are not both derived from the same allocation"), - name = intrinsic_name, + err_ub_format!( + "`{intrinsic_name}` called on two different pointers that are not both derived from the same allocation" ) } })?; @@ -497,9 +481,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ) .map_err_kind(|_| { // Make the error more specific. - err_ub_custom!( - msg!("`{$name}` called on two different pointers that are not both derived from the same allocation"), - name = intrinsic_name, + err_ub_format!( + "`{intrinsic_name}` called on two different pointers that are not both derived from the same allocation" ) })?; @@ -779,7 +762,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let op = self.eval_operand(op, None)?; let cond = self.read_scalar(&op)?.to_bool()?; if !cond { - throw_ub_custom!(msg!("`assume` called with `false`")); + throw_ub_format!("`assume` called with `false`"); } interp_ok(()) } @@ -809,7 +792,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let bits_out = match name { sym::ctpop => u128::from(bits.count_ones()), sym::ctlz_nonzero | sym::cttz_nonzero if bits == 0 => { - throw_ub_custom!(msg!("`{$name}` called on 0"), name = name,); + throw_ub_format!("`{name}` called on 0"); } sym::ctlz | sym::ctlz_nonzero => u128::from(bits.leading_zeros()) - extra, sym::cttz | sym::cttz_nonzero => u128::from((bits << extra).trailing_zeros()) - extra, @@ -841,11 +824,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let rem = self.binary_op(BinOp::Rem, a, b)?; // sign does not matter for 0 test, so `to_bits` is fine if rem.to_scalar().to_bits(a.layout.size)? != 0 { - throw_ub_custom!( - msg!("exact_div: {$a} cannot be divided by {$b} without remainder"), - a = format!("{a}"), - b = format!("{b}") - ) + throw_ub_format!("exact_div: {a} cannot be divided by {b} without remainder") } // `Rem` says this is all right, so we can let `Div` do its job. let res = self.binary_op(BinOp::Div, a, b)?; @@ -926,8 +905,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let (size, align) = (layout.size, layout.align.abi); let size = self.compute_size_in_bytes(size, count).ok_or_else(|| { - err_ub_custom!( - msg!("overflow computing total size of `{$name}`"), + err_ub_format!( + "overflow computing total size of `{name}`", name = if nonoverlapping { "copy_nonoverlapping" } else { "copy" } ) })?; @@ -990,9 +969,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // `checked_mul` enforces a too small bound (the correct one would probably be target_isize_max), // but no actual allocation can be big enough for the difference to be noticeable. - let len = self.compute_size_in_bytes(layout.size, count).ok_or_else(|| { - err_ub_custom!(msg!("overflow computing total size of `{$name}`"), name = name) - })?; + let len = self + .compute_size_in_bytes(layout.size, count) + .ok_or_else(|| err_ub_format!("overflow computing total size of `{name}`"))?; let bytes = std::iter::repeat_n(byte, len.bytes_usize()); self.write_bytes_ptr(dst, bytes) diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 8a864f372b9c3..214d653d23c13 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -14,17 +14,16 @@ use std::{assert_matches, fmt, ptr}; use rustc_abi::{Align, HasDataLayout, Size}; use rustc_ast::Mutability; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; -use rustc_errors::msg; +use rustc_middle::bug; use rustc_middle::mir::display_allocation; use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; -use rustc_middle::{bug, throw_ub_format}; use tracing::{debug, instrument, trace}; use super::{ AllocBytes, AllocId, AllocInit, AllocMap, AllocRange, Allocation, CheckAlignMsg, CheckInAllocMsg, CtfeProvenance, GlobalAlloc, InterpCx, InterpResult, MPlaceTy, Machine, MayLeak, Misalignment, Pointer, PointerArithmetic, Provenance, Scalar, alloc_range, err_ub, - err_ub_custom, interp_ok, throw_ub, throw_ub_custom, throw_unsup, throw_unsup_format, + err_ub_format, interp_ok, throw_ub, throw_ub_format, throw_unsup, throw_unsup_format, }; use crate::const_eval::ConstEvalErrKind; @@ -310,16 +309,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ) -> InterpResult<'tcx, Pointer> { let (alloc_id, offset, _prov) = self.ptr_get_alloc_id(ptr, 0)?; if offset.bytes() != 0 { - throw_ub_custom!( - msg!( - "{$kind -> - [dealloc] deallocating - [realloc] reallocating - *[other] {\"\"} - } {$ptr} which does not point to the beginning of an object" - ), - ptr = format!("{ptr:?}"), - kind = "realloc" + throw_ub_format!( + "reallocating {ptr} which does not point to the beginning of an object" ); } @@ -393,19 +384,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { kind: MemoryKind, ) -> InterpResult<'tcx> { let (alloc_id, offset, prov) = self.ptr_get_alloc_id(ptr, 0)?; - trace!("deallocating: {alloc_id:?}"); + trace!("deallocating: {alloc_id}"); if offset.bytes() != 0 { - throw_ub_custom!( - msg!( - "{$kind -> - [dealloc] deallocating - [realloc] reallocating - *[other] {\"\"} - } {$ptr} which does not point to the beginning of an object" - ), - ptr = format!("{ptr:?}"), - kind = "dealloc", + throw_ub_format!( + "deallocating {ptr} which does not point to the beginning of an object" ); } @@ -413,60 +396,16 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // Deallocating global memory -- always an error return Err(match self.tcx.try_get_global_alloc(alloc_id) { Some(GlobalAlloc::Function { .. }) => { - err_ub_custom!( - msg!( - "deallocating {$alloc_id}, which is {$kind -> - [fn] a function - [vtable] a vtable - [static_mem] static memory - *[other] {\"\"} - }" - ), - alloc_id = alloc_id, - kind = "fn", - ) + err_ub_format!("deallocating {alloc_id}, which is a function") } Some(GlobalAlloc::VTable(..)) => { - err_ub_custom!( - msg!( - "deallocating {$alloc_id}, which is {$kind -> - [fn] a function - [vtable] a vtable - [static_mem] static memory - *[other] {\"\"} - }" - ), - alloc_id = alloc_id, - kind = "vtable", - ) + err_ub_format!("deallocating {alloc_id}, which is a vtable") } Some(GlobalAlloc::TypeId { .. }) => { - err_ub_custom!( - msg!( - "deallocating {$alloc_id}, which is {$kind -> - [fn] a function - [vtable] a vtable - [static_mem] static memory - *[other] {\"\"} - }" - ), - alloc_id = alloc_id, - kind = "typeid", - ) + err_ub_format!("deallocating {alloc_id}, which is a type id") } Some(GlobalAlloc::Static(..) | GlobalAlloc::Memory(..)) => { - err_ub_custom!( - msg!( - "deallocating {$alloc_id}, which is {$kind -> - [fn] a function - [vtable] a vtable - [static_mem] static memory - *[other] {\"\"} - }" - ), - alloc_id = alloc_id, - kind = "static_mem" - ) + err_ub_format!("deallocating {alloc_id}, which is static memory") } None => err_ub!(PointerUseAfterFree(alloc_id, CheckInAllocMsg::MemoryAccess)), }) @@ -474,25 +413,17 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { }; if alloc.mutability.is_not() { - throw_ub_custom!(msg!("deallocating immutable allocation {$alloc}"), alloc = alloc_id,); + throw_ub_format!("deallocating immutable allocation {alloc_id}"); } if alloc_kind != kind { - throw_ub_custom!( - msg!( - "deallocating {$alloc}, which is {$alloc_kind} memory, using {$kind} deallocation operation" - ), - alloc = alloc_id, - alloc_kind = format!("{alloc_kind}"), - kind = format!("{kind}"), + throw_ub_format!( + "deallocating {alloc_id}, which is {alloc_kind} memory, using {kind} deallocation operation", ); } if let Some((size, align)) = old_size_and_align { if size != alloc.size() || align != alloc.align { - throw_ub_custom!( - msg!( - "incorrect layout on deallocation: {$alloc} has size {$size} and alignment {$align}, but gave size {$size_found} and alignment {$align_found}" - ), - alloc = alloc_id, + throw_ub_format!( + "incorrect layout on deallocation: {alloc_id} has size {size} and alignment {align}, but gave size {size_found} and alignment {align_found}", size = alloc.size().bytes(), align = alloc.align.bytes(), size_found = size.bytes(), @@ -1653,9 +1584,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { if (src_offset <= dest_offset && src_offset + size > dest_offset) || (dest_offset <= src_offset && dest_offset + size > src_offset) { - throw_ub_custom!(msg!( - "`copy_nonoverlapping` called on overlapping ranges" - )); + throw_ub_format!("`copy_nonoverlapping` called on overlapping ranges"); } } } diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 677bbf5d41e61..41a4cb2f23a1c 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -5,7 +5,7 @@ //! to be const-safe. use std::borrow::Cow; -use std::fmt::Write; +use std::fmt::{self, Write}; use std::hash::Hash; use std::mem; use std::num::NonZero; @@ -20,10 +20,9 @@ use rustc_ast::Mutability; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_middle::bug; -use rustc_middle::mir::interpret::ValidationErrorKind::{self, *}; use rustc_middle::mir::interpret::{ - ExpectedKind, InterpErrorKind, InvalidMetaKind, Misalignment, PointerKind, Provenance, - UnsupportedOpInfo, ValidationErrorInfo, alloc_range, interp_ok, + InterpErrorKind, InvalidMetaKind, Misalignment, Provenance, UnsupportedOpInfo, alloc_range, + interp_ok, }; use rustc_middle::ty::layout::{LayoutCx, TyAndLayout}; use rustc_middle::ty::{self, Ty}; @@ -46,7 +45,7 @@ use super::UndefinedBehaviorInfo::*; use super::UnsupportedOpInfo::*; macro_rules! err_validation_failure { - ($where:expr, $kind: expr) => {{ + ($where:expr, $msg:expr ) => {{ let where_ = &$where; let path = if !where_.is_empty() { let mut path = String::new(); @@ -56,13 +55,20 @@ macro_rules! err_validation_failure { None }; - err_ub!(ValidationError(ValidationErrorInfo { path, kind: $kind })) + #[allow(unused)] + use ValidationErrorKind::*; + let msg = ValidationErrorKind::from($msg); + err_ub!(ValidationError { + path, + ptr_bytes_warning: msg.ptr_bytes_warning(), + msg: msg.to_string(), + }) }}; } macro_rules! throw_validation_failure { - ($where:expr, $kind: expr) => { - do yeet err_validation_failure!($where, $kind) + ($where:expr, $msg:expr ) => { + do yeet err_validation_failure!($where, $msg) }; } @@ -73,32 +79,15 @@ macro_rules! throw_validation_failure { /// can possibly happen: /// /// ```ignore(illustrative) -/// let v = try_validation!(some_fn(), some_path, { -/// Foo | Bar | Baz => { "some failure" }, +/// let v = try_validation!(some_fn(x), some_path, { +/// Foo | Bar | Baz => format!("some failure involving {x}"), /// }); /// ``` /// /// The patterns must be of type `UndefinedBehaviorInfo`. -/// An additional expected parameter can also be added to the failure message: -/// -/// ```ignore(illustrative) -/// let v = try_validation!(some_fn(), some_path, { -/// Foo | Bar | Baz => { "some failure" } expected { "something that wasn't a failure" }, -/// }); -/// ``` -/// -/// An additional nicety is that both parameters actually take format args, so you can just write -/// the format string in directly: -/// -/// ```ignore(illustrative) -/// let v = try_validation!(some_fn(), some_path, { -/// Foo | Bar | Baz => { "{:?}", some_failure } expected { "{}", expected_value }, -/// }); -/// ``` -/// macro_rules! try_validation { ($e:expr, $where:expr, - $( $( $p:pat_param )|+ => $kind: expr ),+ $(,)? + $( $( $p:pat_param )|+ => $msg:expr ),+ $(,)? ) => {{ $e.map_err_kind(|e| { // We catch the error and turn it into a validation failure. We are okay with @@ -108,7 +97,7 @@ macro_rules! try_validation { $($p)|+ => { err_validation_failure!( $where, - $kind + $msg ) } ),+, @@ -118,6 +107,130 @@ macro_rules! try_validation { }}; } +#[derive(Debug, Clone, Copy)] +enum PointerKind { + Ref(Mutability), + Box, +} + +impl fmt::Display for PointerKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let str = match self { + PointerKind::Ref(_) => "reference", + PointerKind::Box => "box", + }; + write!(f, "{str}") + } +} + +#[derive(Debug)] +enum ExpectedKind { + Reference, + Box, + RawPtr, + InitScalar, + Bool, + Char, + Float, + Int, + FnPtr, + Str, +} + +impl fmt::Display for ExpectedKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let str = match self { + ExpectedKind::Reference => "expected a reference", + ExpectedKind::Box => "expected a box", + ExpectedKind::RawPtr => "expected a raw pointer", + ExpectedKind::InitScalar => "expected initialized scalar value", + ExpectedKind::Bool => "expected a boolean", + ExpectedKind::Char => "expected a unicode scalar value", + ExpectedKind::Float => "expected a floating point number", + ExpectedKind::Int => "expected an integer", + ExpectedKind::FnPtr => "expected a function pointer", + ExpectedKind::Str => "expected a string", + }; + write!(f, "{str}") + } +} + +impl From for ExpectedKind { + fn from(x: PointerKind) -> ExpectedKind { + match x { + PointerKind::Box => ExpectedKind::Box, + PointerKind::Ref(_) => ExpectedKind::Reference, + } + } +} + +/// Validation errors that can be emitted in one than one place get a variant here so that +/// we format them consistently. Everything else uses the `String` fallback. +#[derive(Debug)] +enum ValidationErrorKind<'tcx> { + Uninit { + expected: ExpectedKind, + }, + PointerAsInt { + expected: ExpectedKind, + }, + PartialPointer, + InvalidMetaWrongTrait { + /// The vtable that was actually referenced by the wide pointer metadata. + vtable_dyn_type: &'tcx ty::List>, + /// The vtable that was expected at the point in MIR that it was accessed. + expected_dyn_type: &'tcx ty::List>, + }, + GeneralError { + msg: String, + }, +} + +impl<'tcx> ValidationErrorKind<'tcx> { + // We don't do this via `fmt::Display` to so that we can do a move in the `GeneralError` case. + fn to_string(self) -> String { + use ValidationErrorKind::*; + match self { + Uninit { expected } => format!("encountered uninitialized memory, but {expected}"), + PointerAsInt { expected } => format!("encountered a pointer, but {expected}"), + PartialPointer => format!("encountered a partial pointer or a mix of pointers"), + InvalidMetaWrongTrait { vtable_dyn_type, expected_dyn_type } => format!( + "wrong trait in wide pointer vtable: expected `{expected_dyn_type}`, but encountered `{vtable_dyn_type}`" + ), + GeneralError { msg } => msg, + } + } + + fn ptr_bytes_warning(&self) -> bool { + use ValidationErrorKind::*; + matches!(self, PointerAsInt { .. } | PartialPointer) + } +} + +impl<'tcx> From for ValidationErrorKind<'tcx> { + fn from(msg: String) -> Self { + ValidationErrorKind::GeneralError { msg } + } +} + +fn fmt_range(r: WrappingRange, max_hi: u128) -> String { + let WrappingRange { start: lo, end: hi } = r; + assert!(hi <= max_hi); + if lo > hi { + format!("less or equal to {hi}, or greater or equal to {lo}") + } else if lo == hi { + format!("equal to {lo}") + } else if lo == 0 { + assert!(hi < max_hi, "should not be printing if the range covers everything"); + format!("less or equal to {hi}") + } else if hi == max_hi { + assert!(lo > 0, "should not be printing if the range covers everything"); + format!("greater or equal to {lo}") + } else { + format!("in the range {lo}..={hi}") + } +} + /// We want to show a nice path to the invalid field for diagnostics, /// but avoid string operations in the happy case where no error happens. /// So we track a `Vec` where `PathElem` contains all the data we @@ -193,7 +306,6 @@ impl RefTracking } } -// FIXME make this translatable as well? /// Format a path fn write_path(out: &mut String, path: &[PathElem]) { use self::PathElem::*; @@ -459,10 +571,9 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { self.ecx.get_ptr_vtable_ty(vtable, Some(data)), self.path, Ub(DanglingIntPointer{ .. } | InvalidVTablePointer(..)) => - InvalidVTablePtr { value: format!("{vtable}") }, - Ub(InvalidVTableTrait { vtable_dyn_type, expected_dyn_type }) => { - InvalidMetaWrongTrait { vtable_dyn_type, expected_dyn_type } - }, + format!("encountered {vtable}, but expected a vtable pointer"), + Ub(InvalidVTableTrait { vtable_dyn_type, expected_dyn_type }) => + InvalidMetaWrongTrait { expected_dyn_type, vtable_dyn_type }, ); } ty::Slice(..) | ty::Str => { @@ -497,10 +608,13 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { let size_and_align = try_validation!( self.ecx.size_and_align_of_val(&place), self.path, - Ub(InvalidMeta(msg)) => match msg { - InvalidMetaKind::SliceTooBig => InvalidMetaSliceTooLarge { ptr_kind }, - InvalidMetaKind::TooBig => InvalidMetaTooLarge { ptr_kind }, - } + Ub(InvalidMeta(msg)) => format!( + "encountered invalid {ptr_kind} metadata: {}", + match msg { + InvalidMetaKind::SliceTooBig => "slice is bigger than largest supported object", + InvalidMetaKind::TooBig => "total size is bigger than largest supported object", + } + ) ); let (size, align) = size_and_align // for the purpose of validity, consider foreign types to have @@ -508,11 +622,8 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { // alignment should take attributes into account). .unwrap_or_else(|| (place.layout.size, place.layout.align.abi)); + // If we're not allow to dangle, make sure this is dereferenceable. if !self.may_dangle { - // Make sure this is dereferenceable and all. - - // Direct call to `check_ptr_access_align` checks alignment even on CTFE machines. - // Call `check_ptr_access` to avoid checking alignment here. try_validation!( self.ecx.check_ptr_access( place.ptr(), @@ -520,31 +631,31 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { CheckInAllocMsg::Dereferenceable, // will anyway be replaced by validity message ), self.path, - Ub(DanglingIntPointer { addr: 0, .. }) => NullPtr { ptr_kind, maybe: false }, - Ub(DanglingIntPointer { addr: i, .. }) => DanglingPtrNoProvenance { - ptr_kind, - pointer: format!("{}", Pointer::>::without_provenance(i)) - }, - Ub(PointerOutOfBounds { .. }) => DanglingPtrOutOfBounds { - ptr_kind - }, - Ub(PointerUseAfterFree(..)) => DanglingPtrUseAfterFree { - ptr_kind, - }, + Ub(DanglingIntPointer { addr: 0, .. }) => + format!("encountered a null {ptr_kind}"), + Ub(DanglingIntPointer { addr: i, .. }) => + format!( + "encountered a dangling {ptr_kind} ({ptr} has no provenance)", + ptr = Pointer::>::without_provenance(i) + ), + Ub(PointerOutOfBounds { .. }) => + format!("encountered a dangling {ptr_kind} (going beyond the bounds of its allocation)"), + Ub(PointerUseAfterFree(..)) => + format!("encountered a dangling {ptr_kind} (use-after-free)"), ); } - + // Check alignment after dereferenceable (if both are violated, trigger the error above). try_validation!( self.ecx.check_ptr_align( place.ptr(), align, ), self.path, - Ub(AlignmentCheckFailed(Misalignment { required, has }, _msg)) => UnalignedPtr { - ptr_kind, - required_bytes: required.bytes(), - found_bytes: has.bytes() - }, + Ub(AlignmentCheckFailed(Misalignment { required, has }, _msg)) => format!( + "encountered an unaligned {ptr_kind} (required {required_bytes} byte alignment but found {found_bytes})", + required_bytes = required.bytes(), + found_bytes = has.bytes() + ), ); // Make sure this is non-null. This is obviously needed when `may_dangle` is set, @@ -553,12 +664,21 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { let scalar = Scalar::from_maybe_pointer(place.ptr(), self.ecx); if self.ecx.scalar_may_be_null(scalar)? { let maybe = !M::Provenance::OFFSET_IS_ADDR && matches!(scalar, Scalar::Ptr(..)); - throw_validation_failure!(self.path, NullPtr { ptr_kind, maybe }) + throw_validation_failure!( + self.path, + format!( + "encountered a {maybe}null {ptr_kind}", + maybe = if maybe { "maybe-" } else { "" } + ) + ) } // Do not allow references to uninhabited types. if place.layout.is_uninhabited() { let ty = place.layout.ty; - throw_validation_failure!(self.path, PtrToUninhabited { ptr_kind, ty }) + throw_validation_failure!( + self.path, + format!("encountered a {ptr_kind} pointing to uninhabited type {ty}") + ) } // Recursive checking if let Some(ref_tracking) = self.ref_tracking.as_deref_mut() { @@ -586,7 +706,10 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { // though for zero-sized references this isn't really UB. // A potential future alternative would be to resurrect this as a zero-sized allocation // (which codegen will then compile to an aligned dummy pointer anyway). - throw_validation_failure!(self.path, DanglingPtrUseAfterFree { ptr_kind }); + throw_validation_failure!( + self.path, + format!("encountered a dangling {ptr_kind} (use-after-free)") + ); }; let (size, _align) = global_alloc.size_and_align(*self.ecx.tcx, self.ecx.typing_env); @@ -649,7 +772,12 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { && alloc_actual_mutbl == Mutability::Not { // This can actually occur with transmutes. - throw_validation_failure!(self.path, MutableRefToImmutable); + throw_validation_failure!( + self.path, + format!( + "encountered mutable reference or box pointing to read-only memory" + ) + ); } } } @@ -692,9 +820,8 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { try_validation!( scalar.to_bool(), self.path, - Ub(InvalidBool(..)) => ValidationErrorKind::InvalidBool { - value: format!("{scalar:x}"), - } + Ub(InvalidBool(..)) => + format!("encountered {scalar:x}, but expected a boolean"), ); if self.reset_provenance_and_padding { self.ecx.clear_provenance(value)?; @@ -707,9 +834,9 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { try_validation!( scalar.to_char(), self.path, - Ub(InvalidChar(..)) => ValidationErrorKind::InvalidChar { - value: format!("{scalar:x}"), - } + Ub(InvalidChar(..)) => + format!("encountered {scalar:x}, but expected a valid unicode scalar value \ + (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)") ); if self.reset_provenance_and_padding { self.ecx.clear_provenance(value)?; @@ -755,7 +882,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { self.ecx.get_ptr_fn(ptr), self.path, Ub(DanglingIntPointer{ .. } | InvalidFunctionPointer(..)) => - InvalidFnPtr { value: format!("{ptr}") }, + format!("encountered {ptr}, but expected a function pointer"), ); // FIXME: Check if the signature matches } else { @@ -764,7 +891,13 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { if self.ecx.scalar_may_be_null(scalar)? { let maybe = !M::Provenance::OFFSET_IS_ADDR && matches!(scalar, Scalar::Ptr(..)); - throw_validation_failure!(self.path, NullFnPtr { maybe }); + throw_validation_failure!( + self.path, + format!( + "encountered a {maybe}null function pointer", + maybe = if maybe { "maybe-" } else { "" } + ) + ); } } if self.reset_provenance_and_padding { @@ -777,7 +910,12 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { } interp_ok(true) } - ty::Never => throw_validation_failure!(self.path, NeverVal), + ty::Never => { + throw_validation_failure!( + self.path, + format!("encountered a value of the never type `!`") + ) + } ty::Foreign(..) | ty::FnDef(..) => { // Nothing to check. interp_ok(true) @@ -826,7 +964,12 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { if start == 1 && end == max_value { // Only null is the niche. So make sure the ptr is NOT null. if self.ecx.scalar_may_be_null(scalar)? { - throw_validation_failure!(self.path, NonnullPtrMaybeNull) + throw_validation_failure!( + self.path, + format!( + "encountered a maybe-null pointer, but expected something that is definitely non-zero" + ) + ) } else { return interp_ok(()); } @@ -834,11 +977,13 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { // Easy. (This is reachable if `enforce_number_validity` is set.) return interp_ok(()); } else { - // Conservatively, we reject, because the pointer *could* have a bad - // value. + // Conservatively, we reject, because the pointer *could* have a bad value. throw_validation_failure!( self.path, - PtrOutOfRange { range: valid_range, max_value } + format!( + "encountered a pointer with unknown absolute address, but expected something that is definitely {in_range}", + in_range = fmt_range(valid_range, max_value) + ) ) } } @@ -849,7 +994,10 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { } else { throw_validation_failure!( self.path, - OutOfRange { value: format!("{bits}"), range: valid_range, max_value } + format!( + "encountered {bits}, but expected something {in_range}", + in_range = fmt_range(valid_range, max_value) + ) ) } } @@ -1054,10 +1202,10 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, interp_ok(try_validation!( this.ecx.read_discriminant(val), this.path, - Ub(InvalidTag(val)) => InvalidEnumTag { - value: format!("{val:x}"), - }, - Ub(UninhabitedEnumVariantRead(_)) => UninhabitedEnumVariant, + Ub(InvalidTag(val)) => + format!("encountered {val:x}, but expected a valid enum tag"), + Ub(UninhabitedEnumVariantRead(_)) => + format!("encountered an uninhabited enum variant"), // Uninit / bad provenance are not possible since the field was already previously // checked at its integer type. )) @@ -1104,7 +1252,10 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, let zst = self.ecx.size_and_align_of_val(val)?.is_some_and(|(s, _a)| s.bytes() == 0); if !zst && !val.layout.ty.is_freeze(*self.ecx.tcx, self.ecx.typing_env) { if !self.in_mutable_memory(val) { - throw_validation_failure!(self.path, UnsafeCellInImmutable); + throw_validation_failure!( + self.path, + format!("encountered `UnsafeCell` in read-only memory") + ); } } } @@ -1154,7 +1305,10 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, && def.is_unsafe_cell() { if !self.in_mutable_memory(val) { - throw_validation_failure!(self.path, UnsafeCellInImmutable); + throw_validation_failure!( + self.path, + format!("encountered `UnsafeCell` in read-only memory") + ); } } } @@ -1164,11 +1318,14 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, ty::Str => { let mplace = val.assert_mem_place(); // strings are unsized and hence never immediate let len = mplace.len(self.ecx)?; + let expected = ExpectedKind::Str; try_validation!( self.ecx.read_bytes_ptr_strip_provenance(mplace.ptr(), Size::from_bytes(len)), self.path, - Ub(InvalidUninitBytes(..)) => Uninit { expected: ExpectedKind::Str }, - Unsup(ReadPointerAsInt(_)) => PointerAsInt { expected: ExpectedKind::Str } + Ub(InvalidUninitBytes(..)) => + Uninit { expected }, + Unsup(ReadPointerAsInt(_)) => + PointerAsInt { expected }, ); } ty::Array(tys, ..) | ty::Slice(tys) @@ -1199,7 +1356,10 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, Left(mplace) => mplace, Right(imm) => match *imm { Immediate::Uninit => - throw_validation_failure!(self.path, Uninit { expected }), + throw_validation_failure!( + self.path, + Uninit { expected } + ), Immediate::Scalar(..) | Immediate::ScalarPair(..) => bug!("arrays/slices can never have Scalar/ScalarPair layout"), } @@ -1229,7 +1389,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, if matches!(kind, Ub(InvalidUninitBytes(_))) { err_validation_failure!(self.path, Uninit { expected }) } else { - err_validation_failure!(self.path, PointerAsInt { expected }) + err_validation_failure!(self.path, PointerAsInt {expected}) } } @@ -1292,9 +1452,8 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, self.path, // It's not great to catch errors here, since we can't give a very good path, // but it's better than ICEing. - Ub(InvalidVTableTrait { vtable_dyn_type, expected_dyn_type }) => { - InvalidMetaWrongTrait { vtable_dyn_type, expected_dyn_type } - }, + Ub(InvalidVTableTrait { vtable_dyn_type, expected_dyn_type }) => + InvalidMetaWrongTrait { expected_dyn_type, vtable_dyn_type }, ); } } @@ -1310,7 +1469,10 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, // MyNewtype and then the scalar in there). if val.layout.is_uninhabited() { let ty = val.layout.ty; - throw_validation_failure!(self.path, UninhabitedVal { ty }); + throw_validation_failure!( + self.path, + format!("encountered a value of uninhabited type `{ty}`") + ); } match val.layout.backend_repr { BackendRepr::Scalar(scalar_layout) => { @@ -1383,10 +1545,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { | InterpErrorKind::InvalidProgram(_) | InterpErrorKind::Unsupported(UnsupportedOpInfo::ExternTypeField) ) { - bug!( - "Unexpected error during validation: {}", - format_interp_error(self.tcx.dcx(), err) - ); + bug!("Unexpected error during validation: {}", format_interp_error(err)); } err }) diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index ade6f1c094754..a9fff6d593261 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -22,8 +22,6 @@ use std::sync::atomic::AtomicBool; use rustc_middle::ty; use rustc_middle::util::Providers; -pub use self::errors::ReportErrorExt; - pub fn provide(providers: &mut Providers) { const_eval::provide(&mut providers.queries); providers.queries.tag_for_variant = const_eval::tag_for_variant_provider; diff --git a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs index 384d7858366de..00835a3cc990a 100644 --- a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs +++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs @@ -2,6 +2,7 @@ use rustc_abi::{BackendRepr, FieldsShape, Scalar, Variants}; use rustc_middle::ty::layout::{ HasTyCtxt, LayoutCx, LayoutError, LayoutOf, TyAndLayout, ValidityRequirement, }; +use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{PseudoCanonicalInput, ScalarInt, Ty, TyCtxt}; use rustc_middle::{bug, ty}; use rustc_span::DUMMY_SP; @@ -70,13 +71,19 @@ fn check_validity_requirement_strict<'tcx>( // due to this. // The value we are validating is temporary and discarded at the end of this function, so // there is no point in resetting provenance and padding. - cx.validate_operand( - &allocated.into(), - /*recursive*/ false, - /*reset_provenance_and_padding*/ false, + // This is pretty inefficient: we do the full path tracking and even format an error message + // in case there is a problem, only to entirely throw that away again. For a nightly-only + // option this is fine, but if this is ever meant to be stable we should probably add + // a "fast mode" to validation. + with_no_trimmed_paths!( + cx.validate_operand( + &allocated.into(), + /*recursive*/ false, + /*reset_provenance_and_padding*/ false, + ) + .discard_err() + .is_some() ) - .discard_err() - .is_some() } /// Implements the 'lax' (default) version of the [`check_validity_requirement`] checks; see that diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index 42c605d34814f..e50cbbbf06e0b 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -59,15 +59,10 @@ impl Diagnostic<'_, G> for TargetDataLayoutErrors<'_> { } TargetDataLayoutErrors::InvalidAlignment { cause, err } => { Diag::new(dcx, level, msg!( - "invalid alignment for `{$cause}` in \"data-layout\": `{$align}` is {$err_kind -> - [not_power_of_two] not a power of 2 - [too_large] too large - *[other] {\"\"} - }" + "invalid alignment for `{$cause}` in \"data-layout\": {$err}" )) .with_arg("cause", cause) - .with_arg("err_kind", err.diag_ident()) - .with_arg("align", err.align()) + .with_arg("err", err.to_string()) } TargetDataLayoutErrors::InconsistentTargetArchitecture { dl, target } => { Diag::new(dcx, level, msg!( diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index a96eceb6c715d..9b3dba15f55e2 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -371,8 +371,6 @@ pub enum StashKey { MaybeFruTypo, CallAssocMethod, AssociatedTypeSuggestion, - /// Query cycle detected, stashing in favor of a better error. - Cycle, UndeterminedMacroResolution, /// Used by `Parser::maybe_recover_trailing_expr` ExprInPat, diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 1f5eed25029b9..32cfa3003eebe 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -24,7 +24,6 @@ use rustc_middle::ty::{ TypeVisitable, TypeVisitableExt, fold_regions, }; use rustc_session::lint::builtin::UNINHABITED_STATIC; -use rustc_span::Spanned; use rustc_target::spec::{AbiMap, AbiMapping}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::traits; @@ -216,7 +215,7 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) { // SIMD types with invalid layout (e.g., zero-length) should emit an error Err(e @ LayoutError::InvalidSimd { .. }) => { let ty_span = tcx.ty_span(def_id); - tcx.dcx().emit_err(Spanned { span: ty_span, node: e.into_diagnostic() }); + tcx.dcx().span_err(ty_span, e.to_string()); return; } // Generic statics are rejected, but we still reach this case. diff --git a/compiler/rustc_hir_analysis/src/check/compare_eii.rs b/compiler/rustc_hir_analysis/src/check/compare_eii.rs index 9443aaac2258f..29213058d1d5e 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_eii.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_eii.rs @@ -9,6 +9,7 @@ use std::iter; use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{Applicability, E0806, struct_span_code_err}; use rustc_hir::attrs::EiiImplResolution; +use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::{self as hir, FnSig, HirId, ItemKind, find_attr}; use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt}; @@ -37,6 +38,14 @@ pub(crate) fn compare_eii_function_types<'tcx>( eii_name: Symbol, eii_attr_span: Span, ) -> Result<(), ErrorGuaranteed> { + // Error recovery can resolve the EII target to another value item with the same name, + // such as a tuple-struct constructor. Skip the comparison in that case and rely on the + // earlier name-resolution error instead of ICEing while building EII diagnostics. + // See . + if !is_foreign_function(tcx, foreign_item) { + return Ok(()); + } + check_is_structurally_compatible(tcx, external_impl, foreign_item, eii_name, eii_attr_span)?; let external_impl_span = tcx.def_span(external_impl); @@ -442,3 +451,7 @@ fn get_declaration_sig<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Option<&' let hir_id: HirId = tcx.local_def_id_to_hir_id(def_id); tcx.hir_fn_sig_by_hir_id(hir_id) } + +fn is_foreign_function(tcx: TyCtxt<'_>, def_id: DefId) -> bool { + tcx.is_foreign_item(def_id) && matches!(tcx.def_kind(def_id), DefKind::Fn) +} diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 23df419d06a70..f2ae5c1f928d0 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -4,7 +4,6 @@ use rustc_errors::{Applicability, StashKey, Suggestions}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::VisitorExt; use rustc_hir::{self as hir, AmbigArg, HirId}; -use rustc_middle::query::plumbing::CyclePlaceholder; use rustc_middle::ty::print::with_forced_trimmed_paths; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{self, DefiningScopeKind, IsSuggestable, Ty, TyCtxt, TypeVisitableExt}; @@ -183,10 +182,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_ } }, - Node::OpaqueTy(..) => tcx.type_of_opaque(def_id).map_or_else( - |CyclePlaceholder(guar)| Ty::new_error(tcx, guar), - |ty| ty.instantiate_identity(), - ), + Node::OpaqueTy(..) => tcx.type_of_opaque(def_id).instantiate_identity(), Node::ForeignItem(foreign_item) => match foreign_item.kind { ForeignItemKind::Fn(..) => { @@ -249,12 +245,9 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_ } } -pub(super) fn type_of_opaque( - tcx: TyCtxt<'_>, - def_id: DefId, -) -> Result>, CyclePlaceholder> { +pub(super) fn type_of_opaque(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<'_, Ty<'_>> { if let Some(def_id) = def_id.as_local() { - Ok(match tcx.hir_node_by_def_id(def_id).expect_opaque_ty().origin { + match tcx.hir_node_by_def_id(def_id).expect_opaque_ty().origin { hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: false, .. } => { opaque::find_opaque_ty_constraints_for_tait( tcx, @@ -287,11 +280,11 @@ pub(super) fn type_of_opaque( DefiningScopeKind::MirBorrowck, ) } - }) + } } else { // Foreign opaque type will go through the foreign provider // and load the type from metadata. - Ok(tcx.type_of(def_id)) + tcx.type_of(def_id) } } diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index 05a28c48f8063..ed5951fe1c034 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -144,7 +144,6 @@ struct QueryModifiers { arena_cache: Option, cache_on_disk_if: Option, cycle_delay_bug: Option, - cycle_stash: Option, depth_limit: Option, desc: Desc, eval_always: Option, @@ -159,7 +158,6 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result { let mut cache_on_disk_if = None; let mut desc = None; let mut cycle_delay_bug = None; - let mut cycle_stash = None; let mut no_hash = None; let mut anon = None; let mut eval_always = None; @@ -195,8 +193,6 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result { try_insert!(arena_cache = modifier); } else if modifier == "cycle_delay_bug" { try_insert!(cycle_delay_bug = modifier); - } else if modifier == "cycle_stash" { - try_insert!(cycle_stash = modifier); } else if modifier == "no_hash" { try_insert!(no_hash = modifier); } else if modifier == "anon" { @@ -221,7 +217,6 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result { cache_on_disk_if, desc, cycle_delay_bug, - cycle_stash, no_hash, anon, eval_always, @@ -257,7 +252,6 @@ fn make_modifiers_stream(query: &Query) -> proc_macro2::TokenStream { arena_cache, cache_on_disk_if, cycle_delay_bug, - cycle_stash, depth_limit, desc: _, eval_always, @@ -273,8 +267,6 @@ fn make_modifiers_stream(query: &Query) -> proc_macro2::TokenStream { let cycle_error_handling = if cycle_delay_bug.is_some() { quote! { DelayBug } - } else if cycle_stash.is_some() { - quote! { Stash } } else { quote! { Error } }; @@ -411,7 +403,6 @@ fn add_to_analyzer_stream(query: &Query, analyzer_stream: &mut proc_macro2::Toke doc_link!( arena_cache, cycle_delay_bug, - cycle_stash, no_hash, anon, eval_always, diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs index dfb99fb98513d..44ac747726a61 100644 --- a/compiler/rustc_middle/src/error.rs +++ b/compiler/rustc_middle/src/error.rs @@ -1,8 +1,7 @@ +use std::io; use std::path::Path; -use std::{fmt, io}; use rustc_errors::codes::*; -use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{Span, Symbol}; @@ -114,56 +113,6 @@ pub(super) struct ConstNotUsedTraitAlias { pub span: Span, } -pub struct CustomSubdiagnostic<'a> { - pub msg: fn() -> DiagMessage, - pub add_args: Box, -} - -impl<'a> CustomSubdiagnostic<'a> { - pub fn label(x: fn() -> DiagMessage) -> Self { - Self::label_and_then(x, |_| {}) - } - pub fn label_and_then( - msg: fn() -> DiagMessage, - f: F, - ) -> Self { - Self { msg, add_args: Box::new(move |x| f(x)) } - } -} - -impl fmt::Debug for CustomSubdiagnostic<'_> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("CustomSubdiagnostic").finish_non_exhaustive() - } -} - -#[derive(Diagnostic)] -pub enum LayoutError<'tcx> { - #[diag("the type `{$ty}` has an unknown layout")] - Unknown { ty: Ty<'tcx> }, - - #[diag("the type `{$ty}` does not have a fixed layout")] - TooGeneric { ty: Ty<'tcx> }, - - #[diag("values of the type `{$ty}` are too big for the target architecture")] - Overflow { ty: Ty<'tcx> }, - - #[diag("the SIMD type `{$ty}` has more elements than the limit {$max_lanes}")] - SimdTooManyLanes { ty: Ty<'tcx>, max_lanes: u64 }, - - #[diag("the SIMD type `{$ty}` has zero elements")] - SimdZeroLength { ty: Ty<'tcx> }, - - #[diag("unable to determine layout for `{$ty}` because `{$failure_ty}` cannot be normalized")] - NormalizationFailure { ty: Ty<'tcx>, failure_ty: String }, - - #[diag("a cycle occurred during layout computation")] - Cycle, - - #[diag("the type has an unknown layout")] - ReferencesError, -} - #[derive(Diagnostic)] #[diag("erroneous constant encountered")] pub(crate) struct ErroneousConstant { diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 7fa818ba7d3ae..c0dfc18689ba8 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -341,13 +341,13 @@ impl AllocError { } /// The information that makes up a memory access: offset and size. -#[derive(Copy, Clone)] +#[derive(Debug, Copy, Clone)] pub struct AllocRange { pub start: Size, pub size: Size, } -impl fmt::Debug for AllocRange { +impl fmt::Display for AllocRange { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "[{:#x}..{:#x}]", self.start.bytes(), self.end().bytes()) } diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 035ffd362a6bb..2c3d114a0f25e 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -4,9 +4,9 @@ use std::borrow::Cow; use std::{convert, fmt, mem, ops}; use either::Either; -use rustc_abi::{Align, Size, VariantIdx, WrappingRange}; +use rustc_abi::{Align, Size, VariantIdx}; use rustc_data_structures::sync::Lock; -use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage, ErrorGuaranteed, IntoDiagArg}; +use rustc_errors::{DiagArgValue, ErrorGuaranteed, IntoDiagArg}; use rustc_macros::{HashStable, TyDecodable, TyEncodable}; use rustc_session::CtfeBacktrace; use rustc_span::def_id::DefId; @@ -14,8 +14,9 @@ use rustc_span::{DUMMY_SP, Span, Symbol}; use super::{AllocId, AllocRange, ConstAllocation, Pointer, Scalar}; use crate::error; +use crate::mir::interpret::CtfeProvenance; use crate::mir::{ConstAlloc, ConstValue}; -use crate::ty::{self, Mutability, Ty, TyCtxt, ValTree, layout, tls}; +use crate::ty::{self, Ty, TyCtxt, ValTree, layout, tls}; #[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)] pub enum ErrorHandled { @@ -240,20 +241,6 @@ impl<'tcx> From> for InterpErrorInfo<'tcx> { } } -/// Error information for when the program we executed turned out not to actually be a valid -/// program. This cannot happen in stand-alone Miri (except for layout errors that are only detect -/// during monomorphization), but it can happen during CTFE/ConstProp where we work on generic code -/// or execution does not have all information available. -#[derive(Debug)] -pub enum InvalidProgramInfo<'tcx> { - /// Resolution can fail if we are in a too generic context. - TooGeneric, - /// Abort in case errors are already reported. - AlreadyReported(ReportedErrorInfo), - /// An error occurred during layout computation. - Layout(layout::LayoutError<'tcx>), -} - /// Details of why a pointer had to be in-bounds. #[derive(Debug, Copy, Clone)] pub enum CheckInAllocMsg { @@ -265,6 +252,17 @@ pub enum CheckInAllocMsg { Dereferenceable, } +impl fmt::Display for CheckInAllocMsg { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + use CheckInAllocMsg::*; + match self { + MemoryAccess => write!(f, "memory access failed"), + InboundsPointerArithmetic => write!(f, "in-bounds pointer arithmetic failed"), + Dereferenceable => write!(f, "pointer not dereferenceable"), + } + } +} + /// Details of which pointer is not aligned. #[derive(Debug, Copy, Clone)] pub enum CheckAlignMsg { @@ -314,34 +312,13 @@ pub struct Misalignment { pub required: Align, } -macro_rules! impl_into_diag_arg_through_debug { - ($($ty:ty),*$(,)?) => {$( - impl IntoDiagArg for $ty { - fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { - DiagArgValue::Str(Cow::Owned(format!("{self:?}"))) - } - } - )*} -} - -// These types have nice `Debug` output so we can just use them in diagnostics. -impl_into_diag_arg_through_debug! { - AllocId, - Pointer, - AllocRange, -} - /// Error information for when the program caused Undefined Behavior. #[derive(Debug)] pub enum UndefinedBehaviorInfo<'tcx> { /// Free-form case. Only for errors that are never caught! Used by miri Ub(String), - // FIXME(fee1-dead) these should all be actual variants of the enum instead of dynamically - // dispatched - /// A custom (free-form) fluent-translated error, created by `err_ub_custom!`. - Custom(crate::error::CustomSubdiagnostic<'tcx>), /// Validation error. - ValidationError(ValidationErrorInfo<'tcx>), + ValidationError { path: Option, msg: String, ptr_bytes_warning: bool }, /// Unreachable code was executed. Unreachable, @@ -446,137 +423,259 @@ pub enum UndefinedBehaviorInfo<'tcx> { CVariadicFixedCountMismatch { caller: u32, callee: u32 }, } -#[derive(Debug, Clone, Copy)] -pub enum PointerKind { - Ref(Mutability), - Box, -} +impl<'tcx> fmt::Display for UndefinedBehaviorInfo<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + use UndefinedBehaviorInfo::*; -impl IntoDiagArg for PointerKind { - fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { - DiagArgValue::Str( - match self { - Self::Ref(_) => "ref", - Self::Box => "box", + fn fmt_in_alloc_attempt( + f: &mut fmt::Formatter<'_>, + msg: CheckInAllocMsg, + inbounds_size: i64, + ) -> fmt::Result { + let inbounds_size_fmt = if inbounds_size == 1 { + format_args!("1 byte") + } else { + format_args!("{inbounds_size} bytes") + }; + write!(f, "{msg}: ")?; + match msg { + CheckInAllocMsg::MemoryAccess => { + write!(f, "attempting to access {inbounds_size_fmt}") + } + CheckInAllocMsg::InboundsPointerArithmetic => { + write!(f, "attempting to offset pointer by {inbounds_size_fmt}") + } + CheckInAllocMsg::Dereferenceable if inbounds_size == 0 => { + write!(f, "pointer must point to some allocation") + } + CheckInAllocMsg::Dereferenceable => { + write!(f, "pointer must be dereferenceable for {inbounds_size_fmt}") + } } - .into(), - ) + } + + match self { + Ub(msg) => write!(f, "{msg}"), + + ValidationError { path: None, msg, .. } => { + write!(f, "constructing invalid value: {msg}") + } + ValidationError { path: Some(path), msg, .. } => { + write!(f, "constructing invalid value at {path}: {msg}") + } + + Unreachable => write!(f, "entering unreachable code"), + BoundsCheckFailed { len, index } => { + write!(f, "indexing out of bounds: the len is {len} but the index is {index}") + } + DivisionByZero => write!(f, "dividing by zero"), + RemainderByZero => write!(f, "calculating the remainder with a divisor of zero"), + DivisionOverflow => write!(f, "overflow in signed division (dividing MIN by -1)"), + RemainderOverflow => write!(f, "overflow in signed remainder (dividing MIN by -1)"), + PointerArithOverflow => write!( + f, + "overflowing pointer arithmetic: the total offset in bytes does not fit in an `isize`" + ), + ArithOverflow { intrinsic } => write!(f, "arithmetic overflow in `{intrinsic}`"), + ShiftOverflow { shift_amount, intrinsic } => { + write!(f, "overflowing shift by {shift_amount} in `{intrinsic}`") + } + InvalidMeta(InvalidMetaKind::SliceTooBig) => write!( + f, + "invalid metadata in wide pointer: slice is bigger than largest supported object" + ), + InvalidMeta(InvalidMetaKind::TooBig) => write!( + f, + "invalid metadata in wide pointer: total size is bigger than largest supported object" + ), + UnterminatedCString(ptr) => write!( + f, + "reading a null-terminated string starting at {ptr} with no null found before end of allocation" + ), + PointerUseAfterFree(alloc_id, msg) => { + write!(f, "{msg}: {alloc_id} has been freed, so this pointer is dangling") + } + &PointerOutOfBounds { alloc_id, alloc_size, ptr_offset, inbounds_size, msg } => { + fmt_in_alloc_attempt(f, msg, inbounds_size)?; + write!(f, ", but got ")?; + // Write pointer. Offset might be negative so we cannot use the normal `impl Display + // for Pointer`. + write!(f, "{}", alloc_id)?; + if ptr_offset > 0 { + write!(f, "+{:#x}", ptr_offset)?; + } else if ptr_offset < 0 { + write!(f, "-{:#x}", ptr_offset.unsigned_abs())?; + } + // Write why it is invalid. + write!(f, " which ")?; + if ptr_offset < 0 { + write!(f, "points to before the beginning of the allocation") + } else if inbounds_size < 0 { + // We expected the ptr to have memory to its left, but it does not. + if ptr_offset == 0 { + write!(f, "is at the beginning of the allocation") + } else { + write!(f, "is only {ptr_offset} bytes from the beginning of the allocation") + } + } else { + let ptr_offset = ptr_offset as u64; + let alloc_size = alloc_size.bytes(); + if ptr_offset >= alloc_size { + let size = if alloc_size == 1 { + format_args!("1 byte") + } else { + format_args!("{alloc_size} bytes") + }; + write!(f, "is at or beyond the end of the allocation of size {size}",) + } else { + let dist_to_end = alloc_size - ptr_offset; + let dist = if dist_to_end == 1 { + format_args!("1 byte") + } else { + format_args!("{dist_to_end} bytes") + }; + write!(f, "is only {dist} from the end of the allocation",) + } + } + } + &DanglingIntPointer { addr: 0, inbounds_size, msg } => { + fmt_in_alloc_attempt(f, msg, inbounds_size)?; + write!(f, ", but got null pointer") + } + &DanglingIntPointer { addr, inbounds_size, msg } => { + fmt_in_alloc_attempt(f, msg, inbounds_size)?; + write!( + f, + ", but got {ptr} which is a dangling pointer (it has no provenance)", + ptr = Pointer::>::without_provenance(addr), + ) + } + AlignmentCheckFailed(misalign, msg) => { + write!( + f, + "{acc} with alignment {has}, but alignment {required} is required", + acc = match msg { + CheckAlignMsg::AccessedPtr => "accessing memory", + CheckAlignMsg::BasedOn => "accessing memory based on pointer", + }, + has = misalign.has.bytes(), + required = misalign.required.bytes(), + ) + } + WriteToReadOnly(alloc) => write!(f, "writing to {alloc} which is read-only"), + DerefFunctionPointer(alloc) => { + write!(f, "accessing {alloc} which contains a function") + } + DerefVTablePointer(alloc) => write!(f, "accessing {alloc} which contains a vtable"), + DerefVaListPointer(alloc) => { + write!(f, "accessing {alloc} which contains a variable argument list") + } + DerefTypeIdPointer(alloc) => write!(f, "accessing {alloc} which contains a `TypeId`"), + InvalidBool(value) => { + write!(f, "interpreting an invalid 8-bit value as a bool: 0x{value:02x}") + } + InvalidChar(value) => { + write!(f, "interpreting an invalid 32-bit value as a char: 0x{value:08x}") + } + InvalidTag(tag) => write!(f, "enum value has invalid tag: {tag:x}"), + InvalidFunctionPointer(ptr) => { + write!(f, "using {ptr} as function pointer but it does not point to a function") + } + InvalidVaListPointer(ptr) => write!( + f, + "using {ptr} as variable argument list pointer but it does not point to a variable argument list" + ), + InvalidVTablePointer(ptr) => { + write!(f, "using {ptr} as vtable pointer but it does not point to a vtable") + } + InvalidVTableTrait { vtable_dyn_type, expected_dyn_type } => write!( + f, + "using vtable for `{vtable_dyn_type}` but `{expected_dyn_type}` was expected" + ), + InvalidStr(err) => write!(f, "this string is not valid UTF-8: {err}"), + InvalidUninitBytes(None) => { + write!( + f, + "using uninitialized data, but this operation requires initialized memory" + ) + } + InvalidUninitBytes(Some((alloc, info))) => write!( + f, + "reading memory at {alloc}{access}, but memory is uninitialized at {uninit}, and this operation requires initialized memory", + access = info.access, + uninit = info.bad, + ), + DeadLocal => write!(f, "accessing a dead local variable"), + ScalarSizeMismatch(mismatch) => write!( + f, + "scalar size mismatch: expected {target_size} bytes but got {data_size} bytes instead", + target_size = mismatch.target_size, + data_size = mismatch.data_size, + ), + UninhabitedEnumVariantWritten(_) => { + write!(f, "writing discriminant of an uninhabited enum variant") + } + UninhabitedEnumVariantRead(_) => { + write!(f, "read discriminant of an uninhabited enum variant") + } + InvalidNichedEnumVariantWritten { enum_ty } => { + write!( + f, + "trying to set discriminant of a {enum_ty} to the niched variant, but the value does not match" + ) + } + AbiMismatchArgument { arg_idx, caller_ty, callee_ty } => write!( + f, + "calling a function whose parameter #{arg_idx} has type {callee_ty} passing argument of type {caller_ty}", + arg_idx = arg_idx + 1, // adjust for 1-indexed lists in output + ), + AbiMismatchReturn { caller_ty, callee_ty } => write!( + f, + "calling a function with return type {callee_ty} passing return place of type {caller_ty}" + ), + VaArgOutOfBounds => write!(f, "more C-variadic arguments read than were passed"), + CVariadicMismatch { .. } => write!( + f, + "calling a function where the caller and callee disagree on whether the function is C-variadic" + ), + CVariadicFixedCountMismatch { caller, callee } => write!( + f, + "calling a C-variadic function with {caller} fixed arguments, but the function expects {callee}" + ), + } } } +/// Error information for when the program we executed turned out not to actually be a valid +/// program. This cannot happen in stand-alone Miri (except for layout errors that are only detect +/// during monomorphization), but it can happen during CTFE/ConstProp where we work on generic code +/// or execution does not have all information available. #[derive(Debug)] -pub struct ValidationErrorInfo<'tcx> { - pub path: Option, - pub kind: ValidationErrorKind<'tcx>, +pub enum InvalidProgramInfo<'tcx> { + /// Resolution can fail if we are in a too generic context. + TooGeneric, + /// Abort in case errors are already reported. + AlreadyReported(ReportedErrorInfo), + /// An error occurred during layout computation. + Layout(layout::LayoutError<'tcx>), } -#[derive(Debug)] -pub enum ExpectedKind { - Reference, - Box, - RawPtr, - InitScalar, - Bool, - Char, - Float, - Int, - FnPtr, - EnumTag, - Str, -} - -impl From for ExpectedKind { - fn from(x: PointerKind) -> ExpectedKind { - match x { - PointerKind::Box => ExpectedKind::Box, - PointerKind::Ref(_) => ExpectedKind::Reference, +impl<'tcx> fmt::Display for InvalidProgramInfo<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + use InvalidProgramInfo::*; + match self { + TooGeneric => write!(f, "encountered overly generic constant"), + AlreadyReported(_) => { + write!( + f, + "an error has already been reported elsewhere (this should not usually be printed)" + ) + } + Layout(e) => write!(f, "{e}"), } } } -#[derive(Debug)] -pub enum ValidationErrorKind<'tcx> { - PointerAsInt { - expected: ExpectedKind, - }, - PartialPointer, - PtrToUninhabited { - ptr_kind: PointerKind, - ty: Ty<'tcx>, - }, - MutableRefToImmutable, - UnsafeCellInImmutable, - NullFnPtr { - /// Records whether this pointer is definitely null or just may be null. - maybe: bool, - }, - NeverVal, - NonnullPtrMaybeNull, - PtrOutOfRange { - range: WrappingRange, - max_value: u128, - }, - OutOfRange { - value: String, - range: WrappingRange, - max_value: u128, - }, - UninhabitedVal { - ty: Ty<'tcx>, - }, - InvalidEnumTag { - value: String, - }, - UninhabitedEnumVariant, - Uninit { - expected: ExpectedKind, - }, - InvalidVTablePtr { - value: String, - }, - InvalidMetaWrongTrait { - /// The vtable that was actually referenced by the wide pointer metadata. - vtable_dyn_type: &'tcx ty::List>, - /// The vtable that was expected at the point in MIR that it was accessed. - expected_dyn_type: &'tcx ty::List>, - }, - InvalidMetaSliceTooLarge { - ptr_kind: PointerKind, - }, - InvalidMetaTooLarge { - ptr_kind: PointerKind, - }, - UnalignedPtr { - ptr_kind: PointerKind, - required_bytes: u64, - found_bytes: u64, - }, - NullPtr { - ptr_kind: PointerKind, - /// Records whether this pointer is definitely null or just may be null. - maybe: bool, - }, - DanglingPtrNoProvenance { - ptr_kind: PointerKind, - pointer: String, - }, - DanglingPtrOutOfBounds { - ptr_kind: PointerKind, - }, - DanglingPtrUseAfterFree { - ptr_kind: PointerKind, - }, - InvalidBool { - value: String, - }, - InvalidChar { - value: String, - }, - InvalidFnPtr { - value: String, - }, -} - /// Error information for when the program did something that might (or might not) be correct /// to do according to the Rust spec, but due to limitations in the interpreter, the /// operation could not be carried out. These limitations can differ between CTFE and the @@ -604,6 +703,37 @@ pub enum UnsupportedOpInfo { ExternStatic(DefId), } +impl fmt::Display for UnsupportedOpInfo { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + use UnsupportedOpInfo::*; + match self { + Unsupported(s) => write!(f, "{s}"), + ExternTypeField => { + write!(f, "`extern type` field does not have a known offset") + } + UnsizedLocal => write!(f, "unsized locals are not supported"), + ReadPartialPointer(ptr) => { + write!(f, "unable to read parts of a pointer from memory at {ptr}") + } + ReadPointerAsInt(_) => write!(f, "unable to turn pointer into integer"), + &ThreadLocalStatic(did) => { + write!( + f, + "cannot access thread local static `{did}`", + did = ty::tls::with(|tcx| tcx.def_path_str(did)) + ) + } + &ExternStatic(did) => { + write!( + f, + "cannot access extern static `{did}`", + did = ty::tls::with(|tcx| tcx.def_path_str(did)) + ) + } + } + } +} + /// Error information for when the program exhausted the resources granted to it /// by the interpreter. #[derive(Debug)] @@ -618,15 +748,27 @@ pub enum ResourceExhaustionInfo { Interrupted, } -/// A trait for machine-specific errors (or other "machine stop" conditions). -pub trait MachineStopType: Any + fmt::Debug + Send { - /// The diagnostic message for this error - fn diagnostic_message(&self) -> DiagMessage; - /// Add diagnostic arguments by passing name and value pairs to `adder`, which are passed to - /// fluent for formatting the translated diagnostic message. - fn add_args(self: Box, adder: &mut dyn FnMut(DiagArgName, DiagArgValue)); +impl fmt::Display for ResourceExhaustionInfo { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + use ResourceExhaustionInfo::*; + match self { + StackFrameLimitReached => { + write!(f, "reached the configured maximum number of stack frames") + } + MemoryExhausted => { + write!(f, "tried to allocate more memory than available to compiler") + } + AddressSpaceFull => { + write!(f, "there are no more free addresses in the address space") + } + Interrupted => write!(f, "compilation was interrupted"), + } + } } +/// A trait for machine-specific errors (or other "machine stop" conditions). +pub trait MachineStopType: Any + fmt::Display + fmt::Debug + Send {} + impl dyn MachineStopType { #[inline(always)] pub fn downcast_ref(&self) -> Option<&T> { @@ -639,11 +781,11 @@ impl dyn MachineStopType { pub enum InterpErrorKind<'tcx> { /// The program caused undefined behavior. UndefinedBehavior(UndefinedBehaviorInfo<'tcx>), + /// The program was invalid (ill-typed, bad MIR, not sufficiently monomorphized, ...). + InvalidProgram(InvalidProgramInfo<'tcx>), /// The program did something the interpreter does not support (some of these *might* be UB /// but the interpreter is not sure). Unsupported(UnsupportedOpInfo), - /// The program was invalid (ill-typed, bad MIR, not sufficiently monomorphized, ...). - InvalidProgram(InvalidProgramInfo<'tcx>), /// The program exhausted the interpreter's resources (stack/heap too big, /// execution takes too long, ...). ResourceExhaustion(ResourceExhaustionInfo), @@ -652,6 +794,19 @@ pub enum InterpErrorKind<'tcx> { MachineStop(Box), } +impl<'tcx> fmt::Display for InterpErrorKind<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + use InterpErrorKind::*; + match self { + Unsupported(msg) => write!(f, "{msg}"), + InvalidProgram(msg) => write!(f, "{msg}"), + UndefinedBehavior(msg) => write!(f, "{msg}"), + ResourceExhaustion(msg) => write!(f, "{msg}"), + MachineStop(msg) => write!(f, "{msg}"), + } + } +} + impl InterpErrorKind<'_> { /// Some errors do string formatting even if the error is never printed. /// To avoid performance issues, there are places where we want to be sure to never raise these formatting errors, @@ -704,25 +859,6 @@ macro_rules! err_ub_format { ($($tt:tt)*) => { $crate::err_ub!(Ub(format!($($tt)*))) }; } -#[macro_export] -macro_rules! err_ub_custom { - ($msg:expr $(, $($name:ident = $value:expr),* $(,)?)?) => {{ - $( - let ($($name,)*) = ($($value,)*); - )? - $crate::err_ub!(Custom( - $crate::error::CustomSubdiagnostic { - msg: || $msg, - add_args: Box::new(move |mut set_arg| { - $($( - set_arg(stringify!($name).into(), rustc_errors::IntoDiagArg::into_diag_arg($name, &mut None)); - )*)? - }) - } - )) - }}; -} - #[macro_export] macro_rules! err_exhaust { ($($tt:tt)*) => { @@ -765,11 +901,6 @@ macro_rules! throw_ub_format { ($($tt:tt)*) => { do yeet $crate::err_ub_format!($($tt)*) }; } -#[macro_export] -macro_rules! throw_ub_custom { - ($($tt:tt)*) => { do yeet $crate::err_ub_custom!($($tt)*) }; -} - #[macro_export] macro_rules! throw_exhaust { ($($tt:tt)*) => { do yeet $crate::err_exhaust!($($tt)*) }; diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index 654404f9790cb..b3ec4439e3541 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -24,9 +24,9 @@ use rustc_serialize::{Decodable, Encodable}; use tracing::{debug, trace}; // Also make the error macros available from this module. pub use { - err_exhaust, err_inval, err_machine_stop, err_ub, err_ub_custom, err_ub_format, err_unsup, - err_unsup_format, throw_exhaust, throw_inval, throw_machine_stop, throw_ub, throw_ub_custom, - throw_ub_format, throw_unsup, throw_unsup_format, + err_exhaust, err_inval, err_machine_stop, err_ub, err_ub_format, err_unsup, err_unsup_format, + throw_exhaust, throw_inval, throw_machine_stop, throw_ub, throw_ub_format, throw_unsup, + throw_unsup_format, }; pub use self::allocation::{ @@ -35,11 +35,10 @@ pub use self::allocation::{ }; pub use self::error::{ BadBytesAccess, CheckAlignMsg, CheckInAllocMsg, ErrorHandled, EvalStaticInitializerRawResult, - EvalToAllocationRawResult, EvalToConstValueResult, EvalToValTreeResult, ExpectedKind, - InterpErrorInfo, InterpErrorKind, InterpResult, InvalidMetaKind, InvalidProgramInfo, - MachineStopType, Misalignment, PointerKind, ReportedErrorInfo, ResourceExhaustionInfo, - ScalarSizeMismatch, UndefinedBehaviorInfo, UnsupportedOpInfo, ValTreeCreationError, - ValidationErrorInfo, ValidationErrorKind, interp_ok, + EvalToAllocationRawResult, EvalToConstValueResult, EvalToValTreeResult, InterpErrorInfo, + InterpErrorKind, InterpResult, InvalidMetaKind, InvalidProgramInfo, MachineStopType, + Misalignment, ReportedErrorInfo, ResourceExhaustionInfo, ScalarSizeMismatch, + UndefinedBehaviorInfo, UnsupportedOpInfo, ValTreeCreationError, interp_ok, }; pub use self::pointer::{CtfeProvenance, Pointer, PointerArithmetic, Provenance}; pub use self::value::Scalar; @@ -76,16 +75,22 @@ impl<'tcx> GlobalId<'tcx> { #[derive(Copy, Clone, Eq, Hash, Ord, PartialEq, PartialOrd)] pub struct AllocId(pub NonZero); +// AllocId show up in const-eval error messages +impl fmt::Display for AllocId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if f.alternate() { write!(f, "a{}", self.0) } else { write!(f, "alloc{}", self.0) } + } +} + // We want the `Debug` output to be readable as it is used by `derive(Debug)` for // all the Miri types. impl fmt::Debug for AllocId { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if f.alternate() { write!(f, "a{}", self.0) } else { write!(f, "alloc{}", self.0) } + // Dispatch to `Display` impl. + fmt::Display::fmt(self, f) } } -// No "Display" since AllocIds are not usually user-visible. - #[derive(TyDecodable, TyEncodable)] enum AllocDiscriminant { Alloc, diff --git a/compiler/rustc_middle/src/mir/interpret/pointer.rs b/compiler/rustc_middle/src/mir/interpret/pointer.rs index b6bcc87ff0413..e135404f28e7a 100644 --- a/compiler/rustc_middle/src/mir/interpret/pointer.rs +++ b/compiler/rustc_middle/src/mir/interpret/pointer.rs @@ -241,6 +241,12 @@ impl fmt::Debug for Pointer { } } +impl fmt::Display for Pointer { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + Provenance::fmt(self, f) + } +} + impl fmt::Debug for Pointer> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.provenance { diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 2dd205e8468da..b029112ed8a05 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -14,7 +14,7 @@ use rustc_abi::{FieldIdx, VariantIdx}; pub use rustc_ast::{Mutability, Pinnedness}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::graph::dominators::Dominators; -use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage, ErrorGuaranteed, IntoDiagArg}; +use rustc_errors::ErrorGuaranteed; use rustc_hir::def::{CtorKind, Namespace}; use rustc_hir::def_id::{CRATE_DEF_ID, DefId}; use rustc_hir::{ diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs index 48dcef298d66a..f66c4755de4dd 100644 --- a/compiler/rustc_middle/src/mir/statement.rs +++ b/compiler/rustc_middle/src/mir/statement.rs @@ -1050,11 +1050,12 @@ impl<'tcx> StmtDebugInfos<'tcx> { self.0.extend_from_slice(debuginfos); } - pub fn retain(&mut self, f: F) - where - F: FnMut(&StmtDebugInfo<'tcx>) -> bool, - { - self.0.retain(f); + pub fn retain_locals(&mut self, locals: &DenseBitSet) { + self.retain(|debuginfo| match debuginfo { + StmtDebugInfo::AssignRef(local, _) | StmtDebugInfo::InvalidAssign(local) => { + locals.contains(*local) + } + }); } } diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index 650c44aa41fbe..7931c80bed6c1 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -326,36 +326,42 @@ impl AssertKind { } } } +} - /// Format the diagnostic message for use in a lint (e.g. when the assertion fails during const-eval). - /// - /// Needs to be kept in sync with the run-time behavior (which is defined by - /// `AssertKind::panic_function` and the lang items mentioned in its docs). - /// Note that we deliberately show more details here than we do at runtime, such as the actual - /// numbers that overflowed -- it is much easier to do so here than at runtime. - pub fn diagnostic_message(&self) -> DiagMessage { +/// Format the diagnostic message for use in a lint (e.g. when the assertion fails during const-eval). +/// +/// Needs to be kept in sync with the run-time behavior (which is defined by +/// `AssertKind::panic_function` and the lang items mentioned in its docs). +/// Note that we deliberately show more details here than we do at runtime, such as the actual +/// numbers that overflowed -- it is much easier to do so here than at runtime. +impl fmt::Display for AssertKind { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { use AssertKind::*; match self { - BoundsCheck { .. } => { - msg!("index out of bounds: the length is {$len} but the index is {$index}") + BoundsCheck { len, index } => { + write!(f, "index out of bounds: the length is {len:?} but the index is {index:?}") } - Overflow(BinOp::Shl, _, _) => { - msg!("attempt to shift left by `{$val}`, which would overflow") + Overflow(BinOp::Shl, _, val) => { + write!(f, "attempt to shift left by `{val:#?}`, which would overflow") } - Overflow(BinOp::Shr, _, _) => { - msg!("attempt to shift right by `{$val}`, which would overflow") + Overflow(BinOp::Shr, _, val) => { + write!(f, "attempt to shift right by `{val:#?}`, which would overflow") } - Overflow(_, _, _) => { - msg!("attempt to compute `{$left} {$op} {$right}`, which would overflow") + Overflow(binop, left, right) => { + write!( + f, + "attempt to compute `{left:#?} {op} {right:#?}`, which would overflow", + op = binop.to_hir_binop().as_str() + ) } - OverflowNeg(_) => msg!("attempt to negate `{$val}`, which would overflow"), - DivisionByZero(_) => msg!("attempt to divide `{$val}` by zero"), - RemainderByZero(_) => { - msg!("attempt to calculate the remainder of `{$val}` with a divisor of zero") + OverflowNeg(val) => write!(f, "attempt to negate `{val:#?}`, which would overflow"), + DivisionByZero(val) => write!(f, "attempt to divide `{val:#?}` by zero"), + RemainderByZero(val) => { + write!(f, "attempt to calculate the remainder of `{val:#?}` with a divisor of zero") } ResumedAfterReturn(CoroutineKind::Desugared(CoroutineDesugaring::Async, _)) => { - msg!("`async fn` resumed after completion") + write!(f, "`async fn` resumed after completion") } ResumedAfterReturn(CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _)) => { todo!() @@ -364,84 +370,43 @@ impl AssertKind { bug!("gen blocks can be resumed after they return and will keep returning `None`") } ResumedAfterReturn(CoroutineKind::Coroutine(_)) => { - msg!("coroutine resumed after completion") + write!(f, "coroutine resumed after completion") } ResumedAfterPanic(CoroutineKind::Desugared(CoroutineDesugaring::Async, _)) => { - msg!("`async fn` resumed after panicking") + write!(f, "`async fn` resumed after panicking") } ResumedAfterPanic(CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _)) => { todo!() } ResumedAfterPanic(CoroutineKind::Desugared(CoroutineDesugaring::Gen, _)) => { - msg!("`gen` fn or block cannot be further iterated on after it panicked") + write!(f, "`gen` fn or block cannot be further iterated on after it panicked") } ResumedAfterPanic(CoroutineKind::Coroutine(_)) => { - msg!("coroutine resumed after panicking") + write!(f, "coroutine resumed after panicking") } - NullPointerDereference => msg!("null pointer dereference occurred"), - InvalidEnumConstruction(_) => { - msg!("trying to construct an enum from an invalid value `{$source}`") + NullPointerDereference => write!(f, "null pointer dereference occurred"), + InvalidEnumConstruction(source) => { + write!(f, "trying to construct an enum from an invalid value `{source:#?}`") } ResumedAfterDrop(CoroutineKind::Desugared(CoroutineDesugaring::Async, _)) => { - msg!("`async fn` resumed after async drop") + write!(f, "`async fn` resumed after async drop") } ResumedAfterDrop(CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _)) => { todo!() } ResumedAfterDrop(CoroutineKind::Desugared(CoroutineDesugaring::Gen, _)) => { - msg!("`gen` fn or block cannot be further iterated on after it async dropped") + write!(f, "`gen` fn or block cannot be further iterated on after it async dropped") } ResumedAfterDrop(CoroutineKind::Coroutine(_)) => { - msg!("coroutine resumed after async drop") + write!(f, "coroutine resumed after async drop") } - MisalignedPointerDereference { .. } => msg!( - "misaligned pointer dereference: address must be a multiple of {$required} but is {$found}" + MisalignedPointerDereference { required, found } => write!( + f, + "misaligned pointer dereference: address must be a multiple of {required:#?} but is {found:#?}" ), } } - - pub fn add_args(self, adder: &mut dyn FnMut(DiagArgName, DiagArgValue)) - where - O: fmt::Debug, - { - use AssertKind::*; - - macro_rules! add { - ($name: expr, $value: expr) => { - adder($name.into(), $value.into_diag_arg(&mut None)); - }; - } - - match self { - BoundsCheck { len, index } => { - add!("len", format!("{len:?}")); - add!("index", format!("{index:?}")); - } - Overflow(BinOp::Shl | BinOp::Shr, _, val) - | DivisionByZero(val) - | RemainderByZero(val) - | OverflowNeg(val) => { - add!("val", format!("{val:#?}")); - } - Overflow(binop, left, right) => { - add!("op", binop.to_hir_binop().as_str()); - add!("left", format!("{left:#?}")); - add!("right", format!("{right:#?}")); - } - ResumedAfterReturn(_) - | ResumedAfterPanic(_) - | NullPointerDereference - | ResumedAfterDrop(_) => {} - MisalignedPointerDereference { required, found } => { - add!("required", format!("{required:#?}")); - add!("found", format!("{found:#?}")); - } - InvalidEnumConstruction(source) => { - add!("source", format!("{source:#?}")); - } - } - } } #[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] @@ -510,7 +475,6 @@ impl<'tcx> TerminatorKind<'tcx> { } pub use helper::*; -use rustc_errors::msg; mod helper { use super::*; diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index c20a389f56b97..25ac06a6ed099 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -33,7 +33,6 @@ //! - `cache_on_disk_if { ... }`: Cache the query result to disk if the provided block evaluates to //! true. The query key identifier is available for use within the block, as is `tcx`. //! - `cycle_delay_bug`: If a dependency cycle is detected, emit a delayed bug instead of aborting immediately. -//! - `cycle_stash`: If a dependency cycle is detected, stash the error for later handling. //! - `no_hash`: Do not hash the query result for incremental compilation; just mark as dirty if recomputed. //! - `anon`: Make the query anonymous in the dependency graph (no dep node is created). //! - `eval_always`: Always evaluate the query, ignoring its dependencies and cached results. @@ -118,7 +117,6 @@ use crate::mir::mono::{ CodegenUnit, CollectionMode, MonoItem, MonoItemPartitions, NormalizationErrorInMono, }; use crate::query::describe_as_module; -use crate::query::plumbing::CyclePlaceholder; use crate::traits::query::{ CanonicalAliasGoal, CanonicalDropckOutlivesGoal, CanonicalImpliedOutlivesBoundsGoal, CanonicalMethodAutoderefStepsGoal, CanonicalPredicateGoal, CanonicalTypeOpAscribeUserTypeGoal, @@ -339,22 +337,16 @@ rustc_queries! { feedable } - /// Returns the *hidden type* of the opaque type given by `DefId` unless a cycle occurred. - /// - /// This is a specialized instance of [`Self::type_of`] that detects query cycles. - /// Unless `CyclePlaceholder` needs to be handled separately, call [`Self::type_of`] instead. - /// This is used to improve the error message in cases where revealing the hidden type - /// for auto-trait leakage cycles. + /// Returns the *hidden type* of the opaque type given by `DefId`. /// /// # Panics /// /// This query will panic if the given definition is not an opaque type. - query type_of_opaque(key: DefId) -> Result>, CyclePlaceholder> { + query type_of_opaque(key: DefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> { desc { "computing type of opaque `{path}`", path = tcx.def_path_str(key), } - cycle_stash } query type_of_opaque_hir_typeck(key: LocalDefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> { desc { diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index a02f6f89b9b90..fc96566b069a1 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -14,7 +14,6 @@ use rustc_span::{ErrorGuaranteed, Spanned}; use crate::mir::interpret::EvalToValTreeResult; use crate::mir::mono::{MonoItem, NormalizationErrorInMono}; -use crate::query::plumbing::CyclePlaceholder; use crate::traits::solve; use crate::ty::adjustment::CoerceUnsizedInfo; use crate::ty::{self, Ty, TyCtxt}; @@ -212,10 +211,6 @@ impl Erasable for Result<&'_ ty::List>, ty::util::AlwaysRequiresDrop> { [u8; size_of::>, ty::util::AlwaysRequiresDrop>>()]; } -impl Erasable for Result>, CyclePlaceholder> { - type Storage = [u8; size_of::>, CyclePlaceholder>>()]; -} - impl Erasable for Result<(&'_ [Spanned>], &'_ [Spanned>]), NormalizationErrorInMono> { diff --git a/compiler/rustc_middle/src/query/modifiers.rs b/compiler/rustc_middle/src/query/modifiers.rs index 2bc70dd588df7..eb9fc330a2316 100644 --- a/compiler/rustc_middle/src/query/modifiers.rs +++ b/compiler/rustc_middle/src/query/modifiers.rs @@ -28,11 +28,6 @@ pub(crate) struct cache_on_disk_if; /// A cycle error results in a delay_bug call pub(crate) struct cycle_delay_bug; -/// # `cycle_stash` query modifier -/// -/// A cycle error results in a stashed cycle error that can be unstashed and canceled later -pub(crate) struct cycle_stash; - /// # `depth_limit` query modifier /// /// Whether the query has a call depth limit diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index ad0b6f7c335ef..72330eab30d58 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -7,7 +7,6 @@ use rustc_data_structures::sharded::Sharded; use rustc_data_structures::sync::{AtomicU64, WorkerLocal}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::hir_id::OwnerId; -use rustc_macros::HashStable; use rustc_span::{ErrorGuaranteed, Span}; pub use sealed::IntoQueryParam; @@ -58,7 +57,6 @@ pub enum ActiveKeyStatus<'tcx> { pub enum CycleErrorHandling { Error, DelayBug, - Stash, } #[derive(Clone, Debug)] @@ -651,9 +649,6 @@ mod sealed { } } -#[derive(Copy, Clone, Debug, HashStable)] -pub struct CyclePlaceholder(pub ErrorGuaranteed); - #[cold] pub(crate) fn default_query(name: &str, key: &dyn std::fmt::Debug) -> ! { bug!( diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 2fca85c9f2f19..a940365b90088 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -633,10 +633,6 @@ pub enum SelectionError<'tcx> { NotConstEvaluatable(NotConstEvaluatable), /// Exceeded the recursion depth during type projection. Overflow(OverflowError), - /// Computing an opaque type's hidden type caused an error (e.g. a cycle error). - /// We can thus not know whether the hidden type implements an auto trait, so - /// we should not presume anything about it. - OpaqueTypeAutoTraitLeakageUnknown(DefId), /// Error for a `ConstArgHasType` goal ConstArgHasWrongType { ct: ty::Const<'tcx>, ct_ty: Ty<'tcx>, expected_ty: Ty<'tcx> }, } diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs index eaf67ae23ad26..180ccd9301c49 100644 --- a/compiler/rustc_middle/src/ty/consts/int.rs +++ b/compiler/rustc_middle/src/ty/consts/int.rs @@ -4,7 +4,6 @@ use std::num::NonZero; use rustc_abi::Size; use rustc_apfloat::Float; use rustc_apfloat::ieee::{Double, Half, Quad, Single}; -use rustc_errors::{DiagArgValue, IntoDiagArg}; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use crate::ty::TyCtxt; @@ -137,14 +136,6 @@ impl std::fmt::Debug for ConstInt { } } -impl IntoDiagArg for ConstInt { - // FIXME this simply uses the Debug impl, but we could probably do better by converting both - // to an inherent method that returns `Cow`. - fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { - DiagArgValue::Str(format!("{self:?}").into()) - } -} - /// The raw bytes of a simple value. /// /// This is a packed struct in order to allow this type to be optimally embedded in enums diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index fe8f8abf7f57f..4ca51c078bef5 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -7,9 +7,8 @@ use rustc_abi::{ PointerKind, Primitive, ReprFlags, ReprOptions, Scalar, Size, TagEncoding, TargetDataLayout, TyAbiInterface, VariantIdx, Variants, }; -use rustc_error_messages::DiagMessage; use rustc_errors::{ - Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, IntoDiagArg, Level, msg, + Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, IntoDiagArg, Level, }; use rustc_hir as hir; use rustc_hir::LangItem; @@ -265,53 +264,6 @@ pub enum LayoutError<'tcx> { Cycle(ErrorGuaranteed), } -impl<'tcx> LayoutError<'tcx> { - pub fn diagnostic_message(&self) -> DiagMessage { - use LayoutError::*; - - match self { - Unknown(_) => msg!("the type `{$ty}` has an unknown layout"), - SizeOverflow(_) => { - msg!("values of the type `{$ty}` are too big for the target architecture") - } - InvalidSimd { kind: SimdLayoutError::TooManyLanes(_), .. } => { - msg!("the SIMD type `{$ty}` has more elements than the limit {$max_lanes}") - } - InvalidSimd { kind: SimdLayoutError::ZeroLength, .. } => { - msg!("the SIMD type `{$ty}` has zero elements") - } - TooGeneric(_) => msg!("the type `{$ty}` does not have a fixed layout"), - NormalizationFailure(_, _) => msg!( - "unable to determine layout for `{$ty}` because `{$failure_ty}` cannot be normalized" - ), - Cycle(_) => msg!("a cycle occurred during layout computation"), - ReferencesError(_) => msg!("the type has an unknown layout"), - } - } - - pub fn into_diagnostic(self) -> crate::error::LayoutError<'tcx> { - use LayoutError::*; - - use crate::error::LayoutError as E; - match self { - Unknown(ty) => E::Unknown { ty }, - SizeOverflow(ty) => E::Overflow { ty }, - InvalidSimd { ty, kind: SimdLayoutError::TooManyLanes(max_lanes) } => { - E::SimdTooManyLanes { ty, max_lanes } - } - InvalidSimd { ty, kind: SimdLayoutError::ZeroLength } => E::SimdZeroLength { ty }, - TooGeneric(ty) => E::TooGeneric { ty }, - NormalizationFailure(ty, e) => { - E::NormalizationFailure { ty, failure_ty: e.get_type_for_failure() } - } - Cycle(_) => E::Cycle, - ReferencesError(_) => E::ReferencesError, - } - } -} - -// FIXME: Once the other errors that embed this error have been converted to translatable -// diagnostics, this Display impl should be removed. impl<'tcx> fmt::Display for LayoutError<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { @@ -1333,7 +1285,7 @@ pub enum FnAbiError<'tcx> { impl<'a, 'b, G: EmissionGuarantee> Diagnostic<'a, G> for FnAbiError<'b> { fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { match self { - Self::Layout(e) => e.into_diagnostic().into_diag(dcx, level), + Self::Layout(e) => Diag::new(dcx, level, e.to_string()), } } } diff --git a/compiler/rustc_middle/src/ty/vtable.rs b/compiler/rustc_middle/src/ty/vtable.rs index edb1eaea30275..8a376e5429459 100644 --- a/compiler/rustc_middle/src/ty/vtable.rs +++ b/compiler/rustc_middle/src/ty/vtable.rs @@ -101,7 +101,7 @@ pub(super) fn vtable_allocation_provider<'tcx>( let layout = match tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) { Ok(layout) => layout, - Err(e) => tcx.dcx().emit_fatal(e.into_diagnostic()), + Err(e) => tcx.dcx().fatal(e.to_string()), }; assert!(layout.is_sized(), "can't create a vtable for an unsized type"); let size = layout.size.bytes(); diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs index 00b67b6564594..daee8de965135 100644 --- a/compiler/rustc_mir_transform/src/errors.rs +++ b/compiler/rustc_mir_transform/src/errors.rs @@ -145,11 +145,7 @@ impl<'a, P: std::fmt::Debug> Diagnostic<'a, ()> for AssertLint

{ } }, ); - let label = self.assert_kind.diagnostic_message(); - self.assert_kind.add_args(&mut |name, value| { - diag.arg(name, value); - }); - diag.span_label(self.span, label); + diag.span_label(self.span, self.assert_kind.to_string()); diag } } diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs index c4994417ed7ea..8d0922db8f40e 100644 --- a/compiler/rustc_mir_transform/src/known_panics_lint.rs +++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs @@ -241,7 +241,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { assert!( !err.kind().formatted_string(), "known panics lint encountered formatting error: {}", - format_interp_error(self.ecx.tcx.dcx(), err), + format_interp_error(err), ); err }) diff --git a/compiler/rustc_mir_transform/src/single_use_consts.rs b/compiler/rustc_mir_transform/src/single_use_consts.rs index 6d33736d64ecb..91e040d5cbc89 100644 --- a/compiler/rustc_mir_transform/src/single_use_consts.rs +++ b/compiler/rustc_mir_transform/src/single_use_consts.rs @@ -5,6 +5,8 @@ use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; +use crate::strip_debuginfo::drop_invalid_debuginfos; + /// Various parts of MIR building introduce temporaries that are commonly not needed. /// /// Notably, `if CONST` and `match CONST` end up being used-once temporaries, which @@ -82,6 +84,8 @@ impl<'tcx> crate::MirPass<'tcx> for SingleUseConsts { ); } } + + drop_invalid_debuginfos(body); } fn is_required(&self) -> bool { diff --git a/compiler/rustc_mir_transform/src/strip_debuginfo.rs b/compiler/rustc_mir_transform/src/strip_debuginfo.rs index 7fec25ccb5218..5931a46660241 100644 --- a/compiler/rustc_mir_transform/src/strip_debuginfo.rs +++ b/compiler/rustc_mir_transform/src/strip_debuginfo.rs @@ -32,24 +32,21 @@ impl<'tcx> crate::MirPass<'tcx> for StripDebugInfo { ) }); - let debuginfo_locals = debuginfo_locals(body); - for data in body.basic_blocks.as_mut_preserves_cfg() { - for stmt in data.statements.iter_mut() { - stmt.debuginfos.retain(|debuginfo| match debuginfo { - StmtDebugInfo::AssignRef(local, _) | StmtDebugInfo::InvalidAssign(local) => { - debuginfo_locals.contains(*local) - } - }); - } - data.after_last_stmt_debuginfos.retain(|debuginfo| match debuginfo { - StmtDebugInfo::AssignRef(local, _) | StmtDebugInfo::InvalidAssign(local) => { - debuginfo_locals.contains(*local) - } - }); - } + drop_invalid_debuginfos(body); } fn is_required(&self) -> bool { true } } + +// Drop invalid debuginfos when strip locals in `var_debug_info`. +pub(super) fn drop_invalid_debuginfos(body: &mut Body<'_>) { + let debuginfo_locals = debuginfo_locals(body); + for data in body.basic_blocks.as_mut_preserves_cfg() { + for stmt in data.statements.iter_mut() { + stmt.debuginfos.retain_locals(&debuginfo_locals); + } + data.after_last_stmt_debuginfos.retain_locals(&debuginfo_locals); + } +} diff --git a/compiler/rustc_passes/src/abi_test.rs b/compiler/rustc_passes/src/abi_test.rs index 7d1ee1ffbc364..35bfad3a877f2 100644 --- a/compiler/rustc_passes/src/abi_test.rs +++ b/compiler/rustc_passes/src/abi_test.rs @@ -5,7 +5,7 @@ use rustc_hir::find_attr; use rustc_middle::span_bug; use rustc_middle::ty::layout::{FnAbiError, LayoutError}; use rustc_middle::ty::{self, GenericArgs, Instance, Ty, TyCtxt}; -use rustc_span::{Span, Spanned}; +use rustc_span::Span; use rustc_target::callconv::FnAbi; use super::layout_test::ensure_wf; @@ -44,10 +44,7 @@ fn unwrap_fn_abi<'tcx>( match abi { Ok(abi) => abi, Err(FnAbiError::Layout(layout_error)) => { - tcx.dcx().emit_fatal(Spanned { - node: layout_error.into_diagnostic(), - span: tcx.def_span(item_def_id), - }); + tcx.dcx().span_fatal(tcx.def_span(item_def_id), layout_error.to_string()); } } } @@ -65,11 +62,7 @@ fn dump_abi_of_fn_item( Ok(None) => { // Not sure what to do here, but `LayoutError::Unknown` seems reasonable? let ty = tcx.type_of(item_def_id).instantiate_identity(); - tcx.dcx().emit_fatal(Spanned { - node: LayoutError::Unknown(ty).into_diagnostic(), - - span: tcx.def_span(item_def_id), - }); + tcx.dcx().span_fatal(tcx.def_span(item_def_id), LayoutError::Unknown(ty).to_string()); } Err(_guaranteed) => return, }; diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs index f4f5ae6c1683f..1a9054a51ca39 100644 --- a/compiler/rustc_passes/src/layout_test.rs +++ b/compiler/rustc_passes/src/layout_test.rs @@ -6,7 +6,7 @@ use rustc_hir::find_attr; use rustc_middle::span_bug; use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutError, LayoutOfHelpers}; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_span::{Span, Spanned}; +use rustc_span::Span; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::infer::TyCtxtInferExt; use rustc_trait_selection::traits; @@ -115,7 +115,7 @@ fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attrs: &[RustcLayout } Err(layout_error) => { - tcx.dcx().emit_err(Spanned { node: layout_error.into_diagnostic(), span }); + tcx.dcx().span_err(span, layout_error.to_string()); } } } diff --git a/compiler/rustc_query_impl/src/execution.rs b/compiler/rustc_query_impl/src/execution.rs index 57d503ef7b076..a892958d6a810 100644 --- a/compiler/rustc_query_impl/src/execution.rs +++ b/compiler/rustc_query_impl/src/execution.rs @@ -5,7 +5,7 @@ use rustc_data_structures::hash_table::{Entry, HashTable}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::sync::{DynSend, DynSync}; use rustc_data_structures::{outline, sharded, sync}; -use rustc_errors::{FatalError, StashKey}; +use rustc_errors::FatalError; use rustc_middle::dep_graph::{DepGraphData, DepNodeKey, SerializedDepNodeIndex}; use rustc_middle::query::plumbing::QueryVTable; use rustc_middle::query::{ @@ -16,8 +16,8 @@ use rustc_middle::ty::TyCtxt; use rustc_middle::verify_ich::incremental_verify_ich; use rustc_span::{DUMMY_SP, Span}; -use crate::collect_active_jobs_from_all_queries; use crate::dep_graph::{DepNode, DepNodeIndex}; +use crate::for_each_query_vtable; use crate::job::{QueryJobInfo, QueryJobMap, find_cycle_in_stack, report_cycle}; use crate::plumbing::{current_query_job, next_job_id, start_query}; @@ -30,6 +30,33 @@ pub(crate) fn all_inactive<'tcx, K>(state: &QueryState<'tcx, K>) -> bool { state.active.lock_shards().all(|shard| shard.is_empty()) } +/// Returns a map of currently active query jobs, collected from all queries. +/// +/// If `require_complete` is `true`, this function locks all shards of the +/// query results to produce a complete map, which always returns `Ok`. +/// Otherwise, it may return an incomplete map as an error if any shard +/// lock cannot be acquired. +/// +/// Prefer passing `false` to `require_complete` to avoid potential deadlocks, +/// especially when called from within a deadlock handler, unless a +/// complete map is needed and no deadlock is possible at this call site. +pub fn collect_active_jobs_from_all_queries<'tcx>( + tcx: TyCtxt<'tcx>, + require_complete: bool, +) -> Result, QueryJobMap<'tcx>> { + let mut job_map_out = QueryJobMap::default(); + let mut complete = true; + + for_each_query_vtable!(ALL, tcx, |query| { + let res = gather_active_jobs(query, tcx, require_complete, &mut job_map_out); + if res.is_none() { + complete = false; + } + }); + + if complete { Ok(job_map_out) } else { Err(job_map_out) } +} + /// Internal plumbing for collecting the set of active jobs for this query. /// /// Should only be called from `collect_active_jobs_from_all_queries`. @@ -37,7 +64,7 @@ pub(crate) fn all_inactive<'tcx, K>(state: &QueryState<'tcx, K>) -> bool { /// (We arbitrarily use the word "gather" when collecting the jobs for /// each individual query, so that we have distinct function names to /// grep for.) -pub(crate) fn gather_active_jobs<'tcx, C>( +fn gather_active_jobs<'tcx, C>( query: &'tcx QueryVTable<'tcx, C>, tcx: TyCtxt<'tcx>, require_complete: bool, @@ -110,16 +137,6 @@ fn mk_cycle<'tcx, C: QueryCache>( let guar = error.delay_as_bug(); (query.value_from_cycle_error)(tcx, cycle_error, guar) } - CycleErrorHandling::Stash => { - let guar = if let Some(root) = cycle_error.cycle.first() - && let Some(span) = root.frame.info.span - { - error.stash(span, StashKey::Cycle).unwrap() - } else { - error.emit() - }; - (query.value_from_cycle_error)(tcx, cycle_error, guar) - } } } diff --git a/compiler/rustc_query_impl/src/from_cycle_error.rs b/compiler/rustc_query_impl/src/from_cycle_error.rs index 2599c2fde5d08..0b7f69765823f 100644 --- a/compiler/rustc_query_impl/src/from_cycle_error.rs +++ b/compiler/rustc_query_impl/src/from_cycle_error.rs @@ -12,7 +12,6 @@ use rustc_middle::dep_graph::DepKind; use rustc_middle::queries::QueryVTables; use rustc_middle::query::CycleError; use rustc_middle::query::erase::erase_val; -use rustc_middle::query::plumbing::CyclePlaceholder; use rustc_middle::ty::layout::{LayoutError, TyAndLayout}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; @@ -31,9 +30,6 @@ pub(crate) fn specialize_query_vtables<'tcx>(vtables: &mut QueryVTables<'tcx>) { vtables.erase_and_anonymize_regions_ty.value_from_cycle_error = |tcx, _, guar| erase_val(Ty::new_error(tcx, guar)); - vtables.type_of_opaque.value_from_cycle_error = - |_, _, guar| erase_val(Err(CyclePlaceholder(guar))); - vtables.fn_sig.value_from_cycle_error = |tcx, cycle, guar| erase_val(fn_sig(tcx, cycle, guar)); vtables.check_representability.value_from_cycle_error = diff --git a/compiler/rustc_query_impl/src/job.rs b/compiler/rustc_query_impl/src/job.rs index 9c095603cc848..01f36d06c0472 100644 --- a/compiler/rustc_query_impl/src/job.rs +++ b/compiler/rustc_query_impl/src/job.rs @@ -14,7 +14,7 @@ use rustc_middle::ty::TyCtxt; use rustc_session::Session; use rustc_span::{DUMMY_SP, Span}; -use crate::collect_active_jobs_from_all_queries; +use crate::execution::collect_active_jobs_from_all_queries; /// Map from query job IDs to job information collected by /// `collect_active_jobs_from_all_queries`. diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 6482384f99ea3..41642f66967da 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -11,15 +11,15 @@ use rustc_data_structures::sync::AtomicU64; use rustc_middle::dep_graph; use rustc_middle::queries::{self, ExternProviders, Providers}; -use rustc_middle::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex, OnDiskCache}; +use rustc_middle::query::on_disk_cache::OnDiskCache; use rustc_middle::query::plumbing::{QuerySystem, QueryVTable}; use rustc_middle::query::{AsLocalQueryKey, QueryCache, QueryMode}; use rustc_middle::ty::TyCtxt; use rustc_span::Span; pub use crate::dep_kind_vtables::make_dep_kind_vtables; +pub use crate::execution::collect_active_jobs_from_all_queries; pub use crate::job::{QueryJobMap, break_query_cycles, print_query_stack}; -use crate::profiling_support::QueryKeyStringCache; #[macro_use] mod plumbing; @@ -66,7 +66,8 @@ pub fn query_system<'tcx>( rustc_middle::rustc_with_all_queries! { define_queries! } pub fn provide(providers: &mut rustc_middle::util::Providers) { - providers.hooks.alloc_self_profile_query_strings = alloc_self_profile_query_strings; - providers.hooks.query_key_hash_verify_all = query_key_hash_verify_all; - providers.hooks.encode_all_query_results = encode_all_query_results; + providers.hooks.alloc_self_profile_query_strings = + profiling_support::alloc_self_profile_query_strings; + providers.hooks.query_key_hash_verify_all = plumbing::query_key_hash_verify_all; + providers.hooks.encode_all_query_results = plumbing::encode_all_query_results; } diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 558ecdda5c4b0..ddce892345907 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -33,7 +33,7 @@ use rustc_span::def_id::LOCAL_CRATE; use crate::error::{QueryOverflow, QueryOverflowNote}; use crate::execution::{all_inactive, force_query}; use crate::job::find_dep_kind_root; -use crate::{GetQueryVTable, collect_active_jobs_from_all_queries}; +use crate::{GetQueryVTable, collect_active_jobs_from_all_queries, for_each_query_vtable}; fn depth_limit_error<'tcx>(tcx: TyCtxt<'tcx>, job: QueryJobId) { let job_map = @@ -146,7 +146,17 @@ where QueryStackFrame::new(info, kind, def_id, def_id_for_ty_in_cycle) } -pub(crate) fn encode_query_results<'a, 'tcx, C, V>( +pub(crate) fn encode_all_query_results<'tcx>( + tcx: TyCtxt<'tcx>, + encoder: &mut CacheEncoder<'_, 'tcx>, + query_result_index: &mut EncodedDepNodeIndex, +) { + for_each_query_vtable!(CACHE_ON_DISK, tcx, |query| { + encode_query_results(tcx, query, encoder, query_result_index) + }); +} + +fn encode_query_results<'a, 'tcx, C, V>( tcx: TyCtxt<'tcx>, query: &'tcx QueryVTable<'tcx, C>, encoder: &mut CacheEncoder<'a, 'tcx>, @@ -172,7 +182,17 @@ pub(crate) fn encode_query_results<'a, 'tcx, C, V>( }); } -pub(crate) fn query_key_hash_verify<'tcx, C: QueryCache>( +pub(crate) fn query_key_hash_verify_all<'tcx>(tcx: TyCtxt<'tcx>) { + if tcx.sess.opts.unstable_opts.incremental_verify_ich || cfg!(debug_assertions) { + tcx.sess.time("query_key_hash_verify_all", || { + for_each_query_vtable!(ALL, tcx, |query| { + query_key_hash_verify(query, tcx); + }); + }); + } +} + +fn query_key_hash_verify<'tcx, C: QueryCache>( query: &'tcx QueryVTable<'tcx, C>, tcx: TyCtxt<'tcx>, ) { @@ -510,95 +530,48 @@ macro_rules! define_queries { } } - /// Returns a map of currently active query jobs, collected from all queries. + /// Given a filter condition (e.g. `ALL` or `CACHE_ON_DISK`), a `tcx`, + /// and a closure expression that accepts `&QueryVTable`, this macro + /// calls that closure with each query vtable that satisfies the filter + /// condition. /// - /// If `require_complete` is `true`, this function locks all shards of the - /// query results to produce a complete map, which always returns `Ok`. - /// Otherwise, it may return an incomplete map as an error if any shard - /// lock cannot be acquired. + /// This needs to be a macro, because the vtables can have different + /// key/value/cache types for different queries. /// - /// Prefer passing `false` to `require_complete` to avoid potential deadlocks, - /// especially when called from within a deadlock handler, unless a - /// complete map is needed and no deadlock is possible at this call site. - pub fn collect_active_jobs_from_all_queries<'tcx>( - tcx: TyCtxt<'tcx>, - require_complete: bool, - ) -> Result, QueryJobMap<'tcx>> { - let mut job_map_out = QueryJobMap::default(); - let mut complete = true; - - $( - let res = crate::execution::gather_active_jobs( - &tcx.query_system.query_vtables.$name, - tcx, - require_complete, - &mut job_map_out, - ); - if res.is_none() { - complete = false; - } - )* - - if complete { Ok(job_map_out) } else { Err(job_map_out) } - } - - /// All self-profiling events generated by the query engine use - /// virtual `StringId`s for their `event_id`. This method makes all - /// those virtual `StringId`s point to actual strings. + /// This macro's argument syntax is specifically intended to look like + /// plain Rust code, so that `for_each_query_vtable!(..)` calls will be + /// formatted by rustfmt. /// - /// If we are recording only summary data, the ids will point to - /// just the query names. If we are recording query keys too, we - /// allocate the corresponding strings here. - pub fn alloc_self_profile_query_strings(tcx: TyCtxt<'_>) { - if !tcx.prof.enabled() { - return; - } - - let _prof_timer = tcx.sess.prof.generic_activity("self_profile_alloc_query_strings"); - - let mut string_cache = QueryKeyStringCache::new(); - - $( - $crate::profiling_support::alloc_self_profile_query_strings_for_query_cache( - tcx, - stringify!($name), - &tcx.query_system.query_vtables.$name.cache, - &mut string_cache, - ); - )* - - tcx.sess.prof.store_query_cache_hits(); - } - - fn encode_all_query_results<'tcx>( - tcx: TyCtxt<'tcx>, - encoder: &mut CacheEncoder<'_, 'tcx>, - query_result_index: &mut EncodedDepNodeIndex, - ) { - $( - #[cfg($cache_on_disk)] - { - $crate::plumbing::encode_query_results( - tcx, - &tcx.query_system.query_vtables.$name, - encoder, - query_result_index, - ) - } - )* + /// To avoid too much nested-macro complication, filter conditions are + /// implemented by hand as needed. + macro_rules! for_each_query_vtable { + // Call with all queries. + (ALL, $tcx:expr, $closure:expr) => {{ + let tcx: rustc_middle::ty::TyCtxt<'_> = $tcx; + $( + let query: &rustc_middle::query::plumbing::QueryVTable<'_, _> = + &tcx.query_system.query_vtables.$name; + $closure(query); + )* + }}; + + // Only call with queries that can potentially cache to disk. + // + // This allows the use of trait bounds that only need to be satisfied + // by the subset of queries that actually cache to disk. + (CACHE_ON_DISK, $tcx:expr, $closure:expr) => {{ + let tcx: rustc_middle::ty::TyCtxt<'_> = $tcx; + $( + #[cfg($cache_on_disk)] + { + let query: &rustc_middle::query::plumbing::QueryVTable<'_, _> = + &tcx.query_system.query_vtables.$name; + $closure(query); + } + )* + }} } - pub fn query_key_hash_verify_all<'tcx>(tcx: TyCtxt<'tcx>) { - if tcx.sess.opts.unstable_opts.incremental_verify_ich || cfg!(debug_assertions) { - tcx.sess.time("query_key_hash_verify_all", || { - $( - $crate::plumbing::query_key_hash_verify( - &tcx.query_system.query_vtables.$name, - tcx - ); - )* - }) - } - } + pub(crate) use for_each_query_vtable; } } diff --git a/compiler/rustc_query_impl/src/profiling_support.rs b/compiler/rustc_query_impl/src/profiling_support.rs index 0c0e966f1fa43..c88bc8845ebdb 100644 --- a/compiler/rustc_query_impl/src/profiling_support.rs +++ b/compiler/rustc_query_impl/src/profiling_support.rs @@ -7,8 +7,11 @@ use rustc_data_structures::profiling::SelfProfiler; use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE, LocalDefId}; use rustc_hir::definitions::DefPathData; use rustc_middle::query::QueryCache; +use rustc_middle::query::plumbing::QueryVTable; use rustc_middle::ty::TyCtxt; +use crate::for_each_query_vtable; + pub(crate) struct QueryKeyStringCache { def_id_cache: FxHashMap, } @@ -172,13 +175,35 @@ where } } +/// All self-profiling events generated by the query engine use +/// virtual `StringId`s for their `event_id`. This method makes all +/// those virtual `StringId`s point to actual strings. +/// +/// If we are recording only summary data, the ids will point to +/// just the query names. If we are recording query keys too, we +/// allocate the corresponding strings here. +pub(crate) fn alloc_self_profile_query_strings(tcx: TyCtxt<'_>) { + if !tcx.prof.enabled() { + return; + } + + let _prof_timer = tcx.sess.prof.generic_activity("self_profile_alloc_query_strings"); + + let mut string_cache = QueryKeyStringCache::new(); + + for_each_query_vtable!(ALL, tcx, |query| { + alloc_self_profile_query_strings_for_query_cache(tcx, query, &mut string_cache); + }); + + tcx.sess.prof.store_query_cache_hits(); +} + /// Allocate the self-profiling query strings for a single query cache. This /// method is called from `alloc_self_profile_query_strings` which knows all /// the queries via macro magic. -pub(crate) fn alloc_self_profile_query_strings_for_query_cache<'tcx, C>( +fn alloc_self_profile_query_strings_for_query_cache<'tcx, C>( tcx: TyCtxt<'tcx>, - query_name: &'static str, - query_cache: &C, + query: &'tcx QueryVTable<'tcx, C>, string_cache: &mut QueryKeyStringCache, ) where C: QueryCache, @@ -193,14 +218,14 @@ pub(crate) fn alloc_self_profile_query_strings_for_query_cache<'tcx, C>( if profiler.query_key_recording_enabled() { let mut query_string_builder = QueryKeyStringBuilder::new(profiler, tcx, string_cache); - let query_name = profiler.get_or_alloc_cached_string(query_name); + let query_name = profiler.get_or_alloc_cached_string(query.name); // Since building the string representation of query keys might // need to invoke queries itself, we cannot keep the query caches // locked while doing so. Instead we copy out the // `(query_key, dep_node_index)` pairs and release the lock again. let mut query_keys_and_indices = Vec::new(); - query_cache.for_each(&mut |k, _, i| query_keys_and_indices.push((*k, i))); + query.cache.for_each(&mut |k, _, i| query_keys_and_indices.push((*k, i))); // Now actually allocate the strings. If allocating the strings // generates new entries in the query cache, we'll miss them but @@ -221,14 +246,14 @@ pub(crate) fn alloc_self_profile_query_strings_for_query_cache<'tcx, C>( } } else { // In this branch we don't allocate query keys - let query_name = profiler.get_or_alloc_cached_string(query_name); + let query_name = profiler.get_or_alloc_cached_string(query.name); let event_id = event_id_builder.from_label(query_name).to_string_id(); // FIXME(eddyb) make this O(1) by using a pre-cached query name `EventId`, // instead of passing the `DepNodeIndex` to `finish_with_query_invocation_id`, // when recording the event in the first place. let mut query_invocation_ids = Vec::new(); - query_cache.for_each(&mut |_, _, i| { + query.cache.for_each(&mut |_, _, i| { query_invocation_ids.push(i.into()); }); diff --git a/compiler/rustc_target/src/spec/json.rs b/compiler/rustc_target/src/spec/json.rs index 20fbb687b3080..d8ef2484a95cf 100644 --- a/compiler/rustc_target/src/spec/json.rs +++ b/compiler/rustc_target/src/spec/json.rs @@ -42,11 +42,7 @@ impl Target { } let alignment_error = |field_name: &str, error: AlignFromBytesError| -> String { - let msg = match error { - AlignFromBytesError::NotPowerOfTwo(_) => "not a power of 2 number of bytes", - AlignFromBytesError::TooLarge(_) => "too large", - }; - format!("`{}` bits is not a valid value for {field_name}: {msg}", error.align() * 8) + format!("invalid value for {field_name}: {error}") }; macro_rules! forward { diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index fdb3859022125..d5383fd4d0831 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -756,11 +756,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } - SelectionError::OpaqueTypeAutoTraitLeakageUnknown(def_id) => return self.report_opaque_type_auto_trait_leakage( - &obligation, - def_id, - ), - SelectionError::TraitDynIncompatible(did) => { let violations = self.tcx.dyn_compatibility_violations(did); report_dyn_incompatibility(self.tcx, span, None, did, violations) @@ -3331,34 +3326,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ) } - fn report_opaque_type_auto_trait_leakage( - &self, - obligation: &PredicateObligation<'tcx>, - def_id: DefId, - ) -> ErrorGuaranteed { - let name = match self.tcx.local_opaque_ty_origin(def_id.expect_local()) { - hir::OpaqueTyOrigin::FnReturn { .. } | hir::OpaqueTyOrigin::AsyncFn { .. } => { - "opaque type".to_string() - } - hir::OpaqueTyOrigin::TyAlias { .. } => { - format!("`{}`", self.tcx.def_path_debug_str(def_id)) - } - }; - let mut err = self.dcx().struct_span_err( - obligation.cause.span, - format!("cannot check whether the hidden type of {name} satisfies auto traits"), - ); - - err.note( - "fetching the hidden types of an opaque inside of the defining scope is not supported. \ - You can try moving the opaque type and the item that actually registers a hidden type into a new submodule", - ); - err.span_note(self.tcx.def_span(def_id), "opaque type is declared here"); - - self.note_obligation_cause(&mut err, &obligation); - self.dcx().try_steal_replace_and_emit_err(self.tcx.def_span(def_id), StashKey::Cycle, err) - } - fn report_signature_mismatch_error( &self, obligation: &PredicateObligation<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index a7f47a8615c24..83d199fa8b4cd 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2404,15 +2404,11 @@ impl<'tcx> SelectionContext<'_, 'tcx> { // We can resolve the opaque type to its hidden type, // which enforces a DAG between the functions requiring // the auto trait bounds in question. - match self.tcx().type_of_opaque(def_id) { - Ok(ty) => ty::Binder::dummy(AutoImplConstituents { - types: vec![ty.instantiate(self.tcx(), args)], - assumptions: vec![], - }), - Err(_) => { - return Err(SelectionError::OpaqueTypeAutoTraitLeakageUnknown(def_id)); - } - } + let ty = self.tcx().type_of_opaque(def_id); + ty::Binder::dummy(AutoImplConstituents { + types: vec![ty.instantiate(self.tcx(), args)], + assumptions: vec![], + }) } } }) diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index 0c607cb6ba6f3..b0f8cdd28e82b 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -1151,12 +1151,18 @@ impl Step for Enzyme { let LlvmResult { host_llvm_config, llvm_cmake_dir } = builder.ensure(Llvm { target }); + // Enzyme links against LLVM. If we update the LLVM submodule libLLVM might get a new + // version number, in which case Enzyme will now fail to find LLVM. By including the LLVM + // hash into the Enzyme hash we force a rebuild of Enzyme when updating LLVM. + let enzyme_hash_input = builder.in_tree_llvm_info.sha().unwrap_or_default().to_owned() + + builder.enzyme_info.sha().unwrap_or_default(); + static STAMP_HASH_MEMO: OnceLock = OnceLock::new(); let smart_stamp_hash = STAMP_HASH_MEMO.get_or_init(|| { generate_smart_stamp_hash( builder, &builder.config.src.join("src/tools/enzyme"), - builder.enzyme_info.sha().unwrap_or_default(), + &enzyme_hash_input, ) }); diff --git a/src/doc/rustc/src/platform-support/aarch64-unknown-linux-gnu.md b/src/doc/rustc/src/platform-support/aarch64-unknown-linux-gnu.md index baa46135d534b..36609d5742ccb 100644 --- a/src/doc/rustc/src/platform-support/aarch64-unknown-linux-gnu.md +++ b/src/doc/rustc/src/platform-support/aarch64-unknown-linux-gnu.md @@ -7,6 +7,7 @@ Target for 64-bit little endian ARMv8-A Linux 4.1+ programs using glibc 2.17+. ## Target maintainers - [@rust-lang/arm-maintainers][arm_maintainers] ([rust@arm.com][arm_email]) + - Use `@rustbot ping arm-maintainers` to ping us [arm_maintainers]: https://github.com/rust-lang/team/blob/master/teams/arm-maintainers.toml [arm_email]: mailto:rust@arm.com diff --git a/src/doc/rustc/src/platform-support/aarch64-unknown-none.md b/src/doc/rustc/src/platform-support/aarch64-unknown-none.md index 5d1201bbf4269..b9386f07fe2df 100644 --- a/src/doc/rustc/src/platform-support/aarch64-unknown-none.md +++ b/src/doc/rustc/src/platform-support/aarch64-unknown-none.md @@ -16,6 +16,7 @@ Processors in this family include the [Arm Cortex-A35, 53, 76, etc][aarch64-cpus - [Rust Embedded Devices Working Group Arm Team] - [@rust-lang/arm-maintainers][arm_maintainers] ([rust@arm.com][arm_email]) + - Use `@rustbot ping arm-maintainers` to ping us [Rust Embedded Devices Working Group Arm Team]: https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team [arm_maintainers]: https://github.com/rust-lang/team/blob/master/teams/arm-maintainers.toml diff --git a/src/doc/rustc/src/platform-support/aarch64v8r-unknown-none.md b/src/doc/rustc/src/platform-support/aarch64v8r-unknown-none.md index 9e232b3205162..bbe9d8b3ba875 100644 --- a/src/doc/rustc/src/platform-support/aarch64v8r-unknown-none.md +++ b/src/doc/rustc/src/platform-support/aarch64v8r-unknown-none.md @@ -16,6 +16,7 @@ For Armv8-R CPUs running in AArch32 mode (such as the Arm Cortex-R52), see - [Rust Embedded Devices Working Group Arm Team] - [@rust-lang/arm-maintainers][arm_maintainers] ([rust@arm.com][arm_email]) + - Use `@rustbot ping arm-maintainers` to ping us [Rust Embedded Devices Working Group Arm Team]: https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team [arm_maintainers]: https://github.com/rust-lang/team/blob/master/teams/arm-maintainers.toml diff --git a/src/doc/rustc/src/platform-support/armv7-unknown-linux-gnueabi.md b/src/doc/rustc/src/platform-support/armv7-unknown-linux-gnueabi.md index c2fe63a49087c..c7888571df3d0 100644 --- a/src/doc/rustc/src/platform-support/armv7-unknown-linux-gnueabi.md +++ b/src/doc/rustc/src/platform-support/armv7-unknown-linux-gnueabi.md @@ -8,6 +8,7 @@ Target for 32-bit little endian ARMv7-A Linux 3.2+ programs using glibc 2.17+. ## Target maintainers - [@rust-lang/arm-maintainers][arm_maintainers] ([rust@arm.com][arm_email]) + - Use `@rustbot ping arm-maintainers` to ping us [arm_maintainers]: https://github.com/rust-lang/team/blob/master/teams/arm-maintainers.toml [arm_email]: mailto:rust@arm.com diff --git a/src/doc/rustc/src/platform-support/armv7a-none-eabi.md b/src/doc/rustc/src/platform-support/armv7a-none-eabi.md index 555f69e81a02f..0fa09d3955ff3 100644 --- a/src/doc/rustc/src/platform-support/armv7a-none-eabi.md +++ b/src/doc/rustc/src/platform-support/armv7a-none-eabi.md @@ -24,6 +24,7 @@ See [`arm-none-eabi`](arm-none-eabi.md) for information applicable to all - [Rust Embedded Devices Working Group Arm Team] - [@rust-lang/arm-maintainers][arm_maintainers] ([rust@arm.com][arm_email]) + - Use `@rustbot ping arm-maintainers` to ping us [Rust Embedded Devices Working Group Arm Team]: https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team [arm_maintainers]: https://github.com/rust-lang/team/blob/master/teams/arm-maintainers.toml diff --git a/src/doc/rustc/src/platform-support/armv7r-none-eabi.md b/src/doc/rustc/src/platform-support/armv7r-none-eabi.md index 20fd55c6abd68..5f95af44a7935 100644 --- a/src/doc/rustc/src/platform-support/armv7r-none-eabi.md +++ b/src/doc/rustc/src/platform-support/armv7r-none-eabi.md @@ -22,6 +22,7 @@ See [`arm-none-eabi`](arm-none-eabi.md) for information applicable to all - [@chrisnc](https://github.com/chrisnc) - [Rust Embedded Devices Working Group Arm Team] - [@rust-lang/arm-maintainers][arm_maintainers] ([rust@arm.com][arm_email]) + - Use `@rustbot ping arm-maintainers` to ping us [Rust Embedded Devices Working Group Arm Team]: https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team [arm_maintainers]: https://github.com/rust-lang/team/blob/master/teams/arm-maintainers.toml diff --git a/src/doc/rustc/src/platform-support/armv8r-none-eabihf.md b/src/doc/rustc/src/platform-support/armv8r-none-eabihf.md index 73d88bcb89a15..1ff36b47beb2f 100644 --- a/src/doc/rustc/src/platform-support/armv8r-none-eabihf.md +++ b/src/doc/rustc/src/platform-support/armv8r-none-eabihf.md @@ -26,6 +26,7 @@ For Armv8-R CPUs running in AArch64 mode (such as the Arm Cortex-R82), see - [@chrisnc](https://github.com/chrisnc) - [Rust Embedded Devices Working Group Arm Team] - [@rust-lang/arm-maintainers][arm_maintainers] ([rust@arm.com][arm_email]) + - Use `@rustbot ping arm-maintainers` to ping us [Rust Embedded Devices Working Group Arm Team]: https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team [arm_maintainers]: https://github.com/rust-lang/team/blob/master/teams/arm-maintainers.toml diff --git a/src/doc/rustc/src/platform-support/thumbv7em-none-eabi.md b/src/doc/rustc/src/platform-support/thumbv7em-none-eabi.md index 192e013d3a43f..1f91e2f18631b 100644 --- a/src/doc/rustc/src/platform-support/thumbv7em-none-eabi.md +++ b/src/doc/rustc/src/platform-support/thumbv7em-none-eabi.md @@ -24,6 +24,7 @@ See [`arm-none-eabi`](arm-none-eabi.md) for information applicable to all - [Rust Embedded Devices Working Group Arm Team](https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team) - [@rust-lang/arm-maintainers][arm_maintainers] ([rust@arm.com][arm_email]) + - Use `@rustbot ping arm-maintainers` to ping us [arm_maintainers]: https://github.com/rust-lang/team/blob/master/teams/arm-maintainers.toml [arm_email]: mailto:rust@arm.com diff --git a/src/doc/rustc/src/platform-support/thumbv7m-none-eabi.md b/src/doc/rustc/src/platform-support/thumbv7m-none-eabi.md index b04cb7bfacfac..90f641d6e4f8e 100644 --- a/src/doc/rustc/src/platform-support/thumbv7m-none-eabi.md +++ b/src/doc/rustc/src/platform-support/thumbv7m-none-eabi.md @@ -25,6 +25,7 @@ only option because there is no FPU support in [Armv7-M]. - [Rust Embedded Devices Working Group Arm Team](https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team) - [@rust-lang/arm-maintainers][arm_maintainers] ([rust@arm.com][arm_email]) + - Use `@rustbot ping arm-maintainers` to ping us [arm_maintainers]: https://github.com/rust-lang/team/blob/master/teams/arm-maintainers.toml [arm_email]: mailto:rust@arm.com diff --git a/src/doc/rustc/src/platform-support/thumbv8m.base-none-eabi.md b/src/doc/rustc/src/platform-support/thumbv8m.base-none-eabi.md index 104520854b49c..20fdb18eafa53 100644 --- a/src/doc/rustc/src/platform-support/thumbv8m.base-none-eabi.md +++ b/src/doc/rustc/src/platform-support/thumbv8m.base-none-eabi.md @@ -25,6 +25,7 @@ only option because there is no FPU support in [Armv8-M] Baseline. - [Rust Embedded Devices Working Group Arm Team](https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team) - [@rust-lang/arm-maintainers][arm_maintainers] ([rust@arm.com][arm_email]) + - Use `@rustbot ping arm-maintainers` to ping us [arm_maintainers]: https://github.com/rust-lang/team/blob/master/teams/arm-maintainers.toml [arm_email]: mailto:rust@arm.com diff --git a/src/doc/rustc/src/platform-support/thumbv8m.main-none-eabi.md b/src/doc/rustc/src/platform-support/thumbv8m.main-none-eabi.md index 5cc535ce376b3..ab77153be92b7 100644 --- a/src/doc/rustc/src/platform-support/thumbv8m.main-none-eabi.md +++ b/src/doc/rustc/src/platform-support/thumbv8m.main-none-eabi.md @@ -28,6 +28,7 @@ See [`arm-none-eabi`](arm-none-eabi.md) for information applicable to all - [Rust Embedded Devices Working Group Arm Team](https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team) - [@rust-lang/arm-maintainers][arm_maintainers] ([rust@arm.com][arm_email]) + - Use `@rustbot ping arm-maintainers` to ping us [arm_maintainers]: https://github.com/rust-lang/team/blob/master/teams/arm-maintainers.toml [arm_email]: mailto:rust@arm.com diff --git a/src/doc/rustc/src/platform-support/unknown-uefi.md b/src/doc/rustc/src/platform-support/unknown-uefi.md index e8989616b844b..d286ab4fb35a5 100644 --- a/src/doc/rustc/src/platform-support/unknown-uefi.md +++ b/src/doc/rustc/src/platform-support/unknown-uefi.md @@ -16,6 +16,7 @@ Available targets: - [@dvdhrm](https://github.com/dvdhrm) - [@nicholasbishop](https://github.com/nicholasbishop) - (for `aarch64-unknown-uefi` only) [@rust-lang/arm-maintainers][arm_maintainers] ([rust@arm.com][arm_email]) + - Use `@rustbot ping arm-maintainers` to ping us [arm_maintainers]: https://github.com/rust-lang/team/blob/master/teams/arm-maintainers.toml [arm_email]: mailto:rust@arm.com diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs index 36e574c8e57f7..6b7c0adc8afb0 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs @@ -37,17 +37,14 @@ impl Creation { let tag = self.retag.new_tag; if let Some(perm) = self.retag.permission { ( - format!( - "{tag:?} was created by a {:?} retag at offsets {:?}", - perm, self.retag.range, - ), + format!("{tag:?} was created by a {perm:?} retag at offsets {}", self.retag.range), self.span.data(), ) } else { assert!(self.retag.range.size == Size::ZERO); ( format!( - "{tag:?} would have been created here, but this is a zero-size retag ({:?}) so the tag in question does not exist anywhere", + "{tag:?} would have been created here, but this is a zero-size retag ({}) so the tag in question does not exist anywhere", self.retag.range, ), self.span.data(), @@ -79,12 +76,12 @@ impl Invalidation { // For a FnEntry retag, our Span points at the caller. // See `DiagnosticCx::log_invalidation`. format!( - "{:?} was later invalidated at offsets {:?} by a {} inside this call", + "{:?} was later invalidated at offsets {} by a {} inside this call", self.tag, self.range, self.cause ) } else { format!( - "{:?} was later invalidated at offsets {:?} by a {}", + "{:?} was later invalidated at offsets {} by a {}", self.tag, self.range, self.cause ) }; @@ -343,7 +340,7 @@ impl<'history, 'ecx, 'tcx> DiagnosticCx<'history, 'ecx, 'tcx> { if self.history.root.0.tag() == tag { Some(( format!( - "{tag:?} was created here, as the root tag for {:?}", + "{tag:?} was created here, as the root tag for {}", self.history.id ), self.history.root.1.data(), @@ -383,7 +380,7 @@ impl<'history, 'ecx, 'tcx> DiagnosticCx<'history, 'ecx, 'tcx> { let perm = op.permission.expect("`start_grant` must be called before calling `grant_error`"); let action = format!( - "trying to retag from {:?} for {:?} permission at {:?}[{:#x}]", + "trying to retag from {:?} for {:?} permission at {}[{:#x}]", op.orig_tag, perm, self.history.id, @@ -410,7 +407,7 @@ impl<'history, 'ecx, 'tcx> DiagnosticCx<'history, 'ecx, 'tcx> { Operation::Dealloc(_) => return self.dealloc_error(stack), }; let action = format!( - "attempting a {access} using {tag:?} at {alloc_id:?}[{offset:#x}]", + "attempting a {access} using {tag:?} at {alloc_id}[{offset:#x}]", access = op.kind, tag = op.tag, alloc_id = self.history.id, @@ -455,7 +452,7 @@ impl<'history, 'ecx, 'tcx> DiagnosticCx<'history, 'ecx, 'tcx> { }; err_sb_ub( format!( - "attempting deallocation using {tag:?} at {alloc_id:?}{cause}", + "attempting deallocation using {tag:?} at {alloc_id}{cause}", tag = op.tag, alloc_id = self.history.id, cause = error_cause(stack, op.tag), @@ -488,7 +485,7 @@ impl<'history, 'ecx, 'tcx> DiagnosticCx<'history, 'ecx, 'tcx> { } fn operation_summary(operation: &str, alloc_id: AllocId, alloc_range: AllocRange) -> String { - format!("this error occurs as part of {operation} at {alloc_id:?}{alloc_range:?}") + format!("this error occurs as part of {operation} at {alloc_id}{alloc_range}") } fn error_cause(stack: &Stack, prov_extra: ProvenanceExtra) -> &'static str { diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs index 055baca8542fd..093dada405af8 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs @@ -157,7 +157,7 @@ impl HistoryData { // to the user. The meaningful one is `access_range`. let access = access_cause.print_as_access(is_foreign); let access_range_text = match access_range { - Some(r) => format!("at offsets {r:?}"), + Some(r) => format!("at offsets {r}"), None => format!("on every location previously accessed by this tag"), }; self.events.push(( @@ -339,7 +339,7 @@ impl TbError<'_> { // all tags through which an access would cause UB. let accessed_is_conflicting = accessed.map(|a| a.tag) == Some(conflicting.tag); let title = format!( - "{cause} through {accessed_str} at {alloc_id:?}[{error_offset:#x}] is forbidden", + "{cause} through {accessed_str} at {alloc_id}[{error_offset:#x}] is forbidden", alloc_id = self.access_info.alloc_id ); let (title, details, conflicting_tag_name) = match self.error_kind { diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs index 367012e56ad9c..7992819aafd07 100644 --- a/src/tools/miri/src/diagnostics.rs +++ b/src/tools/miri/src/diagnostics.rs @@ -4,7 +4,7 @@ use std::sync::Mutex; use rustc_abi::{Align, Size}; use rustc_data_structures::fx::{FxBuildHasher, FxHashSet}; -use rustc_errors::{Diag, DiagMessage, Level}; +use rustc_errors::{Diag, Level}; use rustc_span::{DUMMY_SP, Span, SpanData, Symbol}; use crate::borrow_tracker::stacked_borrows::diagnostics::TagHistory; @@ -106,16 +106,7 @@ impl fmt::Debug for TerminationInfo { } } -impl MachineStopType for TerminationInfo { - fn diagnostic_message(&self) -> DiagMessage { - self.to_string().into() - } - fn add_args( - self: Box, - _: &mut dyn FnMut(std::borrow::Cow<'static, str>, rustc_errors::DiagArgValue), - ) { - } -} +impl MachineStopType for TerminationInfo {} /// Miri specific diagnostics pub enum NonHaltingDiagnostic { @@ -354,16 +345,14 @@ pub fn report_result<'tcx>( (title, helps) } else { let title = match res.kind() { - UndefinedBehavior(ValidationError(validation_err)) - if matches!( - validation_err.kind, - ValidationErrorKind::PointerAsInt { .. } | ValidationErrorKind::PartialPointer - ) => - { + UndefinedBehavior(UndefinedBehaviorInfo::ValidationError { + ptr_bytes_warning: true, + .. + }) => { ecx.handle_ice(); // print interpreter backtrace (this is outside the eval `catch_unwind`) bug!( "This validation error should be impossible in Miri: {}", - format_interp_error(ecx.tcx.dcx(), res) + format_interp_error(res) ); } UndefinedBehavior(_) => "Undefined Behavior", @@ -380,10 +369,7 @@ pub fn report_result<'tcx>( ) => "post-monomorphization error", _ => { ecx.handle_ice(); // print interpreter backtrace (this is outside the eval `catch_unwind`) - bug!( - "This error should be impossible in Miri: {}", - format_interp_error(ecx.tcx.dcx(), res) - ); + bug!("This error should be impossible in Miri: {}", format_interp_error(res)); } }; #[rustfmt::skip] @@ -411,10 +397,10 @@ pub fn report_result<'tcx>( match info { PointerUseAfterFree(alloc_id, _) | PointerOutOfBounds { alloc_id, .. } => { if let Some(span) = ecx.machine.allocated_span(*alloc_id) { - helps.push(note_span!(span, "{:?} was allocated here:", alloc_id)); + helps.push(note_span!(span, "{alloc_id} was allocated here:")); } if let Some(span) = ecx.machine.deallocated_span(*alloc_id) { - helps.push(note_span!(span, "{:?} was deallocated here:", alloc_id)); + helps.push(note_span!(span, "{alloc_id} was deallocated here:")); } } AbiMismatchArgument { .. } | AbiMismatchReturn { .. } => { @@ -447,7 +433,7 @@ pub fn report_result<'tcx>( UndefinedBehavior(InvalidUninitBytes(Some((alloc_id, access)))) => { writeln!( extra, - "Uninitialized memory occurred at {alloc_id:?}{range:?}, in this allocation:", + "Uninitialized memory occurred at {alloc_id}{range}, in this allocation:", range = access.bad, ) .unwrap(); @@ -460,7 +446,7 @@ pub fn report_result<'tcx>( if let Some(title) = title { write!(primary_msg, "{title}: ").unwrap(); } - write!(primary_msg, "{}", format_interp_error(ecx.tcx.dcx(), res)).unwrap(); + write!(primary_msg, "{}", format_interp_error(res)).unwrap(); if labels.is_empty() { labels.push(format!( @@ -510,7 +496,7 @@ pub fn report_leaks<'tcx>( let mut any_pruned = false; for (id, kind, alloc) in leaks { let mut title = format!( - "memory leaked: {id:?} ({}, size: {:?}, align: {:?})", + "memory leaked: {id:?} ({}, size: {}, align: {})", kind, alloc.size().bytes(), alloc.align.bytes() @@ -665,17 +651,17 @@ impl<'tcx> MiriMachine<'tcx> { format!("created {tag:?} with {perm} derived from unknown tag"), CreatedPointerTag(tag, Some(perm), Some((alloc_id, range, orig_tag))) => format!( - "created tag {tag:?} with {perm} at {alloc_id:?}{range:?} derived from {orig_tag:?}" + "created tag {tag:?} with {perm} at {alloc_id}{range} derived from {orig_tag:?}" ), PoppedPointerTag(item, cause) => format!("popped tracked tag for item {item:?}{cause}"), TrackingAlloc(id, size, align) => format!( - "now tracking allocation {id:?} of {size} bytes (alignment {align} bytes)", + "now tracking allocation {id} of {size} bytes (alignment {align} bytes)", size = size.bytes(), align = align.bytes(), ), AccessedAlloc(id, range, access_kind) => - format!("{access_kind} at {id:?}[{}..{}]", range.start.bytes(), range.end().bytes()), + format!("{access_kind} at {id}{range}"), FreedAlloc(id) => format!("freed allocation {id:?}"), RejectedIsolatedOp(op) => format!("{op} was made to return an error due to isolation"), ProgressReport { .. } => diff --git a/src/tools/miri/tests/pass/alloc-access-tracking.stderr b/src/tools/miri/tests/pass/alloc-access-tracking.stderr index f1c9241beded7..6c780e78e91b4 100644 --- a/src/tools/miri/tests/pass/alloc-access-tracking.stderr +++ b/src/tools/miri/tests/pass/alloc-access-tracking.stderr @@ -4,13 +4,13 @@ note: now tracking allocation ALLOC of 123 bytes (alignment ALIGN bytes) LL | utils::miri_track_alloc(ptr); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tracking was triggered here -note: write access at ALLOC[0..1] +note: write access at ALLOC[0x0..0x1] --> tests/pass/alloc-access-tracking.rs:LL:CC | LL | *ptr = 42; // Crucially, only a write is printed here, no read! | ^^^^^^^^^ tracking was triggered here -note: read access at ALLOC[0..1] +note: read access at ALLOC[0x0..0x1] --> tests/pass/alloc-access-tracking.rs:LL:CC | LL | assert_eq!(*ptr, 42); diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs index 111fe89e7eb0a..3c2cddb2516dc 100644 --- a/src/tools/tidy/src/style.rs +++ b/src/tools/tidy/src/style.rs @@ -227,8 +227,6 @@ fn should_ignore(line: &str) -> bool { /// Returns `true` if `line` is allowed to be longer than the normal limit. fn long_line_is_ok(extension: &str, is_error_code: bool, max_columns: usize, line: &str) -> bool { match extension { - // fluent files are allowed to be any length - "ftl" => true, // non-error code markdown is allowed to be any length "md" if !is_error_code => true, // HACK(Ezrashaw): there is no way to split a markdown header over multiple lines @@ -357,7 +355,7 @@ pub fn check(path: &Path, tidy_ctx: TidyCtx) { return false; } - let extensions = ["rs", "py", "js", "sh", "c", "cpp", "h", "md", "css", "ftl", "goml"]; + let extensions = ["rs", "py", "js", "sh", "c", "cpp", "h", "md", "css", "goml"]; // NB: don't skip paths without extensions (or else we'll skip all directories and will only check top level files) if path.extension().is_none_or(|ext| !extensions.iter().any(|e| ext == OsStr::new(e))) { @@ -602,12 +600,7 @@ pub fn check(path: &Path, tidy_ctx: TidyCtx) { err(DOUBLE_SPACE_AFTER_DOT) } - if filename.ends_with(".ftl") { - let line_backticks = trimmed.chars().filter(|ch| *ch == '`').count(); - if line_backticks % 2 == 1 { - suppressible_tidy_err!(err, skip_odd_backticks, "odd number of backticks"); - } - } else if trimmed.contains("//") { + if trimmed.contains("//") { let (start_line, mut backtick_count) = comment_block.unwrap_or((i + 1, 0)); let line_backticks = trimmed.chars().filter(|ch| *ch == '`').count(); let comment_text = trimmed.split("//").nth(1).unwrap(); diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index c16cfbe899b7b..50ec411987672 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -214,7 +214,6 @@ fn check_unexpected_extension(check: &mut RunningCheck, file_path: &Path, ext: & "stdout", // expected stdout file, corresponds to a rs file "fixed", // expected source file after applying fixes "md", // test directory descriptions - "ftl", // translation tests ]; const EXTENSION_EXCEPTION_PATHS: &[&str] = &[ diff --git a/tests/mir-opt/debuginfo/single_use_consts.invalid_debuginfo.SingleUseConsts.diff b/tests/mir-opt/debuginfo/single_use_consts.invalid_debuginfo.SingleUseConsts.diff new file mode 100644 index 0000000000000..09e9f26546a85 --- /dev/null +++ b/tests/mir-opt/debuginfo/single_use_consts.invalid_debuginfo.SingleUseConsts.diff @@ -0,0 +1,49 @@ +- // MIR for `invalid_debuginfo` before SingleUseConsts ++ // MIR for `invalid_debuginfo` after SingleUseConsts + + fn invalid_debuginfo() -> () { + let mut _0: (); + let _1: (); + scope 1 (inlined foo) { + let _2: (); + let mut _3: &isize; + let _4: &isize; + let _5: isize; + let mut _6: &isize; + scope 2 (inlined bar) { +- debug x => _4; ++ debug x => const foo::promoted[0]; + let _7: isize; + let mut _9: &isize; + let _10: &isize; + scope 3 { +- debug a => _7; ++ debug a => const 1_isize; + let mut _8: &isize; + scope 4 { +- debug z => _4; ++ debug z => const foo::promoted[0]; + } + } + } + } + + bb0: { + StorageLive(_1); + StorageLive(_4); +- _4 = const foo::promoted[0]; ++ nop; + StorageLive(_7); +- _7 = const 1_isize; +- // DBG: _4 = &_7; ++ nop; + StorageDead(_7); +- _1 = const (); ++ nop; + StorageDead(_4); + StorageDead(_1); + _0 = const (); + return; + } + } + diff --git a/tests/mir-opt/debuginfo/single_use_consts.rs b/tests/mir-opt/debuginfo/single_use_consts.rs new file mode 100644 index 0000000000000..eeae4cb7b81c5 --- /dev/null +++ b/tests/mir-opt/debuginfo/single_use_consts.rs @@ -0,0 +1,25 @@ +//@ test-mir-pass: SingleUseConsts +//@ compile-flags: -g -Zinline-mir -Zmir-enable-passes=+InstSimplify-after-simplifycfg,+DeadStoreElimination-final,+DestinationPropagation -Zvalidate-mir +//! Regression test for . + +#![crate_type = "lib"] + +// EMIT_MIR single_use_consts.invalid_debuginfo.SingleUseConsts.diff +pub fn invalid_debuginfo() { + // CHECK-LABEL: fn invalid_debuginfo( + // CHEK: debug x => const + // CHEK: debug z => const + // CHECK-NOT: DBG + // CHECK: return + foo(); +} + +pub fn foo() { + bar(&1); +} + +fn bar(x: &isize) { + let a = 1; + let mut z = x; + z = &a; +} diff --git a/tests/ui/borrowck/access-mode-in-closures.stderr b/tests/ui/borrowck/access-mode-in-closures.stderr index b9a45edb330c3..94593d51fdf52 100644 --- a/tests/ui/borrowck/access-mode-in-closures.stderr +++ b/tests/ui/borrowck/access-mode-in-closures.stderr @@ -2,10 +2,7 @@ error[E0507]: cannot move out of `s` which is behind a shared reference --> $DIR/access-mode-in-closures.rs:8:15 | LL | match *s { S(v) => v } - | ^^ - - | | - | data moved here - | move occurs because `v` has type `Vec`, which does not implement the `Copy` trait + | ^^ - data moved here because `v` has type `Vec`, which does not implement the `Copy` trait | help: consider removing the dereference here | diff --git a/tests/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.stderr b/tests/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.stderr index f9ced03e0f038..1ff5c78df7808 100644 --- a/tests/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.stderr +++ b/tests/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.stderr @@ -4,8 +4,7 @@ error[E0507]: cannot move out of a shared reference LL | for &a in x.iter() { | - ^^^^^^^^ | | - | data moved here - | move occurs because `a` has type `&mut i32`, which does not implement the `Copy` trait + | data moved here because `a` has type `&mut i32`, which does not implement the `Copy` trait | help: consider removing the borrow | @@ -19,8 +18,7 @@ error[E0507]: cannot move out of a shared reference LL | for &a in &f.a { | - ^^^^ | | - | data moved here - | move occurs because `a` has type `Box`, which does not implement the `Copy` trait + | data moved here because `a` has type `Box`, which does not implement the `Copy` trait | help: consider removing the borrow | @@ -34,8 +32,7 @@ error[E0507]: cannot move out of a shared reference LL | for &a in x.iter() { | - ^^^^^^^^ | | - | data moved here - | move occurs because `a` has type `Box`, which does not implement the `Copy` trait + | data moved here because `a` has type `Box`, which does not implement the `Copy` trait | help: consider removing the borrow | diff --git a/tests/ui/borrowck/borrowck-move-error-with-note.stderr b/tests/ui/borrowck/borrowck-move-error-with-note.stderr index 722c2c1443a7f..e9f0395fa0d41 100644 --- a/tests/ui/borrowck/borrowck-move-error-with-note.stderr +++ b/tests/ui/borrowck/borrowck-move-error-with-note.stderr @@ -44,10 +44,7 @@ error[E0507]: cannot move out of `a.a` which is behind a shared reference LL | match a.a { | ^^^ LL | n => { - | - - | | - | data moved here - | move occurs because `n` has type `Box`, which does not implement the `Copy` trait + | - data moved here because `n` has type `Box`, which does not implement the `Copy` trait | help: consider borrowing here | diff --git a/tests/ui/borrowck/borrowck-move-in-irrefut-pat.stderr b/tests/ui/borrowck/borrowck-move-in-irrefut-pat.stderr index 21bd073321b83..c67499c7d6d70 100644 --- a/tests/ui/borrowck/borrowck-move-in-irrefut-pat.stderr +++ b/tests/ui/borrowck/borrowck-move-in-irrefut-pat.stderr @@ -4,8 +4,7 @@ error[E0507]: cannot move out of a shared reference LL | fn arg_item(&_x: &String) {} | ^-- | | - | data moved here - | move occurs because `_x` has type `String`, which does not implement the `Copy` trait + | data moved here because `_x` has type `String`, which does not implement the `Copy` trait | help: consider removing the borrow | @@ -19,8 +18,7 @@ error[E0507]: cannot move out of a shared reference LL | with(|&_x| ()) | ^-- | | - | data moved here - | move occurs because `_x` has type `String`, which does not implement the `Copy` trait + | data moved here because `_x` has type `String`, which does not implement the `Copy` trait | help: consider removing the borrow | @@ -34,8 +32,7 @@ error[E0507]: cannot move out of a shared reference LL | let &_x = &"hi".to_string(); | -- ^^^^^^^^^^^^^^^^^ | | - | data moved here - | move occurs because `_x` has type `String`, which does not implement the `Copy` trait + | data moved here because `_x` has type `String`, which does not implement the `Copy` trait | help: consider removing the borrow | diff --git a/tests/ui/borrowck/borrowck-move-out-of-struct-with-dtor.stderr b/tests/ui/borrowck/borrowck-move-out-of-struct-with-dtor.stderr index 58f706c65ff28..fa77eddb49651 100644 --- a/tests/ui/borrowck/borrowck-move-out-of-struct-with-dtor.stderr +++ b/tests/ui/borrowck/borrowck-move-out-of-struct-with-dtor.stderr @@ -5,10 +5,7 @@ LL | match (S {f:"foo".to_string()}) { | ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here LL | LL | S {f:_s} => {} - | -- - | | - | data moved here - | move occurs because `_s` has type `String`, which does not implement the `Copy` trait + | -- data moved here because `_s` has type `String`, which does not implement the `Copy` trait | help: consider borrowing the pattern binding | @@ -21,8 +18,7 @@ error[E0509]: cannot move out of type `S`, which implements the `Drop` trait LL | let S {f:_s} = S {f:"foo".to_string()}; | -- ^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here | | - | data moved here - | move occurs because `_s` has type `String`, which does not implement the `Copy` trait + | data moved here because `_s` has type `String`, which does not implement the `Copy` trait | help: consider borrowing the pattern binding | @@ -35,8 +31,7 @@ error[E0509]: cannot move out of type `S`, which implements the `Drop` trait LL | fn move_in_fn_arg(S {f:_s}: S) { | ^^^^^--^ | | | - | | data moved here - | | move occurs because `_s` has type `String`, which does not implement the `Copy` trait + | | data moved here because `_s` has type `String`, which does not implement the `Copy` trait | cannot move out of here | help: consider borrowing the pattern binding diff --git a/tests/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.stderr b/tests/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.stderr index 160a1f99f63f6..17e9792b628d2 100644 --- a/tests/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.stderr +++ b/tests/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.stderr @@ -5,10 +5,7 @@ LL | match S("foo".to_string()) { | ^^^^^^^^^^^^^^^^^^^^ cannot move out of here LL | LL | S(_s) => {} - | -- - | | - | data moved here - | move occurs because `_s` has type `String`, which does not implement the `Copy` trait + | -- data moved here because `_s` has type `String`, which does not implement the `Copy` trait | help: consider borrowing the pattern binding | @@ -21,8 +18,7 @@ error[E0509]: cannot move out of type `S`, which implements the `Drop` trait LL | let S(_s) = S("foo".to_string()); | -- ^^^^^^^^^^^^^^^^^^^^ cannot move out of here | | - | data moved here - | move occurs because `_s` has type `String`, which does not implement the `Copy` trait + | data moved here because `_s` has type `String`, which does not implement the `Copy` trait | help: consider borrowing the pattern binding | @@ -35,8 +31,7 @@ error[E0509]: cannot move out of type `S`, which implements the `Drop` trait LL | fn move_in_fn_arg(S(_s): S) { | ^^--^ | | | - | | data moved here - | | move occurs because `_s` has type `String`, which does not implement the `Copy` trait + | | data moved here because `_s` has type `String`, which does not implement the `Copy` trait | cannot move out of here | help: consider borrowing the pattern binding diff --git a/tests/ui/borrowck/borrowck-vec-pattern-nesting.rs b/tests/ui/borrowck/borrowck-vec-pattern-nesting.rs index 400e5f010ecb2..657c4789aa30f 100644 --- a/tests/ui/borrowck/borrowck-vec-pattern-nesting.rs +++ b/tests/ui/borrowck/borrowck-vec-pattern-nesting.rs @@ -35,8 +35,7 @@ fn c() { //~^ ERROR cannot move out //~| NOTE cannot move out &mut [_a, - //~^ NOTE data moved here - //~| NOTE move occurs because `_a` has type + //~^ NOTE data moved here because `_a` has type //~| HELP consider removing the mutable borrow .. ] => { @@ -59,8 +58,7 @@ fn d() { &mut [ //~^ HELP consider removing the mutable borrow _b] => {} - //~^ NOTE data moved here - //~| NOTE move occurs because `_b` has type + //~^ NOTE data moved here because `_b` has type _ => {} } let a = vec[0]; //~ ERROR cannot move out diff --git a/tests/ui/borrowck/borrowck-vec-pattern-nesting.stderr b/tests/ui/borrowck/borrowck-vec-pattern-nesting.stderr index fff997fd5559f..a002b7e3d7f65 100644 --- a/tests/ui/borrowck/borrowck-vec-pattern-nesting.stderr +++ b/tests/ui/borrowck/borrowck-vec-pattern-nesting.stderr @@ -29,10 +29,7 @@ LL | match vec { | ^^^ cannot move out of here ... LL | &mut [_a, - | -- - | | - | data moved here - | move occurs because `_a` has type `Box`, which does not implement the `Copy` trait + | -- data moved here because `_a` has type `Box`, which does not implement the `Copy` trait | help: consider removing the mutable borrow | @@ -41,7 +38,7 @@ LL + [_a, | error[E0508]: cannot move out of type `[Box]`, a non-copy slice - --> $DIR/borrowck-vec-pattern-nesting.rs:46:13 + --> $DIR/borrowck-vec-pattern-nesting.rs:45:13 | LL | let a = vec[0]; | ^^^^^^ @@ -59,16 +56,13 @@ LL | let a = vec[0].clone(); | ++++++++ error[E0508]: cannot move out of type `[Box]`, a non-copy slice - --> $DIR/borrowck-vec-pattern-nesting.rs:56:11 + --> $DIR/borrowck-vec-pattern-nesting.rs:55:11 | LL | match vec { | ^^^ cannot move out of here ... LL | _b] => {} - | -- - | | - | data moved here - | move occurs because `_b` has type `Box`, which does not implement the `Copy` trait + | -- data moved here because `_b` has type `Box`, which does not implement the `Copy` trait | help: consider removing the mutable borrow | @@ -77,7 +71,7 @@ LL + [ | error[E0508]: cannot move out of type `[Box]`, a non-copy slice - --> $DIR/borrowck-vec-pattern-nesting.rs:66:13 + --> $DIR/borrowck-vec-pattern-nesting.rs:64:13 | LL | let a = vec[0]; | ^^^^^^ @@ -95,7 +89,7 @@ LL | let a = vec[0].clone(); | ++++++++ error[E0508]: cannot move out of type `[Box]`, a non-copy slice - --> $DIR/borrowck-vec-pattern-nesting.rs:76:11 + --> $DIR/borrowck-vec-pattern-nesting.rs:74:11 | LL | match vec { | ^^^ cannot move out of here @@ -114,7 +108,7 @@ LL + [_a, _b, _c] => {} | error[E0508]: cannot move out of type `[Box]`, a non-copy slice - --> $DIR/borrowck-vec-pattern-nesting.rs:87:13 + --> $DIR/borrowck-vec-pattern-nesting.rs:85:13 | LL | let a = vec[0]; | ^^^^^^ diff --git a/tests/ui/borrowck/issue-51301.stderr b/tests/ui/borrowck/issue-51301.stderr index c0b06437093a6..b5c06649e8643 100644 --- a/tests/ui/borrowck/issue-51301.stderr +++ b/tests/ui/borrowck/issue-51301.stderr @@ -4,8 +4,7 @@ error[E0507]: cannot move out of a shared reference LL | .find(|(&event_type, _)| event == event_type) | ^^----------^^^^ | | - | data moved here - | move occurs because `event_type` has type `EventType`, which does not implement the `Copy` trait + | data moved here because `event_type` has type `EventType`, which does not implement the `Copy` trait | help: consider borrowing the pattern binding | diff --git a/tests/ui/borrowck/issue-51415.stderr b/tests/ui/borrowck/issue-51415.stderr index e51e0b33ebd30..dd44c5e5f037e 100644 --- a/tests/ui/borrowck/issue-51415.stderr +++ b/tests/ui/borrowck/issue-51415.stderr @@ -4,8 +4,7 @@ error[E0507]: cannot move out of a shared reference LL | let opt = a.iter().enumerate().find(|(_, &s)| { | ^^^^^-^ | | - | data moved here - | move occurs because `s` has type `String`, which does not implement the `Copy` trait + | data moved here because `s` has type `String`, which does not implement the `Copy` trait | help: consider borrowing the pattern binding | diff --git a/tests/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.stderr b/tests/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.stderr index 45c7a8bb475a6..4e7797c93b516 100644 --- a/tests/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.stderr +++ b/tests/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.stderr @@ -4,8 +4,7 @@ error[E0509]: cannot move out of type `X`, which implements the `Drop` trait LL | let X { x: y } = x; | - ^ cannot move out of here | | - | data moved here - | move occurs because `y` has type `String`, which does not implement the `Copy` trait + | data moved here because `y` has type `String`, which does not implement the `Copy` trait | help: consider borrowing the pattern binding | diff --git a/tests/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.stderr b/tests/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.stderr index 837904cbae072..0b5f80fc5608c 100644 --- a/tests/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.stderr +++ b/tests/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.stderr @@ -5,10 +5,7 @@ LL | match x { | ^ cannot move out of here LL | LL | X { x: y } => println!("contents: {}", y) - | - - | | - | data moved here - | move occurs because `y` has type `String`, which does not implement the `Copy` trait + | - data moved here because `y` has type `String`, which does not implement the `Copy` trait | help: consider borrowing the pattern binding | diff --git a/tests/ui/eii/duplicate/eii-declaration-conflicts-with-constructor.rs b/tests/ui/eii/duplicate/eii-declaration-conflicts-with-constructor.rs new file mode 100644 index 0000000000000..23b930cddaa13 --- /dev/null +++ b/tests/ui/eii/duplicate/eii-declaration-conflicts-with-constructor.rs @@ -0,0 +1,11 @@ +#![feature(extern_item_impls)] + +// Regression test for : + +struct Foo(i32); + +#[eii] +pub fn Foo(x: u64) {} +//~^ ERROR the name `Foo` is defined multiple times + +fn main() {} diff --git a/tests/ui/eii/duplicate/eii-declaration-conflicts-with-constructor.stderr b/tests/ui/eii/duplicate/eii-declaration-conflicts-with-constructor.stderr new file mode 100644 index 0000000000000..e95ab395ff240 --- /dev/null +++ b/tests/ui/eii/duplicate/eii-declaration-conflicts-with-constructor.stderr @@ -0,0 +1,14 @@ +error[E0428]: the name `Foo` is defined multiple times + --> $DIR/eii-declaration-conflicts-with-constructor.rs:8:1 + | +LL | struct Foo(i32); + | ---------------- previous definition of the value `Foo` here +... +LL | pub fn Foo(x: u64) {} + | ^^^^^^^^^^^^^^^^^^ `Foo` redefined here + | + = note: `Foo` must be defined only once in the value namespace of this module + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak.rs b/tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak.rs index de4f523c23aa1..c2fab7d4c5f68 100644 --- a/tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak.rs +++ b/tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak.rs @@ -8,7 +8,7 @@ fn main() {} // Cycles should work as the deferred obligations are // independently resolved and only require the concrete // return type, which can't depend on the obligation. -fn cycle1() -> impl Clone { +fn cycle1() -> impl Clone { //~ ERROR: cycle detected send(cycle2().clone()); Rc::new(Cell::new(5)) @@ -16,7 +16,6 @@ fn cycle1() -> impl Clone { fn cycle2() -> impl Clone { send(cycle1().clone()); - //~^ ERROR: cannot check whether the hidden type of opaque type satisfies auto traits Rc::new(String::from("foo")) } diff --git a/tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak.stderr b/tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak.stderr index cc9939f2d57f9..ae10516999882 100644 --- a/tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak.stderr +++ b/tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak.stderr @@ -1,22 +1,84 @@ -error: cannot check whether the hidden type of opaque type satisfies auto traits - --> $DIR/auto-trait-leak.rs:18:10 +error[E0391]: cycle detected when computing type of opaque `cycle1::{opaque#0}` + --> $DIR/auto-trait-leak.rs:11:16 | -LL | send(cycle1().clone()); - | ---- ^^^^^^^^^^^^^^^^ - | | - | required by a bound introduced by this call +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^ | - = note: fetching the hidden types of an opaque inside of the defining scope is not supported. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule -note: opaque type is declared here - --> $DIR/auto-trait-leak.rs:11:16 +note: ...which requires borrow-checking `cycle1`... + --> $DIR/auto-trait-leak.rs:11:1 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires promoting constants in MIR for `cycle1`... + --> $DIR/auto-trait-leak.rs:11:1 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires checking if `cycle1` contains FFI-unwind calls... + --> $DIR/auto-trait-leak.rs:11:1 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires building MIR for `cycle1`... + --> $DIR/auto-trait-leak.rs:11:1 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires match-checking `cycle1`... + --> $DIR/auto-trait-leak.rs:11:1 | LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires type-checking `cycle1`... + --> $DIR/auto-trait-leak.rs:12:5 + | +LL | send(cycle2().clone()); + | ^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which requires evaluating trait selection obligation `cycle2::{opaque#0}: core::marker::Send`... +note: ...which requires computing type of opaque `cycle2::{opaque#0}`... + --> $DIR/auto-trait-leak.rs:17:16 + | +LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^ -note: required by a bound in `send` - --> $DIR/auto-trait-leak.rs:4:12 +note: ...which requires borrow-checking `cycle2`... + --> $DIR/auto-trait-leak.rs:17:1 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires promoting constants in MIR for `cycle2`... + --> $DIR/auto-trait-leak.rs:17:1 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires checking if `cycle2` contains FFI-unwind calls... + --> $DIR/auto-trait-leak.rs:17:1 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires building MIR for `cycle2`... + --> $DIR/auto-trait-leak.rs:17:1 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires match-checking `cycle2`... + --> $DIR/auto-trait-leak.rs:17:1 | -LL | fn send(_: T) {} - | ^^^^ required by this bound in `send` +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires type-checking `cycle2`... + --> $DIR/auto-trait-leak.rs:18:5 + | +LL | send(cycle1().clone()); + | ^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which requires evaluating trait selection obligation `cycle1::{opaque#0}: core::marker::Send`... + = note: ...which again requires computing type of opaque `cycle1::{opaque#0}`, completing the cycle +note: cycle used when computing type of `cycle1::{opaque#0}` + --> $DIR/auto-trait-leak.rs:11:16 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^ + = 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: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/moves/do-not-suggest-removing-wrong-ref-pattern-issue-132806.stderr b/tests/ui/moves/do-not-suggest-removing-wrong-ref-pattern-issue-132806.stderr index ff579f934137f..5f66c2eb67873 100644 --- a/tests/ui/moves/do-not-suggest-removing-wrong-ref-pattern-issue-132806.stderr +++ b/tests/ui/moves/do-not-suggest-removing-wrong-ref-pattern-issue-132806.stderr @@ -4,8 +4,7 @@ error[E0507]: cannot move out of a shared reference LL | let _ = HashMap::::new().iter().filter(|&(&_k, &_v)| { true }); | ^^^--^^^^^^ | | - | data moved here - | move occurs because `_k` has type `String`, which does not implement the `Copy` trait + | data moved here because `_k` has type `String`, which does not implement the `Copy` trait | help: consider removing the borrow | diff --git a/tests/ui/moves/invalid-suggestions-destructuring-assignment-drop.stderr b/tests/ui/moves/invalid-suggestions-destructuring-assignment-drop.stderr index c2bc85ee6beee..21f51907b5e7c 100644 --- a/tests/ui/moves/invalid-suggestions-destructuring-assignment-drop.stderr +++ b/tests/ui/moves/invalid-suggestions-destructuring-assignment-drop.stderr @@ -4,8 +4,7 @@ error[E0509]: cannot move out of type `Thing`, which implements the `Drop` trait LL | Thing(*&mut String::new()) = Thing(String::new()); | ------------------- ^^^^^^^^^^^^^^^^^^^^ cannot move out of here | | - | data moved here - | move occurs because the place has type `String`, which does not implement the `Copy` trait + | data moved here because the place has type `String`, which does not implement the `Copy` trait error: aborting due to 1 previous error diff --git a/tests/ui/moves/issue-99470-move-out-of-some.stderr b/tests/ui/moves/issue-99470-move-out-of-some.stderr index 71ec5adfdeace..59e4e7d073d96 100644 --- a/tests/ui/moves/issue-99470-move-out-of-some.stderr +++ b/tests/ui/moves/issue-99470-move-out-of-some.stderr @@ -5,10 +5,7 @@ LL | match x { | ^ LL | LL | &Some(_y) => (), - | -- - | | - | data moved here - | move occurs because `_y` has type `Box`, which does not implement the `Copy` trait + | -- data moved here because `_y` has type `Box`, which does not implement the `Copy` trait | help: consider removing the borrow | diff --git a/tests/ui/moves/move-out-of-array-ref.stderr b/tests/ui/moves/move-out-of-array-ref.stderr index 26d4996d6cb1d..5c3e0ad5872c9 100644 --- a/tests/ui/moves/move-out-of-array-ref.stderr +++ b/tests/ui/moves/move-out-of-array-ref.stderr @@ -4,8 +4,7 @@ error[E0508]: cannot move out of type `[D; 4]`, a non-copy array LL | let [_, e, _, _] = *a; | - ^^ cannot move out of here | | - | data moved here - | move occurs because `e` has type `D`, which does not implement the `Copy` trait + | data moved here because `e` has type `D`, which does not implement the `Copy` trait | help: consider removing the dereference here | @@ -19,8 +18,7 @@ error[E0508]: cannot move out of type `[D; 4]`, a non-copy array LL | let [_, s @ .. , _] = *a; | - ^^ cannot move out of here | | - | data moved here - | move occurs because `s` has type `[D; 2]`, which does not implement the `Copy` trait + | data moved here because `s` has type `[D; 2]`, which does not implement the `Copy` trait | help: consider removing the dereference here | @@ -34,8 +32,7 @@ error[E0508]: cannot move out of type `[D; 4]`, a non-copy array LL | let [_, e, _, _] = *a; | - ^^ cannot move out of here | | - | data moved here - | move occurs because `e` has type `D`, which does not implement the `Copy` trait + | data moved here because `e` has type `D`, which does not implement the `Copy` trait | help: consider removing the dereference here | @@ -49,8 +46,7 @@ error[E0508]: cannot move out of type `[D; 4]`, a non-copy array LL | let [_, s @ .. , _] = *a; | - ^^ cannot move out of here | | - | data moved here - | move occurs because `s` has type `[D; 2]`, which does not implement the `Copy` trait + | data moved here because `s` has type `[D; 2]`, which does not implement the `Copy` trait | help: consider removing the dereference here | diff --git a/tests/ui/moves/move-out-of-slice-1.stderr b/tests/ui/moves/move-out-of-slice-1.stderr index 86533714474b5..4b917554057c3 100644 --- a/tests/ui/moves/move-out-of-slice-1.stderr +++ b/tests/ui/moves/move-out-of-slice-1.stderr @@ -4,10 +4,7 @@ error[E0508]: cannot move out of type `[A]`, a non-copy slice LL | match a { | ^ cannot move out of here LL | box [a] => {}, - | - - | | - | data moved here - | move occurs because `a` has type `A`, which does not implement the `Copy` trait + | - data moved here because `a` has type `A`, which does not implement the `Copy` trait | help: consider borrowing the pattern binding | diff --git a/tests/ui/moves/moves-based-on-type-block-bad.stderr b/tests/ui/moves/moves-based-on-type-block-bad.stderr index 431ee1c0bb1bf..31417b59f0993 100644 --- a/tests/ui/moves/moves-based-on-type-block-bad.stderr +++ b/tests/ui/moves/moves-based-on-type-block-bad.stderr @@ -5,10 +5,7 @@ LL | match hellothere.x { | ^^^^^^^^^^^^ LL | box E::Foo(_) => {} LL | box E::Bar(x) => println!("{}", x.to_string()), - | - - | | - | data moved here - | move occurs because `x` has type `Box`, which does not implement the `Copy` trait + | - data moved here because `x` has type `Box`, which does not implement the `Copy` trait | help: consider borrowing here | diff --git a/tests/ui/nll/move-errors.stderr b/tests/ui/nll/move-errors.stderr index bcb2ab84a239b..c1ec357cab069 100644 --- a/tests/ui/nll/move-errors.stderr +++ b/tests/ui/nll/move-errors.stderr @@ -108,8 +108,7 @@ error[E0507]: cannot move out of `a` which is behind a shared reference LL | let A(s) = *a; | - ^^ | | - | data moved here - | move occurs because `s` has type `String`, which does not implement the `Copy` trait + | data moved here because `s` has type `String`, which does not implement the `Copy` trait | help: consider removing the dereference here | @@ -123,8 +122,7 @@ error[E0509]: cannot move out of type `D`, which implements the `Drop` trait LL | let C(D(s)) = c; | - ^ cannot move out of here | | - | data moved here - | move occurs because `s` has type `String`, which does not implement the `Copy` trait + | data moved here because `s` has type `String`, which does not implement the `Copy` trait | help: consider borrowing the pattern binding | @@ -170,10 +168,7 @@ LL | match x { | ^ cannot move out of here ... LL | B::U(D(s)) => (), - | - - | | - | data moved here - | move occurs because `s` has type `String`, which does not implement the `Copy` trait + | - data moved here because `s` has type `String`, which does not implement the `Copy` trait | help: consider borrowing the pattern binding | @@ -187,10 +182,7 @@ LL | match x { | ^ cannot move out of here ... LL | (D(s), &t) => (), - | - - | | - | data moved here - | move occurs because `s` has type `String`, which does not implement the `Copy` trait + | - data moved here because `s` has type `String`, which does not implement the `Copy` trait | help: consider borrowing the pattern binding | @@ -204,10 +196,7 @@ LL | match x { | ^ ... LL | (D(s), &t) => (), - | - - | | - | data moved here - | move occurs because `t` has type `String`, which does not implement the `Copy` trait + | - data moved here because `t` has type `String`, which does not implement the `Copy` trait | help: consider removing the borrow | @@ -243,10 +232,7 @@ LL | match *x { | ^^ LL | LL | Ok(s) | Err(s) => (), - | - - | | - | data moved here - | move occurs because `s` has type `String`, which does not implement the `Copy` trait + | - data moved here because `s` has type `String`, which does not implement the `Copy` trait | help: consider removing the dereference here | diff --git a/tests/ui/pattern/by-move-pattern-binding.stderr b/tests/ui/pattern/by-move-pattern-binding.stderr index 203e37dc387c1..4a65bf3ea27f5 100644 --- a/tests/ui/pattern/by-move-pattern-binding.stderr +++ b/tests/ui/pattern/by-move-pattern-binding.stderr @@ -5,10 +5,7 @@ LL | match &s.x { | ^^^^ LL | &E::Foo => {} LL | &E::Bar(identifier) => f(identifier.clone()) - | ---------- - | | - | data moved here - | move occurs because `identifier` has type `String`, which does not implement the `Copy` trait + | ---------- data moved here because `identifier` has type `String`, which does not implement the `Copy` trait | help: consider removing the borrow | @@ -22,8 +19,7 @@ error[E0507]: cannot move out of a shared reference LL | if let &E::Bar(identifier) = &s.x { | ---------- ^^^^ | | - | data moved here - | move occurs because `identifier` has type `String`, which does not implement the `Copy` trait + | data moved here because `identifier` has type `String`, which does not implement the `Copy` trait | help: consider removing the borrow | @@ -37,8 +33,7 @@ error[E0507]: cannot move out of a shared reference LL | let &E::Bar(identifier) = &s.x else { | ---------- ^^^^ | | - | data moved here - | move occurs because `identifier` has type `String`, which does not implement the `Copy` trait + | data moved here because `identifier` has type `String`, which does not implement the `Copy` trait | help: consider removing the borrow | diff --git a/tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.stderr b/tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.stderr index 532dd496b235f..119b86d528857 100644 --- a/tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.stderr +++ b/tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.stderr @@ -5,10 +5,7 @@ LL | match b { | ^ cannot move out of here LL | LL | deref!([x]) => x, - | - - | | - | data moved here - | move occurs because `x` has type `Struct`, which does not implement the `Copy` trait + | - data moved here because `x` has type `Struct`, which does not implement the `Copy` trait | help: consider borrowing the pattern binding | @@ -22,10 +19,7 @@ LL | match rc { | ^^ LL | LL | deref!(x) => x, - | - - | | - | data moved here - | move occurs because `x` has type `Struct`, which does not implement the `Copy` trait + | - data moved here because `x` has type `Struct`, which does not implement the `Copy` trait | help: consider borrowing the pattern binding | @@ -39,10 +33,7 @@ LL | match b { | ^ cannot move out of here LL | LL | [x] => x, - | - - | | - | data moved here - | move occurs because `x` has type `Struct`, which does not implement the `Copy` trait + | - data moved here because `x` has type `Struct`, which does not implement the `Copy` trait | help: consider borrowing the pattern binding | @@ -56,10 +47,7 @@ LL | match rc { | ^^ LL | LL | Container(x) => x, - | - - | | - | data moved here - | move occurs because `x` has type `Struct`, which does not implement the `Copy` trait + | - data moved here because `x` has type `Struct`, which does not implement the `Copy` trait | help: consider borrowing the pattern binding | diff --git a/tests/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.stderr b/tests/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.stderr index 85379d6605bca..6e974b4f4da00 100644 --- a/tests/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.stderr +++ b/tests/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.stderr @@ -4,8 +4,7 @@ error[E0507]: cannot move out of a mutable reference LL | let (a, mut b) = &mut p; | ----- ^^^^^^ | | - | data moved here - | move occurs because `b` has type `U`, which does not implement the `Copy` trait + | data moved here because `b` has type `U`, which does not implement the `Copy` trait | help: consider borrowing the pattern binding | diff --git a/tests/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.stderr b/tests/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.stderr index 494e5e2b2e85f..2be222d19e685 100644 --- a/tests/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.stderr +++ b/tests/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.stderr @@ -4,8 +4,7 @@ error[E0507]: cannot move out of a shared reference LL | let (a, mut b) = &p; | ----- ^^ | | - | data moved here - | move occurs because `b` has type `U`, which does not implement the `Copy` trait + | data moved here because `b` has type `U`, which does not implement the `Copy` trait | help: consider borrowing the pattern binding | diff --git a/tests/ui/pattern/mut-pattern-of-immutable-borrow.stderr b/tests/ui/pattern/mut-pattern-of-immutable-borrow.stderr index be1b5fadb0dd0..f9ef1efa6b2e5 100644 --- a/tests/ui/pattern/mut-pattern-of-immutable-borrow.stderr +++ b/tests/ui/pattern/mut-pattern-of-immutable-borrow.stderr @@ -4,10 +4,7 @@ error[E0507]: cannot move out of `arg.field` as enum variant `Some` which is beh LL | match arg.field { | ^^^^^^^^^ LL | Some(s) => s.push('a'), - | - - | | - | data moved here - | move occurs because `s` has type `String`, which does not implement the `Copy` trait + | - data moved here because `s` has type `String`, which does not implement the `Copy` trait | help: consider borrowing here | @@ -31,10 +28,7 @@ error[E0507]: cannot move out of a shared reference LL | match &arg.field { | ^^^^^^^^^^ LL | Some(mut s) => s.push('a'), - | ----- - | | - | data moved here - | move occurs because `s` has type `String`, which does not implement the `Copy` trait + | ----- data moved here because `s` has type `String`, which does not implement the `Copy` trait | help: consider borrowing the pattern binding | diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2021.stderr index 6391619fddf0e..ba1654c64d928 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2021.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2021.stderr @@ -4,8 +4,7 @@ error[E0507]: cannot move out of a shared reference LL | if let Some(&Some(x)) = Some(&Some(&mut 0)) { | - ^^^^^^^^^^^^^^^^^^^ | | - | data moved here - | move occurs because `x` has type `&mut u32`, which does not implement the `Copy` trait + | data moved here because `x` has type `&mut u32`, which does not implement the `Copy` trait | help: consider removing the borrow | diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2024.stderr index 1106342e62e49..102d44e7b523b 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2024.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2024.stderr @@ -4,8 +4,7 @@ error[E0508]: cannot move out of type `[&mut i32; 1]`, a non-copy array LL | let [&x] = &[&mut 0]; | - ^^^^^^^^^ cannot move out of here | | - | data moved here - | move occurs because `x` has type `&mut i32`, which does not implement the `Copy` trait + | data moved here because `x` has type `&mut i32`, which does not implement the `Copy` trait | help: consider borrowing the pattern binding | @@ -18,8 +17,7 @@ error[E0508]: cannot move out of type `[&mut i32; 1]`, a non-copy array LL | let [&x] = &mut [&mut 0]; | - ^^^^^^^^^^^^^ cannot move out of here | | - | data moved here - | move occurs because `x` has type `&mut i32`, which does not implement the `Copy` trait + | data moved here because `x` has type `&mut i32`, which does not implement the `Copy` trait | help: consider borrowing the pattern binding | @@ -32,8 +30,7 @@ error[E0507]: cannot move out of a shared reference LL | if let Some(&Some(x)) = Some(&Some(&mut 0)) { | - ^^^^^^^^^^^^^^^^^^^ | | - | data moved here - | move occurs because `x` has type `&mut u32`, which does not implement the `Copy` trait + | data moved here because `x` has type `&mut u32`, which does not implement the `Copy` trait | help: consider removing the borrow | @@ -69,8 +66,7 @@ error[E0508]: cannot move out of type `[&mut i32; 1]`, a non-copy array LL | let [&mut x] = &mut [&mut 0]; | - ^^^^^^^^^^^^^ cannot move out of here | | - | data moved here - | move occurs because `x` has type `&mut i32`, which does not implement the `Copy` trait + | data moved here because `x` has type `&mut i32`, which does not implement the `Copy` trait | help: consider borrowing the pattern binding | diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.stable2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.stable2021.stderr index ac84fdf7f95ff..f9e61394cb519 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.stable2021.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.stable2021.stderr @@ -36,8 +36,7 @@ error[E0507]: cannot move out of a shared reference LL | if let Some(&Some(x)) = Some(&Some(&mut 0)) { | - ^^^^^^^^^^^^^^^^^^^ | | - | data moved here - | move occurs because `x` has type `&mut u32`, which does not implement the `Copy` trait + | data moved here because `x` has type `&mut u32`, which does not implement the `Copy` trait | help: consider removing the borrow | diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural2021.stderr index 0e431326cb915..ac53c0dc89f83 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural2021.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural2021.stderr @@ -4,8 +4,7 @@ error[E0507]: cannot move out of a shared reference LL | if let Some(&Some(x)) = Some(&Some(&mut 0)) { | - ^^^^^^^^^^^^^^^^^^^ | | - | data moved here - | move occurs because `x` has type `&mut u32`, which does not implement the `Copy` trait + | data moved here because `x` has type `&mut u32`, which does not implement the `Copy` trait | help: consider removing the borrow | diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural2024.stderr index 0e431326cb915..ac53c0dc89f83 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural2024.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural2024.stderr @@ -4,8 +4,7 @@ error[E0507]: cannot move out of a shared reference LL | if let Some(&Some(x)) = Some(&Some(&mut 0)) { | - ^^^^^^^^^^^^^^^^^^^ | | - | data moved here - | move occurs because `x` has type `&mut u32`, which does not implement the `Copy` trait + | data moved here because `x` has type `&mut u32`, which does not implement the `Copy` trait | help: consider removing the borrow | diff --git a/tests/ui/pin-ergonomics/pin-pattern.stderr b/tests/ui/pin-ergonomics/pin-pattern.stderr index 49f7a396f3ce2..c0e8b2d40c70f 100644 --- a/tests/ui/pin-ergonomics/pin-pattern.stderr +++ b/tests/ui/pin-ergonomics/pin-pattern.stderr @@ -91,8 +91,7 @@ error[E0507]: cannot move out of `foo_mut.pointer` which is behind a mutable ref LL | let &pin mut Foo(x) = foo_mut; | - ^^^^^^^ | | - | data moved here - | move occurs because `x` has type `T`, which does not implement the `Copy` trait + | data moved here because `x` has type `T`, which does not implement the `Copy` trait | help: consider removing the pinned mutable borrow | @@ -106,8 +105,7 @@ error[E0507]: cannot move out of `foo_const.pointer` which is behind a shared re LL | let &pin const Foo(x) = foo_const; | - ^^^^^^^^^ | | - | data moved here - | move occurs because `x` has type `T`, which does not implement the `Copy` trait + | data moved here because `x` has type `T`, which does not implement the `Copy` trait | help: consider removing the pinned borrow | @@ -138,8 +136,7 @@ error[E0507]: cannot move out of a mutable reference LL | ((&pin mut x,),): &'a pin mut (&'a mut (&'a pin mut Foo,),), | ^^^^^^^^^^^-^^^^ | | - | data moved here - | move occurs because `x` has type `Foo`, which does not implement the `Copy` trait + | data moved here because `x` has type `Foo`, which does not implement the `Copy` trait | help: consider borrowing the pattern binding | diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/for.stderr b/tests/ui/rfcs/rfc-2005-default-binding-mode/for.stderr index 8f720daf11ee6..48aba17db3c26 100644 --- a/tests/ui/rfcs/rfc-2005-default-binding-mode/for.stderr +++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/for.stderr @@ -4,8 +4,7 @@ error[E0507]: cannot move out of a shared reference LL | for (n, mut m) in &tups { | ----- ^^^^^ | | - | data moved here - | move occurs because `m` has type `Foo`, which does not implement the `Copy` trait + | data moved here because `m` has type `Foo`, which does not implement the `Copy` trait | help: consider borrowing the pattern binding | diff --git a/tests/ui/suggestions/dont-suggest-ref/move-into-closure.stderr b/tests/ui/suggestions/dont-suggest-ref/move-into-closure.stderr index 99409dfd5c5e8..03f02223165da 100644 --- a/tests/ui/suggestions/dont-suggest-ref/move-into-closure.stderr +++ b/tests/ui/suggestions/dont-suggest-ref/move-into-closure.stderr @@ -9,8 +9,7 @@ LL | consume_fn(|| { LL | let X(_t) = x; | -- ^ | | - | data moved here - | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | data moved here because `_t` has type `Y`, which does not implement the `Copy` trait | help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:14:18 @@ -34,8 +33,7 @@ LL | consume_fn(|| { LL | if let Either::One(_t) = e { } | -- ^ | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:14:18 @@ -59,8 +57,7 @@ LL | consume_fn(|| { LL | while let Either::One(_t) = e { } | -- ^ | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:14:18 @@ -85,10 +82,7 @@ LL | match e { | ^ ... LL | Either::One(_t) - | -- - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | -- data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:14:18 @@ -113,10 +107,7 @@ LL | match e { | ^ ... LL | Either::One(_t) => (), - | -- - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | -- data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:14:18 @@ -140,8 +131,7 @@ LL | consume_fn(|| { LL | let X(mut _t) = x; | ------ ^ | | - | data moved here - | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | data moved here because `_t` has type `Y`, which does not implement the `Copy` trait | help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:14:18 @@ -165,8 +155,7 @@ LL | consume_fn(|| { LL | if let Either::One(mut _t) = em { } | ------ ^^ | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:14:18 @@ -190,8 +179,7 @@ LL | consume_fn(|| { LL | while let Either::One(mut _t) = em { } | ------ ^^ | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:14:18 @@ -216,10 +204,7 @@ LL | match em { | ^^ ... LL | Either::One(mut _t) - | ------ - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | ------ data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:14:18 @@ -244,10 +229,7 @@ LL | match em { | ^^ ... LL | Either::One(mut _t) => (), - | ------ - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | ------ data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:14:18 @@ -270,8 +252,7 @@ LL | <() as T>::consume_fn(|| { LL | let X(_t) = x; | -- ^ | | - | data moved here - | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | data moved here because `_t` has type `Y`, which does not implement the `Copy` trait | help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:40:22 @@ -295,8 +276,7 @@ LL | <() as T>::consume_fn(|| { LL | if let Either::One(_t) = e { } | -- ^ | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:40:22 @@ -320,8 +300,7 @@ LL | <() as T>::consume_fn(|| { LL | while let Either::One(_t) = e { } | -- ^ | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:40:22 @@ -346,10 +325,7 @@ LL | match e { | ^ ... LL | Either::One(_t) - | -- - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | -- data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:40:22 @@ -374,10 +350,7 @@ LL | match e { | ^ ... LL | Either::One(_t) => (), - | -- - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | -- data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:40:22 @@ -401,8 +374,7 @@ LL | <() as T>::consume_fn(|| { LL | let X(mut _t) = x; | ------ ^ | | - | data moved here - | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | data moved here because `_t` has type `Y`, which does not implement the `Copy` trait | help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:40:22 @@ -426,8 +398,7 @@ LL | <() as T>::consume_fn(|| { LL | if let Either::One(mut _t) = em { } | ------ ^^ | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:40:22 @@ -451,8 +422,7 @@ LL | <() as T>::consume_fn(|| { LL | while let Either::One(mut _t) = em { } | ------ ^^ | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:40:22 @@ -477,10 +447,7 @@ LL | match em { | ^^ ... LL | Either::One(mut _t) - | ------ - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | ------ data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:40:22 @@ -505,10 +472,7 @@ LL | match em { | ^^ ... LL | Either::One(mut _t) => (), - | ------ - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | ------ data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:40:22 @@ -531,8 +495,7 @@ LL | ().method_consume_fn(|| { LL | let X(_t) = x; | -- ^ | | - | data moved here - | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | data moved here because `_t` has type `Y`, which does not implement the `Copy` trait | help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:51:29 @@ -556,8 +519,7 @@ LL | ().method_consume_fn(|| { LL | if let Either::One(_t) = e { } | -- ^ | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:51:29 @@ -581,8 +543,7 @@ LL | ().method_consume_fn(|| { LL | while let Either::One(_t) = e { } | -- ^ | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:51:29 @@ -607,10 +568,7 @@ LL | match e { | ^ ... LL | Either::One(_t) - | -- - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | -- data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:51:29 @@ -635,10 +593,7 @@ LL | match e { | ^ ... LL | Either::One(_t) => (), - | -- - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | -- data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:51:29 @@ -662,8 +617,7 @@ LL | ().method_consume_fn(|| { LL | let X(mut _t) = x; | ------ ^ | | - | data moved here - | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | data moved here because `_t` has type `Y`, which does not implement the `Copy` trait | help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:51:29 @@ -687,8 +641,7 @@ LL | ().method_consume_fn(|| { LL | if let Either::One(mut _t) = em { } | ------ ^^ | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:51:29 @@ -712,8 +665,7 @@ LL | ().method_consume_fn(|| { LL | while let Either::One(mut _t) = em { } | ------ ^^ | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:51:29 @@ -738,10 +690,7 @@ LL | match em { | ^^ ... LL | Either::One(mut _t) - | ------ - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | ------ data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:51:29 @@ -766,10 +715,7 @@ LL | match em { | ^^ ... LL | Either::One(mut _t) => (), - | ------ - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | ------ data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:51:29 @@ -792,8 +738,7 @@ LL | consume_fnmut(|| { LL | let X(_t) = x; | -- ^ | | - | data moved here - | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | data moved here because `_t` has type `Y`, which does not implement the `Copy` trait | help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:26:21 @@ -817,8 +762,7 @@ LL | consume_fnmut(|| { LL | if let Either::One(_t) = e { } | -- ^ | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:26:21 @@ -842,8 +786,7 @@ LL | consume_fnmut(|| { LL | while let Either::One(_t) = e { } | -- ^ | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:26:21 @@ -868,10 +811,7 @@ LL | match e { | ^ ... LL | Either::One(_t) - | -- - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | -- data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:26:21 @@ -896,10 +836,7 @@ LL | match e { | ^ ... LL | Either::One(_t) => (), - | -- - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | -- data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:26:21 @@ -923,8 +860,7 @@ LL | consume_fnmut(|| { LL | let X(mut _t) = x; | ------ ^ | | - | data moved here - | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | data moved here because `_t` has type `Y`, which does not implement the `Copy` trait | help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:26:21 @@ -948,8 +884,7 @@ LL | consume_fnmut(|| { LL | if let Either::One(mut _t) = em { } | ------ ^^ | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:26:21 @@ -973,8 +908,7 @@ LL | consume_fnmut(|| { LL | while let Either::One(mut _t) = em { } | ------ ^^ | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:26:21 @@ -999,10 +933,7 @@ LL | match em { | ^^ ... LL | Either::One(mut _t) - | ------ - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | ------ data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:26:21 @@ -1027,10 +958,7 @@ LL | match em { | ^^ ... LL | Either::One(mut _t) => (), - | ------ - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | ------ data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:26:21 @@ -1055,10 +983,7 @@ LL | match em { | ^^ ... LL | Either::One(mut _t) => (), - | ------ - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | ------ data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:26:21 diff --git a/tests/ui/suggestions/dont-suggest-ref/simple.stderr b/tests/ui/suggestions/dont-suggest-ref/simple.stderr index 41571bf9b2ca4..8e7582fbe588e 100644 --- a/tests/ui/suggestions/dont-suggest-ref/simple.stderr +++ b/tests/ui/suggestions/dont-suggest-ref/simple.stderr @@ -4,8 +4,7 @@ error[E0507]: cannot move out of `s` which is behind a shared reference LL | let X(_t) = *s; | -- ^^ | | - | data moved here - | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | data moved here because `_t` has type `Y`, which does not implement the `Copy` trait | help: consider removing the dereference here | @@ -19,8 +18,7 @@ error[E0507]: cannot move out of `r` as enum variant `One` which is behind a sha LL | if let Either::One(_t) = *r { } | -- ^^ | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: consider removing the dereference here | @@ -34,8 +32,7 @@ error[E0507]: cannot move out of `r` as enum variant `One` which is behind a sha LL | while let Either::One(_t) = *r { } | -- ^^ | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: consider removing the dereference here | @@ -50,10 +47,7 @@ LL | match *r { | ^^ ... LL | Either::One(_t) - | -- - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | -- data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: consider removing the dereference here | @@ -68,10 +62,7 @@ LL | match *r { | ^^ ... LL | Either::One(_t) => (), - | -- - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | -- data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: consider removing the dereference here | @@ -85,8 +76,7 @@ error[E0507]: cannot move out of `sm` which is behind a mutable reference LL | let X(_t) = *sm; | -- ^^^ | | - | data moved here - | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | data moved here because `_t` has type `Y`, which does not implement the `Copy` trait | help: consider removing the dereference here | @@ -100,8 +90,7 @@ error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mu LL | if let Either::One(_t) = *rm { } | -- ^^^ | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: consider removing the dereference here | @@ -115,8 +104,7 @@ error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mu LL | while let Either::One(_t) = *rm { } | -- ^^^ | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: consider removing the dereference here | @@ -131,10 +119,7 @@ LL | match *rm { | ^^^ ... LL | Either::One(_t) - | -- - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | -- data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: consider removing the dereference here | @@ -149,10 +134,7 @@ LL | match *rm { | ^^^ ... LL | Either::One(_t) => (), - | -- - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | -- data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: consider removing the dereference here | @@ -167,10 +149,7 @@ LL | match *rm { | ^^^ ... LL | Either::One(_t) => (), - | -- - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | -- data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: consider removing the dereference here | @@ -184,8 +163,7 @@ error[E0507]: cannot move out of index of `Vec` LL | let X(_t) = vs[0]; | -- ^^^^^ | | - | data moved here - | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | data moved here because `_t` has type `Y`, which does not implement the `Copy` trait | help: consider borrowing here | @@ -198,8 +176,7 @@ error[E0507]: cannot move out of index of `Vec` LL | if let Either::One(_t) = vr[0] { } | -- ^^^^^ | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: consider borrowing here | @@ -212,8 +189,7 @@ error[E0507]: cannot move out of index of `Vec` LL | while let Either::One(_t) = vr[0] { } | -- ^^^^^ | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: consider borrowing here | @@ -227,10 +203,7 @@ LL | match vr[0] { | ^^^^^ ... LL | Either::One(_t) - | -- - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | -- data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: consider borrowing here | @@ -244,10 +217,7 @@ LL | match vr[0] { | ^^^^^ ... LL | Either::One(_t) => (), - | -- - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | -- data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: consider borrowing here | @@ -260,8 +230,7 @@ error[E0507]: cannot move out of index of `Vec` LL | let X(_t) = vsm[0]; | -- ^^^^^^ | | - | data moved here - | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | data moved here because `_t` has type `Y`, which does not implement the `Copy` trait | help: consider borrowing here | @@ -274,8 +243,7 @@ error[E0507]: cannot move out of index of `Vec` LL | if let Either::One(_t) = vrm[0] { } | -- ^^^^^^ | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: consider borrowing here | @@ -288,8 +256,7 @@ error[E0507]: cannot move out of index of `Vec` LL | while let Either::One(_t) = vrm[0] { } | -- ^^^^^^ | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: consider borrowing here | @@ -303,10 +270,7 @@ LL | match vrm[0] { | ^^^^^^ ... LL | Either::One(_t) - | -- - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | -- data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: consider borrowing here | @@ -320,10 +284,7 @@ LL | match vrm[0] { | ^^^^^^ ... LL | Either::One(_t) => (), - | -- - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | -- data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: consider borrowing here | @@ -337,10 +298,7 @@ LL | match vrm[0] { | ^^^^^^ ... LL | Either::One(_t) => (), - | -- - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | -- data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: consider borrowing here | @@ -353,8 +311,7 @@ error[E0507]: cannot move out of `s` which is behind a shared reference LL | let &X(_t) = s; | -- ^ | | - | data moved here - | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | data moved here because `_t` has type `Y`, which does not implement the `Copy` trait | help: consider removing the borrow | @@ -368,8 +325,7 @@ error[E0507]: cannot move out of `r` as enum variant `One` which is behind a sha LL | if let &Either::One(_t) = r { } | -- ^ | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: consider removing the borrow | @@ -383,8 +339,7 @@ error[E0507]: cannot move out of `r` as enum variant `One` which is behind a sha LL | while let &Either::One(_t) = r { } | -- ^ | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: consider removing the borrow | @@ -399,10 +354,7 @@ LL | match r { | ^ LL | LL | &Either::One(_t) - | -- - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | -- data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: consider removing the borrow | @@ -417,10 +369,7 @@ LL | match r { | ^ LL | LL | &Either::One(_t) => (), - | -- - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | -- data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: consider removing the borrow | @@ -435,10 +384,7 @@ LL | match r { | ^ LL | LL | &Either::One(_t) => (), - | -- - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | -- data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: consider removing the borrow | @@ -452,8 +398,7 @@ error[E0507]: cannot move out of `sm` which is behind a mutable reference LL | let &mut X(_t) = sm; | -- ^^ | | - | data moved here - | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | data moved here because `_t` has type `Y`, which does not implement the `Copy` trait | help: consider removing the mutable borrow | @@ -467,8 +412,7 @@ error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mu LL | if let &mut Either::One(_t) = rm { } | -- ^^ | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: consider removing the mutable borrow | @@ -482,8 +426,7 @@ error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mu LL | while let &mut Either::One(_t) = rm { } | -- ^^ | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: consider removing the mutable borrow | @@ -522,10 +465,7 @@ LL | match rm { | ^^ LL | LL | &mut Either::One(_t) => (), - | -- - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | -- data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: consider removing the mutable borrow | @@ -540,10 +480,7 @@ LL | match rm { | ^^ LL | LL | &mut Either::One(_t) => (), - | -- - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | -- data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: consider removing the mutable borrow | @@ -558,10 +495,7 @@ LL | match rm { | ^^ LL | LL | &mut Either::One(_t) => (), - | -- - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | -- data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: consider removing the mutable borrow | @@ -575,8 +509,7 @@ error[E0507]: cannot move out of a shared reference LL | let (&X(_t),) = (&x.clone(),); | -- ^^^^^^^^^^^^^ | | - | data moved here - | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | data moved here because `_t` has type `Y`, which does not implement the `Copy` trait | help: consider removing the borrow | @@ -590,8 +523,7 @@ error[E0507]: cannot move out of a shared reference LL | if let (&Either::One(_t),) = (&e.clone(),) { } | -- ^^^^^^^^^^^^^ | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: consider removing the borrow | @@ -605,8 +537,7 @@ error[E0507]: cannot move out of a shared reference LL | while let (&Either::One(_t),) = (&e.clone(),) { } | -- ^^^^^^^^^^^^^ | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: consider removing the borrow | @@ -621,10 +552,7 @@ LL | match (&e.clone(),) { | ^^^^^^^^^^^^^ LL | LL | (&Either::One(_t),) - | -- - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | -- data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: consider removing the borrow | @@ -638,8 +566,7 @@ error[E0507]: cannot move out of a mutable reference LL | let (&mut X(_t),) = (&mut xm.clone(),); | -- ^^^^^^^^^^^^^^^^^^ | | - | data moved here - | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | data moved here because `_t` has type `Y`, which does not implement the `Copy` trait | help: consider removing the mutable borrow | @@ -653,8 +580,7 @@ error[E0507]: cannot move out of a mutable reference LL | if let (&mut Either::One(_t),) = (&mut em.clone(),) { } | -- ^^^^^^^^^^^^^^^^^^ | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: consider removing the mutable borrow | @@ -668,8 +594,7 @@ error[E0507]: cannot move out of a mutable reference LL | while let (&mut Either::One(_t),) = (&mut em.clone(),) { } | -- ^^^^^^^^^^^^^^^^^^ | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: consider removing the mutable borrow | @@ -707,8 +632,7 @@ error[E0507]: cannot move out of a shared reference LL | let &X(_t) = &x; | -- ^^ | | - | data moved here - | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | data moved here because `_t` has type `Y`, which does not implement the `Copy` trait | help: consider removing the borrow | @@ -722,8 +646,7 @@ error[E0507]: cannot move out of a shared reference LL | if let &Either::One(_t) = &e { } | -- ^^ | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: consider removing the borrow | @@ -737,8 +660,7 @@ error[E0507]: cannot move out of a shared reference LL | while let &Either::One(_t) = &e { } | -- ^^ | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: consider removing the borrow | @@ -753,10 +675,7 @@ LL | match &e { | ^^ LL | LL | &Either::One(_t) - | -- - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | -- data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: consider removing the borrow | @@ -771,10 +690,7 @@ LL | match &e { | ^^ LL | LL | &Either::One(_t) => (), - | -- - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | -- data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: consider removing the borrow | @@ -789,10 +705,7 @@ LL | match &e { | ^^ LL | LL | &Either::One(_t) => (), - | -- - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | -- data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: consider removing the borrow | @@ -806,8 +719,7 @@ error[E0507]: cannot move out of a mutable reference LL | let &mut X(_t) = &mut xm; | -- ^^^^^^^ | | - | data moved here - | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | data moved here because `_t` has type `Y`, which does not implement the `Copy` trait | help: consider removing the mutable borrow | @@ -821,8 +733,7 @@ error[E0507]: cannot move out of a mutable reference LL | if let &mut Either::One(_t) = &mut em { } | -- ^^^^^^^ | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: consider removing the mutable borrow | @@ -836,8 +747,7 @@ error[E0507]: cannot move out of a mutable reference LL | while let &mut Either::One(_t) = &mut em { } | -- ^^^^^^^ | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: consider removing the mutable borrow | @@ -852,10 +762,7 @@ LL | match &mut em { | ^^^^^^^ LL | LL | &mut Either::One(_t) - | -- - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | -- data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: consider removing the mutable borrow | @@ -870,10 +777,7 @@ LL | match &mut em { | ^^^^^^^ LL | LL | &mut Either::One(_t) => (), - | -- - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | -- data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: consider removing the mutable borrow | @@ -888,10 +792,7 @@ LL | match &mut em { | ^^^^^^^ LL | LL | &mut Either::One(_t) => (), - | -- - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | -- data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: consider removing the mutable borrow | @@ -906,10 +807,7 @@ LL | match &mut em { | ^^^^^^^ LL | LL | &mut Either::One(_t) => (), - | -- - | | - | data moved here - | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | -- data moved here because `_t` has type `X`, which does not implement the `Copy` trait | help: consider removing the mutable borrow | @@ -923,8 +821,7 @@ error[E0507]: cannot move out of a shared reference LL | fn f1(&X(_t): &X) { } | ^^^--^ | | - | data moved here - | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | data moved here because `_t` has type `Y`, which does not implement the `Copy` trait | help: consider removing the borrow | @@ -938,8 +835,7 @@ error[E0507]: cannot move out of a mutable reference LL | fn f2(&mut X(_t): &mut X) { } | ^^^^^^^--^ | | - | data moved here - | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | data moved here because `_t` has type `Y`, which does not implement the `Copy` trait | help: consider removing the mutable borrow | @@ -953,8 +849,7 @@ error[E0507]: cannot move out of a shared reference LL | fn f3((&X(_t),): (&X,)) { } | ^^^^--^^^ | | - | data moved here - | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | data moved here because `_t` has type `Y`, which does not implement the `Copy` trait | help: consider removing the borrow | @@ -968,8 +863,7 @@ error[E0507]: cannot move out of a mutable reference LL | fn f4((&mut X(_t),): (&mut X,)) { } | ^^^^^^^^--^^^ | | - | data moved here - | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | data moved here because `_t` has type `Y`, which does not implement the `Copy` trait | help: consider removing the mutable borrow | @@ -983,8 +877,7 @@ error[E0507]: cannot move out of `a.a` as enum variant `Some` which is behind a LL | let Some(_s) = a.a else { | -- ^^^ | | - | data moved here - | move occurs because `_s` has type `String`, which does not implement the `Copy` trait + | data moved here because `_s` has type `String`, which does not implement the `Copy` trait | help: consider borrowing the pattern binding | diff --git a/tests/ui/suggestions/non_copy_move_out_of_tuple.stderr b/tests/ui/suggestions/non_copy_move_out_of_tuple.stderr index 62f24324fcc17..89ce53bf54765 100644 --- a/tests/ui/suggestions/non_copy_move_out_of_tuple.stderr +++ b/tests/ui/suggestions/non_copy_move_out_of_tuple.stderr @@ -4,8 +4,7 @@ error[E0507]: cannot move out of `tuple.0` which is behind a shared reference LL | (b,) = *tuple; | - ^^^^^^ | | - | data moved here - | move occurs because the place has type `NonCopy`, which does not implement the `Copy` trait + | data moved here because the place has type `NonCopy`, which does not implement the `Copy` trait | note: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/non_copy_move_out_of_tuple.rs:3:1 diff --git a/tests/ui/suggestions/option-content-move-from-tuple-match.stderr b/tests/ui/suggestions/option-content-move-from-tuple-match.stderr index c93570c579ee7..2546634c6cad8 100644 --- a/tests/ui/suggestions/option-content-move-from-tuple-match.stderr +++ b/tests/ui/suggestions/option-content-move-from-tuple-match.stderr @@ -5,10 +5,7 @@ LL | match (a, b) { | ^^^^^^ LL | LL | (None, &c) => &c.unwrap(), - | - - | | - | data moved here - | move occurs because `c` has type `Option`, which does not implement the `Copy` trait + | - data moved here because `c` has type `Option`, which does not implement the `Copy` trait | help: consider removing the borrow | diff --git a/tests/ui/type-alias-impl-trait/error-tainting-issue-122904.stderr b/tests/ui/type-alias-impl-trait/error-tainting-issue-122904.stderr index 956ce3e5936b6..c5e347e59de72 100644 --- a/tests/ui/type-alias-impl-trait/error-tainting-issue-122904.stderr +++ b/tests/ui/type-alias-impl-trait/error-tainting-issue-122904.stderr @@ -16,8 +16,7 @@ error[E0507]: cannot move out of a shared reference LL | with_positive(|&n| ()); | ^- | | - | data moved here - | move occurs because `n` has type `S`, which does not implement the `Copy` trait + | data moved here because `n` has type `S`, which does not implement the `Copy` trait | help: consider removing the borrow | diff --git a/tests/ui/type-alias-impl-trait/in-where-clause.rs b/tests/ui/type-alias-impl-trait/in-where-clause.rs index 8d5bfc48a66e9..f4b788b5b6803 100644 --- a/tests/ui/type-alias-impl-trait/in-where-clause.rs +++ b/tests/ui/type-alias-impl-trait/in-where-clause.rs @@ -11,7 +11,6 @@ where Bar: Send, { [0; 1 + 2] - //~^ ERROR: type annotations needed: cannot satisfy `Bar: Send` } fn main() {} diff --git a/tests/ui/type-alias-impl-trait/in-where-clause.stderr b/tests/ui/type-alias-impl-trait/in-where-clause.stderr index 81be8c8362e35..fcb590a961c18 100644 --- a/tests/ui/type-alias-impl-trait/in-where-clause.stderr +++ b/tests/ui/type-alias-impl-trait/in-where-clause.stderr @@ -1,19 +1,3 @@ -error[E0283]: type annotations needed: cannot satisfy `Bar: Send` - --> $DIR/in-where-clause.rs:13:9 - | -LL | [0; 1 + 2] - | ^^^^^ - | - = note: cannot satisfy `Bar: Send` -note: required by a bound in `foo` - --> $DIR/in-where-clause.rs:11:10 - | -LL | fn foo() -> Bar - | --- required by a bound in this function -LL | where -LL | Bar: Send, - | ^^^^ required by this bound in `foo` - error[E0391]: cycle detected when computing type of opaque `Bar::{opaque#0}` --> $DIR/in-where-clause.rs:5:12 | @@ -77,7 +61,6 @@ LL | type Bar = impl Sized; = note: cycle used when evaluating trait selection obligation `Bar: core::marker::Send` = 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: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0283, E0391. -For more information about an error, try `rustc --explain E0283`. +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/type-alias-impl-trait/recursive-drop-elaboration-2.stderr b/tests/ui/type-alias-impl-trait/recursive-drop-elaboration-2.stderr index e1fdd222ee147..94cd9a312ca12 100644 --- a/tests/ui/type-alias-impl-trait/recursive-drop-elaboration-2.stderr +++ b/tests/ui/type-alias-impl-trait/recursive-drop-elaboration-2.stderr @@ -16,8 +16,7 @@ error[E0507]: cannot move out of a shared reference LL | with_positive(|&n| ()); | ^- | | - | data moved here - | move occurs because `n` has type `S`, which does not implement the `Copy` trait + | data moved here because `n` has type `S`, which does not implement the `Copy` trait | help: consider removing the borrow | diff --git a/tests/ui/type-alias-impl-trait/recursive-drop-elaboration.stderr b/tests/ui/type-alias-impl-trait/recursive-drop-elaboration.stderr index 8b5dc950afdde..dc282f30b45b4 100644 --- a/tests/ui/type-alias-impl-trait/recursive-drop-elaboration.stderr +++ b/tests/ui/type-alias-impl-trait/recursive-drop-elaboration.stderr @@ -16,8 +16,7 @@ error[E0507]: cannot move out of a shared reference LL | with_positive(|&n| ()); | ^- | | - | data moved here - | move occurs because `n` has type `S`, which does not implement the `Copy` trait + | data moved here because `n` has type `S`, which does not implement the `Copy` trait | help: consider removing the borrow | @@ -31,8 +30,7 @@ error[E0507]: cannot move out of a shared reference LL | with_positive(|&a| ()); | ^- | | - | data moved here - | move occurs because `a` has type `S`, which does not implement the `Copy` trait + | data moved here because `a` has type `S`, which does not implement the `Copy` trait | help: consider removing the borrow |