diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7c17dfd8c8edc..44f789c592ba2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -322,7 +322,7 @@ jobs: NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 DIST_REQUIRE_ALL_TOOLS: 1 - os: macos-latest + os: macos-12-xl - name: dist-apple-various env: SCRIPT: "./x.py dist bootstrap --include-default-paths --host='' --target=aarch64-apple-ios,x86_64-apple-ios,aarch64-apple-ios-sim" @@ -333,7 +333,7 @@ jobs: NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 - os: macos-latest + os: macos-12-xl - name: dist-x86_64-apple-alt env: SCRIPT: "./x.py dist bootstrap --include-default-paths" @@ -344,7 +344,7 @@ jobs: NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 - os: macos-latest + os: macos-12-xl - name: x86_64-apple-1 env: SCRIPT: "./x.py --stage 2 test --exclude tests/ui --exclude tests/rustdoc --exclude tests/run-make-fulldeps" @@ -355,7 +355,7 @@ jobs: NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 - os: macos-latest + os: macos-12-xl - name: x86_64-apple-2 env: SCRIPT: "./x.py --stage 2 test tests/ui tests/rustdoc tests/run-make-fulldeps" @@ -366,7 +366,7 @@ jobs: NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 - os: macos-latest + os: macos-12-xl - name: dist-aarch64-apple env: SCRIPT: "./x.py dist bootstrap --include-default-paths --stage 2" @@ -381,7 +381,7 @@ jobs: NO_OVERFLOW_CHECKS: 1 DIST_REQUIRE_ALL_TOOLS: 1 JEMALLOC_SYS_WITH_LG_PAGE: 14 - os: macos-latest + os: macos-12-xl - name: x86_64-msvc-1 env: RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --enable-profiler" diff --git a/compiler/rustc_builtin_macros/src/env.rs b/compiler/rustc_builtin_macros/src/env.rs index 6aa900f020163..f011cb754cb4a 100644 --- a/compiler/rustc_builtin_macros/src/env.rs +++ b/compiler/rustc_builtin_macros/src/env.rs @@ -53,7 +53,7 @@ pub fn expand_env<'cx>( tts: TokenStream, ) -> Box { let mut exprs = match get_exprs_from_tts(cx, tts) { - Some(exprs) if exprs.is_empty() => { + Some(exprs) if exprs.is_empty() || exprs.len() > 2 => { cx.span_err(sp, "env! takes 1 or 2 arguments"); return DummyResult::any(sp); } @@ -64,28 +64,48 @@ pub fn expand_env<'cx>( let Some((var, _style)) = expr_to_string(cx, exprs.next().unwrap(), "expected string literal") else { return DummyResult::any(sp); }; - let msg = match exprs.next() { - None => Symbol::intern(&format!("environment variable `{}` not defined", var)), + + let custom_msg = match exprs.next() { + None => None, Some(second) => match expr_to_string(cx, second, "expected string literal") { None => return DummyResult::any(sp), - Some((s, _style)) => s, + Some((s, _style)) => Some(s), }, }; - if exprs.next().is_some() { - cx.span_err(sp, "env! takes 1 or 2 arguments"); - return DummyResult::any(sp); - } - let sp = cx.with_def_site_ctxt(sp); let value = env::var(var.as_str()).ok().as_deref().map(Symbol::intern); cx.sess.parse_sess.env_depinfo.borrow_mut().insert((var, value)); let e = match value { None => { - cx.span_err(sp, msg.as_str()); + let (msg, help) = match custom_msg { + None => ( + format!("environment variable `{var}` not defined at compile time"), + Some(help_for_missing_env_var(var.as_str())), + ), + Some(s) => (s.to_string(), None), + }; + let mut diag = cx.struct_span_err(sp, &msg); + if let Some(help) = help { + diag.help(help); + } + diag.emit(); return DummyResult::any(sp); } Some(value) => cx.expr_str(sp, value), }; MacEager::expr(e) } + +fn help_for_missing_env_var(var: &str) -> String { + if var.starts_with("CARGO_") + || var.starts_with("DEP_") + || matches!(var, "OUT_DIR" | "OPT_LEVEL" | "PROFILE" | "HOST" | "TARGET") + { + format!( + "Cargo sets build script variables at run time. Use `std::env::var(\"{var}\")` instead" + ) + } else { + format!("Use `std::env::var(\"{var}\")` to read the variable at run time") + } +} diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 450488315ef01..92fa59aec6e5f 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -16,8 +16,8 @@ use rustc_target::spec::abi::Abi as CallAbi; use crate::const_eval::CheckAlignment; use super::{ - AllocId, AllocRange, Allocation, ConstAllocation, Frame, ImmTy, InterpCx, InterpResult, - MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar, StackPopUnwind, + AllocBytes, AllocId, AllocRange, Allocation, ConstAllocation, Frame, ImmTy, InterpCx, + InterpResult, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar, StackPopUnwind, }; /// Data returned by Machine::stack_pop, @@ -105,10 +105,16 @@ pub trait Machine<'mir, 'tcx>: Sized { /// Extra data stored in every allocation. type AllocExtra: Debug + Clone + 'static; + /// Type for the bytes of the allocation. + type Bytes: AllocBytes + 'static; + /// Memory's allocation map type MemoryMap: AllocMap< AllocId, - (MemoryKind, Allocation), + ( + MemoryKind, + Allocation, + ), > + Default + Clone; @@ -338,7 +344,7 @@ pub trait Machine<'mir, 'tcx>: Sized { id: AllocId, alloc: Cow<'b, Allocation>, kind: Option>, - ) -> InterpResult<'tcx, Cow<'b, Allocation>>; + ) -> InterpResult<'tcx, Cow<'b, Allocation>>; fn eval_inline_asm( _ecx: &mut InterpCx<'mir, 'tcx, Self>, @@ -459,6 +465,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) { type AllocExtra = (); type FrameExtra = (); + type Bytes = Box<[u8]>; #[inline(always)] fn use_addr_for_alignment_check(_ecx: &InterpCx<$mir, $tcx, Self>) -> bool { diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index f4e03ad8c593d..a3764a7d14266 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -21,8 +21,9 @@ use rustc_target::abi::{Align, HasDataLayout, Size}; use crate::const_eval::CheckAlignment; use super::{ - alloc_range, AllocId, AllocMap, AllocRange, Allocation, CheckInAllocMsg, GlobalAlloc, InterpCx, - InterpResult, Machine, MayLeak, Pointer, PointerArithmetic, Provenance, Scalar, + alloc_range, AllocBytes, AllocId, AllocMap, AllocRange, Allocation, CheckInAllocMsg, + GlobalAlloc, InterpCx, InterpResult, Machine, MayLeak, Pointer, PointerArithmetic, Provenance, + Scalar, }; #[derive(Debug, PartialEq, Copy, Clone)] @@ -114,16 +115,16 @@ pub struct Memory<'mir, 'tcx, M: Machine<'mir, 'tcx>> { /// A reference to some allocation that was already bounds-checked for the given region /// and had the on-access machine hooks run. #[derive(Copy, Clone)] -pub struct AllocRef<'a, 'tcx, Prov: Provenance, Extra> { - alloc: &'a Allocation, +pub struct AllocRef<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes = Box<[u8]>> { + alloc: &'a Allocation, range: AllocRange, tcx: TyCtxt<'tcx>, alloc_id: AllocId, } /// A reference to some allocation that was already bounds-checked for the given region /// and had the on-access machine hooks run. -pub struct AllocRefMut<'a, 'tcx, Prov: Provenance, Extra> { - alloc: &'a mut Allocation, +pub struct AllocRefMut<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes = Box<[u8]>> { + alloc: &'a mut Allocation, range: AllocRange, tcx: TyCtxt<'tcx>, alloc_id: AllocId, @@ -483,7 +484,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { &self, id: AllocId, is_write: bool, - ) -> InterpResult<'tcx, Cow<'tcx, Allocation>> { + ) -> InterpResult<'tcx, Cow<'tcx, Allocation>> { let (alloc, def_id) = match self.tcx.try_get_global_alloc(id) { Some(GlobalAlloc::Memory(mem)) => { // Memory of a constant or promoted or anonymous memory referenced by a static. @@ -526,6 +527,17 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ) } + /// Get the base address for the bytes in an `Allocation` specified by the + /// `AllocID` passed in; error if no such allocation exists. + /// + /// It is up to the caller to take sufficient care when using this address: + /// there could be provenance or uninit memory in there, and other memory + /// accesses could invalidate the exposed pointer. + pub fn alloc_base_addr(&self, id: AllocId) -> InterpResult<'tcx, *const u8> { + let alloc = self.get_alloc_raw(id)?; + Ok(alloc.base_addr()) + } + /// Gives raw access to the `Allocation`, without bounds or alignment checks. /// The caller is responsible for calling the access hooks! /// @@ -533,7 +545,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { fn get_alloc_raw( &self, id: AllocId, - ) -> InterpResult<'tcx, &Allocation> { + ) -> InterpResult<'tcx, &Allocation> { // The error type of the inner closure here is somewhat funny. We have two // ways of "erroring": An actual error, or because we got a reference from // `get_global_alloc` that we can actually use directly without inserting anything anywhere. @@ -569,7 +581,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ptr: Pointer>, size: Size, align: Align, - ) -> InterpResult<'tcx, Option>> { + ) -> InterpResult<'tcx, Option>> + { let ptr_and_alloc = self.check_and_deref_ptr( ptr, size, @@ -612,7 +625,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { fn get_alloc_raw_mut( &mut self, id: AllocId, - ) -> InterpResult<'tcx, (&mut Allocation, &mut M)> { + ) -> InterpResult<'tcx, (&mut Allocation, &mut M)> { // We have "NLL problem case #3" here, which cannot be worked around without loss of // efficiency even for the common case where the key is in the map. // @@ -641,7 +654,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ptr: Pointer>, size: Size, align: Align, - ) -> InterpResult<'tcx, Option>> { + ) -> InterpResult<'tcx, Option>> + { let parts = self.get_ptr_access(ptr, size, align)?; if let Some((alloc_id, offset, prov)) = parts { let tcx = *self.tcx; @@ -840,11 +854,11 @@ pub struct DumpAllocs<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> { impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> std::fmt::Debug for DumpAllocs<'a, 'mir, 'tcx, M> { fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { // Cannot be a closure because it is generic in `Prov`, `Extra`. - fn write_allocation_track_relocs<'tcx, Prov: Provenance, Extra>( + fn write_allocation_track_relocs<'tcx, Prov: Provenance, Extra, Bytes: AllocBytes>( fmt: &mut std::fmt::Formatter<'_>, tcx: TyCtxt<'tcx>, allocs_to_print: &mut VecDeque, - alloc: &Allocation, + alloc: &Allocation, ) -> std::fmt::Result { for alloc_id in alloc.provenance().provenances().filter_map(|prov| prov.get_alloc_id()) { @@ -912,7 +926,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> std::fmt::Debug for DumpAllocs<'a, } /// Reading and writing. -impl<'tcx, 'a, Prov: Provenance, Extra> AllocRefMut<'a, 'tcx, Prov, Extra> { +impl<'tcx, 'a, Prov: Provenance, Extra, Bytes: AllocBytes> + AllocRefMut<'a, 'tcx, Prov, Extra, Bytes> +{ /// `range` is relative to this allocation reference, not the base of the allocation. pub fn write_scalar(&mut self, range: AllocRange, val: Scalar) -> InterpResult<'tcx> { let range = self.range.subrange(range); @@ -937,7 +953,7 @@ impl<'tcx, 'a, Prov: Provenance, Extra> AllocRefMut<'a, 'tcx, Prov, Extra> { } } -impl<'tcx, 'a, Prov: Provenance, Extra> AllocRef<'a, 'tcx, Prov, Extra> { +impl<'tcx, 'a, Prov: Provenance, Extra, Bytes: AllocBytes> AllocRef<'a, 'tcx, Prov, Extra, Bytes> { /// `range` is relative to this allocation reference, not the base of the allocation. pub fn read_scalar( &self, diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 244fa8030af73..3c463500a609e 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -353,7 +353,8 @@ where pub(super) fn get_place_alloc( &self, place: &MPlaceTy<'tcx, M::Provenance>, - ) -> InterpResult<'tcx, Option>> { + ) -> InterpResult<'tcx, Option>> + { assert!(place.layout.is_sized()); assert!(!place.meta.has_meta()); let size = place.layout.size; @@ -364,7 +365,8 @@ where pub(super) fn get_place_alloc_mut( &mut self, place: &MPlaceTy<'tcx, M::Provenance>, - ) -> InterpResult<'tcx, Option>> { + ) -> InterpResult<'tcx, Option>> + { assert!(place.layout.is_sized()); assert!(!place.meta.has_meta()); let size = place.layout.size; diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs index d64492e503db0..b09886fe3a96a 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs @@ -714,12 +714,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.parent(expr_ctor_def_id) } hir::def::DefKind::Ctor(hir::def::CtorOf::Variant, hir::def::CtorKind::Fn) => { - // If this is a variant, its parent is the type definition. - if in_ty_adt.did() != self.tcx.parent(expr_ctor_def_id) { + // For a typical enum like + // `enum Blah { Variant(T) }` + // we get the following resolutions: + // - expr_ctor_def_id ::: DefId(0:29 ~ source_file[b442]::Blah::Variant::{constructor#0}) + // - self.tcx.parent(expr_ctor_def_id) ::: DefId(0:28 ~ source_file[b442]::Blah::Variant) + // - self.tcx.parent(self.tcx.parent(expr_ctor_def_id)) ::: DefId(0:26 ~ source_file[b442]::Blah) + + // Therefore, we need to go up once to obtain the variant and up twice to obtain the type. + // Note that this pattern still holds even when we `use` a variant or `use` an enum type to rename it, or chain `use` expressions + // together; this resolution is handled automatically by `qpath_res`. + + // FIXME: Deal with type aliases? + if in_ty_adt.did() == self.tcx.parent(self.tcx.parent(expr_ctor_def_id)) { + // The constructor definition refers to the "constructor" of the variant: + // For example, `Some(5)` triggers this case. + self.tcx.parent(expr_ctor_def_id) + } else { // FIXME: Deal with type aliases? return Err(expr); } - expr_ctor_def_id } _ => { return Err(expr); diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 221105ac48f79..48375ed301d22 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -8,7 +8,8 @@ mod tests; use std::borrow::Cow; use std::fmt; use std::hash; -use std::ops::Range; +use std::hash::Hash; +use std::ops::{Deref, DerefMut, Range}; use std::ptr; use either::{Left, Right}; @@ -29,6 +30,39 @@ use provenance_map::*; pub use init_mask::{InitChunk, InitChunkIter}; +/// Functionality required for the bytes of an `Allocation`. +pub trait AllocBytes: + Clone + fmt::Debug + Eq + PartialEq + Hash + Deref + DerefMut +{ + /// Adjust the bytes to the specified alignment -- by default, this is a no-op. + fn adjust_to_align(self, _align: Align) -> Self; + + /// Create an `AllocBytes` from a slice of `u8`. + fn from_bytes<'a>(slice: impl Into>, _align: Align) -> Self; + + /// Create a zeroed `AllocBytes` of the specified size and alignment; + /// call the callback error handler if there is an error in allocating the memory. + fn zeroed(size: Size, _align: Align) -> Option; +} + +// Default `bytes` for `Allocation` is a `Box<[u8]>`. +impl AllocBytes for Box<[u8]> { + fn adjust_to_align(self, _align: Align) -> Self { + self + } + + fn from_bytes<'a>(slice: impl Into>, _align: Align) -> Self { + Box::<[u8]>::from(slice.into()) + } + + fn zeroed(size: Size, _align: Align) -> Option { + let bytes = Box::<[u8]>::try_new_zeroed_slice(size.bytes_usize()).ok()?; + // SAFETY: the box was zero-allocated, which is a valid initial value for Box<[u8]> + let bytes = unsafe { bytes.assume_init() }; + Some(bytes) + } +} + /// This type represents an Allocation in the Miri/CTFE core engine. /// /// Its public API is rather low-level, working directly with allocation offsets and a custom error @@ -38,10 +72,10 @@ pub use init_mask::{InitChunk, InitChunkIter}; // hashed. (see the `Hash` impl below for more details), so the impl is not derived. #[derive(Clone, Eq, PartialEq, TyEncodable, TyDecodable)] #[derive(HashStable)] -pub struct Allocation { +pub struct Allocation> { /// The actual bytes of the allocation. /// Note that the bytes of a pointer represent the offset of the pointer. - bytes: Box<[u8]>, + bytes: Bytes, /// Maps from byte addresses to extra provenance data for each pointer. /// Only the first byte of a pointer is inserted into the map; i.e., /// every entry in this map applies to `pointer_size` consecutive bytes starting @@ -220,14 +254,27 @@ impl AllocRange { } // The constructors are all without extra; the extra gets added by a machine hook later. -impl Allocation { +impl Allocation { + /// Creates an allocation from an existing `Bytes` value - this is needed for miri FFI support + pub fn from_raw_bytes(bytes: Bytes, align: Align, mutability: Mutability) -> Self { + let size = Size::from_bytes(bytes.len()); + Self { + bytes, + provenance: ProvenanceMap::new(), + init_mask: InitMask::new(size, true), + align, + mutability, + extra: (), + } + } + /// Creates an allocation initialized by the given bytes pub fn from_bytes<'a>( slice: impl Into>, align: Align, mutability: Mutability, ) -> Self { - let bytes = Box::<[u8]>::from(slice.into()); + let bytes = Bytes::from_bytes(slice, align); let size = Size::from_bytes(bytes.len()); Self { bytes, @@ -248,7 +295,7 @@ impl Allocation { /// /// If `panic_on_fail` is true, this will never return `Err`. pub fn uninit<'tcx>(size: Size, align: Align, panic_on_fail: bool) -> InterpResult<'tcx, Self> { - let bytes = Box::<[u8]>::try_new_zeroed_slice(size.bytes_usize()).map_err(|_| { + let bytes = Bytes::zeroed(size, align).ok_or_else(|| { // This results in an error that can happen non-deterministically, since the memory // available to the compiler can change between runs. Normally queries are always // deterministic. However, we can be non-deterministic here because all uses of const @@ -262,8 +309,7 @@ impl Allocation { }); InterpError::ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted) })?; - // SAFETY: the box was zero-allocated, which is a valid initial value for Box<[u8]> - let bytes = unsafe { bytes.assume_init() }; + Ok(Allocation { bytes, provenance: ProvenanceMap::new(), @@ -275,7 +321,7 @@ impl Allocation { } } -impl Allocation { +impl Allocation { /// Adjust allocation from the ones in tcx to a custom Machine instance /// with a different Provenance and Extra type. pub fn adjust_from_tcx( @@ -283,9 +329,11 @@ impl Allocation { cx: &impl HasDataLayout, extra: Extra, mut adjust_ptr: impl FnMut(Pointer) -> Result, Err>, - ) -> Result, Err> { - // Compute new pointer provenance, which also adjusts the bytes. - let mut bytes = self.bytes; + ) -> Result, Err> { + // Compute new pointer provenance, which also adjusts the bytes, and realign the pointer if + // necessary. + let mut bytes = self.bytes.adjust_to_align(self.align); + let mut new_provenance = Vec::with_capacity(self.provenance.ptrs().len()); let ptr_size = cx.data_layout().pointer_size.bytes_usize(); let endian = cx.data_layout().endian; @@ -311,7 +359,7 @@ impl Allocation { } /// Raw accessors. Provide access to otherwise private bytes. -impl Allocation { +impl Allocation { pub fn len(&self) -> usize { self.bytes.len() } @@ -340,7 +388,11 @@ impl Allocation { } /// Byte accessors. -impl Allocation { +impl Allocation { + pub fn base_addr(&self) -> *const u8 { + self.bytes.as_ptr() + } + /// This is the entirely abstraction-violating way to just grab the raw bytes without /// caring about provenance or initialization. /// @@ -412,7 +464,7 @@ impl Allocation { } /// Reading and writing. -impl Allocation { +impl Allocation { /// Sets the init bit for the given range. fn mark_init(&mut self, range: AllocRange, is_init: bool) { if range.size.bytes() == 0 { diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index b0975616b6151..1766d7a669804 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -127,8 +127,8 @@ pub use self::error::{ pub use self::value::{get_slice_bytes, ConstAlloc, ConstValue, Scalar}; pub use self::allocation::{ - alloc_range, AllocError, AllocRange, AllocResult, Allocation, ConstAllocation, InitChunk, - InitChunkIter, + alloc_range, AllocBytes, AllocError, AllocRange, AllocResult, Allocation, ConstAllocation, + InitChunk, InitChunkIter, }; pub use self::pointer::{Pointer, PointerArithmetic, Provenance}; diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 16daf63b82d9f..d8829e3e782c5 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -12,8 +12,8 @@ use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::DefId; use rustc_index::vec::Idx; use rustc_middle::mir::interpret::{ - alloc_range, read_target_uint, AllocId, Allocation, ConstAllocation, ConstValue, GlobalAlloc, - Pointer, Provenance, + alloc_range, read_target_uint, AllocBytes, AllocId, Allocation, ConstAllocation, ConstValue, + GlobalAlloc, Pointer, Provenance, }; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::*; @@ -787,21 +787,21 @@ pub fn write_allocations<'tcx>( /// After the hex dump, an ascii dump follows, replacing all unprintable characters (control /// characters or characters whose value is larger than 127) with a `.` /// This also prints provenance adequately. -pub fn display_allocation<'a, 'tcx, Prov: Provenance, Extra>( +pub fn display_allocation<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes>( tcx: TyCtxt<'tcx>, - alloc: &'a Allocation, -) -> RenderAllocation<'a, 'tcx, Prov, Extra> { + alloc: &'a Allocation, +) -> RenderAllocation<'a, 'tcx, Prov, Extra, Bytes> { RenderAllocation { tcx, alloc } } #[doc(hidden)] -pub struct RenderAllocation<'a, 'tcx, Prov: Provenance, Extra> { +pub struct RenderAllocation<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes> { tcx: TyCtxt<'tcx>, - alloc: &'a Allocation, + alloc: &'a Allocation, } -impl<'a, 'tcx, Prov: Provenance, Extra> std::fmt::Display - for RenderAllocation<'a, 'tcx, Prov, Extra> +impl<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes> std::fmt::Display + for RenderAllocation<'a, 'tcx, Prov, Extra, Bytes> { fn fmt(&self, w: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let RenderAllocation { tcx, alloc } = *self; @@ -845,9 +845,9 @@ fn write_allocation_newline( /// The `prefix` argument allows callers to add an arbitrary prefix before each line (even if there /// is only one line). Note that your prefix should contain a trailing space as the lines are /// printed directly after it. -fn write_allocation_bytes<'tcx, Prov: Provenance, Extra>( +fn write_allocation_bytes<'tcx, Prov: Provenance, Extra, Bytes: AllocBytes>( tcx: TyCtxt<'tcx>, - alloc: &Allocation, + alloc: &Allocation, w: &mut dyn std::fmt::Write, prefix: &str, ) -> std::fmt::Result { diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 2b3601bec7bb3..3b11fab8cdf57 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -237,6 +237,9 @@ pub struct LocalVarId(pub hir::HirId); /// A THIR expression. #[derive(Clone, Debug, HashStable)] pub struct Expr<'tcx> { + /// kind of expression + pub kind: ExprKind<'tcx>, + /// The type of this expression pub ty: Ty<'tcx>, @@ -246,9 +249,6 @@ pub struct Expr<'tcx> { /// span of the expression in the source pub span: Span, - - /// kind of expression - pub kind: ExprKind<'tcx>, } #[derive(Clone, Debug, HashStable)] diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index efbbfe6c24b56..0648784b26570 100644 --- a/compiler/rustc_ty_utils/src/assoc.rs +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -53,9 +53,37 @@ fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] { ) } } - hir::ItemKind::Impl(ref impl_) => tcx.arena.alloc_from_iter( - impl_.items.iter().map(|impl_item_ref| impl_item_ref.id.owner_id.to_def_id()), - ), + hir::ItemKind::Impl(ref impl_) => { + if tcx.sess.opts.unstable_opts.lower_impl_trait_in_trait_to_assoc_ty { + // We collect RPITITs for each trait method's return type, on the impl side too and + // create a corresponding associated item using + // associated_items_for_impl_trait_in_trait query. + tcx.arena.alloc_from_iter( + impl_ + .items + .iter() + .map(|impl_item_ref| impl_item_ref.id.owner_id.to_def_id()) + .chain(impl_.of_trait.iter().flat_map(|_| { + impl_ + .items + .iter() + .filter(|impl_item_ref| { + matches!(impl_item_ref.kind, hir::AssocItemKind::Fn { .. }) + }) + .flat_map(|impl_item_ref| { + let impl_fn_def_id = + impl_item_ref.id.owner_id.def_id.to_def_id(); + tcx.associated_items_for_impl_trait_in_trait(impl_fn_def_id) + }) + .map(|def_id| *def_id) + })), + ) + } else { + tcx.arena.alloc_from_iter( + impl_.items.iter().map(|impl_item_ref| impl_item_ref.id.owner_id.to_def_id()), + ) + } + } _ => span_bug!(item.span, "associated_item_def_ids: not impl or trait"), } } @@ -290,8 +318,40 @@ fn impl_associated_item_for_impl_trait_in_trait( ) -> LocalDefId { let impl_def_id = tcx.local_parent(impl_fn_def_id); - let span = tcx.def_span(trait_assoc_def_id); + // FIXME fix the span, we probably want the def_id of the return type of the function + let span = tcx.def_span(impl_fn_def_id); let impl_assoc_ty = tcx.at(span).create_def(impl_def_id, DefPathData::ImplTraitAssocTy); - impl_assoc_ty.def_id() + let local_def_id = impl_assoc_ty.def_id(); + let def_id = local_def_id.to_def_id(); + + impl_assoc_ty.opt_def_kind(Some(DefKind::AssocTy)); + + // There's no HIR associated with this new synthesized `def_id`, so feed + // `opt_local_def_id_to_hir_id` with `None`. + impl_assoc_ty.opt_local_def_id_to_hir_id(None); + + // Add the def_id of the function that generated this synthesized associated type. + impl_assoc_ty.opt_rpitit_info(Some(ImplTraitInTraitData::Impl { + fn_def_id: impl_fn_def_id.to_def_id(), + })); + + impl_assoc_ty.associated_item(ty::AssocItem { + name: kw::Empty, + kind: ty::AssocKind::Type, + def_id, + trait_item_def_id: Some(trait_assoc_def_id.to_def_id()), + container: ty::ImplContainer, + fn_has_self_parameter: false, + }); + + // Copy impl_defaultness of the containing function. + impl_assoc_ty.impl_defaultness(tcx.impl_defaultness(impl_fn_def_id)); + + // Copy generics_of the trait's associated item. + // FIXME: This is not correct, in particular the parent is going to be wrong. So we would need + // to copy from trait_assoc_def_id and adjust things. + impl_assoc_ty.generics_of(tcx.generics_of(trait_assoc_def_id).clone()); + + local_def_id } diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index 04e798e3949d9..ab3d08292961f 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -442,6 +442,8 @@ def to_toml(value): return value else: return "'" + value + "'" + elif isinstance(value, dict): + return "{" + ", ".join(map(lambda a: "{} = {}".format(to_toml(a[0]), to_toml(a[1])), value.items())) + "}" else: raise RuntimeError('no toml') diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index ad9c308ad852d..11f1532bef594 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -78,7 +78,7 @@ x--expand-yaml-anchors--remove: <<: *base-job - &job-macos-xl - os: macos-latest # We don't have an XL builder for this + os: macos-12-xl <<: *base-job - &job-windows-xl diff --git a/src/librustdoc/html/static/.eslintrc.js b/src/librustdoc/html/static/.eslintrc.js index fcd925bb3582f..1a34530c2d16e 100644 --- a/src/librustdoc/html/static/.eslintrc.js +++ b/src/librustdoc/html/static/.eslintrc.js @@ -90,7 +90,6 @@ module.exports = { "no-return-assign": "error", "no-script-url": "error", "no-sequences": "error", - "no-throw-literal": "error", "no-div-regex": "error", } }; diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index d18b56eb19c25..95528e70e3519 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1260,6 +1260,11 @@ a.tooltip:hover::after { color: var(--search-tab-title-count-color); } +#search .error code { + border-radius: 3px; + background-color: var(--search-error-code-background-color); +} + #src-sidebar-toggle { position: sticky; top: 0; diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css index 472a725f0539d..90cf689ad3372 100644 --- a/src/librustdoc/html/static/css/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -43,6 +43,7 @@ Original by Dempfi (https://github.com/dempfi/ayu) --search-result-link-focus-background-color: #3c3c3c; --search-result-border-color: #aaa3; --search-color: #fff; + --search-error-code-background-color: #4f4c4c; --search-results-alias-color: #c5c5c5; --search-results-grey-color: #999; --search-tab-title-count-color: #888; diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css index 5612bde96a88a..e8cd069313920 100644 --- a/src/librustdoc/html/static/css/themes/dark.css +++ b/src/librustdoc/html/static/css/themes/dark.css @@ -38,6 +38,7 @@ --search-result-link-focus-background-color: #616161; --search-result-border-color: #aaa3; --search-color: #111; + --search-error-code-background-color: #484848; --search-results-alias-color: #fff; --search-results-grey-color: #ccc; --search-tab-title-count-color: #888; diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css index 34b35c405a8ee..5e3f14e483fae 100644 --- a/src/librustdoc/html/static/css/themes/light.css +++ b/src/librustdoc/html/static/css/themes/light.css @@ -38,6 +38,7 @@ --search-result-link-focus-background-color: #ccc; --search-result-border-color: #aaa3; --search-color: #000; + --search-error-code-background-color: #d0cccc; --search-results-alias-color: #000; --search-results-grey-color: #999; --search-tab-title-count-color: #888; diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 6501d32531fc1..5a46729156d19 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -144,7 +144,7 @@ function initSearch(rawSearchIndex) { function itemTypeFromName(typename) { const index = itemTypes.findIndex(i => i === typename); if (index < 0) { - throw new Error("Unknown type filter `" + typename + "`"); + throw ["Unknown type filter ", typename]; } return index; } @@ -164,21 +164,21 @@ function initSearch(rawSearchIndex) { */ function getStringElem(query, parserState, isInGenerics) { if (isInGenerics) { - throw new Error("`\"` cannot be used in generics"); + throw ["Unexpected ", "\"", " in generics"]; } else if (query.literalSearch) { - throw new Error("Cannot have more than one literal search element"); + throw ["Cannot have more than one literal search element"]; } else if (parserState.totalElems - parserState.genericsElems > 0) { - throw new Error("Cannot use literal search when there is more than one element"); + throw ["Cannot use literal search when there is more than one element"]; } parserState.pos += 1; const start = parserState.pos; const end = getIdentEndPosition(parserState); if (parserState.pos >= parserState.length) { - throw new Error("Unclosed `\"`"); + throw ["Unclosed ", "\""]; } else if (parserState.userQuery[end] !== "\"") { - throw new Error(`Unexpected \`${parserState.userQuery[end]}\` in a string element`); + throw ["Unexpected ", parserState.userQuery[end], " in a string element"]; } else if (start === end) { - throw new Error("Cannot have empty string element"); + throw ["Cannot have empty string element"]; } // To skip the quote at the end. parserState.pos += 1; @@ -257,7 +257,7 @@ function initSearch(rawSearchIndex) { return; } if (query.literalSearch && parserState.totalElems - parserState.genericsElems > 0) { - throw new Error("You cannot have more than one element if you use quotes"); + throw ["You cannot have more than one element if you use quotes"]; } const pathSegments = name.split("::"); if (pathSegments.length > 1) { @@ -266,17 +266,17 @@ function initSearch(rawSearchIndex) { if (pathSegment.length === 0) { if (i === 0) { - throw new Error("Paths cannot start with `::`"); + throw ["Paths cannot start with ", "::"]; } else if (i + 1 === len) { - throw new Error("Paths cannot end with `::`"); + throw ["Paths cannot end with ", "::"]; } - throw new Error("Unexpected `::::`"); + throw ["Unexpected ", "::::"]; } } } // In case we only have something like `

