<ins> #![feature(inline_const)] #![feature(yeet_expr)] #![allow(incomplete_features)] // Necessary for now, while explicit_tail_calls is incomplete #![feature(explicit_tail_calls)] fn a() { let foo = { 1 } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed return; }; } fn b() { let foo = for i in 1..2 { break; } else { //~^ ERROR `for...else` loops are not supported return; }; } fn c() { let foo = if true { 1 } else { 0 } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed return; }; } fn d() { let foo = loop { break; } else { //~^ ERROR loop...else` loops are not supported return; }; } fn e() { let foo = match true { true => 1, false => 0 } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed return; }; } struct X {a: i32} fn f() { let foo = X { a: 1 } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed return; }; } fn g() { let foo = while false { break; } else { //~^ ERROR `while...else` loops are not supported return; }; } fn h() { let foo = const { 1 } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed return; }; } fn i() { let foo = &{ 1 } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed return; }; } fn j() { let bar = 0; let foo = bar = { 1 } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed return; }; } fn k() { let foo = 1 + { 1 } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed return; }; } fn l() { let foo = 1..{ 1 } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed return; }; } fn m() { let foo = return { () } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed return; }; } fn n() { let foo = -{ 1 } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed return; }; } fn o() -> Result<(), ()> { let foo = do yeet { () } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed return Ok(()); }; } fn p() { let foo = become { () } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed return; }; } fn q() { let foo = |x: i32| { x } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed return; }; } fn main() {} </ins>


