diff --git a/Cargo.lock b/Cargo.lock index 3f7427f594072..c4b68c302bc54 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2579,6 +2579,15 @@ dependencies = [ "core", ] +[[package]] +name = "psm" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b14fc68b454f875abc8354c2555e1d56596f74833ddc0f77f87f4871ed6a30e0" +dependencies = [ + "cc", +] + [[package]] name = "publicsuffix" version = "1.5.3" @@ -3122,6 +3131,7 @@ dependencies = [ "scoped-tls", "serialize", "smallvec 1.0.0", + "stacker", ] [[package]] @@ -4541,6 +4551,19 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffbc596e092fe5f598b12ef46cc03754085ac2f4d8c739ad61c4ae266cc3b3fa" +[[package]] +name = "stacker" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d96fc4f13a0ac088e9a3cd9af1cc8c5cc1ab5deb2145cef661267dfc9c542f8a" +dependencies = [ + "cc", + "cfg-if", + "libc", + "psm", + "winapi 0.3.8", +] + [[package]] name = "std" version = "0.0.0" diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml index 481d691b8e9b2..12ed608dcc35e 100644 --- a/src/librustc/Cargo.toml +++ b/src/librustc/Cargo.toml @@ -36,3 +36,4 @@ byteorder = { version = "1.3" } smallvec = { version = "1.0", features = ["union", "may_dangle"] } measureme = "0.7.1" rustc_session = { path = "../librustc_session" } +stacker = "0.1.6" diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 55ed07a97d168..ba1665fb53083 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -346,7 +346,7 @@ impl<'hir> Map<'hir> { } fn get_entry(&self, id: HirId) -> Entry<'hir> { - if id.local_id == ItemLocalId::from_u32_const(0) { + if id.local_id == ItemLocalId::from_u32(0) { let owner = self.tcx.hir_owner(id.owner_def_id()); Entry { parent: owner.parent, node: owner.node } } else { diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 24237235e0c4a..555a85fbfb328 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -26,6 +26,9 @@ #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(box_syntax)] +#![feature(const_if_match)] +#![feature(const_fn)] +#![feature(const_panic)] #![feature(const_transmute)] #![feature(core_intrinsics)] #![feature(drain_filter)] diff --git a/src/librustc/middle/limits.rs b/src/librustc/middle/limits.rs index 22e4f5ea22261..6f6fc8b881a32 100644 --- a/src/librustc/middle/limits.rs +++ b/src/librustc/middle/limits.rs @@ -13,6 +13,24 @@ use rustc_span::symbol::{sym, Symbol}; use rustc_data_structures::sync::Once; +// This is the amount of bytes that need to be left on the stack before increasing the size. +// It must be at least as large as the stack required by any code that does not call +// `ensure_sufficient_stack`. +const RED_ZONE: usize = 100 * 1024; // 100k + +// Only the first stack that is pushed, grows exponentially (2^n * STACK_PER_RECURSION) from then +// on. This flag has performance relevant characteristics. Don't set it too high. +const STACK_PER_RECURSION: usize = 1 * 1024 * 1024; // 1MB + +/// Grows the stack on demand to prevent stack overflow. Call this in strategic locations +/// to "break up" recursive calls. E.g. almost any call to `visit_expr` or equivalent can benefit +/// from this. +/// +/// Should not be sprinkled around carelessly, as it causes a little bit of overhead. +pub fn ensure_sufficient_stack(f: impl FnOnce() -> R) -> R { + stacker::maybe_grow(RED_ZONE, STACK_PER_RECURSION, f) +} + pub fn update_limits(sess: &Session, krate: &ast::Crate) { update_limit(sess, krate, &sess.recursion_limit, sym::recursion_limit, 128); update_limit(sess, krate, &sess.type_length_limit, sym::type_length_limit, 1048576); diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 546ba586d30f9..9474f05b55df7 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -41,6 +41,7 @@ pub struct Allocation { /// The size of the allocation. Currently, must always equal `bytes.len()`. pub size: Size, /// The alignment of the allocation to detect unaligned reads. + /// (`Align` guarantees that this is a power of two.) pub align: Align, /// `true` if the allocation is mutable. /// Also used by codegen to determine if a static should be put into mutable memory, @@ -314,7 +315,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { &self.get_bytes(cx, ptr, size_with_null)?[..size] } // This includes the case where `offset` is out-of-bounds to begin with. - None => throw_unsup!(UnterminatedCString(ptr.erase_tag())), + None => throw_ub!(UnterminatedCString(ptr.erase_tag())), }) } @@ -573,7 +574,7 @@ impl<'tcx, Tag, Extra> Allocation { fn check_defined(&self, ptr: Pointer, size: Size) -> InterpResult<'tcx> { self.undef_mask .is_range_defined(ptr.offset, ptr.offset + size) - .or_else(|idx| throw_unsup!(ReadUndefBytes(idx))) + .or_else(|idx| throw_ub!(InvalidUndefBytes(Some(Pointer::new(ptr.alloc_id, idx))))) } pub fn mark_definedness(&mut self, ptr: Pointer, size: Size, new_state: bool) { diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index 0b33408edf02d..ff107a5f1e268 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -1,7 +1,6 @@ -use super::{CheckInAllocMsg, Pointer, RawConst, ScalarMaybeUndef}; +use super::{AllocId, CheckInAllocMsg, Pointer, RawConst, ScalarMaybeUndef}; use crate::hir::map::definitions::DefPathData; -use crate::mir; use crate::mir::interpret::ConstValue; use crate::ty::layout::{Align, LayoutError, Size}; use crate::ty::query::TyCtxtAt; @@ -14,8 +13,7 @@ use rustc_errors::{struct_span_err, DiagnosticBuilder}; use rustc_hir as hir; use rustc_macros::HashStable; use rustc_session::CtfeBacktrace; -use rustc_span::{Pos, Span}; -use rustc_target::spec::abi::Abi; +use rustc_span::{def_id::DefId, Pos, Span}; use std::{any::Any, fmt}; #[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, RustcEncodable, RustcDecodable)] @@ -296,6 +294,8 @@ pub enum InvalidProgramInfo<'tcx> { TypeckError, /// An error occurred during layout computation. Layout(layout::LayoutError<'tcx>), + /// An invalid transmute happened. + TransmuteSizeDiff(Ty<'tcx>, Ty<'tcx>), } impl fmt::Debug for InvalidProgramInfo<'_> { @@ -306,6 +306,11 @@ impl fmt::Debug for InvalidProgramInfo<'_> { ReferencedConstant => write!(f, "referenced constant has errors"), TypeckError => write!(f, "encountered constants with type errors, stopping evaluation"), Layout(ref err) => write!(f, "{}", err), + TransmuteSizeDiff(from_ty, to_ty) => write!( + f, + "tried to transmute from {:?} to {:?}, but their sizes differed", + from_ty, to_ty + ), } } } @@ -321,7 +326,10 @@ pub enum UndefinedBehaviorInfo { /// An enum discriminant was set to a value which was outside the range of valid values. InvalidDiscriminant(ScalarMaybeUndef), /// A slice/array index projection went out-of-bounds. - BoundsCheckFailed { len: u64, index: u64 }, + BoundsCheckFailed { + len: u64, + index: u64, + }, /// Something was divided by 0 (x / 0). DivisionByZero, /// Something was "remainded" by 0 (x % 0). @@ -330,6 +338,43 @@ pub enum UndefinedBehaviorInfo { PointerArithOverflow, /// Invalid metadata in a wide pointer (using `str` to avoid allocations). InvalidMeta(&'static str), + /// Reading a C string that does not end within its allocation. + UnterminatedCString(Pointer), + /// Dereferencing a dangling pointer after it got freed. + PointerUseAfterFree(AllocId), + /// Used a pointer outside the bounds it is valid for. + PointerOutOfBounds { + ptr: Pointer, + msg: CheckInAllocMsg, + allocation_size: Size, + }, + /// Used a pointer with bad alignment. + AlignmentCheckFailed { + required: Align, + has: Align, + }, + /// Using an integer as a pointer in the wrong way. + InvalidIntPointerUsage(u64), + /// Writing to read-only memory. + WriteToReadOnly(AllocId), + /// Using a pointer-not-to-a-function as function pointer. + InvalidFunctionPointer(Pointer), + // Trying to access the data behind a function pointer. + DerefFunctionPointer(AllocId), + /// The value validity check found a problem. + /// Should only be thrown by `validity.rs` and always point out which part of the value + /// is the problem. + ValidationFailure(String), + /// Using a non-boolean `u8` as bool. + InvalidBool(u8), + /// Using a non-character `u32` as character. + InvalidChar(u32), + /// Using uninitialized data where it is not allowed. + InvalidUndefBytes(Option), + /// Working with a local that is not currently live. + DeadLocal, + /// Trying to read from the return place of a function. + ReadFromReturnPlace, } impl fmt::Debug for UndefinedBehaviorInfo { @@ -348,6 +393,50 @@ impl fmt::Debug for UndefinedBehaviorInfo { RemainderByZero => write!(f, "calculating the remainder with a divisor of zero"), PointerArithOverflow => write!(f, "overflowing in-bounds pointer arithmetic"), InvalidMeta(msg) => write!(f, "invalid metadata in wide pointer: {}", msg), + UnterminatedCString(p) => write!( + f, + "reading a null-terminated string starting at {:?} with no null found before end of allocation", + p, + ), + PointerUseAfterFree(a) => { + write!(f, "pointer to {:?} was dereferenced after this allocation got freed", a) + } + PointerOutOfBounds { ptr, msg, allocation_size } => write!( + f, + "{} failed: pointer must be in-bounds at offset {}, \ + but is outside bounds of {} which has size {}", + msg, + ptr.offset.bytes(), + ptr.alloc_id, + allocation_size.bytes() + ), + InvalidIntPointerUsage(0) => write!(f, "invalid use of NULL pointer"), + InvalidIntPointerUsage(i) => write!(f, "invalid use of {} as a pointer", i), + AlignmentCheckFailed { required, has } => write!( + f, + "accessing memory with alignment {}, but alignment {} is required", + has.bytes(), + required.bytes() + ), + WriteToReadOnly(a) => write!(f, "writing to {:?} which is read-only", a), + InvalidFunctionPointer(p) => { + write!(f, "using {:?} as function pointer but it does not point to a function", p) + } + DerefFunctionPointer(a) => write!(f, "accessing {:?} which contains a function", a), + ValidationFailure(ref err) => write!(f, "type validation failed: {}", err), + InvalidBool(b) => write!(f, "interpreting an invalid 8-bit value as a bool: {}", b), + InvalidChar(c) => write!(f, "interpreting an invalid 32-bit value as a char: {}", c), + InvalidUndefBytes(Some(p)) => write!( + f, + "reading uninitialized memory at {:?}, but this operation requires initialized memory", + p + ), + InvalidUndefBytes(None) => write!( + f, + "using uninitialized data, but this operation requires initialized memory" + ), + DeadLocal => write!(f, "accessing a dead local variable"), + ReadFromReturnPlace => write!(f, "tried to read from the return place"), } } } @@ -359,203 +448,45 @@ impl fmt::Debug for UndefinedBehaviorInfo { /// /// Currently, we also use this as fall-back error kind for errors that have not been /// categorized yet. -pub enum UnsupportedOpInfo<'tcx> { +pub enum UnsupportedOpInfo { /// Free-form case. Only for errors that are never caught! Unsupported(String), - /// When const-prop encounters a situation it does not support, it raises this error. /// This must not allocate for performance reasons (hence `str`, not `String`). ConstPropUnsupported(&'static str), - - // -- Everything below is not categorized yet -- - FunctionAbiMismatch(Abi, Abi), - FunctionArgMismatch(Ty<'tcx>, Ty<'tcx>), - FunctionRetMismatch(Ty<'tcx>, Ty<'tcx>), - FunctionArgCountMismatch, - UnterminatedCString(Pointer), - DanglingPointerDeref, - DoubleFree, - InvalidMemoryAccess, - InvalidFunctionPointer, - InvalidBool, - PointerOutOfBounds { - ptr: Pointer, - msg: CheckInAllocMsg, - allocation_size: Size, - }, - InvalidNullPointerUsage, + /// Accessing an unsupported foreign static. + ReadForeignStatic(DefId), + /// Could not find MIR for a function. + NoMirFor(DefId), + /// Modified a static during const-eval. + /// FIXME: move this to `ConstEvalErrKind` through a machine hook. + ModifiedStatic, + /// Encountered a pointer where we needed raw bytes. ReadPointerAsBytes, + /// Encountered raw bytes where we needed a pointer. ReadBytesAsPointer, - ReadForeignStatic, - InvalidPointerMath, - ReadUndefBytes(Size), - DeadLocal, - InvalidBoolOp(mir::BinOp), - UnimplementedTraitSelection, - CalledClosureAsFunction, - NoMirFor(String), - DerefFunctionPointer, - ExecuteMemory, - InvalidChar(u128), - OutOfTls, - TlsOutOfBounds, - AlignmentCheckFailed { - required: Align, - has: Align, - }, - ValidationFailure(String), - VtableForArgumentlessMethod, - ModifiedConstantMemory, - ModifiedStatic, - TypeNotPrimitive(Ty<'tcx>), - ReallocatedWrongMemoryKind(String, String), - DeallocatedWrongMemoryKind(String, String), - ReallocateNonBasePtr, - DeallocateNonBasePtr, - IncorrectAllocationInformation(Size, Size, Align, Align), - HeapAllocZeroBytes, - HeapAllocNonPowerOfTwoAlignment(u64), - ReadFromReturnPointer, - PathNotFound(Vec), - TransmuteSizeDiff(Ty<'tcx>, Ty<'tcx>), } -impl fmt::Debug for UnsupportedOpInfo<'tcx> { +impl fmt::Debug for UnsupportedOpInfo { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { use UnsupportedOpInfo::*; match self { - PointerOutOfBounds { ptr, msg, allocation_size } => write!( - f, - "{} failed: pointer must be in-bounds at offset {}, \ - but is outside bounds of allocation {} which has size {}", - msg, - ptr.offset.bytes(), - ptr.alloc_id, - allocation_size.bytes() - ), - ValidationFailure(ref err) => write!(f, "type validation failed: {}", err), - NoMirFor(ref func) => write!(f, "no MIR for `{}`", func), - FunctionAbiMismatch(caller_abi, callee_abi) => write!( - f, - "tried to call a function with ABI {:?} using caller ABI {:?}", - callee_abi, caller_abi - ), - FunctionArgMismatch(caller_ty, callee_ty) => write!( - f, - "tried to call a function with argument of type {:?} \ - passing data of type {:?}", - callee_ty, caller_ty - ), - TransmuteSizeDiff(from_ty, to_ty) => write!( - f, - "tried to transmute from {:?} to {:?}, but their sizes differed", - from_ty, to_ty - ), - FunctionRetMismatch(caller_ty, callee_ty) => write!( - f, - "tried to call a function with return type {:?} \ - passing return place of type {:?}", - callee_ty, caller_ty - ), - FunctionArgCountMismatch => { - write!(f, "tried to call a function with incorrect number of arguments") - } - ReallocatedWrongMemoryKind(ref old, ref new) => { - write!(f, "tried to reallocate memory from `{}` to `{}`", old, new) - } - DeallocatedWrongMemoryKind(ref old, ref new) => { - write!(f, "tried to deallocate `{}` memory but gave `{}` as the kind", old, new) - } - InvalidChar(c) => { - write!(f, "tried to interpret an invalid 32-bit value as a char: {}", c) - } - AlignmentCheckFailed { required, has } => write!( - f, - "tried to access memory with alignment {}, but alignment {} is required", - has.bytes(), - required.bytes() - ), - TypeNotPrimitive(ty) => write!(f, "expected primitive type, got {}", ty), - PathNotFound(ref path) => write!(f, "cannot find path {:?}", path), - IncorrectAllocationInformation(size, size2, align, align2) => write!( - f, - "incorrect alloc info: expected size {} and align {}, \ - got size {} and align {}", - size.bytes(), - align.bytes(), - size2.bytes(), - align2.bytes() - ), - InvalidMemoryAccess => write!(f, "tried to access memory through an invalid pointer"), - DanglingPointerDeref => write!(f, "dangling pointer was dereferenced"), - DoubleFree => write!(f, "tried to deallocate dangling pointer"), - InvalidFunctionPointer => { - write!(f, "tried to use a function pointer after offsetting it") - } - InvalidBool => write!(f, "invalid boolean value read"), - InvalidNullPointerUsage => write!(f, "invalid use of NULL pointer"), - ReadPointerAsBytes => write!( - f, - "a raw memory access tried to access part of a pointer value as raw \ - bytes" - ), - ReadBytesAsPointer => { - write!(f, "a memory access tried to interpret some bytes as a pointer") - } - ReadForeignStatic => write!(f, "tried to read from foreign (extern) static"), - InvalidPointerMath => write!( - f, - "attempted to do invalid arithmetic on pointers that would leak base \ - addresses, e.g., comparing pointers into different allocations" - ), - DeadLocal => write!(f, "tried to access a dead local variable"), - DerefFunctionPointer => write!(f, "tried to dereference a function pointer"), - ExecuteMemory => write!(f, "tried to treat a memory pointer as a function pointer"), - OutOfTls => write!(f, "reached the maximum number of representable TLS keys"), - TlsOutOfBounds => write!(f, "accessed an invalid (unallocated) TLS key"), - CalledClosureAsFunction => { - write!(f, "tried to call a closure through a function pointer") + Unsupported(ref msg) => write!(f, "{}", msg), + ConstPropUnsupported(ref msg) => { + write!(f, "Constant propagation encountered an unsupported situation: {}", msg) } - VtableForArgumentlessMethod => { - write!(f, "tried to call a vtable function without arguments") + ReadForeignStatic(did) => { + write!(f, "tried to read from foreign (extern) static {:?}", did) } - ModifiedConstantMemory => write!(f, "tried to modify constant memory"), + NoMirFor(did) => write!(f, "could not load MIR for {:?}", did), ModifiedStatic => write!( f, "tried to modify a static's initial value from another static's \ initializer" ), - ReallocateNonBasePtr => write!( - f, - "tried to reallocate with a pointer not to the beginning of an \ - existing object" - ), - DeallocateNonBasePtr => write!( - f, - "tried to deallocate with a pointer not to the beginning of an \ - existing object" - ), - HeapAllocZeroBytes => write!(f, "tried to re-, de- or allocate zero bytes on the heap"), - ReadFromReturnPointer => write!(f, "tried to read from the return pointer"), - UnimplementedTraitSelection => { - write!(f, "there were unresolved type arguments during trait selection") - } - InvalidBoolOp(_) => write!(f, "invalid boolean operation"), - UnterminatedCString(_) => write!( - f, - "attempted to get length of a null-terminated string, but no null \ - found before end of allocation" - ), - ReadUndefBytes(_) => write!(f, "attempted to read undefined bytes"), - HeapAllocNonPowerOfTwoAlignment(_) => write!( - f, - "tried to re-, de-, or allocate heap memory with alignment that is \ - not a power of two" - ), - Unsupported(ref msg) => write!(f, "{}", msg), - ConstPropUnsupported(ref msg) => { - write!(f, "Constant propagation encountered an unsupported situation: {}", msg) - } + + ReadPointerAsBytes => write!(f, "unable to turn pointer into raw bytes",), + ReadBytesAsPointer => write!(f, "unable to turn bytes into a pointer"), } } } @@ -590,7 +521,7 @@ pub enum InterpError<'tcx> { UndefinedBehavior(UndefinedBehaviorInfo), /// The program did something the interpreter does not support (some of these *might* be UB /// but the interpreter is not sure). - Unsupported(UnsupportedOpInfo<'tcx>), + 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, @@ -606,7 +537,7 @@ pub type InterpResult<'tcx, T = ()> = Result>; impl fmt::Display for InterpError<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // Forward `Display` to `Debug`. - write!(f, "{:?}", self) + fmt::Debug::fmt(self, f) } } @@ -631,7 +562,7 @@ impl InterpError<'_> { match self { InterpError::MachineStop(_) | InterpError::Unsupported(UnsupportedOpInfo::Unsupported(_)) - | InterpError::Unsupported(UnsupportedOpInfo::ValidationFailure(_)) + | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ValidationFailure(_)) | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_)) | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::UbExperimental(_)) => true, _ => false, diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs index 64c07b431db38..0b5bb7f3c03fa 100644 --- a/src/librustc/mir/interpret/mod.rs +++ b/src/librustc/mir/interpret/mod.rs @@ -161,7 +161,13 @@ pub struct AllocId(pub u64); impl fmt::Debug for AllocId { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(fmt, "alloc{}", self.0) + fmt::Display::fmt(self, fmt) + } +} + +impl fmt::Display for AllocId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "alloc{}", self.0) } } @@ -351,12 +357,6 @@ impl<'s> AllocDecodingSession<'s> { } } -impl fmt::Display for AllocId { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0) - } -} - /// An allocation in the global (tcx-managed) memory can be either a function pointer, /// a static, or a "real" allocation with some data in it. #[derive(Debug, Clone, Eq, PartialEq, Hash, RustcDecodable, RustcEncodable, HashStable)] diff --git a/src/librustc/mir/interpret/pointer.rs b/src/librustc/mir/interpret/pointer.rs index cc3c50b7899f3..2cbe25f967426 100644 --- a/src/librustc/mir/interpret/pointer.rs +++ b/src/librustc/mir/interpret/pointer.rs @@ -213,20 +213,4 @@ impl<'tcx, Tag> Pointer { pub fn erase_tag(self) -> Pointer { Pointer { alloc_id: self.alloc_id, offset: self.offset, tag: () } } - - /// Test if the pointer is "inbounds" of an allocation of the given size. - /// A pointer is "inbounds" even if its offset is equal to the size; this is - /// a "one-past-the-end" pointer. - #[inline(always)] - pub fn check_inbounds_alloc( - self, - allocation_size: Size, - msg: CheckInAllocMsg, - ) -> InterpResult<'tcx, ()> { - if self.offset > allocation_size { - throw_unsup!(PointerOutOfBounds { ptr: self.erase_tag(), msg, allocation_size }) - } else { - Ok(()) - } - } } diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs index 1e630c96dd409..04fe70b36c1e0 100644 --- a/src/librustc/mir/interpret/value.rs +++ b/src/librustc/mir/interpret/value.rs @@ -455,10 +455,11 @@ impl<'tcx, Tag> Scalar { } pub fn to_bool(self) -> InterpResult<'tcx, bool> { - match self { - Scalar::Raw { data: 0, size: 1 } => Ok(false), - Scalar::Raw { data: 1, size: 1 } => Ok(true), - _ => throw_unsup!(InvalidBool), + let val = self.to_u8()?; + match val { + 0 => Ok(false), + 1 => Ok(true), + _ => throw_ub!(InvalidBool(val)), } } @@ -466,7 +467,7 @@ impl<'tcx, Tag> Scalar { let val = self.to_u32()?; match ::std::char::from_u32(val) { Some(c) => Ok(c), - None => throw_unsup!(InvalidChar(val as u128)), + None => throw_ub!(InvalidChar(val)), } } @@ -609,7 +610,7 @@ impl<'tcx, Tag> ScalarMaybeUndef { pub fn not_undef(self) -> InterpResult<'static, Scalar> { match self { ScalarMaybeUndef::Scalar(scalar) => Ok(scalar), - ScalarMaybeUndef::Undef => throw_unsup!(ReadUndefBytes(Size::ZERO)), + ScalarMaybeUndef::Undef => throw_ub!(InvalidUndefBytes(None)), } } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index d6f6788697cd8..d7a259cc87074 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -23,7 +23,6 @@ use crate::mir::{ }; use crate::traits; use crate::traits::{Clause, Clauses, Goal, GoalKind, Goals}; -use crate::ty::free_region_map::FreeRegionMap; use crate::ty::layout::{LayoutDetails, TargetDataLayout, VariantIdx}; use crate::ty::query; use crate::ty::steal::Steal; @@ -416,11 +415,6 @@ pub struct TypeckTables<'tcx> { /// this field will be set to `true`. pub tainted_by_errors: bool, - /// Stores the free-region relationships that were deduced from - /// its where-clauses and parameter types. These are then - /// read-again by borrowck. - pub free_region_map: FreeRegionMap<'tcx>, - /// All the opaque types that are restricted to concrete types /// by this function. pub concrete_opaque_types: FxHashMap>, @@ -456,7 +450,6 @@ impl<'tcx> TypeckTables<'tcx> { coercion_casts: Default::default(), used_trait_imports: Lrc::new(Default::default()), tainted_by_errors: false, - free_region_map: Default::default(), concrete_opaque_types: Default::default(), upvar_list: Default::default(), generator_interior_types: Default::default(), @@ -719,7 +712,6 @@ impl<'a, 'tcx> HashStable> for TypeckTables<'tcx> { ref used_trait_imports, tainted_by_errors, - ref free_region_map, ref concrete_opaque_types, ref upvar_list, ref generator_interior_types, @@ -757,7 +749,6 @@ impl<'a, 'tcx> HashStable> for TypeckTables<'tcx> { coercion_casts.hash_stable(hcx, hasher); used_trait_imports.hash_stable(hcx, hasher); tainted_by_errors.hash_stable(hcx, hasher); - free_region_map.hash_stable(hcx, hasher); concrete_opaque_types.hash_stable(hcx, hasher); upvar_list.hash_stable(hcx, hasher); generator_interior_types.hash_stable(hcx, hasher); diff --git a/src/librustc/ty/inhabitedness/mod.rs b/src/librustc/ty/inhabitedness/mod.rs index b166c4dea0c85..35b5bde7c9e1e 100644 --- a/src/librustc/ty/inhabitedness/mod.rs +++ b/src/librustc/ty/inhabitedness/mod.rs @@ -1,5 +1,6 @@ pub use self::def_id_forest::DefIdForest; +use crate::middle::limits::ensure_sufficient_stack; use crate::ty; use crate::ty::context::TyCtxt; use crate::ty::TyKind::*; @@ -196,7 +197,9 @@ impl<'tcx> TyS<'tcx> { /// Calculates the forest of `DefId`s from which this type is visibly uninhabited. fn uninhabited_from(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> DefIdForest { match self.kind { - Adt(def, substs) => def.uninhabited_from(tcx, substs, param_env), + Adt(def, substs) => { + ensure_sufficient_stack(|| def.uninhabited_from(tcx, substs, param_env)) + } Never => DefIdForest::full(tcx), diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index dedb3035cedb3..f5ef9bda0eeda 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -1409,12 +1409,15 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // locals as part of the prefix. We compute the layout of all of // these fields at once to get optimal packing. let discr_index = substs.as_generator().prefix_tys(def_id, tcx).count(); - // FIXME(eddyb) set the correct vaidity range for the discriminant. - let discr_layout = self.layout_of(substs.as_generator().discr_ty(tcx))?; - let discr = match &discr_layout.abi { - Abi::Scalar(s) => s.clone(), - _ => bug!(), - }; + + // `info.variant_fields` already accounts for the reserved variants, so no need to add them. + let max_discr = (info.variant_fields.len() - 1) as u128; + let discr_int = Integer::fit_unsigned(max_discr); + let discr_int_ty = discr_int.to_ty(tcx, false); + let discr = Scalar { value: Primitive::Int(discr_int, false), valid_range: 0..=max_discr }; + let discr_layout = self.tcx.intern_layout(LayoutDetails::scalar(self, discr.clone())); + let discr_layout = TyLayout { ty: discr_int_ty, details: discr_layout }; + let promoted_layouts = ineligible_locals .iter() .map(|local| subst_field(info.field_tys[local])) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index d622d6fbe2c1f..dd834d9109dc9 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1700,7 +1700,7 @@ rustc_index::newtype_index! { } impl UniverseIndex { - pub const ROOT: UniverseIndex = UniverseIndex::from_u32_const(0); + pub const ROOT: UniverseIndex = UniverseIndex::from_u32(0); /// Returns the "next" universe index in order -- this new index /// is considered to extend all previous universes. This diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index acf67f52dceaa..33b348811d91a 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -321,7 +321,9 @@ impl<'tcx> TyCtxt<'tcx> { }; // Use the `ImplicitCtxt` while we execute the query. - tls::enter_context(&new_icx, |_| compute(self)) + tls::enter_context(&new_icx, |_| { + crate::middle::limits::ensure_sufficient_stack(|| compute(self)) + }) }) } diff --git a/src/librustc_ast/lib.rs b/src/librustc_ast/lib.rs index adb96356aae7d..2594cc536ac5f 100644 --- a/src/librustc_ast/lib.rs +++ b/src/librustc_ast/lib.rs @@ -7,7 +7,9 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/", test(attr(deny(warnings))))] #![feature(bool_to_option)] #![feature(box_syntax)] +#![feature(const_if_match)] #![feature(const_fn)] // For the `transmute` in `P::new` +#![feature(const_panic)] #![feature(const_transmute)] #![feature(crate_visibility_modifier)] #![feature(label_break_value)] diff --git a/src/librustc_ast/node_id.rs b/src/librustc_ast/node_id.rs index 58d2334a7b148..cd562c48e9115 100644 --- a/src/librustc_ast/node_id.rs +++ b/src/librustc_ast/node_id.rs @@ -12,7 +12,7 @@ rustc_index::newtype_index! { rustc_data_structures::define_id_collections!(NodeMap, NodeSet, NodeId); /// `NodeId` used to represent the root of the crate. -pub const CRATE_NODE_ID: NodeId = NodeId::from_u32_const(0); +pub const CRATE_NODE_ID: NodeId = NodeId::from_u32(0); /// When parsing and doing expansions, we initially give all AST nodes this AST /// node value. Then later, in the renumber pass, we renumber them to have diff --git a/src/librustc_ast_lowering/expr.rs b/src/librustc_ast_lowering/expr.rs index a4cbae5196635..842dc10ea7bdc 100644 --- a/src/librustc_ast_lowering/expr.rs +++ b/src/librustc_ast_lowering/expr.rs @@ -1,6 +1,7 @@ use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs}; -use rustc::bug; +use rustc::middle::limits::ensure_sufficient_stack; +use rustc::{bug, span_bug}; use rustc_ast::ast::*; use rustc_ast::attr; use rustc_ast::ptr::P as AstP; @@ -22,6 +23,37 @@ impl<'hir> LoweringContext<'_, 'hir> { pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> { let kind = match e.kind { + ExprKind::Paren(ref ex) => { + let mut ex = self.lower_expr_mut(ex); + // Include parens in span, but only if it is a super-span. + if e.span.contains(ex.span) { + ex.span = e.span; + } + // Merge attributes into the inner expression. + let mut attrs = e.attrs.clone(); + attrs.extend::>(ex.attrs.into()); + ex.attrs = attrs; + return ex; + } + + // Desugar `ExprForLoop` + // from: `[opt_ident]: for in ` + ExprKind::ForLoop(ref pat, ref head, ref body, opt_label) => { + return self.lower_expr_for(e, pat, head, body, opt_label); + } + _ => ensure_sufficient_stack(|| self.lower_expr_kind(e)), + }; + + hir::Expr { + hir_id: self.lower_node_id(e.id), + kind, + span: e.span, + attrs: e.attrs.iter().map(|a| self.lower_attr(a)).collect::>().into(), + } + } + + fn lower_expr_kind(&mut self, e: &Expr) -> hir::ExprKind<'hir> { + match e.kind { ExprKind::Box(ref inner) => hir::ExprKind::Box(self.lower_expr(inner)), ExprKind::Array(ref exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)), ExprKind::Repeat(ref expr, ref count) => { @@ -175,37 +207,13 @@ impl<'hir> LoweringContext<'_, 'hir> { maybe_expr, ) } - ExprKind::Paren(ref ex) => { - let mut ex = self.lower_expr_mut(ex); - // Include parens in span, but only if it is a super-span. - if e.span.contains(ex.span) { - ex.span = e.span; - } - // Merge attributes into the inner expression. - let mut attrs = e.attrs.clone(); - attrs.extend::>(ex.attrs.into()); - ex.attrs = attrs; - return ex; - } - ExprKind::Yield(ref opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()), - ExprKind::Err => hir::ExprKind::Err, - - // Desugar `ExprForLoop` - // from: `[opt_ident]: for in ` - ExprKind::ForLoop(ref pat, ref head, ref body, opt_label) => { - return self.lower_expr_for(e, pat, head, body, opt_label); - } ExprKind::Try(ref sub_expr) => self.lower_expr_try(e.span, sub_expr), - ExprKind::MacCall(_) => panic!("Shouldn't exist here"), - }; - - hir::Expr { - hir_id: self.lower_node_id(e.id), - kind, - span: e.span, - attrs: e.attrs.iter().map(|a| self.lower_attr(a)).collect::>().into(), + ExprKind::ForLoop(..) | ExprKind::Paren(_) => { + span_bug!(e.span, "Should have been handled by `lower_expr`") + } + ExprKind::MacCall(_) => span_bug!(e.span, "Shouldn't exist here"), } } diff --git a/src/librustc_ast_lowering/pat.rs b/src/librustc_ast_lowering/pat.rs index 8ba6576f69265..316a600e3c599 100644 --- a/src/librustc_ast_lowering/pat.rs +++ b/src/librustc_ast_lowering/pat.rs @@ -1,5 +1,6 @@ use super::{ImplTraitContext, LoweringContext, ParamMode}; +use rustc::{middle::limits::ensure_sufficient_stack, span_bug}; use rustc_ast::ast::*; use rustc_ast::ptr::P; use rustc_hir as hir; @@ -9,6 +10,16 @@ use rustc_span::{source_map::Spanned, Span}; impl<'a, 'hir> LoweringContext<'a, 'hir> { crate fn lower_pat(&mut self, p: &Pat) -> &'hir hir::Pat<'hir> { let node = match p.kind { + // FIXME: consider not using recursion to lower this. + PatKind::Paren(ref inner) => return self.lower_pat(inner), + _ => ensure_sufficient_stack(|| self.lower_pat_kind(p)), + }; + + self.pat_with_node_id_of(p, node) + } + + fn lower_pat_kind(&mut self, p: &Pat) -> hir::PatKind<'hir> { + match p.kind { PatKind::Wild => hir::PatKind::Wild, PatKind::Ident(ref binding_mode, ident, ref sub) => { let lower_sub = |this: &mut Self| sub.as_ref().map(|s| this.lower_pat(&*s)); @@ -74,11 +85,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // If we reach here the `..` pattern is not semantically allowed. self.ban_illegal_rest_pat(p.span) } - PatKind::Paren(ref inner) => return self.lower_pat(inner), - PatKind::MacCall(_) => panic!("Shouldn't exist here"), - }; - - self.pat_with_node_id_of(p, node) + PatKind::Paren(_) => span_bug!(p.span, "Should have been handled by `lower_pat`"), + PatKind::MacCall(_) => span_bug!(p.span, "Shouldn't exist here"), + } } fn lower_pat_tuple( diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs index b2e6ab7c5e777..bb73e982a9c28 100644 --- a/src/librustc_ast_pretty/pprust.rs +++ b/src/librustc_ast_pretty/pprust.rs @@ -148,12 +148,19 @@ pub fn to_string(f: impl FnOnce(&mut State<'_>)) -> String { // This makes comma-separated lists look slightly nicer, // and also addresses a specific regression described in issue #63896. -fn tt_prepend_space(tt: &TokenTree) -> bool { +fn tt_prepend_space(tt: &TokenTree, prev: &TokenTree) -> bool { match tt { TokenTree::Token(token) => match token.kind { token::Comma => false, _ => true, }, + TokenTree::Delimited(_, DelimToken::Paren, _) => match prev { + TokenTree::Token(token) => match token.kind { + token::Ident(_, _) => false, + _ => true, + }, + _ => true, + }, _ => true, } } @@ -650,11 +657,14 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere } fn print_tts(&mut self, tts: tokenstream::TokenStream, convert_dollar_crate: bool) { - for (i, tt) in tts.into_trees().enumerate() { - if i != 0 && tt_prepend_space(&tt) { + let mut iter = tts.into_trees().peekable(); + while let Some(tt) = iter.next() { + let show_space = + if let Some(next) = iter.peek() { tt_prepend_space(next, &tt) } else { false }; + self.print_tt(tt, convert_dollar_crate); + if show_space { self.space(); } - self.print_tt(tt, convert_dollar_crate); } } diff --git a/src/librustc_builtin_macros/cmdline_attrs.rs b/src/librustc_builtin_macros/cmdline_attrs.rs index 7ddbf08306b72..093815dbbcd4f 100644 --- a/src/librustc_builtin_macros/cmdline_attrs.rs +++ b/src/librustc_builtin_macros/cmdline_attrs.rs @@ -3,7 +3,6 @@ use rustc_ast::ast::{self, AttrItem, AttrStyle}; use rustc_ast::attr::mk_attr; use rustc_ast::token; -use rustc_expand::panictry; use rustc_session::parse::ParseSess; use rustc_span::FileName; @@ -16,7 +15,13 @@ pub fn inject(mut krate: ast::Crate, parse_sess: &ParseSess, attrs: &[String]) - ); let start_span = parser.token.span; - let AttrItem { path, args } = panictry!(parser.parse_attr_item()); + let AttrItem { path, args } = match parser.parse_attr_item() { + Ok(ai) => ai, + Err(mut err) => { + err.emit(); + continue; + } + }; let end_span = parser.token.span; if parser.token != token::Eof { parse_sess.span_diagnostic.span_err(start_span.to(end_span), "invalid crate attribute"); diff --git a/src/librustc_builtin_macros/source_util.rs b/src/librustc_builtin_macros/source_util.rs index 5ad72a7443dd2..1aae93e19f369 100644 --- a/src/librustc_builtin_macros/source_util.rs +++ b/src/librustc_builtin_macros/source_util.rs @@ -4,7 +4,6 @@ use rustc_ast::token; use rustc_ast::tokenstream::TokenStream; use rustc_ast_pretty::pprust; use rustc_expand::base::{self, *}; -use rustc_expand::panictry; use rustc_parse::{self, new_sub_parser_from_file, parser::Parser, DirectoryOwnership}; use rustc_session::lint::builtin::INCOMPLETE_INCLUDE; use rustc_span::symbol::Symbol; @@ -116,7 +115,7 @@ pub fn expand_include<'cx>( } impl<'a> base::MacResult for ExpandResult<'a> { fn make_expr(mut self: Box>) -> Option> { - let r = panictry!(self.p.parse_expr()); + let r = base::parse_expr(&mut self.p)?; if self.p.token != token::Eof { self.p.sess.buffer_lint( &INCOMPLETE_INCLUDE, @@ -131,18 +130,17 @@ pub fn expand_include<'cx>( fn make_items(mut self: Box>) -> Option; 1]>> { let mut ret = SmallVec::new(); while self.p.token != token::Eof { - match panictry!(self.p.parse_item()) { - Some(item) => ret.push(item), - None => { + match self.p.parse_item() { + Err(mut err) => { + err.emit(); + break; + } + Ok(Some(item)) => ret.push(item), + Ok(None) => { let token = pprust::token_to_string(&self.p.token); - self.p - .sess - .span_diagnostic - .span_fatal( - self.p.token.span, - &format!("expected item, found `{}`", token), - ) - .raise(); + let msg = format!("expected item, found `{}`", token); + self.p.struct_span_err(self.p.token.span, &msg).emit(); + break; } } } diff --git a/src/librustc_builtin_macros/test.rs b/src/librustc_builtin_macros/test.rs index 39009ca27f102..bdc4ae2fe274b 100644 --- a/src/librustc_builtin_macros/test.rs +++ b/src/librustc_builtin_macros/test.rs @@ -74,16 +74,16 @@ pub fn expand_test_or_bench( return vec![]; } - let item = if let Annotatable::Item(i) = item { - i - } else { - cx.parse_sess - .span_diagnostic - .span_fatal( - item.span(), + let item = match item { + Annotatable::Item(i) => i, + other => { + cx.struct_span_err( + other.span(), "`#[test]` attribute is only allowed on non associated functions", ) - .raise(); + .emit(); + return vec![other]; + } }; if let ast::ItemKind::MacCall(_) = item.kind { diff --git a/src/librustc_builtin_macros/test_harness.rs b/src/librustc_builtin_macros/test_harness.rs index 15997a27fadf2..778bfc1a1f7df 100644 --- a/src/librustc_builtin_macros/test_harness.rs +++ b/src/librustc_builtin_macros/test_harness.rs @@ -345,14 +345,14 @@ fn is_test_case(i: &ast::Item) -> bool { fn get_test_runner(sd: &rustc_errors::Handler, krate: &ast::Crate) -> Option { let test_attr = attr::find_by_name(&krate.attrs, sym::test_runner)?; - test_attr.meta_item_list().map(|meta_list| { - if meta_list.len() != 1 { - sd.span_fatal(test_attr.span, "`#![test_runner(..)]` accepts exactly 1 argument") - .raise() - } - match meta_list[0].meta_item() { - Some(meta_item) if meta_item.is_word() => meta_item.path.clone(), - _ => sd.span_fatal(test_attr.span, "`test_runner` argument must be a path").raise(), - } - }) + let meta_list = test_attr.meta_item_list()?; + let span = test_attr.span; + match &*meta_list { + [single] => match single.meta_item() { + Some(meta_item) if meta_item.is_word() => return Some(meta_item.path.clone()), + _ => sd.struct_span_err(span, "`test_runner` argument must be a path").emit(), + }, + _ => sd.struct_span_err(span, "`#![test_runner(..)]` accepts exactly 1 argument").emit(), + } + None } diff --git a/src/librustc_error_codes/error_codes/E0308.md b/src/librustc_error_codes/error_codes/E0308.md index a907ca272970e..7d87d54194e9b 100644 --- a/src/librustc_error_codes/error_codes/E0308.md +++ b/src/librustc_error_codes/error_codes/E0308.md @@ -1,10 +1,6 @@ -This error occurs when the compiler was unable to infer the concrete type of a -variable. It can occur for several cases, the most common of which is a -mismatch in the expected type that the compiler inferred for a variable's -initializing expression, and the actual type explicitly assigned to the -variable. +Expected type did not match the received type. -For example: +Erroneous code example: ```compile_fail,E0308 let x: i32 = "I am not a number!"; @@ -15,3 +11,9 @@ let x: i32 = "I am not a number!"; // | // type `i32` assigned to variable `x` ``` + +This error occurs when the compiler was unable to infer the concrete type of a +variable. It can occur for several cases, the most common of which is a +mismatch in the expected type that the compiler inferred for a variable's +initializing expression, and the actual type explicitly assigned to the +variable. diff --git a/src/librustc_expand/base.rs b/src/librustc_expand/base.rs index f5f2a5ed43f2c..7af39ee3c0bb9 100644 --- a/src/librustc_expand/base.rs +++ b/src/librustc_expand/base.rs @@ -9,7 +9,7 @@ use rustc_ast::visit::{AssocCtxt, Visitor}; use rustc_attr::{self as attr, Deprecation, HasAttrs, Stability}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::{self, Lrc}; -use rustc_errors::{DiagnosticBuilder, DiagnosticId}; +use rustc_errors::{DiagnosticBuilder, ErrorReported}; use rustc_parse::{self, parser, DirectoryOwnership, MACRO_ARGUMENTS}; use rustc_session::parse::ParseSess; use rustc_span::edition::Edition; @@ -295,16 +295,26 @@ where } pub trait ProcMacro { - fn expand<'cx>(&self, ecx: &'cx mut ExtCtxt<'_>, span: Span, ts: TokenStream) -> TokenStream; + fn expand<'cx>( + &self, + ecx: &'cx mut ExtCtxt<'_>, + span: Span, + ts: TokenStream, + ) -> Result; } impl ProcMacro for F where F: Fn(TokenStream) -> TokenStream, { - fn expand<'cx>(&self, _ecx: &'cx mut ExtCtxt<'_>, _span: Span, ts: TokenStream) -> TokenStream { + fn expand<'cx>( + &self, + _ecx: &'cx mut ExtCtxt<'_>, + _span: Span, + ts: TokenStream, + ) -> Result { // FIXME setup implicit context in TLS before calling self. - (*self)(ts) + Ok((*self)(ts)) } } @@ -315,7 +325,7 @@ pub trait AttrProcMacro { span: Span, annotation: TokenStream, annotated: TokenStream, - ) -> TokenStream; + ) -> Result; } impl AttrProcMacro for F @@ -328,9 +338,9 @@ where _span: Span, annotation: TokenStream, annotated: TokenStream, - ) -> TokenStream { + ) -> Result { // FIXME setup implicit context in TLS before calling self. - (*self)(annotation, annotated) + Ok((*self)(annotation, annotated)) } } @@ -921,6 +931,7 @@ pub struct ExpansionData { pub struct ExtCtxt<'a> { pub parse_sess: &'a ParseSess, pub ecfg: expand::ExpansionConfig<'a>, + pub reduced_recursion_limit: Option, pub root_path: PathBuf, pub resolver: &'a mut dyn Resolver, pub current_expansion: ExpansionData, @@ -936,6 +947,7 @@ impl<'a> ExtCtxt<'a> { ExtCtxt { parse_sess, ecfg, + reduced_recursion_limit: None, root_path: PathBuf::new(), resolver, current_expansion: ExpansionData { @@ -997,31 +1009,9 @@ impl<'a> ExtCtxt<'a> { self.current_expansion.id.expansion_cause() } - pub fn struct_span_warn>(&self, sp: S, msg: &str) -> DiagnosticBuilder<'a> { - self.parse_sess.span_diagnostic.struct_span_warn(sp, msg) - } pub fn struct_span_err>(&self, sp: S, msg: &str) -> DiagnosticBuilder<'a> { self.parse_sess.span_diagnostic.struct_span_err(sp, msg) } - pub fn struct_span_fatal>(&self, sp: S, msg: &str) -> DiagnosticBuilder<'a> { - self.parse_sess.span_diagnostic.struct_span_fatal(sp, msg) - } - - /// Emit `msg` attached to `sp`, and stop compilation immediately. - /// - /// `span_err` should be strongly preferred where-ever possible: - /// this should *only* be used when: - /// - /// - continuing has a high risk of flow-on errors (e.g., errors in - /// declaring a macro would cause all uses of that macro to - /// complain about "undefined macro"), or - /// - there is literally nothing else that can be done (however, - /// in most cases one can construct a dummy expression/item to - /// substitute; we never hit resolve/type-checking so the dummy - /// value doesn't have to match anything) - pub fn span_fatal>(&self, sp: S, msg: &str) -> ! { - self.parse_sess.span_diagnostic.span_fatal(sp, msg).raise(); - } /// Emit `msg` attached to `sp`, without immediately stopping /// compilation. @@ -1031,9 +1021,6 @@ impl<'a> ExtCtxt<'a> { pub fn span_err>(&self, sp: S, msg: &str) { self.parse_sess.span_diagnostic.span_err(sp, msg); } - pub fn span_err_with_code>(&self, sp: S, msg: &str, code: DiagnosticId) { - self.parse_sess.span_diagnostic.span_err_with_code(sp, msg, code); - } pub fn span_warn>(&self, sp: S, msg: &str) { self.parse_sess.span_diagnostic.span_warn(sp, msg); } @@ -1161,6 +1148,18 @@ pub fn check_zero_tts(cx: &ExtCtxt<'_>, sp: Span, tts: TokenStream, name: &str) } } +/// Parse an expression. On error, emit it, advancing to `Eof`, and return `None`. +pub fn parse_expr(p: &mut parser::Parser<'_>) -> Option> { + match p.parse_expr() { + Ok(e) => return Some(e), + Err(mut err) => err.emit(), + } + while p.token != token::Eof { + p.bump(); + } + None +} + /// Interpreting `tts` as a comma-separated sequence of expressions, /// expect exactly one string literal, or emit an error and return `None`. pub fn get_single_str_from_tts( @@ -1174,7 +1173,7 @@ pub fn get_single_str_from_tts( cx.span_err(sp, &format!("{} takes 1 argument", name)); return None; } - let ret = panictry!(p.parse_expr()); + let ret = parse_expr(&mut p)?; let _ = p.eat(&token::Comma); if p.token != token::Eof { @@ -1183,8 +1182,8 @@ pub fn get_single_str_from_tts( expr_to_string(cx, ret, "argument must be a string literal").map(|(s, _)| s.to_string()) } -/// Extracts comma-separated expressions from `tts`. If there is a -/// parsing error, emit a non-fatal error and return `None`. +/// Extracts comma-separated expressions from `tts`. +/// On error, emit it, and return `None`. pub fn get_exprs_from_tts( cx: &mut ExtCtxt<'_>, sp: Span, @@ -1193,7 +1192,7 @@ pub fn get_exprs_from_tts( let mut p = cx.new_parser_from_tts(tts); let mut es = Vec::new(); while p.token != token::Eof { - let expr = panictry!(p.parse_expr()); + let expr = parse_expr(&mut p)?; // Perform eager expansion on the expression. // We want to be able to handle e.g., `concat!("foo", "bar")`. diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index 4d0548f3f868a..ae2f8cba8ca80 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -15,7 +15,7 @@ use rustc_ast::util::map_in_place::MapInPlace; use rustc_ast::visit::{self, AssocCtxt, Visitor}; use rustc_ast_pretty::pprust; use rustc_attr::{self as attr, is_builtin_attr, HasAttrs}; -use rustc_errors::{Applicability, FatalError, PResult}; +use rustc_errors::{Applicability, PResult}; use rustc_feature::Features; use rustc_parse::configure; use rustc_parse::parser::Parser; @@ -204,7 +204,7 @@ ast_fragments! { } impl AstFragmentKind { - fn dummy(self, span: Span) -> AstFragment { + crate fn dummy(self, span: Span) -> AstFragment { self.make_from(DummyResult::any(span)).expect("couldn't create a dummy AST fragment") } @@ -645,7 +645,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> { )) .emit(); self.cx.trace_macros_diag(); - FatalError.raise(); } /// A macro's expansion does not fit in this fragment kind. @@ -665,8 +664,17 @@ impl<'a, 'b> MacroExpander<'a, 'b> { invoc: Invocation, ext: &SyntaxExtensionKind, ) -> ExpandResult { - if self.cx.current_expansion.depth > self.cx.ecfg.recursion_limit { - self.error_recursion_limit_reached(); + let recursion_limit = + self.cx.reduced_recursion_limit.unwrap_or(self.cx.ecfg.recursion_limit); + if self.cx.current_expansion.depth > recursion_limit { + if self.cx.reduced_recursion_limit.is_none() { + self.error_recursion_limit_reached(); + } + + // Reduce the recursion limit by half each time it triggers. + self.cx.reduced_recursion_limit = Some(recursion_limit / 2); + + return ExpandResult::Ready(invoc.fragment_kind.dummy(invoc.span())); } let (fragment_kind, span) = (invoc.fragment_kind, invoc.span()); @@ -674,7 +682,10 @@ impl<'a, 'b> MacroExpander<'a, 'b> { InvocationKind::Bang { mac, .. } => match ext { SyntaxExtensionKind::Bang(expander) => { self.gate_proc_macro_expansion_kind(span, fragment_kind); - let tok_result = expander.expand(self.cx, span, mac.args.inner_tokens()); + let tok_result = match expander.expand(self.cx, span, mac.args.inner_tokens()) { + Err(_) => return ExpandResult::Ready(fragment_kind.dummy(span)), + Ok(ts) => ts, + }; self.parse_ast_fragment(tok_result, fragment_kind, &mac.path, span) } SyntaxExtensionKind::LegacyBang(expander) => { @@ -701,8 +712,11 @@ impl<'a, 'b> MacroExpander<'a, 'b> { if let MacArgs::Eq(..) = attr_item.args { self.cx.span_err(span, "key-value macro attributes are not supported"); } - let tok_result = - expander.expand(self.cx, span, attr_item.args.inner_tokens(), tokens); + let inner_tokens = attr_item.args.inner_tokens(); + let tok_result = match expander.expand(self.cx, span, inner_tokens, tokens) { + Err(_) => return ExpandResult::Ready(fragment_kind.dummy(span)), + Ok(ts) => ts, + }; self.parse_ast_fragment(tok_result, fragment_kind, &attr_item.path, span) } SyntaxExtensionKind::LegacyAttr(expander) => { @@ -1131,6 +1145,8 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { // macros are expanded before any lint passes so this warning has to be hardcoded if attr.has_name(sym::derive) { self.cx + .parse_sess() + .span_diagnostic .struct_span_warn(attr.span, "`#[derive]` does nothing on macro invocations") .note("this may become a hard error in a future release") .emit(); diff --git a/src/librustc_expand/lib.rs b/src/librustc_expand/lib.rs index f119c956ced04..434d00e905281 100644 --- a/src/librustc_expand/lib.rs +++ b/src/librustc_expand/lib.rs @@ -7,25 +7,6 @@ extern crate proc_macro as pm; -// A variant of 'try!' that panics on an Err. This is used as a crutch on the -// way towards a non-panic!-prone parser. It should be used for fatal parsing -// errors; eventually we plan to convert all code using panictry to just use -// normal try. -#[macro_export] -macro_rules! panictry { - ($e:expr) => {{ - use rustc_errors::FatalError; - use std::result::Result::{Err, Ok}; - match $e { - Ok(e) => e, - Err(mut e) => { - e.emit(); - FatalError.raise() - } - } - }}; -} - mod placeholders; mod proc_macro_server; diff --git a/src/librustc_expand/mbe/macro_parser.rs b/src/librustc_expand/mbe/macro_parser.rs index 3b9158f444519..a3ab98357f40d 100644 --- a/src/librustc_expand/mbe/macro_parser.rs +++ b/src/librustc_expand/mbe/macro_parser.rs @@ -84,7 +84,7 @@ use rustc_parse::parser::{FollowedByType, Parser, PathStyle}; use rustc_session::parse::ParseSess; use rustc_span::symbol::{kw, sym, Ident, MacroRulesNormalizedIdent, Symbol}; -use rustc_errors::{FatalError, PResult}; +use rustc_errors::PResult; use rustc_span::Span; use smallvec::{smallvec, SmallVec}; @@ -271,6 +271,7 @@ crate enum ParseResult { Failure(Token, &'static str), /// Fatal error (malformed macro?). Abort compilation. Error(rustc_span::Span, String), + ErrorReported, } /// A `ParseResult` where the `Success` variant contains a mapping of @@ -652,6 +653,7 @@ pub(super) fn parse_tt(parser: &mut Cow<'_, Parser<'_>>, ms: &[TokenTree]) -> Na Success(_) => {} Failure(token, msg) => return Failure(token, msg), Error(sp, msg) => return Error(sp, msg), + ErrorReported => return ErrorReported, } // inner parse loop handled all cur_items, so it's empty @@ -735,10 +737,11 @@ pub(super) fn parse_tt(parser: &mut Cow<'_, Parser<'_>>, ms: &[TokenTree]) -> Na let mut item = bb_items.pop().unwrap(); if let TokenTree::MetaVarDecl(span, _, ident) = item.top_elts.get_tt(item.idx) { let match_cur = item.match_cur; - item.push_match( - match_cur, - MatchedNonterminal(Lrc::new(parse_nt(parser.to_mut(), span, ident.name))), - ); + let nt = match parse_nt(parser.to_mut(), span, ident.name) { + Err(()) => return ErrorReported, + Ok(nt) => nt, + }; + item.push_match(match_cur, MatchedNonterminal(Lrc::new(nt))); item.idx += 1; item.match_cur += 1; } else { @@ -849,20 +852,16 @@ fn may_begin_with(token: &Token, name: Name) -> bool { /// # Returns /// /// The parsed non-terminal. -fn parse_nt(p: &mut Parser<'_>, sp: Span, name: Symbol) -> Nonterminal { +fn parse_nt(p: &mut Parser<'_>, sp: Span, name: Symbol) -> Result { // FIXME(Centril): Consider moving this to `parser.rs` to make // the visibilities of the methods used below `pub(super)` at most. - if name == sym::tt { - return token::NtTT(p.parse_token_tree()); - } - match parse_nt_inner(p, sp, name) { - Ok(nt) => nt, - Err(mut err) => { - err.emit(); - FatalError.raise(); - } + return Ok(token::NtTT(p.parse_token_tree())); } + parse_nt_inner(p, sp, name).map_err(|mut err| { + err.span_label(sp, format!("while parsing argument for this `{}` macro fragment", name)) + .emit() + }) } fn parse_nt_inner<'a>(p: &mut Parser<'a>, sp: Span, name: Symbol) -> PResult<'a, Nonterminal> { diff --git a/src/librustc_expand/mbe/macro_rules.rs b/src/librustc_expand/mbe/macro_rules.rs index 2268c9b385477..c4a79b87bfdef 100644 --- a/src/librustc_expand/mbe/macro_rules.rs +++ b/src/librustc_expand/mbe/macro_rules.rs @@ -4,7 +4,7 @@ use crate::expand::{ensure_complete_parse, parse_ast_fragment, AstFragment, AstF use crate::mbe; use crate::mbe::macro_check; use crate::mbe::macro_parser::parse_tt; -use crate::mbe::macro_parser::{Error, Failure, Success}; +use crate::mbe::macro_parser::{Error, ErrorReported, Failure, Success}; use crate::mbe::macro_parser::{MatchedNonterminal, MatchedSeq}; use crate::mbe::transcribe::transcribe; @@ -15,7 +15,7 @@ use rustc_ast_pretty::pprust; use rustc_attr::{self as attr, TransparencyError}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; -use rustc_errors::{Applicability, DiagnosticBuilder, FatalError}; +use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_feature::Features; use rustc_parse::parser::Parser; use rustc_parse::Directory; @@ -84,41 +84,56 @@ fn suggest_slice_pat(e: &mut DiagnosticBuilder<'_>, site_span: Span, parser: &Pa ); } +fn emit_frag_parse_err( + mut e: DiagnosticBuilder<'_>, + parser: &Parser<'_>, + site_span: Span, + macro_ident: ast::Ident, + arm_span: Span, + kind: AstFragmentKind, +) { + if parser.token == token::Eof && e.message().ends_with(", found ``") { + if !e.span.is_dummy() { + // early end of macro arm (#52866) + e.replace_span_with(parser.sess.source_map().next_point(parser.token.span)); + } + let msg = &e.message[0]; + e.message[0] = ( + format!( + "macro expansion ends with an incomplete expression: {}", + msg.0.replace(", found ``", ""), + ), + msg.1, + ); + } + if e.span.is_dummy() { + // Get around lack of span in error (#30128) + e.replace_span_with(site_span); + if !parser.sess.source_map().is_imported(arm_span) { + e.span_label(arm_span, "in this macro arm"); + } + } else if parser.sess.source_map().is_imported(parser.token.span) { + e.span_label(site_span, "in this macro invocation"); + } + match kind { + AstFragmentKind::Pat if macro_ident.name == sym::vec => { + suggest_slice_pat(&mut e, site_span, parser); + } + _ => annotate_err_with_kind(&mut e, kind, site_span), + }; + e.emit(); +} + impl<'a> ParserAnyMacro<'a> { crate fn make(mut self: Box>, kind: AstFragmentKind) -> AstFragment { let ParserAnyMacro { site_span, macro_ident, ref mut parser, arm_span } = *self; - let fragment = panictry!(parse_ast_fragment(parser, kind).map_err(|mut e| { - if parser.token == token::Eof && e.message().ends_with(", found ``") { - if !e.span.is_dummy() { - // early end of macro arm (#52866) - e.replace_span_with(parser.sess.source_map().next_point(parser.token.span)); - } - let msg = &e.message[0]; - e.message[0] = ( - format!( - "macro expansion ends with an incomplete expression: {}", - msg.0.replace(", found ``", ""), - ), - msg.1, - ); + let fragment = match parse_ast_fragment(parser, kind) { + Ok(f) => f, + Err(err) => { + emit_frag_parse_err(err, parser, site_span, macro_ident, arm_span, kind); + return kind.dummy(site_span); } - if e.span.is_dummy() { - // Get around lack of span in error (#30128) - e.replace_span_with(site_span); - if !parser.sess.source_map().is_imported(arm_span) { - e.span_label(arm_span, "in this macro arm"); - } - } else if parser.sess.source_map().is_imported(parser.token.span) { - e.span_label(site_span, "in this macro invocation"); - } - match kind { - AstFragmentKind::Pat if macro_ident.name == sym::vec => { - suggest_slice_pat(&mut e, site_span, parser); - } - _ => annotate_err_with_kind(&mut e, kind, site_span), - }; - e - })); + }; // We allow semicolons at the end of expressions -- e.g., the semicolon in // `macro_rules! m { () => { panic!(); } }` isn't parsed by `.parse_expr()`, @@ -166,6 +181,14 @@ impl TTMacroExpander for MacroRulesMacroExpander { } } +fn macro_rules_dummy_expander<'cx>( + _: &'cx mut ExtCtxt<'_>, + span: Span, + _: TokenStream, +) -> Box { + DummyResult::any(span) +} + fn trace_macros_note(cx_expansions: &mut FxHashMap>, sp: Span, message: String) { let sp = sp.macro_backtrace().last().map(|trace| trace.call_site).unwrap_or(sp); cx_expansions.entry(sp).or_default().push(message); @@ -240,7 +263,13 @@ fn generic_extension<'cx>( let rhs_spans = rhs.iter().map(|t| t.span()).collect::>(); // rhs has holes ( `$id` and `$(...)` that need filled) - let mut tts = transcribe(cx, &named_matches, rhs, transparency); + let mut tts = match transcribe(cx, &named_matches, rhs, transparency) { + Ok(tts) => tts, + Err(mut err) => { + err.emit(); + return DummyResult::any(arm_span); + } + }; // Replace all the tokens for the corresponding positions in the macro, to maintain // proper positions in error reporting, while maintaining the macro_backtrace. @@ -284,7 +313,12 @@ fn generic_extension<'cx>( Some((ref best_token, _)) if best_token.span.lo() >= token.span.lo() => {} _ => best_failure = Some((token, msg)), }, - Error(err_sp, ref msg) => cx.span_fatal(err_sp.substitute_dummy(sp), &msg[..]), + Error(err_sp, ref msg) => { + let span = err_sp.substitute_dummy(sp); + cx.struct_span_err(span, &msg).emit(); + return DummyResult::any(span); + } + ErrorReported => return DummyResult::any(sp), } // The matcher was not `Success(..)`ful. @@ -344,6 +378,18 @@ pub fn compile_declarative_macro( def: &ast::Item, edition: Edition, ) -> SyntaxExtension { + let mk_syn_ext = |expander| { + SyntaxExtension::new( + sess, + SyntaxExtensionKind::LegacyBang(expander), + def.span, + Vec::new(), + edition, + def.ident.name, + &def.attrs, + ) + }; + let diag = &sess.span_diagnostic; let lhs_nm = ast::Ident::new(sym::lhs, def.span); let rhs_nm = ast::Ident::new(sym::rhs, def.span); @@ -398,13 +444,15 @@ pub fn compile_declarative_macro( Failure(token, msg) => { let s = parse_failure_msg(&token); let sp = token.span.substitute_dummy(def.span); - let mut err = sess.span_diagnostic.struct_span_fatal(sp, &s); - err.span_label(sp, msg); - err.emit(); - FatalError.raise(); + sess.span_diagnostic.struct_span_err(sp, &s).span_label(sp, msg).emit(); + return mk_syn_ext(Box::new(macro_rules_dummy_expander)); + } + Error(sp, msg) => { + sess.span_diagnostic.struct_span_err(sp.substitute_dummy(def.span), &msg).emit(); + return mk_syn_ext(Box::new(macro_rules_dummy_expander)); } - Error(sp, s) => { - sess.span_diagnostic.span_fatal(sp.substitute_dummy(def.span), &s).raise(); + ErrorReported => { + return mk_syn_ext(Box::new(macro_rules_dummy_expander)); } }; @@ -467,24 +515,14 @@ pub fn compile_declarative_macro( None => {} } - let expander: Box<_> = Box::new(MacroRulesMacroExpander { + mk_syn_ext(Box::new(MacroRulesMacroExpander { name: def.ident, span: def.span, transparency, lhses, rhses, valid, - }); - - SyntaxExtension::new( - sess, - SyntaxExtensionKind::LegacyBang(expander), - def.span, - Vec::new(), - edition, - def.ident.name, - &def.attrs, - ) + })) } fn check_lhs_nt_follows( diff --git a/src/librustc_expand/mbe/transcribe.rs b/src/librustc_expand/mbe/transcribe.rs index 1b1093c9529f4..e2d3d5c4d644e 100644 --- a/src/librustc_expand/mbe/transcribe.rs +++ b/src/librustc_expand/mbe/transcribe.rs @@ -8,7 +8,7 @@ use rustc_ast::token::{self, NtTT, Token}; use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndJoint}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; -use rustc_errors::pluralize; +use rustc_errors::{pluralize, PResult}; use rustc_span::hygiene::{ExpnId, Transparency}; use rustc_span::symbol::MacroRulesNormalizedIdent; use rustc_span::Span; @@ -80,15 +80,15 @@ impl Iterator for Frame { /// `transcribe` would return a `TokenStream` containing `println!("{}", stringify!(bar));`. /// /// Along the way, we do some additional error checking. -pub(super) fn transcribe( - cx: &ExtCtxt<'_>, +pub(super) fn transcribe<'a>( + cx: &ExtCtxt<'a>, interp: &FxHashMap, src: Vec, transparency: Transparency, -) -> TokenStream { +) -> PResult<'a, TokenStream> { // Nothing for us to transcribe... if src.is_empty() { - return TokenStream::default(); + return Ok(TokenStream::default()); } // We descend into the RHS (`src`), expanding things as we go. This stack contains the things @@ -152,7 +152,7 @@ pub(super) fn transcribe( Frame::Delimited { forest, span, .. } => { if result_stack.is_empty() { // No results left to compute! We are back at the top-level. - return TokenStream::new(result); + return Ok(TokenStream::new(result)); } // Step back into the parent Delimited. @@ -173,11 +173,11 @@ pub(super) fn transcribe( seq @ mbe::TokenTree::Sequence(..) => { match lockstep_iter_size(&seq, interp, &repeats) { LockstepIterSize::Unconstrained => { - cx.span_fatal( + return Err(cx.struct_span_err( seq.span(), /* blame macro writer */ "attempted to repeat an expression containing no syntax variables \ matched as repeating at this depth", - ); + )); } LockstepIterSize::Contradiction(ref msg) => { @@ -185,7 +185,7 @@ pub(super) fn transcribe( // happens when two meta-variables are used in the same repetition in a // sequence, but they come from different sequence matchers and repeat // different amounts. - cx.span_fatal(seq.span(), &msg[..]); + return Err(cx.struct_span_err(seq.span(), &msg[..])); } LockstepIterSize::Constraint(len, _) => { @@ -203,7 +203,10 @@ pub(super) fn transcribe( // FIXME: this really ought to be caught at macro definition // time... It happens when the Kleene operator in the matcher and // the body for the same meta-variable do not match. - cx.span_fatal(sp.entire(), "this must repeat at least once"); + return Err(cx.struct_span_err( + sp.entire(), + "this must repeat at least once", + )); } } else { // 0 is the initial counter (we have done 0 repretitions so far). `len` @@ -242,10 +245,10 @@ pub(super) fn transcribe( } } else { // We were unable to descend far enough. This is an error. - cx.span_fatal( + return Err(cx.struct_span_err( sp, /* blame the macro writer */ &format!("variable '{}' is still repeating at this depth", ident), - ); + )); } } else { // If we aren't able to match the meta-var, we push it back into the result but diff --git a/src/librustc_expand/proc_macro.rs b/src/librustc_expand/proc_macro.rs index cb9afa4cd4f02..df7bf9438c3d0 100644 --- a/src/librustc_expand/proc_macro.rs +++ b/src/librustc_expand/proc_macro.rs @@ -5,7 +5,7 @@ use rustc_ast::ast::{self, ItemKind, MetaItemKind, NestedMetaItem}; use rustc_ast::token; use rustc_ast::tokenstream::{self, TokenStream}; use rustc_data_structures::sync::Lrc; -use rustc_errors::{Applicability, FatalError}; +use rustc_errors::{Applicability, ErrorReported}; use rustc_span::symbol::sym; use rustc_span::{Span, DUMMY_SP}; @@ -21,21 +21,16 @@ impl base::ProcMacro for BangProcMacro { ecx: &'cx mut ExtCtxt<'_>, span: Span, input: TokenStream, - ) -> TokenStream { + ) -> Result { let server = proc_macro_server::Rustc::new(ecx); - match self.client.run(&EXEC_STRATEGY, server, input) { - Ok(stream) => stream, - Err(e) => { - let msg = "proc macro panicked"; - let mut err = ecx.struct_span_fatal(span, msg); - if let Some(s) = e.as_str() { - err.help(&format!("message: {}", s)); - } - - err.emit(); - FatalError.raise(); + self.client.run(&EXEC_STRATEGY, server, input).map_err(|e| { + let mut err = ecx.struct_span_err(span, "proc macro panicked"); + if let Some(s) = e.as_str() { + err.help(&format!("message: {}", s)); } - } + err.emit(); + ErrorReported + }) } } @@ -50,21 +45,16 @@ impl base::AttrProcMacro for AttrProcMacro { span: Span, annotation: TokenStream, annotated: TokenStream, - ) -> TokenStream { + ) -> Result { let server = proc_macro_server::Rustc::new(ecx); - match self.client.run(&EXEC_STRATEGY, server, annotation, annotated) { - Ok(stream) => stream, - Err(e) => { - let msg = "custom attribute panicked"; - let mut err = ecx.struct_span_fatal(span, msg); - if let Some(s) = e.as_str() { - err.help(&format!("message: {}", s)); - } - - err.emit(); - FatalError.raise(); + self.client.run(&EXEC_STRATEGY, server, annotation, annotated).map_err(|e| { + let mut err = ecx.struct_span_err(span, "custom attribute panicked"); + if let Some(s) = e.as_str() { + err.help(&format!("message: {}", s)); } - } + err.emit(); + ErrorReported + }) } } @@ -96,8 +86,7 @@ impl MultiItemModifier for ProcMacroDerive { | Annotatable::Expr(_) => { ecx.span_err( span, - "proc-macro derives may only be \ - applied to a struct, enum, or union", + "proc-macro derives may only be applied to a struct, enum, or union", ); return ExpandResult::Ready(Vec::new()); } @@ -107,8 +96,7 @@ impl MultiItemModifier for ProcMacroDerive { _ => { ecx.span_err( span, - "proc-macro derives may only be \ - applied to a struct, enum, or union", + "proc-macro derives may only be applied to a struct, enum, or union", ); return ExpandResult::Ready(Vec::new()); } @@ -121,20 +109,16 @@ impl MultiItemModifier for ProcMacroDerive { let stream = match self.client.run(&EXEC_STRATEGY, server, input) { Ok(stream) => stream, Err(e) => { - let msg = "proc-macro derive panicked"; - let mut err = ecx.struct_span_fatal(span, msg); + let mut err = ecx.struct_span_err(span, "proc-macro derive panicked"); if let Some(s) = e.as_str() { err.help(&format!("message: {}", s)); } - err.emit(); - FatalError.raise(); + return ExpandResult::Ready(vec![]); } }; let error_count_before = ecx.parse_sess.span_diagnostic.err_count(); - let msg = "proc-macro derive produced unparseable tokens"; - let mut parser = rustc_parse::stream_to_parser(ecx.parse_sess, stream, Some("proc-macro derive")); let mut items = vec![]; @@ -144,18 +128,15 @@ impl MultiItemModifier for ProcMacroDerive { Ok(None) => break, Ok(Some(item)) => items.push(Annotatable::Item(item)), Err(mut err) => { - // FIXME: handle this better - err.cancel(); - ecx.struct_span_fatal(span, msg).emit(); - FatalError.raise(); + err.emit(); + break; } } } // fail if there have been errors emitted if ecx.parse_sess.span_diagnostic.err_count() > error_count_before { - ecx.struct_span_fatal(span, msg).emit(); - FatalError.raise(); + ecx.struct_span_err(span, "proc-macro derive produced unparseable tokens").emit(); } ExpandResult::Ready(items) diff --git a/src/librustc_hir/hir_id.rs b/src/librustc_hir/hir_id.rs index 6d2ec44576353..a11638a3bb24f 100644 --- a/src/librustc_hir/hir_id.rs +++ b/src/librustc_hir/hir_id.rs @@ -71,7 +71,7 @@ rustc_data_structures::impl_stable_hash_via_hash!(ItemLocalId); /// The `HirId` corresponding to `CRATE_NODE_ID` and `CRATE_DEF_INDEX`. pub const CRATE_HIR_ID: HirId = - HirId { owner: CRATE_DEF_INDEX, local_id: ItemLocalId::from_u32_const(0) }; + HirId { owner: CRATE_DEF_INDEX, local_id: ItemLocalId::from_u32(0) }; pub const DUMMY_HIR_ID: HirId = HirId { owner: CRATE_DEF_INDEX, local_id: DUMMY_ITEM_LOCAL_ID }; diff --git a/src/librustc_hir/lib.rs b/src/librustc_hir/lib.rs index 45f806b53f50c..fa5c72b060dcf 100644 --- a/src/librustc_hir/lib.rs +++ b/src/librustc_hir/lib.rs @@ -3,7 +3,9 @@ //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html #![feature(crate_visibility_modifier)] +#![feature(const_if_match)] #![feature(const_fn)] // For the unsizing cast on `&[]` +#![feature(const_panic)] #![feature(in_band_lifetimes)] #![feature(specialization)] #![recursion_limit = "256"] diff --git a/src/librustc_index/lib.rs b/src/librustc_index/lib.rs index 86dd1a29d0ce3..e8aa1a209e929 100644 --- a/src/librustc_index/lib.rs +++ b/src/librustc_index/lib.rs @@ -1,4 +1,7 @@ #![feature(allow_internal_unstable)] +#![feature(const_if_match)] +#![feature(const_fn)] +#![feature(const_panic)] #![feature(unboxed_closures)] #![feature(test)] #![feature(fn_traits)] diff --git a/src/librustc_index/vec.rs b/src/librustc_index/vec.rs index 7020939fa20b2..d8c67f6210c75 100644 --- a/src/librustc_index/vec.rs +++ b/src/librustc_index/vec.rs @@ -120,10 +120,10 @@ macro_rules! newtype_index { impl $type { $v const MAX_AS_U32: u32 = $max; - $v const MAX: Self = Self::from_u32_const($max); + $v const MAX: Self = Self::from_u32($max); #[inline] - $v fn from_usize(value: usize) -> Self { + $v const fn from_usize(value: usize) -> Self { assert!(value <= ($max as usize)); unsafe { Self::from_u32_unchecked(value as u32) @@ -131,31 +131,13 @@ macro_rules! newtype_index { } #[inline] - $v fn from_u32(value: u32) -> Self { + $v const fn from_u32(value: u32) -> Self { assert!(value <= $max); unsafe { Self::from_u32_unchecked(value) } } - /// Hacky variant of `from_u32` for use in constants. - /// This version checks the "max" constraint by using an - /// invalid array dereference. - #[inline] - $v const fn from_u32_const(value: u32) -> Self { - // This will fail at const eval time unless `value <= - // max` is true (in which case we get the index 0). - // It will also fail at runtime, of course, but in a - // kind of wacky way. - let _ = ["out of range value used"][ - !(value <= $max) as usize - ]; - - unsafe { - Self { private: value } - } - } - #[inline] $v const unsafe fn from_u32_unchecked(value: u32) -> Self { Self { private: value } @@ -163,19 +145,19 @@ macro_rules! newtype_index { /// Extracts the value of this index as an integer. #[inline] - $v fn index(self) -> usize { + $v const fn index(self) -> usize { self.as_usize() } /// Extracts the value of this index as a `u32`. #[inline] - $v fn as_u32(self) -> u32 { + $v const fn as_u32(self) -> u32 { self.private } /// Extracts the value of this index as a `usize`. #[inline] - $v fn as_usize(self) -> usize { + $v const fn as_usize(self) -> usize { self.as_u32() as usize } } @@ -500,7 +482,7 @@ macro_rules! newtype_index { const $name:ident = $constant:expr, $($tokens:tt)*) => ( $(#[doc = $doc])* - $v const $name: $type = $type::from_u32_const($constant); + $v const $name: $type = $type::from_u32($constant); $crate::newtype_index!( @derives [$($derives,)*] @attrs [$(#[$attrs])*] diff --git a/src/librustc_infer/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs index a544381f33da1..ebbfcb28db2f5 100644 --- a/src/librustc_infer/infer/error_reporting/mod.rs +++ b/src/librustc_infer/infer/error_reporting/mod.rs @@ -49,7 +49,7 @@ use super::lexical_region_resolve::RegionResolutionError; use super::region_constraints::GenericKind; use super::{InferCtxt, RegionVariableOrigin, SubregionOrigin, TypeTrace, ValuePairs}; -use crate::infer::{self, SuppressRegionErrors}; +use crate::infer; use crate::traits::error_reporting::report_object_safety_error; use crate::traits::{ IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode, @@ -372,17 +372,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { &self, region_scope_tree: ®ion::ScopeTree, errors: &Vec>, - suppress: SuppressRegionErrors, ) { - debug!( - "report_region_errors(): {} errors to start, suppress = {:?}", - errors.len(), - suppress - ); - - if suppress.suppressed() { - return; - } + debug!("report_region_errors(): {} errors to start", errors.len()); // try to pre-process the errors, which will group some of them // together into a `ProcessedErrors` group: diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/different_lifetimes.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/different_lifetimes.rs index 1a09729ef6443..50b324c72278e 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/different_lifetimes.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/different_lifetimes.rs @@ -3,6 +3,8 @@ use crate::infer::error_reporting::nice_region_error::util::AnonymousParamInfo; use crate::infer::error_reporting::nice_region_error::NiceRegionError; +use crate::infer::lexical_region_resolve::RegionResolutionError; +use crate::infer::SubregionOrigin; use rustc::util::common::ErrorReported; use rustc_errors::struct_span_err; @@ -47,6 +49,15 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { pub(super) fn try_report_anon_anon_conflict(&self) -> Option { let (span, sub, sup) = self.regions()?; + if let Some(RegionResolutionError::ConcreteFailure( + SubregionOrigin::ReferenceOutlivesReferent(..), + .., + )) = self.error + { + // This error doesn't make much sense in this case. + return None; + } + // Determine whether the sub and sup consist of both anonymous (elided) regions. let anon_reg_sup = self.tcx().is_suitable_region(sup)?; diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/mod.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/mod.rs index d8c314a0d2f1f..2357ee689d59e 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/mod.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/mod.rs @@ -17,12 +17,7 @@ mod util; impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { pub fn try_report_nice_region_error(&self, error: &RegionResolutionError<'tcx>) -> bool { - if let Some(tables) = self.in_progress_tables { - let tables = tables.borrow(); - NiceRegionError::new(self, error.clone(), Some(&tables)).try_report().is_some() - } else { - NiceRegionError::new(self, error.clone(), None).try_report().is_some() - } + NiceRegionError::new(self, error.clone()).try_report().is_some() } } @@ -30,16 +25,11 @@ pub struct NiceRegionError<'cx, 'tcx> { infcx: &'cx InferCtxt<'cx, 'tcx>, error: Option>, regions: Option<(Span, ty::Region<'tcx>, ty::Region<'tcx>)>, - tables: Option<&'cx ty::TypeckTables<'tcx>>, } impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> { - pub fn new( - infcx: &'cx InferCtxt<'cx, 'tcx>, - error: RegionResolutionError<'tcx>, - tables: Option<&'cx ty::TypeckTables<'tcx>>, - ) -> Self { - Self { infcx, error: Some(error), regions: None, tables } + pub fn new(infcx: &'cx InferCtxt<'cx, 'tcx>, error: RegionResolutionError<'tcx>) -> Self { + Self { infcx, error: Some(error), regions: None } } pub fn new_from_span( @@ -47,9 +37,8 @@ impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> { span: Span, sub: ty::Region<'tcx>, sup: ty::Region<'tcx>, - tables: Option<&'cx ty::TypeckTables<'tcx>>, ) -> Self { - Self { infcx, error: None, regions: Some((span, sub, sup)), tables } + Self { infcx, error: None, regions: Some((span, sub, sup)) } } fn tcx(&self) -> TyCtxt<'tcx> { diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs index cab632935fd8e..de72c276595f7 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs @@ -51,52 +51,44 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { }; let hir = &self.tcx().hir(); - if let Some(hir_id) = hir.as_local_hir_id(id) { - if let Some(body_id) = hir.maybe_body_owned_by(hir_id) { - let body = hir.body(body_id); - let owner_id = hir.body_owner(body_id); - let fn_decl = hir.fn_decl_by_hir_id(owner_id).unwrap(); - if let Some(tables) = self.tables { - body.params - .iter() - .enumerate() - .filter_map(|(index, param)| { - // May return None; sometimes the tables are not yet populated. - let ty_hir_id = fn_decl.inputs[index].hir_id; - let param_ty_span = hir.span(ty_hir_id); - let ty = tables.node_type_opt(param.hir_id)?; - let mut found_anon_region = false; - let new_param_ty = self.tcx().fold_regions(&ty, &mut false, |r, _| { - if *r == *anon_region { - found_anon_region = true; - replace_region - } else { - r - } - }); - if found_anon_region { - let is_first = index == 0; - Some(AnonymousParamInfo { - param, - param_ty: new_param_ty, - param_ty_span, - bound_region, - is_first, - }) - } else { - None - } - }) - .next() + let hir_id = hir.as_local_hir_id(id)?; + let body_id = hir.maybe_body_owned_by(hir_id)?; + let body = hir.body(body_id); + let owner_id = hir.body_owner(body_id); + let fn_decl = hir.fn_decl_by_hir_id(owner_id).unwrap(); + let poly_fn_sig = self.tcx().fn_sig(id); + let fn_sig = self.tcx().liberate_late_bound_regions(id, &poly_fn_sig); + body.params + .iter() + .enumerate() + .filter_map(|(index, param)| { + // May return None; sometimes the tables are not yet populated. + let ty = fn_sig.inputs()[index]; + let mut found_anon_region = false; + let new_param_ty = self.tcx().fold_regions(&ty, &mut false, |r, _| { + if *r == *anon_region { + found_anon_region = true; + replace_region + } else { + r + } + }); + if found_anon_region { + let ty_hir_id = fn_decl.inputs[index].hir_id; + let param_ty_span = hir.span(ty_hir_id); + let is_first = index == 0; + Some(AnonymousParamInfo { + param, + param_ty: new_param_ty, + param_ty_span, + bound_region, + is_first, + }) } else { None } - } else { - None - } - } else { - None - } + }) + .next() } // Here, we check for the case where the anonymous region diff --git a/src/librustc_infer/infer/lexical_region_resolve/mod.rs b/src/librustc_infer/infer/lexical_region_resolve/mod.rs index b7278ecd5e407..3af10e850d534 100644 --- a/src/librustc_infer/infer/lexical_region_resolve/mod.rs +++ b/src/librustc_infer/infer/lexical_region_resolve/mod.rs @@ -7,6 +7,7 @@ use crate::infer::region_constraints::RegionConstraintData; use crate::infer::region_constraints::VarInfos; use crate::infer::region_constraints::VerifyBound; use crate::infer::RegionVariableOrigin; +use crate::infer::RegionckMode; use crate::infer::SubregionOrigin; use rustc::middle::free_region::RegionRelations; use rustc::ty::fold::TypeFoldable; @@ -33,12 +34,29 @@ pub fn resolve<'tcx>( region_rels: &RegionRelations<'_, 'tcx>, var_infos: VarInfos, data: RegionConstraintData<'tcx>, + mode: RegionckMode, ) -> (LexicalRegionResolutions<'tcx>, Vec>) { debug!("RegionConstraintData: resolve_regions()"); let mut errors = vec![]; let mut resolver = LexicalResolver { region_rels, var_infos, data }; - let values = resolver.infer_variable_values(&mut errors); - (values, errors) + match mode { + RegionckMode::Solve => { + let values = resolver.infer_variable_values(&mut errors); + (values, errors) + } + RegionckMode::Erase { suppress_errors: false } => { + // Do real inference to get errors, then erase the results. + let mut values = resolver.infer_variable_values(&mut errors); + let re_erased = region_rels.tcx.lifetimes.re_erased; + + values.values.iter_mut().for_each(|v| *v = VarValue::Value(re_erased)); + (values, errors) + } + RegionckMode::Erase { suppress_errors: true } => { + // Skip region inference entirely. + (resolver.erased_data(region_rels.tcx), Vec::new()) + } + } } /// Contains the result of lexical region resolution. Offers methods @@ -163,6 +181,19 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { } } + /// An erased version of the lexical region resolutions. Used when we're + /// erasing regions and suppressing errors: in item bodies with + /// `-Zborrowck=mir`. + fn erased_data(&self, tcx: TyCtxt<'tcx>) -> LexicalRegionResolutions<'tcx> { + LexicalRegionResolutions { + error_region: tcx.lifetimes.re_static, + values: IndexVec::from_elem_n( + VarValue::Value(tcx.lifetimes.re_erased), + self.num_vars(), + ), + } + } + fn dump_constraints(&self, free_regions: &RegionRelations<'_, 'tcx>) { debug!("----() Start constraint listing (context={:?}) ()----", free_regions.context); for (idx, (constraint, _)) in self.data.constraints.iter().enumerate() { diff --git a/src/librustc_infer/infer/mod.rs b/src/librustc_infer/infer/mod.rs index 9ae131c568d0d..c5f06d53b8f73 100644 --- a/src/librustc_infer/infer/mod.rs +++ b/src/librustc_infer/infer/mod.rs @@ -79,31 +79,50 @@ pub type Bound = Option; pub type UnitResult<'tcx> = RelateResult<'tcx, ()>; // "unify result" pub type FixupResult<'tcx, T> = Result>; // "fixup result" -/// A flag that is used to suppress region errors. This is normally -/// false, but sometimes -- when we are doing region checks that the -/// NLL borrow checker will also do -- it might be set to true. -#[derive(Copy, Clone, Default, Debug)] -pub struct SuppressRegionErrors { - suppressed: bool, +/// How we should handle region solving. +/// +/// This is used so that the region values inferred by HIR region solving are +/// not exposed, and so that we can avoid doing work in HIR typeck that MIR +/// typeck will also do. +#[derive(Copy, Clone, Debug)] +pub enum RegionckMode { + /// The default mode: report region errors, don't erase regions. + Solve, + /// Erase the results of region after solving. + Erase { + /// A flag that is used to suppress region errors, when we are doing + /// region checks that the NLL borrow checker will also do -- it might + /// be set to true. + suppress_errors: bool, + }, +} + +impl Default for RegionckMode { + fn default() -> Self { + RegionckMode::Solve + } } -impl SuppressRegionErrors { +impl RegionckMode { pub fn suppressed(self) -> bool { - self.suppressed + match self { + Self::Solve => false, + Self::Erase { suppress_errors } => suppress_errors, + } } /// Indicates that the MIR borrowck will repeat these region /// checks, so we should ignore errors if NLL is (unconditionally) /// enabled. - pub fn when_nll_is_enabled(tcx: TyCtxt<'_>) -> Self { + pub fn for_item_body(tcx: TyCtxt<'_>) -> Self { // FIXME(Centril): Once we actually remove `::Migrate` also make // this always `true` and then proceed to eliminate the dead code. match tcx.borrowck_mode() { // If we're on Migrate mode, report AST region errors - BorrowckMode::Migrate => SuppressRegionErrors { suppressed: false }, + BorrowckMode::Migrate => RegionckMode::Erase { suppress_errors: false }, // If we're on MIR, don't report AST region errors as they should be reported by NLL - BorrowckMode::Mir => SuppressRegionErrors { suppressed: true }, + BorrowckMode::Mir => RegionckMode::Erase { suppress_errors: true }, } } } @@ -1207,20 +1226,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { region_context: DefId, region_map: ®ion::ScopeTree, outlives_env: &OutlivesEnvironment<'tcx>, - suppress: SuppressRegionErrors, + mode: RegionckMode, ) { assert!( self.is_tainted_by_errors() || self.inner.borrow().region_obligations.is_empty(), "region_obligations not empty: {:#?}", self.inner.borrow().region_obligations ); - - let region_rels = &RegionRelations::new( - self.tcx, - region_context, - region_map, - outlives_env.free_region_map(), - ); let (var_infos, data) = self .inner .borrow_mut() @@ -1228,8 +1240,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { .take() .expect("regions already resolved") .into_infos_and_data(); + + let region_rels = &RegionRelations::new( + self.tcx, + region_context, + region_map, + outlives_env.free_region_map(), + ); + let (lexical_region_resolutions, errors) = - lexical_region_resolve::resolve(region_rels, var_infos, data); + lexical_region_resolve::resolve(region_rels, var_infos, data, mode); let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions)); assert!(old_value.is_none()); @@ -1240,7 +1260,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // this infcx was in use. This is totally hokey but // otherwise we have a hard time separating legit region // errors from silly ones. - self.report_region_errors(region_map, &errors, suppress); + self.report_region_errors(region_map, &errors); } } diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 4fe7a06e5609e..1cb4a5cc4b3e2 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -306,6 +306,8 @@ fn configure_and_expand_inner<'a>( ecx.parse_sess.missing_fragment_specifiers.borrow().iter().cloned().collect(); missing_fragment_specifiers.sort(); + let recursion_limit_hit = ecx.reduced_recursion_limit.is_some(); + for span in missing_fragment_specifiers { let lint = lint::builtin::MISSING_FRAGMENT_SPECIFIER; let msg = "missing fragment specifier"; @@ -314,8 +316,15 @@ fn configure_and_expand_inner<'a>( if cfg!(windows) { env::set_var("PATH", &old_path); } - krate - }); + + if recursion_limit_hit { + // If we hit a recursion limit, exit early to avoid later passes getting overwhelmed + // with a large AST + Err(ErrorReported) + } else { + Ok(krate) + } + })?; sess.time("maybe_building_test_harness", || { rustc_builtin_macros::test_harness::inject( diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index 9521195a1b6c0..6d615419aaec5 100644 --- a/src/librustc_interface/util.rs +++ b/src/librustc_interface/util.rs @@ -83,14 +83,7 @@ pub fn create_session( (Lrc::new(sess), Lrc::new(codegen_backend), source_map) } -// Temporarily have stack size set to 32MB to deal with various crates with long method -// chains or deep syntax trees, except when on Haiku. -// FIXME(oli-obk): get https://github.com/rust-lang/rust/pull/55617 the finish line -#[cfg(not(target_os = "haiku"))] -const STACK_SIZE: usize = 32 * 1024 * 1024; - -#[cfg(target_os = "haiku")] -const STACK_SIZE: usize = 16 * 1024 * 1024; +const STACK_SIZE: usize = 8 * 1024 * 1024; fn get_stack_size() -> Option { // FIXME: Hacks on hacks. If the env is trying to override the stack size diff --git a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs index f751a16cfce7c..494b6421fd5d4 100644 --- a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs @@ -284,8 +284,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { debug!("report_region_error: category={:?} {:?}", category, span); // Check if we can use one of the "nice region errors". if let (Some(f), Some(o)) = (self.to_error_region(fr), self.to_error_region(outlived_fr)) { - let tables = self.infcx.tcx.typeck_tables_of(self.mir_def_id); - let nice = NiceRegionError::new_from_span(self.infcx, span, o, f, Some(tables)); + let nice = NiceRegionError::new_from_span(self.infcx, span, o, f); if let Some(diag) = nice.try_report_from_nll() { diag.buffer(&mut self.errors_buffer); return; diff --git a/src/librustc_mir/const_eval/machine.rs b/src/librustc_mir/const_eval/machine.rs index bb661d3d2a30a..28889486c383b 100644 --- a/src/librustc_mir/const_eval/machine.rs +++ b/src/librustc_mir/const_eval/machine.rs @@ -240,7 +240,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, Ok(Some(match ecx.load_mir(instance.def, None) { Ok(body) => *body, Err(err) => { - if let err_unsup!(NoMirFor(ref path)) = err.kind { + if let err_unsup!(NoMirFor(did)) = err.kind { + let path = ecx.tcx.def_path_str(did); return Err(ConstEvalErrKind::NeedsRfc(format!( "calling extern function `{}`", path diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 450e6b2e2d611..481719bfa8e63 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -138,7 +138,7 @@ pub enum LocalValue { impl<'tcx, Tag: Copy + 'static> LocalState<'tcx, Tag> { pub fn access(&self) -> InterpResult<'tcx, Operand> { match self.value { - LocalValue::Dead => throw_unsup!(DeadLocal), + LocalValue::Dead => throw_ub!(DeadLocal), LocalValue::Uninitialized => { bug!("The type checker should prevent reading from a never-written local") } @@ -152,7 +152,7 @@ impl<'tcx, Tag: Copy + 'static> LocalState<'tcx, Tag> { &mut self, ) -> InterpResult<'tcx, Result<&mut LocalValue, MemPlace>> { match self.value { - LocalValue::Dead => throw_unsup!(DeadLocal), + LocalValue::Dead => throw_ub!(DeadLocal), LocalValue::Live(Operand::Indirect(mplace)) => Ok(Err(mplace)), ref mut local @ LocalValue::Live(Operand::Immediate(_)) | ref mut local @ LocalValue::Uninitialized => Ok(Ok(local)), @@ -326,7 +326,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if self.tcx.is_mir_available(did) { Ok(self.tcx.optimized_mir(did).unwrap_read_only()) } else { - throw_unsup!(NoMirFor(self.tcx.def_path_str(def_id))) + throw_unsup!(NoMirFor(def_id)) } } _ => Ok(self.tcx.instance_mir(instance)), diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs index 9b13db2289e7e..90b8a4932991e 100644 --- a/src/librustc_mir/interpret/intern.rs +++ b/src/librustc_mir/interpret/intern.rs @@ -327,7 +327,7 @@ pub fn intern_const_alloc_recursive>( if let Err(error) = interned { // This can happen when e.g. the tag of an enum is not a valid discriminant. We do have // to read enum discriminants in order to find references in enum variant fields. - if let err_unsup!(ValidationFailure(_)) = error.kind { + if let err_ub!(ValidationFailure(_)) = error.kind { let err = crate::const_eval::error_to_const_error(&ecx, error); match err.struct_error( ecx.tcx, @@ -390,7 +390,7 @@ pub fn intern_const_alloc_recursive>( } } else if ecx.memory.dead_alloc_map.contains_key(&alloc_id) { // dangling pointer - throw_unsup!(ValidationFailure("encountered dangling pointer in final constant".into())) + throw_ub_format!("encountered dangling pointer in final constant") } else if ecx.tcx.alloc_map.lock().get(alloc_id).is_none() { // We have hit an `AllocId` that is neither in local or global memory and isn't marked // as dangling by local memory. diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index 37a60bcc8368d..03aedad0d988d 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -135,7 +135,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let bits = self.force_bits(val, layout_of.size)?; let kind = match layout_of.abi { ty::layout::Abi::Scalar(ref scalar) => scalar.value, - _ => throw_unsup!(TypeNotPrimitive(ty)), + _ => bug!("{} called on invalid type {:?}", intrinsic_name, ty), }; let (nonzero, intrinsic_name) = match intrinsic_name { sym::cttz_nonzero => (true, sym::cttz), @@ -246,9 +246,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let layout = self.layout_of(substs.type_at(0))?; let r_val = self.force_bits(r.to_scalar()?, layout.size)?; if let sym::unchecked_shl | sym::unchecked_shr = intrinsic_name { - throw_ub_format!("Overflowing shift by {} in `{}`", r_val, intrinsic_name); + throw_ub_format!("overflowing shift by {} in `{}`", r_val, intrinsic_name); } else { - throw_ub_format!("Overflow executing `{}`", intrinsic_name); + throw_ub_format!("overflow executing `{}`", intrinsic_name); } } self.write_scalar(val, dest)?; diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index 0e70e54ad85af..c9d32f6240037 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -286,8 +286,10 @@ pub trait Machine<'mir, 'tcx>: Sized { int: u64, ) -> InterpResult<'tcx, Pointer> { Err((if int == 0 { - err_unsup!(InvalidNullPointerUsage) + // This is UB, seriously. + err_ub!(InvalidIntPointerUsage(0)) } else { + // This is just something we cannot support during const-eval. err_unsup!(ReadBytesAsPointer) }) .into()) diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 82a467c7ba92c..5b2cd89a12284 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -215,7 +215,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { kind: MemoryKind, ) -> InterpResult<'tcx, Pointer> { if ptr.offset.bytes() != 0 { - throw_unsup!(ReallocateNonBasePtr) + throw_ub_format!( + "reallocating {:?} which does not point to the beginning of an object", + ptr + ); } // For simplicities' sake, we implement reallocate as "alloc, copy, dealloc". @@ -251,7 +254,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { trace!("deallocating: {}", ptr.alloc_id); if ptr.offset.bytes() != 0 { - throw_unsup!(DeallocateNonBasePtr) + throw_ub_format!( + "deallocating {:?} which does not point to the beginning of an object", + ptr + ); } let (alloc_kind, mut alloc) = match self.alloc_map.remove(&ptr.alloc_id) { @@ -259,29 +265,32 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { None => { // Deallocating static memory -- always an error return Err(match self.tcx.alloc_map.lock().get(ptr.alloc_id) { - Some(GlobalAlloc::Function(..)) => err_unsup!(DeallocatedWrongMemoryKind( - "function".to_string(), - format!("{:?}", kind), - )), - Some(GlobalAlloc::Static(..)) | Some(GlobalAlloc::Memory(..)) => err_unsup!( - DeallocatedWrongMemoryKind("static".to_string(), format!("{:?}", kind)) - ), - None => err_unsup!(DoubleFree), + Some(GlobalAlloc::Function(..)) => err_ub_format!("deallocating a function"), + Some(GlobalAlloc::Static(..)) | Some(GlobalAlloc::Memory(..)) => { + err_ub_format!("deallocating static memory") + } + None => err_ub!(PointerUseAfterFree(ptr.alloc_id)), } .into()); } }; if alloc_kind != kind { - throw_unsup!(DeallocatedWrongMemoryKind( - format!("{:?}", alloc_kind), - format!("{:?}", kind), - )) + throw_ub_format!( + "deallocating `{:?}` memory using `{:?}` deallocation operation", + alloc_kind, + kind + ); } if let Some((size, align)) = old_size_and_align { if size != alloc.size || align != alloc.align { - let bytes = alloc.size; - throw_unsup!(IncorrectAllocationInformation(size, bytes, align, alloc.align)) + throw_ub_format!( + "incorrect layout on deallocation: allocation has size {} and alignment {}, but gave size {} and alignment {}", + alloc.size.bytes(), + alloc.align.bytes(), + size.bytes(), + align.bytes(), + ) } } @@ -338,7 +347,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { } else { // The biggest power of two through which `offset` is divisible. let offset_pow2 = 1 << offset.trailing_zeros(); - throw_unsup!(AlignmentCheckFailed { + throw_ub!(AlignmentCheckFailed { has: Align::from_bytes(offset_pow2).unwrap(), required: align, }) @@ -360,7 +369,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { assert!(size.bytes() == 0); // Must be non-NULL. if bits == 0 { - throw_unsup!(InvalidNullPointerUsage) + throw_ub!(InvalidIntPointerUsage(0)) } // Must be aligned. if let Some(align) = align { @@ -375,7 +384,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // It is sufficient to check this for the end pointer. The addition // checks for overflow. let end_ptr = ptr.offset(size, self)?; - end_ptr.check_inbounds_alloc(allocation_size, msg)?; + if end_ptr.offset > allocation_size { + // equal is okay! + throw_ub!(PointerOutOfBounds { ptr: end_ptr.erase_tag(), msg, allocation_size }) + } // Test align. Check this last; if both bounds and alignment are violated // we want the error to be about the bounds. if let Some(align) = align { @@ -385,7 +397,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // got picked we might be aligned even if this check fails. // We instead have to fall back to converting to an integer and checking // the "real" alignment. - throw_unsup!(AlignmentCheckFailed { has: alloc_align, required: align }); + throw_ub!(AlignmentCheckFailed { has: alloc_align, required: align }); } check_offset_align(ptr.offset.bytes(), align)?; } @@ -402,7 +414,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { let (size, _align) = self .get_size_and_align(ptr.alloc_id, AllocCheck::MaybeDead) .expect("alloc info with MaybeDead cannot fail"); - ptr.check_inbounds_alloc(size, CheckInAllocMsg::NullPointerTest).is_err() + // If the pointer is out-of-bounds, it may be null. + // Note that one-past-the-end (offset == size) is still inbounds, and never null. + ptr.offset > size } } @@ -432,13 +446,13 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { let alloc = tcx.alloc_map.lock().get(id); let alloc = match alloc { Some(GlobalAlloc::Memory(mem)) => Cow::Borrowed(mem), - Some(GlobalAlloc::Function(..)) => throw_unsup!(DerefFunctionPointer), - None => throw_unsup!(DanglingPointerDeref), + Some(GlobalAlloc::Function(..)) => throw_ub!(DerefFunctionPointer(id)), + None => throw_ub!(PointerUseAfterFree(id)), Some(GlobalAlloc::Static(def_id)) => { // We got a "lazy" static that has not been computed yet. if tcx.is_foreign_item(def_id) { trace!("get_static_alloc: foreign item {:?}", def_id); - throw_unsup!(ReadForeignStatic) + throw_unsup!(ReadForeignStatic(def_id)) } trace!("get_static_alloc: Need to compute {:?}", def_id); let instance = Instance::mono(tcx.tcx, def_id); @@ -524,7 +538,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // to give us a cheap reference. let alloc = Self::get_static_alloc(memory_extra, tcx, id)?; if alloc.mutability == Mutability::Not { - throw_unsup!(ModifiedConstantMemory) + throw_ub!(WriteToReadOnly(id)) } match M::STATIC_KIND { Some(kind) => Ok((MemoryKind::Machine(kind), alloc.into_owned())), @@ -538,7 +552,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { Ok(a) => { let a = &mut a.1; if a.mutability == Mutability::Not { - throw_unsup!(ModifiedConstantMemory) + throw_ub!(WriteToReadOnly(id)) } Ok(a) } @@ -568,7 +582,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { if self.get_fn_alloc(id).is_some() { return if let AllocCheck::Dereferenceable = liveness { // The caller requested no function pointers. - throw_unsup!(DerefFunctionPointer) + throw_ub!(DerefFunctionPointer(id)) } else { Ok((Size::ZERO, Align::from_bytes(1).unwrap())) }; @@ -596,12 +610,12 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { if let AllocCheck::MaybeDead = liveness { // Deallocated pointers are allowed, we should be able to find // them in the map. - Ok(*self.dead_alloc_map.get(&id).expect( - "deallocated pointers should all be recorded in \ - `dead_alloc_map`", - )) + Ok(*self + .dead_alloc_map + .get(&id) + .expect("deallocated pointers should all be recorded in `dead_alloc_map`")) } else { - throw_unsup!(DanglingPointerDeref) + throw_ub!(PointerUseAfterFree(id)) } } } @@ -626,10 +640,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { ) -> InterpResult<'tcx, FnVal<'tcx, M::ExtraFnVal>> { let ptr = self.force_ptr(ptr)?; // We definitely need a pointer value. if ptr.offset.bytes() != 0 { - throw_unsup!(InvalidFunctionPointer) + throw_ub!(InvalidFunctionPointer(ptr.erase_tag())) } let id = M::canonical_alloc_id(self, ptr.alloc_id); - self.get_fn_alloc(id).ok_or_else(|| err_unsup!(ExecuteMemory).into()) + self.get_fn_alloc(id).ok_or_else(|| err_ub!(InvalidFunctionPointer(ptr.erase_tag())).into()) } pub fn mark_immutable(&mut self, id: AllocId) -> InterpResult<'tcx> { diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 75452b9395b50..316cf2ee41918 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -343,7 +343,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let len = mplace.len(self)?; let bytes = self.memory.read_bytes(mplace.ptr, Size::from_bytes(len as u64))?; let str = ::std::str::from_utf8(bytes) - .map_err(|err| err_unsup!(ValidationFailure(err.to_string())))?; + .map_err(|err| err_ub_format!("this string is not valid UTF-8: {}", err))?; Ok(str) } @@ -457,7 +457,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { layout: Option>, ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> { let base_op = match place.local { - mir::RETURN_PLACE => throw_unsup!(ReadFromReturnPointer), + mir::RETURN_PLACE => throw_ub!(ReadFromReturnPlace), local => { // Do not use the layout passed in as argument if the base we are looking at // here is not the entire place. diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index a4815b9696ebb..107cfee5aceb5 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -926,7 +926,7 @@ where // most likey we *are* running `typeck` right now. Investigate whether we can bail out // on `typeck_tables().has_errors` at all const eval entry points. debug!("Size mismatch when transmuting!\nsrc: {:#?}\ndest: {:#?}", src, dest); - throw_unsup!(TransmuteSizeDiff(src.layout.ty, dest.layout.ty)); + throw_inval!(TransmuteSizeDiff(src.layout.ty, dest.layout.ty)); } // Unsized copies rely on interpreting `src.meta` with `dest.layout`, we want // to avoid that here. diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs index 473ed9d13ecfb..22a081a9c8e0b 100644 --- a/src/librustc_mir/interpret/terminator.rs +++ b/src/librustc_mir/interpret/terminator.rs @@ -172,13 +172,19 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { trace!("Skipping callee ZST"); return Ok(()); } - let caller_arg = caller_arg.next().ok_or_else(|| err_unsup!(FunctionArgCountMismatch))?; + let caller_arg = caller_arg.next().ok_or_else(|| { + err_ub_format!("calling a function with fewer arguments than it requires") + })?; if rust_abi { assert!(!caller_arg.layout.is_zst(), "ZSTs must have been already filtered out"); } // Now, check if !Self::check_argument_compat(rust_abi, caller_arg.layout, callee_arg.layout) { - throw_unsup!(FunctionArgMismatch(caller_arg.layout.ty, callee_arg.layout.ty)) + throw_ub_format!( + "calling a function with argument of type {:?} passing data of type {:?}", + callee_arg.layout.ty, + caller_arg.layout.ty + ) } // We allow some transmutes here self.copy_op_transmute(caller_arg, callee_arg) @@ -223,7 +229,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { abi => abi, }; if normalize_abi(caller_abi) != normalize_abi(callee_abi) { - throw_unsup!(FunctionAbiMismatch(caller_abi, callee_abi)) + throw_ub_format!( + "calling a function with ABI {:?} using caller ABI {:?}", + callee_abi, + caller_abi + ) } } @@ -253,110 +263,108 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { StackPopCleanup::Goto { ret: ret.map(|p| p.1), unwind }, )?; - // We want to pop this frame again in case there was an error, to put - // the blame in the right location. Until the 2018 edition is used in - // the compiler, we have to do this with an immediately invoked function. - let res = - (|| { - trace!( - "caller ABI: {:?}, args: {:#?}", - caller_abi, - args.iter() - .map(|arg| (arg.layout.ty, format!("{:?}", **arg))) - .collect::>() - ); - trace!( - "spread_arg: {:?}, locals: {:#?}", - body.spread_arg, - body.args_iter() - .map(|local| ( - local, - self.layout_of_local(self.frame(), local, None).unwrap().ty - )) - .collect::>() - ); - - // Figure out how to pass which arguments. - // The Rust ABI is special: ZST get skipped. - let rust_abi = match caller_abi { - Abi::Rust | Abi::RustCall => true, - _ => false, + // If an error is raised here, pop the frame again to get an accurate backtrace. + // To this end, we wrap it all in a `try` block. + let res: InterpResult<'tcx> = try { + trace!( + "caller ABI: {:?}, args: {:#?}", + caller_abi, + args.iter() + .map(|arg| (arg.layout.ty, format!("{:?}", **arg))) + .collect::>() + ); + trace!( + "spread_arg: {:?}, locals: {:#?}", + body.spread_arg, + body.args_iter() + .map(|local| ( + local, + self.layout_of_local(self.frame(), local, None).unwrap().ty + )) + .collect::>() + ); + + // Figure out how to pass which arguments. + // The Rust ABI is special: ZST get skipped. + let rust_abi = match caller_abi { + Abi::Rust | Abi::RustCall => true, + _ => false, + }; + // We have two iterators: Where the arguments come from, + // and where they go to. + + // For where they come from: If the ABI is RustCall, we untuple the + // last incoming argument. These two iterators do not have the same type, + // so to keep the code paths uniform we accept an allocation + // (for RustCall ABI only). + let caller_args: Cow<'_, [OpTy<'tcx, M::PointerTag>]> = + if caller_abi == Abi::RustCall && !args.is_empty() { + // Untuple + let (&untuple_arg, args) = args.split_last().unwrap(); + trace!("eval_fn_call: Will pass last argument by untupling"); + Cow::from( + args.iter() + .map(|&a| Ok(a)) + .chain( + (0..untuple_arg.layout.fields.count()) + .map(|i| self.operand_field(untuple_arg, i as u64)), + ) + .collect::>>>( + )?, + ) + } else { + // Plain arg passing + Cow::from(args) }; - // We have two iterators: Where the arguments come from, - // and where they go to. - - // For where they come from: If the ABI is RustCall, we untuple the - // last incoming argument. These two iterators do not have the same type, - // so to keep the code paths uniform we accept an allocation - // (for RustCall ABI only). - let caller_args: Cow<'_, [OpTy<'tcx, M::PointerTag>]> = - if caller_abi == Abi::RustCall && !args.is_empty() { - // Untuple - let (&untuple_arg, args) = args.split_last().unwrap(); - trace!("eval_fn_call: Will pass last argument by untupling"); - Cow::from(args.iter().map(|&a| Ok(a)) - .chain((0..untuple_arg.layout.fields.count()) - .map(|i| self.operand_field(untuple_arg, i as u64)) - ) - .collect::>>>()?) - } else { - // Plain arg passing - Cow::from(args) - }; - // Skip ZSTs - let mut caller_iter = caller_args - .iter() - .filter(|op| !rust_abi || !op.layout.is_zst()) - .copied(); - - // Now we have to spread them out across the callee's locals, - // taking into account the `spread_arg`. If we could write - // this is a single iterator (that handles `spread_arg`), then - // `pass_argument` would be the loop body. It takes care to - // not advance `caller_iter` for ZSTs - for local in body.args_iter() { - let dest = self.eval_place(&mir::Place::from(local))?; - if Some(local) == body.spread_arg { - // Must be a tuple - for i in 0..dest.layout.fields.count() { - let dest = self.place_field(dest, i as u64)?; - self.pass_argument(rust_abi, &mut caller_iter, dest)?; - } - } else { - // Normal argument + // Skip ZSTs + let mut caller_iter = + caller_args.iter().filter(|op| !rust_abi || !op.layout.is_zst()).copied(); + + // Now we have to spread them out across the callee's locals, + // taking into account the `spread_arg`. If we could write + // this is a single iterator (that handles `spread_arg`), then + // `pass_argument` would be the loop body. It takes care to + // not advance `caller_iter` for ZSTs. + for local in body.args_iter() { + let dest = self.eval_place(&mir::Place::from(local))?; + if Some(local) == body.spread_arg { + // Must be a tuple + for i in 0..dest.layout.fields.count() { + let dest = self.place_field(dest, i as u64)?; self.pass_argument(rust_abi, &mut caller_iter, dest)?; } + } else { + // Normal argument + self.pass_argument(rust_abi, &mut caller_iter, dest)?; } - // Now we should have no more caller args - if caller_iter.next().is_some() { - trace!("Caller has passed too many args"); - throw_unsup!(FunctionArgCountMismatch) + } + // Now we should have no more caller args + if caller_iter.next().is_some() { + throw_ub_format!("calling a function with more arguments than it expected") + } + // Don't forget to check the return type! + if let Some((caller_ret, _)) = ret { + let callee_ret = self.eval_place(&mir::Place::return_place())?; + if !Self::check_argument_compat( + rust_abi, + caller_ret.layout, + callee_ret.layout, + ) { + throw_ub_format!( + "calling a function with return type {:?} passing \ + return place of type {:?}", + callee_ret.layout.ty, + caller_ret.layout.ty + ) } - // Don't forget to check the return type! - if let Some((caller_ret, _)) = ret { - let callee_ret = self.eval_place(&mir::Place::return_place())?; - if !Self::check_argument_compat( - rust_abi, - caller_ret.layout, - callee_ret.layout, - ) { - throw_unsup!(FunctionRetMismatch( - caller_ret.layout.ty, - callee_ret.layout.ty - )) - } - } else { - let local = mir::RETURN_PLACE; - let callee_layout = self.layout_of_local(self.frame(), local, None)?; - if !callee_layout.abi.is_uninhabited() { - throw_unsup!(FunctionRetMismatch( - self.tcx.types.never, - callee_layout.ty - )) - } + } else { + let local = mir::RETURN_PLACE; + let callee_layout = self.layout_of_local(self.frame(), local, None)?; + if !callee_layout.abi.is_uninhabited() { + throw_ub_format!("calling a returning function without a return place") } - Ok(()) - })(); + } + }; match res { Err(err) => { self.stack.pop(); diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 05bb010959b32..d93b78a5bd5b6 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -29,7 +29,7 @@ macro_rules! throw_validation_failure { write_path(&mut msg, where_); } write!(&mut msg, ", but expected {}", $details).unwrap(); - throw_unsup!(ValidationFailure(msg)) + throw_ub!(ValidationFailure(msg)) }}; ($what:expr, $where:expr) => {{ let mut msg = format!("encountered {}", $what); @@ -38,7 +38,7 @@ macro_rules! throw_validation_failure { msg.push_str(" at "); write_path(&mut msg, where_); } - throw_unsup!(ValidationFailure(msg)) + throw_ub!(ValidationFailure(msg)) }}; } @@ -353,31 +353,39 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M place.ptr, size, align ); match err.kind { - err_unsup!(InvalidNullPointerUsage) => { + err_ub!(InvalidIntPointerUsage(0)) => { throw_validation_failure!(format_args!("a NULL {}", kind), self.path) } - err_unsup!(AlignmentCheckFailed { required, has }) => { - throw_validation_failure!( - format_args!( - "an unaligned {} \ - (required {} byte alignment but found {})", - kind, - required.bytes(), - has.bytes() - ), - self.path - ) - } + err_ub!(InvalidIntPointerUsage(i)) => throw_validation_failure!( + format_args!("a {} to unallocated address {}", kind, i), + self.path + ), + err_ub!(AlignmentCheckFailed { required, has }) => throw_validation_failure!( + format_args!( + "an unaligned {} (required {} byte alignment but found {})", + kind, + required.bytes(), + has.bytes() + ), + self.path + ), err_unsup!(ReadBytesAsPointer) => throw_validation_failure!( format_args!("a dangling {} (created from integer)", kind), self.path ), - err_unsup!(PointerOutOfBounds { .. }) | err_unsup!(DanglingPointerDeref) => { - throw_validation_failure!( - format_args!("a dangling {} (not entirely in bounds)", kind), - self.path - ) - } + err_ub!(PointerOutOfBounds { .. }) => throw_validation_failure!( + format_args!( + "a dangling {} (going beyond the bounds of its allocation)", + kind + ), + self.path + ), + // This cannot happen during const-eval (because interning already detects + // dangling pointers), but it can happen in Miri. + err_ub!(PointerUseAfterFree(_)) => throw_validation_failure!( + format_args!("a dangling {} (use-after-free)", kind), + self.path + ), _ => bug!("Unexpected error during ptr inbounds test: {}", err), } } @@ -765,11 +773,11 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> Err(err) => { // For some errors we might be able to provide extra information match err.kind { - err_unsup!(ReadUndefBytes(offset)) => { + err_ub!(InvalidUndefBytes(Some(ptr))) => { // Some byte was undefined, determine which // element that byte belongs to so we can // provide an index. - let i = (offset.bytes() / layout.size.bytes()) as usize; + let i = (ptr.offset.bytes() / layout.size.bytes()) as usize; self.path.push(PathElem::ArrayElem(i)); throw_validation_failure!("undefined bytes", self.path) @@ -817,7 +825,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Run it. match visitor.visit_value(op) { Ok(()) => Ok(()), - Err(err) if matches!(err.kind, err_unsup!(ValidationFailure { .. })) => Err(err), + Err(err) if matches!(err.kind, err_ub!(ValidationFailure { .. })) => Err(err), Err(err) if cfg!(debug_assertions) => { bug!("Unexpected error during validation: {}", err) } diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index 284dd74ce99d4..7d3aba3ff034e 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -9,6 +9,9 @@ Rust MIR: a lowered representation of Rust. #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(box_syntax)] +#![feature(const_if_match)] +#![feature(const_fn)] +#![feature(const_panic)] #![feature(crate_visibility_modifier)] #![feature(drain_filter)] #![feature(exhaustive_patterns)] diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index f56bef031a748..119b11c724aca 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -368,7 +368,9 @@ fn collect_items_rec<'tcx>( recursion_depth_reset = Some(check_recursion_limit(tcx, instance, recursion_depths)); check_type_length_limit(tcx, instance); - collect_neighbours(tcx, instance, &mut neighbors); + rustc::middle::limits::ensure_sufficient_stack(|| { + collect_neighbours(tcx, instance, &mut neighbors); + }); } MonoItem::GlobalAsm(..) => { recursion_depth_reset = None; @@ -1134,7 +1136,9 @@ fn collect_miri<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut Vec { trace!("collecting {:?} with {:#?}", alloc_id, alloc); for &((), inner) in alloc.relocations().values() { - collect_miri(tcx, inner, output); + rustc::middle::limits::ensure_sufficient_stack(|| { + collect_miri(tcx, inner, output); + }); } } Some(GlobalAlloc::Function(fn_instance)) => { diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 7418a7519ba2b..a179cd3107502 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -107,15 +107,15 @@ impl<'tcx> MutVisitor<'tcx> for DerefArgVisitor<'tcx> { } fn visit_local(&mut self, local: &mut Local, _: PlaceContext, _: Location) { - assert_ne!(*local, self_arg()); + assert_ne!(*local, SELF_ARG); } fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) { - if place.local == self_arg() { + if place.local == SELF_ARG { replace_base( place, Place { - local: self_arg(), + local: SELF_ARG, projection: self.tcx().intern_place_elems(&[ProjectionElem::Deref]), }, self.tcx, @@ -125,7 +125,7 @@ impl<'tcx> MutVisitor<'tcx> for DerefArgVisitor<'tcx> { for elem in place.projection.iter() { if let PlaceElem::Index(local) = elem { - assert_ne!(*local, self_arg()); + assert_ne!(*local, SELF_ARG); } } } @@ -143,15 +143,15 @@ impl<'tcx> MutVisitor<'tcx> for PinArgVisitor<'tcx> { } fn visit_local(&mut self, local: &mut Local, _: PlaceContext, _: Location) { - assert_ne!(*local, self_arg()); + assert_ne!(*local, SELF_ARG); } fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) { - if place.local == self_arg() { + if place.local == SELF_ARG { replace_base( place, Place { - local: self_arg(), + local: SELF_ARG, projection: self.tcx().intern_place_elems(&[ProjectionElem::Field( Field::new(0), self.ref_gen_ty, @@ -164,7 +164,7 @@ impl<'tcx> MutVisitor<'tcx> for PinArgVisitor<'tcx> { for elem in place.projection.iter() { if let PlaceElem::Index(local) = elem { - assert_ne!(*local, self_arg()); + assert_ne!(*local, SELF_ARG); } } } @@ -180,9 +180,7 @@ fn replace_base<'tcx>(place: &mut Place<'tcx>, new_base: Place<'tcx>, tcx: TyCtx place.projection = tcx.intern_place_elems(&new_projection); } -fn self_arg() -> Local { - Local::new(1) -} +const SELF_ARG: Local = Local::from_u32(1); /// Generator has not been resumed yet. const UNRESUMED: usize = GeneratorSubsts::UNRESUMED; @@ -237,7 +235,7 @@ impl TransformVisitor<'tcx> { // Create a Place referencing a generator struct field fn make_field(&self, variant_index: VariantIdx, idx: usize, ty: Ty<'tcx>) -> Place<'tcx> { - let self_place = Place::from(self_arg()); + let self_place = Place::from(SELF_ARG); let base = self.tcx.mk_place_downcast_unnamed(self_place, variant_index); let mut projection = base.projection.to_vec(); projection.push(ProjectionElem::Field(Field::new(idx), ty)); @@ -247,7 +245,7 @@ impl TransformVisitor<'tcx> { // Create a statement which changes the discriminant fn set_discr(&self, state_disc: VariantIdx, source_info: SourceInfo) -> Statement<'tcx> { - let self_place = Place::from(self_arg()); + let self_place = Place::from(SELF_ARG); Statement { source_info, kind: StatementKind::SetDiscriminant { @@ -263,7 +261,7 @@ impl TransformVisitor<'tcx> { let local_decls_len = body.local_decls.push(temp_decl); let temp = Place::from(local_decls_len); - let self_place = Place::from(self_arg()); + let self_place = Place::from(SELF_ARG); let assign = Statement { source_info: source_info(body), kind: StatementKind::Assign(box (temp, Rvalue::Discriminant(self_place))), @@ -540,7 +538,7 @@ fn locals_live_across_suspend_points( live_locals_here.intersect(&liveness.outs[block]); // The generator argument is ignored. - live_locals_here.remove(self_arg()); + live_locals_here.remove(SELF_ARG); debug!("loc = {:?}, live_locals_here = {:?}", loc, live_locals_here); @@ -837,7 +835,6 @@ fn elaborate_generator_drops<'tcx>( // generator's resume function. let param_env = tcx.param_env(def_id); - let gen = self_arg(); let mut elaborator = DropShimElaborator { body, patch: MirPatch::new(body), tcx, param_env }; @@ -845,7 +842,7 @@ fn elaborate_generator_drops<'tcx>( let (target, unwind, source_info) = match block_data.terminator() { Terminator { source_info, kind: TerminatorKind::Drop { location, target, unwind } } => { if let Some(local) = location.as_local() { - if local == gen { + if local == SELF_ARG { (target, unwind, source_info) } else { continue; @@ -864,7 +861,7 @@ fn elaborate_generator_drops<'tcx>( elaborate_drop( &mut elaborator, *source_info, - &Place::from(gen), + &Place::from(SELF_ARG), (), *target, unwind, @@ -918,7 +915,7 @@ fn create_generator_drop_shim<'tcx>( make_generator_state_argument_indirect(tcx, def_id, &mut body); // Change the generator argument from &mut to *mut - body.local_decls[self_arg()] = LocalDecl { + body.local_decls[SELF_ARG] = LocalDecl { mutability: Mutability::Mut, ty: tcx.mk_ptr(ty::TypeAndMut { ty: gen_ty, mutbl: hir::Mutability::Mut }), user_ty: UserTypeProjections::none(), @@ -933,7 +930,7 @@ fn create_generator_drop_shim<'tcx>( 0, Statement { source_info, - kind: StatementKind::Retag(RetagKind::Raw, box Place::from(self_arg())), + kind: StatementKind::Retag(RetagKind::Raw, box Place::from(SELF_ARG)), }, ) } @@ -1042,7 +1039,7 @@ fn insert_clean_drop(body: &mut BodyAndCache<'_>) -> BasicBlock { // Create a block to destroy an unresumed generators. This can only destroy upvars. let drop_clean = BasicBlock::new(body.basic_blocks().len()); let term = TerminatorKind::Drop { - location: Place::from(self_arg()), + location: Place::from(SELF_ARG), target: return_block, unwind: None, }; diff --git a/src/librustc_mir_build/build/expr/as_temp.rs b/src/librustc_mir_build/build/expr/as_temp.rs index 34dd10cbc0fc8..95ce94a055d83 100644 --- a/src/librustc_mir_build/build/expr/as_temp.rs +++ b/src/librustc_mir_build/build/expr/as_temp.rs @@ -3,7 +3,7 @@ use crate::build::scope::DropKind; use crate::build::{BlockAnd, BlockAndExtension, Builder}; use crate::hair::*; -use rustc::middle::region; +use rustc::middle::{region, limits::ensure_sufficient_stack}; use rustc::mir::*; use rustc_hir as hir; use rustc_span::symbol::sym; @@ -22,7 +22,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { M: Mirror<'tcx, Output = Expr<'tcx>>, { let expr = self.hir.mirror(expr); - self.expr_as_temp(block, temp_lifetime, expr, mutability) + // + // this is the only place in mir building that we need to truly need to worry about + // infinite recursion. Everything else does recurse, too, but it always gets broken up + // at some point by inserting an intermediate temporary + ensure_sufficient_stack(|| self.expr_as_temp(block, temp_lifetime, expr, mutability)) } fn expr_as_temp( diff --git a/src/librustc_mir_build/lib.rs b/src/librustc_mir_build/lib.rs index 3c35827d15d3e..5a8b5a329634d 100644 --- a/src/librustc_mir_build/lib.rs +++ b/src/librustc_mir_build/lib.rs @@ -4,6 +4,9 @@ #![feature(box_patterns)] #![feature(box_syntax)] +#![feature(const_if_match)] +#![feature(const_fn)] +#![feature(const_panic)] #![feature(crate_visibility_modifier)] #![feature(bool_to_option)] #![recursion_limit = "256"] diff --git a/src/librustc_span/def_id.rs b/src/librustc_span/def_id.rs index a2944782e91d4..af8d5ce09b52d 100644 --- a/src/librustc_span/def_id.rs +++ b/src/librustc_span/def_id.rs @@ -25,7 +25,7 @@ pub enum CrateNum { /// Item definitions in the currently-compiled crate would have the `CrateNum` /// `LOCAL_CRATE` in their `DefId`. -pub const LOCAL_CRATE: CrateNum = CrateNum::Index(CrateId::from_u32_const(0)); +pub const LOCAL_CRATE: CrateNum = CrateNum::Index(CrateId::from_u32(0)); impl Idx for CrateNum { #[inline] diff --git a/src/librustc_span/lib.rs b/src/librustc_span/lib.rs index caa50e9a41c0c..1f6d10f4e8f6a 100644 --- a/src/librustc_span/lib.rs +++ b/src/librustc_span/lib.rs @@ -6,6 +6,9 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] #![feature(crate_visibility_modifier)] +#![feature(const_if_match)] +#![feature(const_fn)] +#![feature(const_panic)] #![feature(nll)] #![feature(optin_builtin_traits)] #![feature(specialization)] diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs index 19754c83038e2..5685505f6948d 100644 --- a/src/librustc_span/symbol.rs +++ b/src/librustc_span/symbol.rs @@ -1026,7 +1026,7 @@ rustc_index::newtype_index! { impl Symbol { const fn new(n: u32) -> Self { - Symbol(SymbolIndex::from_u32_const(n)) + Symbol(SymbolIndex::from_u32(n)) } /// Maps a string to its interned representation. diff --git a/src/librustc_target/lib.rs b/src/librustc_target/lib.rs index 3c397eb444d1d..98190867d493f 100644 --- a/src/librustc_target/lib.rs +++ b/src/librustc_target/lib.rs @@ -9,6 +9,9 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] #![feature(bool_to_option)] +#![feature(const_if_match)] +#![feature(const_fn)] +#![feature(const_panic)] #![feature(nll)] #![feature(never_type)] #![feature(associated_type_bounds)] diff --git a/src/librustc_trait_selection/traits/mod.rs b/src/librustc_trait_selection/traits/mod.rs index 7b93982db974b..43a90c4a6c164 100644 --- a/src/librustc_trait_selection/traits/mod.rs +++ b/src/librustc_trait_selection/traits/mod.rs @@ -21,7 +21,7 @@ mod util; pub mod wf; use crate::infer::outlives::env::OutlivesEnvironment; -use crate::infer::{InferCtxt, SuppressRegionErrors, TyCtxtInferExt}; +use crate::infer::{InferCtxt, RegionckMode, TyCtxtInferExt}; use crate::traits::error_reporting::InferCtxtExt as _; use crate::traits::query::evaluate_obligation::InferCtxtExt as _; use rustc::middle::region; @@ -244,7 +244,7 @@ fn do_normalize_predicates<'tcx>( region_context, ®ion_scope_tree, &outlives_env, - SuppressRegionErrors::default(), + RegionckMode::default(), ); let predicates = match infcx.fully_resolve(&predicates) { diff --git a/src/librustc_trait_selection/traits/project.rs b/src/librustc_trait_selection/traits/project.rs index 1ad915742127e..05656b9aebb0d 100644 --- a/src/librustc_trait_selection/traits/project.rs +++ b/src/librustc_trait_selection/traits/project.rs @@ -17,6 +17,7 @@ use super::{VtableClosureData, VtableFnPointerData, VtableGeneratorData, VtableI use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use crate::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime}; use crate::traits::error_reporting::InferCtxtExt; +use rustc::middle::limits::ensure_sufficient_stack; use rustc::ty::fold::{TypeFoldable, TypeFolder}; use rustc::ty::subst::{InternalSubsts, Subst}; use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness}; @@ -261,7 +262,7 @@ where { debug!("normalize_with_depth(depth={}, value={:?})", depth, value); let mut normalizer = AssocTypeNormalizer::new(selcx, param_env, cause, depth, obligations); - let result = normalizer.fold(value); + let result = ensure_sufficient_stack(|| normalizer.fold(value)); debug!( "normalize_with_depth: depth={} result={:?} with {} obligations", depth, diff --git a/src/librustc_trait_selection/traits/query/normalize.rs b/src/librustc_trait_selection/traits/query/normalize.rs index adec2ddb25322..68bc6dd12843c 100644 --- a/src/librustc_trait_selection/traits/query/normalize.rs +++ b/src/librustc_trait_selection/traits/query/normalize.rs @@ -7,6 +7,7 @@ use crate::infer::canonical::OriginalQueryValues; use crate::infer::{InferCtxt, InferOk}; use crate::traits::error_reporting::InferCtxtExt; use crate::traits::{Obligation, ObligationCause, PredicateObligation, Reveal}; +use rustc::middle::limits::ensure_sufficient_stack; use rustc::ty::fold::{TypeFoldable, TypeFolder}; use rustc::ty::subst::Subst; use rustc::ty::{self, Ty, TyCtxt}; @@ -120,7 +121,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { ty ); } - let folded_ty = self.fold_ty(concrete_ty); + let folded_ty = ensure_sufficient_stack(|| self.fold_ty(concrete_ty)); self.anon_depth -= 1; folded_ty } diff --git a/src/librustc_trait_selection/traits/select.rs b/src/librustc_trait_selection/traits/select.rs index ab3214d8d2d23..0202fc83fb3f1 100644 --- a/src/librustc_trait_selection/traits/select.rs +++ b/src/librustc_trait_selection/traits/select.rs @@ -36,7 +36,7 @@ use crate::infer::{CombinedSnapshot, InferCtxt, InferOk, PlaceholderMap, TypeFre use crate::traits::error_reporting::InferCtxtExt; use crate::traits::project::ProjectionCacheKeyExt; use rustc::dep_graph::{DepKind, DepNodeIndex}; -use rustc::middle::lang_items; +use rustc::middle::{lang_items, limits::ensure_sufficient_stack}; use rustc::ty::fast_reject; use rustc::ty::relate::TypeRelation; use rustc::ty::subst::{Subst, SubstsRef}; @@ -2379,13 +2379,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.infcx.commit_unconditionally(|_| { let (skol_ty, _) = self.infcx.replace_bound_vars_with_placeholders(&ty); let Normalized { value: normalized_ty, mut obligations } = - project::normalize_with_depth( - self, - param_env, - cause.clone(), - recursion_depth, - &skol_ty, - ); + ensure_sufficient_stack(|| { + project::normalize_with_depth( + self, + param_env, + cause.clone(), + recursion_depth, + &skol_ty, + ) + }); let skol_obligation = predicate_for_trait_def( self.tcx(), param_env, @@ -2539,13 +2541,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }; let cause = obligation.derived_cause(BuiltinDerivedObligation); - self.collect_predicates_for_types( - obligation.param_env, - cause, - obligation.recursion_depth + 1, - trait_def, - nested, - ) + ensure_sufficient_stack(|| { + self.collect_predicates_for_types( + obligation.param_env, + cause, + obligation.recursion_depth + 1, + trait_def, + nested, + ) + }) } else { vec![] }; @@ -2582,38 +2586,39 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { nested: ty::Binder>>, ) -> VtableAutoImplData> { debug!("vtable_auto_impl: nested={:?}", nested); + ensure_sufficient_stack(|| { + let cause = obligation.derived_cause(BuiltinDerivedObligation); + let mut obligations = self.collect_predicates_for_types( + obligation.param_env, + cause, + obligation.recursion_depth + 1, + trait_def_id, + nested, + ); - let cause = obligation.derived_cause(BuiltinDerivedObligation); - let mut obligations = self.collect_predicates_for_types( - obligation.param_env, - cause, - obligation.recursion_depth + 1, - trait_def_id, - nested, - ); - - let trait_obligations: Vec> = - self.infcx.commit_unconditionally(|_| { - let poly_trait_ref = obligation.predicate.to_poly_trait_ref(); - let (trait_ref, _) = - self.infcx.replace_bound_vars_with_placeholders(&poly_trait_ref); - let cause = obligation.derived_cause(ImplDerivedObligation); - self.impl_or_trait_obligations( - cause, - obligation.recursion_depth + 1, - obligation.param_env, - trait_def_id, - &trait_ref.substs, - ) - }); + let trait_obligations: Vec> = + self.infcx.commit_unconditionally(|_| { + let poly_trait_ref = obligation.predicate.to_poly_trait_ref(); + let (trait_ref, _) = + self.infcx.replace_bound_vars_with_placeholders(&poly_trait_ref); + let cause = obligation.derived_cause(ImplDerivedObligation); + self.impl_or_trait_obligations( + cause, + obligation.recursion_depth + 1, + obligation.param_env, + trait_def_id, + &trait_ref.substs, + ) + }); - // Adds the predicates from the trait. Note that this contains a `Self: Trait` - // predicate as usual. It won't have any effect since auto traits are coinductive. - obligations.extend(trait_obligations); + // Adds the predicates from the trait. Note that this contains a `Self: Trait` + // predicate as usual. It won't have any effect since auto traits are coinductive. + obligations.extend(trait_obligations); - debug!("vtable_auto_impl: obligations={:?}", obligations); + debug!("vtable_auto_impl: obligations={:?}", obligations); - VtableAutoImplData { trait_def_id, nested: obligations } + VtableAutoImplData { trait_def_id, nested: obligations } + }) } fn confirm_impl_candidate( @@ -2629,13 +2634,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let substs = self.rematch_impl(impl_def_id, obligation, snapshot); debug!("confirm_impl_candidate: substs={:?}", substs); let cause = obligation.derived_cause(ImplDerivedObligation); - self.vtable_impl( - impl_def_id, - substs, - cause, - obligation.recursion_depth + 1, - obligation.param_env, - ) + ensure_sufficient_stack(|| { + self.vtable_impl( + impl_def_id, + substs, + cause, + obligation.recursion_depth + 1, + obligation.param_env, + ) + }) }) } @@ -2748,13 +2755,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) .map_bound(|(trait_ref, _)| trait_ref); - let Normalized { value: trait_ref, obligations } = project::normalize_with_depth( - self, - obligation.param_env, - obligation.cause.clone(), - obligation.recursion_depth + 1, - &trait_ref, - ); + let Normalized { value: trait_ref, obligations } = ensure_sufficient_stack(|| { + project::normalize_with_depth( + self, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + &trait_ref, + ) + }); self.confirm_poly_trait_refs( obligation.cause.clone(), @@ -2812,13 +2821,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!("confirm_generator_candidate({:?},{:?},{:?})", obligation, generator_def_id, substs); let trait_ref = self.generator_trait_ref_unnormalized(obligation, generator_def_id, substs); - let Normalized { value: trait_ref, mut obligations } = normalize_with_depth( - self, - obligation.param_env, - obligation.cause.clone(), - obligation.recursion_depth + 1, - &trait_ref, - ); + let Normalized { value: trait_ref, mut obligations } = ensure_sufficient_stack(|| { + normalize_with_depth( + self, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + &trait_ref, + ) + }); debug!( "confirm_generator_candidate(generator_def_id={:?}, \ @@ -2857,13 +2868,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }; let trait_ref = self.closure_trait_ref_unnormalized(obligation, closure_def_id, substs); - let Normalized { value: trait_ref, mut obligations } = normalize_with_depth( - self, - obligation.param_env, - obligation.cause.clone(), - obligation.recursion_depth + 1, - &trait_ref, - ); + let Normalized { value: trait_ref, mut obligations } = ensure_sufficient_stack(|| { + normalize_with_depth( + self, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + &trait_ref, + ) + }); debug!( "confirm_closure_candidate(closure_def_id={:?}, trait_ref={:?}, obligations={:?})", @@ -3146,15 +3159,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { nested.extend(obligations); // Construct the nested `T: Unsize` predicate. - nested.push(predicate_for_trait_def( - tcx, - obligation.param_env, - obligation.cause.clone(), - obligation.predicate.def_id(), - obligation.recursion_depth + 1, - a_last.expect_ty(), - &[b_last], - )); + nested.push(ensure_sufficient_stack(|| { + predicate_for_trait_def( + tcx, + obligation.param_env, + obligation.cause.clone(), + obligation.predicate.def_id(), + obligation.recursion_depth + 1, + a_last.expect_ty(), + &[b_last], + ) + })); } _ => bug!(), @@ -3215,13 +3230,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let impl_trait_ref = impl_trait_ref.subst(self.tcx(), impl_substs); let Normalized { value: impl_trait_ref, obligations: mut nested_obligations } = - project::normalize_with_depth( - self, - obligation.param_env, - obligation.cause.clone(), - obligation.recursion_depth + 1, - &impl_trait_ref, - ); + ensure_sufficient_stack(|| { + project::normalize_with_depth( + self, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + &impl_trait_ref, + ) + }); debug!( "match_impl(impl_def_id={:?}, obligation={:?}, \ diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs index b13a7a3acb165..82380bb65e64d 100644 --- a/src/librustc_traits/dropck_outlives.rs +++ b/src/librustc_traits/dropck_outlives.rs @@ -191,27 +191,33 @@ fn dtorck_constraint_for_ty<'tcx>( ty::Array(ety, _) | ty::Slice(ety) => { // single-element containers, behave like their element - dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ety, constraints)?; + rustc::middle::limits::ensure_sufficient_stack(|| { + dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ety, constraints) + })?; } - ty::Tuple(tys) => { - for ty in tys.iter() { - dtorck_constraint_for_ty( - tcx, - span, - for_ty, - depth + 1, - ty.expect_ty(), - constraints, - )?; - } - } - - ty::Closure(def_id, substs) => { - for ty in substs.as_closure().upvar_tys(def_id, tcx) { - dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty, constraints)?; - } - } + ty::Tuple(tys) => rustc::middle::limits::ensure_sufficient_stack(|| { + tys.iter() + .map(|ty| { + dtorck_constraint_for_ty( + tcx, + span, + for_ty, + depth + 1, + ty.expect_ty(), + constraints, + ) + }) + .collect::>() + })?, + + ty::Closure(def_id, substs) => rustc::middle::limits::ensure_sufficient_stack(|| { + substs + .as_closure() + .upvar_tys(def_id, tcx) + .map(|ty| dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty, constraints)) + .collect::>() + })?, ty::Generator(def_id, substs, _movability) => { // rust-lang/rust#49918: types can be constructed, stored diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index dca4f9e7cbe08..e48ebbbb23514 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -9,7 +9,7 @@ use rustc::ty::subst::{Subst, SubstsRef}; use rustc::ty::{self, Predicate, Ty, TyCtxt}; use rustc_errors::struct_span_err; use rustc_infer::infer::outlives::env::OutlivesEnvironment; -use rustc_infer::infer::{InferOk, SuppressRegionErrors, TyCtxtInferExt}; +use rustc_infer::infer::{InferOk, RegionckMode, TyCtxtInferExt}; use rustc_infer::traits::TraitEngineExt as _; use rustc_span::Span; use rustc_trait_selection::traits::error_reporting::InferCtxtExt; @@ -139,7 +139,7 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>( drop_impl_did, ®ion_scope_tree, &outlives_env, - SuppressRegionErrors::default(), + RegionckMode::default(), ); Ok(()) }) diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 975c6e101a691..b6d6d3a7a873f 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -85,7 +85,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::PatKind; use rustc_infer::infer::outlives::env::OutlivesEnvironment; -use rustc_infer::infer::{self, RegionObligation, SuppressRegionErrors}; +use rustc_infer::infer::{self, RegionObligation, RegionckMode}; use rustc_span::Span; use rustc_trait_selection::infer::OutlivesEnvironmentExt; use rustc_trait_selection::opaque_types::InferCtxtExt; @@ -124,10 +124,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rcx.visit_body(body); rcx.visit_region_obligations(id); } - rcx.resolve_regions_and_report_errors(SuppressRegionErrors::when_nll_is_enabled(self.tcx)); - - assert!(self.tables.borrow().free_region_map.is_empty()); - self.tables.borrow_mut().free_region_map = rcx.outlives_environment.into_free_region_map(); + rcx.resolve_regions_and_report_errors(RegionckMode::for_item_body(self.tcx)); } /// Region checking during the WF phase for items. `wf_tys` are the @@ -145,7 +142,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rcx.outlives_environment.add_implied_bounds(self, wf_tys, item_id, span); rcx.outlives_environment.save_implied_bounds(item_id); rcx.visit_region_obligations(item_id); - rcx.resolve_regions_and_report_errors(SuppressRegionErrors::default()); + rcx.resolve_regions_and_report_errors(RegionckMode::default()); } /// Region check a function body. Not invoked on closures, but @@ -168,13 +165,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rcx.visit_fn_body(fn_id, body, self.tcx.hir().span(fn_id)); } - rcx.resolve_regions_and_report_errors(SuppressRegionErrors::when_nll_is_enabled(self.tcx)); - - // In this mode, we also copy the free-region-map into the - // tables of the enclosing fcx. In the other regionck modes - // (e.g., `regionck_item`), we don't have an enclosing tables. - assert!(self.tables.borrow().free_region_map.is_empty()); - self.tables.borrow_mut().free_region_map = rcx.outlives_environment.into_free_region_map(); + rcx.resolve_regions_and_report_errors(RegionckMode::for_item_body(self.tcx)); } } @@ -355,7 +346,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { self.select_all_obligations_or_error(); } - fn resolve_regions_and_report_errors(&self, suppress: SuppressRegionErrors) { + fn resolve_regions_and_report_errors(&self, mode: RegionckMode) { self.infcx.process_registered_region_obligations( self.outlives_environment.region_bound_pairs_map(), self.implicit_region_bound, @@ -366,7 +357,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { self.subject_def_id, &self.region_scope_tree, &self.outlives_environment, - suppress, + mode, ); } diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index b8f8030e3cdd7..8ed6cc3a94329 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -62,7 +62,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { wbcx.visit_fru_field_types(); wbcx.visit_opaque_types(body.value.span); wbcx.visit_coercion_casts(); - wbcx.visit_free_region_map(); wbcx.visit_user_provided_tys(); wbcx.visit_user_provided_sigs(); wbcx.visit_generator_interior_types(); @@ -125,7 +124,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { fn write_ty_to_tables(&mut self, hir_id: hir::HirId, ty: Ty<'tcx>) { debug!("write_ty_to_tables({:?}, {:?})", hir_id, ty); - assert!(!ty.needs_infer() && !ty.has_placeholders()); + assert!(!ty.needs_infer() && !ty.has_placeholders() && !ty.has_free_regions()); self.tables.node_types_mut().insert(hir_id, ty); } @@ -327,9 +326,10 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { let new_upvar_capture = match *upvar_capture { ty::UpvarCapture::ByValue => ty::UpvarCapture::ByValue, ty::UpvarCapture::ByRef(ref upvar_borrow) => { - let r = upvar_borrow.region; - let r = self.resolve(&r, &upvar_id.var_path.hir_id); - ty::UpvarCapture::ByRef(ty::UpvarBorrow { kind: upvar_borrow.kind, region: r }) + ty::UpvarCapture::ByRef(ty::UpvarBorrow { + kind: upvar_borrow.kind, + region: self.tcx().lifetimes.re_erased, + }) } }; debug!("Upvar capture for {:?} resolved to {:?}", upvar_id, new_upvar_capture); @@ -358,11 +358,6 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { } } - fn visit_free_region_map(&mut self) { - self.tables.free_region_map = self.fcx.tables.borrow().free_region_map.clone(); - debug_assert!(!self.tables.free_region_map.elements().any(|r| r.has_local_value())); - } - fn visit_user_provided_tys(&mut self) { let fcx_tables = self.fcx.tables.borrow(); debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root); @@ -427,8 +422,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { fn visit_opaque_types(&mut self, span: Span) { for (&def_id, opaque_defn) in self.fcx.opaque_types.borrow().iter() { let hir_id = self.tcx().hir().as_local_hir_id(def_id).unwrap(); - let instantiated_ty = - self.tcx().erase_regions(&self.resolve(&opaque_defn.concrete_ty, &hir_id)); + let instantiated_ty = self.resolve(&opaque_defn.concrete_ty, &hir_id); debug_assert!(!instantiated_ty.has_escaping_bound_vars()); @@ -617,10 +611,8 @@ impl Locatable for hir::HirId { } } -/////////////////////////////////////////////////////////////////////////// -// The Resolver. This is the type folding engine that detects -// unresolved types and so forth. - +/// The Resolver. This is the type folding engine that detects +/// unresolved types and so forth. struct Resolver<'cx, 'tcx> { tcx: TyCtxt<'tcx>, infcx: &'cx InferCtxt<'cx, 'tcx>, @@ -653,7 +645,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> { fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { match self.infcx.fully_resolve(&t) { - Ok(t) => t, + Ok(t) => self.infcx.tcx.erase_regions(&t), Err(_) => { debug!("Resolver::fold_ty: input type `{:?}` not fully resolvable", t); self.report_error(t); @@ -662,15 +654,14 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> { } } - // FIXME This should be carefully checked - // We could use `self.report_error` but it doesn't accept a ty::Region, right now. fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - self.infcx.fully_resolve(&r).unwrap_or(self.tcx.lifetimes.re_static) + debug_assert!(!r.is_late_bound(), "Should not be resolving bound region."); + self.tcx.lifetimes.re_erased } fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { match self.infcx.fully_resolve(&ct) { - Ok(ct) => ct, + Ok(ct) => self.infcx.tcx.erase_regions(&ct), Err(_) => { debug!("Resolver::fold_const: input const `{:?}` not fully resolvable", ct); // FIXME: we'd like to use `self.report_error`, but it doesn't yet diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index 2ea7601ae6538..e24d9bebf657f 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -12,7 +12,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::ItemKind; use rustc_infer::infer; use rustc_infer::infer::outlives::env::OutlivesEnvironment; -use rustc_infer::infer::{SuppressRegionErrors, TyCtxtInferExt}; +use rustc_infer::infer::{RegionckMode, TyCtxtInferExt}; use rustc_trait_selection::traits::error_reporting::InferCtxtExt; use rustc_trait_selection::traits::misc::{can_type_implement_copy, CopyImplementationError}; use rustc_trait_selection::traits::predicate_for_trait_def; @@ -307,7 +307,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: DefId) { impl_did, ®ion_scope_tree, &outlives_env, - SuppressRegionErrors::default(), + RegionckMode::default(), ); } } @@ -568,7 +568,7 @@ pub fn coerce_unsized_info(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedI impl_did, ®ion_scope_tree, &outlives_env, - SuppressRegionErrors::default(), + RegionckMode::default(), ); CoerceUnsizedInfo { custom_kind: kind } diff --git a/src/librustc_typeck/impl_wf_check/min_specialization.rs b/src/librustc_typeck/impl_wf_check/min_specialization.rs index e96a8c454b8c7..cae8837611846 100644 --- a/src/librustc_typeck/impl_wf_check/min_specialization.rs +++ b/src/librustc_typeck/impl_wf_check/min_specialization.rs @@ -75,7 +75,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_infer::infer::outlives::env::OutlivesEnvironment; -use rustc_infer::infer::{InferCtxt, SuppressRegionErrors, TyCtxtInferExt}; +use rustc_infer::infer::{InferCtxt, RegionckMode, TyCtxtInferExt}; use rustc_infer::traits::specialization_graph::Node; use rustc_span::Span; use rustc_trait_selection::traits::{self, translate_substs, wf}; @@ -162,7 +162,7 @@ fn get_impl_substs<'tcx>( impl1_def_id, &ScopeTree::default(), &outlives_env, - SuppressRegionErrors::default(), + RegionckMode::default(), ); let impl2_substs = match infcx.fully_resolve(&impl2_substs) { Ok(s) => s, diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index b3d70475bf3c3..d782a9d5a094d 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -3151,7 +3151,6 @@ fn render_attributes(w: &mut Buffer, it: &clean::Item, top: bool) { continue; } - // FIXME: this currently renders too many spaces as in: `#[repr(C, align (8))]`. attrs.push_str(&pprust::attribute_to_string(&attr)); } if !attrs.is_empty() { diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index 2702de15b858a..314424631fcbf 100644 --- a/src/libstd/keyword_docs.rs +++ b/src/libstd/keyword_docs.rs @@ -234,12 +234,55 @@ mod crate_keyword {} #[doc(keyword = "else")] // -/// What to do when an [`if`] condition does not hold. +/// What expression to evaluate when an [`if`] condition evaluates to [`false`]. /// -/// The documentation for this keyword is [not yet complete]. Pull requests welcome! +/// `else` expressions are optional. When no else expressions are supplied it is assumed to evaluate +/// to the unit type `()`. +/// +/// The type that the `else` blocks evaluate to must be compatible with the type that the `if` block +/// evaluates to. +/// +/// As can be seen below, `else` must be followed by either: `if`, `if let`, or a block `{}` and it +/// will return the value of that expression. /// +/// ```rust +/// let result = if true == false { +/// "oh no" +/// } else if "something" == "other thing" { +/// "oh dear" +/// } else if let Some(200) = "blarg".parse::().ok() { +/// "uh oh" +/// } else { +/// println!("Sneaky side effect."); +/// "phew, nothing's broken" +/// }; +/// ``` +/// +/// Here's another example but here we do not try and return an expression: +/// +/// ```rust +/// if true == false { +/// println!("oh no"); +/// } else if "something" == "other thing" { +/// println!("oh dear"); +/// } else if let Some(200) = "blarg".parse::().ok() { +/// println!("uh oh"); +/// } else { +/// println!("phew, nothing's broken"); +/// } +/// ``` +/// +/// The above is _still_ an expression but it will always evaluate to `()`. +/// +/// There is possibly no limit to the number of `else` blocks that could follow an `if` expression +/// however if you have several then a [`match`] expression might be preferable. +/// +/// Read more about control flow in the [Rust Book]. +/// +/// [Rust Book]: ../book/ch03-05-control-flow.html#handling-multiple-conditions-with-else-if +/// [`match`]: keyword.match.html +/// [`false`]: keyword.false.html /// [`if`]: keyword.if.html -/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601 mod else_keyword {} #[doc(keyword = "enum")] @@ -637,10 +680,18 @@ mod impl_keyword {} // /// Iterate over a series of values with [`for`]. /// -/// The documentation for this keyword is [not yet complete]. Pull requests welcome! +/// The expression immediately following `in` must implement the [`Iterator`] trait. /// +/// ## Literal Examples: +/// +/// * `for _ **in** 1..3 {}` - Iterate over an exclusive range up to but excluding 3. +/// * `for _ **in** 1..=3 {}` - Iterate over an inclusive range up to and includeing 3. +/// +/// (Read more about [range patterns]) +/// +/// [`Iterator`]: ../book/ch13-04-performance.html +/// [`range patterns`]: ../reference/patterns.html?highlight=range#range-patterns /// [`for`]: keyword.for.html -/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601 mod in_keyword {} #[doc(keyword = "let")] diff --git a/src/test/incremental/hashes/closure_expressions.rs b/src/test/incremental/hashes/closure_expressions.rs index 3d9db340f6375..8edece2c8d361 100644 --- a/src/test/incremental/hashes/closure_expressions.rs +++ b/src/test/incremental/hashes/closure_expressions.rs @@ -84,8 +84,8 @@ pub fn add_type_ascription_to_parameter() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, typeck_tables_of")] -#[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner_items, typeck_tables_of")] +#[rustc_clean(cfg = "cfail3")] pub fn add_type_ascription_to_parameter() { let closure = |x: u32| x + 1u32; let _: u32 = closure(1); diff --git a/src/test/incremental/hashes/inherent_impls.rs b/src/test/incremental/hashes/inherent_impls.rs index c0b80a92df6ee..139c265164bc5 100644 --- a/src/test/incremental/hashes/inherent_impls.rs +++ b/src/test/incremental/hashes/inherent_impls.rs @@ -360,7 +360,7 @@ impl Foo { impl Foo { #[rustc_clean( cfg="cfail2", - except="hir_owner,hir_owner_items,generics_of,predicates_of,type_of,typeck_tables_of" + except="hir_owner,hir_owner_items,generics_of,predicates_of,type_of" )] #[rustc_clean(cfg="cfail3")] pub fn add_lifetime_bound_to_lifetime_param_of_method<'a, 'b: 'a>(&self) { } diff --git a/src/test/incremental/hashes/unary_and_binary_exprs.rs b/src/test/incremental/hashes/unary_and_binary_exprs.rs index 9b63003482fe5..89aa0b1a58baa 100644 --- a/src/test/incremental/hashes/unary_and_binary_exprs.rs +++ b/src/test/incremental/hashes/unary_and_binary_exprs.rs @@ -81,7 +81,7 @@ pub fn var_deref(x: &i32, y: &i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built,typeck_tables_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn var_deref(x: &i32, y: &i32) -> i32 { *y diff --git a/src/test/mir-opt/const-promotion-extern-static.rs b/src/test/mir-opt/const-promotion-extern-static.rs index 0d4a6d1bafdd2..c858a4c5ee7c6 100644 --- a/src/test/mir-opt/const-promotion-extern-static.rs +++ b/src/test/mir-opt/const-promotion-extern-static.rs @@ -4,9 +4,9 @@ extern "C" { static Y: i32 = 42; -static mut BAR: *const &'static i32 = [&Y].as_ptr(); +static mut BAR: *const &i32 = [&Y].as_ptr(); -static mut FOO: *const &'static i32 = [unsafe { &X }].as_ptr(); +static mut FOO: *const &i32 = [unsafe { &X }].as_ptr(); fn main() {} @@ -18,8 +18,8 @@ fn main() {} // _4 = &(*_5); // _3 = [move _4]; // _2 = &_3; -// _1 = move _2 as &[&'static i32] (Pointer(Unsize)); -// _0 = const core::slice::::as_ptr(move _1) -> [return: bb2, unwind: bb1]; +// _1 = move _2 as &[&i32] (Pointer(Unsize)); +// _0 = const core::slice::::as_ptr(move _1) -> [return: bb2, unwind: bb1]; // } // ... // bb2: { @@ -35,8 +35,8 @@ fn main() {} // _4 = &(*_5); // _3 = [move _4]; // _2 = &_3; -// _1 = move _2 as &[&'static i32] (Pointer(Unsize)); -// _0 = const core::slice::::as_ptr(move _1) -> [return: bb2, unwind: bb1]; +// _1 = move _2 as &[&i32] (Pointer(Unsize)); +// _0 = const core::slice::::as_ptr(move _1) -> [return: bb2, unwind: bb1]; // } // ... // bb2: { @@ -50,8 +50,8 @@ fn main() {} // ... // _6 = const BAR::promoted[0]; // _2 = &(*_6); -// _1 = move _2 as &[&'static i32] (Pointer(Unsize)); -// _0 = const core::slice::::as_ptr(move _1) -> [return: bb2, unwind: bb1]; +// _1 = move _2 as &[&i32] (Pointer(Unsize)); +// _0 = const core::slice::::as_ptr(move _1) -> [return: bb2, unwind: bb1]; // } // ... // bb2: { @@ -63,8 +63,8 @@ fn main() {} // ... // _6 = const FOO::promoted[0]; // _2 = &(*_6); -// _1 = move _2 as &[&'static i32] (Pointer(Unsize)); -// _0 = const core::slice::::as_ptr(move _1) -> [return: bb2, unwind: bb1]; +// _1 = move _2 as &[&i32] (Pointer(Unsize)); +// _0 = const core::slice::::as_ptr(move _1) -> [return: bb2, unwind: bb1]; // } // ... // bb2: { diff --git a/src/test/mir-opt/no-drop-for-inactive-variant.rs b/src/test/mir-opt/no-drop-for-inactive-variant.rs index f906761684526..74a606af28fc1 100644 --- a/src/test/mir-opt/no-drop-for-inactive-variant.rs +++ b/src/test/mir-opt/no-drop-for-inactive-variant.rs @@ -27,7 +27,7 @@ fn main() { // } // bb2: { // ... -// const std::rt::begin_panic::<&'static str>(const "explicit panic") -> bb5; +// const std::rt::begin_panic::<&str>(const "explicit panic") -> bb5; // } // bb3: { // unreachable; diff --git a/src/test/mir-opt/remove_fake_borrows.rs b/src/test/mir-opt/remove_fake_borrows.rs index 294fe247c38be..ea106eaf59529 100644 --- a/src/test/mir-opt/remove_fake_borrows.rs +++ b/src/test/mir-opt/remove_fake_borrows.rs @@ -26,16 +26,16 @@ fn main() { // goto -> bb7; // } // bb2: { -// switchInt((*(*((_1 as Some).0: &' &' i32)))) -> [0i32: bb3, otherwise: bb1]; +// switchInt((*(*((_1 as Some).0: &&i32)))) -> [0i32: bb3, otherwise: bb1]; // } // bb3: { // goto -> bb4; // } // bb4: { // _4 = &shallow _1; -// _5 = &shallow ((_1 as Some).0: &' &' i32); -// _6 = &shallow (*((_1 as Some).0: &' &' i32)); -// _7 = &shallow (*(*((_1 as Some).0: &' &' i32))); +// _5 = &shallow ((_1 as Some).0: &&i32); +// _6 = &shallow (*((_1 as Some).0: &&i32)); +// _7 = &shallow (*(*((_1 as Some).0: &&i32))); // StorageLive(_8); // _8 = _2; // switchInt(move _8) -> [false: bb6, otherwise: bb5]; @@ -72,7 +72,7 @@ fn main() { // goto -> bb7; // } // bb2: { -// switchInt((*(*((_1 as Some).0: &' &' i32)))) -> [0i32: bb3, otherwise: bb1]; +// switchInt((*(*((_1 as Some).0: &&i32)))) -> [0i32: bb3, otherwise: bb1]; // } // bb3: { // goto -> bb4; diff --git a/src/test/mir-opt/storage_live_dead_in_statics.rs b/src/test/mir-opt/storage_live_dead_in_statics.rs index 5dc15286bab50..1c98766b9685c 100644 --- a/src/test/mir-opt/storage_live_dead_in_statics.rs +++ b/src/test/mir-opt/storage_live_dead_in_statics.rs @@ -35,12 +35,12 @@ fn main() { // END RUST SOURCE // START rustc.XXX.mir_map.0.mir -// let mut _0: &'static Foo; -// let _1: &'static Foo; +// let mut _0: &Foo; +// let _1: &Foo; // let _2: Foo; -// let mut _3: &'static [(u32, u32)]; -// let mut _4: &'static [(u32, u32); 42]; -// let _5: &'static [(u32, u32); 42]; +// let mut _3: &[(u32, u32)]; +// let mut _4: &[(u32, u32); 42]; +// let _5: &[(u32, u32); 42]; // let _6: [(u32, u32); 42]; // let mut _7: (u32, u32); // let mut _8: (u32, u32); @@ -178,7 +178,7 @@ fn main() { // _6 = [move _7, move _8, move _9, move _10, move _11, move _12, move _13, move _14, move _15, move _16, move _17, move _18, move _19, move _20, move _21, move _22, move _23, move _24, move _25, move _26, move _27, move _28, move _29, move _30, move _31, move _32, move _33, move _34, move _35, move _36, move _37, move _38, move _39, move _40, move _41, move _42, move _43, move _44, move _45, move _46, move _47, move _48]; // _5 = &_6; // _4 = &(*_5); -// _3 = move _4 as &'static [(u32, u32)] (Pointer(Unsize)); +// _3 = move _4 as &[(u32, u32)] (Pointer(Unsize)); // _2 = Foo { tup: const "hi", data: move _3 }; // _1 = &_2; // _0 = &(*_1); diff --git a/src/test/pretty/attr-literals.rs b/src/test/pretty/attr-literals.rs index 9db7e27b16103..44d2c5db3e668 100644 --- a/src/test/pretty/attr-literals.rs +++ b/src/test/pretty/attr-literals.rs @@ -5,7 +5,7 @@ #![feature(rustc_attrs)] fn main() { - #![rustc_dummy("hi", 1, 2, 1.012, pi = 3.14, bye, name ("John"))] + #![rustc_dummy("hi", 1, 2, 1.012, pi = 3.14, bye, name("John"))] #[rustc_dummy = 8] fn f() { } diff --git a/src/test/pretty/delimited-token-groups.rs b/src/test/pretty/delimited-token-groups.rs index 7bbb7dc911f93..66de0fc6cf7fa 100644 --- a/src/test/pretty/delimited-token-groups.rs +++ b/src/test/pretty/delimited-token-groups.rs @@ -7,7 +7,7 @@ macro_rules! mac { ($ ($ tt : tt) *) => () } mac! { struct S { field1 : u8, field2 : u16, } impl Clone for S { - fn clone () -> S + fn clone() -> S { panic ! () ; @@ -16,9 +16,8 @@ mac! { } mac! { - a - (aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa - aaaaaaaa aaaaaaaa) a + a(aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa + aaaaaaaa aaaaaaaa) a [aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa] a { diff --git a/src/test/pretty/issue-4264.pp b/src/test/pretty/issue-4264.pp index 8aa4cdeb5394e..ee7586bae820a 100644 --- a/src/test/pretty/issue-4264.pp +++ b/src/test/pretty/issue-4264.pp @@ -34,29 +34,29 @@ ((::alloc::fmt::format as for<'r> fn(std::fmt::Arguments<'r>) -> std::string::String {std::fmt::format})(((::core::fmt::Arguments::new_v1 as - fn(&[&str], &[std::fmt::ArgumentV1<'_>]) -> std::fmt::Arguments<'_> {std::fmt::Arguments::<'_>::new_v1})((&([("test" - as - &'static str)] - as - [&str; 1]) - as - &[&str; 1]), - (&(match (() - as - ()) - { - () - => - ([] - as - [std::fmt::ArgumentV1<'_>; 0]), - } - as - [std::fmt::ArgumentV1<'_>; 0]) - as - &[std::fmt::ArgumentV1<'_>; 0])) + fn(&[&str], &[std::fmt::ArgumentV1]) -> std::fmt::Arguments {std::fmt::Arguments::new_v1})((&([("test" + as + &str)] + as + [&str; 1]) + as + &[&str; 1]), + (&(match (() + as + ()) + { + () + => + ([] + as + [std::fmt::ArgumentV1; 0]), + } + as + [std::fmt::ArgumentV1; 0]) + as + &[std::fmt::ArgumentV1; 0])) as - std::fmt::Arguments<'_>)) + std::fmt::Arguments)) as std::string::String); (res as std::string::String) } as std::string::String); diff --git a/src/test/pretty/issue-68710-field-attr-proc-mac-lost.rs b/src/test/pretty/issue-68710-field-attr-proc-mac-lost.rs index 643ca761aac32..031a482595932 100644 --- a/src/test/pretty/issue-68710-field-attr-proc-mac-lost.rs +++ b/src/test/pretty/issue-68710-field-attr-proc-mac-lost.rs @@ -12,5 +12,5 @@ const C: C = #[cfg(debug_assertions)] field: 0, - #[cfg(not (debug_assertions))] + #[cfg(not(debug_assertions))] field: 1,}; diff --git a/src/test/rustdoc/attributes.rs b/src/test/rustdoc/attributes.rs index d5772e183bcb2..e9cd3514a07e2 100644 --- a/src/test/rustdoc/attributes.rs +++ b/src/test/rustdoc/attributes.rs @@ -16,6 +16,6 @@ pub enum Foo { Bar, } -// @has foo/struct.Repr.html '//*[@class="docblock attributes top-attr"]' '#[repr(C, align (8))]' +// @has foo/struct.Repr.html '//*[@class="docblock attributes top-attr"]' '#[repr(C, align(8))]' #[repr(C, align(8))] pub struct Repr; diff --git a/src/test/ui/async-await/async-fn-size-moved-locals.rs b/src/test/ui/async-await/async-fn-size-moved-locals.rs index 4a413381aa300..636fafc2bc44a 100644 --- a/src/test/ui/async-await/async-fn-size-moved-locals.rs +++ b/src/test/ui/async-await/async-fn-size-moved-locals.rs @@ -110,9 +110,9 @@ async fn mixed_sizes() { } fn main() { - assert_eq!(1028, std::mem::size_of_val(&single())); - assert_eq!(1032, std::mem::size_of_val(&single_with_noop())); - assert_eq!(3084, std::mem::size_of_val(&joined())); - assert_eq!(3084, std::mem::size_of_val(&joined_with_noop())); - assert_eq!(7188, std::mem::size_of_val(&mixed_sizes())); + assert_eq!(1025, std::mem::size_of_val(&single())); + assert_eq!(1026, std::mem::size_of_val(&single_with_noop())); + assert_eq!(3078, std::mem::size_of_val(&joined())); + assert_eq!(3079, std::mem::size_of_val(&joined_with_noop())); + assert_eq!(7181, std::mem::size_of_val(&mixed_sizes())); } diff --git a/src/test/ui/async-await/async-fn-size-uninit-locals.rs b/src/test/ui/async-await/async-fn-size-uninit-locals.rs index 0558084f4f8a3..d5d7b3fc3f0bd 100644 --- a/src/test/ui/async-await/async-fn-size-uninit-locals.rs +++ b/src/test/ui/async-await/async-fn-size-uninit-locals.rs @@ -95,9 +95,9 @@ async fn join_retval() -> Joiner { } fn main() { - assert_eq!(8, std::mem::size_of_val(&single())); - assert_eq!(12, std::mem::size_of_val(&single_with_noop())); - assert_eq!(3084, std::mem::size_of_val(&joined())); - assert_eq!(3084, std::mem::size_of_val(&joined_with_noop())); - assert_eq!(3080, std::mem::size_of_val(&join_retval())); + assert_eq!(2, std::mem::size_of_val(&single())); + assert_eq!(3, std::mem::size_of_val(&single_with_noop())); + assert_eq!(3078, std::mem::size_of_val(&joined())); + assert_eq!(3078, std::mem::size_of_val(&joined_with_noop())); + assert_eq!(3074, std::mem::size_of_val(&join_retval())); } diff --git a/src/test/ui/async-await/async-fn-size.rs b/src/test/ui/async-await/async-fn-size.rs index b313992db4ecb..0c1f3636446c9 100644 --- a/src/test/ui/async-await/async-fn-size.rs +++ b/src/test/ui/async-await/async-fn-size.rs @@ -86,13 +86,13 @@ async fn await3_level5() -> u8 { fn main() { assert_eq!(2, std::mem::size_of_val(&base())); - assert_eq!(8, std::mem::size_of_val(&await1_level1())); - assert_eq!(12, std::mem::size_of_val(&await2_level1())); - assert_eq!(12, std::mem::size_of_val(&await3_level1())); - assert_eq!(24, std::mem::size_of_val(&await3_level2())); - assert_eq!(36, std::mem::size_of_val(&await3_level3())); - assert_eq!(48, std::mem::size_of_val(&await3_level4())); - assert_eq!(60, std::mem::size_of_val(&await3_level5())); + assert_eq!(3, std::mem::size_of_val(&await1_level1())); + assert_eq!(4, std::mem::size_of_val(&await2_level1())); + assert_eq!(5, std::mem::size_of_val(&await3_level1())); + assert_eq!(8, std::mem::size_of_val(&await3_level2())); + assert_eq!(11, std::mem::size_of_val(&await3_level3())); + assert_eq!(14, std::mem::size_of_val(&await3_level4())); + assert_eq!(17, std::mem::size_of_val(&await3_level5())); assert_eq!(1, wait(base())); assert_eq!(1, wait(await1_level1())); diff --git a/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr index e0df787f80a44..305f259eac22d 100644 --- a/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr +++ b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr @@ -12,7 +12,7 @@ error: any use of this value will cause an error LL | const I32_REF_U8_UNION: u8 = unsafe { Nonsense { int_32_ref: &3 }.uint_8 }; | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | a raw memory access tried to access part of a pointer value as raw bytes + | unable to turn pointer into raw bytes | = note: `#[deny(const_err)]` on by default @@ -22,7 +22,7 @@ error: any use of this value will cause an error LL | const I32_REF_U16_UNION: u16 = unsafe { Nonsense { int_32_ref: &3 }.uint_16 }; | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | a raw memory access tried to access part of a pointer value as raw bytes + | unable to turn pointer into raw bytes error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:34:45 @@ -30,7 +30,7 @@ error: any use of this value will cause an error LL | const I32_REF_U32_UNION: u32 = unsafe { Nonsense { int_32_ref: &3 }.uint_32 }; | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | a raw memory access tried to access part of a pointer value as raw bytes + | unable to turn pointer into raw bytes error[E0080]: it is undefined behavior to use this value --> $DIR/const-pointer-values-in-various-types.rs:37:5 @@ -54,7 +54,7 @@ error: any use of this value will cause an error LL | const I32_REF_I8_UNION: i8 = unsafe { Nonsense { int_32_ref: &3 }.int_8 }; | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | a raw memory access tried to access part of a pointer value as raw bytes + | unable to turn pointer into raw bytes error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:46:45 @@ -62,7 +62,7 @@ error: any use of this value will cause an error LL | const I32_REF_I16_UNION: i16 = unsafe { Nonsense { int_32_ref: &3 }.int_16 }; | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | a raw memory access tried to access part of a pointer value as raw bytes + | unable to turn pointer into raw bytes error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:49:45 @@ -70,7 +70,7 @@ error: any use of this value will cause an error LL | const I32_REF_I32_UNION: i32 = unsafe { Nonsense { int_32_ref: &3 }.int_32 }; | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | a raw memory access tried to access part of a pointer value as raw bytes + | unable to turn pointer into raw bytes error[E0080]: it is undefined behavior to use this value --> $DIR/const-pointer-values-in-various-types.rs:52:5 @@ -94,7 +94,7 @@ error: any use of this value will cause an error LL | const I32_REF_F32_UNION: f32 = unsafe { Nonsense { int_32_ref: &3 }.float_32 }; | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | a raw memory access tried to access part of a pointer value as raw bytes + | unable to turn pointer into raw bytes error[E0080]: it is undefined behavior to use this value --> $DIR/const-pointer-values-in-various-types.rs:61:5 @@ -110,7 +110,7 @@ error: any use of this value will cause an error LL | const I32_REF_BOOL_UNION: bool = unsafe { Nonsense { int_32_ref: &3 }.truthy_falsey }; | ------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | a raw memory access tried to access part of a pointer value as raw bytes + | unable to turn pointer into raw bytes error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:67:47 @@ -118,7 +118,7 @@ error: any use of this value will cause an error LL | const I32_REF_CHAR_UNION: char = unsafe { Nonsense { int_32_ref: &3 }.character }; | ------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | a raw memory access tried to access part of a pointer value as raw bytes + | unable to turn pointer into raw bytes error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:70:39 @@ -126,7 +126,7 @@ error: any use of this value will cause an error LL | const STR_U8_UNION: u8 = unsafe { Nonsense { stringy: "3" }.uint_8 }; | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | a raw memory access tried to access part of a pointer value as raw bytes + | unable to turn pointer into raw bytes error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:73:41 @@ -134,7 +134,7 @@ error: any use of this value will cause an error LL | const STR_U16_UNION: u16 = unsafe { Nonsense { stringy: "3" }.uint_16 }; | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | a raw memory access tried to access part of a pointer value as raw bytes + | unable to turn pointer into raw bytes error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:76:41 @@ -142,7 +142,7 @@ error: any use of this value will cause an error LL | const STR_U32_UNION: u32 = unsafe { Nonsense { stringy: "3" }.uint_32 }; | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | a raw memory access tried to access part of a pointer value as raw bytes + | unable to turn pointer into raw bytes error[E0080]: it is undefined behavior to use this value --> $DIR/const-pointer-values-in-various-types.rs:79:5 @@ -158,7 +158,7 @@ error: any use of this value will cause an error LL | const STR_U128_UNION: u128 = unsafe { Nonsense { stringy: "3" }.uint_128 }; | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | a raw memory access tried to access part of a pointer value as raw bytes + | unable to turn pointer into raw bytes error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:85:39 @@ -166,7 +166,7 @@ error: any use of this value will cause an error LL | const STR_I8_UNION: i8 = unsafe { Nonsense { stringy: "3" }.int_8 }; | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | a raw memory access tried to access part of a pointer value as raw bytes + | unable to turn pointer into raw bytes error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:88:41 @@ -174,7 +174,7 @@ error: any use of this value will cause an error LL | const STR_I16_UNION: i16 = unsafe { Nonsense { stringy: "3" }.int_16 }; | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | a raw memory access tried to access part of a pointer value as raw bytes + | unable to turn pointer into raw bytes error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:91:41 @@ -182,7 +182,7 @@ error: any use of this value will cause an error LL | const STR_I32_UNION: i32 = unsafe { Nonsense { stringy: "3" }.int_32 }; | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | a raw memory access tried to access part of a pointer value as raw bytes + | unable to turn pointer into raw bytes error[E0080]: it is undefined behavior to use this value --> $DIR/const-pointer-values-in-various-types.rs:94:5 @@ -198,7 +198,7 @@ error: any use of this value will cause an error LL | const STR_I128_UNION: i128 = unsafe { Nonsense { stringy: "3" }.int_128 }; | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | a raw memory access tried to access part of a pointer value as raw bytes + | unable to turn pointer into raw bytes error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:100:41 @@ -206,7 +206,7 @@ error: any use of this value will cause an error LL | const STR_F32_UNION: f32 = unsafe { Nonsense { stringy: "3" }.float_32 }; | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | a raw memory access tried to access part of a pointer value as raw bytes + | unable to turn pointer into raw bytes error[E0080]: it is undefined behavior to use this value --> $DIR/const-pointer-values-in-various-types.rs:103:5 @@ -222,7 +222,7 @@ error: any use of this value will cause an error LL | const STR_BOOL_UNION: bool = unsafe { Nonsense { stringy: "3" }.truthy_falsey }; | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | a raw memory access tried to access part of a pointer value as raw bytes + | unable to turn pointer into raw bytes error: any use of this value will cause an error --> $DIR/const-pointer-values-in-various-types.rs:109:43 @@ -230,7 +230,7 @@ error: any use of this value will cause an error LL | const STR_CHAR_UNION: char = unsafe { Nonsense { stringy: "3" }.character }; | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | a raw memory access tried to access part of a pointer value as raw bytes + | unable to turn pointer into raw bytes error: aborting due to 29 previous errors diff --git a/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr b/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr index 2cba833a74896..cc40728e6b574 100644 --- a/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr +++ b/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr @@ -30,7 +30,7 @@ error: any use of this value will cause an error LL | const Z2: i32 = unsafe { *(42 as *const i32) }; | -------------------------^^^^^^^^^^^^^^^^^^^--- | | - | a memory access tried to interpret some bytes as a pointer + | unable to turn bytes into a pointer error: any use of this value will cause an error --> $DIR/const_raw_ptr_ops.rs:17:26 @@ -38,7 +38,7 @@ error: any use of this value will cause an error LL | const Z3: i32 = unsafe { *(44 as *const i32) }; | -------------------------^^^^^^^^^^^^^^^^^^^--- | | - | a memory access tried to interpret some bytes as a pointer + | unable to turn bytes into a pointer error: aborting due to 5 previous errors diff --git a/src/test/ui/consts/const-eval/issue-49296.stderr b/src/test/ui/consts/const-eval/issue-49296.stderr index 48809e0ae649c..798f130a4baf6 100644 --- a/src/test/ui/consts/const-eval/issue-49296.stderr +++ b/src/test/ui/consts/const-eval/issue-49296.stderr @@ -4,7 +4,7 @@ error: any use of this value will cause an error LL | const X: u64 = *wat(42); | ---------------^^^^^^^^- | | - | dangling pointer was dereferenced + | pointer to alloc2 was dereferenced after this allocation got freed | = note: `#[deny(const_err)]` on by default diff --git a/src/test/ui/consts/const-eval/ub-nonnull.stderr b/src/test/ui/consts/const-eval/ub-nonnull.stderr index edfc7ac837fc7..adad1b4f7fafe 100644 --- a/src/test/ui/consts/const-eval/ub-nonnull.stderr +++ b/src/test/ui/consts/const-eval/ub-nonnull.stderr @@ -13,7 +13,7 @@ LL | / const OUT_OF_BOUNDS_PTR: NonNull = { unsafe { LL | | let ptr: &[u8; 256] = mem::transmute(&0u8); // &0 gets promoted so it does not dangle LL | | // Use address-of-element for pointer arithmetic. This could wrap around to NULL! LL | | let out_of_bounds_ptr = &ptr[255]; - | | ^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of allocation 8 which has size 1 + | | ^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of alloc8 which has size 1 LL | | mem::transmute(out_of_bounds_ptr) LL | | } }; | |____- diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.rs b/src/test/ui/consts/const-eval/ub-wide-ptr.rs index 2d48309b72722..0200bfe9f08f8 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.rs +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.rs @@ -6,7 +6,7 @@ use std::mem; // normalize-stderr-test "offset \d+" -> "offset N" -// normalize-stderr-test "allocation \d+" -> "allocation N" +// normalize-stderr-test "alloc\d+" -> "allocN" // normalize-stderr-test "size \d+" -> "size N" #[repr(C)] diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr index a562c64b124f9..80e60dbb58a5d 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:32:1 | LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (not entirely in bounds) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (going beyond the bounds of its allocation) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -70,7 +70,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:62:1 | LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (not entirely in bounds) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (going beyond the bounds of its allocation) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -86,7 +86,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:68:1 | LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling box (not entirely in bounds) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling box (going beyond the bounds of its allocation) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -192,7 +192,7 @@ error[E0080]: could not evaluate static initializer --> $DIR/ub-wide-ptr.rs:125:5 | LL | mem::transmute::<_, &dyn Trait>((&92u8, &3u64)) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset N, but is outside bounds of allocation N which has size N + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset N, but is outside bounds of allocN which has size N error: aborting due to 24 previous errors diff --git a/src/test/ui/consts/const-int-unchecked.stderr b/src/test/ui/consts/const-int-unchecked.stderr index bf31e0b0732d8..cf70454b6bf9e 100644 --- a/src/test/ui/consts/const-int-unchecked.stderr +++ b/src/test/ui/consts/const-int-unchecked.stderr @@ -4,7 +4,7 @@ error: any use of this value will cause an error LL | const SHL_U8: u8 = unsafe { intrinsics::unchecked_shl(5_u8, 8) }; | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 8 in `unchecked_shl` + | overflowing shift by 8 in `unchecked_shl` | = note: `#[deny(const_err)]` on by default @@ -14,7 +14,7 @@ error: any use of this value will cause an error LL | const SHL_U16: u16 = unsafe { intrinsics::unchecked_shl(5_u16, 16) }; | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 16 in `unchecked_shl` + | overflowing shift by 16 in `unchecked_shl` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:19:31 @@ -22,7 +22,7 @@ error: any use of this value will cause an error LL | const SHL_U32: u32 = unsafe { intrinsics::unchecked_shl(5_u32, 32) }; | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 32 in `unchecked_shl` + | overflowing shift by 32 in `unchecked_shl` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:21:31 @@ -30,7 +30,7 @@ error: any use of this value will cause an error LL | const SHL_U64: u64 = unsafe { intrinsics::unchecked_shl(5_u64, 64) }; | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 64 in `unchecked_shl` + | overflowing shift by 64 in `unchecked_shl` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:23:33 @@ -38,7 +38,7 @@ error: any use of this value will cause an error LL | const SHL_U128: u128 = unsafe { intrinsics::unchecked_shl(5_u128, 128) }; | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 128 in `unchecked_shl` + | overflowing shift by 128 in `unchecked_shl` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:28:29 @@ -46,7 +46,7 @@ error: any use of this value will cause an error LL | const SHL_I8: i8 = unsafe { intrinsics::unchecked_shl(5_i8, 8) }; | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 8 in `unchecked_shl` + | overflowing shift by 8 in `unchecked_shl` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:30:31 @@ -54,7 +54,7 @@ error: any use of this value will cause an error LL | const SHL_I16: i16 = unsafe { intrinsics::unchecked_shl(5_16, 16) }; | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 16 in `unchecked_shl` + | overflowing shift by 16 in `unchecked_shl` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:32:31 @@ -62,7 +62,7 @@ error: any use of this value will cause an error LL | const SHL_I32: i32 = unsafe { intrinsics::unchecked_shl(5_i32, 32) }; | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 32 in `unchecked_shl` + | overflowing shift by 32 in `unchecked_shl` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:34:31 @@ -70,7 +70,7 @@ error: any use of this value will cause an error LL | const SHL_I64: i64 = unsafe { intrinsics::unchecked_shl(5_i64, 64) }; | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 64 in `unchecked_shl` + | overflowing shift by 64 in `unchecked_shl` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:36:33 @@ -78,7 +78,7 @@ error: any use of this value will cause an error LL | const SHL_I128: i128 = unsafe { intrinsics::unchecked_shl(5_i128, 128) }; | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 128 in `unchecked_shl` + | overflowing shift by 128 in `unchecked_shl` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:41:33 @@ -86,7 +86,7 @@ error: any use of this value will cause an error LL | const SHL_I8_NEG: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -1) }; | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 255 in `unchecked_shl` + | overflowing shift by 255 in `unchecked_shl` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:43:35 @@ -94,7 +94,7 @@ error: any use of this value will cause an error LL | const SHL_I16_NEG: i16 = unsafe { intrinsics::unchecked_shl(5_16, -1) }; | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 65535 in `unchecked_shl` + | overflowing shift by 65535 in `unchecked_shl` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:45:35 @@ -102,7 +102,7 @@ error: any use of this value will cause an error LL | const SHL_I32_NEG: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -1) }; | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 4294967295 in `unchecked_shl` + | overflowing shift by 4294967295 in `unchecked_shl` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:47:35 @@ -110,7 +110,7 @@ error: any use of this value will cause an error LL | const SHL_I64_NEG: i64 = unsafe { intrinsics::unchecked_shl(5_i64, -1) }; | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 18446744073709551615 in `unchecked_shl` + | overflowing shift by 18446744073709551615 in `unchecked_shl` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:49:37 @@ -118,7 +118,7 @@ error: any use of this value will cause an error LL | const SHL_I128_NEG: i128 = unsafe { intrinsics::unchecked_shl(5_i128, -1) }; | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 340282366920938463463374607431768211455 in `unchecked_shl` + | overflowing shift by 340282366920938463463374607431768211455 in `unchecked_shl` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:55:40 @@ -126,7 +126,7 @@ error: any use of this value will cause an error LL | const SHL_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -6) }; | ---------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 250 in `unchecked_shl` + | overflowing shift by 250 in `unchecked_shl` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:57:42 @@ -134,7 +134,7 @@ error: any use of this value will cause an error LL | const SHL_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shl(5_16, -13) }; | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 65523 in `unchecked_shl` + | overflowing shift by 65523 in `unchecked_shl` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:59:42 @@ -142,7 +142,7 @@ error: any use of this value will cause an error LL | const SHL_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -25) }; | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 4294967271 in `unchecked_shl` + | overflowing shift by 4294967271 in `unchecked_shl` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:61:42 @@ -150,7 +150,7 @@ error: any use of this value will cause an error LL | const SHL_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shl(5_i64, -30) }; | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 18446744073709551586 in `unchecked_shl` + | overflowing shift by 18446744073709551586 in `unchecked_shl` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:63:44 @@ -158,7 +158,7 @@ error: any use of this value will cause an error LL | const SHL_I128_NEG_RANDOM: i128 = unsafe { intrinsics::unchecked_shl(5_i128, -93) }; | -------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 340282366920938463463374607431768211363 in `unchecked_shl` + | overflowing shift by 340282366920938463463374607431768211363 in `unchecked_shl` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:70:29 @@ -166,7 +166,7 @@ error: any use of this value will cause an error LL | const SHR_U8: u8 = unsafe { intrinsics::unchecked_shr(5_u8, 8) }; | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 8 in `unchecked_shr` + | overflowing shift by 8 in `unchecked_shr` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:72:31 @@ -174,7 +174,7 @@ error: any use of this value will cause an error LL | const SHR_U16: u16 = unsafe { intrinsics::unchecked_shr(5_u16, 16) }; | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 16 in `unchecked_shr` + | overflowing shift by 16 in `unchecked_shr` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:74:31 @@ -182,7 +182,7 @@ error: any use of this value will cause an error LL | const SHR_U32: u32 = unsafe { intrinsics::unchecked_shr(5_u32, 32) }; | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 32 in `unchecked_shr` + | overflowing shift by 32 in `unchecked_shr` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:76:31 @@ -190,7 +190,7 @@ error: any use of this value will cause an error LL | const SHR_U64: u64 = unsafe { intrinsics::unchecked_shr(5_u64, 64) }; | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 64 in `unchecked_shr` + | overflowing shift by 64 in `unchecked_shr` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:78:33 @@ -198,7 +198,7 @@ error: any use of this value will cause an error LL | const SHR_U128: u128 = unsafe { intrinsics::unchecked_shr(5_u128, 128) }; | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 128 in `unchecked_shr` + | overflowing shift by 128 in `unchecked_shr` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:83:29 @@ -206,7 +206,7 @@ error: any use of this value will cause an error LL | const SHR_I8: i8 = unsafe { intrinsics::unchecked_shr(5_i8, 8) }; | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 8 in `unchecked_shr` + | overflowing shift by 8 in `unchecked_shr` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:85:31 @@ -214,7 +214,7 @@ error: any use of this value will cause an error LL | const SHR_I16: i16 = unsafe { intrinsics::unchecked_shr(5_16, 16) }; | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 16 in `unchecked_shr` + | overflowing shift by 16 in `unchecked_shr` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:87:31 @@ -222,7 +222,7 @@ error: any use of this value will cause an error LL | const SHR_I32: i32 = unsafe { intrinsics::unchecked_shr(5_i32, 32) }; | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 32 in `unchecked_shr` + | overflowing shift by 32 in `unchecked_shr` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:89:31 @@ -230,7 +230,7 @@ error: any use of this value will cause an error LL | const SHR_I64: i64 = unsafe { intrinsics::unchecked_shr(5_i64, 64) }; | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 64 in `unchecked_shr` + | overflowing shift by 64 in `unchecked_shr` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:91:33 @@ -238,7 +238,7 @@ error: any use of this value will cause an error LL | const SHR_I128: i128 = unsafe { intrinsics::unchecked_shr(5_i128, 128) }; | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 128 in `unchecked_shr` + | overflowing shift by 128 in `unchecked_shr` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:96:33 @@ -246,7 +246,7 @@ error: any use of this value will cause an error LL | const SHR_I8_NEG: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -1) }; | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 255 in `unchecked_shr` + | overflowing shift by 255 in `unchecked_shr` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:98:35 @@ -254,7 +254,7 @@ error: any use of this value will cause an error LL | const SHR_I16_NEG: i16 = unsafe { intrinsics::unchecked_shr(5_16, -1) }; | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 65535 in `unchecked_shr` + | overflowing shift by 65535 in `unchecked_shr` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:100:35 @@ -262,7 +262,7 @@ error: any use of this value will cause an error LL | const SHR_I32_NEG: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -1) }; | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 4294967295 in `unchecked_shr` + | overflowing shift by 4294967295 in `unchecked_shr` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:102:35 @@ -270,7 +270,7 @@ error: any use of this value will cause an error LL | const SHR_I64_NEG: i64 = unsafe { intrinsics::unchecked_shr(5_i64, -1) }; | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 18446744073709551615 in `unchecked_shr` + | overflowing shift by 18446744073709551615 in `unchecked_shr` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:104:37 @@ -278,7 +278,7 @@ error: any use of this value will cause an error LL | const SHR_I128_NEG: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -1) }; | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 340282366920938463463374607431768211455 in `unchecked_shr` + | overflowing shift by 340282366920938463463374607431768211455 in `unchecked_shr` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:110:40 @@ -286,7 +286,7 @@ error: any use of this value will cause an error LL | const SHR_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -6) }; | ---------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 250 in `unchecked_shr` + | overflowing shift by 250 in `unchecked_shr` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:112:42 @@ -294,7 +294,7 @@ error: any use of this value will cause an error LL | const SHR_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shr(5_16, -13) }; | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 65523 in `unchecked_shr` + | overflowing shift by 65523 in `unchecked_shr` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:114:42 @@ -302,7 +302,7 @@ error: any use of this value will cause an error LL | const SHR_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -25) }; | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 4294967271 in `unchecked_shr` + | overflowing shift by 4294967271 in `unchecked_shr` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:116:42 @@ -310,7 +310,7 @@ error: any use of this value will cause an error LL | const SHR_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shr(5_i64, -30) }; | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 18446744073709551586 in `unchecked_shr` + | overflowing shift by 18446744073709551586 in `unchecked_shr` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:118:44 @@ -318,7 +318,7 @@ error: any use of this value will cause an error LL | const SHR_I128_NEG_RANDOM: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -93) }; | -------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflowing shift by 340282366920938463463374607431768211363 in `unchecked_shr` + | overflowing shift by 340282366920938463463374607431768211363 in `unchecked_shr` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:123:25 @@ -326,7 +326,7 @@ error: any use of this value will cause an error LL | const _: u16 = unsafe { std::intrinsics::unchecked_add(40000u16, 30000) }; | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflow executing `unchecked_add` + | overflow executing `unchecked_add` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:126:25 @@ -334,7 +334,7 @@ error: any use of this value will cause an error LL | const _: u32 = unsafe { std::intrinsics::unchecked_sub(14u32, 22) }; | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflow executing `unchecked_sub` + | overflow executing `unchecked_sub` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:129:25 @@ -342,7 +342,7 @@ error: any use of this value will cause an error LL | const _: u16 = unsafe { std::intrinsics::unchecked_mul(300u16, 250u16) }; | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflow executing `unchecked_mul` + | overflow executing `unchecked_mul` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:132:25 @@ -358,7 +358,7 @@ error: any use of this value will cause an error LL | const _: i32 = unsafe { std::intrinsics::unchecked_div(i32::min_value(), -1) }; | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflow executing `unchecked_div` + | overflow executing `unchecked_div` error: any use of this value will cause an error --> $DIR/const-int-unchecked.rs:137:25 @@ -374,7 +374,7 @@ error: any use of this value will cause an error LL | const _: i32 = unsafe { std::intrinsics::unchecked_rem(i32::min_value(), -1) }; | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- | | - | Overflow executing `unchecked_rem` + | overflow executing `unchecked_rem` error: aborting due to 47 previous errors diff --git a/src/test/ui/consts/dangling-alloc-id-ice.stderr b/src/test/ui/consts/dangling-alloc-id-ice.stderr index bac9f555d271b..0e213555052c8 100644 --- a/src/test/ui/consts/dangling-alloc-id-ice.stderr +++ b/src/test/ui/consts/dangling-alloc-id-ice.stderr @@ -5,7 +5,7 @@ LL | / const FOO: &() = { LL | | let y = (); LL | | unsafe { Foo { y: &y }.long_live_the_unit } LL | | }; - | |__^ type validation failed: encountered dangling pointer in final constant + | |__^ encountered dangling pointer in final constant | = note: `#[deny(const_err)]` on by default diff --git a/src/test/ui/consts/dangling_raw_ptr.stderr b/src/test/ui/consts/dangling_raw_ptr.stderr index 4748be37dffcf..4d4c2876c4598 100644 --- a/src/test/ui/consts/dangling_raw_ptr.stderr +++ b/src/test/ui/consts/dangling_raw_ptr.stderr @@ -5,7 +5,7 @@ LL | / const FOO: *const u32 = { LL | | let x = 42; LL | | &x LL | | }; - | |__^ type validation failed: encountered dangling pointer in final constant + | |__^ encountered dangling pointer in final constant | = note: `#[deny(const_err)]` on by default diff --git a/src/test/ui/consts/miri_unleashed/abi-mismatch.stderr b/src/test/ui/consts/miri_unleashed/abi-mismatch.stderr index da00c49963eec..c7e902132e91a 100644 --- a/src/test/ui/consts/miri_unleashed/abi-mismatch.stderr +++ b/src/test/ui/consts/miri_unleashed/abi-mismatch.stderr @@ -16,7 +16,7 @@ error: any use of this value will cause an error LL | my_fn(); | ^^^^^^^ | | - | tried to call a function with ABI C using caller ABI Rust + | calling a function with ABI C using caller ABI Rust | inside call to `call_rust_fn` at $DIR/abi-mismatch.rs:13:17 ... LL | const VAL: () = call_rust_fn(unsafe { std::mem::transmute(c_fn as extern "C" fn()) }); diff --git a/src/test/ui/consts/miri_unleashed/mutable_const.stderr b/src/test/ui/consts/miri_unleashed/mutable_const.stderr index 86f27784701c6..8456e8ec6870d 100644 --- a/src/test/ui/consts/miri_unleashed/mutable_const.stderr +++ b/src/test/ui/consts/miri_unleashed/mutable_const.stderr @@ -11,7 +11,7 @@ LL | / const MUTATING_BEHIND_RAW: () = { LL | | // Test that `MUTABLE_BEHIND_RAW` is actually immutable, by doing this at const time. LL | | unsafe { LL | | *MUTABLE_BEHIND_RAW = 99 - | | ^^^^^^^^^^^^^^^^^^^^^^^^ tried to modify constant memory + | | ^^^^^^^^^^^^^^^^^^^^^^^^ writing to alloc1 which is read-only LL | | } LL | | }; | |__- diff --git a/src/test/ui/consts/offset_from_ub.stderr b/src/test/ui/consts/offset_from_ub.stderr index bbe3344b412b3..217530740079f 100644 --- a/src/test/ui/consts/offset_from_ub.stderr +++ b/src/test/ui/consts/offset_from_ub.stderr @@ -26,7 +26,7 @@ error: any use of this value will cause an error LL | intrinsics::ptr_offset_from(self, origin) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | - | a memory access tried to interpret some bytes as a pointer + | unable to turn bytes into a pointer | inside call to `std::ptr::const_ptr::::offset_from` at $DIR/offset_from_ub.rs:28:14 | ::: $DIR/offset_from_ub.rs:26:1 @@ -81,7 +81,7 @@ error: any use of this value will cause an error LL | intrinsics::ptr_offset_from(self, origin) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | - | a memory access tried to interpret some bytes as a pointer + | unable to turn bytes into a pointer | inside call to `std::ptr::const_ptr::::offset_from` at $DIR/offset_from_ub.rs:49:14 | ::: $DIR/offset_from_ub.rs:45:1 diff --git a/src/test/ui/consts/transmute-size-mismatch-before-typeck.stderr b/src/test/ui/consts/transmute-size-mismatch-before-typeck.stderr index 296a55ef16076..5a47771459625 100644 --- a/src/test/ui/consts/transmute-size-mismatch-before-typeck.stderr +++ b/src/test/ui/consts/transmute-size-mismatch-before-typeck.stderr @@ -21,7 +21,7 @@ LL | const ZST: &[u8] = unsafe { std::mem::transmute(1usize) }; | ^^^^^^^^^^^^^^^^^^^ | = note: source type: `usize` (word size) - = note: target type: `&'static [u8]` (2 * word size) + = note: target type: `&[u8]` (2 * word size) error: could not evaluate constant pattern --> $DIR/transmute-size-mismatch-before-typeck.rs:10:9 diff --git a/src/test/ui/editions/edition-keywords-2018-2015-parsing.rs b/src/test/ui/editions/edition-keywords-2018-2015-parsing.rs index dbc0465b08e77..d5ed9fb9a285e 100644 --- a/src/test/ui/editions/edition-keywords-2018-2015-parsing.rs +++ b/src/test/ui/editions/edition-keywords-2018-2015-parsing.rs @@ -1,9 +1,17 @@ // edition:2018 // aux-build:edition-kw-macro-2015.rs +#![feature(async_closure)] + +fn main() {} + #[macro_use] extern crate edition_kw_macro_2015; +mod module { + pub fn r#async() {} +} + pub fn check_async() { let mut async = 1; //~ ERROR expected identifier, found keyword `async` let mut r#async = 1; // OK @@ -17,4 +25,6 @@ pub fn check_async() { if passes_ident!(r#async) == 1 {} // OK module::async(); //~ ERROR expected identifier, found keyword `async` module::r#async(); // OK + + let _recovery_witness: () = 0; //~ ERROR mismatched types } diff --git a/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr b/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr index e12d1a48463d7..28663563c6ccd 100644 --- a/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr +++ b/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr @@ -1,5 +1,5 @@ error: expected identifier, found keyword `async` - --> $DIR/edition-keywords-2018-2015-parsing.rs:8:13 + --> $DIR/edition-keywords-2018-2015-parsing.rs:16:13 | LL | let mut async = 1; | ^^^^^ expected identifier, found keyword @@ -10,7 +10,7 @@ LL | let mut r#async = 1; | ^^^^^^^ error: expected identifier, found keyword `async` - --> $DIR/edition-keywords-2018-2015-parsing.rs:18:13 + --> $DIR/edition-keywords-2018-2015-parsing.rs:26:13 | LL | module::async(); | ^^^^^ expected identifier, found keyword @@ -21,13 +21,13 @@ LL | module::r#async(); | ^^^^^^^ error: no rules expected the token `r#async` - --> $DIR/edition-keywords-2018-2015-parsing.rs:12:31 + --> $DIR/edition-keywords-2018-2015-parsing.rs:20:31 | LL | r#async = consumes_async!(r#async); | ^^^^^^^ no rules expected this token in macro call error: no rules expected the token `async` - --> $DIR/edition-keywords-2018-2015-parsing.rs:13:35 + --> $DIR/edition-keywords-2018-2015-parsing.rs:21:35 | LL | r#async = consumes_async_raw!(async); | ^^^^^ no rules expected this token in macro call @@ -38,10 +38,19 @@ error: macro expansion ends with an incomplete expression: expected one of `move LL | ($i: ident) => ($i) | ^ expected one of `move`, `|`, or `||` | - ::: $DIR/edition-keywords-2018-2015-parsing.rs:16:8 + ::: $DIR/edition-keywords-2018-2015-parsing.rs:24:8 | LL | if passes_ident!(async) == 1 {} | -------------------- in this macro invocation -error: aborting due to 5 previous errors +error[E0308]: mismatched types + --> $DIR/edition-keywords-2018-2015-parsing.rs:29:33 + | +LL | let _recovery_witness: () = 0; + | -- ^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to 6 previous errors +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/editions/edition-keywords-2018-2018-parsing.rs b/src/test/ui/editions/edition-keywords-2018-2018-parsing.rs index 5aca0839f0f15..044ab249f2c26 100644 --- a/src/test/ui/editions/edition-keywords-2018-2018-parsing.rs +++ b/src/test/ui/editions/edition-keywords-2018-2018-parsing.rs @@ -1,9 +1,17 @@ // edition:2018 // aux-build:edition-kw-macro-2018.rs +#![feature(async_closure)] + +fn main() {} + #[macro_use] extern crate edition_kw_macro_2018; +mod module { + pub fn r#async() {} +} + pub fn check_async() { let mut async = 1; //~ ERROR expected identifier, found keyword `async` let mut r#async = 1; // OK @@ -17,4 +25,6 @@ pub fn check_async() { if passes_ident!(r#async) == 1 {} // OK module::async(); //~ ERROR expected identifier, found keyword `async` module::r#async(); // OK + + let _recovery_witness: () = 0; //~ ERROR mismatched types } diff --git a/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr b/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr index 110165fc077ca..cda7e65e437e8 100644 --- a/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr +++ b/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr @@ -1,5 +1,5 @@ error: expected identifier, found keyword `async` - --> $DIR/edition-keywords-2018-2018-parsing.rs:8:13 + --> $DIR/edition-keywords-2018-2018-parsing.rs:16:13 | LL | let mut async = 1; | ^^^^^ expected identifier, found keyword @@ -10,7 +10,7 @@ LL | let mut r#async = 1; | ^^^^^^^ error: expected identifier, found keyword `async` - --> $DIR/edition-keywords-2018-2018-parsing.rs:18:13 + --> $DIR/edition-keywords-2018-2018-parsing.rs:26:13 | LL | module::async(); | ^^^^^ expected identifier, found keyword @@ -21,13 +21,13 @@ LL | module::r#async(); | ^^^^^^^ error: no rules expected the token `r#async` - --> $DIR/edition-keywords-2018-2018-parsing.rs:12:31 + --> $DIR/edition-keywords-2018-2018-parsing.rs:20:31 | LL | r#async = consumes_async!(r#async); | ^^^^^^^ no rules expected this token in macro call error: no rules expected the token `async` - --> $DIR/edition-keywords-2018-2018-parsing.rs:13:35 + --> $DIR/edition-keywords-2018-2018-parsing.rs:21:35 | LL | r#async = consumes_async_raw!(async); | ^^^^^ no rules expected this token in macro call @@ -38,10 +38,19 @@ error: macro expansion ends with an incomplete expression: expected one of `move LL | ($i: ident) => ($i) | ^ expected one of `move`, `|`, or `||` | - ::: $DIR/edition-keywords-2018-2018-parsing.rs:16:8 + ::: $DIR/edition-keywords-2018-2018-parsing.rs:24:8 | LL | if passes_ident!(async) == 1 {} | -------------------- in this macro invocation -error: aborting due to 5 previous errors +error[E0308]: mismatched types + --> $DIR/edition-keywords-2018-2018-parsing.rs:29:33 + | +LL | let _recovery_witness: () = 0; + | -- ^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to 6 previous errors +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/error-codes/E0121.stderr b/src/test/ui/error-codes/E0121.stderr index 5a5c6b40c5afe..ad854837ae5bd 100644 --- a/src/test/ui/error-codes/E0121.stderr +++ b/src/test/ui/error-codes/E0121.stderr @@ -14,7 +14,7 @@ LL | static BAR: _ = "test"; | ^ | | | not allowed in type signatures - | help: replace `_` with the correct type: `&'static str` + | help: replace `_` with the correct type: `&str` error: aborting due to 2 previous errors diff --git a/src/test/ui/error-codes/E0396-fixed.stderr b/src/test/ui/error-codes/E0396-fixed.stderr index 7222f87da248f..685055525627e 100644 --- a/src/test/ui/error-codes/E0396-fixed.stderr +++ b/src/test/ui/error-codes/E0396-fixed.stderr @@ -4,7 +4,7 @@ error: any use of this value will cause an error LL | const VALUE: u8 = unsafe { *REG_ADDR }; | ---------------------------^^^^^^^^^--- | | - | a memory access tried to interpret some bytes as a pointer + | unable to turn bytes into a pointer | = note: `#[deny(const_err)]` on by default diff --git a/src/test/ui/generator/discriminant.rs b/src/test/ui/generator/discriminant.rs new file mode 100644 index 0000000000000..8a0f8a380ab59 --- /dev/null +++ b/src/test/ui/generator/discriminant.rs @@ -0,0 +1,134 @@ +//! Tests that generator discriminant sizes and ranges are chosen optimally and that they are +//! reflected in the output of `mem::discriminant`. + +// run-pass + +#![feature(generators, generator_trait, core_intrinsics)] + +use std::intrinsics::discriminant_value; +use std::marker::Unpin; +use std::mem::size_of_val; +use std::{cmp, ops::*}; + +macro_rules! yield25 { + ($e:expr) => { + yield $e; + yield $e; + yield $e; + yield $e; + yield $e; + + yield $e; + yield $e; + yield $e; + yield $e; + yield $e; + + yield $e; + yield $e; + yield $e; + yield $e; + yield $e; + + yield $e; + yield $e; + yield $e; + yield $e; + yield $e; + + yield $e; + yield $e; + yield $e; + yield $e; + yield $e; + }; +} + +/// Yields 250 times. +macro_rules! yield250 { + () => { + yield250!(()) + }; + + ($e:expr) => { + yield25!($e); + yield25!($e); + yield25!($e); + yield25!($e); + yield25!($e); + + yield25!($e); + yield25!($e); + yield25!($e); + yield25!($e); + yield25!($e); + }; +} + +fn cycle(gen: impl Generator<()> + Unpin, expected_max_discr: u64) { + let mut gen = Box::pin(gen); + let mut max_discr = 0; + loop { + max_discr = cmp::max(max_discr, discriminant_value(gen.as_mut().get_mut())); + match gen.as_mut().resume(()) { + GeneratorState::Yielded(_) => {} + GeneratorState::Complete(_) => { + assert_eq!(max_discr, expected_max_discr); + return; + } + } + } +} + +fn main() { + // Has only one invalid discr. value. + let gen_u8_tiny_niche = || { + || { + // 3 reserved variants + + yield250!(); // 253 variants + + yield; // 254 + yield; // 255 + } + }; + + // Uses all values in the u8 discriminant. + let gen_u8_full = || { + || { + // 3 reserved variants + + yield250!(); // 253 variants + + yield; // 254 + yield; // 255 + yield; // 256 + } + }; + + // Barely needs a u16 discriminant. + let gen_u16 = || { + || { + // 3 reserved variants + + yield250!(); // 253 variants + + yield; // 254 + yield; // 255 + yield; // 256 + yield; // 257 + } + }; + + assert_eq!(size_of_val(&gen_u8_tiny_niche()), 1); + assert_eq!(size_of_val(&Some(gen_u8_tiny_niche())), 1); // uses niche + assert_eq!(size_of_val(&Some(Some(gen_u8_tiny_niche()))), 2); // cannot use niche anymore + assert_eq!(size_of_val(&gen_u8_full()), 1); + assert_eq!(size_of_val(&Some(gen_u8_full())), 2); // cannot use niche + assert_eq!(size_of_val(&gen_u16()), 2); + assert_eq!(size_of_val(&Some(gen_u16())), 2); // uses niche + + cycle(gen_u8_tiny_niche(), 254); + cycle(gen_u8_full(), 255); + cycle(gen_u16(), 256); +} diff --git a/src/test/ui/generator/resume-arg-size.rs b/src/test/ui/generator/resume-arg-size.rs index ffdc98d6f1984..4f08ac0702bdb 100644 --- a/src/test/ui/generator/resume-arg-size.rs +++ b/src/test/ui/generator/resume-arg-size.rs @@ -23,6 +23,6 @@ fn main() { // Neither of these generators have the resume arg live across the `yield`, so they should be // 4 Bytes in size (only storing the discriminant) - assert_eq!(size_of_val(&gen_copy), 4); - assert_eq!(size_of_val(&gen_move), 4); + assert_eq!(size_of_val(&gen_copy), 1); + assert_eq!(size_of_val(&gen_move), 1); } diff --git a/src/test/ui/generator/size-moved-locals.rs b/src/test/ui/generator/size-moved-locals.rs index 2864fbb2f3c8d..74c60d98154dd 100644 --- a/src/test/ui/generator/size-moved-locals.rs +++ b/src/test/ui/generator/size-moved-locals.rs @@ -58,7 +58,7 @@ fn overlap_move_points() -> impl Generator { } } -fn overlap_x_and_y() -> impl Generator{ +fn overlap_x_and_y() -> impl Generator { static || { let x = Foo([0; FOO_SIZE]); yield; @@ -70,8 +70,8 @@ fn overlap_x_and_y() -> impl Generator{ } fn main() { - assert_eq!(1028, std::mem::size_of_val(&move_before_yield())); - assert_eq!(1032, std::mem::size_of_val(&move_before_yield_with_noop())); - assert_eq!(2056, std::mem::size_of_val(&overlap_move_points())); - assert_eq!(1032, std::mem::size_of_val(&overlap_x_and_y())); + assert_eq!(1025, std::mem::size_of_val(&move_before_yield())); + assert_eq!(1026, std::mem::size_of_val(&move_before_yield_with_noop())); + assert_eq!(2051, std::mem::size_of_val(&overlap_move_points())); + assert_eq!(1026, std::mem::size_of_val(&overlap_x_and_y())); } diff --git a/src/test/ui/issues/issue-21174.stderr b/src/test/ui/issues/issue-21174.stderr index 5ac5a8665bc69..09402c3d81410 100644 --- a/src/test/ui/issues/issue-21174.stderr +++ b/src/test/ui/issues/issue-21174.stderr @@ -4,8 +4,8 @@ error[E0512]: cannot transmute between types of different sizes, or dependently- LL | let new: T::B = unsafe { std::mem::transmute(value) }; | ^^^^^^^^^^^^^^^^^^^ | - = note: source type: `>::A` (size can vary because of ::A) - = note: target type: `>::B` (size can vary because of ::B) + = note: source type: `::A` (this type does not have a fixed size) + = note: target type: `::B` (this type does not have a fixed size) error: aborting due to previous error diff --git a/src/test/ui/json-bom-plus-crlf-multifile.stderr b/src/test/ui/json-bom-plus-crlf-multifile.stderr index ab0feb3c451ad..026943669f828 100644 --- a/src/test/ui/json-bom-plus-crlf-multifile.stderr +++ b/src/test/ui/json-bom-plus-crlf-multifile.stderr @@ -1,10 +1,6 @@ -{"message":"mismatched types","code":{"code":"E0308","explanation":"This error occurs when the compiler was unable to infer the concrete type of a -variable. It can occur for several cases, the most common of which is a -mismatch in the expected type that the compiler inferred for a variable's -initializing expression, and the actual type explicitly assigned to the -variable. +{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. -For example: +Erroneous code example: ```compile_fail,E0308 let x: i32 = \"I am not a number!\"; @@ -15,15 +11,17 @@ let x: i32 = \"I am not a number!\"; // | // type `i32` assigned to variable `x` ``` -"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":621,"byte_end":622,"line_start":17,"line_end":17,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":612,"byte_end":618,"line_start":17,"line_end":17,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":621,"byte_end":622,"line_start":17,"line_end":17,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:17:22: error[E0308]: mismatched types -"} -{"message":"mismatched types","code":{"code":"E0308","explanation":"This error occurs when the compiler was unable to infer the concrete type of a + +This error occurs when the compiler was unable to infer the concrete type of a variable. It can occur for several cases, the most common of which is a mismatch in the expected type that the compiler inferred for a variable's initializing expression, and the actual type explicitly assigned to the variable. +"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":621,"byte_end":622,"line_start":17,"line_end":17,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":612,"byte_end":618,"line_start":17,"line_end":17,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":621,"byte_end":622,"line_start":17,"line_end":17,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:17:22: error[E0308]: mismatched types +"} +{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. -For example: +Erroneous code example: ```compile_fail,E0308 let x: i32 = \"I am not a number!\"; @@ -34,15 +32,17 @@ let x: i32 = \"I am not a number!\"; // | // type `i32` assigned to variable `x` ``` -"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":681,"byte_end":682,"line_start":19,"line_end":19,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":672,"byte_end":678,"line_start":19,"line_end":19,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":681,"byte_end":682,"line_start":19,"line_end":19,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:19:22: error[E0308]: mismatched types -"} -{"message":"mismatched types","code":{"code":"E0308","explanation":"This error occurs when the compiler was unable to infer the concrete type of a + +This error occurs when the compiler was unable to infer the concrete type of a variable. It can occur for several cases, the most common of which is a mismatch in the expected type that the compiler inferred for a variable's initializing expression, and the actual type explicitly assigned to the variable. +"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":681,"byte_end":682,"line_start":19,"line_end":19,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":672,"byte_end":678,"line_start":19,"line_end":19,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":681,"byte_end":682,"line_start":19,"line_end":19,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:19:22: error[E0308]: mismatched types +"} +{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. -For example: +Erroneous code example: ```compile_fail,E0308 let x: i32 = \"I am not a number!\"; @@ -53,15 +53,17 @@ let x: i32 = \"I am not a number!\"; // | // type `i32` assigned to variable `x` ``` -"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":745,"byte_end":746,"line_start":23,"line_end":23,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":735,"byte_end":741,"line_start":22,"line_end":22,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":745,"byte_end":746,"line_start":23,"line_end":23,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:23:1: error[E0308]: mismatched types -"} -{"message":"mismatched types","code":{"code":"E0308","explanation":"This error occurs when the compiler was unable to infer the concrete type of a + +This error occurs when the compiler was unable to infer the concrete type of a variable. It can occur for several cases, the most common of which is a mismatch in the expected type that the compiler inferred for a variable's initializing expression, and the actual type explicitly assigned to the variable. +"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":745,"byte_end":746,"line_start":23,"line_end":23,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":735,"byte_end":741,"line_start":22,"line_end":22,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":745,"byte_end":746,"line_start":23,"line_end":23,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:23:1: error[E0308]: mismatched types +"} +{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. -For example: +Erroneous code example: ```compile_fail,E0308 let x: i32 = \"I am not a number!\"; @@ -72,6 +74,12 @@ let x: i32 = \"I am not a number!\"; // | // type `i32` assigned to variable `x` ``` + +This error occurs when the compiler was unable to infer the concrete type of a +variable. It can occur for several cases, the most common of which is a +mismatch in the expected type that the compiler inferred for a variable's +initializing expression, and the actual type explicitly assigned to the +variable. "},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":801,"byte_end":809,"line_start":25,"line_end":26,"column_start":22,"column_end":6,"is_primary":true,"text":[{"text":" let s : String = (","highlight_start":22,"highlight_end":23},{"text":" ); // Error spanning the newline.","highlight_start":1,"highlight_end":6}],"label":"expected struct `std::string::String`, found `()`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":792,"byte_end":798,"line_start":25,"line_end":25,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = (","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:25:22: error[E0308]: mismatched types "} {"message":"aborting due to 4 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 4 previous errors diff --git a/src/test/ui/json-bom-plus-crlf.stderr b/src/test/ui/json-bom-plus-crlf.stderr index 1dd898db3ad8c..735a46b8c875a 100644 --- a/src/test/ui/json-bom-plus-crlf.stderr +++ b/src/test/ui/json-bom-plus-crlf.stderr @@ -1,10 +1,6 @@ -{"message":"mismatched types","code":{"code":"E0308","explanation":"This error occurs when the compiler was unable to infer the concrete type of a -variable. It can occur for several cases, the most common of which is a -mismatch in the expected type that the compiler inferred for a variable's -initializing expression, and the actual type explicitly assigned to the -variable. +{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. -For example: +Erroneous code example: ```compile_fail,E0308 let x: i32 = \"I am not a number!\"; @@ -15,15 +11,17 @@ let x: i32 = \"I am not a number!\"; // | // type `i32` assigned to variable `x` ``` -"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":606,"byte_end":607,"line_start":16,"line_end":16,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":597,"byte_end":603,"line_start":16,"line_end":16,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":606,"byte_end":607,"line_start":16,"line_end":16,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:16:22: error[E0308]: mismatched types -"} -{"message":"mismatched types","code":{"code":"E0308","explanation":"This error occurs when the compiler was unable to infer the concrete type of a + +This error occurs when the compiler was unable to infer the concrete type of a variable. It can occur for several cases, the most common of which is a mismatch in the expected type that the compiler inferred for a variable's initializing expression, and the actual type explicitly assigned to the variable. +"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":606,"byte_end":607,"line_start":16,"line_end":16,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":597,"byte_end":603,"line_start":16,"line_end":16,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":606,"byte_end":607,"line_start":16,"line_end":16,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:16:22: error[E0308]: mismatched types +"} +{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. -For example: +Erroneous code example: ```compile_fail,E0308 let x: i32 = \"I am not a number!\"; @@ -34,15 +32,17 @@ let x: i32 = \"I am not a number!\"; // | // type `i32` assigned to variable `x` ``` -"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":666,"byte_end":667,"line_start":18,"line_end":18,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":657,"byte_end":663,"line_start":18,"line_end":18,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":666,"byte_end":667,"line_start":18,"line_end":18,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:18:22: error[E0308]: mismatched types -"} -{"message":"mismatched types","code":{"code":"E0308","explanation":"This error occurs when the compiler was unable to infer the concrete type of a + +This error occurs when the compiler was unable to infer the concrete type of a variable. It can occur for several cases, the most common of which is a mismatch in the expected type that the compiler inferred for a variable's initializing expression, and the actual type explicitly assigned to the variable. +"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":666,"byte_end":667,"line_start":18,"line_end":18,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":657,"byte_end":663,"line_start":18,"line_end":18,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":666,"byte_end":667,"line_start":18,"line_end":18,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:18:22: error[E0308]: mismatched types +"} +{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. -For example: +Erroneous code example: ```compile_fail,E0308 let x: i32 = \"I am not a number!\"; @@ -53,15 +53,17 @@ let x: i32 = \"I am not a number!\"; // | // type `i32` assigned to variable `x` ``` -"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":730,"byte_end":731,"line_start":22,"line_end":22,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":720,"byte_end":726,"line_start":21,"line_end":21,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":730,"byte_end":731,"line_start":22,"line_end":22,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:22:1: error[E0308]: mismatched types -"} -{"message":"mismatched types","code":{"code":"E0308","explanation":"This error occurs when the compiler was unable to infer the concrete type of a + +This error occurs when the compiler was unable to infer the concrete type of a variable. It can occur for several cases, the most common of which is a mismatch in the expected type that the compiler inferred for a variable's initializing expression, and the actual type explicitly assigned to the variable. +"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":730,"byte_end":731,"line_start":22,"line_end":22,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":720,"byte_end":726,"line_start":21,"line_end":21,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":730,"byte_end":731,"line_start":22,"line_end":22,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:22:1: error[E0308]: mismatched types +"} +{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. -For example: +Erroneous code example: ```compile_fail,E0308 let x: i32 = \"I am not a number!\"; @@ -72,6 +74,12 @@ let x: i32 = \"I am not a number!\"; // | // type `i32` assigned to variable `x` ``` + +This error occurs when the compiler was unable to infer the concrete type of a +variable. It can occur for several cases, the most common of which is a +mismatch in the expected type that the compiler inferred for a variable's +initializing expression, and the actual type explicitly assigned to the +variable. "},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":786,"byte_end":794,"line_start":24,"line_end":25,"column_start":22,"column_end":6,"is_primary":true,"text":[{"text":" let s : String = (","highlight_start":22,"highlight_end":23},{"text":" ); // Error spanning the newline.","highlight_start":1,"highlight_end":6}],"label":"expected struct `std::string::String`, found `()`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":777,"byte_end":783,"line_start":24,"line_end":24,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = (","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-bom-plus-crlf.rs:24:22: error[E0308]: mismatched types "} {"message":"aborting due to 4 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 4 previous errors diff --git a/src/test/ui/lint/uninitialized-zeroed.stderr b/src/test/ui/lint/uninitialized-zeroed.stderr index 6d669184deb3e..bf0562713a497 100644 --- a/src/test/ui/lint/uninitialized-zeroed.stderr +++ b/src/test/ui/lint/uninitialized-zeroed.stderr @@ -1,4 +1,4 @@ -error: the type `&'static T` does not permit zero-initialization +error: the type `&T` does not permit zero-initialization --> $DIR/uninitialized-zeroed.rs:29:32 | LL | let _val: &'static T = mem::zeroed(); @@ -14,7 +14,7 @@ LL | #![deny(invalid_value)] | ^^^^^^^^^^^^^ = note: references must be non-null -error: the type `&'static T` does not permit being left uninitialized +error: the type `&T` does not permit being left uninitialized --> $DIR/uninitialized-zeroed.rs:30:32 | LL | let _val: &'static T = mem::uninitialized(); @@ -25,7 +25,7 @@ LL | let _val: &'static T = mem::uninitialized(); | = note: references must be non-null -error: the type `Wrap<&'static T>` does not permit zero-initialization +error: the type `Wrap<&T>` does not permit zero-initialization --> $DIR/uninitialized-zeroed.rs:32:38 | LL | let _val: Wrap<&'static T> = mem::zeroed(); @@ -40,7 +40,7 @@ note: references must be non-null (in this struct field) LL | struct Wrap { wrapped: T } | ^^^^^^^^^^ -error: the type `Wrap<&'static T>` does not permit being left uninitialized +error: the type `Wrap<&T>` does not permit being left uninitialized --> $DIR/uninitialized-zeroed.rs:33:38 | LL | let _val: Wrap<&'static T> = mem::uninitialized(); @@ -121,7 +121,7 @@ LL | let _val: Void = mem::uninitialized(); | = note: enums with no variants have no valid value -error: the type `&'static i32` does not permit zero-initialization +error: the type `&i32` does not permit zero-initialization --> $DIR/uninitialized-zeroed.rs:49:34 | LL | let _val: &'static i32 = mem::zeroed(); @@ -132,7 +132,7 @@ LL | let _val: &'static i32 = mem::zeroed(); | = note: references must be non-null -error: the type `&'static i32` does not permit being left uninitialized +error: the type `&i32` does not permit being left uninitialized --> $DIR/uninitialized-zeroed.rs:50:34 | LL | let _val: &'static i32 = mem::uninitialized(); @@ -366,7 +366,7 @@ LL | let _val: NonBig = mem::uninitialized(); | = note: `NonBig` must be initialized inside its custom valid range -error: the type `&'static i32` does not permit zero-initialization +error: the type `&i32` does not permit zero-initialization --> $DIR/uninitialized-zeroed.rs:84:34 | LL | let _val: &'static i32 = mem::transmute(0usize); @@ -377,7 +377,7 @@ LL | let _val: &'static i32 = mem::transmute(0usize); | = note: references must be non-null -error: the type `&'static [i32]` does not permit zero-initialization +error: the type `&[i32]` does not permit zero-initialization --> $DIR/uninitialized-zeroed.rs:85:36 | LL | let _val: &'static [i32] = mem::transmute((0usize, 0usize)); diff --git a/src/test/ui/macros/issue-61033-1.rs b/src/test/ui/macros/issue-61033-1.rs index 8f85dec017f2a..18df3f6ee94c1 100644 --- a/src/test/ui/macros/issue-61033-1.rs +++ b/src/test/ui/macros/issue-61033-1.rs @@ -1,9 +1,10 @@ // Regression test for issue #61033. macro_rules! test1 { - ($x:ident, $($tt:tt)*) => { $($tt)+ } //~ERROR this must repeat at least once + ($x:ident, $($tt:tt)*) => { $($tt)+ } //~ ERROR this must repeat at least once } fn main() { test1!(x,); + let _recovery_witness: () = 0; //~ ERROR mismatched types } diff --git a/src/test/ui/macros/issue-61033-1.stderr b/src/test/ui/macros/issue-61033-1.stderr index f3c68f4928dbb..18205c3436b0b 100644 --- a/src/test/ui/macros/issue-61033-1.stderr +++ b/src/test/ui/macros/issue-61033-1.stderr @@ -4,5 +4,14 @@ error: this must repeat at least once LL | ($x:ident, $($tt:tt)*) => { $($tt)+ } | ^^^^^ -error: aborting due to previous error +error[E0308]: mismatched types + --> $DIR/issue-61033-1.rs:9:33 + | +LL | let _recovery_witness: () = 0; + | -- ^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/macros/issue-61033-2.rs b/src/test/ui/macros/issue-61033-2.rs index 0799be10b96c7..1760ba1584d0b 100644 --- a/src/test/ui/macros/issue-61033-2.rs +++ b/src/test/ui/macros/issue-61033-2.rs @@ -5,7 +5,9 @@ macro_rules! test2 { $(* $id1:ident)* $(+ $id2:ident)* ) => { - $( //~ERROR meta-variable `id1` repeats 2 times + $( + //~^ ERROR meta-variable `id1` repeats 2 times + //~| ERROR meta-variable `id1` repeats 2 times $id1 + $id2 // $id1 and $id2 may repeat different numbers of times )* } @@ -16,4 +18,8 @@ fn main() { * a * b + a + b + c } + test2! { + * a * b + + a + b + c + d + } } diff --git a/src/test/ui/macros/issue-61033-2.stderr b/src/test/ui/macros/issue-61033-2.stderr index bf502919cf794..cdfe7934a0cac 100644 --- a/src/test/ui/macros/issue-61033-2.stderr +++ b/src/test/ui/macros/issue-61033-2.stderr @@ -3,9 +3,22 @@ error: meta-variable `id1` repeats 2 times, but `id2` repeats 3 times | LL | $( | __________^ +LL | | +LL | | LL | | $id1 + $id2 // $id1 and $id2 may repeat different numbers of times LL | | )* | |_________^ -error: aborting due to previous error +error: meta-variable `id1` repeats 2 times, but `id2` repeats 4 times + --> $DIR/issue-61033-2.rs:8:10 + | +LL | $( + | __________^ +LL | | +LL | | +LL | | $id1 + $id2 // $id1 and $id2 may repeat different numbers of times +LL | | )* + | |_________^ + +error: aborting due to 2 previous errors diff --git a/src/test/ui/macros/local-ambiguity-multiple-parsing-options.rs b/src/test/ui/macros/local-ambiguity-multiple-parsing-options.rs new file mode 100644 index 0000000000000..3967481098cff --- /dev/null +++ b/src/test/ui/macros/local-ambiguity-multiple-parsing-options.rs @@ -0,0 +1,8 @@ +fn main() {} + +macro_rules! ambiguity { + ($($i:ident)* $j:ident) => {}; +} + +ambiguity!(error); //~ ERROR local ambiguity +ambiguity!(error); //~ ERROR local ambiguity diff --git a/src/test/ui/macros/local-ambiguity-multiple-parsing-options.stderr b/src/test/ui/macros/local-ambiguity-multiple-parsing-options.stderr new file mode 100644 index 0000000000000..0ae56c422213c --- /dev/null +++ b/src/test/ui/macros/local-ambiguity-multiple-parsing-options.stderr @@ -0,0 +1,14 @@ +error: local ambiguity: multiple parsing options: built-in NTs ident ('i') or ident ('j'). + --> $DIR/local-ambiguity-multiple-parsing-options.rs:7:12 + | +LL | ambiguity!(error); + | ^^^^^ + +error: local ambiguity: multiple parsing options: built-in NTs ident ('i') or ident ('j'). + --> $DIR/local-ambiguity-multiple-parsing-options.rs:8:12 + | +LL | ambiguity!(error); + | ^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/macros/macro-context.rs b/src/test/ui/macros/macro-context.rs index 9130c3d921c52..13e179578ad01 100644 --- a/src/test/ui/macros/macro-context.rs +++ b/src/test/ui/macros/macro-context.rs @@ -4,6 +4,8 @@ macro_rules! m { //~| ERROR macro expansion ignores token `typeof` //~| ERROR macro expansion ignores token `;` //~| ERROR macro expansion ignores token `;` + //~| ERROR cannot find type `i` in this scope + //~| ERROR cannot find value `i` in this scope } fn main() { diff --git a/src/test/ui/macros/macro-context.stderr b/src/test/ui/macros/macro-context.stderr index 2e712110689f8..17c7389812475 100644 --- a/src/test/ui/macros/macro-context.stderr +++ b/src/test/ui/macros/macro-context.stderr @@ -42,5 +42,29 @@ LL | m!(); | = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 4 previous errors +error[E0412]: cannot find type `i` in this scope + --> $DIR/macro-context.rs:3:13 + | +LL | () => ( i ; typeof ); + | ^ help: a builtin type with a similar name exists: `i8` +... +LL | let a: m!(); + | ---- in this macro invocation + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0425]: cannot find value `i` in this scope + --> $DIR/macro-context.rs:3:13 + | +LL | () => ( i ; typeof ); + | ^ help: a local variable with a similar name exists: `a` +... +LL | let i = m!(); + | ---- in this macro invocation + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 6 previous errors +Some errors have detailed explanations: E0412, E0425. +For more information about an error, try `rustc --explain E0412`. diff --git a/src/test/ui/macros/macro-match-nonterminal.rs b/src/test/ui/macros/macro-match-nonterminal.rs index 6d4b32c9bc9a0..b23e5c71c03f0 100644 --- a/src/test/ui/macros/macro-match-nonterminal.rs +++ b/src/test/ui/macros/macro-match-nonterminal.rs @@ -1,4 +1,11 @@ -macro_rules! test { ($a, $b) => (()); } //~ ERROR missing fragment +macro_rules! test { + ($a, $b) => { + //~^ ERROR missing fragment + //~| ERROR missing fragment + //~| WARN this was previously accepted + () + }; +} fn main() { test!() diff --git a/src/test/ui/macros/macro-match-nonterminal.stderr b/src/test/ui/macros/macro-match-nonterminal.stderr index 1de8c5bd4b472..674ce3434aac6 100644 --- a/src/test/ui/macros/macro-match-nonterminal.stderr +++ b/src/test/ui/macros/macro-match-nonterminal.stderr @@ -1,8 +1,18 @@ error: missing fragment specifier - --> $DIR/macro-match-nonterminal.rs:1:24 + --> $DIR/macro-match-nonterminal.rs:2:8 | -LL | macro_rules! test { ($a, $b) => (()); } - | ^ +LL | ($a, $b) => { + | ^ -error: aborting due to previous error +error: missing fragment specifier + --> $DIR/macro-match-nonterminal.rs:2:10 + | +LL | ($a, $b) => { + | ^^ + | + = note: `#[deny(missing_fragment_specifier)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #40107 + +error: aborting due to 2 previous errors diff --git a/src/test/ui/macros/trace-macro.stderr b/src/test/ui/macros/trace-macro.stderr index 202a9235adbac..6217decd8ef88 100644 --- a/src/test/ui/macros/trace-macro.stderr +++ b/src/test/ui/macros/trace-macro.stderr @@ -5,5 +5,5 @@ LL | println!("Hello, World!"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: expanding `println! { "Hello, World!" }` - = note: to `{ $crate :: io :: _print ($crate :: format_args_nl ! ("Hello, World!")) ; }` + = note: to `{ $crate :: io :: _print($crate :: format_args_nl ! ("Hello, World!")) ; }` diff --git a/src/test/ui/macros/trace_faulty_macros.rs b/src/test/ui/macros/trace_faulty_macros.rs index 627d58abf4ca2..a55f05414b206 100644 --- a/src/test/ui/macros/trace_faulty_macros.rs +++ b/src/test/ui/macros/trace_faulty_macros.rs @@ -13,7 +13,7 @@ macro_rules! pat_macro { pat_macro!(A{a:a, b:0, c:_, ..}); }; ($a:pat) => { - $a + $a //~ ERROR expected expression }; } diff --git a/src/test/ui/macros/trace_faulty_macros.stderr b/src/test/ui/macros/trace_faulty_macros.stderr index a18e22e07f8bc..109b493b43717 100644 --- a/src/test/ui/macros/trace_faulty_macros.stderr +++ b/src/test/ui/macros/trace_faulty_macros.stderr @@ -49,5 +49,16 @@ LL | my_recursive_macro!(); = note: expanding `my_recursive_macro! { }` = note: to `my_recursive_macro ! () ;` -error: aborting due to 2 previous errors +error: expected expression, found `A { a: a, b: 0, c: _, .. }` + --> $DIR/trace_faulty_macros.rs:16:9 + | +LL | $a + | ^^ expected expression +... +LL | let a = pat_macro!(); + | ------------ in this macro invocation + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 3 previous errors diff --git a/src/test/ui/parser/issue-62894.stderr b/src/test/ui/parser/issue-62894.stderr index 6db380f7a7fe2..73e3552e3ec7a 100644 --- a/src/test/ui/parser/issue-62894.stderr +++ b/src/test/ui/parser/issue-62894.stderr @@ -42,6 +42,11 @@ LL | fn f() { assert_eq!(f(), (), assert_eq!(assert_eq! LL | LL | fn main() {} | ^^ unexpected token + | + ::: $SRC_DIR/libcore/macros/mod.rs:LL:COL + | +LL | ($left:expr, $right:expr) => ({ + | ---------- while parsing argument for this `expr` macro fragment error: aborting due to 4 previous errors diff --git a/src/test/ui/parser/macro/issue-33569.rs b/src/test/ui/parser/macro/issue-33569.rs index 9ed53519ceb31..80e2d7c6545ba 100644 --- a/src/test/ui/parser/macro/issue-33569.rs +++ b/src/test/ui/parser/macro/issue-33569.rs @@ -6,3 +6,5 @@ macro_rules! foo { } foo!(); + +fn main() {} diff --git a/src/test/ui/parser/macro/macro-repeat.rs b/src/test/ui/parser/macro/macro-repeat.rs index 580a1daacbf31..3ffbea217e79e 100644 --- a/src/test/ui/parser/macro/macro-repeat.rs +++ b/src/test/ui/parser/macro/macro-repeat.rs @@ -1,9 +1,12 @@ macro_rules! mac { - ( $($v:tt)* ) => ( - $v //~ ERROR still repeating at this depth - ) + ( $($v:tt)* ) => { + $v + //~^ ERROR still repeating at this depth + //~| ERROR still repeating at this depth + }; } fn main() { mac!(0); + mac!(1); } diff --git a/src/test/ui/parser/macro/macro-repeat.stderr b/src/test/ui/parser/macro/macro-repeat.stderr index c86684de74432..63554b197b91c 100644 --- a/src/test/ui/parser/macro/macro-repeat.stderr +++ b/src/test/ui/parser/macro/macro-repeat.stderr @@ -4,5 +4,11 @@ error: variable 'v' is still repeating at this depth LL | $v | ^^ -error: aborting due to previous error +error: variable 'v' is still repeating at this depth + --> $DIR/macro-repeat.rs:3:9 + | +LL | $v + | ^^ + +error: aborting due to 2 previous errors diff --git a/src/test/ui/parser/nt-parsing-has-recovery.rs b/src/test/ui/parser/nt-parsing-has-recovery.rs new file mode 100644 index 0000000000000..ccbeb398af5ba --- /dev/null +++ b/src/test/ui/parser/nt-parsing-has-recovery.rs @@ -0,0 +1,10 @@ +macro_rules! foo { + ($e:expr) => {} +} + +foo!(1 + @); //~ ERROR expected expression, found `@` +foo!(1 + @); //~ ERROR expected expression, found `@` + +fn main() { + let _recovery_witness: () = 0; //~ ERROR mismatched types +} diff --git a/src/test/ui/parser/nt-parsing-has-recovery.stderr b/src/test/ui/parser/nt-parsing-has-recovery.stderr new file mode 100644 index 0000000000000..263c4ad53612e --- /dev/null +++ b/src/test/ui/parser/nt-parsing-has-recovery.stderr @@ -0,0 +1,29 @@ +error: expected expression, found `@` + --> $DIR/nt-parsing-has-recovery.rs:5:10 + | +LL | ($e:expr) => {} + | ------- while parsing argument for this `expr` macro fragment +... +LL | foo!(1 + @); + | ^ expected expression + +error: expected expression, found `@` + --> $DIR/nt-parsing-has-recovery.rs:6:10 + | +LL | ($e:expr) => {} + | ------- while parsing argument for this `expr` macro fragment +... +LL | foo!(1 + @); + | ^ expected expression + +error[E0308]: mismatched types + --> $DIR/nt-parsing-has-recovery.rs:9:33 + | +LL | let _recovery_witness: () = 0; + | -- ^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/pattern/usefulness/always-inhabited-union-ref.rs b/src/test/ui/pattern/usefulness/always-inhabited-union-ref.rs index 11eae2af9c95f..7d1cac8a442f5 100644 --- a/src/test/ui/pattern/usefulness/always-inhabited-union-ref.rs +++ b/src/test/ui/pattern/usefulness/always-inhabited-union-ref.rs @@ -21,7 +21,7 @@ fn uninhab_union() -> Foo { fn match_on_uninhab() { match uninhab_ref() { - //~^ ERROR non-exhaustive patterns: type `&'static !` is non-empty + //~^ ERROR non-exhaustive patterns: type `&!` is non-empty } match uninhab_union() { diff --git a/src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr b/src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr index 1b1096c977ad4..e1079f912d076 100644 --- a/src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr +++ b/src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr @@ -1,4 +1,4 @@ -error[E0004]: non-exhaustive patterns: type `&'static !` is non-empty +error[E0004]: non-exhaustive patterns: type `&!` is non-empty --> $DIR/always-inhabited-union-ref.rs:23:11 | LL | match uninhab_ref() { diff --git a/src/test/ui/proc-macro/attribute-spans-preserved.stdout b/src/test/ui/proc-macro/attribute-spans-preserved.stdout index faf3171215665..cf9a97491f039 100644 --- a/src/test/ui/proc-macro/attribute-spans-preserved.stdout +++ b/src/test/ui/proc-macro/attribute-spans-preserved.stdout @@ -1 +1 @@ -fn main () { let y : u32 = "z" ; { let x : u32 = "y" ; } } +fn main() { let y : u32 = "z" ; { let x : u32 = "y" ; } } diff --git a/src/test/ui/proc-macro/derive-bad.rs b/src/test/ui/proc-macro/derive-bad.rs index 62c0741b6697a..cb5188b5fb43f 100644 --- a/src/test/ui/proc-macro/derive-bad.rs +++ b/src/test/ui/proc-macro/derive-bad.rs @@ -3,11 +3,9 @@ #[macro_use] extern crate derive_bad; -#[derive( - A -)] -//~^^ ERROR proc-macro derive produced unparseable tokens +#[derive(A)] +//~^ ERROR proc-macro derive produced unparseable tokens //~| ERROR expected `:`, found `}` -struct A; +struct A; //~ ERROR the name `A` is defined multiple times fn main() {} diff --git a/src/test/ui/proc-macro/derive-bad.stderr b/src/test/ui/proc-macro/derive-bad.stderr index 8667396c98989..bc5ed9815238a 100644 --- a/src/test/ui/proc-macro/derive-bad.stderr +++ b/src/test/ui/proc-macro/derive-bad.stderr @@ -1,16 +1,28 @@ error: expected `:`, found `}` - --> $DIR/derive-bad.rs:7:5 + --> $DIR/derive-bad.rs:6:10 | -LL | A - | ^ expected `:` +LL | #[derive(A)] + | ^ expected `:` | = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) error: proc-macro derive produced unparseable tokens - --> $DIR/derive-bad.rs:7:5 + --> $DIR/derive-bad.rs:6:10 | -LL | A - | ^ +LL | #[derive(A)] + | ^ -error: aborting due to 2 previous errors +error[E0428]: the name `A` is defined multiple times + --> $DIR/derive-bad.rs:9:1 + | +LL | #[derive(A)] + | - previous definition of the type `A` here +... +LL | struct A; + | ^^^^^^^^^ `A` redefined here + | + = note: `A` must be defined only once in the type namespace of this module + +error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0428`. diff --git a/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout b/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout index ea06f6c1acaf9..15433bebde967 100644 --- a/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout +++ b/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout @@ -1,4 +1,4 @@ -PRINT-BANG INPUT (DISPLAY): struct M ($crate :: S) ; +PRINT-BANG INPUT (DISPLAY): struct M($crate :: S) ; PRINT-BANG INPUT (DEBUG): TokenStream [ Ident { ident: "struct", @@ -39,7 +39,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [ }, ] PRINT-ATTR INPUT (DISPLAY): struct A(crate::S); -PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ($crate :: S) ; +PRINT-ATTR RE-COLLECTED (DISPLAY): struct A($crate :: S) ; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", diff --git a/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout b/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout index 619b2fd5321ff..73e407918ec8c 100644 --- a/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout +++ b/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout @@ -1,5 +1,5 @@ PRINT-ATTR INPUT (DISPLAY): struct A(identity!(crate :: S)); -PRINT-ATTR RE-COLLECTED (DISPLAY): struct A (identity ! ($crate :: S)) ; +PRINT-ATTR RE-COLLECTED (DISPLAY): struct A(identity ! ($crate :: S)) ; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", @@ -55,7 +55,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ }, ] PRINT-ATTR INPUT (DISPLAY): struct B(identity!(::dollar_crate_external :: S)); -PRINT-ATTR RE-COLLECTED (DISPLAY): struct B (identity ! ($crate :: S)) ; +PRINT-ATTR RE-COLLECTED (DISPLAY): struct B(identity ! ($crate :: S)) ; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", diff --git a/src/test/ui/proc-macro/dollar-crate.stdout b/src/test/ui/proc-macro/dollar-crate.stdout index 5fdc6f8ee96ca..e125a3e7f1737 100644 --- a/src/test/ui/proc-macro/dollar-crate.stdout +++ b/src/test/ui/proc-macro/dollar-crate.stdout @@ -1,4 +1,4 @@ -PRINT-BANG INPUT (DISPLAY): struct M ($crate :: S) ; +PRINT-BANG INPUT (DISPLAY): struct M($crate :: S) ; PRINT-BANG INPUT (DEBUG): TokenStream [ Ident { ident: "struct", @@ -39,7 +39,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [ }, ] PRINT-ATTR INPUT (DISPLAY): struct A(crate::S); -PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ($crate :: S) ; +PRINT-ATTR RE-COLLECTED (DISPLAY): struct A($crate :: S) ; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", @@ -80,7 +80,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ }, ] PRINT-DERIVE INPUT (DISPLAY): struct D(crate::S); -PRINT-DERIVE RE-COLLECTED (DISPLAY): struct D ($crate :: S) ; +PRINT-DERIVE RE-COLLECTED (DISPLAY): struct D($crate :: S) ; PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "struct", @@ -120,7 +120,7 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ span: #3 bytes(LO..HI), }, ] -PRINT-BANG INPUT (DISPLAY): struct M ($crate :: S) ; +PRINT-BANG INPUT (DISPLAY): struct M($crate :: S) ; PRINT-BANG INPUT (DEBUG): TokenStream [ Ident { ident: "struct", @@ -161,7 +161,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [ }, ] PRINT-ATTR INPUT (DISPLAY): struct A(::dollar_crate_external::S); -PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ($crate :: S) ; +PRINT-ATTR RE-COLLECTED (DISPLAY): struct A($crate :: S) ; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", @@ -202,7 +202,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ }, ] PRINT-DERIVE INPUT (DISPLAY): struct D(::dollar_crate_external::S); -PRINT-DERIVE RE-COLLECTED (DISPLAY): struct D ($crate :: S) ; +PRINT-DERIVE RE-COLLECTED (DISPLAY): struct D($crate :: S) ; PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "struct", diff --git a/src/test/ui/proc-macro/invalid-punct-ident-1.rs b/src/test/ui/proc-macro/invalid-punct-ident-1.rs index 9de57da5af434..3f78dea917b19 100644 --- a/src/test/ui/proc-macro/invalid-punct-ident-1.rs +++ b/src/test/ui/proc-macro/invalid-punct-ident-1.rs @@ -14,3 +14,5 @@ extern crate invalid_punct_ident; invalid_punct!(); //~ ERROR proc macro panicked + +fn main() {} diff --git a/src/test/ui/proc-macro/invalid-punct-ident-2.rs b/src/test/ui/proc-macro/invalid-punct-ident-2.rs index 79f72324b1d89..4e89e80ae7c41 100644 --- a/src/test/ui/proc-macro/invalid-punct-ident-2.rs +++ b/src/test/ui/proc-macro/invalid-punct-ident-2.rs @@ -14,3 +14,5 @@ extern crate invalid_punct_ident; invalid_ident!(); //~ ERROR proc macro panicked + +fn main() {} diff --git a/src/test/ui/proc-macro/invalid-punct-ident-3.rs b/src/test/ui/proc-macro/invalid-punct-ident-3.rs index d01e9b699cac5..8d8ce8f932e71 100644 --- a/src/test/ui/proc-macro/invalid-punct-ident-3.rs +++ b/src/test/ui/proc-macro/invalid-punct-ident-3.rs @@ -14,3 +14,5 @@ extern crate invalid_punct_ident; invalid_raw_ident!(); //~ ERROR proc macro panicked + +fn main() {} diff --git a/src/test/ui/proc-macro/invalid-punct-ident-4.rs b/src/test/ui/proc-macro/invalid-punct-ident-4.rs index e50f24deae343..59b347dac679c 100644 --- a/src/test/ui/proc-macro/invalid-punct-ident-4.rs +++ b/src/test/ui/proc-macro/invalid-punct-ident-4.rs @@ -3,5 +3,10 @@ #[macro_use] extern crate invalid_punct_ident; -lexer_failure!(); //~ ERROR proc macro panicked - //~| ERROR unexpected closing delimiter: `)` +lexer_failure!(); +//~^ ERROR proc macro panicked +//~| ERROR unexpected closing delimiter: `)` + +fn main() { + let _recovery_witness: () = 0; //~ ERROR mismatched types +} diff --git a/src/test/ui/proc-macro/invalid-punct-ident-4.stderr b/src/test/ui/proc-macro/invalid-punct-ident-4.stderr index fe3e55b31be5d..3b357aecea864 100644 --- a/src/test/ui/proc-macro/invalid-punct-ident-4.stderr +++ b/src/test/ui/proc-macro/invalid-punct-ident-4.stderr @@ -12,5 +12,14 @@ error: proc macro panicked LL | lexer_failure!(); | ^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error[E0308]: mismatched types + --> $DIR/invalid-punct-ident-4.rs:11:33 + | +LL | let _recovery_witness: () = 0; + | -- ^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/proc-macro/issue-36935.rs b/src/test/ui/proc-macro/issue-36935.rs index f809592d5f449..5c43a564c00c2 100644 --- a/src/test/ui/proc-macro/issue-36935.rs +++ b/src/test/ui/proc-macro/issue-36935.rs @@ -5,6 +5,7 @@ extern crate test_macros; #[derive(Identity, Panic)] //~ ERROR proc-macro derive panicked struct Baz { + //~^ ERROR the name `Baz` is defined multiple times a: i32, b: i32, } diff --git a/src/test/ui/proc-macro/issue-36935.stderr b/src/test/ui/proc-macro/issue-36935.stderr index da4366eb668d6..2b2e28fdb2fda 100644 --- a/src/test/ui/proc-macro/issue-36935.stderr +++ b/src/test/ui/proc-macro/issue-36935.stderr @@ -6,5 +6,17 @@ LL | #[derive(Identity, Panic)] | = help: message: panic-derive -error: aborting due to previous error +error[E0428]: the name `Baz` is defined multiple times + --> $DIR/issue-36935.rs:7:1 + | +LL | struct Baz { + | ^^^^^^^^^^ + | | + | `Baz` redefined here + | previous definition of the type `Baz` here + | + = note: `Baz` must be defined only once in the type namespace of this module + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0428`. diff --git a/src/test/ui/regions/regions-free-region-ordering-caller.migrate.stderr b/src/test/ui/regions/regions-free-region-ordering-caller.migrate.stderr index a33d3583552dc..06e1b0f1ac262 100644 --- a/src/test/ui/regions/regions-free-region-ordering-caller.migrate.stderr +++ b/src/test/ui/regions/regions-free-region-ordering-caller.migrate.stderr @@ -1,32 +1,54 @@ -error[E0623]: lifetime mismatch +error[E0491]: in type `&'b &'a usize`, reference has a longer lifetime than the data it references --> $DIR/regions-free-region-ordering-caller.rs:11:12 | -LL | fn call2<'a, 'b>(a: &'a usize, b: &'b usize) { - | --------- --------- - | | - | these two types are declared with different lifetimes... LL | let z: Option<&'b &'a usize> = None; - | ^^^^^^^^^^^^^^^^^^^^^ ...but data from `a` flows into `b` here + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: the pointer is valid for the lifetime `'b` as defined on the function body at 10:14 + --> $DIR/regions-free-region-ordering-caller.rs:10:14 + | +LL | fn call2<'a, 'b>(a: &'a usize, b: &'b usize) { + | ^^ +note: but the referenced data is only valid for the lifetime `'a` as defined on the function body at 10:10 + --> $DIR/regions-free-region-ordering-caller.rs:10:10 + | +LL | fn call2<'a, 'b>(a: &'a usize, b: &'b usize) { + | ^^ -error[E0623]: lifetime mismatch +error[E0491]: in type `&'b Paramd<'a>`, reference has a longer lifetime than the data it references --> $DIR/regions-free-region-ordering-caller.rs:17:12 | -LL | fn call3<'a, 'b>(a: &'a usize, b: &'b usize) { - | --------- --------- - | | - | these two types are declared with different lifetimes... -LL | let y: Paramd<'a> = Paramd { x: a }; LL | let z: Option<&'b Paramd<'a>> = None; - | ^^^^^^^^^^^^^^^^^^^^^^ ...but data from `a` flows into `b` here + | ^^^^^^^^^^^^^^^^^^^^^^ + | +note: the pointer is valid for the lifetime `'b` as defined on the function body at 15:14 + --> $DIR/regions-free-region-ordering-caller.rs:15:14 + | +LL | fn call3<'a, 'b>(a: &'a usize, b: &'b usize) { + | ^^ +note: but the referenced data is only valid for the lifetime `'a` as defined on the function body at 15:10 + --> $DIR/regions-free-region-ordering-caller.rs:15:10 + | +LL | fn call3<'a, 'b>(a: &'a usize, b: &'b usize) { + | ^^ -error[E0623]: lifetime mismatch +error[E0491]: in type `&'a &'b usize`, reference has a longer lifetime than the data it references --> $DIR/regions-free-region-ordering-caller.rs:22:12 | -LL | fn call4<'a, 'b>(a: &'a usize, b: &'b usize) { - | --------- --------- these two types are declared with different lifetimes... LL | let z: Option<&'a &'b usize> = None; - | ^^^^^^^^^^^^^^^^^^^^^ ...but data from `b` flows into `a` here + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: the pointer is valid for the lifetime `'a` as defined on the function body at 21:10 + --> $DIR/regions-free-region-ordering-caller.rs:21:10 + | +LL | fn call4<'a, 'b>(a: &'a usize, b: &'b usize) { + | ^^ +note: but the referenced data is only valid for the lifetime `'b` as defined on the function body at 21:14 + --> $DIR/regions-free-region-ordering-caller.rs:21:14 + | +LL | fn call4<'a, 'b>(a: &'a usize, b: &'b usize) { + | ^^ error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0623`. +For more information about this error, try `rustc --explain E0491`. diff --git a/src/test/ui/regions/regions-free-region-ordering-caller.rs b/src/test/ui/regions/regions-free-region-ordering-caller.rs index c0b12f23cdba7..2bf4734cf7380 100644 --- a/src/test/ui/regions/regions-free-region-ordering-caller.rs +++ b/src/test/ui/regions/regions-free-region-ordering-caller.rs @@ -8,18 +8,18 @@ struct Paramd<'a> { x: &'a usize } fn call2<'a, 'b>(a: &'a usize, b: &'b usize) { - let z: Option<&'b &'a usize> = None;//[migrate]~ ERROR E0623 + let z: Option<&'b &'a usize> = None;//[migrate]~ ERROR E0491 //[nll]~^ ERROR lifetime may not live long enough } fn call3<'a, 'b>(a: &'a usize, b: &'b usize) { let y: Paramd<'a> = Paramd { x: a }; - let z: Option<&'b Paramd<'a>> = None;//[migrate]~ ERROR E0623 + let z: Option<&'b Paramd<'a>> = None;//[migrate]~ ERROR E0491 //[nll]~^ ERROR lifetime may not live long enough } fn call4<'a, 'b>(a: &'a usize, b: &'b usize) { - let z: Option<&'a &'b usize> = None;//[migrate]~ ERROR E0623 + let z: Option<&'a &'b usize> = None;//[migrate]~ ERROR E0491 //[nll]~^ ERROR lifetime may not live long enough } diff --git a/src/test/ui/suggestions/const-no-type.rs b/src/test/ui/suggestions/const-no-type.rs index 99200a965dd21..6b79697e9839e 100644 --- a/src/test/ui/suggestions/const-no-type.rs +++ b/src/test/ui/suggestions/const-no-type.rs @@ -43,4 +43,4 @@ static S = Vec::::new(); static mut SM = "abc"; //~^ ERROR missing type for `static mut` item //~| HELP provide a type for the item -//~| SUGGESTION &'static str +//~| SUGGESTION &str diff --git a/src/test/ui/suggestions/const-no-type.stderr b/src/test/ui/suggestions/const-no-type.stderr index c4f17109dc5c7..a7b5aa5e5b124 100644 --- a/src/test/ui/suggestions/const-no-type.stderr +++ b/src/test/ui/suggestions/const-no-type.stderr @@ -14,7 +14,7 @@ error: missing type for `static mut` item --> $DIR/const-no-type.rs:43:12 | LL | static mut SM = "abc"; - | ^^ help: provide a type for the item: `SM: &'static str` + | ^^ help: provide a type for the item: `SM: &str` error: missing type for `const` item --> $DIR/const-no-type.rs:14:7 diff --git a/src/test/ui/test-attrs/test-attr-non-associated-functions.rs b/src/test/ui/test-attrs/test-attr-non-associated-functions.rs index e475f5b4a75a5..31e567c396067 100644 --- a/src/test/ui/test-attrs/test-attr-non-associated-functions.rs +++ b/src/test/ui/test-attrs/test-attr-non-associated-functions.rs @@ -6,7 +6,13 @@ struct A {} impl A { #[test] - fn new() -> A { //~ ERROR `#[test]` attribute is only allowed on non associated functions + fn new() -> A { + //~^ ERROR `#[test]` attribute is only allowed on non associated functions + A {} + } + #[test] + fn recovery_witness() -> A { + //~^ ERROR `#[test]` attribute is only allowed on non associated functions A {} } } diff --git a/src/test/ui/test-attrs/test-attr-non-associated-functions.stderr b/src/test/ui/test-attrs/test-attr-non-associated-functions.stderr index cb3ae51823e45..a81b8f3980c37 100644 --- a/src/test/ui/test-attrs/test-attr-non-associated-functions.stderr +++ b/src/test/ui/test-attrs/test-attr-non-associated-functions.stderr @@ -2,9 +2,19 @@ error: `#[test]` attribute is only allowed on non associated functions --> $DIR/test-attr-non-associated-functions.rs:9:5 | LL | / fn new() -> A { +LL | | LL | | A {} LL | | } | |_____^ -error: aborting due to previous error +error: `#[test]` attribute is only allowed on non associated functions + --> $DIR/test-attr-non-associated-functions.rs:14:5 + | +LL | / fn recovery_witness() -> A { +LL | | +LL | | A {} +LL | | } + | |_____^ + +error: aborting due to 2 previous errors diff --git a/src/test/ui/transmute/main.stderr b/src/test/ui/transmute/main.stderr index c72876e050f05..4e781318329bf 100644 --- a/src/test/ui/transmute/main.stderr +++ b/src/test/ui/transmute/main.stderr @@ -4,8 +4,7 @@ error[E0512]: cannot transmute between types of different sizes, or dependently- LL | transmute(x) | ^^^^^^^^^ | - = note: source type: `>::T` (size can vary because of ::T) - = note: target type: `>::T` (size can vary because of ::T) + = note: `::T` does not have a fixed size error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/main.rs:20:17 diff --git a/src/test/ui/type/ascription/issue-47666.rs b/src/test/ui/type/ascription/issue-47666.rs index ceb1dd89daea9..8035de4a48a92 100644 --- a/src/test/ui/type/ascription/issue-47666.rs +++ b/src/test/ui/type/ascription/issue-47666.rs @@ -1,5 +1,7 @@ fn main() { let _ = Option:Some(vec![0, 1]); //~ ERROR expected type, found + //~^ ERROR expected value, found enum `Option` + //~| ERROR expected type, found variant `Some` } // This case isn't currently being handled gracefully due to the macro invocation. diff --git a/src/test/ui/type/ascription/issue-47666.stderr b/src/test/ui/type/ascription/issue-47666.stderr index f4c9240ab5372..3cd3be70aa75b 100644 --- a/src/test/ui/type/ascription/issue-47666.stderr +++ b/src/test/ui/type/ascription/issue-47666.stderr @@ -13,5 +13,35 @@ LL | let _ = Option:Some(vec![0, 1]); = note: see issue #23416 for more information = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error[E0423]: expected value, found enum `Option` + --> $DIR/issue-47666.rs:2:13 + | +LL | let _ = Option:Some(vec![0, 1]); + | ^^^^^^ + | +help: try using one of the enum's variants + | +LL | let _ = std::option::Option::None:Some(vec![0, 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _ = std::option::Option::Some:Some(vec![0, 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0573]: expected type, found variant `Some` + --> $DIR/issue-47666.rs:2:20 + | +LL | let _ = Option:Some(vec![0, 1]); + | ^^^^^^^^^^^^^^^^ not a type + | +help: try using the variant's enum + | +LL | let _ = Option:std::option::Option; + | ^^^^^^^^^^^^^^^^^^^ +help: maybe you meant to write a path separator here + | +LL | let _ = Option::Some(vec![0, 1]); + | ^^ + +error: aborting due to 3 previous errors +Some errors have detailed explanations: E0423, E0573. +For more information about an error, try `rustc --explain E0423`. diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.stderr b/src/test/ui/typeck/typeck_type_placeholder_item.stderr index f2d02f70f4a66..dc86ab30dfe41 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item.stderr +++ b/src/test/ui/typeck/typeck_type_placeholder_item.stderr @@ -70,7 +70,7 @@ LL | static TEST3: _ = "test"; | ^ | | | not allowed in type signatures - | help: replace `_` with the correct type: `&'static str` + | help: replace `_` with the correct type: `&str` error[E0121]: the type placeholder `_` is not allowed within types on item signatures --> $DIR/typeck_type_placeholder_item.rs:15:15 @@ -232,7 +232,7 @@ LL | static FN_TEST3: _ = "test"; | ^ | | | not allowed in type signatures - | help: replace `_` with the correct type: `&'static str` + | help: replace `_` with the correct type: `&str` error[E0121]: the type placeholder `_` is not allowed within types on item signatures --> $DIR/typeck_type_placeholder_item.rs:88:22 diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 7a20a96130ccb..54b42bd34c69c 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -134,6 +134,7 @@ const WHITELIST: &[Crate<'_>] = &[ Crate("polonius-engine"), Crate("ppv-lite86"), Crate("proc-macro2"), + Crate("psm"), Crate("punycode"), Crate("quick-error"), Crate("quote"), @@ -162,6 +163,7 @@ const WHITELIST: &[Crate<'_>] = &[ Crate("serde_derive"), Crate("smallvec"), Crate("stable_deref_trait"), + Crate("stacker"), Crate("syn"), Crate("synstructure"), Crate("tempfile"),