`, there is no name. if (pathSegments.length === 0 || (pathSegments.length === 1 && pathSegments[0] === "")) { - throw new Error("Found generics without a path"); + throw ["Found generics without a path"]; } parserState.totalElems += 1; if (isInGenerics) { @@ -308,15 +308,15 @@ function initSearch(rawSearchIndex) { if (!isIdentCharacter(c)) { if (c === "!") { if (foundExclamation !== -1) { - throw new Error("Cannot have more than one `!` in an ident"); + throw ["Cannot have more than one ", "!", " in an ident"]; } else if (parserState.pos + 1 < parserState.length && isIdentCharacter(parserState.userQuery[parserState.pos + 1]) ) { - throw new Error("`!` can only be at the end of an ident"); + throw ["Unexpected ", "!", ": it can only be at the end of an ident"]; } foundExclamation = parserState.pos; } else if (isErrorCharacter(c)) { - throw new Error(`Unexpected \`${c}\``); + throw ["Unexpected ", c]; } else if ( isStopCharacter(c) || isSpecialStartCharacter(c) || @@ -329,7 +329,7 @@ function initSearch(rawSearchIndex) { } if (foundExclamation !== -1) { if (start <= (end - 2)) { - throw new Error("Cannot have associated items in macros"); + throw ["Cannot have associated items in macros"]; } else { // if start == end - 1, we got the never type // while the never type has no associated macros, we still @@ -340,7 +340,7 @@ function initSearch(rawSearchIndex) { // Skip current ":". parserState.pos += 1; } else { - throw new Error(`Unexpected \`${c}\``); + throw ["Unexpected ", c]; } } parserState.pos += 1; @@ -351,8 +351,13 @@ function initSearch(rawSearchIndex) { if (parserState.typeFilter === null) { parserState.typeFilter = "macro"; } else if (parserState.typeFilter !== "macro") { - throw new Error("Invalid search type: macro `!` and " + - `\`${parserState.typeFilter}\` both specified`); + throw [ + "Invalid search type: macro ", + "!", + " and ", + parserState.typeFilter, + " both specified", + ]; } end = foundExclamation; } @@ -382,9 +387,9 @@ function initSearch(rawSearchIndex) { parserState.userQuery[parserState.pos] === "<" ) { if (isInGenerics) { - throw new Error("Unexpected `<` after `<`"); + throw ["Unexpected ", "<", " after ", "<"]; } else if (start >= end) { - throw new Error("Found generics without a path"); + throw ["Found generics without a path"]; } parserState.pos += 1; getItemsBefore(query, parserState, generics, ">"); @@ -428,21 +433,39 @@ function initSearch(rawSearchIndex) { foundStopChar = true; continue; } else if (c === ":" && isPathStart(parserState)) { - throw new Error("Unexpected `::`: paths cannot start with `::`"); + throw ["Unexpected ", "::", ": paths cannot start with ", "::"]; } else if (c === ":" || isEndCharacter(c)) { let extra = ""; if (endChar === ">") { - extra = "`<`"; + extra = "<"; } else if (endChar === "") { - extra = "`->`"; + extra = "->"; + } else { + extra = endChar; } - throw new Error("Unexpected `" + c + "` after " + extra); + throw ["Unexpected ", c, " after ", extra]; } if (!foundStopChar) { if (endChar !== "") { - throw new Error(`Expected \`,\`, \` \` or \`${endChar}\`, found \`${c}\``); + throw [ + "Expected ", + ",", // comma + ", ", + " ", // whitespace + " or ", + endChar, + ", found ", + c, + ]; } - throw new Error(`Expected \`,\` or \` \`, found \`${c}\``); + throw [ + "Expected ", + ",", // comma + " or ", + " ", // whitespace + ", found ", + c, + ]; } const posBefore = parserState.pos; getNextElem(query, parserState, elems, endChar === ">"); @@ -470,7 +493,7 @@ function initSearch(rawSearchIndex) { for (let pos = 0; pos < parserState.pos; ++pos) { if (!isIdentCharacter(query[pos]) && !isWhitespaceCharacter(query[pos])) { - throw new Error(`Unexpected \`${query[pos]}\` in type filter`); + throw ["Unexpected ", query[pos], " in type filter"]; } } } @@ -496,19 +519,19 @@ function initSearch(rawSearchIndex) { if (isReturnArrow(parserState)) { break; } - throw new Error(`Unexpected \`${c}\` (did you mean \`->\`?)`); + throw ["Unexpected ", c, " (did you mean ", "->", "?)"]; } - throw new Error(`Unexpected \`${c}\``); + throw ["Unexpected ", c]; } else if (c === ":" && !isPathStart(parserState)) { if (parserState.typeFilter !== null) { - throw new Error("Unexpected `:`"); + throw ["Unexpected ", ":"]; } if (query.elems.length === 0) { - throw new Error("Expected type filter before `:`"); + throw ["Expected type filter before ", ":"]; } else if (query.elems.length !== 1 || parserState.totalElems !== 1) { - throw new Error("Unexpected `:`"); + throw ["Unexpected ", ":"]; } else if (query.literalSearch) { - throw new Error("You cannot use quotes on type filter"); + throw ["You cannot use quotes on type filter"]; } checkExtraTypeFilterCharacters(parserState); // The type filter doesn't count as an element since it's a modifier. @@ -521,9 +544,29 @@ function initSearch(rawSearchIndex) { } if (!foundStopChar) { if (parserState.typeFilter !== null) { - throw new Error(`Expected \`,\`, \` \` or \`->\`, found \`${c}\``); + throw [ + "Expected ", + ",", // comma + ", ", + " ", // whitespace + " or ", + "->", // arrow + ", found ", + c, + ]; } - throw new Error(`Expected \`,\`, \` \`, \`:\` or \`->\`, found \`${c}\``); + throw [ + "Expected ", + ",", // comma + ", ", + " ", // whitespace + ", ", + ":", // colon + " or ", + "->", // arrow + ", found ", + c, + ]; } const before = query.elems.length; getNextElem(query, parserState, query.elems, false); @@ -540,7 +583,7 @@ function initSearch(rawSearchIndex) { getItemsBefore(query, parserState, query.returned, ""); // Nothing can come afterward! if (query.returned.length === 0) { - throw new Error("Expected at least one item after `->`"); + throw ["Expected at least one item after ", "->"]; } break; } else { @@ -694,7 +737,7 @@ function initSearch(rawSearchIndex) { } } catch (err) { query = newParsedQuery(userQuery); - query.error = err.message; + query.error = err; query.typeFilter = -1; return query; } @@ -1760,7 +1803,16 @@ function initSearch(rawSearchIndex) { let output = `

Results${crates}

`; if (results.query.error !== null) { - output += `

Query parser error: "${results.query.error}".

`; + const error = results.query.error; + error.forEach((value, index) => { + value = value.split("<").join("<").split(">").join(">"); + if (index % 2 !== 0) { + error[index] = `${value}`; + } else { + error[index] = value; + } + }); + output += `

Query parser error: "${error.join("")}".

`; output += "
" + makeTabHeader(0, "In Names", ret_others[1]) + "
"; diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 8bbf9f87b43e5..969c81f7e32be 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -777,10 +777,11 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { type Provenance = Provenance; type ProvenanceExtra = ProvenanceExtra; + type Bytes = Box<[u8]>; type MemoryMap = MonoHashMap< AllocId, - (MemoryKind, Allocation), + (MemoryKind, Allocation), >; const GLOBAL_KIND: Option = Some(MiriMemoryKind::Global); diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js index 3da4fed33e111..ea5780f66d7f7 100644 --- a/src/tools/rustdoc-js/tester.js +++ b/src/tools/rustdoc-js/tester.js @@ -138,8 +138,20 @@ function valueCheck(fullPath, expected, result, error_text, queryName) { error_text.push('==> Unknown key "' + key + '"'); break; } + let result_v = result[key]; + if (result_v !== null && key === "error") { + result_v.forEach((value, index) => { + value = value.split(" ").join(" "); + if (index % 2 === 1) { + result_v[index] = "`" + value + "`"; + } else { + result_v[index] = value; + } + }); + result_v = result_v.join(""); + } const obj_path = fullPath + (fullPath.length > 0 ? '.' : '') + key; - valueCheck(obj_path, expected[key], result[key], error_text, queryName); + valueCheck(obj_path, expected[key], result_v, error_text, queryName); } } else { expectedValue = JSON.stringify(expected); diff --git a/tests/rustdoc-gui/search-error.goml b/tests/rustdoc-gui/search-error.goml new file mode 100644 index 0000000000000..2a10a647b53c3 --- /dev/null +++ b/tests/rustdoc-gui/search-error.goml @@ -0,0 +1,39 @@ +// Checks that the crate search filtering is handled correctly and changes the results. +goto: "file://" + |DOC_PATH| + "/test_docs/index.html?search=sa'%3Bda'%3Bds" +show-text: true + +define-function: ( + "check-colors", + (theme, error_background), + block { + // Setting the theme. + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} + // We reload the page so the local storage settings are being used. + reload: + + wait-for: "#search .error code" + assert-css: ("#search .error code", {"background-color": |error_background|}) + } +) + +call-function: ( + "check-colors", + { + "theme": "ayu", + "error_background": "rgb(79, 76, 76)", + }, +) +call-function: ( + "check-colors", + { + "theme": "dark", + "error_background": "rgb(72, 72, 72)", + }, +) +call-function: ( + "check-colors", + { + "theme": "light", + "error_background": "rgb(208, 204, 204)", + }, +) diff --git a/tests/rustdoc-js-std/parser-errors.js b/tests/rustdoc-js-std/parser-errors.js index f82a2472063ce..6c5a777028335 100644 --- a/tests/rustdoc-js-std/parser-errors.js +++ b/tests/rustdoc-js-std/parser-errors.js @@ -67,7 +67,7 @@ const PARSED = [ returned: [], typeFilter: -1, userQuery: "a<\"p\">", - error: "`\"` cannot be used in generics", + error: "Unexpected `\"` in generics", }, { elems: [], @@ -373,7 +373,7 @@ const PARSED = [ returned: [], typeFilter: -1, userQuery: "a!a", - error: '`!` can only be at the end of an ident', + error: 'Unexpected `!`: it can only be at the end of an ident', }, { elems: [], diff --git a/tests/ui/errors/trait-bound-error-spans/blame-trait-error.rs b/tests/ui/errors/trait-bound-error-spans/blame-trait-error.rs index 5134c672f5f4e..0fbd851431ea6 100644 --- a/tests/ui/errors/trait-bound-error-spans/blame-trait-error.rs +++ b/tests/ui/errors/trait-bound-error-spans/blame-trait-error.rs @@ -18,11 +18,85 @@ struct Burrito { filling: F, } +impl T1 for Option {} + +impl<'a, A: T1> T1 for &'a A {} + fn want(_x: V) {} +enum ExampleTuple { + ExampleTupleVariant(T), +} +use ExampleDifferentTupleVariantName as ExampleYetAnotherTupleVariantName; +use ExampleTuple as ExampleOtherTuple; +use ExampleTuple::ExampleTupleVariant as ExampleDifferentTupleVariantName; +use ExampleTuple::*; + +impl T1 for ExampleTuple where A: T3 {} + +enum ExampleStruct { + ExampleStructVariant { field: T }, +} +use ExampleDifferentStructVariantName as ExampleYetAnotherStructVariantName; +use ExampleStruct as ExampleOtherStruct; +use ExampleStruct::ExampleStructVariant as ExampleDifferentStructVariantName; +use ExampleStruct::*; + +impl T1 for ExampleStruct where A: T3 {} + +struct ExampleActuallyTupleStruct(T, i32); +use ExampleActuallyTupleStruct as ExampleActuallyTupleStructOther; + +impl T1 for ExampleActuallyTupleStruct where A: T3 {} + fn example(q: Q) { want(Wrapper { value: Burrito { filling: q } }); //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277] + + want(Some(())); + //~^ ERROR `()` is not an iterator [E0277] + + want(Some(q)); + //~^ ERROR `Q` is not an iterator [E0277] + + want(&Some(q)); + //~^ ERROR `Q` is not an iterator [E0277] + + want(&ExampleTuple::ExampleTupleVariant(q)); + //~^ ERROR `Q: T3` is not satisfied [E0277] + + want(&ExampleTupleVariant(q)); + //~^ ERROR `Q: T3` is not satisfied [E0277] + + want(&ExampleOtherTuple::ExampleTupleVariant(q)); + //~^ ERROR `Q: T3` is not satisfied [E0277] + + want(&ExampleDifferentTupleVariantName(q)); + //~^ ERROR `Q: T3` is not satisfied [E0277] + + want(&ExampleYetAnotherTupleVariantName(q)); + //~^ ERROR `Q: T3` is not satisfied [E0277] + + want(&ExampleStruct::ExampleStructVariant { field: q }); + //~^ ERROR `Q: T3` is not satisfied [E0277] + + want(&ExampleStructVariant { field: q }); + //~^ ERROR `Q: T3` is not satisfied [E0277] + + want(&ExampleOtherStruct::ExampleStructVariant { field: q }); + //~^ ERROR `Q: T3` is not satisfied [E0277] + + want(&ExampleDifferentStructVariantName { field: q }); + //~^ ERROR `Q: T3` is not satisfied [E0277] + + want(&ExampleYetAnotherStructVariantName { field: q }); + //~^ ERROR `Q: T3` is not satisfied [E0277] + + want(&ExampleActuallyTupleStruct(q, 0)); + //~^ ERROR `Q: T3` is not satisfied [E0277] + + want(&ExampleActuallyTupleStructOther(q, 0)); + //~^ ERROR `Q: T3` is not satisfied [E0277] } fn main() {} diff --git a/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr b/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr index 27b002db1306a..9228a047e8785 100644 --- a/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr +++ b/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `Q: T3` is not satisfied - --> $DIR/blame-trait-error.rs:24:46 + --> $DIR/blame-trait-error.rs:53:46 | LL | want(Wrapper { value: Burrito { filling: q } }); | ---- ^ the trait `T3` is not implemented for `Q` @@ -21,7 +21,7 @@ LL | impl T1 for Wrapper {} | | | unsatisfied trait bound introduced here note: required by a bound in `want` - --> $DIR/blame-trait-error.rs:21:12 + --> $DIR/blame-trait-error.rs:25:12 | LL | fn want(_x: V) {} | ^^ required by this bound in `want` @@ -30,6 +30,373 @@ help: consider restricting type parameter `Q` LL | fn example(q: Q) { | ++++ -error: aborting due to previous error +error[E0277]: `()` is not an iterator + --> $DIR/blame-trait-error.rs:56:15 + | +LL | want(Some(())); + | ---- ^^ `()` is not an iterator + | | + | required by a bound introduced by this call + | + = help: the trait `Iterator` is not implemented for `()` + = help: the trait `T1` is implemented for `Option` +note: required for `Option<()>` to implement `T1` + --> $DIR/blame-trait-error.rs:21:20 + | +LL | impl T1 for Option {} + | -------- ^^ ^^^^^^^^^^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `want` + --> $DIR/blame-trait-error.rs:25:12 + | +LL | fn want(_x: V) {} + | ^^ required by this bound in `want` + +error[E0277]: `Q` is not an iterator + --> $DIR/blame-trait-error.rs:59:15 + | +LL | want(Some(q)); + | ---- ^ `Q` is not an iterator + | | + | required by a bound introduced by this call + | +note: required for `Option` to implement `T1` + --> $DIR/blame-trait-error.rs:21:20 + | +LL | impl T1 for Option {} + | -------- ^^ ^^^^^^^^^^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `want` + --> $DIR/blame-trait-error.rs:25:12 + | +LL | fn want(_x: V) {} + | ^^ required by this bound in `want` +help: consider restricting type parameter `Q` + | +LL | fn example(q: Q) { + | +++++++++++++++++++++ + +error[E0277]: `Q` is not an iterator + --> $DIR/blame-trait-error.rs:62:16 + | +LL | want(&Some(q)); + | ---- ^ `Q` is not an iterator + | | + | required by a bound introduced by this call + | +note: required for `Option` to implement `T1` + --> $DIR/blame-trait-error.rs:21:20 + | +LL | impl T1 for Option {} + | -------- ^^ ^^^^^^^^^^ + | | + | unsatisfied trait bound introduced here + = note: 1 redundant requirement hidden + = note: required for `&Option` to implement `T1` +note: required by a bound in `want` + --> $DIR/blame-trait-error.rs:25:12 + | +LL | fn want(_x: V) {} + | ^^ required by this bound in `want` +help: consider restricting type parameter `Q` + | +LL | fn example(q: Q) { + | +++++++++++++++++++++ + +error[E0277]: the trait bound `Q: T3` is not satisfied + --> $DIR/blame-trait-error.rs:65:45 + | +LL | want(&ExampleTuple::ExampleTupleVariant(q)); + | ---- ^ the trait `T3` is not implemented for `Q` + | | + | required by a bound introduced by this call + | +note: required for `ExampleTuple` to implement `T1` + --> $DIR/blame-trait-error.rs:35:9 + | +LL | impl T1 for ExampleTuple where A: T3 {} + | ^^ ^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here + = note: 1 redundant requirement hidden + = note: required for `&ExampleTuple` to implement `T1` +note: required by a bound in `want` + --> $DIR/blame-trait-error.rs:25:12 + | +LL | fn want(_x: V) {} + | ^^ required by this bound in `want` +help: consider restricting type parameter `Q` + | +LL | fn example(q: Q) { + | ++++ + +error[E0277]: the trait bound `Q: T3` is not satisfied + --> $DIR/blame-trait-error.rs:68:31 + | +LL | want(&ExampleTupleVariant(q)); + | ---- ^ the trait `T3` is not implemented for `Q` + | | + | required by a bound introduced by this call + | +note: required for `ExampleTuple` to implement `T1` + --> $DIR/blame-trait-error.rs:35:9 + | +LL | impl T1 for ExampleTuple where A: T3 {} + | ^^ ^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here + = note: 1 redundant requirement hidden + = note: required for `&ExampleTuple` to implement `T1` +note: required by a bound in `want` + --> $DIR/blame-trait-error.rs:25:12 + | +LL | fn want(_x: V) {} + | ^^ required by this bound in `want` +help: consider restricting type parameter `Q` + | +LL | fn example(q: Q) { + | ++++ + +error[E0277]: the trait bound `Q: T3` is not satisfied + --> $DIR/blame-trait-error.rs:71:50 + | +LL | want(&ExampleOtherTuple::ExampleTupleVariant(q)); + | ---- ^ the trait `T3` is not implemented for `Q` + | | + | required by a bound introduced by this call + | +note: required for `ExampleTuple` to implement `T1` + --> $DIR/blame-trait-error.rs:35:9 + | +LL | impl T1 for ExampleTuple where A: T3 {} + | ^^ ^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here + = note: 1 redundant requirement hidden + = note: required for `&ExampleTuple` to implement `T1` +note: required by a bound in `want` + --> $DIR/blame-trait-error.rs:25:12 + | +LL | fn want(_x: V) {} + | ^^ required by this bound in `want` +help: consider restricting type parameter `Q` + | +LL | fn example(q: Q) { + | ++++ + +error[E0277]: the trait bound `Q: T3` is not satisfied + --> $DIR/blame-trait-error.rs:74:44 + | +LL | want(&ExampleDifferentTupleVariantName(q)); + | ---- ^ the trait `T3` is not implemented for `Q` + | | + | required by a bound introduced by this call + | +note: required for `ExampleTuple` to implement `T1` + --> $DIR/blame-trait-error.rs:35:9 + | +LL | impl T1 for ExampleTuple where A: T3 {} + | ^^ ^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here + = note: 1 redundant requirement hidden + = note: required for `&ExampleTuple` to implement `T1` +note: required by a bound in `want` + --> $DIR/blame-trait-error.rs:25:12 + | +LL | fn want(_x: V) {} + | ^^ required by this bound in `want` +help: consider restricting type parameter `Q` + | +LL | fn example(q: Q) { + | ++++ + +error[E0277]: the trait bound `Q: T3` is not satisfied + --> $DIR/blame-trait-error.rs:77:45 + | +LL | want(&ExampleYetAnotherTupleVariantName(q)); + | ---- ^ the trait `T3` is not implemented for `Q` + | | + | required by a bound introduced by this call + | +note: required for `ExampleTuple` to implement `T1` + --> $DIR/blame-trait-error.rs:35:9 + | +LL | impl T1 for ExampleTuple where A: T3 {} + | ^^ ^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here + = note: 1 redundant requirement hidden + = note: required for `&ExampleTuple` to implement `T1` +note: required by a bound in `want` + --> $DIR/blame-trait-error.rs:25:12 + | +LL | fn want(_x: V) {} + | ^^ required by this bound in `want` +help: consider restricting type parameter `Q` + | +LL | fn example(q: Q) { + | ++++ + +error[E0277]: the trait bound `Q: T3` is not satisfied + --> $DIR/blame-trait-error.rs:80:56 + | +LL | want(&ExampleStruct::ExampleStructVariant { field: q }); + | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q` + | +note: required for `ExampleStruct` to implement `T1` + --> $DIR/blame-trait-error.rs:45:9 + | +LL | impl T1 for ExampleStruct where A: T3 {} + | ^^ ^^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here + = note: 1 redundant requirement hidden + = note: required for `&ExampleStruct` to implement `T1` +note: required by a bound in `want` + --> $DIR/blame-trait-error.rs:25:12 + | +LL | fn want(_x: V) {} + | ^^ required by this bound in `want` +help: consider restricting type parameter `Q` + | +LL | fn example(q: Q) { + | ++++ + +error[E0277]: the trait bound `Q: T3` is not satisfied + --> $DIR/blame-trait-error.rs:83:41 + | +LL | want(&ExampleStructVariant { field: q }); + | ---- ^ the trait `T3` is not implemented for `Q` + | | + | required by a bound introduced by this call + | +note: required for `ExampleStruct` to implement `T1` + --> $DIR/blame-trait-error.rs:45:9 + | +LL | impl T1 for ExampleStruct where A: T3 {} + | ^^ ^^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here + = note: 1 redundant requirement hidden + = note: required for `&ExampleStruct` to implement `T1` +note: required by a bound in `want` + --> $DIR/blame-trait-error.rs:25:12 + | +LL | fn want(_x: V) {} + | ^^ required by this bound in `want` +help: consider restricting type parameter `Q` + | +LL | fn example(q: Q) { + | ++++ + +error[E0277]: the trait bound `Q: T3` is not satisfied + --> $DIR/blame-trait-error.rs:86:61 + | +LL | want(&ExampleOtherStruct::ExampleStructVariant { field: q }); + | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q` + | +note: required for `ExampleStruct` to implement `T1` + --> $DIR/blame-trait-error.rs:45:9 + | +LL | impl T1 for ExampleStruct where A: T3 {} + | ^^ ^^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here + = note: 1 redundant requirement hidden + = note: required for `&ExampleStruct` to implement `T1` +note: required by a bound in `want` + --> $DIR/blame-trait-error.rs:25:12 + | +LL | fn want(_x: V) {} + | ^^ required by this bound in `want` +help: consider restricting type parameter `Q` + | +LL | fn example(q: Q) { + | ++++ + +error[E0277]: the trait bound `Q: T3` is not satisfied + --> $DIR/blame-trait-error.rs:89:54 + | +LL | want(&ExampleDifferentStructVariantName { field: q }); + | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q` + | +note: required for `ExampleStruct` to implement `T1` + --> $DIR/blame-trait-error.rs:45:9 + | +LL | impl T1 for ExampleStruct where A: T3 {} + | ^^ ^^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here + = note: 1 redundant requirement hidden + = note: required for `&ExampleStruct` to implement `T1` +note: required by a bound in `want` + --> $DIR/blame-trait-error.rs:25:12 + | +LL | fn want(_x: V) {} + | ^^ required by this bound in `want` +help: consider restricting type parameter `Q` + | +LL | fn example(q: Q) { + | ++++ + +error[E0277]: the trait bound `Q: T3` is not satisfied + --> $DIR/blame-trait-error.rs:92:55 + | +LL | want(&ExampleYetAnotherStructVariantName { field: q }); + | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q` + | +note: required for `ExampleStruct` to implement `T1` + --> $DIR/blame-trait-error.rs:45:9 + | +LL | impl T1 for ExampleStruct where A: T3 {} + | ^^ ^^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here + = note: 1 redundant requirement hidden + = note: required for `&ExampleStruct` to implement `T1` +note: required by a bound in `want` + --> $DIR/blame-trait-error.rs:25:12 + | +LL | fn want(_x: V) {} + | ^^ required by this bound in `want` +help: consider restricting type parameter `Q` + | +LL | fn example(q: Q) { + | ++++ + +error[E0277]: the trait bound `Q: T3` is not satisfied + --> $DIR/blame-trait-error.rs:95:38 + | +LL | want(&ExampleActuallyTupleStruct(q, 0)); + | ---- ^ the trait `T3` is not implemented for `Q` + | | + | required by a bound introduced by this call + | +note: required for `ExampleActuallyTupleStruct` to implement `T1` + --> $DIR/blame-trait-error.rs:50:9 + | +LL | impl T1 for ExampleActuallyTupleStruct where A: T3 {} + | ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here + = note: 1 redundant requirement hidden + = note: required for `&ExampleActuallyTupleStruct` to implement `T1` +note: required by a bound in `want` + --> $DIR/blame-trait-error.rs:25:12 + | +LL | fn want(_x: V) {} + | ^^ required by this bound in `want` +help: consider restricting type parameter `Q` + | +LL | fn example(q: Q) { + | ++++ + +error[E0277]: the trait bound `Q: T3` is not satisfied + --> $DIR/blame-trait-error.rs:98:43 + | +LL | want(&ExampleActuallyTupleStructOther(q, 0)); + | ---- ^ the trait `T3` is not implemented for `Q` + | | + | required by a bound introduced by this call + | +note: required for `ExampleActuallyTupleStruct` to implement `T1` + --> $DIR/blame-trait-error.rs:50:9 + | +LL | impl T1 for ExampleActuallyTupleStruct where A: T3 {} + | ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- unsatisfied trait bound introduced here + = note: 1 redundant requirement hidden + = note: required for `&ExampleActuallyTupleStruct` to implement `T1` +note: required by a bound in `want` + --> $DIR/blame-trait-error.rs:25:12 + | +LL | fn want(_x: V) {} + | ^^ required by this bound in `want` +help: consider restricting type parameter `Q` + | +LL | fn example(q: Q) { + | ++++ + +error: aborting due to 16 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr b/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr index 6913771f2883e..b6a24e12bcc76 100644 --- a/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr +++ b/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr @@ -91,10 +91,10 @@ LL | fn example(q: Q) { | ++++ error[E0277]: the trait bound `Q: T3` is not satisfied - --> $DIR/blame-trait-error-spans-on-exprs.rs:93:27 + --> $DIR/blame-trait-error-spans-on-exprs.rs:93:53 | LL | want(Wrapper { value: TacoKinds::OneTaco(false, q) }); - | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `T3` is not implemented for `Q` + | ---- ^ the trait `T3` is not implemented for `Q` | | | required by a bound introduced by this call | diff --git a/tests/ui/extenv/extenv-not-defined-default.rs b/tests/ui/extenv/extenv-not-defined-default.rs index 30a06a25465f4..1fb046c78f2a0 100644 --- a/tests/ui/extenv/extenv-not-defined-default.rs +++ b/tests/ui/extenv/extenv-not-defined-default.rs @@ -1,4 +1,4 @@ fn main() { - env!("__HOPEFULLY_NOT_DEFINED__"); - //~^ ERROR: environment variable `__HOPEFULLY_NOT_DEFINED__` not defined + env!("CARGO__HOPEFULLY_NOT_DEFINED__"); + //~^ ERROR: environment variable `CARGO__HOPEFULLY_NOT_DEFINED__` not defined } diff --git a/tests/ui/extenv/extenv-not-defined-default.stderr b/tests/ui/extenv/extenv-not-defined-default.stderr index 884875dca5394..e3dce000530ae 100644 --- a/tests/ui/extenv/extenv-not-defined-default.stderr +++ b/tests/ui/extenv/extenv-not-defined-default.stderr @@ -1,9 +1,10 @@ -error: environment variable `__HOPEFULLY_NOT_DEFINED__` not defined +error: environment variable `CARGO__HOPEFULLY_NOT_DEFINED__` not defined at compile time --> $DIR/extenv-not-defined-default.rs:2:5 | -LL | env!("__HOPEFULLY_NOT_DEFINED__"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | env!("CARGO__HOPEFULLY_NOT_DEFINED__"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | + = help: Cargo sets build script variables at run time. Use `std::env::var("CARGO__HOPEFULLY_NOT_DEFINED__")` instead = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/tests/ui/extenv/issue-55897.stderr b/tests/ui/extenv/issue-55897.stderr index 92e8a44b55fe5..5752a965e3518 100644 --- a/tests/ui/extenv/issue-55897.stderr +++ b/tests/ui/extenv/issue-55897.stderr @@ -1,9 +1,10 @@ -error: environment variable `NON_EXISTENT` not defined +error: environment variable `NON_EXISTENT` not defined at compile time --> $DIR/issue-55897.rs:11:22 | LL | include!(concat!(env!("NON_EXISTENT"), "/data.rs")); | ^^^^^^^^^^^^^^^^^^^^ | + = help: Use `std::env::var("NON_EXISTENT")` to read the variable at run time = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info) error: suffixes on string literals are invalid diff --git a/tests/ui/impl-trait/in-trait/new-lowering-strategy/simple-trait.rs b/tests/ui/impl-trait/in-trait/new-lowering-strategy/simple-trait.rs new file mode 100644 index 0000000000000..dfce973d770b9 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/new-lowering-strategy/simple-trait.rs @@ -0,0 +1,11 @@ +// check-pass +// compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty + +#![feature(return_position_impl_trait_in_trait)] +#![allow(incomplete_features)] + +trait Foo { + fn foo() -> impl Sized; +} + +fn main() {} diff --git a/tests/ui/macros/macros-nonfatal-errors.stderr b/tests/ui/macros/macros-nonfatal-errors.stderr index d42f6c179b7ef..93fbc9c8a447e 100644 --- a/tests/ui/macros/macros-nonfatal-errors.stderr +++ b/tests/ui/macros/macros-nonfatal-errors.stderr @@ -150,18 +150,19 @@ error: expected string literal LL | env!(invalid); | ^^^^^^^ -error: expected string literal - --> $DIR/macros-nonfatal-errors.rs:105:10 +error: env! takes 1 or 2 arguments + --> $DIR/macros-nonfatal-errors.rs:105:5 | LL | env!(foo, abr, baz); - | ^^^ + | ^^^^^^^^^^^^^^^^^^^ -error: environment variable `RUST_HOPEFULLY_THIS_DOESNT_EXIST` not defined +error: environment variable `RUST_HOPEFULLY_THIS_DOESNT_EXIST` not defined at compile time --> $DIR/macros-nonfatal-errors.rs:106:5 | LL | env!("RUST_HOPEFULLY_THIS_DOESNT_EXIST"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | + = help: Use `std::env::var("RUST_HOPEFULLY_THIS_DOESNT_EXIST")` to read the variable at run time = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info) error: format argument must be a string literal diff --git a/tests/ui/thir-print/thir-flat.stdout b/tests/ui/thir-print/thir-flat.stdout index c31e6a218ce4d..910c0da27378a 100644 --- a/tests/ui/thir-print/thir-flat.stdout +++ b/tests/ui/thir-print/thir-flat.stdout @@ -17,21 +17,16 @@ Thir { ], exprs: [ Expr { - ty: (), - temp_lifetime: Some( - Node(2), - ), - span: $DIR/thir-flat.rs:4:15: 4:17 (#0), kind: Block { block: b0, }, - }, - Expr { ty: (), temp_lifetime: Some( Node(2), ), span: $DIR/thir-flat.rs:4:15: 4:17 (#0), + }, + Expr { kind: Scope { region_scope: Node(2), lint_level: Explicit( @@ -39,18 +34,23 @@ Thir { ), value: e0, }, - }, - Expr { ty: (), temp_lifetime: Some( Node(2), ), span: $DIR/thir-flat.rs:4:15: 4:17 (#0), + }, + Expr { kind: Scope { region_scope: Destruction(2), lint_level: Inherited, value: e1, }, + ty: (), + temp_lifetime: Some( + Node(2), + ), + span: $DIR/thir-flat.rs:4:15: 4:17 (#0), }, ], stmts: [],