<ins> error: right curly brace `}` before `else` in a `let...else` statement not allowed --> $DIR/bad-let-else-statement.rs:9:5 | LL |     } else { |     ^ | help: wrap the expression in parentheses | LL ~     let foo = ({ LL |         1 LL ~     }) else { | error: `for...else` loops are not supported --> $DIR/bad-let-else-statement.rs:18:7 | LL |       let foo = for i in 1..2 { |                 --- `else` is attached to this loop LL |           break; LL |       } else { |  _______^ LL | | LL | |         return; LL | |     }; | |_____^ | = note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run error: right curly brace `}` before `else` in a `let...else` statement not allowed --> $DIR/bad-let-else-statement.rs:29:5 | LL |     } else { |     ^ | help: wrap the expression in parentheses | LL ~     let foo = (if true { LL |         1 LL |     } else { LL |         0 LL ~     }) else { | error: `loop...else` loops are not supported --> $DIR/bad-let-else-statement.rs:38:7 | LL |       let foo = loop { |                 ---- `else` is attached to this loop LL |           break; LL |       } else { |  _______^ LL | | LL | |         return; LL | |     }; | |_____^ | = note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run error: right curly brace `}` before `else` in a `let...else` statement not allowed --> $DIR/bad-let-else-statement.rs:48:5 | LL |     } else { |     ^ | help: wrap the expression in parentheses | LL ~     let foo = (match true { LL |         true => 1, LL |         false => 0 LL ~     }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed --> $DIR/bad-let-else-statement.rs:58:5 | LL |     } else { |     ^ | help: wrap the expression in parentheses | LL ~     let foo = (X { LL |         a: 1 LL ~     }) else { | error: `while...else` loops are not supported --> $DIR/bad-let-else-statement.rs:67:7 | LL |       let foo = while false { |                 ----- `else` is attached to this loop LL |           break; LL |       } else { |  _______^ LL | | LL | |         return; LL | |     }; | |_____^ | = note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run error: right curly brace `}` before `else` in a `let...else` statement not allowed --> $DIR/bad-let-else-statement.rs:76:5 | LL |     } else { |     ^ | help: wrap the expression in parentheses | LL ~     let foo = (const { LL |         1 LL ~     }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed --> $DIR/bad-let-else-statement.rs:85:5 | LL |     } else { |     ^ | help: wrap the expression in parentheses | LL ~     let foo = &({ LL |         1 LL ~     }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed --> $DIR/bad-let-else-statement.rs:95:5 | LL |     } else { |     ^ | help: wrap the expression in parentheses | LL ~     let foo = bar = ({ LL |         1 LL ~     }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed --> $DIR/bad-let-else-statement.rs:104:5 | LL |     } else { |     ^ | help: wrap the expression in parentheses | LL ~     let foo = 1 + ({ LL |         1 LL ~     }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed --> $DIR/bad-let-else-statement.rs:113:5 | LL |     } else { |     ^ | help: wrap the expression in parentheses | LL ~     let foo = 1..({ LL |         1 LL ~     }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed --> $DIR/bad-let-else-statement.rs:122:5 | LL |     } else { |     ^ | help: wrap the expression in parentheses | LL ~     let foo = return ({ LL |         () LL ~     }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed --> $DIR/bad-let-else-statement.rs:131:5 | LL |     } else { |     ^ | help: wrap the expression in parentheses | LL ~     let foo = -({ LL |         1 LL ~     }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed --> $DIR/bad-let-else-statement.rs:140:5 | LL |     } else { |     ^ | help: wrap the expression in parentheses | LL ~     let foo = do yeet ({ LL |         () LL ~     }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed --> $DIR/bad-let-else-statement.rs:149:5 | LL |     } else { |     ^ | help: wrap the expression in parentheses | LL ~     let foo = become ({ LL |         () LL ~     }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed --> $DIR/bad-let-else-statement.rs:158:5 | LL |     } else { |     ^ | help: wrap the expression in parentheses | LL ~     let foo = |x: i32| ({ LL |         x LL ~     }) else { | error: aborting due to 17 previous errors </ins>


use std::mem; use std::num::NonZeroUsize; use std::ops::{ControlFlow, Deref}; <ins> use std::ptr::NonNull; </ins> /// An entity in the Rust type system, which can be one of /// several kinds (types, lifetimes, and consts).


/// `Region` and `Const` are all interned. #[derive(Copy, Clone, PartialEq, Eq, Hash)] pub struct GenericArg<'tcx> { <del> ptr: NonZeroUsize, </del> <ins> ptr: NonNull<()>, </ins> marker: PhantomData<(Ty<'tcx>, ty::Region<'tcx>, ty::Const<'tcx>)>, } <ins> #[cfg(parallel_compiler)] unsafe impl<'tcx> rustc_data_structures::sync::DynSend for GenericArg<'tcx> where &'tcx (Ty<'tcx>, ty::Region<'tcx>, ty::Const<'tcx>): rustc_data_structures::sync::DynSend { } #[cfg(parallel_compiler)] unsafe impl<'tcx> rustc_data_structures::sync::DynSync for GenericArg<'tcx> where &'tcx (Ty<'tcx>, ty::Region<'tcx>, ty::Const<'tcx>): rustc_data_structures::sync::DynSync { } unsafe impl<'tcx> Send for GenericArg<'tcx> where &'tcx (Ty<'tcx>, ty::Region<'tcx>, ty::Const<'tcx>): Send { } unsafe impl<'tcx> Sync for GenericArg<'tcx> where &'tcx (Ty<'tcx>, ty::Region<'tcx>, ty::Const<'tcx>): Sync { } </ins> impl<'tcx> IntoDiagnosticArg for GenericArg<'tcx> { fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { self.to_string().into_diagnostic_arg()


GenericArgKind::Lifetime(lt) => { // Ensure we can use the tag bits. assert_eq!(mem::align_of_val(&*lt.0.0) & TAG_MASK, 0); <del> (REGION_TAG, lt.0.0 as *const ty::RegionKind<'tcx> as usize) </del> <ins> (REGION_TAG, NonNull::from(lt.0.0).cast()) </ins> } GenericArgKind::Type(ty) => { // Ensure we can use the tag bits. assert_eq!(mem::align_of_val(&*ty.0.0) & TAG_MASK, 0); <del> (TYPE_TAG, ty.0.0 as *const WithCachedTypeInfo<ty::TyKind<'tcx>> as usize) </del> <ins> (TYPE_TAG, NonNull::from(ty.0.0).cast()) </ins> } GenericArgKind::Const(ct) => { // Ensure we can use the tag bits. assert_eq!(mem::align_of_val(&*ct.0.0) & TAG_MASK, 0); <del> (CONST_TAG, ct.0.0 as *const WithCachedTypeInfo<ty::ConstData<'tcx>> as usize) </del> <ins> (CONST_TAG, NonNull::from(ct.0.0).cast()) </ins> } }; <del> GenericArg { ptr: unsafe { NonZeroUsize::new_unchecked(ptr | tag) }, marker: PhantomData } </del> <ins> GenericArg { ptr: ptr.map_addr(|addr| addr | tag), marker: PhantomData } </ins> } }


impl<'tcx> GenericArg<'tcx> { #[inline] pub fn unpack(self) -> GenericArgKind<'tcx> { <del> let ptr = self.ptr.get(); </del> <ins> let ptr = unsafe { self.ptr.map_addr(|addr| NonZeroUsize::new_unchecked(addr.get() & !TAG_MASK)) }; </ins> // SAFETY: use of `Interned::new_unchecked` here is ok because these // pointers were originally created from `Interned` types in `pack()`, // and this is just going in the other direction. unsafe { <del> match ptr & TAG_MASK { </del> <ins> match self.ptr.addr().get() & TAG_MASK { </ins> REGION_TAG => GenericArgKind::Lifetime(ty::Region(Interned::new_unchecked( <del> &*((ptr & !TAG_MASK) as *const ty::RegionKind<'tcx>), </del> <ins> ptr.cast::<ty::RegionKind<'tcx>>().as_ref(), </ins> ))), TYPE_TAG => GenericArgKind::Type(Ty(Interned::new_unchecked( <del> &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo<ty::TyKind<'tcx>>), </del> <ins> ptr.cast::<WithCachedTypeInfo<ty::TyKind<'tcx>>>().as_ref(), </ins> ))), CONST_TAG => GenericArgKind::Const(ty::Const(Interned::new_unchecked( <del> &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo<ty::ConstData<'tcx>>), </del> <ins> ptr.cast::<WithCachedTypeInfo<ty::ConstData<'tcx>>>().as_ref(), </ins> ))), _ => intrinsics::unreachable(), }


use std::mem; use std::num::NonZeroUsize; use std::ops::ControlFlow; <ins> use std::ptr::NonNull; </ins> use std::{fmt, str}; pub use crate::ty::diagnostics::*;


#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Term<'tcx> { <del> ptr: NonZeroUsize, </del> <ins> ptr: NonNull<()>, </ins> marker: PhantomData<(Ty<'tcx>, Const<'tcx>)>, } <ins> #[cfg(parallel_compiler)] unsafe impl<'tcx> rustc_data_structures::sync::DynSend for Term<'tcx> where &'tcx (Ty<'tcx>, Const<'tcx>): rustc_data_structures::sync::DynSend { } #[cfg(parallel_compiler)] unsafe impl<'tcx> rustc_data_structures::sync::DynSync for Term<'tcx> where &'tcx (Ty<'tcx>, Const<'tcx>): rustc_data_structures::sync::DynSync { } unsafe impl<'tcx> Send for Term<'tcx> where &'tcx (Ty<'tcx>, Const<'tcx>): Send {} unsafe impl<'tcx> Sync for Term<'tcx> where &'tcx (Ty<'tcx>, Const<'tcx>): Sync {} </ins> impl Debug for Term<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let data = if let Some(ty) = self.ty() {


impl<'tcx> Term<'tcx> { #[inline] pub fn unpack(self) -> TermKind<'tcx> { <del> let ptr = self.ptr.get(); </del> <ins> let ptr = unsafe { self.ptr.map_addr(|addr| NonZeroUsize::new_unchecked(addr.get() & !TAG_MASK)) }; </ins> // SAFETY: use of `Interned::new_unchecked` here is ok because these // pointers were originally created from `Interned` types in `pack()`, // and this is just going in the other direction. unsafe { <del> match ptr & TAG_MASK { </del> <ins> match self.ptr.addr().get() & TAG_MASK { </ins> TYPE_TAG => TermKind::Ty(Ty(Interned::new_unchecked( <del> &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo<ty::TyKind<'tcx>>), </del> <ins> ptr.cast::<WithCachedTypeInfo<ty::TyKind<'tcx>>>().as_ref(), </ins> ))), CONST_TAG => TermKind::Const(ty::Const(Interned::new_unchecked( <del> &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo<ty::ConstData<'tcx>>), </del> <ins> ptr.cast::<WithCachedTypeInfo<ty::ConstData<'tcx>>>().as_ref(), </ins> ))), _ => core::intrinsics::unreachable(), }


TermKind::Ty(ty) => { // Ensure we can use the tag bits. assert_eq!(mem::align_of_val(&*ty.0.0) & TAG_MASK, 0); <del> (TYPE_TAG, ty.0.0 as *const WithCachedTypeInfo<ty::TyKind<'tcx>> as usize) </del> <ins> (TYPE_TAG, NonNull::from(ty.0.0).cast()) </ins> } TermKind::Const(ct) => { // Ensure we can use the tag bits. assert_eq!(mem::align_of_val(&*ct.0.0) & TAG_MASK, 0); <del> (CONST_TAG, ct.0.0 as *const WithCachedTypeInfo<ty::ConstData<'tcx>> as usize) </del> <ins> (CONST_TAG, NonNull::from(ct.0.0).cast()) </ins> } }; <del> Term { ptr: unsafe { NonZeroUsize::new_unchecked(ptr | tag) }, marker: PhantomData } </del> <ins> Term { ptr: ptr.map_addr(|addr| addr | tag), marker: PhantomData } </ins> } }


dividing by zero const_eval_division_overflow = overflow in signed division (dividing MIN by -1) <del> const_eval_double_storage_live = StorageLive on a local that was already live </del> const_eval_dyn_call_not_a_method = `dyn` call trying to call something that is not a method


Operand::Immediate(Immediate::Uninit) }); <del> // StorageLive expects the local to be dead, and marks it live. </del> <ins> // If the local is already live, deallocate its old memory. </ins> let old = mem::replace(&mut self.frame_mut().locals[local].value, local_val); <del> if !matches!(old, LocalValue::Dead) { throw_ub_custom!(fluent::const_eval_double_storage_live); } </del> <ins> self.deallocate_local(old)?; </ins> Ok(()) }


assert!(local != mir::RETURN_PLACE, "Cannot make return place dead"); trace!("{:?} is now dead", local); <del> // It is entirely okay for this local to be already dead (at least that's how we currently generate MIR) </del> <ins> // If the local is already dead, this is a NOP. </ins> let old = mem::replace(&mut self.frame_mut().locals[local].value, LocalValue::Dead); self.deallocate_local(old)?; Ok(())


/// At any point during the execution of a function, each local is either allocated or /// unallocated. Except as noted below, all locals except function parameters are initially /// unallocated. `StorageLive` statements cause memory to be allocated for the local while <del> /// `StorageDead` statements cause the memory to be freed. Using a local in any way (not only /// reading/writing from it) while it is unallocated is UB. </del> <ins> /// `StorageDead` statements cause the memory to be freed. In other words, /// `StorageLive`/`StorageDead` act like the heap operations `allocate`/`deallocate`, but for /// stack-allocated local variables. Using a local in any way (not only reading/writing from it) /// while it is unallocated is UB. </ins> /// /// Some locals have no `StorageLive` or `StorageDead` statements within the entire MIR body. /// These locals are implicitly allocated for the full duration of the function. There is a /// convenience method at `rustc_mir_dataflow::storage::always_storage_live_locals` for /// computing these locals. /// <del> /// If the local is already allocated, calling `StorageLive` again is UB. However, for an /// unallocated local an additional `StorageDead` all is simply a nop. </del> <ins> /// If the local is already allocated, calling `StorageLive` again will implicitly free the /// local and then allocate fresh uninitilized memory. If a local is already deallocated, /// calling `StorageDead` again is a NOP. </ins> StorageLive(Local), /// See `StorageLive` above.


<ins> #![feature(core_intrinsics, custom_mir)] use std::intrinsics::mir::*; #[custom_mir(dialect = "runtime")] fn main() { mir! { let val: i32; { val = 42; //~ERROR: accessing a dead local variable StorageLive(val); // too late... (but needs to be here to make `val` not implicitly live) Return() } } } </ins>


<ins> error: Undefined Behavior: accessing a dead local variable --> $DIR/storage-live-dead-var.rs:LL:CC | LL |             val = 42; |             ^^^^^^^^ accessing a dead local variable | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: = note: inside `main` at $DIR/storage-live-dead-var.rs:LL:CC note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace error: aborting due to 1 previous error </ins>


<ins> #![feature(core_intrinsics, custom_mir)] use std::intrinsics::mir::*; #[custom_mir(dialect = "runtime")] fn main() { mir! { let val: i32; let _val2: i32; { StorageLive(val); val = 42; StorageLive(val); // reset val to `uninit` _val2 = val; //~ERROR: uninitialized Return() } } } </ins>


<ins> error: Undefined Behavior: constructing invalid value: encountered uninitialized memory, but expected an integer --> $DIR/storage-live-resets-var.rs:LL:CC | LL |             _val2 = val; |             ^^^^^^^^^^^ constructing invalid value: encountered uninitialized memory, but expected an integer | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: = note: inside `main` at $DIR/storage-live-resets-var.rs:LL:CC note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace error: aborting due to 1 previous error </ins>


], Applicability::MachineApplicable, ); <ins> } else { // FIXME: we may suggest array::repeat instead err.help("consider using `core::array::from_fn` to initialize the array"); err.help("see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html# for more information"); </ins> } if self.tcx.sess.is_nightly_build()


|                    ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Header<'_>` | = note: the `Copy` trait is required because this value will be copied for each element of the array <ins> = help: consider using `core::array::from_fn` to initialize the array = help: see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html# for more information </ins> help: consider annotating `Header<'_>` with `#[derive(Copy)]` | LL + #[derive(Copy)]


|                    ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Header<'_>` | = note: the `Copy` trait is required because this value will be copied for each element of the array <ins> = help: consider using `core::array::from_fn` to initialize the array = help: see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html# for more information </ins> help: consider annotating `Header<'_>` with `#[derive(Copy)]` | LL + #[derive(Copy)]


|      ^ the trait `Copy` is not implemented for `T` | = note: the `Copy` trait is required because this value will be copied for each element of the array <ins> = help: consider using `core::array::from_fn` to initialize the array = help: see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html# for more information </ins> help: consider restricting type parameter `T` | LL | fn g<T: std::marker::Copy, const N: usize>(x: T) -> [T; N] {


| = note: required for `Option<Bar>` to implement `Copy` = note: the `Copy` trait is required because this value will be copied for each element of the array <ins> = help: consider using `core::array::from_fn` to initialize the array = help: see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html# for more information </ins> help: consider annotating `Bar` with `#[derive(Copy)]` | LL + #[derive(Copy)]


|               ^ the trait `Copy` is not implemented for `Foo` | = note: the `Copy` trait is required because this value will be copied for each element of the array <ins> = help: consider using `core::array::from_fn` to initialize the array = help: see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html# for more information </ins> help: consider annotating `Foo` with `#[derive(Copy)]` | LL + #[derive(Copy)]


<ins> fn foo() -> String { String::new() } fn main() { let string_arr = [foo(); 64]; //~ ERROR the trait bound `String: Copy` is not satisfied } </ins>


<ins> error[E0277]: the trait bound `String: Copy` is not satisfied --> $DIR/issue-119530-sugg-from-fn.rs:4:23 | LL |     let string_arr = [foo(); 64]; |                       ^^^^^ the trait `Copy` is not implemented for `String` | = note: the `Copy` trait is required because this value will be copied for each element of the array = help: consider using `core::array::from_fn` to initialize the array = help: see https://doc.rust-lang.org/stable/std/array/fn.from_fn.html# for more information error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. </ins>


P: FnMut(Self::Item) -> bool, { #[inline] <del> fn check<T>( mut predicate: impl FnMut(T) -> bool, ) -> impl FnMut(usize, T) -> ControlFlow<usize, usize> { </del> <ins> fn check<'a, T>( mut predicate: impl FnMut(T) -> bool + 'a, acc: &'a mut usize, ) -> impl FnMut((), T) -> ControlFlow<usize, ()> + 'a { </ins> #[rustc_inherit_overflow_checks] <del> move |i, x| { if predicate(x) { ControlFlow::Break(i) } else { ControlFlow::Continue(i + 1) } </del> <ins> move |_, x| { if predicate(x) { ControlFlow::Break(*acc) } else { *acc += 1; ControlFlow::Continue(()) } </ins> } } <del> self.try_fold(0, check(predicate)).break_value() </del> <ins> let mut acc = 0; self.try_fold((), check(predicate, &mut acc)).break_value() </ins> } /// Searches for an element in an iterator from the right, returning its


// Free the allocation without dropping its contents let (bptr, alloc) = Box::into_raw_with_allocator(src); <del> let src = Box::from_raw(bptr as *mut mem::ManuallyDrop<T>); </del> <ins> let src = Box::from_raw_in(bptr as *mut mem::ManuallyDrop<T>, alloc.by_ref()); </ins> drop(src); Self::from_ptr_in(ptr, alloc)


//! Runtime calls emitted by the compiler. <del> use c_str::ToCStr; </del> <ins> use c_str::CString; use libc::c_char; use cast; use option::Some; </ins> #[cold] #[lang="fail_"]


pub fn fail_bounds_check(file: *u8, line: uint, index: uint, len: uint) -> ! { let msg = format!("index out of bounds: the len is {} but the index is {}", len as uint, index as uint); <del> msg.with_c_str(|buf| fail_(buf as *u8, file, line)) </del> <ins> let file_str = match unsafe { CString::new(file as *c_char, false) }.as_str() { // This transmute is safe because `file` is always stored in rodata. Some(s) => unsafe { cast::transmute::<&str, &'static str>(s) }, None    => "file wasn't UTF-8 safe" }; ::rt::begin_unwind(msg, file_str, line) </ins> } #[lang="malloc"]


UnresolvedFloatTy(FloatVid), UnresolvedTy(TyVid), UnresolvedConst(ConstVid), <ins> UnresolvedEffect(EffectVid), </ins> } /// See the `region_obligations` field for more information.


), UnresolvedTy(_) => write!(f, "unconstrained type"), UnresolvedConst(_) => write!(f, "unconstrained const value"), <ins> UnresolvedEffect(_) => write!(f, "unconstrained effect value"), </ins> } } }


ty::ConstKind::Infer(InferConst::Fresh(_)) => { bug!("Unexpected const in full const resolver: {:?}", c); } <ins> ty::ConstKind::Infer(InferConst::EffectVar(evid)) => { return Err(FixupError::UnresolvedEffect(evid)); } </ins> _ => {} } c.try_super_fold_with(self)


<del> //@ known-bug: #119830 #![feature(effects)] #![feature(min_specialization)] trait Specialize {} trait Foo {} impl<T> const Foo for T {} impl<T> const Foo for T where T: const Specialize {} </del>


<ins> //@ check-fail // Fixes #119830 #![feature(effects)] #![feature(min_specialization)] #![feature(const_trait_impl)] trait Specialize {} trait Foo {} impl<T> const Foo for T {} //~^ error: const `impl` for trait `Foo` which is not marked with `#[const_trait]` //~| error: the const parameter `host` is not constrained by the impl trait, self type, or predicates [E0207] impl<T> const Foo for T where T: const Specialize {} //~^ error: const `impl` for trait `Foo` which is not marked with `#[const_trait]` //~| error: `const` can only be applied to `#[const_trait]` traits //~| error: the const parameter `host` is not constrained by the impl trait, self type, or predicates [E0207] //~| error: specialization impl does not specialize any associated items //~| error: could not resolve generic parameters on overridden impl fn main() { } </ins>


<ins> error: const `impl` for trait `Foo` which is not marked with `#[const_trait]` --> $DIR/spec-effectvar-ice.rs:12:15 | LL | trait Foo {} | - help: mark `Foo` as const: `#[const_trait]` LL | LL | impl<T> const Foo for T {} |               ^^^ | = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` = note: adding a non-const method body in the future would be a breaking change error: const `impl` for trait `Foo` which is not marked with `#[const_trait]` --> $DIR/spec-effectvar-ice.rs:16:15 | LL | trait Foo {} | - help: mark `Foo` as const: `#[const_trait]` ... LL | impl<T> const Foo for T where T: const Specialize {} |               ^^^ | = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` = note: adding a non-const method body in the future would be a breaking change error: `const` can only be applied to `#[const_trait]` traits --> $DIR/spec-effectvar-ice.rs:16:40 | LL | impl<T> const Foo for T where T: const Specialize {} |                                        ^^^^^^^^^^ error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates --> $DIR/spec-effectvar-ice.rs:12:9 | LL | impl<T> const Foo for T {} |         ^^^^^ unconstrained const parameter | = note: expressions using a const parameter must map each value to a distinct output value = note: proving the result of expressions other than the parameter are unique is not supported error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates --> $DIR/spec-effectvar-ice.rs:16:9 | LL | impl<T> const Foo for T where T: const Specialize {} |         ^^^^^ unconstrained const parameter | = note: expressions using a const parameter must map each value to a distinct output value = note: proving the result of expressions other than the parameter are unique is not supported error: specialization impl does not specialize any associated items --> $DIR/spec-effectvar-ice.rs:16:1 | LL | impl<T> const Foo for T where T: const Specialize {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: impl is a specialization of this impl --> $DIR/spec-effectvar-ice.rs:12:1 | LL | impl<T> const Foo for T {} | ^^^^^^^^^^^^^^^^^^^^^^^ error: could not resolve generic parameters on overridden impl --> $DIR/spec-effectvar-ice.rs:16:1 | LL | impl<T> const Foo for T where T: const Specialize {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0207`. </ins>


.extend( // Group the return ty with its def id, if we had one. entry.return_ty.map(|ty| { <del> (tcx.require_lang_item(LangItem::FnOnce, None), ty) </del> <ins> (tcx.require_lang_item(LangItem::FnOnceOutput, None), ty) </ins> }), ); }


<ins> //! This is a regression test to avoid an ICE in diagnostics code. //! A typo in the compiler used to get the DefId of FnOnce, and //! use it where an associated item was expected. fn frob() -> impl Fn<P, Output = T> + '_ {} //~^ ERROR missing lifetime specifier //~| ERROR cannot find type `P` //~| ERROR cannot find type `T` //~| ERROR `Fn`-family traits' type parameters is subject to change fn open_parent<'path>() { todo!() } fn main() { let old_path = frob("hello"); //~^ ERROR function takes 0 arguments open_parent(&old_path) //~^ ERROR function takes 0 arguments } </ins>


<ins> error[E0106]: missing lifetime specifier --> $DIR/opaque-used-in-extraneous-argument.rs:5:39 | LL | fn frob() -> impl Fn<P, Output = T> + '_ {} |                                       ^^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`, or if you will only have owned values | LL | fn frob() -> impl Fn<P, Output = T> + 'static {} |                                       ~~~~~~~ error[E0412]: cannot find type `P` in this scope --> $DIR/opaque-used-in-extraneous-argument.rs:5:22 | LL | fn frob() -> impl Fn<P, Output = T> + '_ {} |                      ^ not found in this scope | help: you might be missing a type parameter | LL | fn frob<P>() -> impl Fn<P, Output = T> + '_ {} |        +++ error[E0412]: cannot find type `T` in this scope --> $DIR/opaque-used-in-extraneous-argument.rs:5:34 | LL | fn frob() -> impl Fn<P, Output = T> + '_ {} |                                  ^ not found in this scope | help: you might be missing a type parameter | LL | fn frob<T>() -> impl Fn<P, Output = T> + '_ {} |        +++ error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change --> $DIR/opaque-used-in-extraneous-argument.rs:5:19 | LL | fn frob() -> impl Fn<P, Output = T> + '_ {} |                   ^^^^^^^^^^^^^^^^^ help: use parenthetical notation instead: `Fn(P) -> T` | = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0061]: this function takes 0 arguments but 1 argument was supplied --> $DIR/opaque-used-in-extraneous-argument.rs:16:20 | LL |     let old_path = frob("hello"); |                    ^^^^ ------- |                         | |                         unexpected argument of type `&'static str` |                         help: remove the extra argument | note: function defined here --> $DIR/opaque-used-in-extraneous-argument.rs:5:4 | LL | fn frob() -> impl Fn<P, Output = T> + '_ {} |    ^^^^ error[E0061]: this function takes 0 arguments but 1 argument was supplied --> $DIR/opaque-used-in-extraneous-argument.rs:19:5 | LL |     open_parent(&old_path) |     ^^^^^^^^^^^ --------- |                 | |                 unexpected argument of type `&impl FnOnce<{type error}, Output = {type error}> + Fn<{type error}> + 'static` |                 help: remove the extra argument | note: function defined here --> $DIR/opaque-used-in-extraneous-argument.rs:11:4 | LL | fn open_parent<'path>() { |    ^^^^^^^^^^^ error: aborting due to 6 previous errors Some errors have detailed explanations: E0061, E0106, E0412, E0658. For more information about an error, try `rustc --explain E0061`. </ins>


<ins> #![feature(associated_type_bounds)] // Test for <https://github.com/rust-lang/rust/issues/119857>. pub trait Iter { type Item<'a>: 'a where Self: 'a; fn next<'a>(&'a mut self) -> Option<Self::Item<'a, As1: Copy>>; //~^ ERROR associated type bindings are not allowed here } impl Iter for () { type Item<'a> = &'a mut [()]; fn next<'a>(&'a mut self) -> Option<Self::Item<'a>> { None } } fn main() {} </ins>


<ins> error[E0229]: associated type bindings are not allowed here --> $DIR/no-gat-position.rs:8:56 | LL |     fn next<'a>(&'a mut self) -> Option<Self::Item<'a, As1: Copy>>; |                                                        ^^^^^^^^^ associated type not allowed here error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0229`. </ins>


<ins> #![feature(generic_const_exprs)] //~^ WARN the feature `generic_const_exprs` is incomplete #![feature(non_lifetime_binders)] //~^ WARN the feature `non_lifetime_binders` is incomplete // Test for <https://github.com/rust-lang/rust/issues/115497>, // which originally relied on associated_type_bounds, but was // minimized away from that. trait TraitA { type AsA; } trait TraitB { type AsB; } trait TraitC {} fn foo<T>() where for<const N: u8 = { T::A }> T: TraitA<AsA = impl TraitB<AsB = impl TraitC>>, //~^ ERROR defaults for generic parameters are not allowed in `for<...>` binders //~| ERROR `impl Trait` is not allowed in bounds { } fn main() {} </ins>


<ins> warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/bad-suggestion-on-missing-assoc.rs:1:12 | LL | #![feature(generic_const_exprs)] |            ^^^^^^^^^^^^^^^^^^^ | = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information = note: `#[warn(incomplete_features)]` on by default warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/bad-suggestion-on-missing-assoc.rs:3:12 | LL | #![feature(non_lifetime_binders)] |            ^^^^^^^^^^^^^^^^^^^^ | = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information error: defaults for generic parameters are not allowed in `for<...>` binders --> $DIR/bad-suggestion-on-missing-assoc.rs:20:9 | LL |     for<const N: u8 = { T::A }> T: TraitA<AsA = impl TraitB<AsB = impl TraitC>>, |         ^^^^^^^^^^^^^^^^^^^^^^ error[E0562]: `impl Trait` is not allowed in bounds --> $DIR/bad-suggestion-on-missing-assoc.rs:20:49 | LL |     for<const N: u8 = { T::A }> T: TraitA<AsA = impl TraitB<AsB = impl TraitC>>, |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `impl Trait` is only allowed in arguments and return types of functions and methods error: aborting due to 2 previous errors; 2 warnings emitted For more information about this error, try `rustc --explain E0562`. </ins>


#![allow(rustc::untranslatable_diagnostic)] use either::Either; <del> use hir::ClosureKind; </del> <ins> use hir::{ClosureKind, Path}; </ins> use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{codes::*, struct_span_code_err, Applicability, Diag, MultiSpan};


use rustc_middle::bug; use rustc_middle::hir::nested_filter::OnlyBodies; use rustc_middle::mir::tcx::PlaceTy; <ins> use rustc_middle::mir::VarDebugInfoContents; </ins> use rustc_middle::mir::{ self, AggregateKind, BindingForm, BorrowKind, CallSource, ClearCrossCrate, ConstraintCategory, FakeBorrowKind, FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, MutBorrowKind,


self.suggest_cloning(err, ty, expr, None, Some(move_spans)); } } <del> if let Some(pat) = finder.pat { </del> <ins> self.suggest_ref_for_dbg_args(expr, place, move_span, err); // it's useless to suggest inserting `ref` when the span don't comes from local code if let Some(pat) = finder.pat && !move_span.is_dummy() && !self.infcx.tcx.sess.source_map().is_imported(move_span) { </ins> *in_pattern = true; let mut sugg = vec![(pat.span.shrink_to_lo(), "ref ".to_string())]; if let Some(pat) = finder.parent_pat {


} } <ins> // for dbg!(x) which may take ownership, suggest dbg!(&x) instead // but here we actually do not check whether the macro name is `dbg!` // so that we may extend the scope a bit larger to cover more cases fn suggest_ref_for_dbg_args( &self, body: &hir::Expr<'_>, place: &Place<'tcx>, move_span: Span, err: &mut Diag<'infcx>, ) { let var_info = self.body.var_debug_info.iter().find(|info| match info.value { VarDebugInfoContents::Place(ref p) => p == place, _ => false, }); let arg_name = if let Some(var_info) = var_info { var_info.name } else { return; }; struct MatchArgFinder { expr_span: Span, match_arg_span: Option<Span>, arg_name: Symbol, } impl Visitor<'_> for MatchArgFinder { fn visit_expr(&mut self, e: &hir::Expr<'_>) { // dbg! is expanded into a match pattern, we need to find the right argument span if let hir::ExprKind::Match(expr, ..) = &e.kind && let hir::ExprKind::Path(hir::QPath::Resolved( _, path @ Path { segments: [seg], .. }, )) = &expr.kind && seg.ident.name == self.arg_name && self.expr_span.source_callsite().contains(expr.span) { self.match_arg_span = Some(path.span); } hir::intravisit::walk_expr(self, e); } } let mut finder = MatchArgFinder { expr_span: move_span, match_arg_span: None, arg_name }; finder.visit_expr(body); if let Some(macro_arg_span) = finder.match_arg_span { err.span_suggestion_verbose( macro_arg_span.shrink_to_lo(), "consider borrowing instead of transferring ownership", "&", Applicability::MachineApplicable, ); } } </ins> fn report_use_of_uninitialized( &self, mpi: MovePathIndex,


<ins> fn s() -> String { let a = String::new(); dbg!(a); return a; //~ ERROR use of moved value: } fn m() -> String { let a = String::new(); dbg!(1, 2, a, 1, 2); return a; //~ ERROR use of moved value: } fn t(a: String) -> String { let b: String = "".to_string(); dbg!(a, b); return b; //~ ERROR use of moved value: } fn x(a: String) -> String { let b: String = "".to_string(); dbg!(a, b); return a; //~ ERROR use of moved value: } macro_rules! my_dbg { () => { eprintln!("[{}:{}:{}]", file!(), line!(), column!()) }; ($val:expr $(,)?) => { match $val { tmp => { eprintln!("[{}:{}:{}] {} = {:#?}", file!(), line!(), column!(), stringify!($val), &tmp); tmp } } }; ($($val:expr),+ $(,)?) => { ($(my_dbg!($val)),+,) }; } fn test_my_dbg() -> String { let b: String = "".to_string(); my_dbg!(b, 1); return b; //~ ERROR use of moved value: } fn test_not_macro() -> String { let a = String::new(); let _b = match a { tmp => { eprintln!("dbg: {}", tmp); tmp } }; return a; //~ ERROR use of moved value: } fn get_expr(_s: String) {} fn test() { let a: String = "".to_string(); let _res = get_expr(dbg!(a)); let _l = a.len(); //~ ERROR borrow of moved value } fn main() {} </ins>


<ins> error[E0382]: use of moved value: `a` --> $DIR/dbg-issue-120327.rs:4:12 | LL |     let a = String::new(); |         - move occurs because `a` has type `String`, which does not implement the `Copy` trait LL |     dbg!(a); |     ------- value moved here LL |     return a; |            ^ value used here after move | help: consider borrowing instead of transferring ownership | LL |     dbg!(&a); |          + error[E0382]: use of moved value: `a` --> $DIR/dbg-issue-120327.rs:10:12 | LL |     let a = String::new(); |         - move occurs because `a` has type `String`, which does not implement the `Copy` trait LL |     dbg!(1, 2, a, 1, 2); |     ------------------- value moved here LL |     return a; |            ^ value used here after move | help: consider borrowing instead of transferring ownership | LL |     dbg!(1, 2, &a, 1, 2); |                + error[E0382]: use of moved value: `b` --> $DIR/dbg-issue-120327.rs:16:12 | LL |     let b: String = "".to_string(); |         - move occurs because `b` has type `String`, which does not implement the `Copy` trait LL |     dbg!(a, b); |     ---------- value moved here LL |     return b; |            ^ value used here after move | help: consider borrowing instead of transferring ownership | LL |     dbg!(a, &b); |             + error[E0382]: use of moved value: `a` --> $DIR/dbg-issue-120327.rs:22:12 | LL | fn x(a: String) -> String { |      - move occurs because `a` has type `String`, which does not implement the `Copy` trait LL |     let b: String = "".to_string(); LL |     dbg!(a, b); |     ---------- value moved here LL |     return a; |            ^ value used here after move | help: consider borrowing instead of transferring ownership | LL |     dbg!(&a, b); |          + error[E0382]: use of moved value: `b` --> $DIR/dbg-issue-120327.rs:46:12 | LL |             tmp => { |             --- value moved here ... LL |     let b: String = "".to_string(); |         - move occurs because `b` has type `String`, which does not implement the `Copy` trait LL |     my_dbg!(b, 1); LL |     return b; |            ^ value used here after move | help: consider borrowing instead of transferring ownership | LL |     my_dbg!(&b, 1); |             + help: borrow this binding in the pattern to avoid moving the value | LL |             ref tmp => { |             +++ error[E0382]: use of moved value: `a` --> $DIR/dbg-issue-120327.rs:57:12 | LL |     let a = String::new(); |         - move occurs because `a` has type `String`, which does not implement the `Copy` trait LL |     let _b = match a { LL |         tmp => { |         --- value moved here ... LL |     return a; |            ^ value used here after move | help: borrow this binding in the pattern to avoid moving the value | LL |         ref tmp => { |         +++ error[E0382]: borrow of moved value: `a` --> $DIR/dbg-issue-120327.rs:65:14 | LL |     let a: String = "".to_string(); |         - move occurs because `a` has type `String`, which does not implement the `Copy` trait LL |     let _res = get_expr(dbg!(a)); |                         ------- value moved here LL |     let _l = a.len(); |              ^ value borrowed here after move | help: consider borrowing instead of transferring ownership | LL |     let _res = get_expr(dbg!(&a)); |                              + error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0382`. </ins>


|             ^^^^^^^ value used here after move | = note: this error originates in the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info) <ins> help: consider borrowing instead of transferring ownership | LL |     let _ = dbg!(&a); |                  + </ins> error: aborting due to 1 previous error


// This makes several assumptions about what layouts we will encounter; we match what // codegen does as good as we can (see `extract_field` in `rustc_codegen_ssa/src/mir/operand.rs`). let inner_val: Immediate<_> = match (**self, self.layout.abi) { <del> // if the entire value is uninit, then so is the field (can happen in ConstProp) </del> <ins> // If the entire value is uninit, then so is the field (can happen in ConstProp). </ins> (Immediate::Uninit, _) => Immediate::Uninit, <ins> // If the field is uninhabited, we can forget the data (can happen in ConstProp). // `enum S { A(!), B, C }` is an example of an enum with Scalar layout that // has an `Uninhabited` variant, which means this case is possible. _ if layout.abi.is_uninhabited() => Immediate::Uninit, </ins> // the field contains no information, can be left uninit // (Scalar/ScalarPair can contain even aligned ZST, not just 1-ZST) _ if layout.is_zst() => Immediate::Uninit,


// see https://github.com/rust-lang/rust/issues/93688#issuecomment-1032929496.) // So we just "offset" by 0. let layout = base.layout().for_variant(self, variant); <del> // In the future we might want to allow this to permit code like this: // (this is a Rust/MIR pseudocode mix) // ``` // enum Option2 { //   Some(i32, !), //   None, // } // // fn panic() -> ! { panic!() } // // let x: Option2; // x.Some.0 = 42; // x.Some.1 = panic(); // SetDiscriminant(x, Some); // ``` // However, for now we don't generate such MIR, and this check here *has* found real // bugs (see https://github.com/rust-lang/rust/issues/115145), so we will keep rejecting // it. assert!(!layout.abi.is_uninhabited()); </del> <ins> // This variant may in fact be uninhabited. // See <https://github.com/rust-lang/rust/issues/120337>. </ins> // This cannot be `transmute` as variants *can* have a smaller size than the entire enum. base.offset(Size::ZERO, layout, self)


/// "Downcast" to a variant of an enum or a coroutine. /// /// The included Symbol is the name of the variant, used for printing MIR. <ins> /// /// This operation itself is never UB, all it does is change the type of the place. </ins> Downcast(Option<Symbol>, VariantIdx), /// Like an explicit cast from an opaque type to a concrete type, but without


operand, &mut |elem, op| match elem { TrackElem::Field(idx) => self.ecx.project_field(op, idx.as_usize()).ok(), <del> TrackElem::Variant(idx) => { if op.layout.for_variant(&self.ecx, idx).abi.is_uninhabited() { return None; } self.ecx.project_downcast(op, idx).ok() } </del> <ins> TrackElem::Variant(idx) => self.ecx.project_downcast(op, idx).ok(), </ins> TrackElem::Discriminant => { let variant = self.ecx.read_discriminant(op).ok()?; let discr_value =


<ins> // Validation stops the test before the ICE we used to hit //@compile-flags: -Zmiri-disable-validation #![feature(never_type)] #[derive(Copy, Clone)] pub enum E { A(!), } pub union U { u: (), e: E, } fn main() { let E::A(ref _a) = unsafe { &(&U { u: () }).e }; } </ins>


<ins> - // MIR for `f` before GVN + // MIR for `f` after GVN fn f() -> u32 { let mut _0: u32; let _1: u32; let mut _2: E; let mut _3: &U; let _4: U; scope 1 { debug i => _1; } scope 2 { let mut _5: &U; } bb0: { StorageLive(_2); StorageLive(_3); _5 = const _; _3 = &(*_5); _2 = ((*_3).1: E); StorageLive(_1); -         _1 = ((_2 as A).1: u32); +         _1 = const 0_u32; StorageDead(_3); StorageDead(_2); -         _0 = _1; +         _0 = const 0_u32; StorageDead(_1); return; } } </ins>


<ins> // unit-test: GVN // compile-flags: -O // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // skip-filecheck #![feature(never_type)] #[derive(Copy, Clone)] pub enum E { A(!, u32), } pub union U { i: u32, e: E, } // EMIT_MIR gvn_uninhabited.f.GVN.diff pub const fn f() -> u32 { let E::A(_, i) = unsafe { (&U { i: 0 }).e }; i } fn main() {} </ins>


<ins> // check-pass #![feature(never_type)] #[derive(Copy, Clone)] pub enum E { A(!), } pub union U { u: (), e: E, } pub const C: () = { let E::A(ref a) = unsafe { &(&U { u: () }).e}; }; fn main() {} </ins>


BuiltinLintDiagnostics::UnexpectedCfgName((name, name_span), value) => { let possibilities: Vec<Symbol> = sess.parse_sess.check_config.expecteds.keys().copied().collect(); <ins> let mut names_possibilities: Vec<_> = if value.is_none() { // We later sort and display all the possibilities, so the order here does not matter. #[allow(rustc::potential_query_instability)] sess.parse_sess .check_config .expecteds .iter() .filter_map(|(k, v)| match v { ExpectedValues::Some(v) if v.contains(&Some(name)) => Some(k), _ => None, }) .collect() } else { Vec::new() }; </ins> let is_from_cargo = std::env::var_os("CARGO").is_some(); let mut is_feature_cfg = name == sym::feature;


} is_feature_cfg |= best_match == sym::feature; <del> } else if !possibilities.is_empty() { let mut possibilities = possibilities.iter().map(Symbol::as_str).collect::<Vec<_>>(); possibilities.sort(); let possibilities = possibilities.join("`, `"); </del> <ins> } else { if !names_possibilities.is_empty() && names_possibilities.len() <= 3 { names_possibilities.sort(); for cfg_name in names_possibilities.iter() { db.span_suggestion( name_span, "found config with similar value", format!("{cfg_name} = "{name}""), Applicability::MaybeIncorrect, ); } } if !possibilities.is_empty() { let mut possibilities = possibilities.iter().map(Symbol::as_str).collect::<Vec<_>>(); possibilities.sort(); let possibilities = possibilities.join("`, `"); </ins> <del> // The list of expected names can be long (even by default) and // so the diagnostic produced can take a lot of space. To avoid // cloging the user output we only want to print that diagnostic // once. db.help_once(format!("expected names are: `{possibilities}`")); </del> <ins> // The list of expected names can be long (even by default) and // so the diagnostic produced can take a lot of space. To avoid // cloging the user output we only want to print that diagnostic // once. db.help_once(format!("expected names are: `{possibilities}`")); } </ins> } let inst = if let Some((value, _value_span)) = value {


<ins> // #120427 // This test checks we won't suggest more than 3 span suggestions for cfg names // // check-pass // compile-flags: -Z unstable-options // compile-flags: --check-cfg=cfg(foo,values("value")) --check-cfg=cfg(bar,values("value")) --check-cfg=cfg(bee,values("value")) --check-cfg=cfg(cow,values("value")) #[cfg(value)] //~^ WARNING unexpected `cfg` condition name: `value` fn x() {} fn main() {} </ins>


<ins> warning: unexpected `cfg` condition name: `value` --> $DIR/cfg-value-for-cfg-name-duplicate.rs:8:7 | LL | #[cfg(value)] |       ^^^^^ | = help: expected names are: `bar`, `bee`, `cow`, `debug_assertions`, `doc`, `doctest`, `foo`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` = help: to expect this configuration use `--check-cfg=cfg(value)` = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default warning: 1 warning emitted </ins>


<ins> // #120427 // This test checks that when a single cfg has a value for user's specified name // // check-pass // compile-flags: -Z unstable-options // compile-flags: --check-cfg=cfg(foo,values("my_value")) --check-cfg=cfg(bar,values("my_value")) #[cfg(my_value)] //~^ WARNING unexpected `cfg` condition name: `my_value` fn x() {} fn main() {} </ins>


<ins> warning: unexpected `cfg` condition name: `my_value` --> $DIR/cfg-value-for-cfg-name-multiple.rs:8:7 | LL | #[cfg(my_value)] |       ^^^^^^^^ | = help: expected names are: `bar`, `debug_assertions`, `doc`, `doctest`, `foo`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` = help: to expect this configuration use `--check-cfg=cfg(my_value)` = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default help: found config with similar value | LL | #[cfg(foo = "my_value")] |       ~~~~~~~~~~~~~~~~ help: found config with similar value | LL | #[cfg(bar = "my_value")] |       ~~~~~~~~~~~~~~~~ warning: 1 warning emitted </ins>


<ins> // #120427 // This test checks that when a single cfg has a value for user's specified name // suggest to use `#[cfg(target_os = "linux")]` instead of `#[cfg(linux)]` // // check-pass // compile-flags: -Z unstable-options // compile-flags: --check-cfg=cfg() #[cfg(linux)] //~^ WARNING unexpected `cfg` condition name: `linux` fn x() {} // will not suggest if the cfg has a value #[cfg(linux = "os-name")] //~^ WARNING unexpected `cfg` condition name: `linux` fn y() {} fn main() {} </ins>


<ins> warning: unexpected `cfg` condition name: `linux` --> $DIR/cfg-value-for-cfg-name.rs:9:7 | LL | #[cfg(linux)] |       ^^^^^ help: found config with similar value: `target_os = "linux"` | = help: expected names are: `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` = help: to expect this configuration use `--check-cfg=cfg(linux)` = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition name: `linux` --> $DIR/cfg-value-for-cfg-name.rs:14:7 | LL | #[cfg(linux = "os-name")] |       ^^^^^^^^^^^^^^^^^ | = help: to expect this configuration use `--check-cfg=cfg(linux, values("os-name"))` = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration warning: 2 warnings emitted </ins>


type summary add -F lldb_lookup.summary_lookup  -e -x -h "^(core::([a-z_]+::)+)RefMut<.+>$" --category Rust type summary add -F lldb_lookup.summary_lookup  -e -x -h "^(core::([a-z_]+::)+)RefCell<.+>$" --category Rust type summary add -F lldb_lookup.summary_lookup  -e -x -h "^(core::([a-z_]+::)+)NonZero<.+>$" --category Rust <ins> type summary add -F lldb_lookup.summary_lookup  -e -x -h "^core::num::([a-z_]+::)*NonZero.+$" --category Rust type summary add -F lldb_lookup.summary_lookup  -e -x -h "^(std::([a-z_]+::)+)PathBuf$" --category Rust type summary add -F lldb_lookup.summary_lookup  -e -x -h "^&(mut )?(std::([a-z_]+::)+)Path$" --category Rust </ins> type category enable Rust


if rust_type == RustType.STD_NONZERO_NUMBER: return StdNonZeroNumberSummaryProvider(valobj, dict) <ins> if rust_type == RustType.STD_PATHBUF: return StdPathBufSummaryProvider(valobj, dict) if rust_type == RustType.STD_PATH: return StdPathSummaryProvider(valobj, dict) </ins> return ""


return '"%s"' % data <ins> def StdPathBufSummaryProvider(valobj, dict): # type: (SBValue, dict) -> str # logger = Logger.Logger() # logger >> "[StdPathBufSummaryProvider] for " + str(valobj.GetName()) return StdOsStringSummaryProvider(valobj.GetChildMemberWithName("inner"), dict) def StdPathSummaryProvider(valobj, dict): # type: (SBValue, dict) -> str # logger = Logger.Logger() # logger >> "[StdPathSummaryProvider] for " + str(valobj.GetName()) length = valobj.GetChildMemberWithName("length").GetValueAsUnsigned() if length == 0: return '""' data_ptr = valobj.GetChildMemberWithName("data_ptr") start = data_ptr.GetValueAsUnsigned() error = SBError() process = data_ptr.GetProcess() data = process.ReadMemory(start, length, error) if PY3: try: data = data.decode(encoding='UTF-8') except UnicodeDecodeError: return '%r' % data return '"%s"' % data </ins> class StructSyntheticProvider: """Pretty-printer for structs and struct enum variants"""


STD_REF_MUT = "StdRefMut" STD_REF_CELL = "StdRefCell" STD_NONZERO_NUMBER = "StdNonZeroNumber" <ins> STD_PATH = "StdPath" STD_PATHBUF = "StdPathBuf" </ins> STD_STRING_REGEX = re.compile(r"^(alloc::([a-z_]+::)+)String$")


STD_REF_MUT_REGEX = re.compile(r"^(core::([a-z_]+::)+)RefMut<.+>$") STD_REF_CELL_REGEX = re.compile(r"^(core::([a-z_]+::)+)RefCell<.+>$") STD_NONZERO_NUMBER_REGEX = re.compile(r"^(core::([a-z_]+::)+)NonZero<.+>$") <ins> STD_PATHBUF_REGEX = re.compile(r"^(std::([a-z_]+::)+)PathBuf$") STD_PATH_REGEX =  re.compile(r"^&(mut )?(std::([a-z_]+::)+)Path$") </ins> TUPLE_ITEM_REGEX = re.compile(r"__d+$")


RustType.STD_REF_CELL: STD_REF_CELL_REGEX, RustType.STD_CELL: STD_CELL_REGEX, RustType.STD_NONZERO_NUMBER: STD_NONZERO_NUMBER_REGEX, <ins> RustType.STD_PATHBUF: STD_PATHBUF_REGEX, RustType.STD_PATH: STD_PATH_REGEX, </ins> } def is_tuple_fields(fields):


<ins> //@ ignore-gdb //@ compile-flags:-g // === LLDB TESTS ================================================================================= // lldb-command:run // lldb-command:print pathbuf // lldb-check:[...] "/some/path" { inner = "/some/path" { inner = { inner = size=10 { [0] = '/' [1] = 's' [2] = 'o' [3] = 'm' [4] = 'e' [5] = '/' [6] = 'p' [7] = 'a' [8] = 't' [9] = 'h' } } } } // lldb-command:po pathbuf // lldb-check:"/some/path" // lldb-command:print path // lldb-check:[...] "/some/path" { data_ptr = [...] length = 10 } // lldb-command:po path // lldb-check:"/some/path" use std::path::Path; fn main() { let path = Path::new("/some/path"); let pathbuf = path.to_path_buf(); zzz(); // #break } fn zzz() { () } </ins>


padding: 2px 4px; box-shadow: 0 0 4px var(--main-background-color); } <ins> .item-table > li > .item-name { width: 33%; } .item-table > li > div { padding-bottom: 5px; word-break: break-all; } </ins> } @media print {


pub type ReallyLongTypeNameLongLongLong = Option<unsafe extern "C" fn(a: *const u8, b: *const u8) -> *const u8>; <ins> /// Short doc. </ins> pub const ReallyLongTypeNameLongLongLongConstBecauseWhyNotAConstRightGigaGigaSupraLong: u32 = 0; /// This also has a really long doccomment. Lorem ipsum dolor sit amet,


// In the table-ish view on the module index, the name should not be wrapped more than necessary. go-to: "file://" + |DOC_PATH| + "/lib2/too_long/index.html" <del> assert-property: (".item-table .struct", {"offsetWidth": "684"}) </del> <ins> // We'll ensure that items with short documentation have the same width. store-property: ("//*[@class='item-table']//*[@class='struct']/..", {"offsetWidth": offset_width}) assert: |offset_width| == "277" assert-property: ("//*[@class='item-table']//*[@class='constant']/..", {"offsetWidth": |offset_width|}) </ins> // We now make the same check on type declaration... go-to: "file://" + |DOC_PATH| + "/lib2/too_long/type.ReallyLongTypeNameLongLongLong.html"


self.lookup_and_handle_method(expr.hir_id); } hir::ExprKind::Field(ref lhs, ..) => { <del> self.handle_field_access(lhs, expr.hir_id); </del> <ins> if self.typeck_results().opt_field_index(expr.hir_id).is_some() { self.handle_field_access(lhs, expr.hir_id); } else { self.tcx.dcx().span_delayed_bug(expr.span, "couldn't resolve index for field"); } </ins> } hir::ExprKind::Struct(qpath, fields, _) => { let res = self.typeck_results().qpath_res(qpath, expr.hir_id);


<ins> // Regression test for issue #120615. fn main() { [(); loop {}].field; //~ ERROR constant evaluation is taking a long time } </ins>


<ins> error: constant evaluation is taking a long time --> $DIR/field-access-after-const-eval-fail-in-ty.rs:4:10 | LL |     [(); loop {}].field; |          ^^^^^^^ | = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval. If your compilation actually takes a long time, you can safely allow the lint. help: the constant being evaluated --> $DIR/field-access-after-const-eval-fail-in-ty.rs:4:10 | LL |     [(); loop {}].field; |          ^^^^^^^ = note: `#[deny(long_running_const_eval)]` on by default error: aborting due to 1 previous error </ins>


}); } <del> let path = if trees.is_empty() && !prefix.segments.is_empty() { </del> <ins> // Condition should match `build_reduced_graph_for_use_tree`. let path = if trees.is_empty() && !(prefix.segments.is_empty() || prefix.segments.len() == 1 && prefix.segments[0].ident.name == kw::PathRoot) { </ins> // For empty lists we need to lower the prefix so it is checked for things // like stability later. let res = self.lower_import_res(id, span);


<ins> // check-pass // edition:2015 use {}; use {{}}; use ::{}; use {::{}}; fn main() {} </ins>


<ins> // check-pass // edition:2018 use {}; use {{}}; use ::{}; use {::{}}; fn main() {} </ins>


use crate::common; use crate::traits::*; use rustc_hir as hir; <ins> use rustc_middle::mir::interpret::ErrorHandled; </ins> use rustc_middle::mir::mono::MonoItem; use rustc_middle::mir::mono::{Linkage, Visibility}; use rustc_middle::ty;


.iter() .map(|(op, op_sp)| match *op { hir::InlineAsmOperand::Const { ref anon_const } => { <del> let const_value = cx .tcx() .const_eval_poly(anon_const.def_id.to_def_id()) .unwrap_or_else(|_| { span_bug!(*op_sp, "asm const cannot be resolved") }); let ty = cx .tcx() .typeck_body(anon_const.body) .node_type(anon_const.hir_id); let string = common::asm_const_to_str( cx.tcx(), *op_sp, const_value, cx.layout_of(ty), ); GlobalAsmOperandRef::Const { string } </del> <ins> match cx.tcx().const_eval_poly(anon_const.def_id.to_def_id()) { Ok(const_value) => { let ty = cx .tcx() .typeck_body(anon_const.body) .node_type(anon_const.hir_id); let string = common::asm_const_to_str( cx.tcx(), *op_sp, const_value, cx.layout_of(ty), ); GlobalAsmOperandRef::Const { string } } Err(ErrorHandled::Reported { .. }) => { // An error has already been reported and // compilation is guaranteed to fail if execution // hits this path. So an empty string instead of // a stringified constant value will suffice. GlobalAsmOperandRef::Const { string: String::new() } } Err(ErrorHandled::TooGeneric(_)) => { span_bug!( *op_sp, "asm const cannot be resolved; too generic" ) } } </ins> } hir::InlineAsmOperand::SymFn { ref anon_const } => { let ty = cx


<ins> //@ build-fail //@ needs-asm-support #![feature(asm_const)] use std::arch::global_asm; fn main() {} global_asm!("/* {} */", const 1 << 500); //~ ERROR evaluation of constant value failed [E0080] global_asm!("/* {} */", const 1 / 0); //~ ERROR evaluation of constant value failed [E0080] </ins>


<ins> error[E0080]: evaluation of constant value failed --> $DIR/fail-const-eval-issue-121099.rs:9:31 | LL | global_asm!("/* {} */", const 1 << 500); |                               ^^^^^^^^ attempt to shift left by `500_i32`, which would overflow error[E0080]: evaluation of constant value failed --> $DIR/fail-const-eval-issue-121099.rs:11:31 | LL | global_asm!("/* {} */", const 1 / 0); |                               ^^^^^ attempt to divide `1_i32` by zero error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0080`. </ins>


} (PlaceElem::Index(idx), Value::Aggregate { fields, .. }) => { let idx = prop.get_const(idx.into())?.immediate()?; <del> let idx = prop.ecx.read_target_usize(idx).ok()?; fields.get(FieldIdx::from_u32(idx.try_into().ok()?)).unwrap_or(&Value::Uninit) </del> <ins> let idx = prop.ecx.read_target_usize(idx).ok()?.try_into().ok()?; if idx <= FieldIdx::MAX_AS_U32 { fields.get(FieldIdx::from_u32(idx)).unwrap_or(&Value::Uninit) } else { return None; } </ins> } ( PlaceElem::ConstantIndex { offset, min_length: _, from_end: false },


<del> //@ known-bug: #121126 fn main() { let _n = 1i64 >> [64][4_294_967_295]; } </del>


<ins> //@ build-fail fn main() { let _n = [64][200]; //~^ ERROR this operation will panic at runtime [unconditional_panic] // issue #121126, test index value between 0xFFFF_FF00 and u32::MAX let _n = [64][u32::MAX as usize - 1]; //~^ ERROR this operation will panic at runtime [unconditional_panic] } </ins>


<ins> error: this operation will panic at runtime --> $DIR/index-bounds.rs:4:14 | LL |     let _n = [64][200]; |              ^^^^^^^^^ index out of bounds: the length is 1 but the index is 200 | = note: `#[deny(unconditional_panic)]` on by default error: this operation will panic at runtime --> $DIR/index-bounds.rs:8:14 | LL |     let _n = [64][u32::MAX as usize - 1]; |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the length is 1 but the index is 4294967294 error: aborting due to 2 previous errors </ins>


fn parse_crate_mod(&mut self) -> Result<ast::Crate, ParserError> { let mut parser = AssertUnwindSafe(&mut self.parser); <del> match catch_unwind(move || parser.parse_crate_mod()) { Ok(Ok(k)) => Ok(k), Ok(Err(db)) => { </del> <ins> // rustfmt doesn't use `run_compiler` like other tools, so it must emit // any stashed diagnostics itself, otherwise the `DiagCtxt` will assert // when dropped. The final result here combines the parsing result and // the `emit_stashed_diagnostics` result. let parse_res = catch_unwind(move || parser.parse_crate_mod()); let stashed_res = self.parser.dcx().emit_stashed_diagnostics(); let err = Err(ParserError::ParsePanicError); match (parse_res, stashed_res) { (Ok(Ok(k)), None) => Ok(k), (Ok(Ok(_)), Some(_guar)) => err, (Ok(Err(db)), _) => { </ins> db.emit(); <del> Err(ParserError::ParseError) </del> <ins> err </ins> } <del> Err(_) => Err(ParserError::ParsePanicError), </del> <ins> (Err(_), _) => err, </ins> } } }


let filename = "tests/parser/unclosed-delims/issue_4466.rs"; assert_parser_error(filename); } <ins> #[test] fn crate_parsing_stashed_diag() { // See also https://github.com/rust-lang/rust/issues/121450 let filename = "tests/parser/stashed-diag.rs"; assert_parser_error(filename); } </ins>


<ins> #![u={static N;}] fn main() {} </ins>


margin: 0 auto; padding: 0 15px; font-size: 18px; <del> color: #333; </del> <ins> color: #000; </ins> line-height: 1.428571429; -webkit-box-sizing: unset; -moz-box-sizing: unset; box-sizing: unset; <ins> background: #fff; </ins> } @media (min-width: 768px) { body {


padding: 5px 10px; } h5, h6 { <del> color: black; </del> text-decoration: underline; }


<del> Subproject commit 7973f3560287d750500718314a0fd4025bd8ac0e </del> <ins> Subproject commit 84f190a4abf58bbd5301c0fc831f7a96acea246f </ins>


use rustc_middle::query::on_disk_cache::AbsoluteBytePos; use rustc_middle::query::on_disk_cache::{CacheDecoder, CacheEncoder, EncodedDepNodeIndex}; use rustc_middle::query::Key; <ins> use rustc_middle::ty::print::with_reduced_queries; </ins> use rustc_middle::ty::tls::{self, ImplicitCtxt}; use rustc_middle::ty::{self, TyCtxt}; use rustc_query_system::dep_graph::{DepNodeParams, HasDepContext};


kind: DepKind, name: &'static str, ) -> QueryStackFrame { <ins> // If reduced queries are requested, we may be printing a query stack due // to a panic. Avoid using `default_span` and `def_kind` in that case. let reduce_queries = with_reduced_queries(); </ins> // Avoid calling queries while formatting the description let description = ty::print::with_no_queries!(do_describe(tcx, key)); let description = if tcx.sess.verbose_internals() {


} else { description }; <del> let span = if kind == dep_graph::dep_kinds::def_span { </del> <ins> let span = if kind == dep_graph::dep_kinds::def_span || reduce_queries { </ins> // The `def_span` query is used to calculate `default_span`, // so exit to avoid infinite recursion. None


Some(key.default_span(tcx)) }; let def_id = key.key_as_def_id(); <del> let def_kind = if kind == dep_graph::dep_kinds::def_kind { </del> <ins> let def_kind = if kind == dep_graph::dep_kinds::def_kind || reduce_queries { </ins> // Try to avoid infinite recursion. None } else {


#[unstable(feature = "slice_index_methods", issue = "none")] fn get_mut(self, slice: &mut T) -> Option<&mut Self::Output>; <del> /// Returns a shared reference to the output at this location, without </del> <ins> /// Returns a pointer to the output at this location, without </ins> /// performing any bounds checking. /// Calling this method with an out-of-bounds index or a dangling `slice` pointer <del> /// is *[undefined behavior]* even if the resulting reference is not used. </del> <ins> /// is *[undefined behavior]* even if the resulting pointer is not used. </ins> /// /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html #[unstable(feature = "slice_index_methods", issue = "none")] unsafe fn get_unchecked(self, slice: *const T) -> *const Self::Output; <del> /// Returns a mutable reference to the output at this location, without </del> <ins> /// Returns a mutable pointer to the output at this location, without </ins> /// performing any bounds checking. /// Calling this method with an out-of-bounds index or a dangling `slice` pointer <del> /// is *[undefined behavior]* even if the resulting reference is not used. </del> <ins> /// is *[undefined behavior]* even if the resulting pointer is not used. </ins> /// /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html #[unstable(feature = "slice_index_methods", issue = "none")]


trait_selection_closure_kind_requirement = the requirement to implement `{$trait_prefix}{$expected}` derives from here <ins> trait_selection_disallowed_positional_argument = positional format arguments are not allowed here .help = only named format arguments with the name of one of the generic types are allowed in this context </ins> trait_selection_dump_vtable_entries = vtable entries for `{$trait_ref}`: {$entries} trait_selection_empty_on_clause_in_rustc_on_unimplemented = empty `on`-clause in `#[rustc_on_unimplemented]`


trait_selection_inherent_projection_normalization_overflow = overflow evaluating associated type `{$ty}` <ins> trait_selection_invalid_format_specifier = invalid format specifier .help = no format specifier are supported in this position </ins> trait_selection_invalid_on_clause_in_rustc_on_unimplemented = invalid `on`-clause in `#[rustc_on_unimplemented]` .label = invalid on-clause here


trait_selection_unknown_format_parameter_for_on_unimplemented_attr = there is no parameter `{$argument_name}` on trait `{$trait_name}` .help = expect either a generic argument name or {"`{Self}`"} as format argument <ins> trait_selection_wrapped_parser_error = {$description} .label = {$label} </ins>


trait_name: Symbol, } <ins> #[derive(LintDiagnostic)] #[diag(trait_selection_disallowed_positional_argument)] #[help] pub struct DisallowedPositionalArgument; #[derive(LintDiagnostic)] #[diag(trait_selection_invalid_format_specifier)] #[help] pub struct InvalidFormatSpecifier; #[derive(LintDiagnostic)] #[diag(trait_selection_wrapped_parser_error)] pub struct WrappedParserError { description: String, label: String, } </ins> impl<'tcx> OnUnimplementedDirective { fn parse( tcx: TyCtxt<'tcx>,


let trait_name = tcx.item_name(trait_def_id); let generics = tcx.generics_of(item_def_id); let s = self.symbol.as_str(); <del> let parser = Parser::new(s, None, None, false, ParseMode::Format); </del> <ins> let mut parser = Parser::new(s, None, None, false, ParseMode::Format); </ins> let mut result = Ok(()); <del> for token in parser { </del> <ins> for token in &mut parser { </ins> match token { Piece::String(_) => (), // Normal string, no need to check it <del> Piece::NextArgument(a) => match a.position { Position::ArgumentNamed(s) => { match Symbol::intern(s) { // `{ThisTraitsName}` is allowed s if s == trait_name && !self.is_diagnostic_namespace_variant => (), s if ALLOWED_FORMAT_SYMBOLS.contains(&s) && !self.is_diagnostic_namespace_variant => { () } // So is `{A}` if A is a type parameter s if generics.params.iter().any(|param| param.name == s) => (), s => { if self.is_diagnostic_namespace_variant { tcx.emit_node_span_lint( UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, tcx.local_def_id_to_hir_id(item_def_id.expect_local()), self.span, UnknownFormatParameterForOnUnimplementedAttr { argument_name: s, trait_name, }, ); } else { result = Err(struct_span_code_err!( tcx.dcx(), self.span, E0230, "there is no parameter `{}` on {}", s, if trait_def_id == item_def_id { format!("trait `{trait_name}`") } else { "impl".to_string() } ) .emit()); </del> <ins> Piece::NextArgument(a) => { let format_spec = a.format; if self.is_diagnostic_namespace_variant && (format_spec.ty_span.is_some() || format_spec.width_span.is_some() || format_spec.precision_span.is_some() || format_spec.fill_span.is_some()) { tcx.emit_node_span_lint( UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, tcx.local_def_id_to_hir_id(item_def_id.expect_local()), self.span, InvalidFormatSpecifier, ); } match a.position { Position::ArgumentNamed(s) => { match Symbol::intern(s) { // `{ThisTraitsName}` is allowed s if s == trait_name && !self.is_diagnostic_namespace_variant => (), s if ALLOWED_FORMAT_SYMBOLS.contains(&s) && !self.is_diagnostic_namespace_variant => { () } // So is `{A}` if A is a type parameter s if generics.params.iter().any(|param| param.name == s) => (), s => { if self.is_diagnostic_namespace_variant { tcx.emit_node_span_lint( UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, tcx.local_def_id_to_hir_id(item_def_id.expect_local()), self.span, UnknownFormatParameterForOnUnimplementedAttr { argument_name: s, trait_name, }, ); } else { result = Err(struct_span_code_err!( tcx.dcx(), self.span, E0230, "there is no parameter `{}` on {}", s, if trait_def_id == item_def_id { format!("trait `{trait_name}`") } else { "impl".to_string() } ) .emit()); } </ins> } } } <ins> // `{:1}` and `{}` are not to be used Position::ArgumentIs(..) | Position::ArgumentImplicitlyIs(_) => { if self.is_diagnostic_namespace_variant { tcx.emit_node_span_lint( UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, tcx.local_def_id_to_hir_id(item_def_id.expect_local()), self.span, DisallowedPositionalArgument, ); } else { let reported = struct_span_code_err!( tcx.dcx(), self.span, E0231, "only named generic parameters are allowed" ) .emit(); result = Err(reported); } } </ins> } <del> // `{:1}` and `{}` are not to be used Position::ArgumentIs(..) | Position::ArgumentImplicitlyIs(_) => { let reported = struct_span_code_err!( tcx.dcx(), self.span, E0231, "only named generic parameters are allowed" ) .emit(); result = Err(reported); } }, </del> <ins> } } } // we cannot return errors from processing the format string as hard error here // as the diagnostic namespace gurantees that malformed input cannot cause an error // // if we encounter any error while processing we nevertheless want to show it as warning // so that users are aware that something is not correct for e in parser.errors { if self.is_diagnostic_namespace_variant { tcx.emit_node_span_lint( UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, tcx.local_def_id_to_hir_id(item_def_id.expect_local()), self.span, WrappedParserError { description: e.description, label: e.label }, ); } else { let reported = struct_span_code_err!(tcx.dcx(), self.span, E0231, "{}", e.description,).emit(); result = Err(reported); </ins> } }


let empty_string = String::new(); let s = self.symbol.as_str(); <del> let parser = Parser::new(s, None, None, false, ParseMode::Format); </del> <ins> let mut parser = Parser::new(s, None, None, false, ParseMode::Format); </ins> let item_context = (options.get(&sym::ItemContext)).unwrap_or(&empty_string); <del> parser </del> <ins> let constructed_message = (&mut parser) </ins> .map(|p| match p { Piece::String(s) => s.to_owned(), Piece::NextArgument(a) => match a.position {


} } } <ins> Position::ArgumentImplicitlyIs(_) if self.is_diagnostic_namespace_variant => { String::from("{}") } Position::ArgumentIs(idx) if self.is_diagnostic_namespace_variant => { format!("{{{idx}}}") } </ins> _ => bug!("broken on_unimplemented {:?} - bad format arg", self.symbol), }, }) <del> .collect() </del> <ins> .collect(); // we cannot return errors from processing the format string as hard error here // as the diagnostic namespace gurantees that malformed input cannot cause an error // // if we encounter any error while processing the format string // we don't want to show the potentially half assembled formated string, // therefore we fall back to just showing the input string in this case // // The actual parser errors are emitted earlier // as lint warnings in OnUnimplementedFormatString::verify if self.is_diagnostic_namespace_variant && !parser.errors.is_empty() { String::from(s) } else { constructed_message } </ins> } }


<ins> #[diagnostic::on_unimplemented(message = "{{Test } thing")] //~^WARN unmatched `}` found //~|WARN unmatched `}` found trait ImportantTrait1 {} #[diagnostic::on_unimplemented(message = "Test {}")] //~^WARN positional format arguments are not allowed here //~|WARN positional format arguments are not allowed here trait ImportantTrait2 {} #[diagnostic::on_unimplemented(message = "Test {1:}")] //~^WARN positional format arguments are not allowed here //~|WARN positional format arguments are not allowed here trait ImportantTrait3 {} #[diagnostic::on_unimplemented(message = "Test {Self:123}")] //~^WARN invalid format specifier //~|WARN invalid format specifier trait ImportantTrait4 {} #[diagnostic::on_unimplemented(message = "Test {Self:!}")] //~^WARN expected `'}'`, found `'!'` //~|WARN expected `'}'`, found `'!'` //~|WARN unmatched `}` found //~|WARN unmatched `}` found trait ImportantTrait5 {} fn check_1(_: impl ImportantTrait1) {} fn check_2(_: impl ImportantTrait2) {} fn check_3(_: impl ImportantTrait3) {} fn check_4(_: impl ImportantTrait4) {} fn check_5(_: impl ImportantTrait5) {} fn main() { check_1(()); //~^ERROR {{Test } thing check_2(()); //~^ERROR Test {} check_3(()); //~^ERROR Test {1} check_4(()); //~^ERROR Test () check_5(()); //~^ERROR Test {Self:!} } </ins>


<ins> warning: unmatched `}` found --> $DIR/broken_format.rs:1:32 | LL | #[diagnostic::on_unimplemented(message = "{{Test } thing")] |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default warning: positional format arguments are not allowed here --> $DIR/broken_format.rs:6:32 | LL | #[diagnostic::on_unimplemented(message = "Test {}")] |                                ^^^^^^^^^^^^^^^^^^^ | = help: only named format arguments with the name of one of the generic types are allowed in this context warning: positional format arguments are not allowed here --> $DIR/broken_format.rs:11:32 | LL | #[diagnostic::on_unimplemented(message = "Test {1:}")] |                                ^^^^^^^^^^^^^^^^^^^^^ | = help: only named format arguments with the name of one of the generic types are allowed in this context warning: invalid format specifier --> $DIR/broken_format.rs:16:32 | LL | #[diagnostic::on_unimplemented(message = "Test {Self:123}")] |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: no format specifier are supported in this position warning: expected `'}'`, found `'!'` --> $DIR/broken_format.rs:21:32 | LL | #[diagnostic::on_unimplemented(message = "Test {Self:!}")] |                                ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unmatched `}` found --> $DIR/broken_format.rs:21:32 | LL | #[diagnostic::on_unimplemented(message = "Test {Self:!}")] |                                ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unmatched `}` found --> $DIR/broken_format.rs:1:32 | LL | #[diagnostic::on_unimplemented(message = "{{Test } thing")] |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: {{Test } thing --> $DIR/broken_format.rs:35:13 | LL |     check_1(()); |     ------- ^^ the trait `ImportantTrait1` is not implemented for `()` |     | |     required by a bound introduced by this call | help: this trait has no implementations, consider adding one --> $DIR/broken_format.rs:4:1 | LL | trait ImportantTrait1 {} | ^^^^^^^^^^^^^^^^^^^^^ note: required by a bound in `check_1` --> $DIR/broken_format.rs:28:20 | LL | fn check_1(_: impl ImportantTrait1) {} |                    ^^^^^^^^^^^^^^^ required by this bound in `check_1` warning: positional format arguments are not allowed here --> $DIR/broken_format.rs:6:32 | LL | #[diagnostic::on_unimplemented(message = "Test {}")] |                                ^^^^^^^^^^^^^^^^^^^ | = help: only named format arguments with the name of one of the generic types are allowed in this context = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: Test {} --> $DIR/broken_format.rs:37:13 | LL |     check_2(()); |     ------- ^^ the trait `ImportantTrait2` is not implemented for `()` |     | |     required by a bound introduced by this call | help: this trait has no implementations, consider adding one --> $DIR/broken_format.rs:9:1 | LL | trait ImportantTrait2 {} | ^^^^^^^^^^^^^^^^^^^^^ note: required by a bound in `check_2` --> $DIR/broken_format.rs:29:20 | LL | fn check_2(_: impl ImportantTrait2) {} |                    ^^^^^^^^^^^^^^^ required by this bound in `check_2` warning: positional format arguments are not allowed here --> $DIR/broken_format.rs:11:32 | LL | #[diagnostic::on_unimplemented(message = "Test {1:}")] |                                ^^^^^^^^^^^^^^^^^^^^^ | = help: only named format arguments with the name of one of the generic types are allowed in this context = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: Test {1} --> $DIR/broken_format.rs:39:13 | LL |     check_3(()); |     ------- ^^ the trait `ImportantTrait3` is not implemented for `()` |     | |     required by a bound introduced by this call | help: this trait has no implementations, consider adding one --> $DIR/broken_format.rs:14:1 | LL | trait ImportantTrait3 {} | ^^^^^^^^^^^^^^^^^^^^^ note: required by a bound in `check_3` --> $DIR/broken_format.rs:30:20 | LL | fn check_3(_: impl ImportantTrait3) {} |                    ^^^^^^^^^^^^^^^ required by this bound in `check_3` warning: invalid format specifier --> $DIR/broken_format.rs:16:32 | LL | #[diagnostic::on_unimplemented(message = "Test {Self:123}")] |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: no format specifier are supported in this position = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: Test () --> $DIR/broken_format.rs:41:13 | LL |     check_4(()); |     ------- ^^ the trait `ImportantTrait4` is not implemented for `()` |     | |     required by a bound introduced by this call | help: this trait has no implementations, consider adding one --> $DIR/broken_format.rs:19:1 | LL | trait ImportantTrait4 {} | ^^^^^^^^^^^^^^^^^^^^^ note: required by a bound in `check_4` --> $DIR/broken_format.rs:31:20 | LL | fn check_4(_: impl ImportantTrait4) {} |                    ^^^^^^^^^^^^^^^ required by this bound in `check_4` warning: expected `'}'`, found `'!'` --> $DIR/broken_format.rs:21:32 | LL | #[diagnostic::on_unimplemented(message = "Test {Self:!}")] |                                ^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: unmatched `}` found --> $DIR/broken_format.rs:21:32 | LL | #[diagnostic::on_unimplemented(message = "Test {Self:!}")] |                                ^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: Test {Self:!} --> $DIR/broken_format.rs:43:13 | LL |     check_5(()); |     ------- ^^ the trait `ImportantTrait5` is not implemented for `()` |     | |     required by a bound introduced by this call | help: this trait has no implementations, consider adding one --> $DIR/broken_format.rs:26:1 | LL | trait ImportantTrait5 {} | ^^^^^^^^^^^^^^^^^^^^^ note: required by a bound in `check_5` --> $DIR/broken_format.rs:32:20 | LL | fn check_5(_: impl ImportantTrait5) {} |                    ^^^^^^^^^^^^^^^ required by this bound in `check_5` error: aborting due to 5 previous errors; 12 warnings emitted For more information about this error, try `rustc --explain E0277`. </ins>


<ins> //@ check-pass #![feature(type_alias_impl_trait)] fn spawn<T, F>(future: F) -> impl Sized where F: FnOnce() -> T, { future } fn spawn_task(sender: &'static ()) -> impl Sized { type Tait = impl Sized + 'static; spawn::<Tait, _>(move || sender) } fn main() {} </ins>


// FIXME: We should investigate the perf implications of not uniquifying // `ReErased`. We may be able to short-circuit registering region // obligations if we encounter a `ReErased` on one side, for example. <del> ty::ReStatic | ty::ReErased => match self.canonicalize_mode { </del> <ins> ty::ReStatic | ty::ReErased | ty::ReError(_) => match self.canonicalize_mode { </ins> CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT), CanonicalizeMode::Response { .. } => return r, },


} } } <del> ty::ReError(_) => return r, </del> }; let existing_bound_var = match self.canonicalize_mode {


<ins> //@ compile-flags: -Znext-solver trait Tr<'a> {} // Fulfillment in the new solver relies on an invariant to hold: Either // `has_changed` is true, or computing a goal's certainty is idempotent. // This isn't true for `ReError`, which we used to pass through in the // canonicalizer even on input mode, which can cause a goal to go from // ambig => pass, but we don't consider `has_changed` when the response // only contains region constraints (since we usually uniquify regions). // //   In this test: // Implicit negative coherence tries to prove `W<?0>: Constrain<'?1>`, // which will then match with the impl below. This constrains `'?1` to // `ReError`, but still bails w/ ambiguity bc we can't prove `?0: Sized`. // Then, when we recompute the goal `W<?0>: Constrain<'error>`, when // collecting ambiguities and overflows, we end up assembling a default // error candidate w/o ambiguity, which causes the goal to pass, and ICE. impl<'a, A: ?Sized> Tr<'a> for W<A> {} struct W<A: ?Sized>(A); impl<'a, A: ?Sized> Tr<'a> for A where A: Constrain<'a> {} //~^ ERROR conflicting implementations of trait `Tr<'_>` for type `W<_>` trait Constrain<'a> {} impl<A: Sized> Constrain<'missing> for W<A> {} //~^ ERROR use of undeclared lifetime name `'missing` fn main() {} </ins>


<ins> error[E0261]: use of undeclared lifetime name `'missing` --> $DIR/dont-canonicalize-re-error.rs:25:26 | LL | impl<A: Sized> Constrain<'missing> for W<A> {} |      -                   ^^^^^^^^ undeclared lifetime |      | |      help: consider introducing lifetime `'missing` here: `'missing,` error[E0119]: conflicting implementations of trait `Tr<'_>` for type `W<_>` --> $DIR/dont-canonicalize-re-error.rs:21:1 | LL | impl<'a, A: ?Sized> Tr<'a> for W<A> {} | ----------------------------------- first implementation here LL | struct W<A: ?Sized>(A); LL | impl<'a, A: ?Sized> Tr<'a> for A where A: Constrain<'a> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `W<_>` error: aborting due to 2 previous errors Some errors have detailed explanations: E0119, E0261. For more information about an error, try `rustc --explain E0119`. </ins>


tcx: TyCtxt<'tcx>, predicates: &List<ty::PolyExistentialPredicate<'tcx>>, ) -> &'tcx List<ty::PolyExistentialPredicate<'tcx>> { <del> let predicates: Vec<ty::PolyExistentialPredicate<'tcx>> = predicates .iter() .filter_map(|predicate| match predicate.skip_binder() { </del> <ins> tcx.mk_poly_existential_predicates_from_iter(predicates.iter().filter_map(|predicate| { match predicate.skip_binder() { </ins> ty::ExistentialPredicate::Trait(trait_ref) => { let trait_ref = ty::TraitRef::identity(tcx, trait_ref.def_id); Some(ty::Binder::dummy(ty::ExistentialPredicate::Trait(


} ty::ExistentialPredicate::Projection(..) => None, ty::ExistentialPredicate::AutoTrait(..) => Some(predicate), <del> }) .collect(); tcx.mk_poly_existential_predicates(&predicates) </del> <ins> } })) </ins> } /// Transforms args for being encoded and used in the substitution dictionary.


let ty::Dynamic(preds, lifetime, kind) = ty.kind() else { bug!("Tried to strip auto traits from non-dynamic type {ty}"); }; <del> let filtered_preds = if preds.principal().is_some() { </del> <ins> let new_rcvr = if preds.principal().is_some() { let filtered_preds = </ins> tcx.mk_poly_existential_predicates_from_iter(preds.into_iter().filter(|pred| { !matches!(pred.skip_binder(), ty::ExistentialPredicate::AutoTrait(..)) <del> })) } else { ty::List::empty() }; let new_rcvr = Ty::new_dynamic(tcx, filtered_preds, *lifetime, *kind); </del> <ins> })); Ty::new_dynamic(tcx, filtered_preds, *lifetime, *kind) } else { // If there's no principal type, re-encode it as a unit, since we don't know anything // about it. This technically discards the knowledge that it was a type that was made // into a trait object at some point, but that's not a lot. tcx.types.unit }; </ins> tcx.mk_args_trait(new_rcvr, args.into_iter().skip(1)) }


<ins> // Check that dropping a trait object without a principal trait succeeds //@ needs-sanitizer-cfi // FIXME(#122848) Remove only-linux once OSX CFI binaries works //@ only-linux //@ compile-flags: --crate-type=bin -Cprefer-dynamic=off -Clto -Zsanitizer=cfi //@ compile-flags: -C target-feature=-crt-static -C codegen-units=1 -C opt-level=0 // FIXME(#118761) Should be run-pass once the labels on drop are compatible. // This test is being landed ahead of that to test that the compiler doesn't ICE while labeling the // callsite for a drop, but the vtable doesn't have the correct label yet. //@ build-pass struct CustomDrop; impl Drop for CustomDrop { fn drop(&mut self) {} } fn main() { let _ = Box::new(CustomDrop) as Box<dyn Send>; } </ins>


// See the discussion in the stream implementation for why we we // might decrement steals. Some(data) => { <del> self.steals += 1; </del> if self.steals > MAX_STEALS { match self.cnt.swap(0, atomics::SeqCst) { DISCONNECTED => {


n => { let m = cmp::min(n, self.steals); self.steals -= m; <del> self.cnt.fetch_add(n - m, atomics::SeqCst); </del> <ins> self.bump(n - m); </ins> } } assert!(self.steals >= 0); } <ins> self.steals += 1; </ins> Ok(data) }


// down as much as possible (without going negative), and then // adding back in whatever we couldn't factor into steals. Some(data) => { <del> self.steals += 1; </del> if self.steals > MAX_STEALS { match self.cnt.swap(0, atomics::SeqCst) { DISCONNECTED => {


n => { let m = cmp::min(n, self.steals); self.steals -= m; <del> self.cnt.fetch_add(n - m, atomics::SeqCst); </del> <ins> self.bump(n - m); </ins> } } assert!(self.steals >= 0); } <ins> self.steals += 1; </ins> match data { Data(t) => Ok(t), GoUp(up) => Err(Upgraded(up)),


binder: EarlyBinder<TraitRef<'tcx>>, mut did_has_local_parent: impl FnMut(DefId) -> bool, ) -> bool { <del> let infcx = tcx.infer_ctxt().build(); </del> <ins> let infcx = tcx .infer_ctxt() // We use the new trait solver since the obligation we are trying to // prove here may overflow and those are fatal in the old trait solver. // Which is unacceptable for a lint. // // Thanksfully the part we use here are very similar to the // new-trait-solver-as-coherence, which is in stabilization. // // https://github.com/rust-lang/rust/issues/123573 .with_next_trait_solver(true) .build(); </ins> let trait_ref = binder.instantiate(tcx, infcx.fresh_args_for_item(infer_span, trait_def_id)); let trait_ref = trait_ref.fold_with(&mut ReplaceLocalTypesWithInfer {


<ins> //@ check-pass //@ edition:2021 // https://github.com/rust-lang/rust/issues/123573#issue-2229428739 pub trait Test {} impl<'a, T: 'a> Test for &[T] where &'a T: Test {} fn main() { struct Local {} impl Test for &Local {} //~^ WARN non-local `impl` definition } </ins>


<ins> warning: non-local `impl` definition, they should be avoided as they go against expectation --> $DIR/trait-solver-overflow-123573.rs:12:5 | LL |     impl Test for &Local {} |     ^^^^^^^^^^^^^^^^^^^^^^^ | = help: move this `impl` block outside the of the current function `main` = note: an `impl` definition is non-local if it is nested inside an item and may impact type checking outside of that item. This can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: one exception to the rule are anon-const (`const _: () = { ... }`) at top-level module and anon-const at the same nesting as the trait or type = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue <https://github.com/rust-lang/rust/issues/120363> = note: `#[warn(non_local_definitions)]` on by default warning: 1 warning emitted </ins>


use rustc_middle::mir::FakeReadCause; use rustc_middle::traits::ObligationCauseCode; use rustc_middle::ty::{ <del> self, ClosureSizeProfileData, Ty, TyCtxt, TypeckResults, UpvarArgs, UpvarCapture, </del> <ins> self, ClosureSizeProfileData, Ty, TyCtxt, TypeVisitableExt as _, TypeckResults, UpvarArgs, UpvarCapture, </ins> }; use rustc_session::lint; use rustc_span::sym;


); } }; <ins> let args = self.resolve_vars_if_possible(args); </ins> let closure_def_id = closure_def_id.expect_local(); assert_eq!(self.tcx.hir().body_owner_def_id(body.id()), closure_def_id);


// For coroutine-closures, we additionally must compute the // `coroutine_captures_by_ref_ty` type, which is used to generate the by-ref // version of the coroutine-closure's output coroutine. <del> if let UpvarArgs::CoroutineClosure(args) = args { </del> <ins> if let UpvarArgs::CoroutineClosure(args) = args && !args.references_error() { </ins> let closure_env_region: ty::Region<'_> = ty::Region::new_bound( self.tcx, ty::INNERMOST,


} } <del> #[derive(Debug, Copy, Clone, HashStable)] </del> <ins> #[derive(Debug, Copy, Clone, HashStable, TypeFoldable, TypeVisitable)] </ins> pub enum UpvarArgs<'tcx> { Closure(GenericArgsRef<'tcx>), Coroutine(GenericArgsRef<'tcx>),


<ins> //@ edition: 2021 #![feature(async_closure)] struct DropMe; trait Impossible {} fn trait_error<T: Impossible>() {} pub fn main() { let b = DropMe; let async_closure = async move || { // Type error here taints the environment. This causes us to fallback all // variables to `Error`. This means that when we compute the upvars for the // *outer* coroutine-closure, we don't actually see any upvars since `MemCategorization` // and `ExprUseVisitor`` will bail early when it sees error. This means // that our underlying assumption that the parent and child captures are // compatible ends up being broken, previously leading to an ICE. trait_error::<()>(); //~^ ERROR the trait bound `(): Impossible` is not satisfied let _b = b; }; } </ins>


<ins> error[E0277]: the trait bound `(): Impossible` is not satisfied --> $DIR/dont-ice-when-body-tainted-by-errors.rs:19:23 | LL |         trait_error::<()>(); |                       ^^ the trait `Impossible` is not implemented for `()` | help: this trait has no implementations, consider adding one --> $DIR/dont-ice-when-body-tainted-by-errors.rs:7:1 | LL | trait Impossible {} | ^^^^^^^^^^^^^^^^ note: required by a bound in `trait_error` --> $DIR/dont-ice-when-body-tainted-by-errors.rs:8:19 | LL | fn trait_error<T: Impossible>() {} |                   ^^^^^^^^^^ required by this bound in `trait_error` error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. </ins>


passes_both_ffi_const_and_pure = `#[ffi_const]` function cannot be `#[ffi_pure]` <del> passes_break_inside_async_block = `{$name}` inside of an `async` block .label = cannot `{$name}` inside of an `async` block .async_block_label = enclosing `async` block </del> passes_break_inside_closure = `{$name}` inside of a closure .label = cannot `{$name}` inside of a closure .closure_label = enclosing closure <ins> passes_break_inside_coroutine = `{$name}` inside `{$kind}` {$source} .label = cannot `{$name}` inside `{$kind}` {$source} .coroutine_label = enclosing `{$kind}` {$source} </ins> passes_break_non_loop = `break` with value from a `{$kind}` loop .label = can only break with a value inside `loop` or breakable block


} #[derive(Diagnostic)] <del> #[diag(passes_break_inside_async_block, code = E0267)] pub struct BreakInsideAsyncBlock<'a> { </del> <ins> #[diag(passes_break_inside_coroutine, code = E0267)] pub struct BreakInsideCoroutine<'a> { </ins> #[primary_span] #[label] pub span: Span, <del> #[label(passes_async_block_label)] pub closure_span: Span, </del> <ins> #[label(passes_coroutine_label)] pub coroutine_span: Span, </ins> pub name: &'a str, <ins> pub kind: &'a str, pub source: &'a str, </ins> } #[derive(Diagnostic)]


use rustc_span::{BytePos, Span}; use crate::errors::{ <del> BreakInsideAsyncBlock, BreakInsideClosure, BreakNonLoop, ContinueLabeledBlock, OutsideLoop, </del> <ins> BreakInsideClosure, BreakInsideCoroutine, BreakNonLoop, ContinueLabeledBlock, OutsideLoop, </ins> OutsideLoopSuggestion, UnlabeledCfInWhileCondition, UnlabeledInLabeledBlock, };


Fn, Loop(hir::LoopSource), Closure(Span), <del> AsyncClosure(Span), </del> <ins> Coroutine { coroutine_span: Span, kind: hir::CoroutineDesugaring, source: hir::CoroutineSource }, </ins> UnlabeledBlock(Span), LabeledBlock, Constant,


hir::ExprKind::Closure(&hir::Closure { ref fn_decl, body, fn_decl_span, kind, .. }) => { <del> // FIXME(coroutines): This doesn't handle coroutines correctly </del> let cx = match kind { <del> hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared( hir::CoroutineDesugaring::Async, hir::CoroutineSource::Block, )) => AsyncClosure(fn_decl_span), </del> <ins> hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(kind, source)) => { Coroutine { coroutine_span: fn_decl_span, kind, source } } </ins> _ => Closure(fn_decl_span), }; self.visit_fn_decl(fn_decl);


Closure(closure_span) => { self.sess.dcx().emit_err(BreakInsideClosure { span, closure_span, name }); } <del> AsyncClosure(closure_span) => { self.sess.dcx().emit_err(BreakInsideAsyncBlock { span, closure_span, name }); </del> <ins> Coroutine { coroutine_span, kind, source } => { let kind = match kind { hir::CoroutineDesugaring::Async => "async", hir::CoroutineDesugaring::Gen => "gen", hir::CoroutineDesugaring::AsyncGen => "async gen", }; let source = match source { hir::CoroutineSource::Block => "block", hir::CoroutineSource::Closure => "closure", hir::CoroutineSource::Fn => "function", }; self.sess.dcx().emit_err(BreakInsideCoroutine { span, coroutine_span, name, kind, source, }); </ins> } UnlabeledBlock(block_span) if is_break && block_span.eq_ctxt(break_span) => { let suggestion = Some(OutsideLoopSuggestion { block_span, break_span });


fn no_break_in_async_block() { async { <del> break 0u8; //~ ERROR `break` inside of an `async` block </del> <ins> break 0u8; //~ ERROR `break` inside `async` block </ins> }; } fn no_break_in_async_block_even_with_outer_loop() { loop { async { <del> break 0u8; //~ ERROR `break` inside of an `async` block </del> <ins> break 0u8; //~ ERROR `break` inside `async` block </ins> }; } }


<del> error[E0267]: `break` inside of an `async` block </del> <ins> error[E0267]: `break` inside `async` block </ins> --> $DIR/async-block-control-flow-static-semantics.rs:32:9 | LL | /     async { LL | |         break 0u8; <del> | |         ^^^^^^^^^ cannot `break` inside of an `async` block </del> <ins> | |         ^^^^^^^^^ cannot `break` inside `async` block </ins> LL | |     }; | |_____- enclosing `async` block <del> error[E0267]: `break` inside of an `async` block </del> <ins> error[E0267]: `break` inside `async` block </ins> --> $DIR/async-block-control-flow-static-semantics.rs:39:13 | LL | /         async { LL | |             break 0u8; <del> | |             ^^^^^^^^^ cannot `break` inside of an `async` block </del> <ins> | |             ^^^^^^^^^ cannot `break` inside `async` block </ins> LL | |         }; | |_________- enclosing `async` block


<ins> //@ edition: 2024 //@ compile-flags: -Z unstable-options #![feature(gen_blocks)] #![feature(async_closure)] async fn async_fn() { break; //~ ERROR `break` inside `async` function } gen fn gen_fn() { break; //~ ERROR `break` inside `gen` function } async gen fn async_gen_fn() { break; //~ ERROR `break` inside `async gen` function } fn main() { let _ = async { break; }; //~ ERROR `break` inside `async` block let _ = async || { break; }; //~ ERROR `break` inside `async` closure let _ = gen { break; }; //~ ERROR `break` inside `gen` block let _ = async gen { break; }; //~ ERROR `break` inside `async gen` block } </ins>