From f4426c189f2587fc5e8f48bf518cc75a37d93d0f Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Sat, 24 Feb 2024 00:48:20 -0500 Subject: [PATCH 01/36] use [N x i8] for alloca types --- compiler/rustc_codegen_gcc/src/builder.rs | 20 +-- .../rustc_codegen_gcc/src/intrinsic/mod.rs | 2 +- .../rustc_codegen_gcc/src/intrinsic/simd.rs | 4 +- compiler/rustc_codegen_llvm/src/abi.rs | 2 +- compiler/rustc_codegen_llvm/src/builder.rs | 7 +- compiler/rustc_codegen_llvm/src/intrinsic.rs | 20 +-- compiler/rustc_codegen_ssa/src/base.rs | 2 +- compiler/rustc_codegen_ssa/src/mir/block.rs | 2 +- compiler/rustc_codegen_ssa/src/mir/operand.rs | 4 +- compiler/rustc_codegen_ssa/src/mir/place.rs | 2 +- .../rustc_codegen_ssa/src/traits/builder.rs | 4 +- .../codegen/align-byval-alignment-mismatch.rs | 6 +- tests/codegen/align-byval.rs | 12 +- tests/codegen/align-enum.rs | 4 +- tests/codegen/align-struct.rs | 8 +- tests/codegen/array-codegen.rs | 2 +- tests/codegen/array-map.rs | 2 +- tests/codegen/cast-target-abi.rs | 121 +++++++++--------- tests/codegen/cffi/ffi-out-of-bounds-loads.rs | 2 +- tests/codegen/debug-fndef-size.rs | 2 +- tests/codegen/emcripten-catch-unwind.rs | 59 +++++++++ tests/codegen/enum/enum-match.rs | 2 +- tests/codegen/i128-x86-align.rs | 9 +- tests/codegen/intrinsics/transmute.rs | 16 +-- .../issues/issue-105386-ub-in-debuginfo.rs | 2 +- tests/codegen/issues/issue-111603.rs | 2 +- tests/codegen/overaligned-constant.rs | 9 +- tests/codegen/packed.rs | 4 +- tests/codegen/personality_lifetimes.rs | 2 +- tests/codegen/sroa-fragment-debuginfo.rs | 6 +- tests/codegen/stores.rs | 8 +- tests/codegen/swap-large-types.rs | 2 +- tests/codegen/swap-small-types.rs | 2 +- 33 files changed, 203 insertions(+), 148 deletions(-) create mode 100644 tests/codegen/emcripten-catch-unwind.rs diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index 43cc46cfe682..cf1aa3f47934 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -898,26 +898,14 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { self.gcc_checked_binop(oop, typ, lhs, rhs) } - fn alloca(&mut self, ty: Type<'gcc>, align: Align) -> RValue<'gcc> { - // FIXME(antoyo): this check that we don't call get_aligned() a second time on a type. - // Ideally, we shouldn't need to do this check. - let aligned_type = if ty == self.cx.u128_type || ty == self.cx.i128_type { - ty - } else { - ty.get_aligned(align.bytes()) - }; + fn alloca(&mut self, size: Size, align: Align) -> RValue<'gcc> { + let ty = self.cx.type_array(self.cx.type_i8(), size.bytes()).get_aligned(align.bytes()); // TODO(antoyo): It might be better to return a LValue, but fixing the rustc API is non-trivial. self.stack_var_count.set(self.stack_var_count.get() + 1); - self.current_func() - .new_local( - self.location, - aligned_type, - &format!("stack_var_{}", self.stack_var_count.get()), - ) - .get_address(self.location) + self.current_func().new_local(None, ty, &format!("stack_var_{}", self.stack_var_count.get())).get_address(None) } - fn byte_array_alloca(&mut self, _len: RValue<'gcc>, _align: Align) -> RValue<'gcc> { + fn dynamic_alloca(&mut self, _len: RValue<'gcc>, _align: Align) -> RValue<'gcc> { unimplemented!(); } diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index cebd45c09aa3..0c50b2bb5fe4 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -531,7 +531,7 @@ impl<'gcc, 'tcx> ArgAbiExt<'gcc, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> { // We instead thus allocate some scratch space... let scratch_size = cast.size(bx); let scratch_align = cast.align(bx); - let llscratch = bx.alloca(cast.gcc_type(bx), scratch_align); + let llscratch = bx.alloca(scratch_size, scratch_align); bx.lifetime_start(llscratch, scratch_size); // ... where we first store the value... diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs index 60361a44c2d7..1d9ff257a76f 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs @@ -18,7 +18,7 @@ use rustc_middle::span_bug; use rustc_middle::ty::layout::HasTyCtxt; use rustc_middle::ty::{self, Ty}; use rustc_span::{sym, Span, Symbol}; -use rustc_target::abi::Align; +use rustc_target::abi::{Align, Size}; use crate::builder::Builder; #[cfg(not(feature = "master"))] @@ -558,7 +558,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( let ze = bx.zext(result, bx.type_ix(expected_bytes * 8)); // Convert the integer to a byte array - let ptr = bx.alloca(bx.type_ix(expected_bytes * 8), Align::ONE); + let ptr = bx.alloca(Size::from_bytes(expected_bytes), Align::ONE); bx.store(ze, ptr, Align::ONE); let array_ty = bx.type_array(bx.type_i8(), expected_bytes); let ptr = bx.pointercast(ptr, bx.cx.type_ptr_to(array_ty)); diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index f918facc86db..68afcd08f043 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -227,7 +227,7 @@ impl<'ll, 'tcx> ArgAbiExt<'ll, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> { // when passed by value, making it larger. let copy_bytes = cmp::min(scratch_size.bytes(), self.layout.size.bytes()); // Allocate some scratch space... - let llscratch = bx.alloca(cast.llvm_type(bx), scratch_align); + let llscratch = bx.alloca(scratch_size, scratch_align); bx.lifetime_start(llscratch, scratch_size); // ...store the value... bx.store(val, llscratch, scratch_align); diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index b7235972204d..0956542337f5 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -468,9 +468,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { val } - fn alloca(&mut self, ty: &'ll Type, align: Align) -> &'ll Value { + fn alloca(&mut self, size: Size, align: Align) -> &'ll Value { let mut bx = Builder::with_cx(self.cx); bx.position_at_start(unsafe { llvm::LLVMGetFirstBasicBlock(self.llfn()) }); + let ty = self.cx().type_array(self.cx().type_i8(), size.bytes()); unsafe { let alloca = llvm::LLVMBuildAlloca(bx.llbuilder, ty, UNNAMED); llvm::LLVMSetAlignment(alloca, align.bytes() as c_uint); @@ -478,10 +479,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } } - fn byte_array_alloca(&mut self, len: &'ll Value, align: Align) -> &'ll Value { + fn dynamic_alloca(&mut self, size: &'ll Value, align: Align) -> &'ll Value { unsafe { let alloca = - llvm::LLVMBuildArrayAlloca(self.llbuilder, self.cx().type_i8(), len, UNNAMED); + llvm::LLVMBuildArrayAlloca(self.llbuilder, self.cx().type_i8(), size, UNNAMED); llvm::LLVMSetAlignment(alloca, align.bytes() as c_uint); alloca } diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index dc52dd156b7e..9bf9c6ec0bcb 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -18,7 +18,7 @@ use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf}; use rustc_middle::ty::{self, GenericArgsRef, Ty}; use rustc_middle::{bug, span_bug}; use rustc_span::{sym, Span, Symbol}; -use rustc_target::abi::{self, Align, HasDataLayout, Primitive}; +use rustc_target::abi::{self, Align, HasDataLayout, Primitive, Size}; use rustc_target::spec::{HasTargetSpec, PanicStrategy}; use std::cmp::Ordering; @@ -638,8 +638,9 @@ fn codegen_msvc_try<'ll>( // } // // More information can be found in libstd's seh.rs implementation. + let ptr_size = bx.tcx().data_layout.pointer_size; let ptr_align = bx.tcx().data_layout.pointer_align.abi; - let slot = bx.alloca(bx.type_ptr(), ptr_align); + let slot = bx.alloca(ptr_size, ptr_align); let try_func_ty = bx.type_func(&[bx.type_ptr()], bx.type_void()); bx.invoke(try_func_ty, None, None, try_func, &[data], normal, catchswitch, None, None); @@ -909,15 +910,14 @@ fn codegen_emcc_try<'ll>( // We need to pass two values to catch_func (ptr and is_rust_panic), so // create an alloca and pass a pointer to that. + let ptr_size = bx.tcx().data_layout.pointer_size; let ptr_align = bx.tcx().data_layout.pointer_align.abi; let i8_align = bx.tcx().data_layout.i8_align.abi; - let catch_data_type = bx.type_struct(&[bx.type_ptr(), bx.type_bool()], false); - let catch_data = bx.alloca(catch_data_type, ptr_align); - let catch_data_0 = - bx.inbounds_gep(catch_data_type, catch_data, &[bx.const_usize(0), bx.const_usize(0)]); - bx.store(ptr, catch_data_0, ptr_align); - let catch_data_1 = - bx.inbounds_gep(catch_data_type, catch_data, &[bx.const_usize(0), bx.const_usize(1)]); + // Required in order for there to be no padding between the fields. + assert!(i8_align <= ptr_align); + let catch_data = bx.alloca(2 * ptr_size, ptr_align); + bx.store(ptr, catch_data, ptr_align); + let catch_data_1 = bx.inbounds_ptradd(catch_data, bx.const_usize(ptr_size.bytes())); bx.store(is_rust_panic, catch_data_1, i8_align); let catch_ty = bx.type_func(&[bx.type_ptr(), bx.type_ptr()], bx.type_void()); @@ -1363,7 +1363,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>( let ze = bx.zext(i_, bx.type_ix(expected_bytes * 8)); // Convert the integer to a byte array - let ptr = bx.alloca(bx.type_ix(expected_bytes * 8), Align::ONE); + let ptr = bx.alloca(Size::from_bytes(expected_bytes), Align::ONE); bx.store(ze, ptr, Align::ONE); let array_ty = bx.type_array(bx.type_i8(), expected_bytes); return Ok(bx.load(array_ty, ptr, Align::ONE)); diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 930b9b8c0db2..ae7c0f24b40f 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -508,7 +508,7 @@ fn get_argc_argv<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let ptr_size = bx.tcx().data_layout.pointer_size; let ptr_align = bx.tcx().data_layout.pointer_align.abi; let arg_argc = bx.const_int(cx.type_isize(), 2); - let arg_argv = bx.alloca(cx.type_array(cx.type_ptr(), 2), ptr_align); + let arg_argv = bx.alloca(2 * ptr_size, ptr_align); bx.store(param_handle, arg_argv, ptr_align); let arg_argv_el1 = bx.inbounds_ptradd(arg_argv, bx.const_usize(ptr_size.bytes())); bx.store(param_system_table, arg_argv_el1, ptr_align); diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index c3137f0628e4..14fae453bcca 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -1512,7 +1512,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // when passed by value, making it larger. let copy_bytes = cmp::min(scratch_size.bytes(), arg.layout.size.bytes()); // Allocate some scratch space... - let llscratch = bx.alloca(bx.cast_backend_type(cast), scratch_align); + let llscratch = bx.alloca(scratch_size, scratch_align); bx.lifetime_start(llscratch, scratch_size); // ...memcpy the value... bx.memcpy( diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index ac38b91c5e0c..13e3debc3639 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -323,7 +323,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { let llfield_ty = bx.cx().backend_type(field); // Can't bitcast an aggregate, so round trip through memory. - let llptr = bx.alloca(llfield_ty, field.align.abi); + let llptr = bx.alloca(field.size, field.align.abi); bx.store(*llval, llptr, field.align.abi); *llval = bx.load(llfield_ty, llptr, field.align.abi); } @@ -466,7 +466,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue { let align_minus_1 = bx.sub(align, one); let size_extra = bx.add(size, align_minus_1); let min_align = Align::ONE; - let alloca = bx.byte_array_alloca(size_extra, min_align); + let alloca = bx.dynamic_alloca(size_extra, min_align); let address = bx.ptrtoint(alloca, bx.type_isize()); let neg_address = bx.neg(address); let offset = bx.and(neg_address, align_minus_1); diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index 1ec6c351e253..a4f57f25b7ab 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -57,7 +57,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { align: Align, ) -> Self { assert!(layout.is_sized(), "tried to statically allocate unsized place"); - let tmp = bx.alloca(bx.cx().backend_type(layout), align); + let tmp = bx.alloca(layout.size, align); Self::new_sized_aligned(tmp, layout, align) } diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index c0281e75d9d6..f7a3d5eaff58 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -144,8 +144,8 @@ pub trait BuilderMethods<'a, 'tcx>: } fn to_immediate_scalar(&mut self, val: Self::Value, scalar: Scalar) -> Self::Value; - fn alloca(&mut self, ty: Self::Type, align: Align) -> Self::Value; - fn byte_array_alloca(&mut self, len: Self::Value, align: Align) -> Self::Value; + fn alloca(&mut self, size: Size, align: Align) -> Self::Value; + fn dynamic_alloca(&mut self, size: Self::Value, align: Align) -> Self::Value; fn load(&mut self, ty: Self::Type, ptr: Self::Value, align: Align) -> Self::Value; fn volatile_load(&mut self, ty: Self::Type, ptr: Self::Value) -> Self::Value; diff --git a/tests/codegen/align-byval-alignment-mismatch.rs b/tests/codegen/align-byval-alignment-mismatch.rs index 306e3ce1358a..71f2dd42ec22 100644 --- a/tests/codegen/align-byval-alignment-mismatch.rs +++ b/tests/codegen/align-byval-alignment-mismatch.rs @@ -56,7 +56,7 @@ extern "C" { #[no_mangle] pub unsafe fn rust_to_c_increases_alignment(x: Align1) { // i686-linux: start: - // i686-linux-NEXT: [[ALLOCA:%[0-9a-z]+]] = alloca %Align1, align 4 + // i686-linux-NEXT: [[ALLOCA:%[0-9a-z]+]] = alloca [48 x i8], align 4 // i686-linux-NEXT: call void @llvm.memcpy.{{.+}}(ptr {{.*}}align 4 {{.*}}[[ALLOCA]], ptr {{.*}}align 1 {{.*}}%x // i686-linux-NEXT: call void @extern_c_align1({{.+}} [[ALLOCA]]) @@ -90,7 +90,7 @@ pub unsafe extern "C" fn c_to_rust_decreases_alignment(x: Align1) { #[no_mangle] pub unsafe extern "C" fn c_to_rust_increases_alignment(x: Align16) { // i686-linux: start: - // i686-linux-NEXT: [[ALLOCA:%[0-9a-z]+]] = alloca %Align16, align 16 + // i686-linux-NEXT: [[ALLOCA:%[0-9a-z]+]] = alloca [48 x i8], align 16 // i686-linux-NEXT: call void @llvm.memcpy.{{.+}}(ptr {{.*}}align 16 {{.*}}[[ALLOCA]], ptr {{.*}}align 4 {{.*}}%0 // i686-linux-NEXT: call void @extern_rust_align16({{.+}} [[ALLOCA]]) @@ -116,7 +116,7 @@ pub unsafe extern "C" fn c_to_rust_ref_decreases_alignment(x: Align1) { #[no_mangle] pub unsafe extern "C" fn c_to_rust_ref_increases_alignment(x: Align16) { // i686-linux: start: - // i686-linux-NEXT: [[ALLOCA:%[0-9a-z]+]] = alloca %Align16, align 16 + // i686-linux-NEXT: [[ALLOCA:%[0-9a-z]+]] = alloca [48 x i8], align 16 // i686-linux-NEXT: call void @llvm.memcpy.{{.+}}(ptr {{.*}}align 16 {{.*}}[[ALLOCA]], ptr {{.*}}align 4 {{.*}}%0 // i686-linux-NEXT: call void @extern_rust_ref_align16({{.+}} [[ALLOCA]]) diff --git a/tests/codegen/align-byval.rs b/tests/codegen/align-byval.rs index c74e236f29d3..3a2be2b2b9c3 100644 --- a/tests/codegen/align-byval.rs +++ b/tests/codegen/align-byval.rs @@ -106,20 +106,20 @@ pub struct ForceAlign16 { pub unsafe fn call_na1(x: NaturalAlign1) { // CHECK: start: - // m68k: [[ALLOCA:%[a-z0-9+]]] = alloca %NaturalAlign1, align 1 + // m68k: [[ALLOCA:%[a-z0-9+]]] = alloca [2 x i8], align 1 // m68k: call void @natural_align_1({{.*}}byval([2 x i8]) align 1{{.*}} [[ALLOCA]]) - // wasm: [[ALLOCA:%[a-z0-9+]]] = alloca %NaturalAlign1, align 1 + // wasm: [[ALLOCA:%[a-z0-9+]]] = alloca [2 x i8], align 1 // wasm: call void @natural_align_1({{.*}}byval([2 x i8]) align 1{{.*}} [[ALLOCA]]) // x86_64-linux: call void @natural_align_1(i16 // x86_64-windows: call void @natural_align_1(i16 - // i686-linux: [[ALLOCA:%[a-z0-9+]]] = alloca %NaturalAlign1, align 4 + // i686-linux: [[ALLOCA:%[a-z0-9+]]] = alloca [2 x i8], align 4 // i686-linux: call void @natural_align_1({{.*}}byval([2 x i8]) align 4{{.*}} [[ALLOCA]]) - // i686-windows: [[ALLOCA:%[a-z0-9+]]] = alloca %NaturalAlign1, align 4 + // i686-windows: [[ALLOCA:%[a-z0-9+]]] = alloca [2 x i8], align 4 // i686-windows: call void @natural_align_1({{.*}}byval([2 x i8]) align 4{{.*}} [[ALLOCA]]) natural_align_1(x); } @@ -134,10 +134,10 @@ pub unsafe fn call_na2(x: NaturalAlign2) { // x86_64-linux-NEXT: call void @natural_align_2 // x86_64-windows-NEXT: call void @natural_align_2 - // i686-linux: [[ALLOCA:%[0-9]+]] = alloca %NaturalAlign2, align 4 + // i686-linux: [[ALLOCA:%[0-9]+]] = alloca [34 x i8], align 4 // i686-linux: call void @natural_align_2({{.*}}byval([34 x i8]) align 4{{.*}} [[ALLOCA]]) - // i686-windows: [[ALLOCA:%[0-9]+]] = alloca %NaturalAlign2, align 4 + // i686-windows: [[ALLOCA:%[0-9]+]] = alloca [34 x i8], align 4 // i686-windows: call void @natural_align_2({{.*}}byval([34 x i8]) align 4{{.*}} [[ALLOCA]]) natural_align_2(x); } diff --git a/tests/codegen/align-enum.rs b/tests/codegen/align-enum.rs index b40168d77a47..93d5a87fb309 100644 --- a/tests/codegen/align-enum.rs +++ b/tests/codegen/align-enum.rs @@ -18,7 +18,7 @@ pub struct Nested64 { // CHECK-LABEL: @align64 #[no_mangle] pub fn align64(a: u32) -> Align64 { -// CHECK: %a64 = alloca %Align64, align 64 +// CHECK: %a64 = alloca [64 x i8], align 64 // CHECK: call void @llvm.memcpy.{{.*}}(ptr align 64 %{{.*}}, ptr align 64 %{{.*}}, i{{[0-9]+}} 64, i1 false) let a64 = Align64::A(a); a64 @@ -27,7 +27,7 @@ pub fn align64(a: u32) -> Align64 { // CHECK-LABEL: @nested64 #[no_mangle] pub fn nested64(a: u8, b: u32, c: u16) -> Nested64 { -// CHECK: %n64 = alloca %Nested64, align 64 +// CHECK: %n64 = alloca [128 x i8], align 64 let n64 = Nested64 { a, b: Align64::B(b), c }; n64 } diff --git a/tests/codegen/align-struct.rs b/tests/codegen/align-struct.rs index dbbb85bee6f3..e70b42b47db8 100644 --- a/tests/codegen/align-struct.rs +++ b/tests/codegen/align-struct.rs @@ -26,7 +26,7 @@ pub enum Enum64 { // CHECK-LABEL: @align64 #[no_mangle] pub fn align64(i : i32) -> Align64 { -// CHECK: %a64 = alloca %Align64, align 64 +// CHECK: %a64 = alloca [64 x i8], align 64 // CHECK: call void @llvm.memcpy.{{.*}}(ptr align 64 %{{.*}}, ptr align 64 %{{.*}}, i{{[0-9]+}} 64, i1 false) let a64 = Align64(i); a64 @@ -44,7 +44,7 @@ pub fn align64_load(a: Align64) -> i32 { // CHECK-LABEL: @nested64 #[no_mangle] pub fn nested64(a: Align64, b: i32, c: i32, d: i8) -> Nested64 { -// CHECK: %n64 = alloca %Nested64, align 64 +// CHECK: %n64 = alloca [128 x i8], align 64 let n64 = Nested64 { a, b, c, d }; n64 } @@ -52,7 +52,7 @@ pub fn nested64(a: Align64, b: i32, c: i32, d: i8) -> Nested64 { // CHECK-LABEL: @enum4 #[no_mangle] pub fn enum4(a: i32) -> Enum4 { -// CHECK: %e4 = alloca %Enum4, align 4 +// CHECK: %e4 = alloca [8 x i8], align 4 let e4 = Enum4::A(a); e4 } @@ -60,7 +60,7 @@ pub fn enum4(a: i32) -> Enum4 { // CHECK-LABEL: @enum64 #[no_mangle] pub fn enum64(a: Align64) -> Enum64 { -// CHECK: %e64 = alloca %Enum64, align 64 +// CHECK: %e64 = alloca [128 x i8], align 64 let e64 = Enum64::A(a); e64 } diff --git a/tests/codegen/array-codegen.rs b/tests/codegen/array-codegen.rs index 1310e61c41d0..fc272f2556cb 100644 --- a/tests/codegen/array-codegen.rs +++ b/tests/codegen/array-codegen.rs @@ -18,7 +18,7 @@ pub fn array_load(a: &[u8; 4]) -> [u8; 4] { #[no_mangle] pub fn array_store(a: [u8; 4], p: &mut [u8; 4]) { // CHECK-NOT: alloca - // CHECK: %[[TEMP:.+]] = alloca i32, [[TEMPALIGN:align [0-9]+]] + // CHECK: %[[TEMP:.+]] = alloca [4 x i8], [[TEMPALIGN:align [0-9]+]] // CHECK-NOT: alloca // CHECK: %a = alloca [4 x i8] // CHECK-NOT: alloca diff --git a/tests/codegen/array-map.rs b/tests/codegen/array-map.rs index 743a15989f78..f49dddcfc207 100644 --- a/tests/codegen/array-map.rs +++ b/tests/codegen/array-map.rs @@ -27,7 +27,7 @@ pub fn short_integer_map(x: [u32; 8]) -> [u32; 8] { #[no_mangle] pub fn long_integer_map(x: [u32; 512]) -> [u32; 512] { // CHECK: start: - // CHECK-NEXT: alloca [512 x i32] + // CHECK-NEXT: alloca [2048 x i8] // CHECK-NOT: alloca // CHECK: mul <{{[0-9]+}} x i32> // CHECK: add <{{[0-9]+}} x i32> diff --git a/tests/codegen/cast-target-abi.rs b/tests/codegen/cast-target-abi.rs index e6024f03425f..9c31acc9bb7c 100644 --- a/tests/codegen/cast-target-abi.rs +++ b/tests/codegen/cast-target-abi.rs @@ -77,15 +77,20 @@ extern "C" { // CHECK-LABEL: @call_twou16s #[no_mangle] pub unsafe fn call_twou16s() { - // aarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:i64]], align [[ABI_ALIGN:8]] - // loongarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:i64]], align [[ABI_ALIGN:8]] - // powerpc64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:i32]], align [[ABI_ALIGN:4]] - // sparc64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:i64]], align [[ABI_ALIGN:8]] + // aarch64: [[ABI_ALLOCA:%.+]] = alloca [8 x i8], align [[ABI_ALIGN:8]] + // loongarch64: [[ABI_ALLOCA:%.+]] = alloca [8 x i8], align [[ABI_ALIGN:8]] + // powerpc64: [[ABI_ALLOCA:%.+]] = alloca [4 x i8], align [[ABI_ALIGN:4]] + // sparc64: [[ABI_ALLOCA:%.+]] = alloca [8 x i8], align [[ABI_ALIGN:8]] - // CHECK: [[RUST_ALLOCA:%.+]] = alloca %TwoU16s, align [[RUST_ALIGN:2]] + // CHECK: [[RUST_ALLOCA:%.+]] = alloca [4 x i8], align [[RUST_ALIGN:2]] // CHECK: call void @llvm.memcpy.{{.+}}(ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], i64 4, i1 false) - // CHECK: [[ABI_VALUE:%.+]] = load [[ABI_TYPE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + + // aarch64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:i64]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // loongarch64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:i64]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // powerpc64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:i32]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // sparc64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:i64]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // CHECK: call void @receives_twou16s([[ABI_TYPE]] [[ABI_VALUE]]) let x = TwoU16s { a: 1, b: 2 }; receives_twou16s(x); @@ -96,23 +101,23 @@ pub unsafe fn call_twou16s() { pub unsafe fn return_twou16s() -> TwoU16s { // powerpc returns this struct via sret pointer, it doesn't use the cast ABI. - // powerpc64: [[RETVAL:%.+]] = alloca %TwoU16s, align 2 + // powerpc64: [[RETVAL:%.+]] = alloca [4 x i8], align 2 // powerpc64: call void @returns_twou16s(ptr {{.+}} [[RETVAL]]) // The other targets copy the cast ABI type to an alloca. - // aarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:i64]], align [[ABI_ALIGN:8]] - // loongarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:i64]], align [[ABI_ALIGN:8]] - // sparc64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:i64]], align [[ABI_ALIGN:8]] + // aarch64: [[ABI_ALLOCA:%.+]] = alloca [8 x i8], align [[ABI_ALIGN:8]] + // loongarch64: [[ABI_ALLOCA:%.+]] = alloca [8 x i8], align [[ABI_ALIGN:8]] + // sparc64: [[ABI_ALLOCA:%.+]] = alloca [8 x i8], align [[ABI_ALIGN:8]] - // aarch64: [[RUST_ALLOCA:%.+]] = alloca %TwoU16s, align [[RUST_ALIGN:2]] - // loongarch64: [[RUST_ALLOCA:%.+]] = alloca %TwoU16s, align [[RUST_ALIGN:2]] - // sparc64: [[RUST_ALLOCA:%.+]] = alloca %TwoU16s, align [[RUST_ALIGN:2]] + // aarch64: [[RUST_ALLOCA:%.+]] = alloca [4 x i8], align [[RUST_ALIGN:2]] + // loongarch64: [[RUST_ALLOCA:%.+]] = alloca [4 x i8], align [[RUST_ALIGN:2]] + // sparc64: [[RUST_ALLOCA:%.+]] = alloca [4 x i8], align [[RUST_ALIGN:2]] - // aarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_twou16s() - // loongarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_twou16s() - // sparc64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_twou16s() + // aarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE:i64]] @returns_twou16s() + // loongarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE:i64]] @returns_twou16s() + // sparc64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE:i64]] @returns_twou16s() // aarch64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] // loongarch64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] @@ -127,12 +132,12 @@ pub unsafe fn return_twou16s() -> TwoU16s { // CHECK-LABEL: @call_fiveu16s #[no_mangle] pub unsafe fn call_fiveu16s() { - // CHECK: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:\[2 x i64\]]], align [[ABI_ALIGN:8]] + // CHECK: [[ABI_ALLOCA:%.+]] = alloca [16 x i8], align [[ABI_ALIGN:8]] - // CHECK: [[RUST_ALLOCA:%.+]] = alloca %FiveU16s, align 2 + // CHECK: [[RUST_ALLOCA:%.+]] = alloca [10 x i8], align 2 // CHECK: call void @llvm.memcpy.{{.+}}(ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], i64 10, i1 false) - // CHECK: [[ABI_VALUE:%.+]] = load [[ABI_TYPE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // CHECK: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:\[2 x i64\]]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] // CHECK: call void @receives_fiveu16s([[ABI_TYPE]] [[ABI_VALUE]]) let x = FiveU16s { a: 1, b: 2, c: 3, d: 4, e: 5 }; receives_fiveu16s(x); @@ -149,13 +154,13 @@ pub unsafe fn return_fiveu16s() -> FiveU16s { // The other targets copy the cast ABI type to the sret pointer. - // aarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:\[2 x i64\]]], align [[ABI_ALIGN:8]] - // loongarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:\[2 x i64\]]], align [[ABI_ALIGN:8]] - // sparc64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:\[2 x i64\]]], align [[ABI_ALIGN:8]] + // aarch64: [[ABI_ALLOCA:%.+]] = alloca [16 x i8], align [[ABI_ALIGN:8]] + // loongarch64: [[ABI_ALLOCA:%.+]] = alloca [16 x i8], align [[ABI_ALIGN:8]] + // sparc64: [[ABI_ALLOCA:%.+]] = alloca [16 x i8], align [[ABI_ALIGN:8]] - // aarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_fiveu16s() - // loongarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_fiveu16s() - // sparc64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_fiveu16s() + // aarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE:\[2 x i64\]]] @returns_fiveu16s() + // loongarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE:\[2 x i64\]]] @returns_fiveu16s() + // sparc64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE:\[2 x i64\]]] @returns_fiveu16s() // aarch64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] // loongarch64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] @@ -170,15 +175,17 @@ pub unsafe fn return_fiveu16s() -> FiveU16s { // CHECK-LABEL: @call_doubledouble #[no_mangle] pub unsafe fn call_doubledouble() { - // aarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:\[2 x double\]]], align [[ABI_ALIGN:8]] - // loongarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:{ double, double }]], align [[ABI_ALIGN:8]] - // powerpc64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:\[2 x i64\]]], align [[ABI_ALIGN:8]] - // sparc64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:{ double, double }]], align [[ABI_ALIGN:8]] + // CHECK: [[ABI_ALLOCA:%.+]] = alloca [16 x i8], align [[ABI_ALIGN:8]] - // CHECK: [[RUST_ALLOCA:%.+]] = alloca %DoubleDouble, align [[RUST_ALIGN:8]] + // CHECK: [[RUST_ALLOCA:%.+]] = alloca [16 x i8], align [[RUST_ALIGN:8]] // CHECK: call void @llvm.memcpy.{{.+}}(ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], i64 16, i1 false) - // CHECK: [[ABI_VALUE:%.+]] = load [[ABI_TYPE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + + // aarch64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:\[2 x double\]]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // loongarch64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:{ double, double }]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // powerpc64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:\[2 x i64\]]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // sparc64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:{ double, double }]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // CHECK: call void @receives_doubledouble([[ABI_TYPE]] [[ABI_VALUE]]) let x = DoubleDouble { f: 1., g: 2. }; receives_doubledouble(x); @@ -189,23 +196,23 @@ pub unsafe fn call_doubledouble() { pub unsafe fn return_doubledouble() -> DoubleDouble { // powerpc returns this struct via sret pointer, it doesn't use the cast ABI. - // powerpc64: [[RETVAL:%.+]] = alloca %DoubleDouble, align 8 + // powerpc64: [[RETVAL:%.+]] = alloca [16 x i8], align 8 // powerpc64: call void @returns_doubledouble(ptr {{.+}} [[RETVAL]]) // The other targets copy the cast ABI type to an alloca. - // aarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:\[2 x double\]]], align [[ABI_ALIGN:8]] - // loongarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:{ double, double }]], align [[ABI_ALIGN:8]] - // sparc64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:{ double, double }]], align [[ABI_ALIGN:8]] + // aarch64: [[ABI_ALLOCA:%.+]] = alloca [16 x i8], align [[ABI_ALIGN:8]] + // loongarch64: [[ABI_ALLOCA:%.+]] = alloca [16 x i8], align [[ABI_ALIGN:8]] + // sparc64: [[ABI_ALLOCA:%.+]] = alloca [16 x i8], align [[ABI_ALIGN:8]] - // aarch64: [[RUST_ALLOCA:%.+]] = alloca %DoubleDouble, align [[RUST_ALIGN:8]] - // loongarch64: [[RUST_ALLOCA:%.+]] = alloca %DoubleDouble, align [[RUST_ALIGN:8]] - // sparc64: [[RUST_ALLOCA:%.+]] = alloca %DoubleDouble, align [[RUST_ALIGN:8]] + // aarch64: [[RUST_ALLOCA:%.+]] = alloca [16 x i8], align [[RUST_ALIGN:8]] + // loongarch64: [[RUST_ALLOCA:%.+]] = alloca [16 x i8], align [[RUST_ALIGN:8]] + // sparc64: [[RUST_ALLOCA:%.+]] = alloca [16 x i8], align [[RUST_ALIGN:8]] - // aarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_doubledouble() - // loongarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_doubledouble() - // sparc64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_doubledouble() + // aarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE:\[2 x double\]]] @returns_doubledouble() + // loongarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE:{ double, double }]] @returns_doubledouble() + // sparc64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE:{ double, double }]] @returns_doubledouble() // aarch64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] // loongarch64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] @@ -224,21 +231,21 @@ pub unsafe fn return_doubledouble() -> DoubleDouble { // powerpc64-LABEL: @call_doublefloat #[no_mangle] pub unsafe fn call_doublefloat() { - // aarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:\[2 x i64\]]], align [[ABI_ALIGN:8]] - // loongarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:{ double, float }]], align [[ABI_ALIGN:8]] - // powerpc64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:\[2 x i64\]]], align [[ABI_ALIGN:8]] + // aarch64: [[ABI_ALLOCA:%.+]] = alloca [16 x i8], align [[ABI_ALIGN:8]] + // loongarch64: [[ABI_ALLOCA:%.+]] = alloca [12 x i8], align [[ABI_ALIGN:8]] + // powerpc64: [[ABI_ALLOCA:%.+]] = alloca [16 x i8], align [[ABI_ALIGN:8]] - // aarch64: [[RUST_ALLOCA:%.+]] = alloca %DoubleFloat, align [[RUST_ALIGN:8]] - // loongarch64: [[RUST_ALLOCA:%.+]] = alloca %DoubleFloat, align [[RUST_ALIGN:8]] - // powerpc64: [[RUST_ALLOCA:%.+]] = alloca %DoubleFloat, align [[RUST_ALIGN:8]] + // aarch64: [[RUST_ALLOCA:%.+]] = alloca [16 x i8], align [[RUST_ALIGN:8]] + // loongarch64: [[RUST_ALLOCA:%.+]] = alloca [16 x i8], align [[RUST_ALIGN:8]] + // powerpc64: [[RUST_ALLOCA:%.+]] = alloca [16 x i8], align [[RUST_ALIGN:8]] // aarch64: call void @llvm.memcpy.{{.+}}(ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], i64 16, i1 false) // loongarch64: call void @llvm.memcpy.{{.+}}(ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], i64 12, i1 false) // powerpc64: call void @llvm.memcpy.{{.+}}(ptr align [[ABI_ALIGN]] [[ABI_ALLOCA]], ptr align [[RUST_ALIGN]] [[RUST_ALLOCA]], i64 16, i1 false) - // aarch64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] - // loongarch64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] - // powerpc64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // aarch64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:\[2 x i64\]]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // loongarch64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:{ double, float }]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] + // powerpc64: [[ABI_VALUE:%.+]] = load [[ABI_TYPE:\[2 x i64\]]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] // aarch64: call void @receives_doublefloat([[ABI_TYPE]] {{(inreg )?}}[[ABI_VALUE]]) // loongarch64: call void @receives_doublefloat([[ABI_TYPE]] {{(inreg )?}}[[ABI_VALUE]]) @@ -256,20 +263,20 @@ pub unsafe fn call_doublefloat() { pub unsafe fn return_doublefloat() -> DoubleFloat { // powerpc returns this struct via sret pointer, it doesn't use the cast ABI. - // powerpc64: [[RETVAL:%.+]] = alloca %DoubleFloat, align 8 + // powerpc64: [[RETVAL:%.+]] = alloca [16 x i8], align 8 // powerpc64: call void @returns_doublefloat(ptr {{.+}} [[RETVAL]]) // The other targets copy the cast ABI type to an alloca. - // aarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:\[2 x i64\]]], align [[ABI_ALIGN:8]] - // loongarch64: [[ABI_ALLOCA:%.+]] = alloca [[ABI_TYPE:{ double, float }]], align [[ABI_ALIGN:8]] + // aarch64: [[ABI_ALLOCA:%.+]] = alloca [16 x i8], align [[ABI_ALIGN:8]] + // loongarch64: [[ABI_ALLOCA:%.+]] = alloca [12 x i8], align [[ABI_ALIGN:8]] - // aarch64: [[RUST_ALLOCA:%.+]] = alloca %DoubleFloat, align [[RUST_ALIGN:8]] - // loongarch64: [[RUST_ALLOCA:%.+]] = alloca %DoubleFloat, align [[RUST_ALIGN:8]] + // aarch64: [[RUST_ALLOCA:%.+]] = alloca [16 x i8], align [[RUST_ALIGN:8]] + // loongarch64: [[RUST_ALLOCA:%.+]] = alloca [16 x i8], align [[RUST_ALIGN:8]] - // aarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_doublefloat() - // loongarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE]] @returns_doublefloat() + // aarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE:\[2 x i64\]]] @returns_doublefloat() + // loongarch64: [[ABI_VALUE:%.+]] = call [[ABI_TYPE:{ double, float }]] @returns_doublefloat() // aarch64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] // loongarch64: store [[ABI_TYPE]] [[ABI_VALUE]], ptr [[ABI_ALLOCA]], align [[ABI_ALIGN]] diff --git a/tests/codegen/cffi/ffi-out-of-bounds-loads.rs b/tests/codegen/cffi/ffi-out-of-bounds-loads.rs index 8b32e902b3f5..35bf00f8f3c3 100644 --- a/tests/codegen/cffi/ffi-out-of-bounds-loads.rs +++ b/tests/codegen/cffi/ffi-out-of-bounds-loads.rs @@ -33,7 +33,7 @@ extern "C" { pub fn test() { let s = S { f1: 1, f2: 2, f3: 3 }; unsafe { - // CHECK: [[ALLOCA:%.+]] = alloca { i64, i32 }, align 8 + // CHECK: [[ALLOCA:%.+]] = alloca [12 x i8], align 8 // CHECK: [[LOAD:%.+]] = load { i64, i32 }, ptr [[ALLOCA]], align 8 // CHECK: call void @foo({ i64, i32 } [[LOAD]]) foo(s); diff --git a/tests/codegen/debug-fndef-size.rs b/tests/codegen/debug-fndef-size.rs index b3cc45614bc5..5551d2cc39cf 100644 --- a/tests/codegen/debug-fndef-size.rs +++ b/tests/codegen/debug-fndef-size.rs @@ -12,7 +12,7 @@ pub fn main() { foo(0, 1, i32::cmp); } -// CHECK: %compare.dbg.spill = alloca {}, align 1 +// CHECK: %compare.dbg.spill = alloca [0 x i8], align 1 // CHECK: call void @llvm.dbg.declare(metadata ptr %compare.dbg.spill, metadata ![[VAR:.*]], metadata !DIExpression()), !dbg !{{.*}} // CHECK: ![[TYPE:.*]] = !DIDerivedType(tag: DW_TAG_pointer_type, name: "fn(&i32, &i32) -> core::cmp::Ordering", baseType: !{{.*}}, align: 1, dwarfAddressSpace: {{.*}}) // CHECK: ![[VAR]] = !DILocalVariable(name: "compare", scope: !{{.*}}, file: !{{.*}}, line: {{.*}}, type: ![[TYPE]], align: 1) diff --git a/tests/codegen/emcripten-catch-unwind.rs b/tests/codegen/emcripten-catch-unwind.rs new file mode 100644 index 000000000000..7de7bd81b5c0 --- /dev/null +++ b/tests/codegen/emcripten-catch-unwind.rs @@ -0,0 +1,59 @@ +//@ compile-flags: -O --target wasm32-unknown-emscripten +//@ needs-llvm-components: webassembly + +// Emscripten has its own unique implementation of catch_unwind (in `codegen_emcc_try`), +// make sure it generates something reasonable. + +#![feature(no_core, lang_items, intrinsics, rustc_attrs)] +#![crate_type = "lib"] +#![no_std] +#![no_core] + +#[lang="sized"] trait Sized { } +#[lang="freeze"] trait Freeze { } +#[lang="copy"] trait Copy { } + +#[rustc_intrinsic] +fn size_of() -> usize { loop {} } + +extern "rust-intrinsic" { + fn catch_unwind( + try_fn: fn(_: *mut u8), + data: *mut u8, + catch_fn: fn(_: *mut u8, _: *mut u8) + ) -> i32; +} + +// CHECK-LABEL: @ptr_size +#[no_mangle] +pub fn ptr_size() -> usize { + // CHECK: ret [[PTR_SIZE:.*]] + size_of::<*mut u8>() +} + +// CHECK-LABEL: @test_catch_unwind +#[no_mangle] +pub unsafe fn test_catch_unwind( + try_fn: fn(_: *mut u8), + data: *mut u8, + catch_fn: fn(_: *mut u8, _: *mut u8) +) -> i32 { + // CHECK: start: + // CHECK: [[ALLOCA:%.*]] = alloca + + // CHECK: catch.i: + // CHECK: [[LANDINGPAD:%.*]] = landingpad + // CHECK: [[EXCEPTION:%.*]] = extractvalue {{.*}} [[LANDINGPAD]], 0 + // CHECK: [[SELECTOR:%.*]] = extractvalue {{.*}} [[LANDINGPAD]], 1 + + // CHECK: [[IS_RUST_EXN:%.*]] = icmp eq {{.*}}[[SELECTOR]] + // CHECK: [[IS_RUST_EXN_I8:%.*]] = zext i1 [[IS_RUST_EXN]] to i8 + + // CHECK: store ptr [[EXCEPTION]], ptr [[ALLOCA]] + // CHECK: [[IS_RUST_SLOT:%.*]] = getelementptr inbounds i8, ptr [[ALLOCA]], [[PTR_SIZE]] + // CHECK: store i8 [[IS_RUST_EXN_I8]], ptr [[IS_RUST_SLOT]] + + // CHECK: call void %catch_fn(ptr %data, ptr nonnull [[ALLOCA]]) + + catch_unwind(try_fn, data, catch_fn) +} diff --git a/tests/codegen/enum/enum-match.rs b/tests/codegen/enum/enum-match.rs index 2e6dad8791b2..f1c40f6695be 100644 --- a/tests/codegen/enum/enum-match.rs +++ b/tests/codegen/enum/enum-match.rs @@ -15,7 +15,7 @@ pub enum Enum0 { // CHECK-NEXT: start: // CHECK-NEXT: %1 = icmp eq i8 %0, 2 // CHECK-NEXT: %2 = and i8 %0, 1 -// CHECK-NEXT: %_0.0 = select i1 %1, i8 13, i8 %2 +// CHECK-NEXT: %{{.+}} = select i1 %1, i8 13, i8 %2 #[no_mangle] pub fn match0(e: Enum0) -> u8 { use Enum0::*; diff --git a/tests/codegen/i128-x86-align.rs b/tests/codegen/i128-x86-align.rs index b2e0c294c39d..3e6ed2b8e16a 100644 --- a/tests/codegen/i128-x86-align.rs +++ b/tests/codegen/i128-x86-align.rs @@ -6,7 +6,6 @@ // correctly. // CHECK: %ScalarPair = type { i32, [3 x i32], i128 } -// CHECK: %Struct = type { i32, i32, [2 x i32], i128 } #![feature(core_intrinsics)] @@ -43,7 +42,7 @@ pub fn store(x: &mut ScalarPair) { #[no_mangle] pub fn alloca() { // CHECK-LABEL: @alloca( - // CHECK: [[X:%.*]] = alloca %ScalarPair, align 16 + // CHECK: [[X:%.*]] = alloca [32 x i8], align 16 // CHECK: store i32 1, ptr %x, align 16 // CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr %x, i64 16 // CHECK-NEXT: store i128 2, ptr [[GEP]], align 16 @@ -55,7 +54,7 @@ pub fn alloca() { pub fn load_volatile(x: &ScalarPair) -> ScalarPair { // CHECK-LABEL: @load_volatile( // CHECK-SAME: align 16 dereferenceable(32) %x - // CHECK: [[TMP:%.*]] = alloca %ScalarPair, align 16 + // CHECK: [[TMP:%.*]] = alloca [32 x i8], align 16 // CHECK: [[LOAD:%.*]] = load volatile %ScalarPair, ptr %x, align 16 // CHECK-NEXT: store %ScalarPair [[LOAD]], ptr [[TMP]], align 16 // CHECK-NEXT: [[A:%.*]] = load i32, ptr [[TMP]], align 16 @@ -67,7 +66,7 @@ pub fn load_volatile(x: &ScalarPair) -> ScalarPair { #[no_mangle] pub fn transmute(x: ScalarPair) -> (std::mem::MaybeUninit, i128) { // CHECK-LABEL: define { i128, i128 } @transmute(i32 noundef %x.0, i128 noundef %x.1) - // CHECK: [[TMP:%.*]] = alloca { i128, i128 }, align 16 + // CHECK: [[TMP:%.*]] = alloca [32 x i8], align 16 // CHECK-NEXT: store i32 %x.0, ptr [[TMP]], align 16 // CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr [[TMP]], i64 16 // CHECK-NEXT: store i128 %x.1, ptr [[GEP]], align 16 @@ -92,7 +91,7 @@ pub struct Struct { pub fn store_struct(x: &mut Struct) { // CHECK-LABEL: @store_struct( // CHECK-SAME: align 16 dereferenceable(32) %x - // CHECK: [[TMP:%.*]] = alloca %Struct, align 16 + // CHECK: [[TMP:%.*]] = alloca [32 x i8], align 16 // CHECK: store i32 1, ptr [[TMP]], align 16 // CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i8, ptr [[TMP]], i64 4 // CHECK-NEXT: store i32 2, ptr [[GEP1]], align 4 diff --git a/tests/codegen/intrinsics/transmute.rs b/tests/codegen/intrinsics/transmute.rs index f858562b5f11..76cdf7e191e4 100644 --- a/tests/codegen/intrinsics/transmute.rs +++ b/tests/codegen/intrinsics/transmute.rs @@ -153,7 +153,7 @@ pub unsafe fn check_from_newtype(x: Scalar64) -> u64 { // CHECK-LABEL: @check_aggregate_to_bool( #[no_mangle] pub unsafe fn check_aggregate_to_bool(x: Aggregate8) -> bool { - // CHECK: %x = alloca %Aggregate8, align 1 + // CHECK: %x = alloca [1 x i8], align 1 // CHECK: %[[BYTE:.+]] = load i8, ptr %x, align 1 // CHECK: %[[BOOL:.+]] = trunc i8 %[[BYTE]] to i1 // CHECK: ret i1 %[[BOOL]] @@ -163,7 +163,7 @@ pub unsafe fn check_aggregate_to_bool(x: Aggregate8) -> bool { // CHECK-LABEL: @check_aggregate_from_bool( #[no_mangle] pub unsafe fn check_aggregate_from_bool(x: bool) -> Aggregate8 { - // CHECK: %_0 = alloca %Aggregate8, align 1 + // CHECK: %_0 = alloca [1 x i8], align 1 // CHECK: %[[BYTE:.+]] = zext i1 %x to i8 // CHECK: store i8 %[[BYTE]], ptr %_0, align 1 transmute(x) @@ -190,7 +190,7 @@ pub unsafe fn check_byte_from_bool(x: bool) -> u8 { // CHECK-LABEL: @check_to_pair( #[no_mangle] pub unsafe fn check_to_pair(x: u64) -> Option { - // CHECK: %_0 = alloca %"core::option::Option", align 4 + // CHECK: %_0 = alloca [8 x i8], align 4 // CHECK: store i64 %x, ptr %_0, align 4 transmute(x) } @@ -202,7 +202,7 @@ pub unsafe fn check_from_pair(x: Option) -> u64 { // immediates so we can write using the destination alloca's alignment. const { assert!(std::mem::align_of::>() == 4) }; - // CHECK: %_0 = alloca i64, align 8 + // CHECK: %_0 = alloca [8 x i8], align 8 // CHECK: store i32 %x.0, ptr %_0, align 8 // CHECK: store i32 %x.1, ptr %0, align 4 // CHECK: %[[R:.+]] = load i64, ptr %_0, align 8 @@ -248,7 +248,7 @@ pub unsafe fn check_from_bytes(x: [u8; 4]) -> u32 { // CHECK-LABEL: @check_to_aggregate( #[no_mangle] pub unsafe fn check_to_aggregate(x: u64) -> Aggregate64 { - // CHECK: %_0 = alloca %Aggregate64, align 4 + // CHECK: %_0 = alloca [8 x i8], align 4 // CHECK: store i64 %x, ptr %_0, align 4 // CHECK: %0 = load i64, ptr %_0, align 4 // CHECK: ret i64 %0 @@ -258,7 +258,7 @@ pub unsafe fn check_to_aggregate(x: u64) -> Aggregate64 { // CHECK-LABEL: @check_from_aggregate( #[no_mangle] pub unsafe fn check_from_aggregate(x: Aggregate64) -> u64 { - // CHECK: %x = alloca %Aggregate64, align 4 + // CHECK: %x = alloca [8 x i8], align 4 // CHECK: %[[VAL:.+]] = load i64, ptr %x, align 4 // CHECK: ret i64 %[[VAL]] transmute(x) @@ -452,7 +452,7 @@ pub struct HighAlignScalar(u8); // CHECK-LABEL: @check_to_overalign( #[no_mangle] pub unsafe fn check_to_overalign(x: u64) -> HighAlignScalar { - // CHECK: %_0 = alloca %HighAlignScalar, align 8 + // CHECK: %_0 = alloca [8 x i8], align 8 // CHECK: store i64 %x, ptr %_0, align 8 // CHECK: %0 = load i64, ptr %_0, align 8 // CHECK: ret i64 %0 @@ -462,7 +462,7 @@ pub unsafe fn check_to_overalign(x: u64) -> HighAlignScalar { // CHECK-LABEL: @check_from_overalign( #[no_mangle] pub unsafe fn check_from_overalign(x: HighAlignScalar) -> u64 { - // CHECK: %x = alloca %HighAlignScalar, align 8 + // CHECK: %x = alloca [8 x i8], align 8 // CHECK: %[[VAL:.+]] = load i64, ptr %x, align 8 // CHECK: ret i64 %[[VAL]] transmute(x) diff --git a/tests/codegen/issues/issue-105386-ub-in-debuginfo.rs b/tests/codegen/issues/issue-105386-ub-in-debuginfo.rs index 0bd43dc50b21..4d1c0a83b55f 100644 --- a/tests/codegen/issues/issue-105386-ub-in-debuginfo.rs +++ b/tests/codegen/issues/issue-105386-ub-in-debuginfo.rs @@ -15,7 +15,7 @@ pub fn outer_function(x: S, y: S) -> usize { // Check that we do not attempt to load from the spilled arg before it is assigned to // when generating debuginfo. // CHECK-LABEL: @outer_function -// CHECK: [[spill:%.*]] = alloca %"{closure@{{.*.rs}}:9:23: 9:25}" +// CHECK: [[spill:%.*]] = alloca [72 x i8] // CHECK-NOT: [[ptr_tmp:%.*]] = getelementptr inbounds i8, ptr [[spill]] // CHECK-NOT: [[load:%.*]] = load ptr, ptr // CHECK: call void @llvm.lifetime.start{{.*}}({{.*}}, ptr [[spill]]) diff --git a/tests/codegen/issues/issue-111603.rs b/tests/codegen/issues/issue-111603.rs index 3f4c7e7d5423..41bfb493ff58 100644 --- a/tests/codegen/issues/issue-111603.rs +++ b/tests/codegen/issues/issue-111603.rs @@ -11,7 +11,7 @@ pub fn new_from_array(x: u64) -> Arc<[u64]> { // Ensure that we only generate one alloca for the array. // CHECK: alloca - // CHECK-SAME: [1000 x i64] + // CHECK-SAME: [8000 x i8] // CHECK-NOT: alloca let array = [x; 1000]; Arc::new(array) diff --git a/tests/codegen/overaligned-constant.rs b/tests/codegen/overaligned-constant.rs index 9e5b69ff2670..7cd8d19c2113 100644 --- a/tests/codegen/overaligned-constant.rs +++ b/tests/codegen/overaligned-constant.rs @@ -2,7 +2,7 @@ // do not ICE during codegen, and that the LLVM constant has the higher alignment. // //@ compile-flags: -Zmir-opt-level=0 -Zmir-enable-passes=+GVN -//@ compile-flags: -Cno-prepopulate-passes +//@ compile-flags: -Cno-prepopulate-passes --crate-type=lib //@ only-64bit struct S(i32); @@ -12,9 +12,10 @@ struct SmallStruct(f32, Option, &'static [f32]); // CHECK: @0 = private unnamed_addr constant // CHECK-SAME: , align 8 -fn main() { - // CHECK-LABEL: @_ZN20overaligned_constant4main - // CHECK: [[full:%_.*]] = alloca %SmallStruct, align 8 +#[no_mangle] +pub fn overaligned_constant() { + // CHECK-LABEL: @overaligned_constant + // CHECK: [[full:%_.*]] = alloca [32 x i8], align 8 // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[full]], ptr align 8 @0, i64 32, i1 false) // CHECK: %b.0 = load i32, ptr @0, align 4 // CHECK: %b.1 = load i32, ptr getelementptr inbounds ({{.*}}), align 4 diff --git a/tests/codegen/packed.rs b/tests/codegen/packed.rs index 764476b0aa13..5142df9c4881 100644 --- a/tests/codegen/packed.rs +++ b/tests/codegen/packed.rs @@ -51,7 +51,7 @@ pub struct BigPacked2 { // CHECK-LABEL: @call_pkd1 #[no_mangle] pub fn call_pkd1(f: fn() -> Array) -> BigPacked1 { -// CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca %Array +// CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca [32 x i8] // CHECK: call void %{{.*}}(ptr noalias nocapture noundef sret{{.*}} dereferenceable(32) [[ALLOCA]]) // CHECK: call void @llvm.memcpy.{{.*}}(ptr align 1 %{{.*}}, ptr align 4 %{{.*}}, i{{[0-9]+}} 32, i1 false) // check that calls whose destination is a field of a packed struct @@ -63,7 +63,7 @@ pub fn call_pkd1(f: fn() -> Array) -> BigPacked1 { // CHECK-LABEL: @call_pkd2 #[no_mangle] pub fn call_pkd2(f: fn() -> Array) -> BigPacked2 { -// CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca %Array +// CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca [32 x i8] // CHECK: call void %{{.*}}(ptr noalias nocapture noundef sret{{.*}} dereferenceable(32) [[ALLOCA]]) // CHECK: call void @llvm.memcpy.{{.*}}(ptr align 2 %{{.*}}, ptr align 4 %{{.*}}, i{{[0-9]+}} 32, i1 false) // check that calls whose destination is a field of a packed struct diff --git a/tests/codegen/personality_lifetimes.rs b/tests/codegen/personality_lifetimes.rs index f2ab9c3bb82b..0ef4aa424d83 100644 --- a/tests/codegen/personality_lifetimes.rs +++ b/tests/codegen/personality_lifetimes.rs @@ -23,7 +23,7 @@ pub fn test() { let _s = S; // Check that the personality slot alloca gets a lifetime start in each cleanup block, not just // in the first one. - // CHECK: [[SLOT:%[0-9]+]] = alloca { ptr, i32{{.*}} } + // CHECK: [[SLOT:%[0-9]+]] = alloca [{{[0-9]+}} x i8] // CHECK-LABEL: cleanup: // CHECK: call void @llvm.lifetime.start.{{.*}}({{.*}}) // CHECK-LABEL: cleanup1: diff --git a/tests/codegen/sroa-fragment-debuginfo.rs b/tests/codegen/sroa-fragment-debuginfo.rs index d8c2d2c6f9ef..32786d2a76a4 100644 --- a/tests/codegen/sroa-fragment-debuginfo.rs +++ b/tests/codegen/sroa-fragment-debuginfo.rs @@ -14,9 +14,9 @@ pub struct ExtraSlice<'input> { #[no_mangle] pub fn extra(s: &[u8]) { // CHECK: void @extra( -// CHECK: %slice.dbg.spill1 = alloca i32, -// CHECK: %slice.dbg.spill = alloca { ptr, i64 }, -// CHECK: %s.dbg.spill = alloca { ptr, i64 }, +// CHECK: %slice.dbg.spill1 = alloca [4 x i8], +// CHECK: %slice.dbg.spill = alloca [16 x i8], +// CHECK: %s.dbg.spill = alloca [16 x i8], // CHECK: call void @llvm.dbg.declare(metadata ptr %s.dbg.spill, metadata ![[S_EXTRA:.*]], metadata !DIExpression()), // CHECK: call void @llvm.dbg.declare(metadata ptr %slice.dbg.spill, metadata ![[SLICE_EXTRA:.*]], metadata !DIExpression(DW_OP_LLVM_fragment, 0, 128)), // CHECK: call void @llvm.dbg.declare(metadata ptr %slice.dbg.spill1, metadata ![[SLICE_EXTRA]], metadata !DIExpression(DW_OP_LLVM_fragment, 128, 32)), diff --git a/tests/codegen/stores.rs b/tests/codegen/stores.rs index 3fda5aa47eaf..86ec52fa1015 100644 --- a/tests/codegen/stores.rs +++ b/tests/codegen/stores.rs @@ -15,8 +15,8 @@ pub struct Bytes { // dependent alignment #[no_mangle] pub fn small_array_alignment(x: &mut [i8; 4], y: [i8; 4]) { -// CHECK: [[TMP:%.+]] = alloca i32 -// CHECK: %y = alloca [4 x i8] +// CHECK: [[TMP:%.+]] = alloca [4 x i8], align 4 +// CHECK: %y = alloca [4 x i8], align 1 // CHECK: store i32 %0, ptr [[TMP]] // CHECK: call void @llvm.memcpy.{{.*}}(ptr align 1 {{.+}}, ptr align 4 {{.+}}, i{{[0-9]+}} 4, i1 false) *x = y; @@ -27,8 +27,8 @@ pub fn small_array_alignment(x: &mut [i8; 4], y: [i8; 4]) { // dependent alignment #[no_mangle] pub fn small_struct_alignment(x: &mut Bytes, y: Bytes) { -// CHECK: [[TMP:%.+]] = alloca i32 -// CHECK: %y = alloca %Bytes +// CHECK: [[TMP:%.+]] = alloca [4 x i8], align 4 +// CHECK: %y = alloca [4 x i8], align 1 // CHECK: store i32 %0, ptr [[TMP]] // CHECK: call void @llvm.memcpy.{{.*}}(ptr align 1 {{.+}}, ptr align 4 {{.+}}, i{{[0-9]+}} 4, i1 false) *x = y; diff --git a/tests/codegen/swap-large-types.rs b/tests/codegen/swap-large-types.rs index b182f3ed9479..b976f6fe207b 100644 --- a/tests/codegen/swap-large-types.rs +++ b/tests/codegen/swap-large-types.rs @@ -15,7 +15,7 @@ type KeccakBuffer = [[u64; 5]; 5]; // CHECK-LABEL: @swap_basic #[no_mangle] pub fn swap_basic(x: &mut KeccakBuffer, y: &mut KeccakBuffer) { -// CHECK: alloca [5 x [5 x i64]] +// CHECK: alloca [200 x i8] // SAFETY: exclusive references are always valid to read/write, // are non-overlapping, and nothing here panics so it's drop-safe. diff --git a/tests/codegen/swap-small-types.rs b/tests/codegen/swap-small-types.rs index 4dcfed2a53af..1a48c63d8139 100644 --- a/tests/codegen/swap-small-types.rs +++ b/tests/codegen/swap-small-types.rs @@ -12,7 +12,7 @@ type RGB48 = [u16; 3]; pub fn swap_rgb48_manually(x: &mut RGB48, y: &mut RGB48) { // FIXME: See #115212 for why this has an alloca again - // CHECK: alloca [3 x i16], align 2 + // CHECK: alloca [6 x i8], align 2 // CHECK: call void @llvm.memcpy.p0.p0.i64({{.+}}, i64 6, i1 false) // CHECK: call void @llvm.memcpy.p0.p0.i64({{.+}}, i64 6, i1 false) // CHECK: call void @llvm.memcpy.p0.p0.i64({{.+}}, i64 6, i1 false) From d46b6889451de69a9cf7808a042d8292fc2c341a Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Tue, 5 Mar 2024 20:55:42 -0500 Subject: [PATCH 02/36] adjust stack-protector test (which inappropriately depends on IR types) --- .../stack-protector-heuristics-effect.rs | 55 +++++-------------- 1 file changed, 15 insertions(+), 40 deletions(-) diff --git a/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs b/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs index e63adc88ff50..8e32d170244a 100644 --- a/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs +++ b/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs @@ -11,6 +11,11 @@ //@ compile-flags: -C opt-level=2 -Z merge-functions=disabled //@ min-llvm-version: 17.0.2 +// NOTE: the heuristics for stack smash protection inappropriately rely on types in LLVM IR, +// despite those types having no semantic meaning. This means that the `basic` and `strong` +// settings do not behave in a coherent way. This is a known issue in LLVM. +// See comments on https://github.com/rust-lang/rust/issues/114903. + #![crate_type = "lib"] #![allow(incomplete_features)] @@ -39,23 +44,9 @@ pub fn array_char(f: fn(*const char)) { f(&b as *const _); f(&c as *const _); - // Any type of local array variable leads to stack protection with the - // "strong" heuristic. The 'basic' heuristic only adds stack protection to - // functions with local array variables of a byte-sized type, however. Since - // 'char' is 4 bytes in Rust, this function is not protected by the 'basic' - // heuristic - // - // (This test *also* takes the address of the local stack variables. We - // cannot know that this isn't what triggers the `strong` heuristic. - // However, the test strategy of passing the address of a stack array to an - // external function is sufficient to trigger the `basic` heuristic (see - // test `array_u8_large()`). Since the `basic` heuristic only checks for the - // presence of stack-local array variables, we can be confident that this - // test also captures this part of the `strong` heuristic specification.) - // all: __stack_chk_fail // strong: __stack_chk_fail - // basic-NOT: __stack_chk_fail + // basic: __stack_chk_fail // none-NOT: __stack_chk_fail // missing-NOT: __stack_chk_fail } @@ -163,26 +154,11 @@ pub fn local_string_addr_taken(f: fn(&String)) { f(&x); // Taking the address of the local variable `x` leads to stack smash - // protection with the `strong` heuristic, but not with the `basic` - // heuristic. It does not matter that the reference is not mut. - // - // An interesting note is that a similar function in C++ *would* be - // protected by the `basic` heuristic, because `std::string` has a char - // array internally as a small object optimization: - // ``` - // cat < - // void f(void (*g)(const std::string&)) { - // std::string x; - // g(x); - // } - // EOF - // ``` - // + // protection. It does not matter that the reference is not mut. // all: __stack_chk_fail // strong: __stack_chk_fail - // basic-NOT: __stack_chk_fail + // basic: __stack_chk_fail // none-NOT: __stack_chk_fail // missing-NOT: __stack_chk_fail } @@ -233,8 +209,8 @@ pub fn local_large_var_moved(f: fn(Gigastruct)) { // Even though the local variable conceptually doesn't have its address // taken, it's so large that the "move" is implemented with a reference to a // stack-local variable in the ABI. Consequently, this function *is* - // protected by the `strong` heuristic. This is also the case for - // rvalue-references in C++, regardless of struct size: + // protected. This is also the case for rvalue-references in C++, + // regardless of struct size: // ``` // cat < @@ -248,7 +224,7 @@ pub fn local_large_var_moved(f: fn(Gigastruct)) { // all: __stack_chk_fail // strong: __stack_chk_fail - // basic-NOT: __stack_chk_fail + // basic: __stack_chk_fail // none-NOT: __stack_chk_fail // missing-NOT: __stack_chk_fail } @@ -261,9 +237,9 @@ pub fn local_large_var_cloned(f: fn(Gigastruct)) { // A new instance of `Gigastruct` is passed to `f()`, without any apparent // connection to this stack frame. Still, since instances of `Gigastruct` // are sufficiently large, it is allocated in the caller stack frame and - // passed as a pointer. As such, this function is *also* protected by the - // `strong` heuristic, just like `local_large_var_moved`. This is also the - // case for pass-by-value of sufficiently large structs in C++: + // passed as a pointer. As such, this function is *also* protected, just + // like `local_large_var_moved`. This is also the case for pass-by-value + // of sufficiently large structs in C++: // ``` // cat < @@ -275,10 +251,9 @@ pub fn local_large_var_cloned(f: fn(Gigastruct)) { // EOF // ``` - // all: __stack_chk_fail // strong: __stack_chk_fail - // basic-NOT: __stack_chk_fail + // basic: __stack_chk_fail // none-NOT: __stack_chk_fail // missing-NOT: __stack_chk_fail } From 1ce5dc8d9c638194306e63abfe81748c77e7386e Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Fri, 12 Apr 2024 08:29:06 -0400 Subject: [PATCH 03/36] restore location in gcc alloca codegen --- compiler/rustc_codegen_gcc/src/builder.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index cf1aa3f47934..8d6c16ebe045 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -902,7 +902,13 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let ty = self.cx.type_array(self.cx.type_i8(), size.bytes()).get_aligned(align.bytes()); // TODO(antoyo): It might be better to return a LValue, but fixing the rustc API is non-trivial. self.stack_var_count.set(self.stack_var_count.get() + 1); - self.current_func().new_local(None, ty, &format!("stack_var_{}", self.stack_var_count.get())).get_address(None) + self.current_func() + .new_local( + self.location, + ty, + &format!("stack_var_{}", self.stack_var_count.get()), + ) + .get_address(self.location) } fn dynamic_alloca(&mut self, _len: RValue<'gcc>, _align: Align) -> RValue<'gcc> { From daaaacdcb31addf5a56fe70884d72cf28998bdc2 Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Fri, 12 Apr 2024 08:31:35 -0400 Subject: [PATCH 04/36] remove alloca type from issue-105386-ub-in-debuginfo It's irrelevant for the purposes of this test (there is only one alloca) and its size changes depending on the target, so it can't be matched easily. --- tests/codegen/issues/issue-105386-ub-in-debuginfo.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/codegen/issues/issue-105386-ub-in-debuginfo.rs b/tests/codegen/issues/issue-105386-ub-in-debuginfo.rs index 4d1c0a83b55f..56b4330b1a6c 100644 --- a/tests/codegen/issues/issue-105386-ub-in-debuginfo.rs +++ b/tests/codegen/issues/issue-105386-ub-in-debuginfo.rs @@ -15,7 +15,7 @@ pub fn outer_function(x: S, y: S) -> usize { // Check that we do not attempt to load from the spilled arg before it is assigned to // when generating debuginfo. // CHECK-LABEL: @outer_function -// CHECK: [[spill:%.*]] = alloca [72 x i8] +// CHECK: [[spill:%.*]] = alloca // CHECK-NOT: [[ptr_tmp:%.*]] = getelementptr inbounds i8, ptr [[spill]] // CHECK-NOT: [[load:%.*]] = load ptr, ptr // CHECK: call void @llvm.lifetime.start{{.*}}({{.*}}, ptr [[spill]]) From b76de157090381eefa6079be0efe763a192a76cb Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Fri, 12 Apr 2024 16:12:13 -0700 Subject: [PATCH 05/36] Bump Fuchsia versions This updates the Fuchsia commit used in `auto - x86_64-gnu-integration` CI bot to use the Rust commit 703dc9ce64d9b31a239a7280d9b5f9ddd85ffed6. This should help improve the coverage of this builder. It also updates the SDK version to F20.20240412.3.1, and the Fuchsia Clang version to c777c011a709dffd4fa5e79cad7947b7c3405d02. --- .../host-x86_64/x86_64-gnu-integration/build-fuchsia.sh | 2 +- src/ci/docker/scripts/build-fuchsia-toolchain.sh | 8 ++++---- src/ci/docker/scripts/fuchsia-test-runner.py | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-integration/build-fuchsia.sh b/src/ci/docker/host-x86_64/x86_64-gnu-integration/build-fuchsia.sh index d6de992913bf..9cc508fe9288 100755 --- a/src/ci/docker/host-x86_64/x86_64-gnu-integration/build-fuchsia.sh +++ b/src/ci/docker/host-x86_64/x86_64-gnu-integration/build-fuchsia.sh @@ -5,7 +5,7 @@ set -euf -o pipefail -INTEGRATION_SHA=56310bca298872ffb5ea02e665956d9b6dc41171 +INTEGRATION_SHA=1011e3298775ee7cdf6f6dc73e808d6a86e33bd6 PICK_REFS=() checkout=fuchsia diff --git a/src/ci/docker/scripts/build-fuchsia-toolchain.sh b/src/ci/docker/scripts/build-fuchsia-toolchain.sh index beea2f522fde..7a0d4fcffc15 100755 --- a/src/ci/docker/scripts/build-fuchsia-toolchain.sh +++ b/src/ci/docker/scripts/build-fuchsia-toolchain.sh @@ -4,13 +4,13 @@ set -ex source shared.sh FUCHSIA_SDK_URL=https://chrome-infra-packages.appspot.com/dl/fuchsia/sdk/core/linux-amd64 -FUCHSIA_SDK_ID=MrhQwtmP8CpZre-i_PNOREcThbUcrX3bA-45d6WQr-cC -FUCHSIA_SDK_SHA256=32b850c2d98ff02a59adefa2fcf34e44471385b51cad7ddb03ee3977a590afe7 +FUCHSIA_SDK_ID=version:20.20240412.3.1 +FUCHSIA_SDK_SHA256=cc52f3497487dd813c89d9316e6967efcea89c7759edccf3e40fcf3662e53f19 FUCHSIA_SDK_USR_DIR=/usr/local/core-linux-amd64-fuchsia-sdk CLANG_DOWNLOAD_URL=\ https://chrome-infra-packages.appspot.com/dl/fuchsia/third_party/clang/linux-amd64 -CLANG_DOWNLOAD_ID=Tpc85d1ZwSlZ6UKl2d96GRUBGNA5JKholOKe24sRDr0C -CLANG_DOWNLOAD_SHA256=4e973ce5dd59c12959e942a5d9df7a19150118d03924a86894e29edb8b110ebd +CLANG_DOWNLOAD_ID=git_revision:c777c011a709dffd4fa5e79cad7947b7c3405d02 +CLANG_DOWNLOAD_SHA256=779167422ad73c292f049dcea5569f84577af9292189ed2749518b966a4d0844 install_clang() { mkdir -p clang_download diff --git a/src/ci/docker/scripts/fuchsia-test-runner.py b/src/ci/docker/scripts/fuchsia-test-runner.py index 437b51641fc9..8ac00a8863f6 100755 --- a/src/ci/docker/scripts/fuchsia-test-runner.py +++ b/src/ci/docker/scripts/fuchsia-test-runner.py @@ -280,7 +280,7 @@ class TestEnvironment: # Look up the product bundle transfer manifest. self.log_info("Looking up the product bundle transfer manifest...") product_name = "minimal." + self.triple_to_arch(self.target) - fuchsia_version = "14.20230811.2.1" + fuchsia_version = "20.20240412.3.1" # FIXME: We should be able to replace this with the machine parsable # `ffx --machine json product lookup ...` once F15 is released. From 4559e61dd7c44705ca2ed62e4d93fe94ab1010f6 Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Mon, 1 Apr 2024 11:27:48 +0200 Subject: [PATCH 06/36] Test `#[unix_sigpipe = "inherit"]` with both `SIG_DFL` and `SIG_IGN` Add a test that fails if `#[unix_sigpipe = "inherit"]` wrongly results in `SIGPIPE` being `SIG_DFL` if the parent has `SIG_IGN`. We have no current test for this particular case. --- .../auxiliary/assert-inherit-sig_dfl.rs | 8 +++++ .../auxiliary/assert-inherit-sig_ign.rs | 8 +++++ .../unix_sigpipe/unix_sigpipe-inherit.rs | 31 ++++++++++++++----- 3 files changed, 39 insertions(+), 8 deletions(-) create mode 100644 tests/ui/attributes/unix_sigpipe/auxiliary/assert-inherit-sig_dfl.rs create mode 100644 tests/ui/attributes/unix_sigpipe/auxiliary/assert-inherit-sig_ign.rs diff --git a/tests/ui/attributes/unix_sigpipe/auxiliary/assert-inherit-sig_dfl.rs b/tests/ui/attributes/unix_sigpipe/auxiliary/assert-inherit-sig_dfl.rs new file mode 100644 index 000000000000..7f95fa7ebbec --- /dev/null +++ b/tests/ui/attributes/unix_sigpipe/auxiliary/assert-inherit-sig_dfl.rs @@ -0,0 +1,8 @@ +//@ aux-crate: sigpipe_utils=sigpipe-utils.rs + +#![feature(unix_sigpipe)] + +#[unix_sigpipe = "inherit"] +fn main() { + sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Default); +} diff --git a/tests/ui/attributes/unix_sigpipe/auxiliary/assert-inherit-sig_ign.rs b/tests/ui/attributes/unix_sigpipe/auxiliary/assert-inherit-sig_ign.rs new file mode 100644 index 000000000000..d96e8b8ef843 --- /dev/null +++ b/tests/ui/attributes/unix_sigpipe/auxiliary/assert-inherit-sig_ign.rs @@ -0,0 +1,8 @@ +//@ aux-crate: sigpipe_utils=sigpipe-utils.rs + +#![feature(unix_sigpipe)] + +#[unix_sigpipe = "inherit"] +fn main() { + sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Ignore); +} diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-inherit.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-inherit.rs index db3407a7d55f..694fa460e9bb 100644 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-inherit.rs +++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-inherit.rs @@ -1,14 +1,29 @@ +//@ ignore-cross-compile because aux-bin does not yet support it +//@ only-unix because SIGPIPE is a unix thing +//@ aux-bin: assert-inherit-sig_dfl.rs +//@ aux-bin: assert-inherit-sig_ign.rs //@ run-pass -//@ aux-build:sigpipe-utils.rs -#![feature(unix_sigpipe)] +#![feature(rustc_private, unix_sigpipe)] -#[unix_sigpipe = "inherit"] +extern crate libc; + +// By default the Rust runtime resets SIGPIPE to SIG_DFL before exec:ing child +// processes so opt-out of that with `#[unix_sigpipe = "sig_dfl"]`. See +// https://github.com/rust-lang/rust/blob/bf4de3a874753bbee3323081c8b0c133444fed2d/library/std/src/sys/pal/unix/process/process_unix.rs#L359-L384 +#[unix_sigpipe = "sig_dfl"] fn main() { - extern crate sigpipe_utils; + // First expect SIG_DFL in a child process with #[unix_sigpipe = "inherit"]. + assert_inherit_sigpipe_disposition("auxiliary/bin/assert-inherit-sig_dfl"); - // #[unix_sigpipe = "inherit"] is active, so SIGPIPE shall NOT be ignored, - // instead the default handler shall be installed. (We assume that the - // process that runs these tests have the default handler.) - sigpipe_utils::assert_sigpipe_handler(sigpipe_utils::SignalHandler::Default); + // With SIG_IGN we expect #[unix_sigpipe = "inherit"] to also get SIG_IGN. + unsafe { + libc::signal(libc::SIGPIPE, libc::SIG_IGN); + } + assert_inherit_sigpipe_disposition("auxiliary/bin/assert-inherit-sig_ign"); +} + +fn assert_inherit_sigpipe_disposition(aux_bin: &str) { + let mut cmd = std::process::Command::new(aux_bin); + assert!(cmd.status().unwrap().success()); } From 9fec43ddf12118f6bfa66aedb17bca91618f153b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Fri, 19 Apr 2024 21:41:49 +0200 Subject: [PATCH 07/36] Move calculate-job-matrix.py to `ci/github-actions` --- .github/workflows/ci.yml | 2 +- src/ci/{scripts => github-actions}/calculate-job-matrix.py | 2 +- src/ci/github-actions/ci.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename src/ci/{scripts => github-actions}/calculate-job-matrix.py (84%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 90269f56c52a..e01eec949a21 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -45,7 +45,7 @@ jobs: - name: Checkout the source code uses: actions/checkout@v4 - name: Calculate the CI job matrix - run: python3 src/ci/scripts/calculate-job-matrix.py >> $GITHUB_OUTPUT + run: python3 src/ci/github-actions/calculate-job-matrix.py >> $GITHUB_OUTPUT id: jobs pr: name: "PR - ${{ matrix.name }}" diff --git a/src/ci/scripts/calculate-job-matrix.py b/src/ci/github-actions/calculate-job-matrix.py similarity index 84% rename from src/ci/scripts/calculate-job-matrix.py rename to src/ci/github-actions/calculate-job-matrix.py index 9b1e74c23c32..ba40f4da8475 100755 --- a/src/ci/scripts/calculate-job-matrix.py +++ b/src/ci/github-actions/calculate-job-matrix.py @@ -15,7 +15,7 @@ from pathlib import Path import yaml -JOBS_YAML_PATH = Path(__file__).absolute().parent.parent / "github-actions" / "jobs.yml" +JOBS_YAML_PATH = Path(__file__).absolute().parent / "jobs.yml" if __name__ == "__main__": diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index de71b9f874f8..9d1c3284be20 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -351,7 +351,7 @@ jobs: - name: Checkout the source code uses: actions/checkout@v4 - name: Calculate the CI job matrix - run: python3 src/ci/scripts/calculate-job-matrix.py >> $GITHUB_OUTPUT + run: python3 src/ci/github-actions/calculate-job-matrix.py >> $GITHUB_OUTPUT id: jobs pr: <<: *base-ci-job From 7a90679e28382ebd48790eaab80cb2381704223e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sat, 20 Apr 2024 09:07:11 +0200 Subject: [PATCH 08/36] Perform PR and try builds dynamically --- .github/workflows/ci.yml | 155 +----------------- src/ci/github-actions/calculate-job-matrix.py | 42 ++++- src/ci/github-actions/ci.yml | 41 ++--- src/ci/github-actions/jobs.yml | 45 ++++- 4 files changed, 102 insertions(+), 181 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e01eec949a21..25be8607edd7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -45,23 +45,23 @@ jobs: - name: Checkout the source code uses: actions/checkout@v4 - name: Calculate the CI job matrix + env: + GITHUB_CTX: "${{ toJSON(github) }}" run: python3 src/ci/github-actions/calculate-job-matrix.py >> $GITHUB_OUTPUT id: jobs - pr: - name: "PR - ${{ matrix.name }}" + job: + name: "${{ matrix.name }}" needs: - calculate_matrix env: - PR_CI_JOB: 1 - CI_JOB_NAME: "${{ matrix.name }}" + CI_JOB_NAME: "${{ matrix.image }}" CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse HEAD_SHA: "${{ github.event.pull_request.head.sha || github.sha }}" DOCKER_TOKEN: "${{ secrets.GITHUB_TOKEN }}" SCCACHE_BUCKET: rust-lang-ci-sccache2 TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate" CACHE_DOMAIN: ci-caches.rust-lang.org - if: "github.event_name == 'pull_request'" - continue-on-error: "${{ matrix.name == 'mingw-check-tidy' }}" + continue-on-error: "${{ matrix.continue_on_error || false }}" strategy: matrix: include: "${{ fromJSON(needs.calculate_matrix.outputs.jobs) }}" @@ -589,145 +589,6 @@ jobs: AWS_ACCESS_KEY_ID: "${{ env.ARTIFACTS_AWS_ACCESS_KEY_ID }}" AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }}" if: "success() && !env.SKIP_JOB && (github.event_name == 'push' || env.DEPLOY == '1' || env.DEPLOY_ALT == '1')" - try: - name: "try - ${{ matrix.name }}" - env: - DIST_TRY_BUILD: 1 - CI_JOB_NAME: "${{ matrix.name }}" - CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse - HEAD_SHA: "${{ github.event.pull_request.head.sha || github.sha }}" - DOCKER_TOKEN: "${{ secrets.GITHUB_TOKEN }}" - SCCACHE_BUCKET: rust-lang-ci-sccache2 - DEPLOY_BUCKET: rust-lang-ci2 - TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate" - TOOLSTATE_ISSUES_API_URL: "https://api.github.com/repos/rust-lang/rust/issues" - TOOLSTATE_PUBLISH: 1 - CACHES_AWS_ACCESS_KEY_ID: AKIA46X5W6CZI5DHEBFL - ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZN24CBO55 - AWS_REGION: us-west-1 - CACHE_DOMAIN: ci-caches.rust-lang.org - if: "github.event_name == 'push' && (((github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.repository == 'rust-lang-ci/rust') || ((github.ref == 'refs/heads/automation/bors/try') && github.repository == 'rust-lang/rust'))" - strategy: - matrix: - include: - - name: dist-x86_64-linux - env: - CODEGEN_BACKENDS: "llvm,cranelift" - os: ubuntu-20.04-16core-64gb - defaults: - run: - shell: "${{ contains(matrix.os, 'windows') && 'msys2 {0}' || 'bash' }}" - timeout-minutes: 600 - runs-on: "${{ matrix.os }}" - steps: - - if: "contains(matrix.os, 'windows')" - uses: msys2/setup-msys2@v2.22.0 - with: - msystem: "${{ contains(matrix.name, 'i686') && 'mingw32' || 'mingw64' }}" - update: false - release: true - path-type: inherit - install: "make dos2unix diffutils\n" - - name: disable git crlf conversion - run: git config --global core.autocrlf false - - name: checkout the source code - uses: actions/checkout@v4 - with: - fetch-depth: 2 - - name: configure the PR in which the error message will be posted - run: "echo \"[CI_PR_NUMBER=$num]\"" - env: - num: "${{ github.event.number }}" - if: "success() && !env.SKIP_JOB && github.event_name == 'pull_request'" - - name: add extra environment variables - run: src/ci/scripts/setup-environment.sh - env: - EXTRA_VARIABLES: "${{ toJson(matrix.env) }}" - if: success() && !env.SKIP_JOB - - name: decide whether to skip this job - run: src/ci/scripts/should-skip-this.sh - if: success() && !env.SKIP_JOB - - name: ensure the channel matches the target branch - run: src/ci/scripts/verify-channel.sh - if: success() && !env.SKIP_JOB - - name: collect CPU statistics - run: src/ci/scripts/collect-cpu-stats.sh - if: success() && !env.SKIP_JOB - - name: show the current environment - run: src/ci/scripts/dump-environment.sh - if: success() && !env.SKIP_JOB - - name: install awscli - run: src/ci/scripts/install-awscli.sh - if: success() && !env.SKIP_JOB - - name: install sccache - run: src/ci/scripts/install-sccache.sh - if: success() && !env.SKIP_JOB - - name: select Xcode - run: src/ci/scripts/select-xcode.sh - if: success() && !env.SKIP_JOB - - name: install clang - run: src/ci/scripts/install-clang.sh - if: success() && !env.SKIP_JOB - - name: install tidy - run: src/ci/scripts/install-tidy.sh - if: success() && !env.SKIP_JOB - - name: install WIX - run: src/ci/scripts/install-wix.sh - if: success() && !env.SKIP_JOB - - name: disable git crlf conversion - run: src/ci/scripts/disable-git-crlf-conversion.sh - if: success() && !env.SKIP_JOB - - name: checkout submodules - run: src/ci/scripts/checkout-submodules.sh - if: success() && !env.SKIP_JOB - - name: install MSYS2 - run: src/ci/scripts/install-msys2.sh - if: success() && !env.SKIP_JOB - - name: install MinGW - run: src/ci/scripts/install-mingw.sh - if: success() && !env.SKIP_JOB - - name: install ninja - run: src/ci/scripts/install-ninja.sh - if: success() && !env.SKIP_JOB - - name: enable ipv6 on Docker - run: src/ci/scripts/enable-docker-ipv6.sh - if: success() && !env.SKIP_JOB - - name: disable git crlf conversion - run: src/ci/scripts/disable-git-crlf-conversion.sh - if: success() && !env.SKIP_JOB - - name: ensure line endings are correct - run: src/ci/scripts/verify-line-endings.sh - if: success() && !env.SKIP_JOB - - name: ensure backported commits are in upstream branches - run: src/ci/scripts/verify-backported-commits.sh - if: success() && !env.SKIP_JOB - - name: ensure the stable version number is correct - run: src/ci/scripts/verify-stable-version-number.sh - if: success() && !env.SKIP_JOB - - name: run the build - run: src/ci/scripts/run-build-from-ci.sh 2>&1 - env: - AWS_ACCESS_KEY_ID: "${{ env.CACHES_AWS_ACCESS_KEY_ID }}" - AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.CACHES_AWS_ACCESS_KEY_ID)] }}" - TOOLSTATE_REPO_ACCESS_TOKEN: "${{ secrets.TOOLSTATE_REPO_ACCESS_TOKEN }}" - if: success() && !env.SKIP_JOB - - name: create github artifacts - run: src/ci/scripts/create-doc-artifacts.sh - if: success() && !env.SKIP_JOB - - name: upload artifacts to github - uses: actions/upload-artifact@v4 - with: - name: "${{ env.DOC_ARTIFACT_NAME }}" - path: obj/artifacts/doc - if-no-files-found: ignore - retention-days: 5 - if: success() && !env.SKIP_JOB - - name: upload artifacts to S3 - run: src/ci/scripts/upload-artifacts.sh - env: - AWS_ACCESS_KEY_ID: "${{ env.ARTIFACTS_AWS_ACCESS_KEY_ID }}" - AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }}" - if: "success() && !env.SKIP_JOB && (github.event_name == 'push' || env.DEPLOY == '1' || env.DEPLOY_ALT == '1')" master: name: master runs-on: ubuntu-latest @@ -755,7 +616,7 @@ jobs: if: success() && !env.SKIP_JOB try-success: needs: - - try + - job if: "success() && github.event_name == 'push' && (github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.repository == 'rust-lang-ci/rust'" steps: - name: mark the job as a success @@ -765,7 +626,7 @@ jobs: runs-on: ubuntu-latest try-failure: needs: - - try + - job if: "!success() && github.event_name == 'push' && (github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.repository == 'rust-lang-ci/rust'" steps: - name: mark the job as a failure diff --git a/src/ci/github-actions/calculate-job-matrix.py b/src/ci/github-actions/calculate-job-matrix.py index ba40f4da8475..59c191cb45db 100755 --- a/src/ci/github-actions/calculate-job-matrix.py +++ b/src/ci/github-actions/calculate-job-matrix.py @@ -7,19 +7,53 @@ be executed on CI. It reads job definitions from `src/ci/github-actions/jobs.yml` and filters them based on the event that happened on CI. -Currently, it only supports PR builds. +Currently, it only supports PR and try builds. """ import json +import os +import sys from pathlib import Path +from typing import List, Dict import yaml JOBS_YAML_PATH = Path(__file__).absolute().parent / "jobs.yml" +def name_jobs(jobs: List[Dict], prefix: str) -> List[Dict]: + for job in jobs: + job["name"] = f"{prefix} - {job['image']}" + return jobs + + if __name__ == "__main__": + github_ctx = json.loads(os.environ["GITHUB_CTX"]) + with open(JOBS_YAML_PATH) as f: - jobs = yaml.safe_load(f) - job_output = jobs["pr"] - print(f"jobs={json.dumps(job_output)}") + data = yaml.safe_load(f) + + event_name = github_ctx["event_name"] + ref = github_ctx["ref"] + repository = github_ctx["repository"] + + old_bors_try_build = ( + ref in ("refs/heads/try", "refs/heads/try-perf") and + repository == "rust-lang-ci/rust" + ) + new_bors_try_build = ( + ref == "refs/heads/automation/bors/try" and + repository == "rust-lang/rust" + ) + try_build = old_bors_try_build or new_bors_try_build + + jobs = [] + # Pull request CI jobs. Their name is 'PR - ' + if event_name == "pull_request": + jobs = name_jobs(data["pr"], "PR") + # Try builds + elif event_name == "push" and try_build: + jobs = name_jobs(data["try"], "try") + + print(f"Output:\n{json.dumps(jobs, indent=4)}", file=sys.stderr) + print(f"jobs={json.dumps(jobs)}") diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index 9d1c3284be20..e7847a57e974 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -351,17 +351,25 @@ jobs: - name: Checkout the source code uses: actions/checkout@v4 - name: Calculate the CI job matrix + env: + GITHUB_CTX: ${{ toJSON(github) }} run: python3 src/ci/github-actions/calculate-job-matrix.py >> $GITHUB_OUTPUT id: jobs - pr: + # This is either a PR or a try job, decided by calculate-job-matrix.py + job: <<: *base-ci-job - name: PR - ${{ matrix.name }} + name: ${{ matrix.name }} needs: [ calculate_matrix ] env: - <<: [*shared-ci-variables, *public-variables] - PR_CI_JOB: 1 - if: github.event_name == 'pull_request' - continue-on-error: ${{ matrix.name == 'mingw-check-tidy' }} + CI_JOB_NAME: ${{ matrix.image }} + CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse + # commit of PR sha or commit sha. `GITHUB_SHA` is not accurate for PRs. + HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }} + DOCKER_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SCCACHE_BUCKET: rust-lang-ci-sccache2 + TOOLSTATE_REPO: https://github.com/rust-lang-nursery/rust-toolstate + CACHE_DOMAIN: ci-caches.rust-lang.org + continue-on-error: ${{ matrix.continue_on_error || false }} strategy: matrix: # Check the `calculate_matrix` job to see how is the matrix defined. @@ -751,23 +759,6 @@ jobs: SCRIPT: python x.py dist bootstrap --include-default-paths <<: *job-windows-8c - try: - <<: *base-ci-job - name: try - ${{ matrix.name }} - env: - DIST_TRY_BUILD: 1 - <<: [*shared-ci-variables, *prod-variables] - if: github.event_name == 'push' && (((github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.repository == 'rust-lang-ci/rust') || ((github.ref == 'refs/heads/automation/bors/try') && github.repository == 'rust-lang/rust')) - strategy: - matrix: - include: - - &dist-x86_64-linux - name: dist-x86_64-linux - env: - CODEGEN_BACKENDS: llvm,cranelift - <<: *job-linux-16c - - master: name: master runs-on: ubuntu-latest @@ -791,11 +782,11 @@ jobs: # build completed, as there is no practical way to detect when a workflow is # successful listening to webhooks only. try-success: - needs: [try] + needs: [ job ] if: "success() && github.event_name == 'push' && (github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.repository == 'rust-lang-ci/rust'" <<: *base-success-job try-failure: - needs: [try] + needs: [ job ] if: "!success() && github.event_name == 'push' && (github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.repository == 'rust-lang-ci/rust'" <<: *base-failure-job auto-success: diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 7e89eef2670e..2aea6ce4fa7d 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -2,7 +2,7 @@ # dynamically in CI from ci.yml. # You *do not* need to re-run `src/tools/expand-yaml-anchors` when you # modify this file. -shared_defs: +runners: - &base-job env: { } @@ -37,14 +37,49 @@ shared_defs: - &job-aarch64-linux os: [ self-hosted, ARM64, linux ] +envs: + - &prod-variables + DEPLOY_BUCKET: rust-lang-ci2 + TOOLSTATE_ISSUES_API_URL: https://api.github.com/repos/rust-lang/rust/issues + TOOLSTATE_PUBLISH: 1 + # AWS_SECRET_ACCESS_KEYs are stored in GitHub's secrets storage, named + # AWS_SECRET_ACCESS_KEY_. Including the key id in the name allows to + # rotate them in a single branch while keeping the old key in another + # branch, which wouldn't be possible if the key was named with the kind + # (caches, artifacts...). + CACHES_AWS_ACCESS_KEY_ID: AKIA46X5W6CZI5DHEBFL + ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZN24CBO55 + AWS_REGION: us-west-1 + + - &pr-env + PR_CI_JOB: 1 + +# Pull request jobs pr: - - name: mingw-check + - image: mingw-check + env: + <<: *pr-env <<: *job-linux-4c - - name: mingw-check-tidy + - image: mingw-check-tidy + continue_on_error: true + env: + <<: *pr-env <<: *job-linux-4c - - name: x86_64-gnu-llvm-17 + - image: x86_64-gnu-llvm-17 env: ENABLE_GCC_CODEGEN: "1" + <<: *pr-env <<: *job-linux-16c - - name: x86_64-gnu-tools + - image: x86_64-gnu-tools + env: + <<: *pr-env + <<: *job-linux-16c + +# Try build jobs +try: + - image: dist-x86_64-linux + env: + DIST_TRY_BUILD: 1 + CODEGEN_BACKENDS: llvm,cranelift + <<: *prod-variables <<: *job-linux-16c From 6f0ff0b03a291382ceb51fc12ea6882605684a5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sat, 20 Apr 2024 09:16:16 +0200 Subject: [PATCH 09/36] Refactor `calculate-job-matrix.py` --- src/ci/github-actions/calculate-job-matrix.py | 71 +++++++++++++------ 1 file changed, 48 insertions(+), 23 deletions(-) diff --git a/src/ci/github-actions/calculate-job-matrix.py b/src/ci/github-actions/calculate-job-matrix.py index 59c191cb45db..15a835e260cc 100755 --- a/src/ci/github-actions/calculate-job-matrix.py +++ b/src/ci/github-actions/calculate-job-matrix.py @@ -9,12 +9,12 @@ and filters them based on the event that happened on CI. Currently, it only supports PR and try builds. """ - +import enum import json +import logging import os -import sys from pathlib import Path -from typing import List, Dict +from typing import List, Dict, Any, Optional import yaml @@ -27,33 +27,58 @@ def name_jobs(jobs: List[Dict], prefix: str) -> List[Dict]: return jobs +class JobType(enum.Enum): + PR = enum.auto() + Try = enum.auto() + + +def find_job_type(github_ctx: Dict[str, Any]) -> Optional[JobType]: + event_name = github_ctx["event_name"] + ref = github_ctx["ref"] + repository = github_ctx["repository"] + + if event_name == "pull_request": + return JobType.PR + elif event_name == "push": + old_bors_try_build = ( + ref in ("refs/heads/try", "refs/heads/try-perf") and + repository == "rust-lang-ci/rust" + ) + new_bors_try_build = ( + ref == "refs/heads/automation/bors/try" and + repository == "rust-lang/rust" + ) + try_build = old_bors_try_build or new_bors_try_build + + if try_build: + return JobType.Try + + return None + + +def calculate_jobs(job_type: JobType, job_data: Dict[str, Any]) -> List[Dict[str, Any]]: + if job_type == JobType.PR: + return name_jobs(job_data["pr"], "PR") + elif job_type == JobType.Try: + return name_jobs(job_data["try"], "try") + + return [] + + if __name__ == "__main__": + logging.basicConfig(level=logging.INFO) + github_ctx = json.loads(os.environ["GITHUB_CTX"]) with open(JOBS_YAML_PATH) as f: data = yaml.safe_load(f) - event_name = github_ctx["event_name"] - ref = github_ctx["ref"] - repository = github_ctx["repository"] - - old_bors_try_build = ( - ref in ("refs/heads/try", "refs/heads/try-perf") and - repository == "rust-lang-ci/rust" - ) - new_bors_try_build = ( - ref == "refs/heads/automation/bors/try" and - repository == "rust-lang/rust" - ) - try_build = old_bors_try_build or new_bors_try_build + job_type = find_job_type(github_ctx) + logging.info(f"Job type: {job_type}") jobs = [] - # Pull request CI jobs. Their name is 'PR - ' - if event_name == "pull_request": - jobs = name_jobs(data["pr"], "PR") - # Try builds - elif event_name == "push" and try_build: - jobs = name_jobs(data["try"], "try") + if job_type is not None: + jobs = calculate_jobs(job_type, data) - print(f"Output:\n{json.dumps(jobs, indent=4)}", file=sys.stderr) + logging.info(f"Output:\n{yaml.dump(jobs, indent=4)}") print(f"jobs={json.dumps(jobs)}") From d2059aef270fc60f65273f816467761a4eeeb638 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sat, 20 Apr 2024 09:42:23 +0200 Subject: [PATCH 10/36] Move `auto` jobs to calculate-job-matrix.py --- .github/workflows/ci.yml | 414 +----------------- src/ci/github-actions/calculate-job-matrix.py | 31 +- src/ci/github-actions/ci.yml | 391 +---------------- src/ci/github-actions/jobs.yml | 398 ++++++++++++++++- 4 files changed, 417 insertions(+), 817 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 25be8607edd7..010872c980f9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -179,416 +179,6 @@ jobs: AWS_ACCESS_KEY_ID: "${{ env.ARTIFACTS_AWS_ACCESS_KEY_ID }}" AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }}" if: "success() && !env.SKIP_JOB && (github.event_name == 'push' || env.DEPLOY == '1' || env.DEPLOY_ALT == '1')" - auto: - name: "auto - ${{ matrix.name }}" - env: - CI_JOB_NAME: "${{ matrix.name }}" - CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse - HEAD_SHA: "${{ github.event.pull_request.head.sha || github.sha }}" - DOCKER_TOKEN: "${{ secrets.GITHUB_TOKEN }}" - SCCACHE_BUCKET: rust-lang-ci-sccache2 - DEPLOY_BUCKET: rust-lang-ci2 - TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate" - TOOLSTATE_ISSUES_API_URL: "https://api.github.com/repos/rust-lang/rust/issues" - TOOLSTATE_PUBLISH: 1 - CACHES_AWS_ACCESS_KEY_ID: AKIA46X5W6CZI5DHEBFL - ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZN24CBO55 - AWS_REGION: us-west-1 - CACHE_DOMAIN: ci-caches.rust-lang.org - if: "github.event_name == 'push' && github.ref == 'refs/heads/auto' && github.repository == 'rust-lang-ci/rust'" - strategy: - matrix: - include: - - name: aarch64-gnu - os: - - self-hosted - - ARM64 - - linux - - name: arm-android - os: ubuntu-20.04-8core-32gb - env: {} - - name: armhf-gnu - os: ubuntu-20.04-8core-32gb - env: {} - - name: dist-aarch64-linux - env: - CODEGEN_BACKENDS: "llvm,cranelift" - os: ubuntu-20.04-8core-32gb - - name: dist-android - os: ubuntu-20.04-8core-32gb - env: {} - - name: dist-arm-linux - os: ubuntu-20.04-16core-64gb - env: {} - - name: dist-armhf-linux - os: ubuntu-20.04-8core-32gb - env: {} - - name: dist-armv7-linux - os: ubuntu-20.04-8core-32gb - env: {} - - name: dist-i586-gnu-i586-i686-musl - os: ubuntu-20.04-8core-32gb - env: {} - - name: dist-i686-linux - os: ubuntu-20.04-8core-32gb - env: {} - - name: dist-loongarch64-linux - os: ubuntu-20.04-8core-32gb - env: {} - - name: dist-ohos - os: ubuntu-20.04-8core-32gb - env: {} - - name: dist-powerpc-linux - os: ubuntu-20.04-8core-32gb - env: {} - - name: dist-powerpc64-linux - os: ubuntu-20.04-8core-32gb - env: {} - - name: dist-powerpc64le-linux - os: ubuntu-20.04-8core-32gb - env: {} - - name: dist-riscv64-linux - os: ubuntu-20.04-8core-32gb - env: {} - - name: dist-s390x-linux - os: ubuntu-20.04-8core-32gb - env: {} - - name: dist-various-1 - os: ubuntu-20.04-8core-32gb - env: {} - - name: dist-various-2 - os: ubuntu-20.04-8core-32gb - env: {} - - name: dist-x86_64-freebsd - os: ubuntu-20.04-8core-32gb - env: {} - - name: dist-x86_64-illumos - os: ubuntu-20.04-8core-32gb - env: {} - - name: dist-x86_64-linux - env: - CODEGEN_BACKENDS: "llvm,cranelift" - os: ubuntu-20.04-16core-64gb - - name: dist-x86_64-linux-alt - env: - IMAGE: dist-x86_64-linux - CODEGEN_BACKENDS: "llvm,cranelift" - os: ubuntu-20.04-16core-64gb - - name: dist-x86_64-musl - env: - CODEGEN_BACKENDS: "llvm,cranelift" - os: ubuntu-20.04-8core-32gb - - name: dist-x86_64-netbsd - os: ubuntu-20.04-8core-32gb - env: {} - - name: i686-gnu - os: ubuntu-20.04-8core-32gb - env: {} - - name: i686-gnu-nopt - os: ubuntu-20.04-8core-32gb - env: {} - - name: mingw-check - os: ubuntu-20.04-4core-16gb - env: {} - - name: test-various - os: ubuntu-20.04-8core-32gb - env: {} - - name: x86_64-gnu - os: ubuntu-20.04-4core-16gb - env: {} - - name: x86_64-gnu-stable - env: - IMAGE: x86_64-gnu - RUST_CI_OVERRIDE_RELEASE_CHANNEL: stable - CI_ONLY_WHEN_CHANNEL: nightly - os: ubuntu-20.04-4core-16gb - - name: x86_64-gnu-aux - os: ubuntu-20.04-4core-16gb - env: {} - - name: x86_64-gnu-integration - env: - CI_ONLY_WHEN_CHANNEL: nightly - os: ubuntu-20.04-8core-32gb - - name: x86_64-gnu-debug - os: ubuntu-20.04-8core-32gb - env: {} - - name: x86_64-gnu-distcheck - os: ubuntu-20.04-8core-32gb - env: {} - - name: x86_64-gnu-llvm-18 - env: - RUST_BACKTRACE: 1 - os: ubuntu-20.04-8core-32gb - - name: x86_64-gnu-llvm-17 - env: - RUST_BACKTRACE: 1 - os: ubuntu-20.04-8core-32gb - - name: x86_64-gnu-nopt - os: ubuntu-20.04-4core-16gb - env: {} - - name: x86_64-gnu-tools - env: - DEPLOY_TOOLSTATES_JSON: toolstates-linux.json - os: ubuntu-20.04-8core-32gb - - name: dist-x86_64-apple - env: - SCRIPT: "./x.py dist bootstrap --include-default-paths --host=x86_64-apple-darwin --target=x86_64-apple-darwin" - RUST_CONFIGURE_ARGS: "--enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set rust.lto=thin --set rust.codegen-units=1" - RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.12 - SELECT_XCODE: /Applications/Xcode_14.3.1.app - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - NO_OVERFLOW_CHECKS: 1 - DIST_REQUIRE_ALL_TOOLS: 1 - CODEGEN_BACKENDS: "llvm,cranelift" - os: macos-13 - - name: dist-apple-various - env: - SCRIPT: "./x.py dist bootstrap --include-default-paths --host='' --target=aarch64-apple-ios,x86_64-apple-ios,aarch64-apple-ios-sim" - RUST_CONFIGURE_ARGS: "--enable-sanitizers --enable-profiler --set rust.jemalloc" - RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.12 - SELECT_XCODE: /Applications/Xcode_14.3.1.app - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - NO_OVERFLOW_CHECKS: 1 - os: macos-13 - - name: x86_64-apple-1 - env: - SCRIPT: "./x.py --stage 2 test --skip tests/ui --skip tests/rustdoc --skip tests/run-make-fulldeps" - RUST_CONFIGURE_ARGS: "--build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc" - RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.12 - MACOSX_STD_DEPLOYMENT_TARGET: 10.12 - SELECT_XCODE: /Applications/Xcode_14.3.1.app - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - NO_OVERFLOW_CHECKS: 1 - os: macos-13 - - name: x86_64-apple-2 - env: - SCRIPT: "./x.py --stage 2 test tests/ui tests/rustdoc tests/run-make-fulldeps" - RUST_CONFIGURE_ARGS: "--build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc" - RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.12 - MACOSX_STD_DEPLOYMENT_TARGET: 10.12 - SELECT_XCODE: /Applications/Xcode_14.3.1.app - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - NO_OVERFLOW_CHECKS: 1 - os: macos-13 - - name: dist-aarch64-apple - env: - SCRIPT: "./x.py dist bootstrap --include-default-paths --host=aarch64-apple-darwin --target=aarch64-apple-darwin" - RUST_CONFIGURE_ARGS: "--enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false --set rust.lto=thin" - RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - SELECT_XCODE: /Applications/Xcode_14.3.1.app - USE_XCODE_CLANG: 1 - MACOSX_DEPLOYMENT_TARGET: 11.0 - MACOSX_STD_DEPLOYMENT_TARGET: 11.0 - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - NO_OVERFLOW_CHECKS: 1 - DIST_REQUIRE_ALL_TOOLS: 1 - os: macos-14 - - name: aarch64-apple - env: - SCRIPT: "./x.py --stage 2 test --host=aarch64-apple-darwin --target=aarch64-apple-darwin" - RUST_CONFIGURE_ARGS: "--enable-sanitizers --enable-profiler --set rust.jemalloc" - RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - SELECT_XCODE: /Applications/Xcode_14.3.1.app - USE_XCODE_CLANG: 1 - MACOSX_DEPLOYMENT_TARGET: 11.0 - MACOSX_STD_DEPLOYMENT_TARGET: 11.0 - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - NO_OVERFLOW_CHECKS: 1 - os: macos-14 - - name: x86_64-msvc - env: - RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --enable-profiler" - SCRIPT: make ci-msvc - os: windows-2019-8core-32gb - - name: i686-msvc - env: - RUST_CONFIGURE_ARGS: "--build=i686-pc-windows-msvc" - SCRIPT: make ci-msvc - os: windows-2019-8core-32gb - - name: x86_64-msvc-ext - env: - SCRIPT: python x.py --stage 2 test src/tools/cargotest src/tools/cargo && src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstate/toolstates.json windows - HOST_TARGET: x86_64-pc-windows-msvc - RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --enable-lld --save-toolstates=/tmp/toolstate/toolstates.json" - DEPLOY_TOOLSTATES_JSON: toolstates-windows.json - os: windows-2019-8core-32gb - - name: i686-mingw - env: - RUST_CONFIGURE_ARGS: "--build=i686-pc-windows-gnu" - SCRIPT: make ci-mingw - NO_DOWNLOAD_CI_LLVM: 1 - CUSTOM_MINGW: 1 - os: windows-2019-8core-32gb - - name: x86_64-mingw - env: - SCRIPT: make ci-mingw - RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-gnu --enable-profiler" - NO_DOWNLOAD_CI_LLVM: 1 - CUSTOM_MINGW: 1 - os: windows-2019-8core-32gb - - name: dist-x86_64-msvc - env: - RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --host=x86_64-pc-windows-msvc --target=x86_64-pc-windows-msvc --enable-full-tools --enable-profiler --set rust.codegen-units=1" - SCRIPT: python x.py build --set rust.debug=true opt-dist && PGO_HOST=x86_64-pc-windows-msvc ./build/x86_64-pc-windows-msvc/stage0-tools-bin/opt-dist windows-ci -- python x.py dist bootstrap --include-default-paths - DIST_REQUIRE_ALL_TOOLS: 1 - os: windows-2019-8core-32gb - - name: dist-i686-msvc - env: - RUST_CONFIGURE_ARGS: "--build=i686-pc-windows-msvc --host=i686-pc-windows-msvc --target=i686-pc-windows-msvc,i586-pc-windows-msvc --enable-full-tools --enable-profiler" - SCRIPT: python x.py dist bootstrap --include-default-paths - DIST_REQUIRE_ALL_TOOLS: 1 - os: windows-2019-8core-32gb - - name: dist-aarch64-msvc - env: - RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --host=aarch64-pc-windows-msvc --enable-full-tools --enable-profiler" - SCRIPT: python x.py dist bootstrap --include-default-paths - DIST_REQUIRE_ALL_TOOLS: 1 - os: windows-2019-8core-32gb - - name: dist-i686-mingw - env: - RUST_CONFIGURE_ARGS: "--build=i686-pc-windows-gnu --enable-full-tools --enable-profiler" - NO_DOWNLOAD_CI_LLVM: 1 - SCRIPT: python x.py dist bootstrap --include-default-paths - CUSTOM_MINGW: 1 - DIST_REQUIRE_ALL_TOOLS: 1 - os: windows-2019-8core-32gb - - name: dist-x86_64-mingw - env: - SCRIPT: python x.py dist bootstrap --include-default-paths - RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-gnu --enable-full-tools --enable-profiler" - NO_DOWNLOAD_CI_LLVM: 1 - CUSTOM_MINGW: 1 - DIST_REQUIRE_ALL_TOOLS: 1 - os: windows-2019-8core-32gb - - name: dist-x86_64-msvc-alt - env: - RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --enable-extended --enable-profiler" - SCRIPT: python x.py dist bootstrap --include-default-paths - os: windows-2019-8core-32gb - defaults: - run: - shell: "${{ contains(matrix.os, 'windows') && 'msys2 {0}' || 'bash' }}" - timeout-minutes: 600 - runs-on: "${{ matrix.os }}" - steps: - - if: "contains(matrix.os, 'windows')" - uses: msys2/setup-msys2@v2.22.0 - with: - msystem: "${{ contains(matrix.name, 'i686') && 'mingw32' || 'mingw64' }}" - update: false - release: true - path-type: inherit - install: "make dos2unix diffutils\n" - - name: disable git crlf conversion - run: git config --global core.autocrlf false - - name: checkout the source code - uses: actions/checkout@v4 - with: - fetch-depth: 2 - - name: configure the PR in which the error message will be posted - run: "echo \"[CI_PR_NUMBER=$num]\"" - env: - num: "${{ github.event.number }}" - if: "success() && !env.SKIP_JOB && github.event_name == 'pull_request'" - - name: add extra environment variables - run: src/ci/scripts/setup-environment.sh - env: - EXTRA_VARIABLES: "${{ toJson(matrix.env) }}" - if: success() && !env.SKIP_JOB - - name: decide whether to skip this job - run: src/ci/scripts/should-skip-this.sh - if: success() && !env.SKIP_JOB - - name: ensure the channel matches the target branch - run: src/ci/scripts/verify-channel.sh - if: success() && !env.SKIP_JOB - - name: collect CPU statistics - run: src/ci/scripts/collect-cpu-stats.sh - if: success() && !env.SKIP_JOB - - name: show the current environment - run: src/ci/scripts/dump-environment.sh - if: success() && !env.SKIP_JOB - - name: install awscli - run: src/ci/scripts/install-awscli.sh - if: success() && !env.SKIP_JOB - - name: install sccache - run: src/ci/scripts/install-sccache.sh - if: success() && !env.SKIP_JOB - - name: select Xcode - run: src/ci/scripts/select-xcode.sh - if: success() && !env.SKIP_JOB - - name: install clang - run: src/ci/scripts/install-clang.sh - if: success() && !env.SKIP_JOB - - name: install tidy - run: src/ci/scripts/install-tidy.sh - if: success() && !env.SKIP_JOB - - name: install WIX - run: src/ci/scripts/install-wix.sh - if: success() && !env.SKIP_JOB - - name: disable git crlf conversion - run: src/ci/scripts/disable-git-crlf-conversion.sh - if: success() && !env.SKIP_JOB - - name: checkout submodules - run: src/ci/scripts/checkout-submodules.sh - if: success() && !env.SKIP_JOB - - name: install MSYS2 - run: src/ci/scripts/install-msys2.sh - if: success() && !env.SKIP_JOB - - name: install MinGW - run: src/ci/scripts/install-mingw.sh - if: success() && !env.SKIP_JOB - - name: install ninja - run: src/ci/scripts/install-ninja.sh - if: success() && !env.SKIP_JOB - - name: enable ipv6 on Docker - run: src/ci/scripts/enable-docker-ipv6.sh - if: success() && !env.SKIP_JOB - - name: disable git crlf conversion - run: src/ci/scripts/disable-git-crlf-conversion.sh - if: success() && !env.SKIP_JOB - - name: ensure line endings are correct - run: src/ci/scripts/verify-line-endings.sh - if: success() && !env.SKIP_JOB - - name: ensure backported commits are in upstream branches - run: src/ci/scripts/verify-backported-commits.sh - if: success() && !env.SKIP_JOB - - name: ensure the stable version number is correct - run: src/ci/scripts/verify-stable-version-number.sh - if: success() && !env.SKIP_JOB - - name: run the build - run: src/ci/scripts/run-build-from-ci.sh 2>&1 - env: - AWS_ACCESS_KEY_ID: "${{ env.CACHES_AWS_ACCESS_KEY_ID }}" - AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.CACHES_AWS_ACCESS_KEY_ID)] }}" - TOOLSTATE_REPO_ACCESS_TOKEN: "${{ secrets.TOOLSTATE_REPO_ACCESS_TOKEN }}" - if: success() && !env.SKIP_JOB - - name: create github artifacts - run: src/ci/scripts/create-doc-artifacts.sh - if: success() && !env.SKIP_JOB - - name: upload artifacts to github - uses: actions/upload-artifact@v4 - with: - name: "${{ env.DOC_ARTIFACT_NAME }}" - path: obj/artifacts/doc - if-no-files-found: ignore - retention-days: 5 - if: success() && !env.SKIP_JOB - - name: upload artifacts to S3 - run: src/ci/scripts/upload-artifacts.sh - env: - AWS_ACCESS_KEY_ID: "${{ env.ARTIFACTS_AWS_ACCESS_KEY_ID }}" - AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }}" - if: "success() && !env.SKIP_JOB && (github.event_name == 'push' || env.DEPLOY == '1' || env.DEPLOY_ALT == '1')" master: name: master runs-on: ubuntu-latest @@ -636,7 +226,7 @@ jobs: runs-on: ubuntu-latest auto-success: needs: - - auto + - job if: "success() && github.event_name == 'push' && github.ref == 'refs/heads/auto' && github.repository == 'rust-lang-ci/rust'" steps: - name: mark the job as a success @@ -646,7 +236,7 @@ jobs: runs-on: ubuntu-latest auto-failure: needs: - - auto + - job if: "!success() && github.event_name == 'push' && github.ref == 'refs/heads/auto' && github.repository == 'rust-lang-ci/rust'" steps: - name: mark the job as a failure diff --git a/src/ci/github-actions/calculate-job-matrix.py b/src/ci/github-actions/calculate-job-matrix.py index 15a835e260cc..935b1bb56c37 100755 --- a/src/ci/github-actions/calculate-job-matrix.py +++ b/src/ci/github-actions/calculate-job-matrix.py @@ -6,8 +6,6 @@ be executed on CI. It reads job definitions from `src/ci/github-actions/jobs.yml` and filters them based on the event that happened on CI. - -Currently, it only supports PR and try builds. """ import enum import json @@ -22,14 +20,30 @@ JOBS_YAML_PATH = Path(__file__).absolute().parent / "jobs.yml" def name_jobs(jobs: List[Dict], prefix: str) -> List[Dict]: + """ + Add a `name` attribute to each job, based on its image and the given `prefix`. + """ for job in jobs: job["name"] = f"{prefix} - {job['image']}" return jobs +def add_base_env(jobs: List[Dict], environment: Dict[str, str]) -> List[Dict]: + """ + Prepends `environment` to the `env` attribute of each job. + The `env` of each job has higher precedence than `environment`. + """ + for job in jobs: + env = environment.copy() + env.update(job.get("env", {})) + job["env"] = env + return jobs + + class JobType(enum.Enum): PR = enum.auto() Try = enum.auto() + Auto = enum.auto() def find_job_type(github_ctx: Dict[str, Any]) -> Optional[JobType]: @@ -53,14 +67,19 @@ def find_job_type(github_ctx: Dict[str, Any]) -> Optional[JobType]: if try_build: return JobType.Try + if ref == "refs/heads/auto" and repository == "rust-lang-ci/rust": + return JobType.Auto + return None def calculate_jobs(job_type: JobType, job_data: Dict[str, Any]) -> List[Dict[str, Any]]: if job_type == JobType.PR: - return name_jobs(job_data["pr"], "PR") + return add_base_env(name_jobs(job_data["pr"], "PR"), job_data["envs"]["pr"]) elif job_type == JobType.Try: - return name_jobs(job_data["try"], "try") + return add_base_env(name_jobs(job_data["try"], "try"), job_data["envs"]["production"]) + elif job_type == JobType.Auto: + return add_base_env(name_jobs(job_data["auto"], "auto"), job_data["envs"]["production"]) return [] @@ -68,11 +87,11 @@ def calculate_jobs(job_type: JobType, job_data: Dict[str, Any]) -> List[Dict[str if __name__ == "__main__": logging.basicConfig(level=logging.INFO) - github_ctx = json.loads(os.environ["GITHUB_CTX"]) - with open(JOBS_YAML_PATH) as f: data = yaml.safe_load(f) + github_ctx = json.loads(os.environ["GITHUB_CTX"]) + job_type = find_job_type(github_ctx) logging.info(f"Job type: {job_type}") diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index e7847a57e974..2a271b43a8a5 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -342,6 +342,8 @@ concurrency: jobs: # The job matrix for `calculate_matrix` is defined in src/ci/github-actions/jobs.yml. + # It calculates which jobs should be executed, based on the data of the ${{ github }} context. + # If you want to modify CI jobs, take a look at src/ci/github-actions/jobs.yml. calculate_matrix: name: Calculate job matrix runs-on: ubuntu-latest @@ -355,7 +357,6 @@ jobs: GITHUB_CTX: ${{ toJSON(github) }} run: python3 src/ci/github-actions/calculate-job-matrix.py >> $GITHUB_OUTPUT id: jobs - # This is either a PR or a try job, decided by calculate-job-matrix.py job: <<: *base-ci-job name: ${{ matrix.name }} @@ -375,390 +376,6 @@ jobs: # Check the `calculate_matrix` job to see how is the matrix defined. include: ${{ fromJSON(needs.calculate_matrix.outputs.jobs) }} - auto: - <<: *base-ci-job - name: auto - ${{ matrix.name }} - env: - <<: [*shared-ci-variables, *prod-variables] - if: github.event_name == 'push' && github.ref == 'refs/heads/auto' && github.repository == 'rust-lang-ci/rust' - strategy: - matrix: - include: - ############################# - # Linux/Docker builders # - ############################# - - - name: aarch64-gnu - <<: *job-aarch64-linux - - - name: arm-android - <<: *job-linux-8c - - - name: armhf-gnu - <<: *job-linux-8c - - - name: dist-aarch64-linux - env: - CODEGEN_BACKENDS: llvm,cranelift - <<: *job-linux-8c - - - name: dist-android - <<: *job-linux-8c - - - name: dist-arm-linux - <<: *job-linux-16c - - - name: dist-armhf-linux - <<: *job-linux-8c - - - name: dist-armv7-linux - <<: *job-linux-8c - - - name: dist-i586-gnu-i586-i686-musl - <<: *job-linux-8c - - - name: dist-i686-linux - <<: *job-linux-8c - - - name: dist-loongarch64-linux - <<: *job-linux-8c - - - name: dist-ohos - <<: *job-linux-8c - - - name: dist-powerpc-linux - <<: *job-linux-8c - - - name: dist-powerpc64-linux - <<: *job-linux-8c - - - name: dist-powerpc64le-linux - <<: *job-linux-8c - - - name: dist-riscv64-linux - <<: *job-linux-8c - - - name: dist-s390x-linux - <<: *job-linux-8c - - - name: dist-various-1 - <<: *job-linux-8c - - - name: dist-various-2 - <<: *job-linux-8c - - - name: dist-x86_64-freebsd - <<: *job-linux-8c - - - name: dist-x86_64-illumos - <<: *job-linux-8c - - - &dist-x86_64-linux - name: dist-x86_64-linux - env: - CODEGEN_BACKENDS: llvm,cranelift - <<: *job-linux-16c - - - name: dist-x86_64-linux-alt - env: - IMAGE: dist-x86_64-linux - CODEGEN_BACKENDS: llvm,cranelift - <<: *job-linux-16c - - - name: dist-x86_64-musl - env: - CODEGEN_BACKENDS: llvm,cranelift - <<: *job-linux-8c - - - name: dist-x86_64-netbsd - <<: *job-linux-8c - - - name: i686-gnu - <<: *job-linux-8c - - - name: i686-gnu-nopt - <<: *job-linux-8c - - - name: mingw-check - <<: *job-linux-4c - - - name: test-various - <<: *job-linux-8c - - - name: x86_64-gnu - <<: *job-linux-4c - - # This job ensures commits landing on nightly still pass the full - # test suite on the stable channel. There are some UI tests that - # depend on the channel being built (for example if they include the - # channel name on the output), and this builder prevents landing - # changes that would result in broken builds after a promotion. - - name: x86_64-gnu-stable - env: - IMAGE: x86_64-gnu - RUST_CI_OVERRIDE_RELEASE_CHANNEL: stable - # Only run this job on the nightly channel. Running this on beta - # could cause failures when `dev: 1` in `stage0.txt`, and running - # this on stable is useless. - CI_ONLY_WHEN_CHANNEL: nightly - <<: *job-linux-4c - - - name: x86_64-gnu-aux - <<: *job-linux-4c - - - name: x86_64-gnu-integration - env: - # Only run this job on the nightly channel. Fuchsia requires - # nightly features to compile, and this job would fail if - # executed on beta and stable. - CI_ONLY_WHEN_CHANNEL: nightly - <<: *job-linux-8c - - - name: x86_64-gnu-debug - <<: *job-linux-8c - - - name: x86_64-gnu-distcheck - <<: *job-linux-8c - - - name: x86_64-gnu-llvm-18 - env: - RUST_BACKTRACE: 1 - <<: *job-linux-8c - - - name: x86_64-gnu-llvm-17 - env: - RUST_BACKTRACE: 1 - <<: *job-linux-8c - - - name: x86_64-gnu-nopt - <<: *job-linux-4c - - - name: x86_64-gnu-tools - env: - DEPLOY_TOOLSTATES_JSON: toolstates-linux.json - <<: *job-linux-8c - - #################### - # macOS Builders # - #################### - - - name: dist-x86_64-apple - env: - SCRIPT: ./x.py dist bootstrap --include-default-paths --host=x86_64-apple-darwin --target=x86_64-apple-darwin - RUST_CONFIGURE_ARGS: --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set rust.lto=thin --set rust.codegen-units=1 - RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.12 - SELECT_XCODE: /Applications/Xcode_14.3.1.app - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - NO_OVERFLOW_CHECKS: 1 - DIST_REQUIRE_ALL_TOOLS: 1 - CODEGEN_BACKENDS: llvm,cranelift - <<: *job-macos-xl - - - name: dist-apple-various - env: - SCRIPT: ./x.py dist bootstrap --include-default-paths --host='' --target=aarch64-apple-ios,x86_64-apple-ios,aarch64-apple-ios-sim - RUST_CONFIGURE_ARGS: --enable-sanitizers --enable-profiler --set rust.jemalloc - RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.12 - SELECT_XCODE: /Applications/Xcode_14.3.1.app - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - NO_OVERFLOW_CHECKS: 1 - <<: *job-macos-xl - - - name: x86_64-apple-1 - env: &env-x86_64-apple-tests - SCRIPT: ./x.py --stage 2 test --skip tests/ui --skip tests/rustdoc --skip tests/run-make-fulldeps - RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc - RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.12 - MACOSX_STD_DEPLOYMENT_TARGET: 10.12 - SELECT_XCODE: /Applications/Xcode_14.3.1.app - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - NO_OVERFLOW_CHECKS: 1 - <<: *job-macos-xl - - - name: x86_64-apple-2 - env: - SCRIPT: ./x.py --stage 2 test tests/ui tests/rustdoc tests/run-make-fulldeps - <<: *env-x86_64-apple-tests - <<: *job-macos-xl - - # This target only needs to support 11.0 and up as nothing else supports the hardware - - name: dist-aarch64-apple - env: - SCRIPT: ./x.py dist bootstrap --include-default-paths --host=aarch64-apple-darwin --target=aarch64-apple-darwin - RUST_CONFIGURE_ARGS: >- - --enable-full-tools - --enable-sanitizers - --enable-profiler - --set rust.jemalloc - --set llvm.ninja=false - --set rust.lto=thin - RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - SELECT_XCODE: /Applications/Xcode_14.3.1.app - USE_XCODE_CLANG: 1 - MACOSX_DEPLOYMENT_TARGET: 11.0 - MACOSX_STD_DEPLOYMENT_TARGET: 11.0 - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - NO_OVERFLOW_CHECKS: 1 - DIST_REQUIRE_ALL_TOOLS: 1 - <<: *job-macos-m1 - - # This target only needs to support 11.0 and up as nothing else supports the hardware - - name: aarch64-apple - env: - SCRIPT: ./x.py --stage 2 test --host=aarch64-apple-darwin --target=aarch64-apple-darwin - RUST_CONFIGURE_ARGS: >- - --enable-sanitizers - --enable-profiler - --set rust.jemalloc - RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - SELECT_XCODE: /Applications/Xcode_14.3.1.app - USE_XCODE_CLANG: 1 - MACOSX_DEPLOYMENT_TARGET: 11.0 - MACOSX_STD_DEPLOYMENT_TARGET: 11.0 - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - NO_OVERFLOW_CHECKS: 1 - <<: *job-macos-m1 - - ###################### - # Windows Builders # - ###################### - - - name: x86_64-msvc - env: - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler - SCRIPT: make ci-msvc - <<: *job-windows-8c - - - name: i686-msvc - env: - RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc - SCRIPT: make ci-msvc - <<: *job-windows-8c - - - name: x86_64-msvc-ext - env: - SCRIPT: python x.py --stage 2 test src/tools/cargotest src/tools/cargo && src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstate/toolstates.json windows - HOST_TARGET: x86_64-pc-windows-msvc - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-lld --save-toolstates=/tmp/toolstate/toolstates.json - DEPLOY_TOOLSTATES_JSON: toolstates-windows.json - <<: *job-windows-8c - - # 32/64-bit MinGW builds. - # - # We are using MinGW with POSIX threads since LLVM requires - # C++'s std::thread which is disabled in libstdc++ with win32 threads. - # FIXME: Libc++ doesn't have this limitation so we can avoid - # winpthreads if we switch to it. - # - # Instead of relying on the MinGW version installed on CI we download - # and install one ourselves so we won't be surprised by changes to CI's - # build image. - # - # Finally, note that the downloads below are all in the `rust-lang-ci` S3 - # bucket, but they clearly didn't originate there! The downloads originally - # came from the mingw-w64 SourceForge download site. Unfortunately - # SourceForge is notoriously flaky, so we mirror it on our own infrastructure. - - - name: i686-mingw - env: - RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu - SCRIPT: make ci-mingw - # We are intentionally allowing an old toolchain on this builder (and that's - # incompatible with LLVM downloads today). - NO_DOWNLOAD_CI_LLVM: 1 - CUSTOM_MINGW: 1 - <<: *job-windows-8c - - - name: x86_64-mingw - env: - SCRIPT: make ci-mingw - RUST_CONFIGURE_ARGS: >- - --build=x86_64-pc-windows-gnu - --enable-profiler - # We are intentionally allowing an old toolchain on this builder (and that's - # incompatible with LLVM downloads today). - NO_DOWNLOAD_CI_LLVM: 1 - CUSTOM_MINGW: 1 - <<: *job-windows-8c - - - name: dist-x86_64-msvc - env: - RUST_CONFIGURE_ARGS: >- - --build=x86_64-pc-windows-msvc - --host=x86_64-pc-windows-msvc - --target=x86_64-pc-windows-msvc - --enable-full-tools - --enable-profiler - --set rust.codegen-units=1 - SCRIPT: python x.py build --set rust.debug=true opt-dist && PGO_HOST=x86_64-pc-windows-msvc ./build/x86_64-pc-windows-msvc/stage0-tools-bin/opt-dist windows-ci -- python x.py dist bootstrap --include-default-paths - DIST_REQUIRE_ALL_TOOLS: 1 - <<: *job-windows-8c - - - name: dist-i686-msvc - env: - RUST_CONFIGURE_ARGS: >- - --build=i686-pc-windows-msvc - --host=i686-pc-windows-msvc - --target=i686-pc-windows-msvc,i586-pc-windows-msvc - --enable-full-tools - --enable-profiler - SCRIPT: python x.py dist bootstrap --include-default-paths - DIST_REQUIRE_ALL_TOOLS: 1 - <<: *job-windows-8c - - - name: dist-aarch64-msvc - env: - RUST_CONFIGURE_ARGS: >- - --build=x86_64-pc-windows-msvc - --host=aarch64-pc-windows-msvc - --enable-full-tools - --enable-profiler - SCRIPT: python x.py dist bootstrap --include-default-paths - DIST_REQUIRE_ALL_TOOLS: 1 - <<: *job-windows-8c - - - name: dist-i686-mingw - env: - RUST_CONFIGURE_ARGS: >- - --build=i686-pc-windows-gnu - --enable-full-tools - --enable-profiler - # We are intentionally allowing an old toolchain on this builder (and that's - # incompatible with LLVM downloads today). - NO_DOWNLOAD_CI_LLVM: 1 - SCRIPT: python x.py dist bootstrap --include-default-paths - CUSTOM_MINGW: 1 - DIST_REQUIRE_ALL_TOOLS: 1 - <<: *job-windows-8c - - - name: dist-x86_64-mingw - env: - SCRIPT: python x.py dist bootstrap --include-default-paths - RUST_CONFIGURE_ARGS: >- - --build=x86_64-pc-windows-gnu - --enable-full-tools - --enable-profiler - # We are intentionally allowing an old toolchain on this builder (and that's - # incompatible with LLVM downloads today). - NO_DOWNLOAD_CI_LLVM: 1 - CUSTOM_MINGW: 1 - DIST_REQUIRE_ALL_TOOLS: 1 - <<: *job-windows-8c - - - name: dist-x86_64-msvc-alt - env: - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended --enable-profiler - SCRIPT: python x.py dist bootstrap --include-default-paths - <<: *job-windows-8c - master: name: master runs-on: ubuntu-latest @@ -790,10 +407,10 @@ jobs: if: "!success() && github.event_name == 'push' && (github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.repository == 'rust-lang-ci/rust'" <<: *base-failure-job auto-success: - needs: [auto] + needs: [ job ] if: "success() && github.event_name == 'push' && github.ref == 'refs/heads/auto' && github.repository == 'rust-lang-ci/rust'" <<: *base-success-job auto-failure: - needs: [auto] + needs: [ job ] if: "!success() && github.event_name == 'push' && github.ref == 'refs/heads/auto' && github.repository == 'rust-lang-ci/rust'" <<: *base-failure-job diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 2aea6ce4fa7d..cfa0732cf2d6 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -38,7 +38,7 @@ runners: os: [ self-hosted, ARM64, linux ] envs: - - &prod-variables + production: DEPLOY_BUCKET: rust-lang-ci2 TOOLSTATE_ISSUES_API_URL: https://api.github.com/repos/rust-lang/rust/issues TOOLSTATE_PUBLISH: 1 @@ -51,35 +51,409 @@ envs: ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZN24CBO55 AWS_REGION: us-west-1 - - &pr-env + pr: PR_CI_JOB: 1 -# Pull request jobs +# Jobs that run on each push to a pull request (PR) +# These jobs automatically inherit envs.pr, to avoid repeating +# it in each job definition. pr: - image: mingw-check - env: - <<: *pr-env <<: *job-linux-4c - image: mingw-check-tidy continue_on_error: true - env: - <<: *pr-env <<: *job-linux-4c - image: x86_64-gnu-llvm-17 env: ENABLE_GCC_CODEGEN: "1" - <<: *pr-env <<: *job-linux-16c - image: x86_64-gnu-tools - env: - <<: *pr-env <<: *job-linux-16c -# Try build jobs +# Jobs that run when you perform a try build (@bors try) +# These jobs automatically inherit envs.production, to avoid repeating +# it in each job definition. try: - image: dist-x86_64-linux env: DIST_TRY_BUILD: 1 CODEGEN_BACKENDS: llvm,cranelift - <<: *prod-variables <<: *job-linux-16c + +# Main CI jobs that have to be green to merge a commit into master +# These jobs automatically inherit envs.production, to avoid repeating +# it in each job definition. +auto: + ############################# + # Linux/Docker builders # + ############################# + + - name: aarch64-gnu + <<: *job-aarch64-linux + + - name: arm-android + <<: *job-linux-8c + + - name: armhf-gnu + <<: *job-linux-8c + + - name: dist-aarch64-linux + env: + CODEGEN_BACKENDS: llvm,cranelift + <<: *job-linux-8c + + - name: dist-android + <<: *job-linux-8c + + - name: dist-arm-linux + <<: *job-linux-16c + + - name: dist-armhf-linux + <<: *job-linux-8c + + - name: dist-armv7-linux + <<: *job-linux-8c + + - name: dist-i586-gnu-i586-i686-musl + <<: *job-linux-8c + + - name: dist-i686-linux + <<: *job-linux-8c + + - name: dist-loongarch64-linux + <<: *job-linux-8c + + - name: dist-ohos + <<: *job-linux-8c + + - name: dist-powerpc-linux + <<: *job-linux-8c + + - name: dist-powerpc64-linux + <<: *job-linux-8c + + - name: dist-powerpc64le-linux + <<: *job-linux-8c + + - name: dist-riscv64-linux + <<: *job-linux-8c + + - name: dist-s390x-linux + <<: *job-linux-8c + + - name: dist-various-1 + <<: *job-linux-8c + + - name: dist-various-2 + <<: *job-linux-8c + + - name: dist-x86_64-freebsd + <<: *job-linux-8c + + - name: dist-x86_64-illumos + <<: *job-linux-8c + + - name: dist-x86_64-linux + env: + CODEGEN_BACKENDS: llvm,cranelift + <<: *job-linux-16c + + - name: dist-x86_64-linux-alt + env: + IMAGE: dist-x86_64-linux + CODEGEN_BACKENDS: llvm,cranelift + <<: *job-linux-16c + + - name: dist-x86_64-musl + env: + CODEGEN_BACKENDS: llvm,cranelift + <<: *job-linux-8c + + - name: dist-x86_64-netbsd + <<: *job-linux-8c + + - name: i686-gnu + <<: *job-linux-8c + + - name: i686-gnu-nopt + <<: *job-linux-8c + + - name: mingw-check + <<: *job-linux-4c + + - name: test-various + <<: *job-linux-8c + + - name: x86_64-gnu + <<: *job-linux-4c + + # This job ensures commits landing on nightly still pass the full + # test suite on the stable channel. There are some UI tests that + # depend on the channel being built (for example if they include the + # channel name on the output), and this builder prevents landing + # changes that would result in broken builds after a promotion. + - name: x86_64-gnu-stable + env: + IMAGE: x86_64-gnu + RUST_CI_OVERRIDE_RELEASE_CHANNEL: stable + # Only run this job on the nightly channel. Running this on beta + # could cause failures when `dev: 1` in `stage0.txt`, and running + # this on stable is useless. + CI_ONLY_WHEN_CHANNEL: nightly + <<: *job-linux-4c + + - name: x86_64-gnu-aux + <<: *job-linux-4c + + - name: x86_64-gnu-integration + env: + # Only run this job on the nightly channel. Fuchsia requires + # nightly features to compile, and this job would fail if + # executed on beta and stable. + CI_ONLY_WHEN_CHANNEL: nightly + <<: *job-linux-8c + + - name: x86_64-gnu-debug + <<: *job-linux-8c + + - name: x86_64-gnu-distcheck + <<: *job-linux-8c + + - name: x86_64-gnu-llvm-18 + env: + RUST_BACKTRACE: 1 + <<: *job-linux-8c + + - name: x86_64-gnu-llvm-17 + env: + RUST_BACKTRACE: 1 + <<: *job-linux-8c + + - name: x86_64-gnu-nopt + <<: *job-linux-4c + + - name: x86_64-gnu-tools + env: + DEPLOY_TOOLSTATES_JSON: toolstates-linux.json + <<: *job-linux-8c + + #################### + # macOS Builders # + #################### + + - name: dist-x86_64-apple + env: + SCRIPT: ./x.py dist bootstrap --include-default-paths --host=x86_64-apple-darwin --target=x86_64-apple-darwin + RUST_CONFIGURE_ARGS: --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set rust.lto=thin --set rust.codegen-units=1 + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.12 + SELECT_XCODE: /Applications/Xcode_14.3.1.app + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + NO_OVERFLOW_CHECKS: 1 + DIST_REQUIRE_ALL_TOOLS: 1 + CODEGEN_BACKENDS: llvm,cranelift + <<: *job-macos-xl + + - name: dist-apple-various + env: + SCRIPT: ./x.py dist bootstrap --include-default-paths --host='' --target=aarch64-apple-ios,x86_64-apple-ios,aarch64-apple-ios-sim + RUST_CONFIGURE_ARGS: --enable-sanitizers --enable-profiler --set rust.jemalloc + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.12 + SELECT_XCODE: /Applications/Xcode_14.3.1.app + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + NO_OVERFLOW_CHECKS: 1 + <<: *job-macos-xl + + - name: x86_64-apple-1 + env: &env-x86_64-apple-tests + SCRIPT: ./x.py --stage 2 test --skip tests/ui --skip tests/rustdoc --skip tests/run-make-fulldeps + RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.12 + MACOSX_STD_DEPLOYMENT_TARGET: 10.12 + SELECT_XCODE: /Applications/Xcode_14.3.1.app + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + NO_OVERFLOW_CHECKS: 1 + <<: *job-macos-xl + + - name: x86_64-apple-2 + env: + SCRIPT: ./x.py --stage 2 test tests/ui tests/rustdoc tests/run-make-fulldeps + <<: *env-x86_64-apple-tests + <<: *job-macos-xl + + # This target only needs to support 11.0 and up as nothing else supports the hardware + - name: dist-aarch64-apple + env: + SCRIPT: ./x.py dist bootstrap --include-default-paths --host=aarch64-apple-darwin --target=aarch64-apple-darwin + RUST_CONFIGURE_ARGS: >- + --enable-full-tools + --enable-sanitizers + --enable-profiler + --set rust.jemalloc + --set llvm.ninja=false + --set rust.lto=thin + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + SELECT_XCODE: /Applications/Xcode_14.3.1.app + USE_XCODE_CLANG: 1 + MACOSX_DEPLOYMENT_TARGET: 11.0 + MACOSX_STD_DEPLOYMENT_TARGET: 11.0 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + NO_OVERFLOW_CHECKS: 1 + DIST_REQUIRE_ALL_TOOLS: 1 + <<: *job-macos-m1 + + # This target only needs to support 11.0 and up as nothing else supports the hardware + - name: aarch64-apple + env: + SCRIPT: ./x.py --stage 2 test --host=aarch64-apple-darwin --target=aarch64-apple-darwin + RUST_CONFIGURE_ARGS: >- + --enable-sanitizers + --enable-profiler + --set rust.jemalloc + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + SELECT_XCODE: /Applications/Xcode_14.3.1.app + USE_XCODE_CLANG: 1 + MACOSX_DEPLOYMENT_TARGET: 11.0 + MACOSX_STD_DEPLOYMENT_TARGET: 11.0 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + NO_OVERFLOW_CHECKS: 1 + <<: *job-macos-m1 + + ###################### + # Windows Builders # + ###################### + + - name: x86_64-msvc + env: + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler + SCRIPT: make ci-msvc + <<: *job-windows-8c + + - name: i686-msvc + env: + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc + SCRIPT: make ci-msvc + <<: *job-windows-8c + + - name: x86_64-msvc-ext + env: + SCRIPT: python x.py --stage 2 test src/tools/cargotest src/tools/cargo && src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstate/toolstates.json windows + HOST_TARGET: x86_64-pc-windows-msvc + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-lld --save-toolstates=/tmp/toolstate/toolstates.json + DEPLOY_TOOLSTATES_JSON: toolstates-windows.json + <<: *job-windows-8c + + # 32/64-bit MinGW builds. + # + # We are using MinGW with POSIX threads since LLVM requires + # C++'s std::thread which is disabled in libstdc++ with win32 threads. + # FIXME: Libc++ doesn't have this limitation so we can avoid + # winpthreads if we switch to it. + # + # Instead of relying on the MinGW version installed on CI we download + # and install one ourselves so we won't be surprised by changes to CI's + # build image. + # + # Finally, note that the downloads below are all in the `rust-lang-ci` S3 + # bucket, but they clearly didn't originate there! The downloads originally + # came from the mingw-w64 SourceForge download site. Unfortunately + # SourceForge is notoriously flaky, so we mirror it on our own infrastructure. + + - name: i686-mingw + env: + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu + SCRIPT: make ci-mingw + # We are intentionally allowing an old toolchain on this builder (and that's + # incompatible with LLVM downloads today). + NO_DOWNLOAD_CI_LLVM: 1 + CUSTOM_MINGW: 1 + <<: *job-windows-8c + + - name: x86_64-mingw + env: + SCRIPT: make ci-mingw + RUST_CONFIGURE_ARGS: >- + --build=x86_64-pc-windows-gnu + --enable-profiler + # We are intentionally allowing an old toolchain on this builder (and that's + # incompatible with LLVM downloads today). + NO_DOWNLOAD_CI_LLVM: 1 + CUSTOM_MINGW: 1 + <<: *job-windows-8c + + - name: dist-x86_64-msvc + env: + RUST_CONFIGURE_ARGS: >- + --build=x86_64-pc-windows-msvc + --host=x86_64-pc-windows-msvc + --target=x86_64-pc-windows-msvc + --enable-full-tools + --enable-profiler + --set rust.codegen-units=1 + SCRIPT: python x.py build --set rust.debug=true opt-dist && PGO_HOST=x86_64-pc-windows-msvc ./build/x86_64-pc-windows-msvc/stage0-tools-bin/opt-dist windows-ci -- python x.py dist bootstrap --include-default-paths + DIST_REQUIRE_ALL_TOOLS: 1 + <<: *job-windows-8c + + - name: dist-i686-msvc + env: + RUST_CONFIGURE_ARGS: >- + --build=i686-pc-windows-msvc + --host=i686-pc-windows-msvc + --target=i686-pc-windows-msvc,i586-pc-windows-msvc + --enable-full-tools + --enable-profiler + SCRIPT: python x.py dist bootstrap --include-default-paths + DIST_REQUIRE_ALL_TOOLS: 1 + <<: *job-windows-8c + + - name: dist-aarch64-msvc + env: + RUST_CONFIGURE_ARGS: >- + --build=x86_64-pc-windows-msvc + --host=aarch64-pc-windows-msvc + --enable-full-tools + --enable-profiler + SCRIPT: python x.py dist bootstrap --include-default-paths + DIST_REQUIRE_ALL_TOOLS: 1 + <<: *job-windows-8c + + - name: dist-i686-mingw + env: + RUST_CONFIGURE_ARGS: >- + --build=i686-pc-windows-gnu + --enable-full-tools + --enable-profiler + # We are intentionally allowing an old toolchain on this builder (and that's + # incompatible with LLVM downloads today). + NO_DOWNLOAD_CI_LLVM: 1 + SCRIPT: python x.py dist bootstrap --include-default-paths + CUSTOM_MINGW: 1 + DIST_REQUIRE_ALL_TOOLS: 1 + <<: *job-windows-8c + + - name: dist-x86_64-mingw + env: + SCRIPT: python x.py dist bootstrap --include-default-paths + RUST_CONFIGURE_ARGS: >- + --build=x86_64-pc-windows-gnu + --enable-full-tools + --enable-profiler + # We are intentionally allowing an old toolchain on this builder (and that's + # incompatible with LLVM downloads today). + NO_DOWNLOAD_CI_LLVM: 1 + CUSTOM_MINGW: 1 + DIST_REQUIRE_ALL_TOOLS: 1 + <<: *job-windows-8c + + - name: dist-x86_64-msvc-alt + env: + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended --enable-profiler + SCRIPT: python x.py dist bootstrap --include-default-paths + <<: *job-windows-8c From 6df27ef88f2ce082c8f3b9db134bfa3c0c28cf38 Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Mon, 22 Apr 2024 23:45:04 -0400 Subject: [PATCH 11/36] also update windows slack-protector tests --- ...otector-heuristics-effect-windows-32bit.rs | 30 +++++-------------- ...otector-heuristics-effect-windows-64bit.rs | 30 +++++-------------- 2 files changed, 16 insertions(+), 44 deletions(-) diff --git a/tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs b/tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs index 12339cb4415c..51b4dc4e1699 100644 --- a/tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs +++ b/tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs @@ -37,23 +37,9 @@ pub fn array_char(f: fn(*const char)) { f(&b as *const _); f(&c as *const _); - // Any type of local array variable leads to stack protection with the - // "strong" heuristic. The 'basic' heuristic only adds stack protection to - // functions with local array variables of a byte-sized type, however. Since - // 'char' is 4 bytes in Rust, this function is not protected by the 'basic' - // heuristic - // - // (This test *also* takes the address of the local stack variables. We - // cannot know that this isn't what triggers the `strong` heuristic. - // However, the test strategy of passing the address of a stack array to an - // external function is sufficient to trigger the `basic` heuristic (see - // test `array_u8_large()`). Since the `basic` heuristic only checks for the - // presence of stack-local array variables, we can be confident that this - // test also captures this part of the `strong` heuristic specification.) - // all: __security_check_cookie // strong: __security_check_cookie - // basic-NOT: __security_check_cookie + // basic: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie } @@ -231,8 +217,8 @@ pub fn local_large_var_moved(f: fn(Gigastruct)) { // Even though the local variable conceptually doesn't have its address // taken, it's so large that the "move" is implemented with a reference to a // stack-local variable in the ABI. Consequently, this function *is* - // protected by the `strong` heuristic. This is also the case for - // rvalue-references in C++, regardless of struct size: + // protected. This is also the case for rvalue-references in C++, + // regardless of struct size: // ``` // cat < @@ -246,7 +232,7 @@ pub fn local_large_var_moved(f: fn(Gigastruct)) { // all: __security_check_cookie // strong: __security_check_cookie - // basic-NOT: __security_check_cookie + // basic: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie } @@ -259,9 +245,9 @@ pub fn local_large_var_cloned(f: fn(Gigastruct)) { // A new instance of `Gigastruct` is passed to `f()`, without any apparent // connection to this stack frame. Still, since instances of `Gigastruct` // are sufficiently large, it is allocated in the caller stack frame and - // passed as a pointer. As such, this function is *also* protected by the - // `strong` heuristic, just like `local_large_var_moved`. This is also the - // case for pass-by-value of sufficiently large structs in C++: + // passed as a pointer. As such, this function is *also* protected, just + // like `local_large_var_moved`. This is also the case for pass-by-value + // of sufficiently large structs in C++: // ``` // cat < @@ -276,7 +262,7 @@ pub fn local_large_var_cloned(f: fn(Gigastruct)) { // all: __security_check_cookie // strong: __security_check_cookie - // basic-NOT: __security_check_cookie + // basic: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie } diff --git a/tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs b/tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs index 46c775112519..c5915262c093 100644 --- a/tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs +++ b/tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs @@ -37,23 +37,9 @@ pub fn array_char(f: fn(*const char)) { f(&b as *const _); f(&c as *const _); - // Any type of local array variable leads to stack protection with the - // "strong" heuristic. The 'basic' heuristic only adds stack protection to - // functions with local array variables of a byte-sized type, however. Since - // 'char' is 4 bytes in Rust, this function is not protected by the 'basic' - // heuristic - // - // (This test *also* takes the address of the local stack variables. We - // cannot know that this isn't what triggers the `strong` heuristic. - // However, the test strategy of passing the address of a stack array to an - // external function is sufficient to trigger the `basic` heuristic (see - // test `array_u8_large()`). Since the `basic` heuristic only checks for the - // presence of stack-local array variables, we can be confident that this - // test also captures this part of the `strong` heuristic specification.) - // all: __security_check_cookie // strong: __security_check_cookie - // basic-NOT: __security_check_cookie + // basic: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie } @@ -239,8 +225,8 @@ pub fn local_large_var_moved(f: fn(Gigastruct)) { // Even though the local variable conceptually doesn't have its address // taken, it's so large that the "move" is implemented with a reference to a // stack-local variable in the ABI. Consequently, this function *is* - // protected by the `strong` heuristic. This is also the case for - // rvalue-references in C++, regardless of struct size: + // protected. This is also the case for rvalue-references in C++, + // regardless of struct size: // ``` // cat < @@ -254,7 +240,7 @@ pub fn local_large_var_moved(f: fn(Gigastruct)) { // all: __security_check_cookie // strong: __security_check_cookie - // basic-NOT: __security_check_cookie + // basic: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie } @@ -267,9 +253,9 @@ pub fn local_large_var_cloned(f: fn(Gigastruct)) { // A new instance of `Gigastruct` is passed to `f()`, without any apparent // connection to this stack frame. Still, since instances of `Gigastruct` // are sufficiently large, it is allocated in the caller stack frame and - // passed as a pointer. As such, this function is *also* protected by the - // `strong` heuristic, just like `local_large_var_moved`. This is also the - // case for pass-by-value of sufficiently large structs in C++: + // passed as a pointer. As such, this function is *also* protected, just + // like `local_large_var_moved`. This is also the case for pass-by-value + // of sufficiently large structs in C++: // ``` // cat < @@ -284,7 +270,7 @@ pub fn local_large_var_cloned(f: fn(Gigastruct)) { // all: __security_check_cookie // strong: __security_check_cookie - // basic-NOT: __security_check_cookie + // basic: __security_check_cookie // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie } From c251abc7ec1425bc36941d22af4600ea5c8ea505 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 23 Apr 2024 08:52:28 +0200 Subject: [PATCH 12/36] Load GitHub context from environment variables --- .github/workflows/ci.yml | 2 -- src/ci/github-actions/calculate-job-matrix.py | 36 ++++++++++++------- src/ci/github-actions/ci.yml | 2 -- 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 010872c980f9..670a2854fed4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -45,8 +45,6 @@ jobs: - name: Checkout the source code uses: actions/checkout@v4 - name: Calculate the CI job matrix - env: - GITHUB_CTX: "${{ toJSON(github) }}" run: python3 src/ci/github-actions/calculate-job-matrix.py >> $GITHUB_OUTPUT id: jobs job: diff --git a/src/ci/github-actions/calculate-job-matrix.py b/src/ci/github-actions/calculate-job-matrix.py index 935b1bb56c37..a844b201c16d 100755 --- a/src/ci/github-actions/calculate-job-matrix.py +++ b/src/ci/github-actions/calculate-job-matrix.py @@ -7,6 +7,7 @@ be executed on CI. It reads job definitions from `src/ci/github-actions/jobs.yml` and filters them based on the event that happened on CI. """ +import dataclasses import enum import json import logging @@ -46,28 +47,31 @@ class JobType(enum.Enum): Auto = enum.auto() -def find_job_type(github_ctx: Dict[str, Any]) -> Optional[JobType]: - event_name = github_ctx["event_name"] - ref = github_ctx["ref"] - repository = github_ctx["repository"] +@dataclasses.dataclass +class GitHubCtx: + event_name: str + ref: str + repository: str - if event_name == "pull_request": + +def find_job_type(ctx: GitHubCtx) -> Optional[JobType]: + if ctx.event_name == "pull_request": return JobType.PR - elif event_name == "push": + elif ctx.event_name == "push": old_bors_try_build = ( - ref in ("refs/heads/try", "refs/heads/try-perf") and - repository == "rust-lang-ci/rust" + ctx.ref in ("refs/heads/try", "refs/heads/try-perf") and + ctx.repository == "rust-lang-ci/rust" ) new_bors_try_build = ( - ref == "refs/heads/automation/bors/try" and - repository == "rust-lang/rust" + ctx.ref == "refs/heads/automation/bors/try" and + ctx.repository == "rust-lang/rust" ) try_build = old_bors_try_build or new_bors_try_build if try_build: return JobType.Try - if ref == "refs/heads/auto" and repository == "rust-lang-ci/rust": + if ctx.ref == "refs/heads/auto" and ctx.repository == "rust-lang-ci/rust": return JobType.Auto return None @@ -84,13 +88,21 @@ def calculate_jobs(job_type: JobType, job_data: Dict[str, Any]) -> List[Dict[str return [] +def get_github_ctx() -> GitHubCtx: + return GitHubCtx( + event_name=os.environ["GITHUB_EVENT_NAME"], + ref=os.environ["GITHUB_REF"], + repository=os.environ["GITHUB_REPOSITORY"] + ) + + if __name__ == "__main__": logging.basicConfig(level=logging.INFO) with open(JOBS_YAML_PATH) as f: data = yaml.safe_load(f) - github_ctx = json.loads(os.environ["GITHUB_CTX"]) + github_ctx = get_github_ctx() job_type = find_job_type(github_ctx) logging.info(f"Job type: {job_type}") diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index 2a271b43a8a5..1efdd7e22e90 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -353,8 +353,6 @@ jobs: - name: Checkout the source code uses: actions/checkout@v4 - name: Calculate the CI job matrix - env: - GITHUB_CTX: ${{ toJSON(github) }} run: python3 src/ci/github-actions/calculate-job-matrix.py >> $GITHUB_OUTPUT id: jobs job: From 2f2d59dd06dfe88878e7873cb87d4bc39fe6b188 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 23 Apr 2024 08:53:07 +0200 Subject: [PATCH 13/36] Fix image field in auto jobs --- src/ci/github-actions/jobs.yml | 112 ++++++++++++++++----------------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index cfa0732cf2d6..a287a4383e37 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -88,103 +88,103 @@ auto: # Linux/Docker builders # ############################# - - name: aarch64-gnu + - image: aarch64-gnu <<: *job-aarch64-linux - - name: arm-android + - image: arm-android <<: *job-linux-8c - - name: armhf-gnu + - image: armhf-gnu <<: *job-linux-8c - - name: dist-aarch64-linux + - image: dist-aarch64-linux env: CODEGEN_BACKENDS: llvm,cranelift <<: *job-linux-8c - - name: dist-android + - image: dist-android <<: *job-linux-8c - - name: dist-arm-linux + - image: dist-arm-linux <<: *job-linux-16c - - name: dist-armhf-linux + - image: dist-armhf-linux <<: *job-linux-8c - - name: dist-armv7-linux + - image: dist-armv7-linux <<: *job-linux-8c - - name: dist-i586-gnu-i586-i686-musl + - image: dist-i586-gnu-i586-i686-musl <<: *job-linux-8c - - name: dist-i686-linux + - image: dist-i686-linux <<: *job-linux-8c - - name: dist-loongarch64-linux + - image: dist-loongarch64-linux <<: *job-linux-8c - - name: dist-ohos + - image: dist-ohos <<: *job-linux-8c - - name: dist-powerpc-linux + - image: dist-powerpc-linux <<: *job-linux-8c - - name: dist-powerpc64-linux + - image: dist-powerpc64-linux <<: *job-linux-8c - - name: dist-powerpc64le-linux + - image: dist-powerpc64le-linux <<: *job-linux-8c - - name: dist-riscv64-linux + - image: dist-riscv64-linux <<: *job-linux-8c - - name: dist-s390x-linux + - image: dist-s390x-linux <<: *job-linux-8c - - name: dist-various-1 + - image: dist-various-1 <<: *job-linux-8c - - name: dist-various-2 + - image: dist-various-2 <<: *job-linux-8c - - name: dist-x86_64-freebsd + - image: dist-x86_64-freebsd <<: *job-linux-8c - - name: dist-x86_64-illumos + - image: dist-x86_64-illumos <<: *job-linux-8c - - name: dist-x86_64-linux + - image: dist-x86_64-linux env: CODEGEN_BACKENDS: llvm,cranelift <<: *job-linux-16c - - name: dist-x86_64-linux-alt + - image: dist-x86_64-linux-alt env: IMAGE: dist-x86_64-linux CODEGEN_BACKENDS: llvm,cranelift <<: *job-linux-16c - - name: dist-x86_64-musl + - image: dist-x86_64-musl env: CODEGEN_BACKENDS: llvm,cranelift <<: *job-linux-8c - - name: dist-x86_64-netbsd + - image: dist-x86_64-netbsd <<: *job-linux-8c - - name: i686-gnu + - image: i686-gnu <<: *job-linux-8c - - name: i686-gnu-nopt + - image: i686-gnu-nopt <<: *job-linux-8c - - name: mingw-check + - image: mingw-check <<: *job-linux-4c - - name: test-various + - image: test-various <<: *job-linux-8c - - name: x86_64-gnu + - image: x86_64-gnu <<: *job-linux-4c # This job ensures commits landing on nightly still pass the full @@ -192,7 +192,7 @@ auto: # depend on the channel being built (for example if they include the # channel name on the output), and this builder prevents landing # changes that would result in broken builds after a promotion. - - name: x86_64-gnu-stable + - image: x86_64-gnu-stable env: IMAGE: x86_64-gnu RUST_CI_OVERRIDE_RELEASE_CHANNEL: stable @@ -202,10 +202,10 @@ auto: CI_ONLY_WHEN_CHANNEL: nightly <<: *job-linux-4c - - name: x86_64-gnu-aux + - image: x86_64-gnu-aux <<: *job-linux-4c - - name: x86_64-gnu-integration + - image: x86_64-gnu-integration env: # Only run this job on the nightly channel. Fuchsia requires # nightly features to compile, and this job would fail if @@ -213,26 +213,26 @@ auto: CI_ONLY_WHEN_CHANNEL: nightly <<: *job-linux-8c - - name: x86_64-gnu-debug + - image: x86_64-gnu-debug <<: *job-linux-8c - - name: x86_64-gnu-distcheck + - image: x86_64-gnu-distcheck <<: *job-linux-8c - - name: x86_64-gnu-llvm-18 + - image: x86_64-gnu-llvm-18 env: RUST_BACKTRACE: 1 <<: *job-linux-8c - - name: x86_64-gnu-llvm-17 + - image: x86_64-gnu-llvm-17 env: RUST_BACKTRACE: 1 <<: *job-linux-8c - - name: x86_64-gnu-nopt + - image: x86_64-gnu-nopt <<: *job-linux-4c - - name: x86_64-gnu-tools + - image: x86_64-gnu-tools env: DEPLOY_TOOLSTATES_JSON: toolstates-linux.json <<: *job-linux-8c @@ -241,7 +241,7 @@ auto: # macOS Builders # #################### - - name: dist-x86_64-apple + - image: dist-x86_64-apple env: SCRIPT: ./x.py dist bootstrap --include-default-paths --host=x86_64-apple-darwin --target=x86_64-apple-darwin RUST_CONFIGURE_ARGS: --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set rust.lto=thin --set rust.codegen-units=1 @@ -255,7 +255,7 @@ auto: CODEGEN_BACKENDS: llvm,cranelift <<: *job-macos-xl - - name: dist-apple-various + - image: dist-apple-various env: SCRIPT: ./x.py dist bootstrap --include-default-paths --host='' --target=aarch64-apple-ios,x86_64-apple-ios,aarch64-apple-ios-sim RUST_CONFIGURE_ARGS: --enable-sanitizers --enable-profiler --set rust.jemalloc @@ -267,7 +267,7 @@ auto: NO_OVERFLOW_CHECKS: 1 <<: *job-macos-xl - - name: x86_64-apple-1 + - image: x86_64-apple-1 env: &env-x86_64-apple-tests SCRIPT: ./x.py --stage 2 test --skip tests/ui --skip tests/rustdoc --skip tests/run-make-fulldeps RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc @@ -280,14 +280,14 @@ auto: NO_OVERFLOW_CHECKS: 1 <<: *job-macos-xl - - name: x86_64-apple-2 + - image: x86_64-apple-2 env: SCRIPT: ./x.py --stage 2 test tests/ui tests/rustdoc tests/run-make-fulldeps <<: *env-x86_64-apple-tests <<: *job-macos-xl # This target only needs to support 11.0 and up as nothing else supports the hardware - - name: dist-aarch64-apple + - image: dist-aarch64-apple env: SCRIPT: ./x.py dist bootstrap --include-default-paths --host=aarch64-apple-darwin --target=aarch64-apple-darwin RUST_CONFIGURE_ARGS: >- @@ -309,7 +309,7 @@ auto: <<: *job-macos-m1 # This target only needs to support 11.0 and up as nothing else supports the hardware - - name: aarch64-apple + - image: aarch64-apple env: SCRIPT: ./x.py --stage 2 test --host=aarch64-apple-darwin --target=aarch64-apple-darwin RUST_CONFIGURE_ARGS: >- @@ -330,19 +330,19 @@ auto: # Windows Builders # ###################### - - name: x86_64-msvc + - image: x86_64-msvc env: RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler SCRIPT: make ci-msvc <<: *job-windows-8c - - name: i686-msvc + - image: i686-msvc env: RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc SCRIPT: make ci-msvc <<: *job-windows-8c - - name: x86_64-msvc-ext + - image: x86_64-msvc-ext env: SCRIPT: python x.py --stage 2 test src/tools/cargotest src/tools/cargo && src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstate/toolstates.json windows HOST_TARGET: x86_64-pc-windows-msvc @@ -366,7 +366,7 @@ auto: # came from the mingw-w64 SourceForge download site. Unfortunately # SourceForge is notoriously flaky, so we mirror it on our own infrastructure. - - name: i686-mingw + - image: i686-mingw env: RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu SCRIPT: make ci-mingw @@ -376,7 +376,7 @@ auto: CUSTOM_MINGW: 1 <<: *job-windows-8c - - name: x86_64-mingw + - image: x86_64-mingw env: SCRIPT: make ci-mingw RUST_CONFIGURE_ARGS: >- @@ -388,7 +388,7 @@ auto: CUSTOM_MINGW: 1 <<: *job-windows-8c - - name: dist-x86_64-msvc + - image: dist-x86_64-msvc env: RUST_CONFIGURE_ARGS: >- --build=x86_64-pc-windows-msvc @@ -401,7 +401,7 @@ auto: DIST_REQUIRE_ALL_TOOLS: 1 <<: *job-windows-8c - - name: dist-i686-msvc + - image: dist-i686-msvc env: RUST_CONFIGURE_ARGS: >- --build=i686-pc-windows-msvc @@ -413,7 +413,7 @@ auto: DIST_REQUIRE_ALL_TOOLS: 1 <<: *job-windows-8c - - name: dist-aarch64-msvc + - image: dist-aarch64-msvc env: RUST_CONFIGURE_ARGS: >- --build=x86_64-pc-windows-msvc @@ -424,7 +424,7 @@ auto: DIST_REQUIRE_ALL_TOOLS: 1 <<: *job-windows-8c - - name: dist-i686-mingw + - image: dist-i686-mingw env: RUST_CONFIGURE_ARGS: >- --build=i686-pc-windows-gnu @@ -438,7 +438,7 @@ auto: DIST_REQUIRE_ALL_TOOLS: 1 <<: *job-windows-8c - - name: dist-x86_64-mingw + - image: dist-x86_64-mingw env: SCRIPT: python x.py dist bootstrap --include-default-paths RUST_CONFIGURE_ARGS: >- @@ -452,7 +452,7 @@ auto: DIST_REQUIRE_ALL_TOOLS: 1 <<: *job-windows-8c - - name: dist-x86_64-msvc-alt + - image: dist-x86_64-msvc-alt env: RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended --enable-profiler SCRIPT: python x.py dist bootstrap --include-default-paths From 162892b030b95aa8ad422212a82457d940b15a4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 23 Apr 2024 08:55:35 +0200 Subject: [PATCH 14/36] Make separate envs for try and auto builds --- src/ci/github-actions/calculate-job-matrix.py | 4 ++-- src/ci/github-actions/jobs.yml | 9 ++++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/ci/github-actions/calculate-job-matrix.py b/src/ci/github-actions/calculate-job-matrix.py index a844b201c16d..c24cefa8d896 100755 --- a/src/ci/github-actions/calculate-job-matrix.py +++ b/src/ci/github-actions/calculate-job-matrix.py @@ -81,9 +81,9 @@ def calculate_jobs(job_type: JobType, job_data: Dict[str, Any]) -> List[Dict[str if job_type == JobType.PR: return add_base_env(name_jobs(job_data["pr"], "PR"), job_data["envs"]["pr"]) elif job_type == JobType.Try: - return add_base_env(name_jobs(job_data["try"], "try"), job_data["envs"]["production"]) + return add_base_env(name_jobs(job_data["try"], "try"), job_data["envs"]["try"]) elif job_type == JobType.Auto: - return add_base_env(name_jobs(job_data["auto"], "auto"), job_data["envs"]["production"]) + return add_base_env(name_jobs(job_data["auto"], "auto"), job_data["envs"]["auto"]) return [] diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index a287a4383e37..ec58bd0924e8 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -39,6 +39,7 @@ runners: envs: production: + &production DEPLOY_BUCKET: rust-lang-ci2 TOOLSTATE_ISSUES_API_URL: https://api.github.com/repos/rust-lang/rust/issues TOOLSTATE_PUBLISH: 1 @@ -51,6 +52,13 @@ envs: ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZN24CBO55 AWS_REGION: us-west-1 + try: + <<: *production + DIST_TRY_BUILD: 1 + + auto: + <<: *production + pr: PR_CI_JOB: 1 @@ -76,7 +84,6 @@ pr: try: - image: dist-x86_64-linux env: - DIST_TRY_BUILD: 1 CODEGEN_BACKENDS: llvm,cranelift <<: *job-linux-16c From 2632c6139d9b1a7ca7be4da1924e7a78edfa452c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 23 Apr 2024 08:59:45 +0200 Subject: [PATCH 15/36] Fix empty job matrix --- .github/workflows/ci.yml | 1 + src/ci/github-actions/ci.yml | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 670a2854fed4..872b671b031e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -63,6 +63,7 @@ jobs: strategy: matrix: include: "${{ fromJSON(needs.calculate_matrix.outputs.jobs) }}" + if: "fromJSON(needs.calculate_matrix.outputs.jobs)[0] != null" defaults: run: shell: "${{ contains(matrix.os, 'windows') && 'msys2 {0}' || 'bash' }}" diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index 1efdd7e22e90..19d6b517552f 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -373,6 +373,14 @@ jobs: matrix: # Check the `calculate_matrix` job to see how is the matrix defined. include: ${{ fromJSON(needs.calculate_matrix.outputs.jobs) }} + # GitHub Actions fails the workflow if an empty list of jobs is provided to + # the workflow, so we need to skip this job if nothing was produced by + # the Python script. + # + # Unfortunately checking whether a list is empty is not possible in a nice + # way due to GitHub Actions expressions limits. + # This hack is taken from https://github.com/ferrocene/ferrocene/blob/d43edc6b7697cf1719ec1c17c54904ab94825763/.github/workflows/release.yml#L75-L82 + if: fromJSON(needs.calculate_matrix.outputs.jobs)[0] != null master: name: master From a21c2d870470b07d559faeaf88e7d16c765fc6ef Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 23 Apr 2024 09:32:35 +0200 Subject: [PATCH 16/36] windows fill_utf16_buf: explain the expected return value --- library/std/src/sys/pal/windows/mod.rs | 17 ++++++++++++----- library/std/src/sys/pal/windows/os.rs | 2 ++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs index b49585599cb3..ff41f6e77be7 100644 --- a/library/std/src/sys/pal/windows/mod.rs +++ b/library/std/src/sys/pal/windows/mod.rs @@ -201,14 +201,21 @@ pub fn to_u16s>(s: S) -> crate::io::Result> { // currently reside in the buffer. This function is an abstraction over these // functions by making them easier to call. // -// The first callback, `f1`, is yielded a (pointer, len) pair which can be +// The first callback, `f1`, is passed a (pointer, len) pair which can be // passed to a syscall. The `ptr` is valid for `len` items (u16 in this case). -// The closure is expected to return what the syscall returns which will be -// interpreted by this function to determine if the syscall needs to be invoked -// again (with more buffer space). +// The closure is expected to: +// - On success, return the actual length of the written data *without* the null terminator. +// This can be 0. In this case the last_error must be left unchanged. +// - On insufficient buffer space, +// - either return the required length *with* the null terminator, +// - or set the last-error to ERROR_INSUFFICIENT_BUFFER and return `len`. +// - On other failure, return 0 and set last_error. +// +// This is how most but not all syscalls indicate the required buffer space. +// Other syscalls may need translation to match this protocol. // // Once the syscall has completed (errors bail out early) the second closure is -// yielded the data which has been read from the syscall. The return value +// passed the data which has been read from the syscall. The return value // from this closure is then the return value of the function. pub fn fill_utf16_buf(mut f1: F1, f2: F2) -> crate::io::Result where diff --git a/library/std/src/sys/pal/windows/os.rs b/library/std/src/sys/pal/windows/os.rs index 374c9845ea4b..64d8b72aed28 100644 --- a/library/std/src/sys/pal/windows/os.rs +++ b/library/std/src/sys/pal/windows/os.rs @@ -326,6 +326,8 @@ fn home_dir_crt() -> Option { super::fill_utf16_buf( |buf, mut sz| { + // GetUserProfileDirectoryW does not quite use the usual protocol for + // negotiating the buffer size, so we have to translate. match c::GetUserProfileDirectoryW( ptr::without_provenance_mut(CURRENT_PROCESS_TOKEN), buf, From d5d714bb34d1c257a6328bde8614d1a9f5e1914d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 23 Apr 2024 08:22:29 +0200 Subject: [PATCH 17/36] fix weak memory bug in TLS on Windows --- .../src/sys/pal/windows/thread_local_key.rs | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/library/std/src/sys/pal/windows/thread_local_key.rs b/library/std/src/sys/pal/windows/thread_local_key.rs index 4c00860dae38..e5ba619fc6ba 100644 --- a/library/std/src/sys/pal/windows/thread_local_key.rs +++ b/library/std/src/sys/pal/windows/thread_local_key.rs @@ -141,9 +141,15 @@ impl StaticKey { panic!("out of TLS indexes"); } - self.key.store(key + 1, Release); register_dtor(self); + // Release-storing the key needs to be the last thing we do. + // This is because in `fn key()`, other threads will do an acquire load of the key, + // and if that sees this write then it will entirely bypass the `InitOnce`. We thus + // need to establish synchronization through `key`. In particular that acquire load + // must happen-after the register_dtor above, to ensure the dtor actually runs! + self.key.store(key + 1, Release); + let r = c::InitOnceComplete(self.once.get(), 0, ptr::null_mut()); debug_assert_eq!(r, c::TRUE); @@ -313,8 +319,22 @@ unsafe fn run_dtors() { // Use acquire ordering to observe key initialization. let mut cur = DTORS.load(Acquire); while !cur.is_null() { - let key = (*cur).key.load(Relaxed) - 1; + let pre_key = (*cur).key.load(Acquire); let dtor = (*cur).dtor.unwrap(); + cur = (*cur).next.load(Relaxed); + + // In StaticKey::init, we register the dtor before setting `key`. + // So if one thread's `run_dtors` races with another thread executing `init` on the same + // `StaticKey`, we can encounter a key of 0 here. That means this key was never + // initialized in this thread so we can safely skip it. + if pre_key == 0 { + continue; + } + // If this is non-zero, then via the `Acquire` load above we synchronized with + // everything relevant for this key. (It's not clear that this is needed, since the + // release-acquire pair on DTORS also establishes synchronization, but better safe than + // sorry.) + let key = pre_key - 1; let ptr = c::TlsGetValue(key); if !ptr.is_null() { @@ -322,8 +342,6 @@ unsafe fn run_dtors() { dtor(ptr as *mut _); any_run = true; } - - cur = (*cur).next.load(Relaxed); } if !any_run { From 99b635eafa372d3b8522e978262095f60a8b4e56 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 14 Mar 2024 11:41:38 +0300 Subject: [PATCH 18/36] delegation: Support renaming --- compiler/rustc_ast/src/ast.rs | 1 + compiler/rustc_ast/src/mut_visit.rs | 10 ++++++++-- compiler/rustc_ast/src/visit.rs | 6 ++++-- compiler/rustc_parse/src/parser/item.rs | 10 +++++----- tests/ui/delegation/rename.rs | 20 ++++++++++++++++++++ 5 files changed, 38 insertions(+), 9 deletions(-) create mode 100644 tests/ui/delegation/rename.rs diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index bddb50568d41..727c6bc82fef 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -3112,6 +3112,7 @@ pub struct Delegation { /// Path resolution id. pub id: NodeId, pub qself: Option>, + pub rename: Option, pub path: Path, pub body: Option>, } diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index c4e49d7dbea4..7dbfb7c73645 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1149,10 +1149,13 @@ pub fn noop_visit_item_kind(kind: &mut ItemKind, vis: &mut T) { } ItemKind::MacCall(m) => vis.visit_mac_call(m), ItemKind::MacroDef(def) => vis.visit_macro_def(def), - ItemKind::Delegation(box Delegation { id, qself, path, body }) => { + ItemKind::Delegation(box Delegation { id, qself, path, rename, body }) => { vis.visit_id(id); vis.visit_qself(qself); vis.visit_path(path); + if let Some(rename) = rename { + vis.visit_ident(rename); + } if let Some(body) = body { vis.visit_block(body); } @@ -1195,10 +1198,13 @@ pub fn noop_flat_map_assoc_item( visit_opt(ty, |ty| visitor.visit_ty(ty)); } AssocItemKind::MacCall(mac) => visitor.visit_mac_call(mac), - AssocItemKind::Delegation(box Delegation { id, qself, path, body }) => { + AssocItemKind::Delegation(box Delegation { id, qself, path, rename, body }) => { visitor.visit_id(id); visitor.visit_qself(qself); visitor.visit_path(path); + if let Some(rename) = rename { + visitor.visit_ident(rename); + } if let Some(body) = body { visitor.visit_block(body); } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 968d10ad4872..d9740928f8d6 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -382,11 +382,12 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) -> V::Resu } ItemKind::MacCall(mac) => try_visit!(visitor.visit_mac_call(mac)), ItemKind::MacroDef(ts) => try_visit!(visitor.visit_mac_def(ts, item.id)), - ItemKind::Delegation(box Delegation { id, qself, path, body }) => { + ItemKind::Delegation(box Delegation { id, qself, path, rename, body }) => { if let Some(qself) = qself { try_visit!(visitor.visit_ty(&qself.ty)); } try_visit!(visitor.visit_path(path, *id)); + visit_opt!(visitor, visit_ident, *rename); visit_opt!(visitor, visit_block, body); } } @@ -782,11 +783,12 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>( AssocItemKind::MacCall(mac) => { try_visit!(visitor.visit_mac_call(mac)); } - AssocItemKind::Delegation(box Delegation { id, qself, path, body }) => { + AssocItemKind::Delegation(box Delegation { id, qself, path, rename, body }) => { if let Some(qself) = qself { try_visit!(visitor.visit_ty(&qself.ty)); } try_visit!(visitor.visit_path(path, *id)); + visit_opt!(visitor, visit_ident, *rename); visit_opt!(visitor, visit_block, body); } } diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 84ecd0a0de54..ed51710564a4 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -686,6 +686,8 @@ impl<'a> Parser<'a> { (None, self.parse_path(PathStyle::Expr)?) }; + let rename = if self.eat_keyword(kw::As) { Some(self.parse_ident()?) } else { None }; + let body = if self.check(&token::OpenDelim(Delimiter::Brace)) { Some(self.parse_block()?) } else { @@ -695,11 +697,9 @@ impl<'a> Parser<'a> { let span = span.to(self.prev_token.span); self.psess.gated_spans.gate(sym::fn_delegation, span); - let ident = path.segments.last().map(|seg| seg.ident).unwrap_or(Ident::empty()); - Ok(( - ident, - ItemKind::Delegation(Box::new(Delegation { id: DUMMY_NODE_ID, qself, path, body })), - )) + let ident = rename.unwrap_or_else(|| path.segments.last().unwrap().ident); + let deleg = Delegation { id: DUMMY_NODE_ID, qself, path, rename, body }; + Ok((ident, ItemKind::Delegation(Box::new(deleg)))) } fn parse_item_list( diff --git a/tests/ui/delegation/rename.rs b/tests/ui/delegation/rename.rs new file mode 100644 index 000000000000..f4b3da76c56c --- /dev/null +++ b/tests/ui/delegation/rename.rs @@ -0,0 +1,20 @@ +//@ check-pass + +#![feature(fn_delegation)] +#![allow(incomplete_features)] + +mod to_reuse { + pub fn a() {} +} + +reuse to_reuse::a as b; + +struct S; +impl S { + reuse to_reuse::a as b; +} + +fn main() { + b(); + S::b(); +} From 7b7c26f09bbc292da8600e8dfaa454de63ada886 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 14 Mar 2024 15:42:14 +0300 Subject: [PATCH 19/36] delegation: Support async, const, extern "ABI" and C-variadic functions Also allow `impl Trait` in delegated functions. The delegation item will refer to the original opaque type from the callee, fresh opaque type won't be created. --- compiler/rustc_ast_lowering/src/delegation.rs | 117 ++++++++++++------ compiler/rustc_ast_lowering/src/item.rs | 2 +- .../src/hir_ty_lowering/mod.rs | 28 ----- compiler/rustc_middle/src/ty/mod.rs | 13 +- compiler/rustc_resolve/src/late.rs | 14 ++- .../rustc_resolve/src/late/diagnostics.rs | 7 +- compiler/rustc_resolve/src/lib.rs | 16 +-- .../ui/delegation/auxiliary/fn-header-aux.rs | 9 ++ tests/ui/delegation/fn-header.rs | 57 +++++++++ tests/ui/delegation/impl-trait.rs | 27 ++++ tests/ui/delegation/not-supported.rs | 30 ++--- tests/ui/delegation/not-supported.stderr | 75 +++++------ 12 files changed, 244 insertions(+), 151 deletions(-) create mode 100644 tests/ui/delegation/auxiliary/fn-header-aux.rs create mode 100644 tests/ui/delegation/fn-header.rs create mode 100644 tests/ui/delegation/impl-trait.rs diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs index f4d5e71badeb..a1e5c275c189 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -49,7 +49,7 @@ use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_middle::span_bug; -use rustc_middle::ty::ResolverAstLowering; +use rustc_middle::ty::{Asyncness, ResolverAstLowering}; use rustc_span::{symbol::Ident, Span}; use rustc_target::spec::abi; use std::iter; @@ -67,7 +67,7 @@ impl<'hir> LoweringContext<'_, 'hir> { return false; }; if let Some(local_sig_id) = sig_id.as_local() { - self.resolver.has_self.contains(&local_sig_id) + self.resolver.delegation_fn_sigs[&local_sig_id].has_self } else { match self.tcx.def_kind(sig_id) { DefKind::Fn => false, @@ -82,13 +82,14 @@ impl<'hir> LoweringContext<'_, 'hir> { delegation: &Delegation, item_id: NodeId, ) -> DelegationResults<'hir> { - let span = delegation.path.segments.last().unwrap().ident.span; + let span = self.lower_span(delegation.path.segments.last().unwrap().ident.span); let sig_id = self.get_delegation_sig_id(item_id, delegation.id, span); match sig_id { Ok(sig_id) => { - let decl = self.lower_delegation_decl(sig_id, span); - let sig = self.lower_delegation_sig(span, decl); - let body_id = self.lower_delegation_body(sig.decl, delegation); + let (param_count, c_variadic) = self.param_count(sig_id); + let decl = self.lower_delegation_decl(sig_id, param_count, c_variadic, span); + let sig = self.lower_delegation_sig(sig_id, decl, span); + let body_id = self.lower_delegation_body(delegation, param_count, span); let generics = self.lower_delegation_generics(span); DelegationResults { body_id, sig, generics } @@ -123,34 +124,47 @@ impl<'hir> LoweringContext<'_, 'hir> { }) } + // Function parameter count, including C variadic `...` if present. + fn param_count(&self, sig_id: DefId) -> (usize, bool /*c_variadic*/) { + if let Some(local_sig_id) = sig_id.as_local() { + // Map may be filled incorrectly due to recursive delegation. + // Error will be emmited later during HIR ty lowering. + match self.resolver.delegation_fn_sigs.get(&local_sig_id) { + Some(sig) => (sig.param_count, sig.c_variadic), + None => (0, false), + } + } else { + let sig = self.tcx.fn_sig(sig_id).skip_binder().skip_binder(); + (sig.inputs().len() + usize::from(sig.c_variadic), sig.c_variadic) + } + } + fn lower_delegation_decl( &mut self, sig_id: DefId, - param_span: Span, + param_count: usize, + c_variadic: bool, + span: Span, ) -> &'hir hir::FnDecl<'hir> { - let args_count = if let Some(local_sig_id) = sig_id.as_local() { - // Map may be filled incorrectly due to recursive delegation. - // Error will be emitted later during HIR ty lowering. - self.resolver.fn_parameter_counts.get(&local_sig_id).cloned().unwrap_or_default() - } else { - self.tcx.fn_arg_names(sig_id).len() - }; - let inputs = self.arena.alloc_from_iter((0..args_count).map(|arg| hir::Ty { + // The last parameter in C variadic functions is skipped in the signature, + // like during regular lowering. + let decl_param_count = param_count - c_variadic as usize; + let inputs = self.arena.alloc_from_iter((0..decl_param_count).map(|arg| hir::Ty { hir_id: self.next_id(), kind: hir::TyKind::InferDelegation(sig_id, hir::InferDelegationKind::Input(arg)), - span: self.lower_span(param_span), + span, })); let output = self.arena.alloc(hir::Ty { hir_id: self.next_id(), kind: hir::TyKind::InferDelegation(sig_id, hir::InferDelegationKind::Output), - span: self.lower_span(param_span), + span, }); self.arena.alloc(hir::FnDecl { inputs, output: hir::FnRetTy::Return(output), - c_variadic: false, + c_variadic, lifetime_elision_allowed: true, implicit_self: hir::ImplicitSelfKind::None, }) @@ -158,35 +172,45 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_delegation_sig( &mut self, - span: Span, + sig_id: DefId, decl: &'hir hir::FnDecl<'hir>, + span: Span, ) -> hir::FnSig<'hir> { - hir::FnSig { - decl, - header: hir::FnHeader { - unsafety: hir::Unsafety::Normal, - constness: hir::Constness::NotConst, - asyncness: hir::IsAsync::NotAsync, - abi: abi::Abi::Rust, - }, - span: self.lower_span(span), - } + let header = if let Some(local_sig_id) = sig_id.as_local() { + match self.resolver.delegation_fn_sigs.get(&local_sig_id) { + Some(sig) => self.lower_fn_header(sig.header), + None => self.generate_header_error(), + } + } else { + let sig = self.tcx.fn_sig(sig_id).skip_binder().skip_binder(); + let asyncness = match self.tcx.asyncness(sig_id) { + Asyncness::Yes => hir::IsAsync::Async(span), + Asyncness::No => hir::IsAsync::NotAsync, + }; + hir::FnHeader { + unsafety: sig.unsafety, + constness: self.tcx.constness(sig_id), + asyncness, + abi: sig.abi, + } + }; + hir::FnSig { decl, header, span } } - fn generate_param(&mut self, ty: &'hir hir::Ty<'hir>) -> (hir::Param<'hir>, NodeId) { + fn generate_param(&mut self, span: Span) -> (hir::Param<'hir>, NodeId) { let pat_node_id = self.next_node_id(); let pat_id = self.lower_node_id(pat_node_id); let pat = self.arena.alloc(hir::Pat { hir_id: pat_id, kind: hir::PatKind::Binding(hir::BindingMode::NONE, pat_id, Ident::empty(), None), - span: ty.span, + span, default_binding_modes: false, }); - (hir::Param { hir_id: self.next_id(), pat, ty_span: ty.span, span: ty.span }, pat_node_id) + (hir::Param { hir_id: self.next_id(), pat, ty_span: span, span }, pat_node_id) } - fn generate_arg(&mut self, ty: &'hir hir::Ty<'hir>, param_id: HirId) -> hir::Expr<'hir> { + fn generate_arg(&mut self, param_id: HirId, span: Span) -> hir::Expr<'hir> { let segments = self.arena.alloc_from_iter(iter::once(hir::PathSegment { ident: Ident::empty(), hir_id: self.next_id(), @@ -195,20 +219,20 @@ impl<'hir> LoweringContext<'_, 'hir> { infer_args: false, })); - let path = - self.arena.alloc(hir::Path { span: ty.span, res: Res::Local(param_id), segments }); + let path = self.arena.alloc(hir::Path { span, res: Res::Local(param_id), segments }); hir::Expr { hir_id: self.next_id(), kind: hir::ExprKind::Path(hir::QPath::Resolved(None, path)), - span: ty.span, + span, } } fn lower_delegation_body( &mut self, - decl: &'hir hir::FnDecl<'hir>, delegation: &Delegation, + param_count: usize, + span: Span, ) -> BodyId { let path = self.lower_qpath( delegation.id, @@ -224,8 +248,8 @@ impl<'hir> LoweringContext<'_, 'hir> { let mut parameters: Vec> = Vec::new(); let mut args: Vec> = Vec::new(); - for (idx, param_ty) in decl.inputs.iter().enumerate() { - let (param, pat_node_id) = this.generate_param(param_ty); + for idx in 0..param_count { + let (param, pat_node_id) = this.generate_param(span); parameters.push(param); let arg = if let Some(block) = block @@ -245,7 +269,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } } else { let pat_hir_id = this.lower_node_id(pat_node_id); - this.generate_arg(param_ty, pat_hir_id) + this.generate_arg(pat_hir_id, span) }; args.push(arg); } @@ -304,7 +328,9 @@ impl<'hir> LoweringContext<'_, 'hir> { implicit_self: hir::ImplicitSelfKind::None, }); - let sig = self.lower_delegation_sig(span, decl); + let header = self.generate_header_error(); + let sig = hir::FnSig { decl, header, span }; + let body_id = self.lower_body(|this| { let expr = hir::Expr { hir_id: this.next_id(), kind: hir::ExprKind::Err(err), span: span }; @@ -312,6 +338,15 @@ impl<'hir> LoweringContext<'_, 'hir> { }); DelegationResults { generics, body_id, sig } } + + fn generate_header_error(&self) -> hir::FnHeader { + hir::FnHeader { + unsafety: hir::Unsafety::Normal, + constness: hir::Constness::NotConst, + asyncness: hir::IsAsync::NotAsync, + abi: abi::Abi::Rust, + } + } } struct SelfResolver<'a> { diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index e4c633aa324a..1a1c50018ac5 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1344,7 +1344,7 @@ impl<'hir> LoweringContext<'_, 'hir> { (generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) }) } - fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader { + pub(super) fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader { let asyncness = if let Some(CoroutineKind::Async { span, .. }) = h.coroutine_kind { hir::IsAsync::Async(span) } else { diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 4a0df6cf7b86..63da27246a2a 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -1964,11 +1964,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { try_emit("recursive delegation"); } - let sig = self.tcx().fn_sig(sig_id).instantiate_identity(); - if sig.output().has_opaque_types() { - try_emit("delegation to a function with opaque type"); - } - let sig_generics = self.tcx().generics_of(sig_id); let parent = self.tcx().parent(self.item_def_id()); let parent_generics = self.tcx().generics_of(parent); @@ -1991,29 +1986,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { try_emit("delegation to a trait method from a free function"); } - if self.tcx().asyncness(sig_id) == ty::Asyncness::Yes { - try_emit("delegation to async functions"); - } - - if self.tcx().constness(sig_id) == hir::Constness::Const { - try_emit("delegation to const functions"); - } - - if sig.c_variadic() { - try_emit("delegation to variadic functions"); - // variadic functions are also `unsafe` and `extern "C"`. - // Do not emit same error multiple times. - return error_occured; - } - - if let hir::Unsafety::Unsafe = sig.unsafety() { - try_emit("delegation to unsafe functions"); - } - - if abi::Abi::Rust != sig.abi() { - try_emit("delegation to non Rust ABI functions"); - } - error_occured } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index cc026e349d74..cda332aee564 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -45,7 +45,7 @@ use rustc_data_structures::unord::UnordMap; use rustc_errors::{Diag, ErrorGuaranteed, StashKey}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res}; -use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap, LocalDefIdSet}; +use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap}; use rustc_index::IndexVec; use rustc_macros::HashStable; use rustc_query_system::ich::StableHashingContext; @@ -224,8 +224,15 @@ pub struct ResolverAstLowering { pub lint_buffer: Steal, /// Information about functions signatures for delegation items expansion - pub has_self: LocalDefIdSet, - pub fn_parameter_counts: LocalDefIdMap, + pub delegation_fn_sigs: LocalDefIdMap, +} + +#[derive(Debug)] +pub struct DelegationFnSig { + pub header: ast::FnHeader, + pub param_count: usize, + pub has_self: bool, + pub c_variadic: bool, } #[derive(Clone, Copy, Debug)] diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index c877ae5e21f4..292af43b602e 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -21,6 +21,7 @@ use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, Par use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::{MissingLifetimeKind, PrimTy, TraitCandidate}; use rustc_middle::middle::resolve_bound_vars::Set1; +use rustc_middle::ty::DelegationFnSig; use rustc_middle::{bug, span_bug}; use rustc_session::config::{CrateType, ResolveDocLinks}; use rustc_session::lint; @@ -4749,12 +4750,13 @@ struct ItemInfoCollector<'a, 'b, 'tcx> { impl ItemInfoCollector<'_, '_, '_> { fn collect_fn_info(&mut self, sig: &FnSig, id: NodeId) { - let def_id = self.r.local_def_id(id); - self.r.fn_parameter_counts.insert(def_id, sig.decl.inputs.len()); - - if sig.decl.has_self() { - self.r.has_self.insert(def_id); - } + let sig = DelegationFnSig { + header: sig.header, + param_count: sig.decl.inputs.len(), + has_self: sig.decl.has_self(), + c_variadic: sig.decl.c_variadic(), + }; + self.r.delegation_fn_sigs.insert(self.r.local_def_id(id), sig); } } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index d79c638fa078..64451030adf0 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -2039,7 +2039,8 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { ast::AssocItemKind::Fn(..) => AssocSuggestion::AssocFn { called }, ast::AssocItemKind::Type(..) => AssocSuggestion::AssocType, ast::AssocItemKind::Delegation(..) - if self.r.has_self.contains(&self.r.local_def_id(assoc_item.id)) => + if self.r.delegation_fn_sigs[&self.r.local_def_id(assoc_item.id)] + .has_self => { AssocSuggestion::MethodWithSelf { called } } @@ -2062,7 +2063,9 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { if filter_fn(res) { let def_id = res.def_id(); let has_self = match def_id.as_local() { - Some(def_id) => self.r.has_self.contains(&def_id), + Some(def_id) => { + self.r.delegation_fn_sigs.get(&def_id).map_or(false, |sig| sig.has_self) + } None => self .r .tcx diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index b5b6d899cc58..e07c3247d07a 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -43,7 +43,7 @@ use rustc_feature::BUILTIN_ATTRIBUTES; use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::NonMacroAttrKind; use rustc_hir::def::{self, CtorOf, DefKind, DocLinkResMap, LifetimeRes, PartialRes, PerNS}; -use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap, LocalDefIdSet}; +use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap}; use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::{PrimTy, TraitCandidate}; use rustc_index::IndexVec; @@ -52,8 +52,8 @@ use rustc_middle::metadata::ModChild; use rustc_middle::middle::privacy::EffectiveVisibilities; use rustc_middle::query::Providers; use rustc_middle::span_bug; -use rustc_middle::ty::{self, MainDefinition, RegisteredTools, TyCtxt, TyCtxtFeed}; -use rustc_middle::ty::{Feed, ResolverGlobalCtxt, ResolverOutputs}; +use rustc_middle::ty::{self, DelegationFnSig, Feed, MainDefinition, RegisteredTools}; +use rustc_middle::ty::{ResolverGlobalCtxt, ResolverOutputs, TyCtxt, TyCtxtFeed}; use rustc_query_system::ich::StableHashingContext; use rustc_session::lint::builtin::PRIVATE_MACRO_USE; use rustc_session::lint::LintBuffer; @@ -992,7 +992,6 @@ pub struct Resolver<'a, 'tcx> { extern_prelude: FxHashMap>, /// N.B., this is used only for better diagnostics, not name resolution itself. - has_self: LocalDefIdSet, field_def_ids: LocalDefIdMap<&'tcx [DefId]>, /// Span of the privacy modifier in fields of an item `DefId` accessible with dot syntax. @@ -1149,8 +1148,7 @@ pub struct Resolver<'a, 'tcx> { legacy_const_generic_args: FxHashMap>>, /// Amount of lifetime parameters for each item in the crate. item_generics_num_lifetimes: FxHashMap, - /// Amount of parameters for each function in the crate. - fn_parameter_counts: LocalDefIdMap, + delegation_fn_sigs: LocalDefIdMap, main_def: Option, trait_impls: FxIndexMap>, @@ -1399,7 +1397,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { prelude: None, extern_prelude, - has_self: Default::default(), field_def_ids: Default::default(), field_visibility_spans: FxHashMap::default(), @@ -1508,7 +1505,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { doc_link_resolutions: Default::default(), doc_link_traits_in_scope: Default::default(), all_macro_rules: Default::default(), - fn_parameter_counts: Default::default(), + delegation_fn_sigs: Default::default(), }; let root_parent_scope = ParentScope::module(graph_root, &resolver); @@ -1621,8 +1618,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { trait_map: self.trait_map, lifetime_elision_allowed: self.lifetime_elision_allowed, lint_buffer: Steal::new(self.lint_buffer), - has_self: self.has_self, - fn_parameter_counts: self.fn_parameter_counts, + delegation_fn_sigs: self.delegation_fn_sigs, }; ResolverOutputs { global_ctxt, ast_lowering } } diff --git a/tests/ui/delegation/auxiliary/fn-header-aux.rs b/tests/ui/delegation/auxiliary/fn-header-aux.rs new file mode 100644 index 000000000000..d26209a4f789 --- /dev/null +++ b/tests/ui/delegation/auxiliary/fn-header-aux.rs @@ -0,0 +1,9 @@ +//@ edition:2018 + +#![feature(c_variadic)] + +pub unsafe fn unsafe_fn_extern() {} +pub extern "C" fn extern_fn_extern() {} +pub unsafe extern "C" fn variadic_fn_extern(n: usize, mut args: ...) {} +pub const fn const_fn_extern() {} +pub async fn async_fn_extern() {} diff --git a/tests/ui/delegation/fn-header.rs b/tests/ui/delegation/fn-header.rs new file mode 100644 index 000000000000..db20e1058e06 --- /dev/null +++ b/tests/ui/delegation/fn-header.rs @@ -0,0 +1,57 @@ +//@ check-pass +//@ edition:2018 +//@ aux-crate:fn_header_aux=fn-header-aux.rs + +#![feature(c_variadic)] +#![feature(fn_delegation)] +#![allow(incomplete_features)] +#![deny(unused_unsafe)] + +mod to_reuse { + pub unsafe fn unsafe_fn() {} + pub extern "C" fn extern_fn() {} + pub unsafe extern "C" fn variadic_fn(n: usize, mut args: ...) {} + pub const fn const_fn() {} + pub async fn async_fn() {} +} + +reuse to_reuse::unsafe_fn; +reuse to_reuse::extern_fn; +reuse to_reuse::variadic_fn; +reuse to_reuse::const_fn; +reuse to_reuse::async_fn; + +reuse fn_header_aux::unsafe_fn_extern; +reuse fn_header_aux::extern_fn_extern; +reuse fn_header_aux::variadic_fn_extern; +reuse fn_header_aux::const_fn_extern; +reuse fn_header_aux::async_fn_extern; + +const fn const_check() { + const_fn(); + const_fn_extern(); +} + +async fn async_check() { + async_fn().await; + async_fn_extern().await; +} + +fn main() { + unsafe { + unsafe_fn(); + unsafe_fn_extern(); + } + extern_fn(); + extern_fn_extern(); + let _: extern "C" fn() = extern_fn; + let _: extern "C" fn() = extern_fn_extern; + unsafe { + variadic_fn(0); + variadic_fn(0, 1); + variadic_fn_extern(0); + variadic_fn_extern(0, 1); + } + let _: unsafe extern "C" fn(usize, ...) = variadic_fn; + let _: unsafe extern "C" fn(usize, ...) = variadic_fn_extern; +} diff --git a/tests/ui/delegation/impl-trait.rs b/tests/ui/delegation/impl-trait.rs new file mode 100644 index 000000000000..13df0155485c --- /dev/null +++ b/tests/ui/delegation/impl-trait.rs @@ -0,0 +1,27 @@ +//@ check-pass + +#![feature(fn_delegation)] +#![allow(incomplete_features)] + +mod to_reuse { + pub fn foo() -> impl Clone { 0 } +} + +reuse to_reuse::foo; + +trait Trait { + fn bar() -> impl Clone { 1 } +} + +struct S; +impl Trait for S {} + +impl S { + reuse to_reuse::foo; + reuse ::bar; +} + +fn main() { + foo().clone(); + ::bar().clone(); +} diff --git a/tests/ui/delegation/not-supported.rs b/tests/ui/delegation/not-supported.rs index 9dccb12b57ad..5f78de97638b 100644 --- a/tests/ui/delegation/not-supported.rs +++ b/tests/ui/delegation/not-supported.rs @@ -14,9 +14,9 @@ mod generics { fn foo3<'a: 'a>(_: &'a u32) {} reuse GenericTrait::bar; - //~^ delegation with early bound generics is not supported yet + //~^ ERROR delegation with early bound generics is not supported yet reuse GenericTrait::bar1; - //~^ delegation with early bound generics is not supported yet + //~^ ERROR delegation with early bound generics is not supported yet } struct F; @@ -73,26 +73,18 @@ mod opaque { } reuse to_reuse::opaque_arg; //~^ ERROR delegation with early bound generics is not supported yet - reuse to_reuse::opaque_ret; - //~^ ERROR delegation to a function with opaque type is not supported yet -} -mod fn_header { - mod to_reuse { - pub unsafe fn unsafe_fn() {} - pub extern "C" fn extern_fn() {} - pub unsafe extern "C" fn variadic_fn(n: usize, mut args: ...) {} - pub const fn const_fn() {} + trait ToReuse { + fn opaque_ret() -> impl Trait { unimplemented!() } } - reuse to_reuse::unsafe_fn; - //~^ ERROR delegation to unsafe functions is not supported yet - reuse to_reuse::extern_fn; - //~^ ERROR delegation to non Rust ABI functions is not supported yet - reuse to_reuse::variadic_fn; - //~^ ERROR delegation to variadic functions is not supported yet - reuse to_reuse::const_fn; - //~^ ERROR delegation to const functions is not supported yet + // FIXME: Inherited `impl Trait`s create query cycles when used inside trait impls. + impl ToReuse for u8 { + reuse to_reuse::opaque_ret; //~ ERROR cycle detected when computing type + } + impl ToReuse for u16 { + reuse ToReuse::opaque_ret; //~ ERROR cycle detected when computing type + } } mod recursive { diff --git a/tests/ui/delegation/not-supported.stderr b/tests/ui/delegation/not-supported.stderr index f6c49366899c..e2cb04f977b1 100644 --- a/tests/ui/delegation/not-supported.stderr +++ b/tests/ui/delegation/not-supported.stderr @@ -115,53 +115,46 @@ LL | pub fn opaque_arg(_: impl Trait) -> i32 { 0 } LL | reuse to_reuse::opaque_arg; | ^^^^^^^^^^ -error: delegation to a function with opaque type is not supported yet - --> $DIR/not-supported.rs:76:21 +error[E0391]: cycle detected when computing type of `opaque::::{synthetic#0}` + --> $DIR/not-supported.rs:83:25 | -LL | pub fn opaque_ret() -> impl Trait { unimplemented!() } - | --------------------------------- callee defined here -... -LL | reuse to_reuse::opaque_ret; - | ^^^^^^^^^^ +LL | reuse to_reuse::opaque_ret; + | ^^^^^^^^^^ + | +note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process... + --> $DIR/not-supported.rs:83:25 + | +LL | reuse to_reuse::opaque_ret; + | ^^^^^^^^^^ + = note: ...which again requires computing type of `opaque::::{synthetic#0}`, completing the cycle +note: cycle used when checking that `opaque::` is well-formed + --> $DIR/not-supported.rs:82:5 + | +LL | impl ToReuse for u8 { + | ^^^^^^^^^^^^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: delegation to unsafe functions is not supported yet - --> $DIR/not-supported.rs:88:21 +error[E0391]: cycle detected when computing type of `opaque::::{synthetic#0}` + --> $DIR/not-supported.rs:86:24 | -LL | pub unsafe fn unsafe_fn() {} - | ------------------------- callee defined here -... -LL | reuse to_reuse::unsafe_fn; - | ^^^^^^^^^ - -error: delegation to non Rust ABI functions is not supported yet - --> $DIR/not-supported.rs:90:21 +LL | reuse ToReuse::opaque_ret; + | ^^^^^^^^^^ | -LL | pub extern "C" fn extern_fn() {} - | ----------------------------- callee defined here -... -LL | reuse to_reuse::extern_fn; - | ^^^^^^^^^ - -error: delegation to variadic functions is not supported yet - --> $DIR/not-supported.rs:92:21 +note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process... + --> $DIR/not-supported.rs:86:24 | -LL | pub unsafe extern "C" fn variadic_fn(n: usize, mut args: ...) {} - | ------------------------------------------------------------- callee defined here -... -LL | reuse to_reuse::variadic_fn; - | ^^^^^^^^^^^ - -error: delegation to const functions is not supported yet - --> $DIR/not-supported.rs:94:21 +LL | reuse ToReuse::opaque_ret; + | ^^^^^^^^^^ + = note: ...which again requires computing type of `opaque::::{synthetic#0}`, completing the cycle +note: cycle used when checking that `opaque::` is well-formed + --> $DIR/not-supported.rs:85:5 | -LL | pub const fn const_fn() {} - | ----------------------- callee defined here -... -LL | reuse to_reuse::const_fn; - | ^^^^^^^^ +LL | impl ToReuse for u16 { + | ^^^^^^^^^^^^^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error: recursive delegation is not supported yet - --> $DIR/not-supported.rs:107:22 + --> $DIR/not-supported.rs:99:22 | LL | pub reuse to_reuse2::foo; | --- callee defined here @@ -169,7 +162,7 @@ LL | pub reuse to_reuse2::foo; LL | reuse to_reuse1::foo; | ^^^ -error: aborting due to 19 previous errors +error: aborting due to 16 previous errors -Some errors have detailed explanations: E0049, E0195. +Some errors have detailed explanations: E0049, E0195, E0391. For more information about an error, try `rustc --explain E0049`. From bcc4469c2b4d75bd52f23d404e9c4b3561372b2a Mon Sep 17 00:00:00 2001 From: "Christopher B. Speir" Date: Tue, 23 Apr 2024 14:38:29 -0500 Subject: [PATCH 20/36] Add diagnostic item for std::iter::Enumerate --- compiler/rustc_span/src/symbol.rs | 1 + library/core/src/iter/adapters/enumerate.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 8abf42e2c139..99591b5e1440 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -192,6 +192,7 @@ symbols! { Duration, Encodable, Encoder, + Enumerate, Eq, Equal, Err, diff --git a/library/core/src/iter/adapters/enumerate.rs b/library/core/src/iter/adapters/enumerate.rs index ef46040f0a70..7adbabf69e49 100644 --- a/library/core/src/iter/adapters/enumerate.rs +++ b/library/core/src/iter/adapters/enumerate.rs @@ -15,6 +15,7 @@ use crate::ops::Try; #[derive(Clone, Debug)] #[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "Enumerate")] pub struct Enumerate { iter: I, count: usize, From a589632dad58c2669b7984019efb59917a16ac67 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 11 Apr 2024 12:48:32 +0000 Subject: [PATCH 21/36] Add explicit syntax for coroutines instead of relying on closures having `yield` expressions --- compiler/rustc_ast_lowering/src/expr.rs | 12 +++++++++++- compiler/rustc_feature/src/builtin_attrs.rs | 6 ++++++ tests/ui/coroutine/derived-drop-parent-expr.rs | 4 ++-- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 2305cc07795d..6c3f03431472 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -217,6 +217,7 @@ impl<'hir> LoweringContext<'_, 'hir> { binder, *capture_clause, e.id, + hir_id, *constness, *movability, fn_decl, @@ -955,6 +956,7 @@ impl<'hir> LoweringContext<'_, 'hir> { binder: &ClosureBinder, capture_clause: CaptureBy, closure_id: NodeId, + closure_hir_id: hir::HirId, constness: Const, movability: Movability, decl: &FnDecl, @@ -965,7 +967,15 @@ impl<'hir> LoweringContext<'_, 'hir> { let (binder_clause, generic_params) = self.lower_closure_binder(binder); let (body_id, closure_kind) = self.with_new_scopes(fn_decl_span, move |this| { - let mut coroutine_kind = None; + let mut coroutine_kind = if this + .attrs + .get(&closure_hir_id.local_id) + .is_some_and(|attrs| attrs.iter().any(|attr| attr.has_name(sym::coroutine))) + { + Some(hir::CoroutineKind::Coroutine(Movability::Movable)) + } else { + None + }; let body_id = this.lower_fn_body(decl, |this| { let e = this.lower_expr_mut(body); coroutine_kind = this.coroutine_kind; diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 23b3f31b4370..647cd8d06f26 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -534,6 +534,12 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ EncodeCrossCrate::Yes, experimental!(cfi_encoding) ), + // `#[coroutine]` attribute to be applied to closures to make them coroutines instead + gated!( + coroutine, Normal, template!(Word), ErrorFollowing, + EncodeCrossCrate::No, coroutines, experimental!(coroutines) + ), + // ========================================================================== // Internal attributes: Stability, deprecation, and unsafe: // ========================================================================== diff --git a/tests/ui/coroutine/derived-drop-parent-expr.rs b/tests/ui/coroutine/derived-drop-parent-expr.rs index f70a732c90f0..71f7506ab845 100644 --- a/tests/ui/coroutine/derived-drop-parent-expr.rs +++ b/tests/ui/coroutine/derived-drop-parent-expr.rs @@ -10,7 +10,7 @@ pub struct Client { pub nickname: String } fn main() { let g = move || match drop(Client { ..Client::default() }) { - _status => yield, - }; + _status => yield, + }; assert_send(g); } From aef0f4024aec24fd7e53dbc51883457e44fe17ce Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 11 Apr 2024 13:15:34 +0000 Subject: [PATCH 22/36] Error on using `yield` without also using `#[coroutine]` on the closure And suggest adding the `#[coroutine]` to the closure --- compiler/rustc_ast_lowering/messages.ftl | 3 + compiler/rustc_ast_lowering/src/errors.rs | 9 ++ compiler/rustc_ast_lowering/src/expr.rs | 5 ++ compiler/rustc_ast_lowering/src/item.rs | 2 +- .../example/polymorphize_coroutine.rs | 5 +- .../example/std_example.rs | 10 ++- .../rustc_codegen_gcc/example/std_example.rs | 4 +- .../src/error_codes/E0626.md | 20 ++--- .../src/error_codes/E0627.md | 6 +- .../src/error_codes/E0628.md | 8 +- .../src/error_codes/E0727.md | 8 +- compiler/rustc_metadata/src/rmeta/decoder.rs | 42 +++++----- compiler/rustc_middle/src/lib.rs | 1 + compiler/rustc_middle/src/ty/closure.rs | 78 +++++++++-------- compiler/rustc_middle/src/ty/context.rs | 27 +++--- compiler/rustc_type_ir/src/ty_kind.rs | 2 +- .../core/src/iter/sources/from_coroutine.rs | 2 +- library/core/src/ops/coroutine.rs | 3 +- library/core/src/pin.rs | 2 +- .../src/language-features/coroutines.md | 23 ++--- .../unstable-book/src/the-unstable-book.md | 4 +- src/tools/clippy/tests/ui/crashes/ice-5238.rs | 4 +- src/tools/clippy/tests/ui/large_futures.fixed | 1 - src/tools/clippy/tests/ui/large_futures.rs | 1 - .../clippy/tests/ui/large_futures.stderr | 16 ++-- src/tools/clippy/tests/ui/redundant_locals.rs | 6 +- .../miri/tests/fail/coroutine-pinned-moved.rs | 4 +- src/tools/miri/tests/pass/coroutine.rs | 36 ++++---- .../coroutine-self-referential.rs | 4 +- .../miri/tests/pass/track-caller-attribute.rs | 6 +- .../crates/ide-db/src/generated/lints.rs | 6 +- .../tests/source/immovable_coroutines.rs | 3 +- .../tests/target/immovable_coroutines.rs | 3 +- tests/codegen/coroutine-debug-msvc.rs | 2 +- tests/codegen/coroutine-debug.rs | 2 +- tests/coverage/coroutine.cov-map | 4 +- tests/coverage/coroutine.coverage | 4 +- tests/coverage/coroutine.rs | 4 +- tests/coverage/yield.cov-map | 8 +- tests/coverage/yield.coverage | 6 +- tests/coverage/yield.rs | 6 +- tests/debuginfo/coroutine-locals.rs | 9 +- tests/debuginfo/coroutine-objects.rs | 5 +- tests/debuginfo/function-names.rs | 5 +- tests/debuginfo/issue-57822.rs | 8 +- ...losure#0}.coroutine_drop.0.panic-abort.mir | 2 +- ...osure#0}.coroutine_drop.0.panic-unwind.mir | 2 +- tests/mir-opt/coroutine_drop_cleanup.rs | 5 +- ...e#0}.StateTransform.before.panic-abort.mir | 2 +- ...#0}.StateTransform.before.panic-unwind.mir | 2 +- .../mir-opt/coroutine_storage_dead_unwind.rs | 5 +- ...ny.main-{closure#0}.coroutine_resume.0.mir | 12 +-- tests/mir-opt/coroutine_tiny.rs | 5 +- ...ine_coroutine.main.Inline.panic-abort.diff | 22 ++--- ...ne_coroutine.main.Inline.panic-unwind.diff | 22 ++--- tests/mir-opt/inline/inline_coroutine.rs | 3 +- ...async-outside-of-await-issue-121096.stderr | 2 +- .../incorrect-syntax-suggestions.stderr | 10 +-- tests/ui/async-await/coroutine-not-future.rs | 23 +++-- .../async-await/coroutine-not-future.stderr | 42 +++++----- .../ui/async-await/issues/issue-51751.stderr | 2 +- .../async-await/issues/issue-62009-1.stderr | 6 +- .../async-await/issues/issue-62009-2.stderr | 2 +- ...65419-coroutine-resume-after-completion.rs | 10 +-- .../issues/non-async-enclosing-span.stderr | 2 +- tests/ui/async-await/non-trivial-drop.rs | 2 +- .../ui/coherence/coherence-with-coroutine.rs | 1 + .../coherence-with-coroutine.stock.stderr | 2 +- tests/ui/coroutine/addassign-yield.rs | 8 +- tests/ui/coroutine/auto-trait-regions.rs | 8 +- .../metadata-sufficient-for-layout.rs | 1 + tests/ui/coroutine/auxiliary/unwind-aux.rs | 5 +- .../coroutine/auxiliary/xcrate-reachable.rs | 1 + tests/ui/coroutine/auxiliary/xcrate.rs | 12 ++- tests/ui/coroutine/borrow-in-tail-expr.rs | 4 +- tests/ui/coroutine/borrowing.rs | 6 +- tests/ui/coroutine/borrowing.stderr | 14 ++-- .../coroutine/check-resume-ty-lifetimes-2.rs | 8 +- .../check-resume-ty-lifetimes-2.stderr | 12 +-- .../ui/coroutine/check-resume-ty-lifetimes.rs | 15 ++-- .../check-resume-ty-lifetimes.stderr | 6 +- tests/ui/coroutine/clone-impl-static.rs | 5 +- tests/ui/coroutine/clone-impl-static.stderr | 16 ++-- tests/ui/coroutine/clone-impl.rs | 17 ++-- tests/ui/coroutine/clone-impl.stderr | 84 +++++++++---------- tests/ui/coroutine/clone-rpit.next.stderr | 12 +-- tests/ui/coroutine/clone-rpit.rs | 1 + tests/ui/coroutine/conditional-drop.rs | 6 +- tests/ui/coroutine/control-flow.rs | 12 +-- .../coroutine-region-requirements.rs | 4 +- .../coroutine/coroutine-resume-after-panic.rs | 4 +- tests/ui/coroutine/coroutine-with-nll.rs | 1 + tests/ui/coroutine/coroutine-with-nll.stderr | 2 +- .../coroutine-yielding-or-returning-itself.rs | 6 +- ...outine-yielding-or-returning-itself.stderr | 16 ++-- .../ui/coroutine/derived-drop-parent-expr.rs | 4 +- tests/ui/coroutine/discriminant.rs | 6 +- tests/ui/coroutine/drop-and-replace.rs | 5 +- tests/ui/coroutine/drop-control-flow.rs | 20 ++--- tests/ui/coroutine/drop-env.rs | 8 +- .../coroutine/drop-track-addassign-yield.rs | 6 +- .../drop-tracking-parent-expression.rs | 6 +- .../drop-tracking-parent-expression.stderr | 18 ++-- .../drop-tracking-yielding-in-match-guards.rs | 4 +- tests/ui/coroutine/drop-yield-twice.rs | 4 +- tests/ui/coroutine/drop-yield-twice.stderr | 4 +- tests/ui/coroutine/dropck-resume.rs | 5 +- tests/ui/coroutine/dropck-resume.stderr | 2 +- tests/ui/coroutine/dropck.rs | 5 +- tests/ui/coroutine/dropck.stderr | 6 +- tests/ui/coroutine/gen_block.e2024.stderr | 47 ++++++++++- tests/ui/coroutine/gen_block.none.stderr | 66 +++++++++++++-- tests/ui/coroutine/gen_block.rs | 9 ++ tests/ui/coroutine/issue-102645.rs | 5 +- tests/ui/coroutine/issue-102645.stderr | 2 +- tests/ui/coroutine/issue-105084.rs | 3 +- tests/ui/coroutine/issue-105084.stderr | 18 ++-- ...sue-110929-coroutine-conflict-error-ice.rs | 5 +- tests/ui/coroutine/issue-113279.rs | 5 +- tests/ui/coroutine/issue-113279.stderr | 4 +- tests/ui/coroutine/issue-44197.rs | 4 +- .../issue-45729-unsafe-in-coroutine.rs | 5 +- .../issue-45729-unsafe-in-coroutine.stderr | 2 +- tests/ui/coroutine/issue-48048.rs | 2 +- tests/ui/coroutine/issue-52304.rs | 1 + tests/ui/coroutine/issue-52398.rs | 4 +- tests/ui/coroutine/issue-52398.stderr | 10 ++- tests/ui/coroutine/issue-53548.rs | 4 +- tests/ui/coroutine/issue-57017.rs | 6 +- tests/ui/coroutine/issue-57084.rs | 4 +- tests/ui/coroutine/issue-57084.stderr | 5 +- tests/ui/coroutine/issue-57478.rs | 15 ++-- tests/ui/coroutine/issue-58888.rs | 2 +- .../issue-61442-stmt-expr-with-drop.rs | 8 +- .../issue-64620-yield-array-element.rs | 1 + .../issue-64620-yield-array-element.stderr | 13 ++- tests/ui/coroutine/issue-68112.rs | 8 +- tests/ui/coroutine/issue-68112.stderr | 16 ++-- tests/ui/coroutine/issue-69017.rs | 1 + tests/ui/coroutine/issue-69039.rs | 1 + tests/ui/coroutine/issue-87142.rs | 1 + tests/ui/coroutine/issue-88653.rs | 1 + tests/ui/coroutine/issue-91477.rs | 1 + tests/ui/coroutine/issue-91477.stderr | 13 ++- tests/ui/coroutine/iterator-count.rs | 2 + tests/ui/coroutine/live-upvar-across-yield.rs | 4 +- tests/ui/coroutine/match-bindings.rs | 2 +- tests/ui/coroutine/match-bindings.stderr | 5 +- .../missing_coroutine_attr_suggestion.fixed | 8 ++ .../missing_coroutine_attr_suggestion.rs | 8 ++ .../missing_coroutine_attr_suggestion.stderr | 13 +++ tests/ui/coroutine/nested_coroutine.rs | 8 +- tests/ui/coroutine/niche-in-coroutine.rs | 4 +- tests/ui/coroutine/non-static-is-unpin.rs | 4 +- tests/ui/coroutine/not-send-sync.rs | 6 +- tests/ui/coroutine/not-send-sync.stderr | 8 +- tests/ui/coroutine/overlap-locals.rs | 5 +- tests/ui/coroutine/panic-drops-resume.rs | 4 +- tests/ui/coroutine/panic-drops.rs | 17 ++-- tests/ui/coroutine/panic-safe.rs | 4 +- tests/ui/coroutine/parent-expression.rs | 6 +- tests/ui/coroutine/parent-expression.stderr | 18 ++-- tests/ui/coroutine/partial-drop.rs | 45 ++++++---- .../partial-initialization-across-yield.rs | 8 +- tests/ui/coroutine/pattern-borrow.rs | 2 +- tests/ui/coroutine/pin-box-coroutine.rs | 6 +- tests/ui/coroutine/polymorphize-args.rs | 5 +- .../print/coroutine-print-verbose-1.rs | 8 +- .../print/coroutine-print-verbose-1.stderr | 12 +-- .../print/coroutine-print-verbose-2.rs | 6 +- .../print/coroutine-print-verbose-2.stderr | 4 +- .../print/coroutine-print-verbose-3.rs | 9 +- .../print/coroutine-print-verbose-3.stderr | 11 ++- tests/ui/coroutine/reborrow-mut-upvar.rs | 2 +- tests/ui/coroutine/reborrow-mut-upvar.stderr | 5 +- .../ref-escapes-but-not-over-yield.rs | 9 +- .../ref-escapes-but-not-over-yield.stderr | 2 +- tests/ui/coroutine/ref-upvar-not-send.rs | 6 +- tests/ui/coroutine/ref-upvar-not-send.stderr | 16 ++-- tests/ui/coroutine/reinit-in-match-guard.rs | 6 +- tests/ui/coroutine/resume-after-return.rs | 12 +-- tests/ui/coroutine/resume-arg-late-bound.rs | 4 +- .../ui/coroutine/resume-arg-late-bound.stderr | 2 +- tests/ui/coroutine/resume-arg-size.rs | 8 +- .../ui/coroutine/resume-live-across-yield.rs | 5 +- tests/ui/coroutine/retain-resume-ref.rs | 5 +- tests/ui/coroutine/retain-resume-ref.stderr | 2 +- tests/ui/coroutine/size-moved-locals.rs | 4 + tests/ui/coroutine/sized-yield.rs | 5 +- tests/ui/coroutine/sized-yield.stderr | 7 +- tests/ui/coroutine/smoke-resume-args.rs | 17 ++-- tests/ui/coroutine/smoke.rs | 32 +++---- tests/ui/coroutine/static-coroutine.rs | 7 +- .../static-mut-reference-across-yield.rs | 8 +- .../coroutine/static-not-unpin.current.stderr | 6 +- .../ui/coroutine/static-not-unpin.next.stderr | 6 +- tests/ui/coroutine/static-not-unpin.rs | 8 +- .../static-reference-across-yield.rs | 4 +- .../too-live-local-in-immovable-gen.rs | 2 +- .../too-live-local-in-immovable-gen.stderr | 5 +- tests/ui/coroutine/too-many-parameters.rs | 1 + tests/ui/coroutine/too-many-parameters.stderr | 2 +- tests/ui/coroutine/type-mismatch-error.rs | 3 +- tests/ui/coroutine/type-mismatch-error.stderr | 2 +- .../type-mismatch-signature-deduction.rs | 1 + .../type-mismatch-signature-deduction.stderr | 6 +- tests/ui/coroutine/uninhabited-field.rs | 4 +- .../coroutine/unsized-capture-across-yield.rs | 1 + .../unsized-capture-across-yield.stderr | 2 +- .../coroutine/unsized-local-across-yield.rs | 1 + .../unsized-local-across-yield.stderr | 2 +- tests/ui/coroutine/yield-in-args-rev.rs | 2 +- tests/ui/coroutine/yield-in-args-rev.stderr | 5 +- tests/ui/coroutine/yield-in-args.rs | 1 + tests/ui/coroutine/yield-in-args.stderr | 2 +- tests/ui/coroutine/yield-in-const.rs | 1 + tests/ui/coroutine/yield-in-const.stderr | 8 +- tests/ui/coroutine/yield-in-function.rs | 1 + tests/ui/coroutine/yield-in-function.stderr | 13 ++- tests/ui/coroutine/yield-in-initializer.rs | 2 +- .../ui/coroutine/yield-in-initializer.stderr | 5 +- tests/ui/coroutine/yield-in-static.rs | 1 + tests/ui/coroutine/yield-in-static.stderr | 8 +- .../yield-outside-coroutine-issue-78653.rs | 1 + ...yield-outside-coroutine-issue-78653.stderr | 13 ++- tests/ui/coroutine/yield-subtype.rs | 2 +- tests/ui/coroutine/yield-subtype.stderr | 5 +- tests/ui/coroutine/yield-while-iterating.rs | 14 ++-- .../ui/coroutine/yield-while-iterating.stderr | 4 +- .../coroutine/yield-while-local-borrowed.rs | 8 +- .../coroutine/yield-while-ref-reborrowed.rs | 21 +++-- .../yield-while-ref-reborrowed.stderr | 6 +- tests/ui/drop/dynamic-drop.rs | 4 +- .../feature-gate-closure_track_caller.rs | 2 +- .../feature-gate-closure_track_caller.stderr | 6 +- .../feature-gate-coroutines.e2024.stderr | 26 +++++- .../feature-gate-coroutines.none.stderr | 32 +++++-- .../feature-gates/feature-gate-coroutines.rs | 2 + tests/ui/impl-trait/issues/issue-58504.rs | 2 +- tests/ui/impl-trait/lifetimes.rs | 2 +- .../recursive-coroutine-boxed.next.stderr | 9 +- .../impl-trait/recursive-coroutine-boxed.rs | 3 +- ...ecursive-coroutine-indirect.current.stderr | 6 +- .../recursive-coroutine-indirect.next.stderr | 6 +- .../recursive-coroutine-indirect.rs | 2 +- .../recursive-impl-trait-type-indirect.rs | 2 + .../recursive-impl-trait-type-indirect.stderr | 8 +- .../lint/must_not_suspend/tuple-mismatch.rs | 5 +- .../must_not_suspend/tuple-mismatch.stderr | 2 +- .../issue-74883-unused-paren-baren-yield.rs | 4 +- tests/ui/lint/unused/unused-closure.rs | 4 +- tests/ui/liveness/liveness-upvars.rs | 4 +- tests/ui/nll/coroutine-distinct-lifetime.rs | 1 + tests/ui/nll/coroutine-upvar-mutability.rs | 2 + .../ui/nll/coroutine-upvar-mutability.stderr | 4 +- tests/ui/nll/extra-unused-mut.rs | 6 +- tests/ui/nll/issue-48623-coroutine.rs | 2 +- tests/ui/nll/issue-48623-coroutine.stderr | 6 +- tests/ui/nll/issue-55850.rs | 2 +- tests/ui/packed/packed-struct-drop-aligned.rs | 10 +-- tests/ui/polymorphization/coroutine.rs | 6 ++ tests/ui/polymorphization/coroutine.stderr | 6 +- tests/ui/print_type_sizes/coroutine.rs | 1 + tests/ui/print_type_sizes/coroutine.stdout | 2 +- .../coroutine_discr_placement.rs | 5 +- .../coroutine_discr_placement.stdout | 2 +- .../rfc-2091-track-caller/tracked-closure.rs | 6 +- tests/ui/sanitizer/cfi-coroutine.rs | 4 +- tests/ui/suggestions/issue-84973-blacklist.rs | 2 +- .../suggestions/issue-84973-blacklist.stderr | 8 +- tests/ui/suggestions/unnamable-types.rs | 4 +- tests/ui/suggestions/unnamable-types.stderr | 10 +-- .../traits/next-solver/coroutine.fail.stderr | 54 ++++++------ tests/ui/traits/next-solver/coroutine.rs | 26 +++--- .../issue-53678-coroutine-and-const-fn.rs | 1 + .../issue-58662-coroutine-with-lifetime.rs | 2 + tests/ui/type-alias-impl-trait/issue-94429.rs | 1 + .../type-alias-impl-trait/issue-94429.stderr | 2 +- tests/ui/weird-exprs.rs | 1 + 279 files changed, 1290 insertions(+), 886 deletions(-) create mode 100644 tests/ui/coroutine/missing_coroutine_attr_suggestion.fixed create mode 100644 tests/ui/coroutine/missing_coroutine_attr_suggestion.rs create mode 100644 tests/ui/coroutine/missing_coroutine_attr_suggestion.stderr diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl index a23e714ef017..73001c9990c8 100644 --- a/compiler/rustc_ast_lowering/messages.ftl +++ b/compiler/rustc_ast_lowering/messages.ftl @@ -163,3 +163,6 @@ ast_lowering_underscore_expr_lhs_assign = .label = `_` not allowed here ast_lowering_use_angle_brackets = use angle brackets instead +ast_lowering_yield_in_closure = + `yield` can only be used in `#[coroutine]` closures, or `gen` blocks + .suggestion = use `#[coroutine]` to make this closure a coroutine diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index 6799513a323c..6f70e135c72a 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -421,3 +421,12 @@ pub(crate) struct NoPreciseCapturesOnApit { #[primary_span] pub span: Span, } + +#[derive(Diagnostic)] +#[diag(ast_lowering_yield_in_closure)] +pub(crate) struct YieldInClosure { + #[primary_span] + pub span: Span, + #[suggestion(code = "#[coroutine] ", applicability = "maybe-incorrect", style = "verbose")] + pub suggestion: Option, +} diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 6c3f03431472..5cc05d7336ee 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -8,6 +8,7 @@ use super::errors::{ }; use super::ResolverAstLoweringExt; use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs}; +use crate::errors::YieldInClosure; use crate::{FnDeclKind, ImplTraitPosition}; use rustc_ast::ptr::P as AstP; use rustc_ast::*; @@ -977,6 +978,7 @@ impl<'hir> LoweringContext<'_, 'hir> { None }; let body_id = this.lower_fn_body(decl, |this| { + this.coroutine_kind = coroutine_kind; let e = this.lower_expr_mut(body); coroutine_kind = this.coroutine_kind; e @@ -1575,7 +1577,10 @@ impl<'hir> LoweringContext<'_, 'hir> { ) .emit(); } + let suggestion = self.current_item.map(|s| s.shrink_to_lo()); + self.dcx().emit_err(YieldInClosure { span, suggestion }); self.coroutine_kind = Some(hir::CoroutineKind::Coroutine(Movability::Movable)); + false } }; diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index e4c633aa324a..1d52b4107d7b 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -203,7 +203,7 @@ impl<'hir> LoweringContext<'_, 'hir> { body, .. }) => { - self.with_new_scopes(ident.span, |this| { + self.with_new_scopes(*fn_sig_span, |this| { // Note: we don't need to change the return type from `T` to // `impl Future` here because lower_body // only cares about the input argument patterns in the function diff --git a/compiler/rustc_codegen_cranelift/example/polymorphize_coroutine.rs b/compiler/rustc_codegen_cranelift/example/polymorphize_coroutine.rs index c965b34e13b9..407da94c0f09 100644 --- a/compiler/rustc_codegen_cranelift/example/polymorphize_coroutine.rs +++ b/compiler/rustc_codegen_cranelift/example/polymorphize_coroutine.rs @@ -1,4 +1,4 @@ -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] use std::ops::Coroutine; use std::pin::Pin; @@ -8,7 +8,8 @@ fn main() { } fn run_coroutine() { - let mut coroutine = || { + let mut coroutine = #[coroutine] + || { yield; return; }; diff --git a/compiler/rustc_codegen_cranelift/example/std_example.rs b/compiler/rustc_codegen_cranelift/example/std_example.rs index 0205de556228..90d4ab721dae 100644 --- a/compiler/rustc_codegen_cranelift/example/std_example.rs +++ b/compiler/rustc_codegen_cranelift/example/std_example.rs @@ -1,6 +1,7 @@ #![feature( core_intrinsics, coroutines, + stmt_expr_attributes, coroutine_trait, is_sorted, repr_simd, @@ -123,9 +124,12 @@ fn main() { test_simd(); } - Box::pin(move |mut _task_context| { - yield (); - }) + Box::pin( + #[coroutine] + move |mut _task_context| { + yield (); + }, + ) .as_mut() .resume(0); diff --git a/compiler/rustc_codegen_gcc/example/std_example.rs b/compiler/rustc_codegen_gcc/example/std_example.rs index ad69409eb659..8ab8fcc525e5 100644 --- a/compiler/rustc_codegen_gcc/example/std_example.rs +++ b/compiler/rustc_codegen_gcc/example/std_example.rs @@ -1,5 +1,5 @@ #![allow(internal_features)] -#![feature(core_intrinsics, coroutines, coroutine_trait, is_sorted)] +#![feature(core_intrinsics, coroutines, coroutine_trait, is_sorted, stmt_expr_attributes)] #[cfg(feature="master")] #[cfg(target_arch="x86_64")] @@ -103,7 +103,7 @@ fn main() { test_simd(); } - Box::pin(move |mut _task_context| { + Box::pin(#[coroutine] move |mut _task_context| { yield (); }).as_mut().resume(0); diff --git a/compiler/rustc_error_codes/src/error_codes/E0626.md b/compiler/rustc_error_codes/src/error_codes/E0626.md index e2534415d830..28d543350ffd 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0626.md +++ b/compiler/rustc_error_codes/src/error_codes/E0626.md @@ -4,10 +4,10 @@ yield point. Erroneous code example: ```compile_fail,E0626 -# #![feature(coroutines, coroutine_trait, pin)] +# #![feature(coroutines, coroutine_trait, stmt_expr_attributes)] # use std::ops::Coroutine; # use std::pin::Pin; -let mut b = || { +let mut b = #[coroutine] || { let a = &String::new(); // <-- This borrow... yield (); // ...is still in scope here, when the yield occurs. println!("{}", a); @@ -23,10 +23,10 @@ resolve the previous example by removing the borrow and just storing the integer by value: ``` -# #![feature(coroutines, coroutine_trait, pin)] +# #![feature(coroutines, coroutine_trait, stmt_expr_attributes)] # use std::ops::Coroutine; # use std::pin::Pin; -let mut b = || { +let mut b = #[coroutine] || { let a = 3; yield (); println!("{}", a); @@ -41,10 +41,10 @@ in those cases, something like the `Rc` or `Arc` types may be useful. This error also frequently arises with iteration: ```compile_fail,E0626 -# #![feature(coroutines, coroutine_trait, pin)] +# #![feature(coroutines, coroutine_trait, stmt_expr_attributes)] # use std::ops::Coroutine; # use std::pin::Pin; -let mut b = || { +let mut b = #[coroutine] || { let v = vec![1,2,3]; for &x in &v { // <-- borrow of `v` is still in scope... yield x; // ...when this yield occurs. @@ -57,10 +57,10 @@ Such cases can sometimes be resolved by iterating "by value" (or using `into_iter()`) to avoid borrowing: ``` -# #![feature(coroutines, coroutine_trait, pin)] +# #![feature(coroutines, coroutine_trait, stmt_expr_attributes)] # use std::ops::Coroutine; # use std::pin::Pin; -let mut b = || { +let mut b = #[coroutine] || { let v = vec![1,2,3]; for x in v { // <-- Take ownership of the values instead! yield x; // <-- Now yield is OK. @@ -72,10 +72,10 @@ Pin::new(&mut b).resume(()); If taking ownership is not an option, using indices can work too: ``` -# #![feature(coroutines, coroutine_trait, pin)] +# #![feature(coroutines, coroutine_trait, stmt_expr_attributes)] # use std::ops::Coroutine; # use std::pin::Pin; -let mut b = || { +let mut b = #[coroutine] || { let v = vec![1,2,3]; let len = v.len(); // (*) for i in 0..len { diff --git a/compiler/rustc_error_codes/src/error_codes/E0627.md b/compiler/rustc_error_codes/src/error_codes/E0627.md index 5d366f78fc57..da2e2d355a16 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0627.md +++ b/compiler/rustc_error_codes/src/error_codes/E0627.md @@ -3,7 +3,7 @@ A yield expression was used outside of the coroutine literal. Erroneous code example: ```compile_fail,E0627 -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] fn fake_coroutine() -> &'static str { yield 1; @@ -19,10 +19,10 @@ The error occurs because keyword `yield` can only be used inside the coroutine literal. This can be fixed by constructing the coroutine correctly. ``` -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] fn main() { - let mut coroutine = || { + let mut coroutine = #[coroutine] || { yield 1; return "foo" }; diff --git a/compiler/rustc_error_codes/src/error_codes/E0628.md b/compiler/rustc_error_codes/src/error_codes/E0628.md index ce19bcd56cc7..d0d387cf6c7e 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0628.md +++ b/compiler/rustc_error_codes/src/error_codes/E0628.md @@ -3,10 +3,10 @@ More than one parameter was used for a coroutine. Erroneous code example: ```compile_fail,E0628 -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] fn main() { - let coroutine = |a: i32, b: i32| { + let coroutine = #[coroutine] |a: i32, b: i32| { // error: too many parameters for a coroutine // Allowed only 0 or 1 parameter yield a; @@ -20,10 +20,10 @@ at most 1 parameter for the coroutine. For example, we might resolve the previous example by passing only one parameter. ``` -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] fn main() { - let coroutine = |a: i32| { + let coroutine = #[coroutine] |a: i32| { yield a; }; } diff --git a/compiler/rustc_error_codes/src/error_codes/E0727.md b/compiler/rustc_error_codes/src/error_codes/E0727.md index fde35885c920..7754186508f1 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0727.md +++ b/compiler/rustc_error_codes/src/error_codes/E0727.md @@ -3,10 +3,10 @@ A `yield` clause was used in an `async` context. Erroneous code example: ```compile_fail,E0727,edition2018 -#![feature(coroutines)] +#![feature(coroutines, stmt_expr_attributes)] fn main() { - let coroutine = || { + let coroutine = #[coroutine] || { async { yield; } @@ -20,10 +20,10 @@ which is not yet supported. To fix this error, you have to move `yield` out of the `async` block: ```edition2018 -#![feature(coroutines)] +#![feature(coroutines, stmt_expr_attributes)] fn main() { - let coroutine = || { + let coroutine = #[coroutine] || { yield; }; } diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index c4ab4eb2657d..fd42c9c1faaf 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1260,30 +1260,34 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { id: DefIndex, sess: &'a Session, ) -> impl Iterator + 'a { - iter::from_coroutine(move || { - if let Some(data) = &self.root.proc_macro_data { - // If we are loading as a proc macro, we want to return - // the view of this crate as a proc macro crate. - if id == CRATE_DEF_INDEX { - for child_index in data.macros.decode(self) { + iter::from_coroutine( + #[cfg_attr(not(bootstrap), coroutine)] + move || { + if let Some(data) = &self.root.proc_macro_data { + // If we are loading as a proc macro, we want to return + // the view of this crate as a proc macro crate. + if id == CRATE_DEF_INDEX { + for child_index in data.macros.decode(self) { + yield self.get_mod_child(child_index, sess); + } + } + } else { + // Iterate over all children. + let non_reexports = + self.root.tables.module_children_non_reexports.get(self, id); + for child_index in non_reexports.unwrap().decode(self) { yield self.get_mod_child(child_index, sess); } - } - } else { - // Iterate over all children. - let non_reexports = self.root.tables.module_children_non_reexports.get(self, id); - for child_index in non_reexports.unwrap().decode(self) { - yield self.get_mod_child(child_index, sess); - } - let reexports = self.root.tables.module_children_reexports.get(self, id); - if !reexports.is_default() { - for reexport in reexports.decode((self, sess)) { - yield reexport; + let reexports = self.root.tables.module_children_reexports.get(self, id); + if !reexports.is_default() { + for reexport in reexports.decode((self, sess)) { + yield reexport; + } } } - } - }) + }, + ) } fn is_ctfe_mir_available(self, id: DefIndex) -> bool { diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index aadaca18326c..80762e3e5c1b 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -35,6 +35,7 @@ #![feature(const_type_name)] #![feature(discriminant_kind)] #![feature(coroutines)] +#![feature(stmt_expr_attributes)] #![feature(if_let_guard)] #![feature(inline_const)] #![feature(iter_from_coroutine)] diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs index 11167515b7ca..b66c664e6ae1 100644 --- a/compiler/rustc_middle/src/ty/closure.rs +++ b/compiler/rustc_middle/src/ty/closure.rs @@ -422,49 +422,53 @@ pub fn analyze_coroutine_closure_captures<'a, 'tcx: 'a, T>( child_captures: impl IntoIterator>, mut for_each: impl FnMut((usize, &'a CapturedPlace<'tcx>), (usize, &'a CapturedPlace<'tcx>)) -> T, ) -> impl Iterator + Captures<'a> + Captures<'tcx> { - std::iter::from_coroutine(move || { - let mut child_captures = child_captures.into_iter().enumerate().peekable(); + std::iter::from_coroutine( + #[cfg_attr(not(bootstrap), coroutine)] + move || { + let mut child_captures = child_captures.into_iter().enumerate().peekable(); - // One parent capture may correspond to several child captures if we end up - // refining the set of captures via edition-2021 precise captures. We want to - // match up any number of child captures with one parent capture, so we keep - // peeking off this `Peekable` until the child doesn't match anymore. - for (parent_field_idx, parent_capture) in parent_captures.into_iter().enumerate() { - // Make sure we use every field at least once, b/c why are we capturing something - // if it's not used in the inner coroutine. - let mut field_used_at_least_once = false; + // One parent capture may correspond to several child captures if we end up + // refining the set of captures via edition-2021 precise captures. We want to + // match up any number of child captures with one parent capture, so we keep + // peeking off this `Peekable` until the child doesn't match anymore. + for (parent_field_idx, parent_capture) in parent_captures.into_iter().enumerate() { + // Make sure we use every field at least once, b/c why are we capturing something + // if it's not used in the inner coroutine. + let mut field_used_at_least_once = false; - // A parent matches a child if they share the same prefix of projections. - // The child may have more, if it is capturing sub-fields out of - // something that is captured by-move in the parent closure. - while child_captures.peek().map_or(false, |(_, child_capture)| { - child_prefix_matches_parent_projections(parent_capture, child_capture) - }) { - let (child_field_idx, child_capture) = child_captures.next().unwrap(); - // This analysis only makes sense if the parent capture is a - // prefix of the child capture. - assert!( - child_capture.place.projections.len() >= parent_capture.place.projections.len(), - "parent capture ({parent_capture:#?}) expected to be prefix of \ + // A parent matches a child if they share the same prefix of projections. + // The child may have more, if it is capturing sub-fields out of + // something that is captured by-move in the parent closure. + while child_captures.peek().map_or(false, |(_, child_capture)| { + child_prefix_matches_parent_projections(parent_capture, child_capture) + }) { + let (child_field_idx, child_capture) = child_captures.next().unwrap(); + // This analysis only makes sense if the parent capture is a + // prefix of the child capture. + assert!( + child_capture.place.projections.len() + >= parent_capture.place.projections.len(), + "parent capture ({parent_capture:#?}) expected to be prefix of \ child capture ({child_capture:#?})" - ); + ); - yield for_each( - (parent_field_idx, parent_capture), - (child_field_idx, child_capture), - ); + yield for_each( + (parent_field_idx, parent_capture), + (child_field_idx, child_capture), + ); - field_used_at_least_once = true; + field_used_at_least_once = true; + } + + // Make sure the field was used at least once. + assert!( + field_used_at_least_once, + "we captured {parent_capture:#?} but it was not used in the child coroutine?" + ); } - - // Make sure the field was used at least once. - assert!( - field_used_at_least_once, - "we captured {parent_capture:#?} but it was not used in the child coroutine?" - ); - } - assert_eq!(child_captures.next(), None, "leftover child captures?"); - }) + assert_eq!(child_captures.next(), None, "leftover child captures?"); + }, + ) } fn child_prefix_matches_parent_projections( diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 7dbe59e132d7..45fa5e8f7ca3 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1284,20 +1284,23 @@ impl<'tcx> TyCtxt<'tcx> { self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE); let definitions = &self.untracked.definitions; - std::iter::from_coroutine(|| { - let mut i = 0; + std::iter::from_coroutine( + #[cfg_attr(not(bootstrap), coroutine)] + || { + let mut i = 0; - // Recompute the number of definitions each time, because our caller may be creating - // new ones. - while i < { definitions.read().num_definitions() } { - let local_def_index = rustc_span::def_id::DefIndex::from_usize(i); - yield LocalDefId { local_def_index }; - i += 1; - } + // Recompute the number of definitions each time, because our caller may be creating + // new ones. + while i < { definitions.read().num_definitions() } { + let local_def_index = rustc_span::def_id::DefIndex::from_usize(i); + yield LocalDefId { local_def_index }; + i += 1; + } - // Freeze definitions once we finish iterating on them, to prevent adding new ones. - definitions.freeze(); - }) + // Freeze definitions once we finish iterating on them, to prevent adding new ones. + definitions.freeze(); + }, + ) } pub fn def_path_table(self) -> &'tcx rustc_hir::definitions::DefPathTable { diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 397e104512fd..d7de0dd3bbf8 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -183,7 +183,7 @@ pub enum TyKind { /// /// ``` /// #![feature(coroutines)] - /// static |a| { + /// #[coroutine] static |a| { /// let x = &vec![3]; /// yield a; /// yield x[0]; diff --git a/library/core/src/iter/sources/from_coroutine.rs b/library/core/src/iter/sources/from_coroutine.rs index bf413b24d417..9bac9037a024 100644 --- a/library/core/src/iter/sources/from_coroutine.rs +++ b/library/core/src/iter/sources/from_coroutine.rs @@ -14,7 +14,7 @@ use crate::pin::Pin; /// #![feature(coroutines)] /// #![feature(iter_from_coroutine)] /// -/// let it = std::iter::from_coroutine(|| { +/// let it = std::iter::from_coroutine(#[cfg_attr(not(bootstrap), coroutine)] || { /// yield 1; /// yield 2; /// yield 3; diff --git a/library/core/src/ops/coroutine.rs b/library/core/src/ops/coroutine.rs index 6e067f95da92..5250be15fe43 100644 --- a/library/core/src/ops/coroutine.rs +++ b/library/core/src/ops/coroutine.rs @@ -40,12 +40,13 @@ pub enum CoroutineState { /// ```rust /// #![feature(coroutines)] /// #![feature(coroutine_trait)] +/// #![feature(stmt_expr_attributes)] /// /// use std::ops::{Coroutine, CoroutineState}; /// use std::pin::Pin; /// /// fn main() { -/// let mut coroutine = || { +/// let mut coroutine = #[cfg_attr(not(bootstrap), coroutine)] || { /// yield 1; /// "foo" /// }; diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index efd525aeb3b7..a11c6c742d7d 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -1809,7 +1809,7 @@ impl DispatchFromDyn> for Pin where Ptr: DispatchFromDyn /// fn coroutine_fn() -> impl Coroutine /* not Unpin */ { /// // Allow coroutine to be self-referential (not `Unpin`) /// // vvvvvv so that locals can cross yield points. -/// static || { +/// #[cfg_attr(not(bootstrap), coroutine)] static || { /// let foo = String::from("foo"); /// let foo_ref = &foo; // ------+ /// yield 0; // | <- crosses yield point! diff --git a/src/doc/unstable-book/src/language-features/coroutines.md b/src/doc/unstable-book/src/language-features/coroutines.md index f8e5a22fbd5c..9fb07594650f 100644 --- a/src/doc/unstable-book/src/language-features/coroutines.md +++ b/src/doc/unstable-book/src/language-features/coroutines.md @@ -26,13 +26,13 @@ tweaks to the overall design. A syntactical example of a coroutine is: ```rust -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] use std::ops::{Coroutine, CoroutineState}; use std::pin::Pin; fn main() { - let mut coroutine = || { + let mut coroutine = #[coroutine] || { yield 1; return "foo" }; @@ -48,7 +48,8 @@ fn main() { } ``` -Coroutines are closure-like literals which can contain a `yield` statement. The +Coroutines are closure-like literals which are annotated with `#[coroutine]` +and can contain a `yield` statement. The `yield` statement takes an optional expression of a value to yield out of the coroutine. All coroutine literals implement the `Coroutine` trait in the `std::ops` module. The `Coroutine` trait has one main method, `resume`, which @@ -58,13 +59,13 @@ An example of the control flow of coroutines is that the following example prints all numbers in order: ```rust -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] use std::ops::Coroutine; use std::pin::Pin; fn main() { - let mut coroutine = || { + let mut coroutine = #[coroutine] || { println!("2"); yield; println!("4"); @@ -78,9 +79,9 @@ fn main() { } ``` -At this time the main intended use case of coroutines is an implementation -primitive for async/await syntax, but coroutines will likely be extended to -ergonomic implementations of iterators and other primitives in the future. +At this time the main use case of coroutines is an implementation +primitive for `async`/`await` and `gen` syntax, but coroutines +will likely be extended to other primitives in the future. Feedback on the design and usage is always appreciated! ### The `Coroutine` trait @@ -163,14 +164,14 @@ which point all state is saved off in the coroutine and a value is returned. Let's take a look at an example to see what's going on here: ```rust -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] use std::ops::Coroutine; use std::pin::Pin; fn main() { let ret = "foo"; - let mut coroutine = move || { + let mut coroutine = #[coroutine] move || { yield 1; return ret }; @@ -183,7 +184,7 @@ fn main() { This coroutine literal will compile down to something similar to: ```rust -#![feature(arbitrary_self_types, coroutines, coroutine_trait)] +#![feature(arbitrary_self_types, coroutine_trait)] use std::ops::{Coroutine, CoroutineState}; use std::pin::Pin; diff --git a/src/doc/unstable-book/src/the-unstable-book.md b/src/doc/unstable-book/src/the-unstable-book.md index 0f4fb405669a..63134f7ae28c 100644 --- a/src/doc/unstable-book/src/the-unstable-book.md +++ b/src/doc/unstable-book/src/the-unstable-book.md @@ -5,13 +5,13 @@ each one organized by a "feature flag." That is, when using an unstable feature of Rust, you must use a flag, like this: ```rust -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] use std::ops::{Coroutine, CoroutineState}; use std::pin::Pin; fn main() { - let mut coroutine = || { + let mut coroutine = #[coroutine] || { yield 1; return "foo" }; diff --git a/src/tools/clippy/tests/ui/crashes/ice-5238.rs b/src/tools/clippy/tests/ui/crashes/ice-5238.rs index b1fc3fb9d251..fe03a39ad1ba 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-5238.rs +++ b/src/tools/clippy/tests/ui/crashes/ice-5238.rs @@ -1,9 +1,9 @@ // Regression test for #5238 / https://github.com/rust-lang/rust/pull/69562 -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] fn main() { - let _ = || { + let _ = #[coroutine] || { yield; }; } diff --git a/src/tools/clippy/tests/ui/large_futures.fixed b/src/tools/clippy/tests/ui/large_futures.fixed index aa8c3021b970..1e87859f4526 100644 --- a/src/tools/clippy/tests/ui/large_futures.fixed +++ b/src/tools/clippy/tests/ui/large_futures.fixed @@ -1,4 +1,3 @@ -#![feature(coroutines)] #![warn(clippy::large_futures)] #![allow(clippy::never_loop)] #![allow(clippy::future_not_send)] diff --git a/src/tools/clippy/tests/ui/large_futures.rs b/src/tools/clippy/tests/ui/large_futures.rs index fc6ea458d3db..3f4ea2ebf8bb 100644 --- a/src/tools/clippy/tests/ui/large_futures.rs +++ b/src/tools/clippy/tests/ui/large_futures.rs @@ -1,4 +1,3 @@ -#![feature(coroutines)] #![warn(clippy::large_futures)] #![allow(clippy::never_loop)] #![allow(clippy::future_not_send)] diff --git a/src/tools/clippy/tests/ui/large_futures.stderr b/src/tools/clippy/tests/ui/large_futures.stderr index 5709c7b77a0a..00082e579c59 100644 --- a/src/tools/clippy/tests/ui/large_futures.stderr +++ b/src/tools/clippy/tests/ui/large_futures.stderr @@ -1,5 +1,5 @@ error: large future with a size of 16385 bytes - --> tests/ui/large_futures.rs:11:9 + --> tests/ui/large_futures.rs:10:9 | LL | big_fut([0u8; 1024 * 16]).await; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Box::pin` on it: `Box::pin(big_fut([0u8; 1024 * 16]))` @@ -8,37 +8,37 @@ LL | big_fut([0u8; 1024 * 16]).await; = help: to override `-D warnings` add `#[allow(clippy::large_futures)]` error: large future with a size of 16386 bytes - --> tests/ui/large_futures.rs:15:5 + --> tests/ui/large_futures.rs:14:5 | LL | f.await | ^ help: consider `Box::pin` on it: `Box::pin(f)` error: large future with a size of 16387 bytes - --> tests/ui/large_futures.rs:20:9 + --> tests/ui/large_futures.rs:19:9 | LL | wait().await; | ^^^^^^ help: consider `Box::pin` on it: `Box::pin(wait())` error: large future with a size of 16387 bytes - --> tests/ui/large_futures.rs:25:13 + --> tests/ui/large_futures.rs:24:13 | LL | wait().await; | ^^^^^^ help: consider `Box::pin` on it: `Box::pin(wait())` error: large future with a size of 65540 bytes - --> tests/ui/large_futures.rs:33:5 + --> tests/ui/large_futures.rs:32:5 | LL | foo().await; | ^^^^^ help: consider `Box::pin` on it: `Box::pin(foo())` error: large future with a size of 49159 bytes - --> tests/ui/large_futures.rs:35:5 + --> tests/ui/large_futures.rs:34:5 | LL | calls_fut(fut).await; | ^^^^^^^^^^^^^^ help: consider `Box::pin` on it: `Box::pin(calls_fut(fut))` error: large future with a size of 65540 bytes - --> tests/ui/large_futures.rs:48:5 + --> tests/ui/large_futures.rs:47:5 | LL | / async { LL | | @@ -59,7 +59,7 @@ LL + }) | error: large future with a size of 65540 bytes - --> tests/ui/large_futures.rs:60:13 + --> tests/ui/large_futures.rs:59:13 | LL | / async { LL | | let x = [0i32; 1024 * 16]; diff --git a/src/tools/clippy/tests/ui/redundant_locals.rs b/src/tools/clippy/tests/ui/redundant_locals.rs index f6909828aa9a..e9d77182a919 100644 --- a/src/tools/clippy/tests/ui/redundant_locals.rs +++ b/src/tools/clippy/tests/ui/redundant_locals.rs @@ -1,7 +1,7 @@ //@aux-build:proc_macros.rs #![allow(unused, clippy::no_effect, clippy::needless_pass_by_ref_mut)] #![warn(clippy::redundant_locals)] -#![feature(async_closure, coroutines)] +#![feature(async_closure, coroutines, stmt_expr_attributes)] extern crate proc_macros; use proc_macros::{external, with_span}; @@ -191,11 +191,11 @@ fn issue12225() { let v4 = v4; dbg!(&v4); }); - assert_static(static || { + assert_static(#[coroutine] static || { let v5 = v5; yield; }); - assert_static(|| { + assert_static(#[coroutine] || { let v6 = v6; yield; }); diff --git a/src/tools/miri/tests/fail/coroutine-pinned-moved.rs b/src/tools/miri/tests/fail/coroutine-pinned-moved.rs index 005ae7e91323..8648be2a2641 100644 --- a/src/tools/miri/tests/fail/coroutine-pinned-moved.rs +++ b/src/tools/miri/tests/fail/coroutine-pinned-moved.rs @@ -1,5 +1,5 @@ //@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] use std::{ ops::{Coroutine, CoroutineState}, @@ -7,7 +7,7 @@ use std::{ }; fn firstn() -> impl Coroutine { - static move || { + #[coroutine] static move || { let mut num = 0; let num = &mut num; *num += 0; diff --git a/src/tools/miri/tests/pass/coroutine.rs b/src/tools/miri/tests/pass/coroutine.rs index 7e1f64df04d4..e76abfc4185d 100644 --- a/src/tools/miri/tests/pass/coroutine.rs +++ b/src/tools/miri/tests/pass/coroutine.rs @@ -1,6 +1,6 @@ //@revisions: stack tree //@[tree]compile-flags: -Zmiri-tree-borrows -#![feature(coroutines, coroutine_trait, never_type)] +#![feature(coroutines, coroutine_trait, never_type, stmt_expr_attributes)] use std::fmt::Debug; use std::mem::ManuallyDrop; @@ -43,9 +43,9 @@ fn basic() { panic!() } - finish(1, false, || yield 1); + finish(1, false, #[coroutine] || yield 1); - finish(3, false, || { + finish(3, false, #[coroutine] || { let mut x = 0; yield 1; x += 1; @@ -55,27 +55,27 @@ fn basic() { assert_eq!(x, 2); }); - finish(7 * 8 / 2, false, || { + finish(7 * 8 / 2, false, #[coroutine] || { for i in 0..8 { yield i; } }); - finish(1, false, || { + finish(1, false, #[coroutine] || { if true { yield 1; } else { } }); - finish(1, false, || { + finish(1, false, #[coroutine] || { if false { } else { yield 1; } }); - finish(2, false, || { + finish(2, false, #[coroutine] || { if { yield 1; false @@ -88,7 +88,7 @@ fn basic() { // also test self-referential coroutines assert_eq!( - finish(5, true, static || { + finish(5, true, #[coroutine] static || { let mut x = 5; let y = &mut x; *y = 5; @@ -99,7 +99,7 @@ fn basic() { 10 ); assert_eq!( - finish(5, true, || { + finish(5, true, #[coroutine] || { let mut x = Box::new(5); let y = &mut *x; *y = 5; @@ -111,7 +111,7 @@ fn basic() { ); let b = true; - finish(1, false, || { + finish(1, false, #[coroutine] || { yield 1; if b { return; @@ -123,7 +123,7 @@ fn basic() { drop(x); }); - finish(3, false, || { + finish(3, false, #[coroutine] || { yield 1; #[allow(unreachable_code)] let _x: (String, !) = (String::new(), { @@ -172,7 +172,7 @@ fn smoke_resume_arg() { } drain( - &mut |mut b| { + &mut #[coroutine] |mut b| { while b != 0 { b = yield (b + 1); } @@ -181,21 +181,21 @@ fn smoke_resume_arg() { vec![(1, Yielded(2)), (-45, Yielded(-44)), (500, Yielded(501)), (0, Complete(-1))], ); - expect_drops(2, || drain(&mut |a| yield a, vec![(DropMe, Yielded(DropMe))])); + expect_drops(2, || drain(&mut #[coroutine] |a| yield a, vec![(DropMe, Yielded(DropMe))])); expect_drops(6, || { drain( - &mut |a| yield yield a, + &mut #[coroutine] |a| yield yield a, vec![(DropMe, Yielded(DropMe)), (DropMe, Yielded(DropMe)), (DropMe, Complete(DropMe))], ) }); #[allow(unreachable_code)] - expect_drops(2, || drain(&mut |a| yield return a, vec![(DropMe, Complete(DropMe))])); + expect_drops(2, || drain(&mut #[coroutine] |a| yield return a, vec![(DropMe, Complete(DropMe))])); expect_drops(2, || { drain( - &mut |a: DropMe| { + &mut #[coroutine] |a: DropMe| { if false { yield () } else { a } }, vec![(DropMe, Complete(DropMe))], @@ -205,7 +205,7 @@ fn smoke_resume_arg() { expect_drops(4, || { drain( #[allow(unused_assignments, unused_variables)] - &mut |mut a: DropMe| { + &mut #[coroutine] |mut a: DropMe| { a = yield; a = yield; a = yield; @@ -228,7 +228,7 @@ fn uninit_fields() { } fn run(x: bool, y: bool) { - let mut c = || { + let mut c = #[coroutine] || { if x { let _a: T; if y { diff --git a/src/tools/miri/tests/pass/stacked-borrows/coroutine-self-referential.rs b/src/tools/miri/tests/pass/stacked-borrows/coroutine-self-referential.rs index c4b15c8758be..bb98e024a0a1 100644 --- a/src/tools/miri/tests/pass/stacked-borrows/coroutine-self-referential.rs +++ b/src/tools/miri/tests/pass/stacked-borrows/coroutine-self-referential.rs @@ -1,6 +1,6 @@ // See https://github.com/rust-lang/unsafe-code-guidelines/issues/148: // this fails when Stacked Borrows is strictly applied even to `!Unpin` types. -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] use std::{ ops::{Coroutine, CoroutineState}, @@ -8,7 +8,7 @@ use std::{ }; fn firstn() -> impl Coroutine { - static move || { + #[coroutine] static move || { let mut num = 0; let num = &mut num; diff --git a/src/tools/miri/tests/pass/track-caller-attribute.rs b/src/tools/miri/tests/pass/track-caller-attribute.rs index d88bcc98858f..c3803af3cc8e 100644 --- a/src/tools/miri/tests/pass/track-caller-attribute.rs +++ b/src/tools/miri/tests/pass/track-caller-attribute.rs @@ -232,7 +232,7 @@ fn test_coroutine() { } #[rustfmt::skip] - let coroutine = #[track_caller] |arg: String| { + let coroutine = #[track_caller] #[coroutine] |arg: String| { yield ("first", arg.clone(), Location::caller()); yield ("second", arg.clone(), Location::caller()); }; @@ -255,7 +255,7 @@ fn test_coroutine() { assert_eq!(mono_loc.column(), 42); #[rustfmt::skip] - let non_tracked_coroutine = || { yield Location::caller(); }; + let non_tracked_coroutine = #[coroutine] || { yield Location::caller(); }; let non_tracked_line = line!() - 1; // This is the line of the coroutine, not its caller let non_tracked_loc = match Box::pin(non_tracked_coroutine).as_mut().resume(()) { CoroutineState::Yielded(val) => val, @@ -263,7 +263,7 @@ fn test_coroutine() { }; assert_eq!(non_tracked_loc.file(), file!()); assert_eq!(non_tracked_loc.line(), non_tracked_line); - assert_eq!(non_tracked_loc.column(), 44); + assert_eq!(non_tracked_loc.column(), 57); } fn main() { diff --git a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs index d50088e6cf1d..c92d4e78ffa7 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs @@ -3869,7 +3869,7 @@ use std::ops::{Coroutine, CoroutineState}; use std::pin::Pin; fn main() { - let mut coroutine = || { + let mut coroutine = #[coroutine] || { yield 1; return "foo" }; @@ -3901,7 +3901,7 @@ use std::ops::Coroutine; use std::pin::Pin; fn main() { - let mut coroutine = || { + let mut coroutine = #[coroutine] || { println!("2"); yield; println!("4"); @@ -4007,7 +4007,7 @@ use std::pin::Pin; fn main() { let ret = "foo"; - let mut coroutine = move || { + let mut coroutine = #[coroutine] move || { yield 1; return ret }; diff --git a/src/tools/rustfmt/tests/source/immovable_coroutines.rs b/src/tools/rustfmt/tests/source/immovable_coroutines.rs index 3b94af0c96ce..539049577a00 100644 --- a/src/tools/rustfmt/tests/source/immovable_coroutines.rs +++ b/src/tools/rustfmt/tests/source/immovable_coroutines.rs @@ -1,7 +1,8 @@ #![feature(coroutines)] unsafe fn foo() { - let mut ga = static || { + let mut ga = #[coroutine] + static || { yield 1; }; } diff --git a/src/tools/rustfmt/tests/target/immovable_coroutines.rs b/src/tools/rustfmt/tests/target/immovable_coroutines.rs index f52cfa00f978..539049577a00 100644 --- a/src/tools/rustfmt/tests/target/immovable_coroutines.rs +++ b/src/tools/rustfmt/tests/target/immovable_coroutines.rs @@ -1,7 +1,8 @@ #![feature(coroutines)] unsafe fn foo() { - let mut ga = static || { + let mut ga = #[coroutine] + static || { yield 1; }; } diff --git a/tests/codegen/coroutine-debug-msvc.rs b/tests/codegen/coroutine-debug-msvc.rs index fb1b46fe497f..e2296db1d594 100644 --- a/tests/codegen/coroutine-debug-msvc.rs +++ b/tests/codegen/coroutine-debug-msvc.rs @@ -11,7 +11,7 @@ use std::ops::Coroutine; fn coroutine_test() -> impl Coroutine { - || { + #[coroutine] || { yield 0; let s = String::from("foo"); yield 1; diff --git a/tests/codegen/coroutine-debug.rs b/tests/codegen/coroutine-debug.rs index 7eaee669559e..914515f58b85 100644 --- a/tests/codegen/coroutine-debug.rs +++ b/tests/codegen/coroutine-debug.rs @@ -11,7 +11,7 @@ use std::ops::Coroutine; fn coroutine_test() -> impl Coroutine { - || { + #[coroutine] || { yield 0; let s = String::from("foo"); yield 1; diff --git a/tests/coverage/coroutine.cov-map b/tests/coverage/coroutine.cov-map index ef9faab590b3..255708d365ee 100644 --- a/tests/coverage/coroutine.cov-map +++ b/tests/coverage/coroutine.cov-map @@ -43,11 +43,11 @@ Number of file 0 mappings: 9 = ((c4 - c5) - c6) Function name: coroutine::main::{closure#0} -Raw bytes (14): 0x[01, 01, 00, 02, 01, 15, 1c, 01, 1f, 05, 02, 10, 01, 06] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 15, 29, 01, 1f, 05, 02, 10, 01, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 21, 28) to (start + 1, 31) +- Code(Counter(0)) at (prev + 21, 41) to (start + 1, 31) - Code(Counter(1)) at (prev + 2, 16) to (start + 1, 6) diff --git a/tests/coverage/coroutine.coverage b/tests/coverage/coroutine.coverage index bd3d4e468801..68b52d198316 100644 --- a/tests/coverage/coroutine.coverage +++ b/tests/coverage/coroutine.coverage @@ -1,4 +1,4 @@ - LL| |#![feature(coroutines, coroutine_trait)] + LL| |#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] LL| | LL| |use std::ops::{Coroutine, CoroutineState}; LL| |use std::pin::Pin; @@ -18,7 +18,7 @@ LL| | LL| 1|fn main() { LL| 1| let is_true = std::env::args().len() == 1; - LL| 1| let mut coroutine = || { + LL| 1| let mut coroutine = #[coroutine] || { LL| 1| yield get_u32(is_true); LL| 1| return "foo"; LL| 1| }; diff --git a/tests/coverage/coroutine.rs b/tests/coverage/coroutine.rs index 2aa689466fc3..7f72e0d8bd42 100644 --- a/tests/coverage/coroutine.rs +++ b/tests/coverage/coroutine.rs @@ -1,4 +1,4 @@ -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] use std::ops::{Coroutine, CoroutineState}; use std::pin::Pin; @@ -18,7 +18,7 @@ fn get_u32(val: bool) -> Result { fn main() { let is_true = std::env::args().len() == 1; - let mut coroutine = || { + let mut coroutine = #[coroutine] || { yield get_u32(is_true); return "foo"; }; diff --git a/tests/coverage/yield.cov-map b/tests/coverage/yield.cov-map index 9cc67dfe88ac..0347aaaa3676 100644 --- a/tests/coverage/yield.cov-map +++ b/tests/coverage/yield.cov-map @@ -41,21 +41,21 @@ Number of file 0 mappings: 16 - Code(Counter(11)) at (prev + 2, 1) to (start + 0, 2) Function name: yield::main::{closure#0} -Raw bytes (14): 0x[01, 01, 00, 02, 01, 08, 1c, 01, 10, 05, 02, 10, 01, 06] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 08, 29, 01, 10, 05, 02, 10, 01, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 8, 28) to (start + 1, 16) +- Code(Counter(0)) at (prev + 8, 41) to (start + 1, 16) - Code(Counter(1)) at (prev + 2, 16) to (start + 1, 6) Function name: yield::main::{closure#1} -Raw bytes (24): 0x[01, 01, 00, 04, 01, 16, 1c, 01, 10, 05, 02, 09, 00, 10, 09, 01, 09, 00, 10, 0d, 01, 10, 01, 06] +Raw bytes (24): 0x[01, 01, 00, 04, 01, 16, 29, 01, 10, 05, 02, 09, 00, 10, 09, 01, 09, 00, 10, 0d, 01, 10, 01, 06] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 22, 28) to (start + 1, 16) +- Code(Counter(0)) at (prev + 22, 41) to (start + 1, 16) - Code(Counter(1)) at (prev + 2, 9) to (start + 0, 16) - Code(Counter(2)) at (prev + 1, 9) to (start + 0, 16) - Code(Counter(3)) at (prev + 1, 16) to (start + 1, 6) diff --git a/tests/coverage/yield.coverage b/tests/coverage/yield.coverage index d7e455f211e4..e2fc9196d244 100644 --- a/tests/coverage/yield.coverage +++ b/tests/coverage/yield.coverage @@ -1,11 +1,11 @@ - LL| |#![feature(coroutines, coroutine_trait)] + LL| |#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] LL| |#![allow(unused_assignments)] LL| | LL| |use std::ops::{Coroutine, CoroutineState}; LL| |use std::pin::Pin; LL| | LL| 1|fn main() { - LL| 1| let mut coroutine = || { + LL| 1| let mut coroutine = #[coroutine] || { LL| 1| yield 1; LL| 1| return "foo"; LL| 1| }; @@ -19,7 +19,7 @@ LL| 0| _ => panic!("unexpected value from resume"), LL| | } LL| | - LL| 1| let mut coroutine = || { + LL| 1| let mut coroutine = #[coroutine] || { LL| 1| yield 1; LL| 1| yield 2; LL| 0| yield 3; diff --git a/tests/coverage/yield.rs b/tests/coverage/yield.rs index b7e2ba31b59c..64ea27066047 100644 --- a/tests/coverage/yield.rs +++ b/tests/coverage/yield.rs @@ -1,11 +1,11 @@ -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] #![allow(unused_assignments)] use std::ops::{Coroutine, CoroutineState}; use std::pin::Pin; fn main() { - let mut coroutine = || { + let mut coroutine = #[coroutine] || { yield 1; return "foo"; }; @@ -19,7 +19,7 @@ fn main() { _ => panic!("unexpected value from resume"), } - let mut coroutine = || { + let mut coroutine = #[coroutine] || { yield 1; yield 2; yield 3; diff --git a/tests/debuginfo/coroutine-locals.rs b/tests/debuginfo/coroutine-locals.rs index 54b5cd577c8b..c019998040b9 100644 --- a/tests/debuginfo/coroutine-locals.rs +++ b/tests/debuginfo/coroutine-locals.rs @@ -46,7 +46,7 @@ // lldb-command:v c // lldb-check:(int) c = 6 -#![feature(omit_gdb_pretty_printer_section, coroutines, coroutine_trait)] +#![feature(omit_gdb_pretty_printer_section, coroutines, coroutine_trait, stmt_expr_attributes)] #![omit_gdb_pretty_printer_section] use std::ops::Coroutine; @@ -54,7 +54,8 @@ use std::pin::Pin; fn main() { let mut a = 5; - let mut b = || { + let mut b = #[coroutine] + || { let c = 6; // Live across multiple yield points let d = 7; // Live across only one yield point @@ -76,4 +77,6 @@ fn main() { _zzz(); // #break } -fn _zzz() {()} +fn _zzz() { + () +} diff --git a/tests/debuginfo/coroutine-objects.rs b/tests/debuginfo/coroutine-objects.rs index 9e1bd5d62e7a..e13f20455a86 100644 --- a/tests/debuginfo/coroutine-objects.rs +++ b/tests/debuginfo/coroutine-objects.rs @@ -63,7 +63,7 @@ // cdb-check: b : Returned [Type: enum2$] // cdb-check: [+0x[...]] _ref__a : 0x[...] : 6 [Type: int *] -#![feature(omit_gdb_pretty_printer_section, coroutines, coroutine_trait)] +#![feature(omit_gdb_pretty_printer_section, coroutines, coroutine_trait, stmt_expr_attributes)] #![omit_gdb_pretty_printer_section] use std::ops::Coroutine; @@ -71,7 +71,8 @@ use std::pin::Pin; fn main() { let mut a = 5; - let mut b = || { + let mut b = #[coroutine] + || { let mut c = 6; let mut d = 7; diff --git a/tests/debuginfo/function-names.rs b/tests/debuginfo/function-names.rs index 1e4be4324455..2b0c2593676b 100644 --- a/tests/debuginfo/function-names.rs +++ b/tests/debuginfo/function-names.rs @@ -83,7 +83,7 @@ #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] #![omit_gdb_pretty_printer_section] -#![feature(adt_const_params, coroutines, coroutine_trait)] +#![feature(adt_const_params, coroutines, coroutine_trait, stmt_expr_attributes)] #![allow(incomplete_features)] use std::ops::Coroutine; @@ -111,7 +111,8 @@ fn main() { closure(); // Coroutine - let mut coroutine = || { + let mut coroutine = #[coroutine] + || { yield; return; }; diff --git a/tests/debuginfo/issue-57822.rs b/tests/debuginfo/issue-57822.rs index 93e1a2558f69..995779a6a9ca 100644 --- a/tests/debuginfo/issue-57822.rs +++ b/tests/debuginfo/issue-57822.rs @@ -26,7 +26,7 @@ // lldb-command:v b // lldbg-check:(issue_57822::main::{coroutine_env#3}) b = -#![feature(omit_gdb_pretty_printer_section, coroutines, coroutine_trait)] +#![feature(omit_gdb_pretty_printer_section, coroutines, coroutine_trait, stmt_expr_attributes)] #![omit_gdb_pretty_printer_section] use std::ops::Coroutine; @@ -38,11 +38,13 @@ fn main() { let g = move || f(); let mut y = 2; - let mut a = move || { + let mut a = #[coroutine] + move || { y += 1; yield; }; - let mut b = move || { + let mut b = #[coroutine] + move || { Pin::new(&mut a).resume(()); yield; }; diff --git a/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-abort.mir b/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-abort.mir index 7214b01c6016..7e033916fd34 100644 --- a/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-abort.mir +++ b/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-abort.mir @@ -1,6 +1,6 @@ // MIR for `main::{closure#0}` 0 coroutine_drop -fn main::{closure#0}(_1: *mut {coroutine@$DIR/coroutine_drop_cleanup.rs:11:15: 11:17}) -> () { +fn main::{closure#0}(_1: *mut {coroutine@$DIR/coroutine_drop_cleanup.rs:12:5: 12:7}) -> () { let mut _0: (); let mut _2: (); let _3: std::string::String; diff --git a/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-unwind.mir b/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-unwind.mir index 00769a493b5a..613ef2909b5e 100644 --- a/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-unwind.mir +++ b/tests/mir-opt/coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.panic-unwind.mir @@ -1,6 +1,6 @@ // MIR for `main::{closure#0}` 0 coroutine_drop -fn main::{closure#0}(_1: *mut {coroutine@$DIR/coroutine_drop_cleanup.rs:11:15: 11:17}) -> () { +fn main::{closure#0}(_1: *mut {coroutine@$DIR/coroutine_drop_cleanup.rs:12:5: 12:7}) -> () { let mut _0: (); let mut _2: (); let _3: std::string::String; diff --git a/tests/mir-opt/coroutine_drop_cleanup.rs b/tests/mir-opt/coroutine_drop_cleanup.rs index 69984c737fed..33fdd2dd0d9c 100644 --- a/tests/mir-opt/coroutine_drop_cleanup.rs +++ b/tests/mir-opt/coroutine_drop_cleanup.rs @@ -1,5 +1,5 @@ // skip-filecheck -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] // EMIT_MIR_FOR_EACH_PANIC_STRATEGY @@ -8,7 +8,8 @@ // EMIT_MIR coroutine_drop_cleanup.main-{closure#0}.coroutine_drop.0.mir fn main() { - let gen = || { + let gen = #[coroutine] + || { let _s = String::new(); yield; }; diff --git a/tests/mir-opt/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-abort.mir b/tests/mir-opt/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-abort.mir index 8369a3e60dd9..4731aed335d9 100644 --- a/tests/mir-opt/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-abort.mir +++ b/tests/mir-opt/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-abort.mir @@ -1,6 +1,6 @@ // MIR for `main::{closure#0}` before StateTransform -fn main::{closure#0}(_1: {coroutine@$DIR/coroutine_storage_dead_unwind.rs:23:16: 23:18}, _2: ()) -> () +fn main::{closure#0}(_1: {coroutine@$DIR/coroutine_storage_dead_unwind.rs:24:5: 24:7}, _2: ()) -> () yields () { let mut _0: (); diff --git a/tests/mir-opt/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-unwind.mir b/tests/mir-opt/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-unwind.mir index 1773db1abffe..14e1782b8601 100644 --- a/tests/mir-opt/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-unwind.mir +++ b/tests/mir-opt/coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.panic-unwind.mir @@ -1,6 +1,6 @@ // MIR for `main::{closure#0}` before StateTransform -fn main::{closure#0}(_1: {coroutine@$DIR/coroutine_storage_dead_unwind.rs:23:16: 23:18}, _2: ()) -> () +fn main::{closure#0}(_1: {coroutine@$DIR/coroutine_storage_dead_unwind.rs:24:5: 24:7}, _2: ()) -> () yields () { let mut _0: (); diff --git a/tests/mir-opt/coroutine_storage_dead_unwind.rs b/tests/mir-opt/coroutine_storage_dead_unwind.rs index 253be1ff698d..ce9bad483af8 100644 --- a/tests/mir-opt/coroutine_storage_dead_unwind.rs +++ b/tests/mir-opt/coroutine_storage_dead_unwind.rs @@ -6,7 +6,7 @@ // Basic block and local names can safely change, but the StorageDead statements // should not go away. -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] struct Foo(i32); @@ -20,7 +20,8 @@ fn take(_x: T) {} // EMIT_MIR coroutine_storage_dead_unwind.main-{closure#0}.StateTransform.before.mir fn main() { - let _gen = || { + let _gen = #[coroutine] + || { let a = Foo(5); let b = Bar(6); yield; diff --git a/tests/mir-opt/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir index 165aa3a05cb7..f8b3f68d21e6 100644 --- a/tests/mir-opt/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir +++ b/tests/mir-opt/coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir @@ -4,7 +4,7 @@ _0: CoroutineSavedTy { ty: HasDrop, source_info: SourceInfo { - span: $DIR/coroutine_tiny.rs:21:13: 21:15 (#0), + span: $DIR/coroutine_tiny.rs:22:13: 22:15 (#0), scope: scope[0], }, ignore_for_traits: false, @@ -21,7 +21,7 @@ }, } */ -fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine_tiny.rs:20:16: 20:24}>, _2: u8) -> CoroutineState<(), ()> { +fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13}>, _2: u8) -> CoroutineState<(), ()> { debug _x => _10; let mut _0: std::ops::CoroutineState<(), ()>; let _3: HasDrop; @@ -34,18 +34,18 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine_tiny.rs:20:16: 20:24 let _10: u8; let mut _11: u32; scope 1 { - debug _d => (((*(_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:20:16: 20:24})) as variant#3).0: HasDrop); + debug _d => (((*(_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13})) as variant#3).0: HasDrop); } bb0: { - _11 = discriminant((*(_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:20:16: 20:24}))); + _11 = discriminant((*(_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13}))); switchInt(move _11) -> [0: bb1, 3: bb5, otherwise: bb6]; } bb1: { _10 = move _2; nop; - (((*(_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:20:16: 20:24})) as variant#3).0: HasDrop) = HasDrop; + (((*(_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13})) as variant#3).0: HasDrop) = HasDrop; StorageLive(_4); goto -> bb2; } @@ -58,7 +58,7 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine_tiny.rs:20:16: 20:24 StorageDead(_4); StorageDead(_6); StorageDead(_7); - discriminant((*(_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:20:16: 20:24}))) = 3; + discriminant((*(_1.0: &mut {coroutine@$DIR/coroutine_tiny.rs:21:5: 21:13}))) = 3; return; } diff --git a/tests/mir-opt/coroutine_tiny.rs b/tests/mir-opt/coroutine_tiny.rs index 9728425f2326..81e9940541ba 100644 --- a/tests/mir-opt/coroutine_tiny.rs +++ b/tests/mir-opt/coroutine_tiny.rs @@ -5,7 +5,7 @@ //@ compile-flags: -C panic=abort //@ no-prefer-dynamic -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] struct HasDrop; @@ -17,7 +17,8 @@ fn callee() {} // EMIT_MIR coroutine_tiny.main-{closure#0}.coroutine_resume.0.mir fn main() { - let _gen = |_x: u8| { + let _gen = #[coroutine] + |_x: u8| { let _d = HasDrop; loop { yield; diff --git a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff index 859082c31119..07031a298bc3 100644 --- a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff @@ -4,24 +4,24 @@ fn main() -> () { let mut _0: (); let _1: std::ops::CoroutineState; - let mut _2: std::pin::Pin<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}>; - let mut _3: &mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}; - let mut _4: {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}; + let mut _2: std::pin::Pin<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}>; + let mut _3: &mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}; + let mut _4: {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}; + let mut _5: bool; scope 1 { debug _r => _1; } + scope 2 (inlined g) { + } -+ scope 3 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}>::new) { ++ scope 3 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}>::new) { + debug pointer => _3; -+ scope 4 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}>::new_unchecked) { ++ scope 4 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}>::new_unchecked) { + debug pointer => _3; + } + } + scope 5 (inlined g::{closure#0}) { + debug a => _5; -+ let mut _6: &mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}; ++ let mut _6: &mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}; + let mut _7: u32; + let mut _8: i32; + } @@ -32,22 +32,22 @@ StorageLive(_3); StorageLive(_4); - _4 = g() -> [return: bb1, unwind unreachable]; -+ _4 = {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8 (#0)}; ++ _4 = {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8 (#0)}; + _3 = &mut _4; -+ _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}> { __pointer: _3 }; ++ _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}> { __pointer: _3 }; + StorageDead(_3); + StorageLive(_5); + _5 = const false; + StorageLive(_6); + StorageLive(_7); -+ _6 = (_2.0: &mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}); ++ _6 = (_2.0: &mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}); + _7 = discriminant((*_6)); + switchInt(move _7) -> [0: bb3, 1: bb7, 3: bb8, otherwise: bb9]; } bb1: { - _3 = &mut _4; -- _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}>::new(move _3) -> [return: bb2, unwind unreachable]; +- _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}>::new(move _3) -> [return: bb2, unwind unreachable]; + StorageDead(_4); + _0 = const (); + StorageDead(_1); @@ -56,7 +56,7 @@ bb2: { - StorageDead(_3); -- _1 = <{coroutine@$DIR/inline_coroutine.rs:19:5: 19:8} as Coroutine>::resume(move _2, const false) -> [return: bb3, unwind unreachable]; +- _1 = <{coroutine@$DIR/inline_coroutine.rs:20:5: 20:8} as Coroutine>::resume(move _2, const false) -> [return: bb3, unwind unreachable]; + StorageDead(_7); + StorageDead(_6); + StorageDead(_5); diff --git a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff index 44b06c34972a..ab6c62b0baf5 100644 --- a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff @@ -4,24 +4,24 @@ fn main() -> () { let mut _0: (); let _1: std::ops::CoroutineState; - let mut _2: std::pin::Pin<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}>; - let mut _3: &mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}; - let mut _4: {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}; + let mut _2: std::pin::Pin<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}>; + let mut _3: &mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}; + let mut _4: {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}; + let mut _5: bool; scope 1 { debug _r => _1; } + scope 2 (inlined g) { + } -+ scope 3 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}>::new) { ++ scope 3 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}>::new) { + debug pointer => _3; -+ scope 4 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}>::new_unchecked) { ++ scope 4 (inlined Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}>::new_unchecked) { + debug pointer => _3; + } + } + scope 5 (inlined g::{closure#0}) { + debug a => _5; -+ let mut _6: &mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}; ++ let mut _6: &mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}; + let mut _7: u32; + let mut _8: i32; + } @@ -32,22 +32,22 @@ StorageLive(_3); StorageLive(_4); - _4 = g() -> [return: bb1, unwind continue]; -+ _4 = {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8 (#0)}; ++ _4 = {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8 (#0)}; + _3 = &mut _4; -+ _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}> { __pointer: _3 }; ++ _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}> { __pointer: _3 }; + StorageDead(_3); + StorageLive(_5); + _5 = const false; + StorageLive(_6); + StorageLive(_7); -+ _6 = (_2.0: &mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}); ++ _6 = (_2.0: &mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}); + _7 = discriminant((*_6)); + switchInt(move _7) -> [0: bb5, 1: bb9, 3: bb10, otherwise: bb11]; } bb1: { - _3 = &mut _4; -- _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}>::new(move _3) -> [return: bb2, unwind: bb5]; +- _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}>::new(move _3) -> [return: bb2, unwind: bb5]; + StorageDead(_4); + _0 = const (); + StorageDead(_1); @@ -56,7 +56,7 @@ - bb2: { - StorageDead(_3); -- _1 = <{coroutine@$DIR/inline_coroutine.rs:19:5: 19:8} as Coroutine>::resume(move _2, const false) -> [return: bb3, unwind: bb5]; +- _1 = <{coroutine@$DIR/inline_coroutine.rs:20:5: 20:8} as Coroutine>::resume(move _2, const false) -> [return: bb3, unwind: bb5]; + bb2 (cleanup): { + drop(_4) -> [return: bb3, unwind terminate(cleanup)]; } diff --git a/tests/mir-opt/inline/inline_coroutine.rs b/tests/mir-opt/inline/inline_coroutine.rs index 180f9d4a6fdd..07f8fb20f7ea 100644 --- a/tests/mir-opt/inline/inline_coroutine.rs +++ b/tests/mir-opt/inline/inline_coroutine.rs @@ -16,5 +16,6 @@ fn main() { #[inline] pub fn g() -> impl Coroutine { #[inline] - |a| { yield if a { 7 } else { 13 } } + #[coroutine] + |a| yield if a { 7 } else { 13 } } diff --git a/tests/ui/async-await/async-outside-of-await-issue-121096.stderr b/tests/ui/async-await/async-outside-of-await-issue-121096.stderr index b0677a83864e..d7caf6b3c0d2 100644 --- a/tests/ui/async-await/async-outside-of-await-issue-121096.stderr +++ b/tests/ui/async-await/async-outside-of-await-issue-121096.stderr @@ -2,7 +2,7 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks --> $DIR/async-outside-of-await-issue-121096.rs:7:7 | LL | fn main() { - | ---- this is not `async` + | --------- this is not `async` ... LL | }.await | ^^^^^ only allowed inside `async` functions and blocks diff --git a/tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr b/tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr index 928eb0b821db..a98bb0764c0e 100644 --- a/tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr +++ b/tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr @@ -141,7 +141,7 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks --> $DIR/incorrect-syntax-suggestions.rs:68:19 | LL | fn foo13() -> Result<(), ()> { - | ----- this is not `async` + | ---------------------------- this is not `async` LL | let _ = bar().await(); | ^^^^^ only allowed inside `async` functions and blocks @@ -149,7 +149,7 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks --> $DIR/incorrect-syntax-suggestions.rs:73:19 | LL | fn foo14() -> Result<(), ()> { - | ----- this is not `async` + | ---------------------------- this is not `async` LL | let _ = bar().await()?; | ^^^^^ only allowed inside `async` functions and blocks @@ -157,7 +157,7 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks --> $DIR/incorrect-syntax-suggestions.rs:78:19 | LL | fn foo15() -> Result<(), ()> { - | ----- this is not `async` + | ---------------------------- this is not `async` LL | let _ = bar().await; | ^^^^^ only allowed inside `async` functions and blocks @@ -165,7 +165,7 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks --> $DIR/incorrect-syntax-suggestions.rs:82:19 | LL | fn foo16() -> Result<(), ()> { - | ----- this is not `async` + | ---------------------------- this is not `async` LL | let _ = bar().await?; | ^^^^^ only allowed inside `async` functions and blocks @@ -173,7 +173,7 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks --> $DIR/incorrect-syntax-suggestions.rs:87:23 | LL | fn foo() -> Result<(), ()> { - | --- this is not `async` + | -------------------------- this is not `async` LL | let _ = bar().await?; | ^^^^^ only allowed inside `async` functions and blocks diff --git a/tests/ui/async-await/coroutine-not-future.rs b/tests/ui/async-await/coroutine-not-future.rs index 2993f58378a4..452274355078 100644 --- a/tests/ui/async-await/coroutine-not-future.rs +++ b/tests/ui/async-await/coroutine-not-future.rs @@ -1,5 +1,5 @@ //@ edition:2018 -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] use std::future::Future; use std::ops::Coroutine; @@ -9,6 +9,7 @@ fn returns_async_block() -> impl Future { async {} } fn returns_coroutine() -> impl Coroutine<(), Yield = (), Return = ()> { + #[coroutine] || { let _: () = yield (); } @@ -23,9 +24,12 @@ fn main() { takes_future(returns_async_block()); takes_future(async {}); takes_coroutine(returns_coroutine()); - takes_coroutine(|| { - let _: () = yield (); - }); + takes_coroutine( + #[coroutine] + || { + let _: () = yield (); + }, + ); // async futures are not coroutines: takes_coroutine(async_fn()); @@ -38,8 +42,11 @@ fn main() { // coroutines are not futures: takes_future(returns_coroutine()); //~^ ERROR is not a future - takes_future(|ctx| { - //~^ ERROR is not a future - ctx = yield (); - }); + takes_future( + #[coroutine] + |ctx| { + //~^ ERROR is not a future + ctx = yield (); + }, + ); } diff --git a/tests/ui/async-await/coroutine-not-future.stderr b/tests/ui/async-await/coroutine-not-future.stderr index 580217fb4f82..403e547a7538 100644 --- a/tests/ui/async-await/coroutine-not-future.stderr +++ b/tests/ui/async-await/coroutine-not-future.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `impl Future: Coroutine<_>` is not satisfied - --> $DIR/coroutine-not-future.rs:31:21 + --> $DIR/coroutine-not-future.rs:35:21 | LL | takes_coroutine(async_fn()); | --------------- ^^^^^^^^^^ the trait `Coroutine<_>` is not implemented for `impl Future` @@ -7,13 +7,13 @@ LL | takes_coroutine(async_fn()); | required by a bound introduced by this call | note: required by a bound in `takes_coroutine` - --> $DIR/coroutine-not-future.rs:18:39 + --> $DIR/coroutine-not-future.rs:19:39 | LL | fn takes_coroutine(_g: impl Coroutine) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_coroutine` error[E0277]: the trait bound `impl Future: Coroutine<_>` is not satisfied - --> $DIR/coroutine-not-future.rs:33:21 + --> $DIR/coroutine-not-future.rs:37:21 | LL | takes_coroutine(returns_async_block()); | --------------- ^^^^^^^^^^^^^^^^^^^^^ the trait `Coroutine<_>` is not implemented for `impl Future` @@ -21,27 +21,27 @@ LL | takes_coroutine(returns_async_block()); | required by a bound introduced by this call | note: required by a bound in `takes_coroutine` - --> $DIR/coroutine-not-future.rs:18:39 + --> $DIR/coroutine-not-future.rs:19:39 | LL | fn takes_coroutine(_g: impl Coroutine) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_coroutine` -error[E0277]: the trait bound `{async block@$DIR/coroutine-not-future.rs:35:21: 35:29}: Coroutine<_>` is not satisfied - --> $DIR/coroutine-not-future.rs:35:21 +error[E0277]: the trait bound `{async block@$DIR/coroutine-not-future.rs:39:21: 39:29}: Coroutine<_>` is not satisfied + --> $DIR/coroutine-not-future.rs:39:21 | LL | takes_coroutine(async {}); - | --------------- ^^^^^^^^ the trait `Coroutine<_>` is not implemented for `{async block@$DIR/coroutine-not-future.rs:35:21: 35:29}` + | --------------- ^^^^^^^^ the trait `Coroutine<_>` is not implemented for `{async block@$DIR/coroutine-not-future.rs:39:21: 39:29}` | | | required by a bound introduced by this call | note: required by a bound in `takes_coroutine` - --> $DIR/coroutine-not-future.rs:18:39 + --> $DIR/coroutine-not-future.rs:19:39 | LL | fn takes_coroutine(_g: impl Coroutine) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_coroutine` error[E0277]: `impl Coroutine` is not a future - --> $DIR/coroutine-not-future.rs:39:18 + --> $DIR/coroutine-not-future.rs:43:18 | LL | takes_future(returns_coroutine()); | ------------ ^^^^^^^^^^^^^^^^^^^ `impl Coroutine` is not a future @@ -50,26 +50,26 @@ LL | takes_future(returns_coroutine()); | = help: the trait `Future` is not implemented for `impl Coroutine` note: required by a bound in `takes_future` - --> $DIR/coroutine-not-future.rs:17:26 + --> $DIR/coroutine-not-future.rs:18:26 | LL | fn takes_future(_f: impl Future) {} | ^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_future` -error[E0277]: `{coroutine@$DIR/coroutine-not-future.rs:41:18: 41:23}` is not a future - --> $DIR/coroutine-not-future.rs:41:18 +error[E0277]: `{coroutine@$DIR/coroutine-not-future.rs:47:9: 47:14}` is not a future + --> $DIR/coroutine-not-future.rs:47:9 | -LL | takes_future(|ctx| { - | _____------------_^ - | | | - | | required by a bound introduced by this call +LL | takes_future( + | ------------ required by a bound introduced by this call +LL | #[coroutine] +LL | / |ctx| { LL | | -LL | | ctx = yield (); -LL | | }); - | |_____^ `{coroutine@$DIR/coroutine-not-future.rs:41:18: 41:23}` is not a future +LL | | ctx = yield (); +LL | | }, + | |_________^ `{coroutine@$DIR/coroutine-not-future.rs:47:9: 47:14}` is not a future | - = help: the trait `Future` is not implemented for `{coroutine@$DIR/coroutine-not-future.rs:41:18: 41:23}` + = help: the trait `Future` is not implemented for `{coroutine@$DIR/coroutine-not-future.rs:47:9: 47:14}` note: required by a bound in `takes_future` - --> $DIR/coroutine-not-future.rs:17:26 + --> $DIR/coroutine-not-future.rs:18:26 | LL | fn takes_future(_f: impl Future) {} | ^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_future` diff --git a/tests/ui/async-await/issues/issue-51751.stderr b/tests/ui/async-await/issues/issue-51751.stderr index ba256b19948c..ab12e0427b47 100644 --- a/tests/ui/async-await/issues/issue-51751.stderr +++ b/tests/ui/async-await/issues/issue-51751.stderr @@ -2,7 +2,7 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks --> $DIR/issue-51751.rs:9:27 | LL | fn main() { - | ---- this is not `async` + | --------- this is not `async` LL | let result = inc(10000); LL | let finished = result.await; | ^^^^^ only allowed inside `async` functions and blocks diff --git a/tests/ui/async-await/issues/issue-62009-1.stderr b/tests/ui/async-await/issues/issue-62009-1.stderr index 02933f4f2f23..f8a4b5d9af8b 100644 --- a/tests/ui/async-await/issues/issue-62009-1.stderr +++ b/tests/ui/async-await/issues/issue-62009-1.stderr @@ -2,7 +2,7 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks --> $DIR/issue-62009-1.rs:6:23 | LL | fn main() { - | ---- this is not `async` + | --------- this is not `async` LL | async { let (); }.await; | ^^^^^ only allowed inside `async` functions and blocks @@ -10,7 +10,7 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks --> $DIR/issue-62009-1.rs:10:7 | LL | fn main() { - | ---- this is not `async` + | --------- this is not `async` ... LL | }.await; | ^^^^^ only allowed inside `async` functions and blocks @@ -19,7 +19,7 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks --> $DIR/issue-62009-1.rs:12:16 | LL | fn main() { - | ---- this is not `async` + | --------- this is not `async` ... LL | (|_| 2333).await; | ^^^^^ only allowed inside `async` functions and blocks diff --git a/tests/ui/async-await/issues/issue-62009-2.stderr b/tests/ui/async-await/issues/issue-62009-2.stderr index 80a831cc5475..0004f99f9018 100644 --- a/tests/ui/async-await/issues/issue-62009-2.stderr +++ b/tests/ui/async-await/issues/issue-62009-2.stderr @@ -2,7 +2,7 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks --> $DIR/issue-62009-2.rs:8:23 | LL | fn main() { - | ---- this is not `async` + | --------- this is not `async` LL | (async || 2333)().await; | ^^^^^ only allowed inside `async` functions and blocks diff --git a/tests/ui/async-await/issues/issue-65419/issue-65419-coroutine-resume-after-completion.rs b/tests/ui/async-await/issues/issue-65419/issue-65419-coroutine-resume-after-completion.rs index f937311a5a0f..6b7dfc1235e8 100644 --- a/tests/ui/async-await/issues/issue-65419/issue-65419-coroutine-resume-after-completion.rs +++ b/tests/ui/async-await/issues/issue-65419/issue-65419-coroutine-resume-after-completion.rs @@ -6,15 +6,13 @@ //@ error-pattern:coroutine resumed after completion //@ edition:2018 -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] -use std::{ - ops::Coroutine, - pin::Pin, -}; +use std::{ops::Coroutine, pin::Pin}; fn main() { - let mut g = || { + let mut g = #[coroutine] + || { yield; }; Pin::new(&mut g).resume(()); // Yields once. diff --git a/tests/ui/async-await/issues/non-async-enclosing-span.stderr b/tests/ui/async-await/issues/non-async-enclosing-span.stderr index 91a9e5aa6cab..9c26de1c5047 100644 --- a/tests/ui/async-await/issues/non-async-enclosing-span.stderr +++ b/tests/ui/async-await/issues/non-async-enclosing-span.stderr @@ -2,7 +2,7 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks --> $DIR/non-async-enclosing-span.rs:9:28 | LL | fn main() { - | ---- this is not `async` + | --------- this is not `async` LL | let x = move || {}; LL | let y = do_the_thing().await; | ^^^^^ only allowed inside `async` functions and blocks diff --git a/tests/ui/async-await/non-trivial-drop.rs b/tests/ui/async-await/non-trivial-drop.rs index 71b881242197..95de3c5b0054 100644 --- a/tests/ui/async-await/non-trivial-drop.rs +++ b/tests/ui/async-await/non-trivial-drop.rs @@ -8,7 +8,7 @@ fn main() { } fn foo() { - || { + #[coroutine] || { yield drop(Config { nickname: NonCopy, b: NonCopy2, diff --git a/tests/ui/coherence/coherence-with-coroutine.rs b/tests/ui/coherence/coherence-with-coroutine.rs index 1ba983446726..6b0617e950b7 100644 --- a/tests/ui/coherence/coherence-with-coroutine.rs +++ b/tests/ui/coherence/coherence-with-coroutine.rs @@ -8,6 +8,7 @@ type OpaqueCoroutine = impl Sized; fn defining_use() -> OpaqueCoroutine { + #[coroutine] || { for i in 0..10 { yield i; diff --git a/tests/ui/coherence/coherence-with-coroutine.stock.stderr b/tests/ui/coherence/coherence-with-coroutine.stock.stderr index 9cf20ea49364..5f58b3088f14 100644 --- a/tests/ui/coherence/coherence-with-coroutine.stock.stderr +++ b/tests/ui/coherence/coherence-with-coroutine.stock.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper` - --> $DIR/coherence-with-coroutine.rs:21:1 + --> $DIR/coherence-with-coroutine.rs:22:1 | LL | impl Trait for Wrapper {} | --------------------------------------- first implementation here diff --git a/tests/ui/coroutine/addassign-yield.rs b/tests/ui/coroutine/addassign-yield.rs index 8718e73512f7..8329b53d715e 100644 --- a/tests/ui/coroutine/addassign-yield.rs +++ b/tests/ui/coroutine/addassign-yield.rs @@ -5,21 +5,21 @@ // is being used), we were failing to account for all types that might // possibly be live across a yield point. -#![feature(coroutines)] +#![feature(coroutines, stmt_expr_attributes)] fn foo() { - let _x = static || { + let _x = #[coroutine] static || { let mut s = String::new(); s += { yield; "" }; }; - let _y = static || { + let _y = #[coroutine] static || { let x = &mut 0; *{ yield; x } += match String::new() { _ => 0 }; }; // Please don't ever actually write something like this - let _z = static || { + let _z = #[coroutine] static || { let x = &mut 0; *{ let inner = &mut 1; diff --git a/tests/ui/coroutine/auto-trait-regions.rs b/tests/ui/coroutine/auto-trait-regions.rs index 5fce70e8e54d..4c239f9ee76c 100644 --- a/tests/ui/coroutine/auto-trait-regions.rs +++ b/tests/ui/coroutine/auto-trait-regions.rs @@ -1,4 +1,4 @@ -#![feature(coroutines)] +#![feature(coroutines, stmt_expr_attributes)] #![feature(auto_traits)] #![feature(negative_impls)] @@ -23,7 +23,7 @@ fn assert_foo(f: T) {} fn main() { // Make sure 'static is erased for coroutine interiors so we can't match it in trait selection let x: &'static _ = &OnlyFooIfStaticRef(No); - let gen = move || { + let gen = #[coroutine] move || { let x = x; yield; assert_foo(x); @@ -33,7 +33,7 @@ fn main() { // Allow impls which matches any lifetime let x = &OnlyFooIfRef(No); - let gen = move || { + let gen = #[coroutine] move || { let x = x; yield; assert_foo(x); @@ -41,7 +41,7 @@ fn main() { assert_foo(gen); // ok // Disallow impls which relates lifetimes in the coroutine interior - let gen = move || { + let gen = #[coroutine] move || { let a = A(&mut true, &mut true, No); //~^ temporary value dropped while borrowed //~| temporary value dropped while borrowed diff --git a/tests/ui/coroutine/auxiliary/metadata-sufficient-for-layout.rs b/tests/ui/coroutine/auxiliary/metadata-sufficient-for-layout.rs index 8af6973134a6..8ecb8c0c0979 100644 --- a/tests/ui/coroutine/auxiliary/metadata-sufficient-for-layout.rs +++ b/tests/ui/coroutine/auxiliary/metadata-sufficient-for-layout.rs @@ -5,6 +5,7 @@ use std::marker::Unpin; use std::ops::Coroutine; pub fn g() -> impl Coroutine<(), Yield = (), Return = ()> { + #[coroutine] || { yield; } diff --git a/tests/ui/coroutine/auxiliary/unwind-aux.rs b/tests/ui/coroutine/auxiliary/unwind-aux.rs index ff1e8ed32cd4..5d5e5c2218d3 100644 --- a/tests/ui/coroutine/auxiliary/unwind-aux.rs +++ b/tests/ui/coroutine/auxiliary/unwind-aux.rs @@ -2,9 +2,10 @@ //@ no-prefer-dynamic //@ edition:2021 -#![feature(coroutines)] +#![feature(coroutines, stmt_expr_attributes)] pub fn run(a: T) { - let _ = move || { + let _ = #[coroutine] + move || { drop(a); yield; }; diff --git a/tests/ui/coroutine/auxiliary/xcrate-reachable.rs b/tests/ui/coroutine/auxiliary/xcrate-reachable.rs index 673153f0619e..0b5d18823004 100644 --- a/tests/ui/coroutine/auxiliary/xcrate-reachable.rs +++ b/tests/ui/coroutine/auxiliary/xcrate-reachable.rs @@ -7,6 +7,7 @@ fn msg() -> u32 { } pub fn foo() -> impl Coroutine<(), Yield = (), Return = u32> { + #[coroutine] || { yield; return msg(); diff --git a/tests/ui/coroutine/auxiliary/xcrate.rs b/tests/ui/coroutine/auxiliary/xcrate.rs index f749a95ad35a..52f188135bd1 100644 --- a/tests/ui/coroutine/auxiliary/xcrate.rs +++ b/tests/ui/coroutine/auxiliary/xcrate.rs @@ -1,9 +1,10 @@ -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] use std::marker::Unpin; use std::ops::Coroutine; pub fn foo() -> impl Coroutine<(), Yield = (), Return = ()> { + #[coroutine] || { if false { yield; @@ -12,7 +13,10 @@ pub fn foo() -> impl Coroutine<(), Yield = (), Return = ()> { } pub fn bar(t: T) -> Box + Unpin> { - Box::new(|| { - yield t; - }) + Box::new( + #[coroutine] + || { + yield t; + }, + ) } diff --git a/tests/ui/coroutine/borrow-in-tail-expr.rs b/tests/ui/coroutine/borrow-in-tail-expr.rs index 2f0aa62019e8..380e95cfc776 100644 --- a/tests/ui/coroutine/borrow-in-tail-expr.rs +++ b/tests/ui/coroutine/borrow-in-tail-expr.rs @@ -1,9 +1,9 @@ //@ run-pass -#![feature(coroutines)] +#![feature(coroutines, stmt_expr_attributes)] fn main() { - let _a = || { + let _a = #[coroutine] || { yield; let a = String::new(); a.len() diff --git a/tests/ui/coroutine/borrowing.rs b/tests/ui/coroutine/borrowing.rs index 778eed8bd0d9..a6628766c1ba 100644 --- a/tests/ui/coroutine/borrowing.rs +++ b/tests/ui/coroutine/borrowing.rs @@ -1,4 +1,4 @@ -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] use std::ops::Coroutine; use std::pin::Pin; @@ -6,13 +6,13 @@ use std::pin::Pin; fn main() { let _b = { let a = 3; - Pin::new(&mut || yield &a).resume(()) + Pin::new(&mut #[coroutine] || yield &a).resume(()) //~^ ERROR: `a` does not live long enough }; let _b = { let a = 3; - || { + #[coroutine] || { yield &a //~^ ERROR: `a` does not live long enough } diff --git a/tests/ui/coroutine/borrowing.stderr b/tests/ui/coroutine/borrowing.stderr index acd4cdafdfdf..9132e5d84edd 100644 --- a/tests/ui/coroutine/borrowing.stderr +++ b/tests/ui/coroutine/borrowing.stderr @@ -1,13 +1,13 @@ error[E0597]: `a` does not live long enough - --> $DIR/borrowing.rs:9:33 + --> $DIR/borrowing.rs:9:46 | LL | let _b = { | -- borrow later stored here LL | let a = 3; -LL | Pin::new(&mut || yield &a).resume(()) - | -- ^ borrowed value does not live long enough - | | - | value captured here by coroutine +LL | Pin::new(&mut #[coroutine] || yield &a).resume(()) + | -- ^ borrowed value does not live long enough + | | + | value captured here by coroutine LL | LL | }; | - `a` dropped here while still borrowed @@ -18,8 +18,8 @@ error[E0597]: `a` does not live long enough LL | let _b = { | -- borrow later stored here LL | let a = 3; -LL | || { - | -- value captured here by coroutine +LL | #[coroutine] || { + | -- value captured here by coroutine LL | yield &a | ^ borrowed value does not live long enough ... diff --git a/tests/ui/coroutine/check-resume-ty-lifetimes-2.rs b/tests/ui/coroutine/check-resume-ty-lifetimes-2.rs index a316c50e8673..327756ebe660 100644 --- a/tests/ui/coroutine/check-resume-ty-lifetimes-2.rs +++ b/tests/ui/coroutine/check-resume-ty-lifetimes-2.rs @@ -7,27 +7,27 @@ struct Contravariant<'a>(fn(&'a ())); struct Covariant<'a>(fn() -> &'a ()); fn bad1<'short, 'long: 'short>() -> impl Coroutine> { - |_: Covariant<'short>| { + #[coroutine] |_: Covariant<'short>| { let a: Covariant<'long> = yield (); //~^ ERROR lifetime may not live long enough } } fn bad2<'short, 'long: 'short>() -> impl Coroutine> { - |_: Contravariant<'long>| { + #[coroutine] |_: Contravariant<'long>| { let a: Contravariant<'short> = yield (); //~^ ERROR lifetime may not live long enough } } fn good1<'short, 'long: 'short>() -> impl Coroutine> { - |_: Covariant<'long>| { + #[coroutine] |_: Covariant<'long>| { let a: Covariant<'short> = yield (); } } fn good2<'short, 'long: 'short>() -> impl Coroutine> { - |_: Contravariant<'short>| { + #[coroutine] |_: Contravariant<'short>| { let a: Contravariant<'long> = yield (); } } diff --git a/tests/ui/coroutine/check-resume-ty-lifetimes-2.stderr b/tests/ui/coroutine/check-resume-ty-lifetimes-2.stderr index e0cbca2dd526..8eb7ab3501b3 100644 --- a/tests/ui/coroutine/check-resume-ty-lifetimes-2.stderr +++ b/tests/ui/coroutine/check-resume-ty-lifetimes-2.stderr @@ -5,15 +5,15 @@ LL | fn bad1<'short, 'long: 'short>() -> impl Coroutine> { | ------ ----- lifetime `'long` defined here | | | lifetime `'short` defined here -LL | |_: Covariant<'short>| { +LL | #[coroutine] |_: Covariant<'short>| { LL | let a: Covariant<'long> = yield (); | ^^^^^^^^^^^^^^^^ type annotation requires that `'short` must outlive `'long` | = help: consider adding the following bound: `'short: 'long` help: consider adding 'move' keyword before the nested closure | -LL | move |_: Covariant<'short>| { - | ++++ +LL | #[coroutine] move |_: Covariant<'short>| { + | ++++ error: lifetime may not live long enough --> $DIR/check-resume-ty-lifetimes-2.rs:18:40 @@ -22,15 +22,15 @@ LL | fn bad2<'short, 'long: 'short>() -> impl Coroutine> { | ------ ----- lifetime `'long` defined here | | | lifetime `'short` defined here -LL | |_: Contravariant<'long>| { +LL | #[coroutine] |_: Contravariant<'long>| { LL | let a: Contravariant<'short> = yield (); | ^^^^^^^^ yielding this value requires that `'short` must outlive `'long` | = help: consider adding the following bound: `'short: 'long` help: consider adding 'move' keyword before the nested closure | -LL | move |_: Contravariant<'long>| { - | ++++ +LL | #[coroutine] move |_: Contravariant<'long>| { + | ++++ error: aborting due to 2 previous errors diff --git a/tests/ui/coroutine/check-resume-ty-lifetimes.rs b/tests/ui/coroutine/check-resume-ty-lifetimes.rs index add0b5080a8a..b75e46c541cc 100644 --- a/tests/ui/coroutine/check-resume-ty-lifetimes.rs +++ b/tests/ui/coroutine/check-resume-ty-lifetimes.rs @@ -1,5 +1,5 @@ #![feature(coroutine_trait)] -#![feature(coroutines)] +#![feature(coroutines, stmt_expr_attributes)] #![allow(unused)] use std::ops::Coroutine; @@ -9,11 +9,14 @@ use std::pin::pin; fn mk_static(s: &str) -> &'static str { let mut storage: Option<&'static str> = None; - let mut coroutine = pin!(|_: &str| { - let x: &'static str = yield (); - //~^ ERROR lifetime may not live long enough - storage = Some(x); - }); + let mut coroutine = pin!( + #[coroutine] + |_: &str| { + let x: &'static str = yield (); + //~^ ERROR lifetime may not live long enough + storage = Some(x); + } + ); coroutine.as_mut().resume(s); coroutine.as_mut().resume(s); diff --git a/tests/ui/coroutine/check-resume-ty-lifetimes.stderr b/tests/ui/coroutine/check-resume-ty-lifetimes.stderr index f373aa778a82..1fbaeb9f7fa4 100644 --- a/tests/ui/coroutine/check-resume-ty-lifetimes.stderr +++ b/tests/ui/coroutine/check-resume-ty-lifetimes.stderr @@ -1,11 +1,11 @@ error: lifetime may not live long enough - --> $DIR/check-resume-ty-lifetimes.rs:13:16 + --> $DIR/check-resume-ty-lifetimes.rs:15:20 | LL | fn mk_static(s: &str) -> &'static str { | - let's call the lifetime of this reference `'1` ... -LL | let x: &'static str = yield (); - | ^^^^^^^^^^^^ type annotation requires that `'1` must outlive `'static` +LL | let x: &'static str = yield (); + | ^^^^^^^^^^^^ type annotation requires that `'1` must outlive `'static` error: aborting due to 1 previous error diff --git a/tests/ui/coroutine/clone-impl-static.rs b/tests/ui/coroutine/clone-impl-static.rs index 9a165cf4672e..56d1ccac7035 100644 --- a/tests/ui/coroutine/clone-impl-static.rs +++ b/tests/ui/coroutine/clone-impl-static.rs @@ -1,10 +1,11 @@ // gate-test-coroutine_clone // Verifies that static coroutines cannot be cloned/copied. -#![feature(coroutines, coroutine_clone)] +#![feature(coroutines, coroutine_clone, stmt_expr_attributes)] fn main() { - let gen = static move || { + let gen = #[coroutine] + static move || { yield; }; check_copy(&gen); diff --git a/tests/ui/coroutine/clone-impl-static.stderr b/tests/ui/coroutine/clone-impl-static.stderr index 8fa9fb12bf68..43920326d5df 100644 --- a/tests/ui/coroutine/clone-impl-static.stderr +++ b/tests/ui/coroutine/clone-impl-static.stderr @@ -1,27 +1,27 @@ -error[E0277]: the trait bound `{static coroutine@$DIR/clone-impl-static.rs:7:15: 7:29}: Copy` is not satisfied - --> $DIR/clone-impl-static.rs:10:16 +error[E0277]: the trait bound `{static coroutine@$DIR/clone-impl-static.rs:8:5: 8:19}: Copy` is not satisfied + --> $DIR/clone-impl-static.rs:11:16 | LL | check_copy(&gen); - | ---------- ^^^^ the trait `Copy` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:7:15: 7:29}` + | ---------- ^^^^ the trait `Copy` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:8:5: 8:19}` | | | required by a bound introduced by this call | note: required by a bound in `check_copy` - --> $DIR/clone-impl-static.rs:16:18 + --> $DIR/clone-impl-static.rs:17:18 | LL | fn check_copy(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `{static coroutine@$DIR/clone-impl-static.rs:7:15: 7:29}: Clone` is not satisfied - --> $DIR/clone-impl-static.rs:12:17 +error[E0277]: the trait bound `{static coroutine@$DIR/clone-impl-static.rs:8:5: 8:19}: Clone` is not satisfied + --> $DIR/clone-impl-static.rs:13:17 | LL | check_clone(&gen); - | ----------- ^^^^ the trait `Clone` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:7:15: 7:29}` + | ----------- ^^^^ the trait `Clone` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:8:5: 8:19}` | | | required by a bound introduced by this call | note: required by a bound in `check_clone` - --> $DIR/clone-impl-static.rs:17:19 + --> $DIR/clone-impl-static.rs:18:19 | LL | fn check_clone(_x: &T) {} | ^^^^^ required by this bound in `check_clone` diff --git a/tests/ui/coroutine/clone-impl.rs b/tests/ui/coroutine/clone-impl.rs index fffdae632ef7..94420e56a226 100644 --- a/tests/ui/coroutine/clone-impl.rs +++ b/tests/ui/coroutine/clone-impl.rs @@ -2,13 +2,14 @@ // Verifies that non-static coroutines can be cloned/copied if all their upvars and locals held // across awaits can be cloned/copied. -#![feature(coroutines, coroutine_clone)] +#![feature(coroutines, coroutine_clone, stmt_expr_attributes)] struct NonClone; fn test1() { let copyable: u32 = 123; - let gen_copy_0 = move || { + let gen_copy_0 = #[coroutine] + move || { yield; drop(copyable); }; @@ -18,7 +19,8 @@ fn test1() { fn test2() { let copyable: u32 = 123; - let gen_copy_1 = move || { + let gen_copy_1 = #[coroutine] + move || { /* let v = vec!['a']; let n = NonClone; @@ -37,7 +39,8 @@ fn test2() { fn test3() { let clonable_0: Vec = Vec::new(); - let gen_clone_0 = move || { + let gen_clone_0 = #[coroutine] + move || { let v = vec!['a']; yield; drop(v); @@ -51,7 +54,8 @@ fn test3() { fn test4() { let clonable_1: Vec = Vec::new(); - let gen_clone_1 = move || { + let gen_clone_1 = #[coroutine] + move || { let v = vec!['a']; /* let n = NonClone; @@ -71,7 +75,8 @@ fn test4() { fn test5() { let non_clonable: NonClone = NonClone; - let gen_non_clone = move || { + let gen_non_clone = #[coroutine] + move || { yield; drop(non_clonable); }; diff --git a/tests/ui/coroutine/clone-impl.stderr b/tests/ui/coroutine/clone-impl.stderr index b454846faac9..5330d3bbd39d 100644 --- a/tests/ui/coroutine/clone-impl.stderr +++ b/tests/ui/coroutine/clone-impl.stderr @@ -1,76 +1,76 @@ -error[E0277]: the trait bound `Vec: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:40:23: 40:30}` - --> $DIR/clone-impl.rs:46:5 +error[E0277]: the trait bound `Vec: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:43:5: 43:12}` + --> $DIR/clone-impl.rs:49:5 | -LL | let gen_clone_0 = move || { - | ------- within this `{coroutine@$DIR/clone-impl.rs:40:23: 40:30}` +LL | move || { + | ------- within this `{coroutine@$DIR/clone-impl.rs:43:5: 43:12}` ... LL | check_copy(&gen_clone_0); - | ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:40:23: 40:30}`, the trait `Copy` is not implemented for `Vec`, which is required by `{coroutine@$DIR/clone-impl.rs:40:23: 40:30}: Copy` + | ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:43:5: 43:12}`, the trait `Copy` is not implemented for `Vec`, which is required by `{coroutine@$DIR/clone-impl.rs:43:5: 43:12}: Copy` | note: captured value does not implement `Copy` - --> $DIR/clone-impl.rs:44:14 + --> $DIR/clone-impl.rs:47:14 | LL | drop(clonable_0); | ^^^^^^^^^^ has type `Vec` which does not implement `Copy` note: required by a bound in `check_copy` - --> $DIR/clone-impl.rs:84:18 + --> $DIR/clone-impl.rs:89:18 | LL | fn check_copy(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `Vec: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:40:23: 40:30}` - --> $DIR/clone-impl.rs:46:5 +error[E0277]: the trait bound `Vec: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:43:5: 43:12}` + --> $DIR/clone-impl.rs:49:5 | -LL | let gen_clone_0 = move || { - | ------- within this `{coroutine@$DIR/clone-impl.rs:40:23: 40:30}` +LL | move || { + | ------- within this `{coroutine@$DIR/clone-impl.rs:43:5: 43:12}` ... LL | check_copy(&gen_clone_0); - | ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:40:23: 40:30}`, the trait `Copy` is not implemented for `Vec`, which is required by `{coroutine@$DIR/clone-impl.rs:40:23: 40:30}: Copy` + | ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:43:5: 43:12}`, the trait `Copy` is not implemented for `Vec`, which is required by `{coroutine@$DIR/clone-impl.rs:43:5: 43:12}: Copy` | note: coroutine does not implement `Copy` as this value is used across a yield - --> $DIR/clone-impl.rs:42:9 + --> $DIR/clone-impl.rs:45:9 | LL | let v = vec!['a']; | - has type `Vec` which does not implement `Copy` LL | yield; | ^^^^^ yield occurs here, with `v` maybe used later note: required by a bound in `check_copy` - --> $DIR/clone-impl.rs:84:18 + --> $DIR/clone-impl.rs:89:18 | LL | fn check_copy(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `Vec: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:54:23: 54:30}` - --> $DIR/clone-impl.rs:66:5 +error[E0277]: the trait bound `Vec: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:58:5: 58:12}` + --> $DIR/clone-impl.rs:70:5 | -LL | let gen_clone_1 = move || { - | ------- within this `{coroutine@$DIR/clone-impl.rs:54:23: 54:30}` +LL | move || { + | ------- within this `{coroutine@$DIR/clone-impl.rs:58:5: 58:12}` ... LL | check_copy(&gen_clone_1); - | ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:54:23: 54:30}`, the trait `Copy` is not implemented for `Vec`, which is required by `{coroutine@$DIR/clone-impl.rs:54:23: 54:30}: Copy` + | ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:58:5: 58:12}`, the trait `Copy` is not implemented for `Vec`, which is required by `{coroutine@$DIR/clone-impl.rs:58:5: 58:12}: Copy` | note: captured value does not implement `Copy` - --> $DIR/clone-impl.rs:64:14 + --> $DIR/clone-impl.rs:68:14 | LL | drop(clonable_1); | ^^^^^^^^^^ has type `Vec` which does not implement `Copy` note: required by a bound in `check_copy` - --> $DIR/clone-impl.rs:84:18 + --> $DIR/clone-impl.rs:89:18 | LL | fn check_copy(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `Vec: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:54:23: 54:30}` - --> $DIR/clone-impl.rs:66:5 +error[E0277]: the trait bound `Vec: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:58:5: 58:12}` + --> $DIR/clone-impl.rs:70:5 | -LL | let gen_clone_1 = move || { - | ------- within this `{coroutine@$DIR/clone-impl.rs:54:23: 54:30}` +LL | move || { + | ------- within this `{coroutine@$DIR/clone-impl.rs:58:5: 58:12}` ... LL | check_copy(&gen_clone_1); - | ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:54:23: 54:30}`, the trait `Copy` is not implemented for `Vec`, which is required by `{coroutine@$DIR/clone-impl.rs:54:23: 54:30}: Copy` + | ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:58:5: 58:12}`, the trait `Copy` is not implemented for `Vec`, which is required by `{coroutine@$DIR/clone-impl.rs:58:5: 58:12}: Copy` | note: coroutine does not implement `Copy` as this value is used across a yield - --> $DIR/clone-impl.rs:60:9 + --> $DIR/clone-impl.rs:64:9 | LL | let v = vec!['a']; | - has type `Vec` which does not implement `Copy` @@ -78,27 +78,27 @@ LL | let v = vec!['a']; LL | yield; | ^^^^^ yield occurs here, with `v` maybe used later note: required by a bound in `check_copy` - --> $DIR/clone-impl.rs:84:18 + --> $DIR/clone-impl.rs:89:18 | LL | fn check_copy(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `NonClone: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:74:25: 74:32}` - --> $DIR/clone-impl.rs:78:5 +error[E0277]: the trait bound `NonClone: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:79:5: 79:12}` + --> $DIR/clone-impl.rs:83:5 | -LL | let gen_non_clone = move || { - | ------- within this `{coroutine@$DIR/clone-impl.rs:74:25: 74:32}` +LL | move || { + | ------- within this `{coroutine@$DIR/clone-impl.rs:79:5: 79:12}` ... LL | check_copy(&gen_non_clone); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:74:25: 74:32}`, the trait `Copy` is not implemented for `NonClone`, which is required by `{coroutine@$DIR/clone-impl.rs:74:25: 74:32}: Copy` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:79:5: 79:12}`, the trait `Copy` is not implemented for `NonClone`, which is required by `{coroutine@$DIR/clone-impl.rs:79:5: 79:12}: Copy` | note: captured value does not implement `Copy` - --> $DIR/clone-impl.rs:76:14 + --> $DIR/clone-impl.rs:81:14 | LL | drop(non_clonable); | ^^^^^^^^^^^^ has type `NonClone` which does not implement `Copy` note: required by a bound in `check_copy` - --> $DIR/clone-impl.rs:84:18 + --> $DIR/clone-impl.rs:89:18 | LL | fn check_copy(_x: &T) {} | ^^^^ required by this bound in `check_copy` @@ -108,22 +108,22 @@ LL + #[derive(Copy)] LL | struct NonClone; | -error[E0277]: the trait bound `NonClone: Clone` is not satisfied in `{coroutine@$DIR/clone-impl.rs:74:25: 74:32}` - --> $DIR/clone-impl.rs:80:5 +error[E0277]: the trait bound `NonClone: Clone` is not satisfied in `{coroutine@$DIR/clone-impl.rs:79:5: 79:12}` + --> $DIR/clone-impl.rs:85:5 | -LL | let gen_non_clone = move || { - | ------- within this `{coroutine@$DIR/clone-impl.rs:74:25: 74:32}` +LL | move || { + | ------- within this `{coroutine@$DIR/clone-impl.rs:79:5: 79:12}` ... LL | check_clone(&gen_non_clone); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:74:25: 74:32}`, the trait `Clone` is not implemented for `NonClone`, which is required by `{coroutine@$DIR/clone-impl.rs:74:25: 74:32}: Clone` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:79:5: 79:12}`, the trait `Clone` is not implemented for `NonClone`, which is required by `{coroutine@$DIR/clone-impl.rs:79:5: 79:12}: Clone` | note: captured value does not implement `Clone` - --> $DIR/clone-impl.rs:76:14 + --> $DIR/clone-impl.rs:81:14 | LL | drop(non_clonable); | ^^^^^^^^^^^^ has type `NonClone` which does not implement `Clone` note: required by a bound in `check_clone` - --> $DIR/clone-impl.rs:85:19 + --> $DIR/clone-impl.rs:90:19 | LL | fn check_clone(_x: &T) {} | ^^^^^ required by this bound in `check_clone` diff --git a/tests/ui/coroutine/clone-rpit.next.stderr b/tests/ui/coroutine/clone-rpit.next.stderr index 41aa2d63af01..c223f1f211ac 100644 --- a/tests/ui/coroutine/clone-rpit.next.stderr +++ b/tests/ui/coroutine/clone-rpit.next.stderr @@ -5,32 +5,32 @@ LL | pub fn foo<'a, 'b>() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: ...which requires coroutine witness types for `foo::{closure#0}`... - --> $DIR/clone-rpit.rs:14:5 + --> $DIR/clone-rpit.rs:15:5 | LL | move |_: ()| { | ^^^^^^^^^^^^ note: ...which requires promoting constants in MIR for `foo::{closure#0}`... - --> $DIR/clone-rpit.rs:14:5 + --> $DIR/clone-rpit.rs:15:5 | LL | move |_: ()| { | ^^^^^^^^^^^^ note: ...which requires checking if `foo::{closure#0}` contains FFI-unwind calls... - --> $DIR/clone-rpit.rs:14:5 + --> $DIR/clone-rpit.rs:15:5 | LL | move |_: ()| { | ^^^^^^^^^^^^ note: ...which requires building MIR for `foo::{closure#0}`... - --> $DIR/clone-rpit.rs:14:5 + --> $DIR/clone-rpit.rs:15:5 | LL | move |_: ()| { | ^^^^^^^^^^^^ note: ...which requires match-checking `foo::{closure#0}`... - --> $DIR/clone-rpit.rs:14:5 + --> $DIR/clone-rpit.rs:15:5 | LL | move |_: ()| { | ^^^^^^^^^^^^ note: ...which requires type-checking `foo::{closure#0}`... - --> $DIR/clone-rpit.rs:14:5 + --> $DIR/clone-rpit.rs:15:5 | LL | move |_: ()| { | ^^^^^^^^^^^^ diff --git a/tests/ui/coroutine/clone-rpit.rs b/tests/ui/coroutine/clone-rpit.rs index 0df9bf616018..66569b4f4274 100644 --- a/tests/ui/coroutine/clone-rpit.rs +++ b/tests/ui/coroutine/clone-rpit.rs @@ -11,6 +11,7 @@ // witness types, which we don't know until after borrowck. When we later check // the goal for correctness, we want to be able to bind the `impl Clone` opaque. pub fn foo<'a, 'b>() -> impl Clone { + #[coroutine] move |_: ()| { let () = yield (); } diff --git a/tests/ui/coroutine/conditional-drop.rs b/tests/ui/coroutine/conditional-drop.rs index 65d3a9e701ee..52e1b561946c 100644 --- a/tests/ui/coroutine/conditional-drop.rs +++ b/tests/ui/coroutine/conditional-drop.rs @@ -3,7 +3,7 @@ //@ revisions: default nomiropt //@[nomiropt]compile-flags: -Z mir-opt-level=0 -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] use std::ops::Coroutine; use std::pin::Pin; @@ -29,7 +29,7 @@ fn main() { } fn t1() { - let mut a = || { + let mut a = #[coroutine] || { let b = B; if test() { drop(b); @@ -45,7 +45,7 @@ fn t1() { } fn t2() { - let mut a = || { + let mut a = #[coroutine] || { let b = B; if test2() { drop(b); diff --git a/tests/ui/coroutine/control-flow.rs b/tests/ui/coroutine/control-flow.rs index 9070ba17856c..f64b6f738836 100644 --- a/tests/ui/coroutine/control-flow.rs +++ b/tests/ui/coroutine/control-flow.rs @@ -3,7 +3,7 @@ //@ revisions: default nomiropt //@[nomiropt]compile-flags: -Z mir-opt-level=0 -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] use std::ops::{CoroutineState, Coroutine}; use std::pin::Pin; @@ -24,25 +24,25 @@ fn finish(mut amt: usize, mut t: T) -> T::Return } fn main() { - finish(1, || yield); - finish(8, || { + finish(1, #[coroutine] || yield); + finish(8, #[coroutine] || { for _ in 0..8 { yield; } }); - finish(1, || { + finish(1, #[coroutine] || { if true { yield; } else { } }); - finish(1, || { + finish(1, #[coroutine] || { if false { } else { yield; } }); - finish(2, || { + finish(2, #[coroutine] || { if { yield; false } { yield; panic!() diff --git a/tests/ui/coroutine/coroutine-region-requirements.rs b/tests/ui/coroutine/coroutine-region-requirements.rs index 8bc34fdd2f05..ab6f16995e27 100644 --- a/tests/ui/coroutine/coroutine-region-requirements.rs +++ b/tests/ui/coroutine/coroutine-region-requirements.rs @@ -1,9 +1,9 @@ -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] use std::ops::{Coroutine, CoroutineState}; use std::pin::Pin; fn dangle(x: &mut i32) -> &'static mut i32 { - let mut g = || { + let mut g = #[coroutine] || { yield; x }; diff --git a/tests/ui/coroutine/coroutine-resume-after-panic.rs b/tests/ui/coroutine/coroutine-resume-after-panic.rs index 8445bf7e6352..2745ebc61326 100644 --- a/tests/ui/coroutine/coroutine-resume-after-panic.rs +++ b/tests/ui/coroutine/coroutine-resume-after-panic.rs @@ -5,7 +5,7 @@ // Test that we get the correct message for resuming a panicked coroutine. -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] use std::{ ops::Coroutine, @@ -14,7 +14,7 @@ use std::{ }; fn main() { - let mut g = || { + let mut g = #[coroutine] || { panic!(); yield; }; diff --git a/tests/ui/coroutine/coroutine-with-nll.rs b/tests/ui/coroutine/coroutine-with-nll.rs index 28a3643fbc9c..fa77ab4e0495 100644 --- a/tests/ui/coroutine/coroutine-with-nll.rs +++ b/tests/ui/coroutine/coroutine-with-nll.rs @@ -1,6 +1,7 @@ #![feature(coroutines)] fn main() { + #[coroutine] || { // The reference in `_a` is a Legal with NLL since it ends before the yield let _a = &mut true; diff --git a/tests/ui/coroutine/coroutine-with-nll.stderr b/tests/ui/coroutine/coroutine-with-nll.stderr index 77e8bb1f92ee..3f3d51da3118 100644 --- a/tests/ui/coroutine/coroutine-with-nll.stderr +++ b/tests/ui/coroutine/coroutine-with-nll.stderr @@ -1,5 +1,5 @@ error[E0626]: borrow may still be in use when coroutine yields - --> $DIR/coroutine-with-nll.rs:7:17 + --> $DIR/coroutine-with-nll.rs:8:17 | LL | let b = &mut true; | ^^^^^^^^^ diff --git a/tests/ui/coroutine/coroutine-yielding-or-returning-itself.rs b/tests/ui/coroutine/coroutine-yielding-or-returning-itself.rs index 3c91b3c93295..f3110d71d0d7 100644 --- a/tests/ui/coroutine/coroutine-yielding-or-returning-itself.rs +++ b/tests/ui/coroutine/coroutine-yielding-or-returning-itself.rs @@ -1,5 +1,5 @@ #![feature(coroutine_trait)] -#![feature(coroutines)] +#![feature(coroutines, stmt_expr_attributes)] // Test that we cannot create a coroutine that returns a value of its // own type. @@ -12,7 +12,7 @@ pub fn want_cyclic_coroutine_return(_: T) } fn supply_cyclic_coroutine_return() { - want_cyclic_coroutine_return(|| { + want_cyclic_coroutine_return(#[coroutine] || { //~^ ERROR type mismatch if false { yield None.unwrap(); } None.unwrap() @@ -25,7 +25,7 @@ pub fn want_cyclic_coroutine_yield(_: T) } fn supply_cyclic_coroutine_yield() { - want_cyclic_coroutine_yield(|| { + want_cyclic_coroutine_yield(#[coroutine] || { //~^ ERROR type mismatch if false { yield None.unwrap(); } None.unwrap() diff --git a/tests/ui/coroutine/coroutine-yielding-or-returning-itself.stderr b/tests/ui/coroutine/coroutine-yielding-or-returning-itself.stderr index 325030524ba8..32799148ae1d 100644 --- a/tests/ui/coroutine/coroutine-yielding-or-returning-itself.stderr +++ b/tests/ui/coroutine/coroutine-yielding-or-returning-itself.stderr @@ -1,8 +1,8 @@ -error[E0271]: type mismatch resolving `<{coroutine@$DIR/coroutine-yielding-or-returning-itself.rs:15:34: 15:36} as Coroutine>::Return == {coroutine@$DIR/coroutine-yielding-or-returning-itself.rs:15:34: 15:36}` - --> $DIR/coroutine-yielding-or-returning-itself.rs:15:34 +error[E0271]: type mismatch resolving `<{coroutine@$DIR/coroutine-yielding-or-returning-itself.rs:15:47: 15:49} as Coroutine>::Return == {coroutine@$DIR/coroutine-yielding-or-returning-itself.rs:15:47: 15:49}` + --> $DIR/coroutine-yielding-or-returning-itself.rs:15:47 | -LL | want_cyclic_coroutine_return(|| { - | _____----------------------------_^ +LL | want_cyclic_coroutine_return(#[coroutine] || { + | _____----------------------------______________^ | | | | | required by a bound introduced by this call LL | | @@ -23,11 +23,11 @@ LL | pub fn want_cyclic_coroutine_return(_: T) LL | where T: Coroutine | ^^^^^^^^^^ required by this bound in `want_cyclic_coroutine_return` -error[E0271]: type mismatch resolving `<{coroutine@$DIR/coroutine-yielding-or-returning-itself.rs:28:33: 28:35} as Coroutine>::Yield == {coroutine@$DIR/coroutine-yielding-or-returning-itself.rs:28:33: 28:35}` - --> $DIR/coroutine-yielding-or-returning-itself.rs:28:33 +error[E0271]: type mismatch resolving `<{coroutine@$DIR/coroutine-yielding-or-returning-itself.rs:28:46: 28:48} as Coroutine>::Yield == {coroutine@$DIR/coroutine-yielding-or-returning-itself.rs:28:46: 28:48}` + --> $DIR/coroutine-yielding-or-returning-itself.rs:28:46 | -LL | want_cyclic_coroutine_yield(|| { - | _____---------------------------_^ +LL | want_cyclic_coroutine_yield(#[coroutine] || { + | _____---------------------------______________^ | | | | | required by a bound introduced by this call LL | | diff --git a/tests/ui/coroutine/derived-drop-parent-expr.rs b/tests/ui/coroutine/derived-drop-parent-expr.rs index 71f7506ab845..cc217e4960e9 100644 --- a/tests/ui/coroutine/derived-drop-parent-expr.rs +++ b/tests/ui/coroutine/derived-drop-parent-expr.rs @@ -1,7 +1,7 @@ //@ build-pass //! Like drop-tracking-parent-expression, but also tests that this doesn't ICE when building MIR -#![feature(coroutines)] +#![feature(coroutines, stmt_expr_attributes)] fn assert_send(_thing: T) {} @@ -9,7 +9,7 @@ fn assert_send(_thing: T) {} pub struct Client { pub nickname: String } fn main() { - let g = move || match drop(Client { ..Client::default() }) { + let g = #[coroutine] move || match drop(Client { ..Client::default() }) { _status => yield, }; assert_send(g); diff --git a/tests/ui/coroutine/discriminant.rs b/tests/ui/coroutine/discriminant.rs index a44d8f74746b..d6879e218255 100644 --- a/tests/ui/coroutine/discriminant.rs +++ b/tests/ui/coroutine/discriminant.rs @@ -86,7 +86,7 @@ fn cycle( fn main() { // Has only one invalid discr. value. let gen_u8_tiny_niche = || { - || { + #[coroutine] || { // 3 reserved variants yield250!(); // 253 variants @@ -98,7 +98,7 @@ fn main() { // Uses all values in the u8 discriminant. let gen_u8_full = || { - || { + #[coroutine] || { // 3 reserved variants yield250!(); // 253 variants @@ -111,7 +111,7 @@ fn main() { // Barely needs a u16 discriminant. let gen_u16 = || { - || { + #[coroutine] || { // 3 reserved variants yield250!(); // 253 variants diff --git a/tests/ui/coroutine/drop-and-replace.rs b/tests/ui/coroutine/drop-and-replace.rs index 6e30d76512b7..d3d7e000020a 100644 --- a/tests/ui/coroutine/drop-and-replace.rs +++ b/tests/ui/coroutine/drop-and-replace.rs @@ -4,7 +4,7 @@ // #60187, this produced incorrect code for coroutines when a saved local was // re-assigned. -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] use std::ops::{Coroutine, CoroutineState}; use std::pin::Pin; @@ -17,7 +17,8 @@ impl Drop for Foo { } fn main() { - let mut a = || { + let mut a = #[coroutine] + || { let mut x = Foo(4); yield; assert_eq!(x.0, 4); diff --git a/tests/ui/coroutine/drop-control-flow.rs b/tests/ui/coroutine/drop-control-flow.rs index f4e8eed4f8dc..f576b1b75944 100644 --- a/tests/ui/coroutine/drop-control-flow.rs +++ b/tests/ui/coroutine/drop-control-flow.rs @@ -4,7 +4,7 @@ // and also that values that are dropped along all paths to a yield do not get // included in the coroutine type. -#![feature(coroutines, negative_impls)] +#![feature(coroutines, negative_impls, stmt_expr_attributes)] #![allow(unused_assignments, dead_code)] struct Ptr; @@ -19,7 +19,7 @@ fn assert_send(_: T) {} // This test case is reduced from tests/ui/drop/dynamic-drop-async.rs fn one_armed_if(arg: bool) { - let _ = || { + let _ = #[coroutine] || { let arr = [Ptr]; if arg { drop(arr); @@ -29,7 +29,7 @@ fn one_armed_if(arg: bool) { } fn two_armed_if(arg: bool) { - assert_send(|| { + assert_send(#[coroutine] || { let arr = [Ptr]; if arg { drop(arr); @@ -41,7 +41,7 @@ fn two_armed_if(arg: bool) { } fn if_let(arg: Option) { - let _ = || { + let _ = #[coroutine] || { let arr = [Ptr]; if let Some(_) = arg { drop(arr); @@ -51,7 +51,7 @@ fn if_let(arg: Option) { } fn init_in_if(arg: bool) { - assert_send(|| { + assert_send(#[coroutine] || { let mut x = NonSend; drop(x); if arg { @@ -63,7 +63,7 @@ fn init_in_if(arg: bool) { } fn init_in_match_arm(arg: Option) { - assert_send(|| { + assert_send(#[coroutine] || { let mut x = NonSend; drop(x); match arg { @@ -74,7 +74,7 @@ fn init_in_match_arm(arg: Option) { } fn reinit() { - let _ = || { + let _ = #[coroutine] || { let mut arr = [Ptr]; drop(arr); arr = [Ptr]; @@ -83,7 +83,7 @@ fn reinit() { } fn loop_uninit() { - let _ = || { + let _ = #[coroutine] || { let mut arr = [Ptr]; let mut count = 0; drop(arr); @@ -96,7 +96,7 @@ fn loop_uninit() { } fn nested_loop() { - let _ = || { + let _ = #[coroutine] || { let mut arr = [Ptr]; let mut count = 0; drop(arr); @@ -111,7 +111,7 @@ fn nested_loop() { } fn loop_continue(b: bool) { - let _ = || { + let _ = #[coroutine] || { let mut arr = [Ptr]; let mut count = 0; drop(arr); diff --git a/tests/ui/coroutine/drop-env.rs b/tests/ui/coroutine/drop-env.rs index b189ab814995..d36228dc8490 100644 --- a/tests/ui/coroutine/drop-env.rs +++ b/tests/ui/coroutine/drop-env.rs @@ -3,7 +3,7 @@ //@ revisions: default nomiropt //@[nomiropt]compile-flags: -Z mir-opt-level=0 -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] #![allow(dropping_copy_types)] use std::ops::Coroutine; @@ -28,7 +28,7 @@ fn main() { fn t1() { let b = B; - let mut foo = || { + let mut foo = #[coroutine] || { yield; drop(b); }; @@ -42,7 +42,7 @@ fn t1() { fn t2() { let b = B; - let mut foo = || { + let mut foo = #[coroutine] || { yield b; }; @@ -55,7 +55,7 @@ fn t2() { fn t3() { let b = B; - let foo = || { + let foo = #[coroutine] || { yield; drop(b); }; diff --git a/tests/ui/coroutine/drop-track-addassign-yield.rs b/tests/ui/coroutine/drop-track-addassign-yield.rs index b1a4bd79f31c..537e66c41b20 100644 --- a/tests/ui/coroutine/drop-track-addassign-yield.rs +++ b/tests/ui/coroutine/drop-track-addassign-yield.rs @@ -3,10 +3,10 @@ // Based on addassign-yield.rs, but with drop tracking enabled. Originally we did not implement // the fake_read callback on ExprUseVisitor which caused this case to break. -#![feature(coroutines)] +#![feature(coroutines, stmt_expr_attributes)] fn foo() { - let _y = static || { + let _y = #[coroutine] static || { let x = &mut 0; *{ yield; @@ -17,7 +17,7 @@ fn foo() { }; // Please don't ever actually write something like this - let _z = static || { + let _z = #[coroutine] static || { let x = &mut 0; *{ let inner = &mut 1; diff --git a/tests/ui/coroutine/drop-tracking-parent-expression.rs b/tests/ui/coroutine/drop-tracking-parent-expression.rs index 4d40192c07a2..0f4d99c89364 100644 --- a/tests/ui/coroutine/drop-tracking-parent-expression.rs +++ b/tests/ui/coroutine/drop-tracking-parent-expression.rs @@ -1,4 +1,4 @@ -#![feature(coroutines, negative_impls, rustc_attrs)] +#![feature(coroutines, negative_impls, rustc_attrs, stmt_expr_attributes)] macro_rules! type_combinations { ( @@ -14,7 +14,7 @@ macro_rules! type_combinations { // Struct update syntax. This fails because the Client used in the update is considered // dropped *after* the yield. { - let g = move || match drop($name::Client { ..$name::Client::default() }) { + let g = #[coroutine] move || match drop($name::Client { ..$name::Client::default() }) { //~^ `significant_drop::Client` which is not `Send` //~| `insignificant_dtor::Client` which is not `Send` //~| `derived_drop::Client` which is not `Send` @@ -29,7 +29,7 @@ macro_rules! type_combinations { // Simple owned value. This works because the Client is considered moved into `drop`, // even though the temporary expression doesn't end until after the yield. { - let g = move || match drop($name::Client::default()) { + let g = #[coroutine] move || match drop($name::Client::default()) { _ => yield, }; assert_send(g); diff --git a/tests/ui/coroutine/drop-tracking-parent-expression.stderr b/tests/ui/coroutine/drop-tracking-parent-expression.stderr index 21aa35b9579b..5f8d8495e4f1 100644 --- a/tests/ui/coroutine/drop-tracking-parent-expression.stderr +++ b/tests/ui/coroutine/drop-tracking-parent-expression.stderr @@ -13,12 +13,12 @@ LL | | }; LL | | ); | |_____- in this macro invocation | - = help: within `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `derived_drop::Client`, which is required by `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:21: 17:28}: Send` + = help: within `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:34: 17:41}`, the trait `Send` is not implemented for `derived_drop::Client`, which is required by `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:34: 17:41}: Send` note: coroutine is not `Send` as this value is used across a yield --> $DIR/drop-tracking-parent-expression.rs:21:22 | -LL | let g = move || match drop($name::Client { ..$name::Client::default() }) { - | ------------------------ has type `derived_drop::Client` which is not `Send` +LL | let g = #[coroutine] move || match drop($name::Client { ..$name::Client::default() }) { + | ------------------------ has type `derived_drop::Client` which is not `Send` ... LL | _ => yield, | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later @@ -53,12 +53,12 @@ LL | | }; LL | | ); | |_____- in this macro invocation | - = help: within `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `significant_drop::Client`, which is required by `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:21: 17:28}: Send` + = help: within `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:34: 17:41}`, the trait `Send` is not implemented for `significant_drop::Client`, which is required by `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:34: 17:41}: Send` note: coroutine is not `Send` as this value is used across a yield --> $DIR/drop-tracking-parent-expression.rs:21:22 | -LL | let g = move || match drop($name::Client { ..$name::Client::default() }) { - | ------------------------ has type `significant_drop::Client` which is not `Send` +LL | let g = #[coroutine] move || match drop($name::Client { ..$name::Client::default() }) { + | ------------------------ has type `significant_drop::Client` which is not `Send` ... LL | _ => yield, | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later @@ -93,12 +93,12 @@ LL | | }; LL | | ); | |_____- in this macro invocation | - = help: within `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `insignificant_dtor::Client`, which is required by `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:21: 17:28}: Send` + = help: within `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:34: 17:41}`, the trait `Send` is not implemented for `insignificant_dtor::Client`, which is required by `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:34: 17:41}: Send` note: coroutine is not `Send` as this value is used across a yield --> $DIR/drop-tracking-parent-expression.rs:21:22 | -LL | let g = move || match drop($name::Client { ..$name::Client::default() }) { - | ------------------------ has type `insignificant_dtor::Client` which is not `Send` +LL | let g = #[coroutine] move || match drop($name::Client { ..$name::Client::default() }) { + | ------------------------ has type `insignificant_dtor::Client` which is not `Send` ... LL | _ => yield, | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later diff --git a/tests/ui/coroutine/drop-tracking-yielding-in-match-guards.rs b/tests/ui/coroutine/drop-tracking-yielding-in-match-guards.rs index 0f94016f11b8..43e42fa85f7f 100644 --- a/tests/ui/coroutine/drop-tracking-yielding-in-match-guards.rs +++ b/tests/ui/coroutine/drop-tracking-yielding-in-match-guards.rs @@ -1,10 +1,10 @@ //@ build-pass //@ edition:2018 -#![feature(coroutines)] +#![feature(coroutines, stmt_expr_attributes)] fn main() { - let _ = static |x: u8| match x { + let _ = #[coroutine] static |x: u8| match x { y if { yield } == y + 1 => (), _ => (), }; diff --git a/tests/ui/coroutine/drop-yield-twice.rs b/tests/ui/coroutine/drop-yield-twice.rs index 015343a27762..7ac1345b2ff2 100644 --- a/tests/ui/coroutine/drop-yield-twice.rs +++ b/tests/ui/coroutine/drop-yield-twice.rs @@ -1,10 +1,10 @@ -#![feature(negative_impls, coroutines)] +#![feature(negative_impls, coroutines, stmt_expr_attributes)] struct Foo(i32); impl !Send for Foo {} fn main() { - assert_send(|| { //~ ERROR coroutine cannot be sent between threads safely + assert_send(#[coroutine] || { //~ ERROR coroutine cannot be sent between threads safely let guard = Foo(42); yield; drop(guard); diff --git a/tests/ui/coroutine/drop-yield-twice.stderr b/tests/ui/coroutine/drop-yield-twice.stderr index c6a9e20b8b51..362c6e943ade 100644 --- a/tests/ui/coroutine/drop-yield-twice.stderr +++ b/tests/ui/coroutine/drop-yield-twice.stderr @@ -1,7 +1,7 @@ error: coroutine cannot be sent between threads safely --> $DIR/drop-yield-twice.rs:7:5 | -LL | / assert_send(|| { +LL | / assert_send(#[coroutine] || { LL | | let guard = Foo(42); LL | | yield; LL | | drop(guard); @@ -9,7 +9,7 @@ LL | | yield; LL | | }) | |______^ coroutine is not `Send` | - = help: within `{coroutine@$DIR/drop-yield-twice.rs:7:17: 7:19}`, the trait `Send` is not implemented for `Foo`, which is required by `{coroutine@$DIR/drop-yield-twice.rs:7:17: 7:19}: Send` + = help: within `{coroutine@$DIR/drop-yield-twice.rs:7:30: 7:32}`, the trait `Send` is not implemented for `Foo`, which is required by `{coroutine@$DIR/drop-yield-twice.rs:7:30: 7:32}: Send` note: coroutine is not `Send` as this value is used across a yield --> $DIR/drop-yield-twice.rs:9:9 | diff --git a/tests/ui/coroutine/dropck-resume.rs b/tests/ui/coroutine/dropck-resume.rs index 07ca4d37aba6..df014400f00f 100644 --- a/tests/ui/coroutine/dropck-resume.rs +++ b/tests/ui/coroutine/dropck-resume.rs @@ -1,4 +1,4 @@ -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] use std::ops::{Coroutine, CoroutineState}; use std::pin::Pin; @@ -16,7 +16,8 @@ fn drop_using_coroutine() -> i32 { let z = &mut y; let r; { - let mut g = move |r| { + let mut g = #[coroutine] + move |r| { let _s = SetToNone(r); yield; }; diff --git a/tests/ui/coroutine/dropck-resume.stderr b/tests/ui/coroutine/dropck-resume.stderr index aa6e423c7604..e9243ffa41e5 100644 --- a/tests/ui/coroutine/dropck-resume.stderr +++ b/tests/ui/coroutine/dropck-resume.stderr @@ -1,5 +1,5 @@ error[E0502]: cannot borrow `y` as immutable because it is also borrowed as mutable - --> $DIR/dropck-resume.rs:25:13 + --> $DIR/dropck-resume.rs:26:13 | LL | let z = &mut y; | ------ mutable borrow occurs here diff --git a/tests/ui/coroutine/dropck.rs b/tests/ui/coroutine/dropck.rs index 450361c8dd03..9331c1fa1d58 100644 --- a/tests/ui/coroutine/dropck.rs +++ b/tests/ui/coroutine/dropck.rs @@ -1,4 +1,4 @@ -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] use std::cell::RefCell; use std::ops::Coroutine; @@ -10,7 +10,8 @@ fn main() { let ref_ = Box::leak(Box::new(Some(cell.borrow_mut()))); //~^ ERROR `*cell` does not live long enough [E0597] // the upvar is the non-dropck `&mut Option>`. - gen = || { + gen = #[coroutine] + || { // but the coroutine can use it to drop a `Ref<'a, i32>`. let _d = ref_.take(); //~ ERROR `ref_` does not live long enough yield; diff --git a/tests/ui/coroutine/dropck.stderr b/tests/ui/coroutine/dropck.stderr index 241d6dfe0a16..d6cd7c4cd47a 100644 --- a/tests/ui/coroutine/dropck.stderr +++ b/tests/ui/coroutine/dropck.stderr @@ -16,10 +16,10 @@ LL | } = note: values in a scope are dropped in the opposite order they are defined error[E0597]: `ref_` does not live long enough - --> $DIR/dropck.rs:15:18 + --> $DIR/dropck.rs:16:18 | -LL | gen = || { - | -- value captured here by coroutine +LL | || { + | -- value captured here by coroutine LL | // but the coroutine can use it to drop a `Ref<'a, i32>`. LL | let _d = ref_.take(); | ^^^^ borrowed value does not live long enough diff --git a/tests/ui/coroutine/gen_block.e2024.stderr b/tests/ui/coroutine/gen_block.e2024.stderr index 2b9eb4a820b6..322259cf2f84 100644 --- a/tests/ui/coroutine/gen_block.e2024.stderr +++ b/tests/ui/coroutine/gen_block.e2024.stderr @@ -1,5 +1,25 @@ +error[E0658]: the `#[coroutines]` attribute is an experimental feature + --> $DIR/gen_block.rs:20:13 + | +LL | let _ = #[coroutine] || yield true; + | ^^^^^^^^^^^^ + | + = note: see issue #43122 for more information + = help: add `#![feature(coroutines)]` 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[E0658]: the `#[coroutines]` attribute is an experimental feature + --> $DIR/gen_block.rs:24:13 + | +LL | let _ = #[coroutine] || {}; + | ^^^^^^^^^^^^ + | + = note: see issue #43122 for more information + = help: add `#![feature(coroutines)]` 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[E0658]: yield syntax is experimental - --> $DIR/gen_block.rs:15:16 + --> $DIR/gen_block.rs:16:16 | LL | let _ = || yield true; | ^^^^^^^^^^ @@ -8,13 +28,34 @@ LL | let _ = || yield true; = help: add `#![feature(coroutines)]` 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: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks + --> $DIR/gen_block.rs:16:16 + | +LL | let _ = || yield true; + | ^^^^^^^^^^ + | +help: use `#[coroutine]` to make this closure a coroutine + | +LL | let _ = #[coroutine] || yield true; + | ++++++++++++ + +error[E0658]: yield syntax is experimental + --> $DIR/gen_block.rs:20:29 + | +LL | let _ = #[coroutine] || yield true; + | ^^^^^^^^^^ + | + = note: see issue #43122 for more information + = help: add `#![feature(coroutines)]` 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[E0282]: type annotations needed - --> $DIR/gen_block.rs:6:13 + --> $DIR/gen_block.rs:7:13 | LL | let x = gen {}; | ^^^^^^ cannot infer type -error: aborting due to 2 previous errors +error: aborting due to 6 previous errors Some errors have detailed explanations: E0282, E0658. For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/coroutine/gen_block.none.stderr b/tests/ui/coroutine/gen_block.none.stderr index 78a8c5e798ad..64fa2be003de 100644 --- a/tests/ui/coroutine/gen_block.none.stderr +++ b/tests/ui/coroutine/gen_block.none.stderr @@ -1,5 +1,5 @@ error: expected identifier, found reserved keyword `yield` - --> $DIR/gen_block.rs:9:19 + --> $DIR/gen_block.rs:10:19 | LL | let y = gen { yield 42 }; | --- ^^^^^ expected identifier, found reserved keyword @@ -7,25 +7,25 @@ LL | let y = gen { yield 42 }; | while parsing this struct error[E0422]: cannot find struct, variant or union type `gen` in this scope - --> $DIR/gen_block.rs:6:13 + --> $DIR/gen_block.rs:7:13 | LL | let x = gen {}; | ^^^ not found in this scope error[E0422]: cannot find struct, variant or union type `gen` in this scope - --> $DIR/gen_block.rs:9:13 + --> $DIR/gen_block.rs:10:13 | LL | let y = gen { yield 42 }; | ^^^ not found in this scope error[E0422]: cannot find struct, variant or union type `gen` in this scope - --> $DIR/gen_block.rs:12:5 + --> $DIR/gen_block.rs:13:5 | LL | gen {}; | ^^^ not found in this scope error[E0658]: yield syntax is experimental - --> $DIR/gen_block.rs:15:16 + --> $DIR/gen_block.rs:16:16 | LL | let _ = || yield true; | ^^^^^^^^^^ @@ -35,7 +35,37 @@ LL | let _ = || yield true; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: yield syntax is experimental - --> $DIR/gen_block.rs:15:16 + --> $DIR/gen_block.rs:20:29 + | +LL | let _ = #[coroutine] || yield true; + | ^^^^^^^^^^ + | + = note: see issue #43122 for more information + = help: add `#![feature(coroutines)]` 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[E0658]: the `#[coroutines]` attribute is an experimental feature + --> $DIR/gen_block.rs:20:13 + | +LL | let _ = #[coroutine] || yield true; + | ^^^^^^^^^^^^ + | + = note: see issue #43122 for more information + = help: add `#![feature(coroutines)]` 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[E0658]: the `#[coroutines]` attribute is an experimental feature + --> $DIR/gen_block.rs:24:13 + | +LL | let _ = #[coroutine] || {}; + | ^^^^^^^^^^^^ + | + = note: see issue #43122 for more information + = help: add `#![feature(coroutines)]` 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[E0658]: yield syntax is experimental + --> $DIR/gen_block.rs:16:16 | LL | let _ = || yield true; | ^^^^^^^^^^ @@ -45,7 +75,29 @@ LL | let _ = || yield true; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 6 previous errors +error: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks + --> $DIR/gen_block.rs:16:16 + | +LL | let _ = || yield true; + | ^^^^^^^^^^ + | +help: use `#[coroutine]` to make this closure a coroutine + | +LL | let _ = #[coroutine] || yield true; + | ++++++++++++ + +error[E0658]: yield syntax is experimental + --> $DIR/gen_block.rs:20:29 + | +LL | let _ = #[coroutine] || yield true; + | ^^^^^^^^^^ + | + = note: see issue #43122 for more information + = help: add `#![feature(coroutines)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 11 previous errors Some errors have detailed explanations: E0422, E0658. For more information about an error, try `rustc --explain E0422`. diff --git a/tests/ui/coroutine/gen_block.rs b/tests/ui/coroutine/gen_block.rs index f6a775aa6619..7e87a572b909 100644 --- a/tests/ui/coroutine/gen_block.rs +++ b/tests/ui/coroutine/gen_block.rs @@ -1,6 +1,7 @@ //@ revisions: e2024 none //@[e2024] compile-flags: --edition 2024 -Zunstable-options #![cfg_attr(e2024, feature(gen_blocks))] +#![feature(stmt_expr_attributes)] fn main() { let x = gen {}; @@ -14,4 +15,12 @@ fn main() { let _ = || yield true; //[none]~ ERROR yield syntax is experimental //~^ ERROR yield syntax is experimental + //~^^ ERROR `yield` can only be used in + + let _ = #[coroutine] || yield true; //[none]~ ERROR yield syntax is experimental + //~^ ERROR `#[coroutines]` attribute is an experimental feature + //~^^ ERROR yield syntax is experimental + + let _ = #[coroutine] || {}; + //~^ ERROR `#[coroutines]` attribute is an experimental feature } diff --git a/tests/ui/coroutine/issue-102645.rs b/tests/ui/coroutine/issue-102645.rs index a0263510e136..ccf82c3606ac 100644 --- a/tests/ui/coroutine/issue-102645.rs +++ b/tests/ui/coroutine/issue-102645.rs @@ -1,11 +1,12 @@ -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] use std::ops::Coroutine; use std::pin::Pin; fn main() { let mut a = 5; - let mut b = || { + let mut b = #[coroutine] + || { let d = 6; yield; _zzz(); // #break diff --git a/tests/ui/coroutine/issue-102645.stderr b/tests/ui/coroutine/issue-102645.stderr index 7a3b7f2b04c3..ab5e4a8459f4 100644 --- a/tests/ui/coroutine/issue-102645.stderr +++ b/tests/ui/coroutine/issue-102645.stderr @@ -1,5 +1,5 @@ error[E0061]: this method takes 1 argument but 0 arguments were supplied - --> $DIR/issue-102645.rs:14:22 + --> $DIR/issue-102645.rs:15:22 | LL | Pin::new(&mut b).resume(); | ^^^^^^-- an argument of type `()` is missing diff --git a/tests/ui/coroutine/issue-105084.rs b/tests/ui/coroutine/issue-105084.rs index 7801f1bcea0d..4e40bc127d78 100644 --- a/tests/ui/coroutine/issue-105084.rs +++ b/tests/ui/coroutine/issue-105084.rs @@ -11,7 +11,8 @@ fn copy(x: T) -> T { } fn main() { - let mut g = || { + let mut g = #[coroutine] + || { // This is desuraged as 4 stages: // - allocate a `*mut u8` with `exchange_malloc`; // - create a Box that is ignored for trait computations; diff --git a/tests/ui/coroutine/issue-105084.stderr b/tests/ui/coroutine/issue-105084.stderr index c8a6522dbd93..6b1701f0c2ab 100644 --- a/tests/ui/coroutine/issue-105084.stderr +++ b/tests/ui/coroutine/issue-105084.stderr @@ -1,8 +1,8 @@ error[E0382]: borrow of moved value: `g` - --> $DIR/issue-105084.rs:37:14 + --> $DIR/issue-105084.rs:38:14 | -LL | let mut g = || { - | ----- move occurs because `g` has type `{coroutine@$DIR/issue-105084.rs:14:17: 14:19}`, which does not implement the `Copy` trait +LL | let mut g = #[coroutine] + | ----- move occurs because `g` has type `{coroutine@$DIR/issue-105084.rs:15:5: 15:7}`, which does not implement the `Copy` trait ... LL | let mut h = copy(g); | - value moved here @@ -22,17 +22,17 @@ help: consider cloning the value if the performance cost is acceptable LL | let mut h = copy(g.clone()); | ++++++++ -error[E0277]: the trait bound `Box<(i32, ())>: Copy` is not satisfied in `{coroutine@$DIR/issue-105084.rs:14:17: 14:19}` - --> $DIR/issue-105084.rs:31:17 +error[E0277]: the trait bound `Box<(i32, ())>: Copy` is not satisfied in `{coroutine@$DIR/issue-105084.rs:15:5: 15:7}` + --> $DIR/issue-105084.rs:32:17 | -LL | let mut g = || { - | -- within this `{coroutine@$DIR/issue-105084.rs:14:17: 14:19}` +LL | || { + | -- within this `{coroutine@$DIR/issue-105084.rs:15:5: 15:7}` ... LL | let mut h = copy(g); - | ^^^^^^^ within `{coroutine@$DIR/issue-105084.rs:14:17: 14:19}`, the trait `Copy` is not implemented for `Box<(i32, ())>`, which is required by `{coroutine@$DIR/issue-105084.rs:14:17: 14:19}: Copy` + | ^^^^^^^ within `{coroutine@$DIR/issue-105084.rs:15:5: 15:7}`, the trait `Copy` is not implemented for `Box<(i32, ())>`, which is required by `{coroutine@$DIR/issue-105084.rs:15:5: 15:7}: Copy` | note: coroutine does not implement `Copy` as this value is used across a yield - --> $DIR/issue-105084.rs:21:22 + --> $DIR/issue-105084.rs:22:22 | LL | Box::new((5, yield)); | -------------^^^^^-- diff --git a/tests/ui/coroutine/issue-110929-coroutine-conflict-error-ice.rs b/tests/ui/coroutine/issue-110929-coroutine-conflict-error-ice.rs index 3d372ac9110c..300c8fe6d461 100644 --- a/tests/ui/coroutine/issue-110929-coroutine-conflict-error-ice.rs +++ b/tests/ui/coroutine/issue-110929-coroutine-conflict-error-ice.rs @@ -1,11 +1,12 @@ //@ edition:2021 //@ check-pass -#![feature(coroutines)] +#![feature(coroutines, stmt_expr_attributes)] fn main() { let x = &mut (); || { - let _c = || yield *&mut *x; + let _c = #[coroutine] + || yield *&mut *x; || _ = &mut *x; }; } diff --git a/tests/ui/coroutine/issue-113279.rs b/tests/ui/coroutine/issue-113279.rs index f251c924c133..98617af105c3 100644 --- a/tests/ui/coroutine/issue-113279.rs +++ b/tests/ui/coroutine/issue-113279.rs @@ -1,4 +1,4 @@ -#![feature(coroutines)] +#![feature(coroutines, stmt_expr_attributes)] // `foo` attempts to dereference `""`, which results in an error being reported. Later, the // coroutine transform for `foo` then produces a union which contains a `str` type - unions should @@ -9,7 +9,8 @@ // makes sure that doesn't happen again. fn foo() { - let _y = static || { + let _y = #[coroutine] + static || { let x = &mut 0; *{ yield; diff --git a/tests/ui/coroutine/issue-113279.stderr b/tests/ui/coroutine/issue-113279.stderr index cc9b64ef9ac2..a80fe670188d 100644 --- a/tests/ui/coroutine/issue-113279.stderr +++ b/tests/ui/coroutine/issue-113279.stderr @@ -1,11 +1,11 @@ error[E0161]: cannot move a value of type `str` - --> $DIR/issue-113279.rs:17:20 + --> $DIR/issue-113279.rs:18:20 | LL | } += match { *"" }.len() { | ^^^^^^^ the size of `str` cannot be statically determined error[E0507]: cannot move out of a shared reference - --> $DIR/issue-113279.rs:17:22 + --> $DIR/issue-113279.rs:18:22 | LL | } += match { *"" }.len() { | ^^^ move occurs because value has type `str`, which does not implement the `Copy` trait diff --git a/tests/ui/coroutine/issue-44197.rs b/tests/ui/coroutine/issue-44197.rs index e18bcc2c996f..0240f7a7eaac 100644 --- a/tests/ui/coroutine/issue-44197.rs +++ b/tests/ui/coroutine/issue-44197.rs @@ -10,7 +10,7 @@ fn foo(_: &str) -> String { } fn bar(baz: String) -> impl Coroutine<(), Yield = String, Return = ()> { - move || { + #[coroutine] move || { yield foo(&baz); } } @@ -20,7 +20,7 @@ fn foo2(_: &str) -> Result { } fn bar2(baz: String) -> impl Coroutine<(), Yield = String, Return = ()> { - move || { + #[coroutine] move || { if let Ok(quux) = foo2(&baz) { yield quux; } diff --git a/tests/ui/coroutine/issue-45729-unsafe-in-coroutine.rs b/tests/ui/coroutine/issue-45729-unsafe-in-coroutine.rs index dab9c81bc8fe..d90886b6b1d6 100644 --- a/tests/ui/coroutine/issue-45729-unsafe-in-coroutine.rs +++ b/tests/ui/coroutine/issue-45729-unsafe-in-coroutine.rs @@ -1,7 +1,8 @@ -#![feature(coroutines)] +#![feature(coroutines, stmt_expr_attributes)] fn main() { - let _ = || { + let _ = #[coroutine] + || { *(1 as *mut u32) = 42; //~^ ERROR dereference of raw pointer is unsafe yield; diff --git a/tests/ui/coroutine/issue-45729-unsafe-in-coroutine.stderr b/tests/ui/coroutine/issue-45729-unsafe-in-coroutine.stderr index 19949b429396..f99c295bb9eb 100644 --- a/tests/ui/coroutine/issue-45729-unsafe-in-coroutine.stderr +++ b/tests/ui/coroutine/issue-45729-unsafe-in-coroutine.stderr @@ -1,5 +1,5 @@ error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block - --> $DIR/issue-45729-unsafe-in-coroutine.rs:5:9 + --> $DIR/issue-45729-unsafe-in-coroutine.rs:6:9 | LL | *(1 as *mut u32) = 42; | ^^^^^^^^^^^^^^^^ dereference of raw pointer diff --git a/tests/ui/coroutine/issue-48048.rs b/tests/ui/coroutine/issue-48048.rs index b61b7c770723..75664f20198b 100644 --- a/tests/ui/coroutine/issue-48048.rs +++ b/tests/ui/coroutine/issue-48048.rs @@ -3,7 +3,7 @@ fn main() { let x = (|_| {},); - || { + #[coroutine] || { let x = x; x.0({ //~ ERROR borrow may still be in use when coroutine yields diff --git a/tests/ui/coroutine/issue-52304.rs b/tests/ui/coroutine/issue-52304.rs index 01ed181ab1dc..552bc0028ee0 100644 --- a/tests/ui/coroutine/issue-52304.rs +++ b/tests/ui/coroutine/issue-52304.rs @@ -5,6 +5,7 @@ use std::ops::Coroutine; pub fn example() -> impl Coroutine { + #[coroutine] || yield &1 } diff --git a/tests/ui/coroutine/issue-52398.rs b/tests/ui/coroutine/issue-52398.rs index 826ce6b9d9b3..f8b2faf4eabf 100644 --- a/tests/ui/coroutine/issue-52398.rs +++ b/tests/ui/coroutine/issue-52398.rs @@ -14,14 +14,14 @@ impl A { fn main() { // Test that the MIR local with type &A created for the auto-borrow adjustment // is caught by typeck - move || { //~ WARN unused coroutine that must be used + #[coroutine] move || { //~ WARN unused coroutine that must be used A.test(yield); }; // Test that the std::cell::Ref temporary returned from the `borrow` call // is caught by typeck let y = RefCell::new(true); - static move || { //~ WARN unused coroutine that must be used + #[coroutine] static move || { //~ WARN unused coroutine that must be used yield *y.borrow(); return "Done"; }; diff --git a/tests/ui/coroutine/issue-52398.stderr b/tests/ui/coroutine/issue-52398.stderr index 18d816da4c61..806690cc3327 100644 --- a/tests/ui/coroutine/issue-52398.stderr +++ b/tests/ui/coroutine/issue-52398.stderr @@ -1,7 +1,8 @@ warning: unused coroutine that must be used - --> $DIR/issue-52398.rs:17:5 + --> $DIR/issue-52398.rs:17:18 | -LL | / move || { +LL | #[coroutine] move || { + | __________________^ LL | | A.test(yield); LL | | }; | |_____^ @@ -10,9 +11,10 @@ LL | | }; = note: `#[warn(unused_must_use)]` on by default warning: unused coroutine that must be used - --> $DIR/issue-52398.rs:24:5 + --> $DIR/issue-52398.rs:24:18 | -LL | / static move || { +LL | #[coroutine] static move || { + | __________________^ LL | | yield *y.borrow(); LL | | return "Done"; LL | | }; diff --git a/tests/ui/coroutine/issue-53548.rs b/tests/ui/coroutine/issue-53548.rs index 6d55994137ff..3b8dff2be28c 100644 --- a/tests/ui/coroutine/issue-53548.rs +++ b/tests/ui/coroutine/issue-53548.rs @@ -17,7 +17,7 @@ // //@ check-pass -#![feature(coroutines)] +#![feature(coroutines, stmt_expr_attributes)] use std::cell::RefCell; use std::rc::Rc; @@ -29,7 +29,7 @@ struct Store { } fn main() { - Box::new(static move || { + Box::new(#[coroutine] static move || { let store = Store::> { inner: Default::default(), }; diff --git a/tests/ui/coroutine/issue-57017.rs b/tests/ui/coroutine/issue-57017.rs index b83d916932ab..19cd80ab4a65 100644 --- a/tests/ui/coroutine/issue-57017.rs +++ b/tests/ui/coroutine/issue-57017.rs @@ -1,5 +1,5 @@ //@ build-pass -#![feature(coroutines, negative_impls)] +#![feature(coroutines, negative_impls, stmt_expr_attributes)] #![allow(dropping_references, dropping_copy_types)] macro_rules! type_combinations { @@ -21,7 +21,7 @@ macro_rules! type_combinations { // This is the same bug as issue 57017, but using yield instead of await { - let g = move || match drop(&$name::unsync::Client::default()) { + let g = #[coroutine] move || match drop(&$name::unsync::Client::default()) { _status => yield, }; assert_send(g); @@ -30,7 +30,7 @@ macro_rules! type_combinations { // This tests that `Client` is properly considered to be dropped after moving it into the // function. { - let g = move || match drop($name::unsend::Client::default()) { + let g = #[coroutine] move || match drop($name::unsend::Client::default()) { _status => yield, }; assert_send(g); diff --git a/tests/ui/coroutine/issue-57084.rs b/tests/ui/coroutine/issue-57084.rs index 51b0c8e1de96..2df60550e037 100644 --- a/tests/ui/coroutine/issue-57084.rs +++ b/tests/ui/coroutine/issue-57084.rs @@ -8,7 +8,7 @@ use std::ops::Coroutine; fn with(f: F) -> impl Coroutine where F: Fn() -> () { - move || { + #[coroutine] move || { loop { match f() { _ => yield, @@ -19,7 +19,7 @@ where F: Fn() -> () fn main() { let data = &vec![1]; - || { //~ WARN unused coroutine that must be used + #[coroutine] || { //~ WARN unused coroutine that must be used let _to_pin = with(move || println!("{:p}", data)); loop { yield diff --git a/tests/ui/coroutine/issue-57084.stderr b/tests/ui/coroutine/issue-57084.stderr index 9f5b79a6ae8a..81bd27da9190 100644 --- a/tests/ui/coroutine/issue-57084.stderr +++ b/tests/ui/coroutine/issue-57084.stderr @@ -1,7 +1,8 @@ warning: unused coroutine that must be used - --> $DIR/issue-57084.rs:22:5 + --> $DIR/issue-57084.rs:22:18 | -LL | / || { +LL | #[coroutine] || { + | __________________^ LL | | let _to_pin = with(move || println!("{:p}", data)); LL | | loop { LL | | yield diff --git a/tests/ui/coroutine/issue-57478.rs b/tests/ui/coroutine/issue-57478.rs index 5e479aaa9c1b..494c2ee9843e 100644 --- a/tests/ui/coroutine/issue-57478.rs +++ b/tests/ui/coroutine/issue-57478.rs @@ -1,16 +1,19 @@ //@ check-pass -#![feature(negative_impls, coroutines)] +#![feature(negative_impls, coroutines, stmt_expr_attributes)] struct Foo; impl !Send for Foo {} fn main() { - assert_send(|| { - let guard = Foo; - drop(guard); - yield; - }) + assert_send( + #[coroutine] + || { + let guard = Foo; + drop(guard); + yield; + }, + ) } fn assert_send(_: T) {} diff --git a/tests/ui/coroutine/issue-58888.rs b/tests/ui/coroutine/issue-58888.rs index ce45f22dd6ef..6266f97ce8c4 100644 --- a/tests/ui/coroutine/issue-58888.rs +++ b/tests/ui/coroutine/issue-58888.rs @@ -13,7 +13,7 @@ impl Database { } fn check_connection(&self) -> impl Coroutine + '_ { - move || { + #[coroutine] move || { let iter = self.get_connection(); for i in iter { yield i diff --git a/tests/ui/coroutine/issue-61442-stmt-expr-with-drop.rs b/tests/ui/coroutine/issue-61442-stmt-expr-with-drop.rs index 6280b777201f..6f513c250a55 100644 --- a/tests/ui/coroutine/issue-61442-stmt-expr-with-drop.rs +++ b/tests/ui/coroutine/issue-61442-stmt-expr-with-drop.rs @@ -4,7 +4,7 @@ //@ check-pass //@ edition:2018 -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] use std::ops::Coroutine; @@ -14,12 +14,14 @@ async fn drop_and_await() { } fn drop_and_yield() { - let x = || { + let x = #[coroutine] + || { String::new(); yield; }; Box::pin(x).as_mut().resume(()); - let y = static || { + let y = #[coroutine] + static || { String::new(); yield; }; diff --git a/tests/ui/coroutine/issue-64620-yield-array-element.rs b/tests/ui/coroutine/issue-64620-yield-array-element.rs index a9307d306a61..0d898d014e80 100644 --- a/tests/ui/coroutine/issue-64620-yield-array-element.rs +++ b/tests/ui/coroutine/issue-64620-yield-array-element.rs @@ -4,6 +4,7 @@ pub fn crash(arr: [usize; 1]) { yield arr[0]; //~ ERROR: yield expression outside of coroutine literal + //~^ ERROR: `yield` can only be used in } fn main() {} diff --git a/tests/ui/coroutine/issue-64620-yield-array-element.stderr b/tests/ui/coroutine/issue-64620-yield-array-element.stderr index 347532fb7193..1c030c5248e1 100644 --- a/tests/ui/coroutine/issue-64620-yield-array-element.stderr +++ b/tests/ui/coroutine/issue-64620-yield-array-element.stderr @@ -1,9 +1,20 @@ +error: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks + --> $DIR/issue-64620-yield-array-element.rs:6:5 + | +LL | yield arr[0]; + | ^^^^^^^^^^^^ + | +help: use `#[coroutine]` to make this closure a coroutine + | +LL | #[coroutine] pub fn crash(arr: [usize; 1]) { + | ++++++++++++ + error[E0627]: yield expression outside of coroutine literal --> $DIR/issue-64620-yield-array-element.rs:6:5 | LL | yield arr[0]; | ^^^^^^^^^^^^ -error: aborting due to 1 previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0627`. diff --git a/tests/ui/coroutine/issue-68112.rs b/tests/ui/coroutine/issue-68112.rs index ccec2acc9762..b296772c9057 100644 --- a/tests/ui/coroutine/issue-68112.rs +++ b/tests/ui/coroutine/issue-68112.rs @@ -1,4 +1,4 @@ -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] use std::{ cell::RefCell, @@ -30,7 +30,7 @@ fn make_non_send_coroutine() -> impl Coroutine>> { } fn test1() { - let send_gen = || { + let send_gen = #[coroutine] || { let _non_send_gen = make_non_send_coroutine(); //~^ NOTE not `Send` yield; @@ -46,7 +46,7 @@ fn test1() { pub fn make_gen2(t: T) -> impl Coroutine { //~^ NOTE appears within the type //~| NOTE expansion of desugaring - || { //~ NOTE used within this coroutine + #[coroutine] || { //~ NOTE used within this coroutine yield; t } @@ -57,7 +57,7 @@ fn make_non_send_coroutine2() -> impl Coroutine>> { // } fn test2() { - let send_gen = || { //~ NOTE used within this coroutine + let send_gen = #[coroutine] || { //~ NOTE used within this coroutine let _non_send_gen = make_non_send_coroutine2(); yield; }; diff --git a/tests/ui/coroutine/issue-68112.stderr b/tests/ui/coroutine/issue-68112.stderr index 443195d36a30..bcfcb5ec6e60 100644 --- a/tests/ui/coroutine/issue-68112.stderr +++ b/tests/ui/coroutine/issue-68112.stderr @@ -4,7 +4,7 @@ error: coroutine cannot be sent between threads safely LL | require_send(send_gen); | ^^^^^^^^^^^^^^^^^^^^^^ coroutine is not `Send` | - = help: the trait `Sync` is not implemented for `RefCell`, which is required by `{coroutine@$DIR/issue-68112.rs:33:20: 33:22}: Send` + = help: the trait `Sync` is not implemented for `RefCell`, which is required by `{coroutine@$DIR/issue-68112.rs:33:33: 33:35}: Send` = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead note: coroutine is not `Send` as this value is used across a yield --> $DIR/issue-68112.rs:36:9 @@ -26,14 +26,14 @@ error[E0277]: `RefCell` cannot be shared between threads safely LL | require_send(send_gen); | ^^^^^^^^^^^^^^^^^^^^^^ `RefCell` cannot be shared between threads safely | - = help: the trait `Sync` is not implemented for `RefCell`, which is required by `{coroutine@$DIR/issue-68112.rs:60:20: 60:22}: Send` + = help: the trait `Sync` is not implemented for `RefCell`, which is required by `{coroutine@$DIR/issue-68112.rs:60:33: 60:35}: Send` = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead = note: required for `Arc>` to implement `Send` note: required because it's used within this coroutine - --> $DIR/issue-68112.rs:49:5 + --> $DIR/issue-68112.rs:49:18 | -LL | || { - | ^^ +LL | #[coroutine] || { + | ^^ note: required because it appears within the type `impl Coroutine>>` --> $DIR/issue-68112.rs:46:30 | @@ -45,10 +45,10 @@ note: required because it appears within the type `impl Coroutine impl Coroutine>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: required because it's used within this coroutine - --> $DIR/issue-68112.rs:60:20 + --> $DIR/issue-68112.rs:60:33 | -LL | let send_gen = || { - | ^^ +LL | let send_gen = #[coroutine] || { + | ^^ note: required by a bound in `require_send` --> $DIR/issue-68112.rs:22:25 | diff --git a/tests/ui/coroutine/issue-69017.rs b/tests/ui/coroutine/issue-69017.rs index 09bbf63a986e..bf69e1dfdb13 100644 --- a/tests/ui/coroutine/issue-69017.rs +++ b/tests/ui/coroutine/issue-69017.rs @@ -10,6 +10,7 @@ use std::ops::Coroutine; fn gen() -> impl Coroutine { + #[coroutine] |_: usize| { println!("-> {}", yield); } diff --git a/tests/ui/coroutine/issue-69039.rs b/tests/ui/coroutine/issue-69039.rs index fd12414c3d85..13cb50e58281 100644 --- a/tests/ui/coroutine/issue-69039.rs +++ b/tests/ui/coroutine/issue-69039.rs @@ -9,6 +9,7 @@ fn mkstr(my_name: String, my_mood: String) -> String { } fn my_scenario() -> impl Coroutine { + #[coroutine] |_arg: String| { let my_name = yield "What is your name?"; let my_mood = yield "How are you feeling?"; diff --git a/tests/ui/coroutine/issue-87142.rs b/tests/ui/coroutine/issue-87142.rs index f5c3805842c5..6c22ba3dd756 100644 --- a/tests/ui/coroutine/issue-87142.rs +++ b/tests/ui/coroutine/issue-87142.rs @@ -22,6 +22,7 @@ pub struct Context { impl CoroutineProviderAlt for () { type Coro = impl Coroutine<(), Return = (), Yield = ()>; fn start(ctx: Context) -> Self::Coro { + #[coroutine] move || { match ctx { _ => (), diff --git a/tests/ui/coroutine/issue-88653.rs b/tests/ui/coroutine/issue-88653.rs index ec4c20547587..3afd12a20937 100644 --- a/tests/ui/coroutine/issue-88653.rs +++ b/tests/ui/coroutine/issue-88653.rs @@ -11,6 +11,7 @@ fn foo(bar: bool) -> impl Coroutine<(bool,)> { //~| NOTE: expected coroutine signature `fn((bool,)) -> _` //~| NOTE: in this expansion of desugaring of `impl Trait` //~| NOTE: in this expansion of desugaring of `impl Trait` + #[coroutine] |bar| { //~^ NOTE: found signature defined here if bar { diff --git a/tests/ui/coroutine/issue-91477.rs b/tests/ui/coroutine/issue-91477.rs index c98546f7971c..c215fd7948f3 100644 --- a/tests/ui/coroutine/issue-91477.rs +++ b/tests/ui/coroutine/issue-91477.rs @@ -2,6 +2,7 @@ fn foo() -> impl Sized { yield 1; //~ ERROR E0627 + //~^ ERROR: `yield` can only be used in } fn main() {} diff --git a/tests/ui/coroutine/issue-91477.stderr b/tests/ui/coroutine/issue-91477.stderr index ca8e43d8a26d..5e2151c4c35f 100644 --- a/tests/ui/coroutine/issue-91477.stderr +++ b/tests/ui/coroutine/issue-91477.stderr @@ -1,9 +1,20 @@ +error: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks + --> $DIR/issue-91477.rs:4:5 + | +LL | yield 1; + | ^^^^^^^ + | +help: use `#[coroutine]` to make this closure a coroutine + | +LL | #[coroutine] fn foo() -> impl Sized { + | ++++++++++++ + error[E0627]: yield expression outside of coroutine literal --> $DIR/issue-91477.rs:4:5 | LL | yield 1; | ^^^^^^^ -error: aborting due to 1 previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0627`. diff --git a/tests/ui/coroutine/iterator-count.rs b/tests/ui/coroutine/iterator-count.rs index bb202ab2d33e..1ca8ceaed2a9 100644 --- a/tests/ui/coroutine/iterator-count.rs +++ b/tests/ui/coroutine/iterator-count.rs @@ -21,6 +21,7 @@ impl + Unpin> Iterator for W { } fn test() -> impl Coroutine<(), Return = (), Yield = u8> + Unpin { + #[coroutine] || { for i in 1..6 { yield i @@ -32,6 +33,7 @@ fn main() { let end = 11; let closure_test = |start| { + #[coroutine] move || { for i in start..end { yield i diff --git a/tests/ui/coroutine/live-upvar-across-yield.rs b/tests/ui/coroutine/live-upvar-across-yield.rs index 86c4716c9516..d13d480dcdcc 100644 --- a/tests/ui/coroutine/live-upvar-across-yield.rs +++ b/tests/ui/coroutine/live-upvar-across-yield.rs @@ -1,13 +1,13 @@ //@ run-pass -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] use std::ops::Coroutine; use std::pin::Pin; fn main() { let b = |_| 3; - let mut a = || { + let mut a = #[coroutine] || { b(yield); }; Pin::new(&mut a).resume(()); diff --git a/tests/ui/coroutine/match-bindings.rs b/tests/ui/coroutine/match-bindings.rs index 9ea1deaab362..2a0cd9af9f38 100644 --- a/tests/ui/coroutine/match-bindings.rs +++ b/tests/ui/coroutine/match-bindings.rs @@ -9,7 +9,7 @@ enum Enum { } fn main() { - || { //~ WARN unused coroutine that must be used + #[coroutine] || { //~ WARN unused coroutine that must be used loop { if let true = true { match Enum::A(String::new()) { diff --git a/tests/ui/coroutine/match-bindings.stderr b/tests/ui/coroutine/match-bindings.stderr index a7aa6eadb95f..5525bfed1165 100644 --- a/tests/ui/coroutine/match-bindings.stderr +++ b/tests/ui/coroutine/match-bindings.stderr @@ -1,7 +1,8 @@ warning: unused coroutine that must be used - --> $DIR/match-bindings.rs:12:5 + --> $DIR/match-bindings.rs:12:18 | -LL | / || { +LL | #[coroutine] || { + | __________________^ LL | | loop { LL | | if let true = true { LL | | match Enum::A(String::new()) { diff --git a/tests/ui/coroutine/missing_coroutine_attr_suggestion.fixed b/tests/ui/coroutine/missing_coroutine_attr_suggestion.fixed new file mode 100644 index 000000000000..128f09a11843 --- /dev/null +++ b/tests/ui/coroutine/missing_coroutine_attr_suggestion.fixed @@ -0,0 +1,8 @@ +//@ run-rustfix + +#![feature(coroutines, gen_blocks, stmt_expr_attributes)] + +fn main() { + let _ = #[coroutine] || yield; + //~^ ERROR `yield` can only be used +} diff --git a/tests/ui/coroutine/missing_coroutine_attr_suggestion.rs b/tests/ui/coroutine/missing_coroutine_attr_suggestion.rs new file mode 100644 index 000000000000..dc9525914960 --- /dev/null +++ b/tests/ui/coroutine/missing_coroutine_attr_suggestion.rs @@ -0,0 +1,8 @@ +//@ run-rustfix + +#![feature(coroutines, gen_blocks, stmt_expr_attributes)] + +fn main() { + let _ = || yield; + //~^ ERROR `yield` can only be used +} diff --git a/tests/ui/coroutine/missing_coroutine_attr_suggestion.stderr b/tests/ui/coroutine/missing_coroutine_attr_suggestion.stderr new file mode 100644 index 000000000000..8d92471a361c --- /dev/null +++ b/tests/ui/coroutine/missing_coroutine_attr_suggestion.stderr @@ -0,0 +1,13 @@ +error: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks + --> $DIR/missing_coroutine_attr_suggestion.rs:6:16 + | +LL | let _ = || yield; + | ^^^^^ + | +help: use `#[coroutine]` to make this closure a coroutine + | +LL | let _ = #[coroutine] || yield; + | ++++++++++++ + +error: aborting due to 1 previous error + diff --git a/tests/ui/coroutine/nested_coroutine.rs b/tests/ui/coroutine/nested_coroutine.rs index 7ff97abf4bb1..2c12ab2adad4 100644 --- a/tests/ui/coroutine/nested_coroutine.rs +++ b/tests/ui/coroutine/nested_coroutine.rs @@ -1,13 +1,15 @@ //@ run-pass -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] use std::ops::{Coroutine, CoroutineState}; use std::pin::Pin; fn main() { - let _coroutine = || { - let mut sub_coroutine = || { + let _coroutine = #[coroutine] + || { + let mut sub_coroutine = #[coroutine] + || { yield 2; }; diff --git a/tests/ui/coroutine/niche-in-coroutine.rs b/tests/ui/coroutine/niche-in-coroutine.rs index 45b920ab9273..117ee9e6f038 100644 --- a/tests/ui/coroutine/niche-in-coroutine.rs +++ b/tests/ui/coroutine/niche-in-coroutine.rs @@ -2,7 +2,7 @@ //@ run-pass -#![feature(coroutines)] +#![feature(coroutines, stmt_expr_attributes)] use std::mem::size_of_val; @@ -10,7 +10,7 @@ fn take(_: T) {} fn main() { let x = false; - let gen1 = || { + let gen1 = #[coroutine] || { yield; take(x); }; diff --git a/tests/ui/coroutine/non-static-is-unpin.rs b/tests/ui/coroutine/non-static-is-unpin.rs index 616a78d5fe2a..b28bf1977145 100644 --- a/tests/ui/coroutine/non-static-is-unpin.rs +++ b/tests/ui/coroutine/non-static-is-unpin.rs @@ -3,7 +3,7 @@ //@[next] compile-flags: -Znext-solver //@ run-pass -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] #![allow(dropping_copy_types)] use std::marker::PhantomPinned; @@ -14,7 +14,7 @@ fn assert_unpin(_: G) { fn main() { // Even though this coroutine holds a `PhantomPinned` in its environment, it // remains `Unpin`. - assert_unpin(|| { + assert_unpin(#[coroutine] || { let pinned = PhantomPinned; yield; drop(pinned); diff --git a/tests/ui/coroutine/not-send-sync.rs b/tests/ui/coroutine/not-send-sync.rs index dd6182c10de0..a46dcd14e882 100644 --- a/tests/ui/coroutine/not-send-sync.rs +++ b/tests/ui/coroutine/not-send-sync.rs @@ -1,4 +1,4 @@ -#![feature(coroutines)] +#![feature(coroutines, stmt_expr_attributes)] #![feature(negative_impls)] struct NotSend; @@ -11,14 +11,14 @@ fn main() { fn assert_sync(_: T) {} fn assert_send(_: T) {} - assert_sync(|| { + assert_sync(#[coroutine] || { //~^ ERROR: coroutine cannot be shared between threads safely let a = NotSync; yield; drop(a); }); - assert_send(|| { + assert_send(#[coroutine] || { //~^ ERROR: coroutine cannot be sent between threads safely let a = NotSend; yield; diff --git a/tests/ui/coroutine/not-send-sync.stderr b/tests/ui/coroutine/not-send-sync.stderr index 9228340c710d..0f9cbdec1300 100644 --- a/tests/ui/coroutine/not-send-sync.stderr +++ b/tests/ui/coroutine/not-send-sync.stderr @@ -1,7 +1,7 @@ error: coroutine cannot be shared between threads safely --> $DIR/not-send-sync.rs:14:5 | -LL | / assert_sync(|| { +LL | / assert_sync(#[coroutine] || { LL | | LL | | let a = NotSync; LL | | yield; @@ -9,7 +9,7 @@ LL | | drop(a); LL | | }); | |______^ coroutine is not `Sync` | - = help: within `{coroutine@$DIR/not-send-sync.rs:14:17: 14:19}`, the trait `Sync` is not implemented for `NotSync`, which is required by `{coroutine@$DIR/not-send-sync.rs:14:17: 14:19}: Sync` + = help: within `{coroutine@$DIR/not-send-sync.rs:14:30: 14:32}`, the trait `Sync` is not implemented for `NotSync`, which is required by `{coroutine@$DIR/not-send-sync.rs:14:30: 14:32}: Sync` note: coroutine is not `Sync` as this value is used across a yield --> $DIR/not-send-sync.rs:17:9 | @@ -26,7 +26,7 @@ LL | fn assert_sync(_: T) {} error: coroutine cannot be sent between threads safely --> $DIR/not-send-sync.rs:21:5 | -LL | / assert_send(|| { +LL | / assert_send(#[coroutine] || { LL | | LL | | let a = NotSend; LL | | yield; @@ -34,7 +34,7 @@ LL | | drop(a); LL | | }); | |______^ coroutine is not `Send` | - = help: within `{coroutine@$DIR/not-send-sync.rs:21:17: 21:19}`, the trait `Send` is not implemented for `NotSend`, which is required by `{coroutine@$DIR/not-send-sync.rs:21:17: 21:19}: Send` + = help: within `{coroutine@$DIR/not-send-sync.rs:21:30: 21:32}`, the trait `Send` is not implemented for `NotSend`, which is required by `{coroutine@$DIR/not-send-sync.rs:21:30: 21:32}: Send` note: coroutine is not `Send` as this value is used across a yield --> $DIR/not-send-sync.rs:24:9 | diff --git a/tests/ui/coroutine/overlap-locals.rs b/tests/ui/coroutine/overlap-locals.rs index eea8595ed06f..9cfa6e2a76dd 100644 --- a/tests/ui/coroutine/overlap-locals.rs +++ b/tests/ui/coroutine/overlap-locals.rs @@ -1,9 +1,10 @@ //@ run-pass -#![feature(coroutines)] +#![feature(coroutines, stmt_expr_attributes)] fn main() { - let a = || { + let a = #[coroutine] + || { { let w: i32 = 4; yield; diff --git a/tests/ui/coroutine/panic-drops-resume.rs b/tests/ui/coroutine/panic-drops-resume.rs index 6d026e6edc8a..b23666b7885f 100644 --- a/tests/ui/coroutine/panic-drops-resume.rs +++ b/tests/ui/coroutine/panic-drops-resume.rs @@ -3,7 +3,7 @@ //@ run-pass //@ needs-unwind -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] use std::ops::Coroutine; use std::panic::{catch_unwind, AssertUnwindSafe}; @@ -21,7 +21,7 @@ impl Drop for Dropper { } fn main() { - let mut gen = |_arg| { + let mut gen = #[coroutine] |_arg| { if true { panic!(); } diff --git a/tests/ui/coroutine/panic-drops.rs b/tests/ui/coroutine/panic-drops.rs index c99abdc72461..8c2cf560f2ac 100644 --- a/tests/ui/coroutine/panic-drops.rs +++ b/tests/ui/coroutine/panic-drops.rs @@ -1,8 +1,7 @@ //@ run-pass //@ needs-unwind - -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] use std::ops::Coroutine; use std::panic; @@ -25,7 +24,8 @@ fn bool_true() -> bool { fn main() { let b = B; - let mut foo = || { + let mut foo = #[coroutine] + || { if bool_true() { panic!(); } @@ -34,13 +34,12 @@ fn main() { }; assert_eq!(A.load(Ordering::SeqCst), 0); - let res = panic::catch_unwind(panic::AssertUnwindSafe(|| { - Pin::new(&mut foo).resume(()) - })); + let res = panic::catch_unwind(panic::AssertUnwindSafe(|| Pin::new(&mut foo).resume(()))); assert!(res.is_err()); assert_eq!(A.load(Ordering::SeqCst), 1); - let mut foo = || { + let mut foo = #[coroutine] + || { if bool_true() { panic!(); } @@ -49,9 +48,7 @@ fn main() { }; assert_eq!(A.load(Ordering::SeqCst), 1); - let res = panic::catch_unwind(panic::AssertUnwindSafe(|| { - Pin::new(&mut foo).resume(()) - })); + let res = panic::catch_unwind(panic::AssertUnwindSafe(|| Pin::new(&mut foo).resume(()))); assert!(res.is_err()); assert_eq!(A.load(Ordering::SeqCst), 1); } diff --git a/tests/ui/coroutine/panic-safe.rs b/tests/ui/coroutine/panic-safe.rs index 89dd09bf5203..6b9b4cb33c32 100644 --- a/tests/ui/coroutine/panic-safe.rs +++ b/tests/ui/coroutine/panic-safe.rs @@ -2,14 +2,14 @@ //@ needs-unwind -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] use std::ops::Coroutine; use std::pin::Pin; use std::panic; fn main() { - let mut foo = || { + let mut foo = #[coroutine] || { if true { panic!(); } diff --git a/tests/ui/coroutine/parent-expression.rs b/tests/ui/coroutine/parent-expression.rs index 4d40192c07a2..0f4d99c89364 100644 --- a/tests/ui/coroutine/parent-expression.rs +++ b/tests/ui/coroutine/parent-expression.rs @@ -1,4 +1,4 @@ -#![feature(coroutines, negative_impls, rustc_attrs)] +#![feature(coroutines, negative_impls, rustc_attrs, stmt_expr_attributes)] macro_rules! type_combinations { ( @@ -14,7 +14,7 @@ macro_rules! type_combinations { // Struct update syntax. This fails because the Client used in the update is considered // dropped *after* the yield. { - let g = move || match drop($name::Client { ..$name::Client::default() }) { + let g = #[coroutine] move || match drop($name::Client { ..$name::Client::default() }) { //~^ `significant_drop::Client` which is not `Send` //~| `insignificant_dtor::Client` which is not `Send` //~| `derived_drop::Client` which is not `Send` @@ -29,7 +29,7 @@ macro_rules! type_combinations { // Simple owned value. This works because the Client is considered moved into `drop`, // even though the temporary expression doesn't end until after the yield. { - let g = move || match drop($name::Client::default()) { + let g = #[coroutine] move || match drop($name::Client::default()) { _ => yield, }; assert_send(g); diff --git a/tests/ui/coroutine/parent-expression.stderr b/tests/ui/coroutine/parent-expression.stderr index 5b3737069e6c..2d817f1bfd9c 100644 --- a/tests/ui/coroutine/parent-expression.stderr +++ b/tests/ui/coroutine/parent-expression.stderr @@ -13,12 +13,12 @@ LL | | }; LL | | ); | |_____- in this macro invocation | - = help: within `{coroutine@$DIR/parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `derived_drop::Client`, which is required by `{coroutine@$DIR/parent-expression.rs:17:21: 17:28}: Send` + = help: within `{coroutine@$DIR/parent-expression.rs:17:34: 17:41}`, the trait `Send` is not implemented for `derived_drop::Client`, which is required by `{coroutine@$DIR/parent-expression.rs:17:34: 17:41}: Send` note: coroutine is not `Send` as this value is used across a yield --> $DIR/parent-expression.rs:21:22 | -LL | let g = move || match drop($name::Client { ..$name::Client::default() }) { - | ------------------------ has type `derived_drop::Client` which is not `Send` +LL | let g = #[coroutine] move || match drop($name::Client { ..$name::Client::default() }) { + | ------------------------ has type `derived_drop::Client` which is not `Send` ... LL | _ => yield, | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later @@ -53,12 +53,12 @@ LL | | }; LL | | ); | |_____- in this macro invocation | - = help: within `{coroutine@$DIR/parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `significant_drop::Client`, which is required by `{coroutine@$DIR/parent-expression.rs:17:21: 17:28}: Send` + = help: within `{coroutine@$DIR/parent-expression.rs:17:34: 17:41}`, the trait `Send` is not implemented for `significant_drop::Client`, which is required by `{coroutine@$DIR/parent-expression.rs:17:34: 17:41}: Send` note: coroutine is not `Send` as this value is used across a yield --> $DIR/parent-expression.rs:21:22 | -LL | let g = move || match drop($name::Client { ..$name::Client::default() }) { - | ------------------------ has type `significant_drop::Client` which is not `Send` +LL | let g = #[coroutine] move || match drop($name::Client { ..$name::Client::default() }) { + | ------------------------ has type `significant_drop::Client` which is not `Send` ... LL | _ => yield, | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later @@ -93,12 +93,12 @@ LL | | }; LL | | ); | |_____- in this macro invocation | - = help: within `{coroutine@$DIR/parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `insignificant_dtor::Client`, which is required by `{coroutine@$DIR/parent-expression.rs:17:21: 17:28}: Send` + = help: within `{coroutine@$DIR/parent-expression.rs:17:34: 17:41}`, the trait `Send` is not implemented for `insignificant_dtor::Client`, which is required by `{coroutine@$DIR/parent-expression.rs:17:34: 17:41}: Send` note: coroutine is not `Send` as this value is used across a yield --> $DIR/parent-expression.rs:21:22 | -LL | let g = move || match drop($name::Client { ..$name::Client::default() }) { - | ------------------------ has type `insignificant_dtor::Client` which is not `Send` +LL | let g = #[coroutine] move || match drop($name::Client { ..$name::Client::default() }) { + | ------------------------ has type `insignificant_dtor::Client` which is not `Send` ... LL | _ => yield, | ^^^^^ yield occurs here, with `$name::Client::default()` maybe used later diff --git a/tests/ui/coroutine/partial-drop.rs b/tests/ui/coroutine/partial-drop.rs index ba13544712f1..9efb551c9c18 100644 --- a/tests/ui/coroutine/partial-drop.rs +++ b/tests/ui/coroutine/partial-drop.rs @@ -1,5 +1,5 @@ //@ check-pass -#![feature(negative_impls, coroutines)] +#![feature(negative_impls, coroutines, stmt_expr_attributes)] struct Foo; impl !Send for Foo {} @@ -10,25 +10,34 @@ struct Bar { } fn main() { - assert_send(|| { - let guard = Bar { foo: Foo, x: 42 }; - drop(guard.foo); - yield; - }); + assert_send( + #[coroutine] + || { + let guard = Bar { foo: Foo, x: 42 }; + drop(guard.foo); + yield; + }, + ); - assert_send(|| { - let mut guard = Bar { foo: Foo, x: 42 }; - drop(guard); - guard = Bar { foo: Foo, x: 23 }; - yield; - }); + assert_send( + #[coroutine] + || { + let mut guard = Bar { foo: Foo, x: 42 }; + drop(guard); + guard = Bar { foo: Foo, x: 23 }; + yield; + }, + ); - assert_send(|| { - let guard = Bar { foo: Foo, x: 42 }; - let Bar { foo, x } = guard; - drop(foo); - yield; - }); + assert_send( + #[coroutine] + || { + let guard = Bar { foo: Foo, x: 42 }; + let Bar { foo, x } = guard; + drop(foo); + yield; + }, + ); } fn assert_send(_: T) {} diff --git a/tests/ui/coroutine/partial-initialization-across-yield.rs b/tests/ui/coroutine/partial-initialization-across-yield.rs index 75ad5a228040..ab6f9c5b1e98 100644 --- a/tests/ui/coroutine/partial-initialization-across-yield.rs +++ b/tests/ui/coroutine/partial-initialization-across-yield.rs @@ -1,13 +1,13 @@ // Test that we don't allow yielding from a coroutine while a local is partially // initialized. -#![feature(coroutines)] +#![feature(coroutines, stmt_expr_attributes)] struct S { x: i32, y: i32 } struct T(i32, i32); fn test_tuple() { - let _ = || { + let _ = #[coroutine] || { let mut t: (i32, i32); t.0 = 42; //~ ERROR E0381 yield; @@ -17,7 +17,7 @@ fn test_tuple() { } fn test_tuple_struct() { - let _ = || { + let _ = #[coroutine] || { let mut t: T; t.0 = 42; //~ ERROR E0381 yield; @@ -27,7 +27,7 @@ fn test_tuple_struct() { } fn test_struct() { - let _ = || { + let _ = #[coroutine] || { let mut t: S; t.x = 42; //~ ERROR E0381 yield; diff --git a/tests/ui/coroutine/pattern-borrow.rs b/tests/ui/coroutine/pattern-borrow.rs index 76084433d470..46547504abc9 100644 --- a/tests/ui/coroutine/pattern-borrow.rs +++ b/tests/ui/coroutine/pattern-borrow.rs @@ -5,7 +5,7 @@ enum Test { A(i32), B, } fn main() { } fn fun(test: Test) { - move || { + #[coroutine] move || { if let Test::A(ref _a) = test { //~ ERROR borrow may still be in use when coroutine yields yield (); _a.use_ref(); diff --git a/tests/ui/coroutine/pin-box-coroutine.rs b/tests/ui/coroutine/pin-box-coroutine.rs index 1ee6393d1d83..d030f3ef214d 100644 --- a/tests/ui/coroutine/pin-box-coroutine.rs +++ b/tests/ui/coroutine/pin-box-coroutine.rs @@ -1,6 +1,6 @@ //@ run-pass -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] use std::ops::Coroutine; @@ -8,6 +8,6 @@ fn assert_coroutine(_: G) { } fn main() { - assert_coroutine(static || yield); - assert_coroutine(Box::pin(static || yield)); + assert_coroutine(#[coroutine] static || yield); + assert_coroutine(Box::pin(#[coroutine] static || yield)); } diff --git a/tests/ui/coroutine/polymorphize-args.rs b/tests/ui/coroutine/polymorphize-args.rs index 21aa3c7aafd8..5123bf412b55 100644 --- a/tests/ui/coroutine/polymorphize-args.rs +++ b/tests/ui/coroutine/polymorphize-args.rs @@ -1,14 +1,15 @@ //@ compile-flags: -Zpolymorphize=on //@ build-pass -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] use std::ops::Coroutine; use std::pin::Pin; use std::thread; fn main() { - let mut foo = || yield; + let mut foo = #[coroutine] + || yield; thread::spawn(move || match Pin::new(&mut foo).resume(()) { s => panic!("bad state: {:?}", s), }) diff --git a/tests/ui/coroutine/print/coroutine-print-verbose-1.rs b/tests/ui/coroutine/print/coroutine-print-verbose-1.rs index 73106328618e..dc0165c9194d 100644 --- a/tests/ui/coroutine/print/coroutine-print-verbose-1.rs +++ b/tests/ui/coroutine/print/coroutine-print-verbose-1.rs @@ -2,7 +2,7 @@ // Same as: tests/ui/coroutine/issue-68112.stderr -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] use std::{ cell::RefCell, @@ -30,7 +30,7 @@ fn make_non_send_coroutine() -> impl Coroutine>> { } fn test1() { - let send_gen = || { + let send_gen = #[coroutine] || { let _non_send_gen = make_non_send_coroutine(); yield; }; @@ -39,7 +39,7 @@ fn test1() { } pub fn make_gen2(t: T) -> impl Coroutine { - || { + #[coroutine] || { yield; t } @@ -49,7 +49,7 @@ fn make_non_send_coroutine2() -> impl Coroutine>> { } fn test2() { - let send_gen = || { + let send_gen = #[coroutine] || { let _non_send_gen = make_non_send_coroutine2(); yield; }; diff --git a/tests/ui/coroutine/print/coroutine-print-verbose-1.stderr b/tests/ui/coroutine/print/coroutine-print-verbose-1.stderr index 37db83d57f75..934ab08cf178 100644 --- a/tests/ui/coroutine/print/coroutine-print-verbose-1.stderr +++ b/tests/ui/coroutine/print/coroutine-print-verbose-1.stderr @@ -29,10 +29,10 @@ LL | require_send(send_gen); = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead = note: required for `Arc>` to implement `Send` note: required because it's used within this coroutine - --> $DIR/coroutine-print-verbose-1.rs:42:5 + --> $DIR/coroutine-print-verbose-1.rs:42:18 | -LL | || { - | ^^ +LL | #[coroutine] || { + | ^^ note: required because it appears within the type `Opaque(DefId(0:35 ~ coroutine_print_verbose_1[75fb]::make_gen2::{opaque#0}), [Arc>])` --> $DIR/coroutine-print-verbose-1.rs:41:30 | @@ -44,10 +44,10 @@ note: required because it appears within the type `Opaque(DefId(0:36 ~ coroutine LL | fn make_non_send_coroutine2() -> impl Coroutine>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: required because it's used within this coroutine - --> $DIR/coroutine-print-verbose-1.rs:52:20 + --> $DIR/coroutine-print-verbose-1.rs:52:33 | -LL | let send_gen = || { - | ^^ +LL | let send_gen = #[coroutine] || { + | ^^ note: required by a bound in `require_send` --> $DIR/coroutine-print-verbose-1.rs:26:25 | diff --git a/tests/ui/coroutine/print/coroutine-print-verbose-2.rs b/tests/ui/coroutine/print/coroutine-print-verbose-2.rs index f9ea68a8cd94..ef7199cafdde 100644 --- a/tests/ui/coroutine/print/coroutine-print-verbose-2.rs +++ b/tests/ui/coroutine/print/coroutine-print-verbose-2.rs @@ -1,7 +1,7 @@ //@ compile-flags: -Zverbose-internals // Same as test/ui/coroutine/not-send-sync.rs -#![feature(coroutines)] +#![feature(coroutines, stmt_expr_attributes)] #![feature(negative_impls)] struct NotSend; @@ -14,14 +14,14 @@ fn main() { fn assert_sync(_: T) {} fn assert_send(_: T) {} - assert_sync(|| { + assert_sync(#[coroutine] || { //~^ ERROR: coroutine cannot be shared between threads safely let a = NotSync; yield; drop(a); }); - assert_send(|| { + assert_send(#[coroutine] || { //~^ ERROR: coroutine cannot be sent between threads safely let a = NotSend; yield; diff --git a/tests/ui/coroutine/print/coroutine-print-verbose-2.stderr b/tests/ui/coroutine/print/coroutine-print-verbose-2.stderr index 26c9c27743c0..0de53d9e1d7d 100644 --- a/tests/ui/coroutine/print/coroutine-print-verbose-2.stderr +++ b/tests/ui/coroutine/print/coroutine-print-verbose-2.stderr @@ -1,7 +1,7 @@ error: coroutine cannot be shared between threads safely --> $DIR/coroutine-print-verbose-2.rs:17:5 | -LL | / assert_sync(|| { +LL | / assert_sync(#[coroutine] || { LL | | LL | | let a = NotSync; LL | | yield; @@ -26,7 +26,7 @@ LL | fn assert_sync(_: T) {} error: coroutine cannot be sent between threads safely --> $DIR/coroutine-print-verbose-2.rs:24:5 | -LL | / assert_send(|| { +LL | / assert_send(#[coroutine] || { LL | | LL | | let a = NotSend; LL | | yield; diff --git a/tests/ui/coroutine/print/coroutine-print-verbose-3.rs b/tests/ui/coroutine/print/coroutine-print-verbose-3.rs index be6dbad9e1c2..5dd15fc1b951 100644 --- a/tests/ui/coroutine/print/coroutine-print-verbose-3.rs +++ b/tests/ui/coroutine/print/coroutine-print-verbose-3.rs @@ -1,12 +1,13 @@ //@ compile-flags: -Zverbose-internals -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] fn main() { let x = "Type mismatch test"; - let coroutine :() = || { - //~^ ERROR mismatched types + let coroutine: () = #[coroutine] + || { + //~^ ERROR mismatched types yield 1i32; - return x + return x; }; } diff --git a/tests/ui/coroutine/print/coroutine-print-verbose-3.stderr b/tests/ui/coroutine/print/coroutine-print-verbose-3.stderr index e2973cde6d3c..dce45aeae56a 100644 --- a/tests/ui/coroutine/print/coroutine-print-verbose-3.stderr +++ b/tests/ui/coroutine/print/coroutine-print-verbose-3.stderr @@ -1,13 +1,12 @@ error[E0308]: mismatched types - --> $DIR/coroutine-print-verbose-3.rs:7:25 + --> $DIR/coroutine-print-verbose-3.rs:8:5 | -LL | let coroutine :() = || { - | ____________________--___^ - | | | - | | expected due to this +LL | let coroutine: () = #[coroutine] + | -- expected due to this +LL | / || { LL | | LL | | yield 1i32; -LL | | return x +LL | | return x; LL | | }; | |_____^ expected `()`, found coroutine | diff --git a/tests/ui/coroutine/reborrow-mut-upvar.rs b/tests/ui/coroutine/reborrow-mut-upvar.rs index e1f6211baebd..716781e365c5 100644 --- a/tests/ui/coroutine/reborrow-mut-upvar.rs +++ b/tests/ui/coroutine/reborrow-mut-upvar.rs @@ -3,7 +3,7 @@ #![feature(coroutines)] fn _run(bar: &mut i32) { - || { //~ WARN unused coroutine that must be used + #[coroutine] || { //~ WARN unused coroutine that must be used { let _baz = &*bar; yield; diff --git a/tests/ui/coroutine/reborrow-mut-upvar.stderr b/tests/ui/coroutine/reborrow-mut-upvar.stderr index 5b614ac4be8b..a05e84c5f3ef 100644 --- a/tests/ui/coroutine/reborrow-mut-upvar.stderr +++ b/tests/ui/coroutine/reborrow-mut-upvar.stderr @@ -1,7 +1,8 @@ warning: unused coroutine that must be used - --> $DIR/reborrow-mut-upvar.rs:6:5 + --> $DIR/reborrow-mut-upvar.rs:6:18 | -LL | / || { +LL | #[coroutine] || { + | __________________^ LL | | { LL | | let _baz = &*bar; LL | | yield; diff --git a/tests/ui/coroutine/ref-escapes-but-not-over-yield.rs b/tests/ui/coroutine/ref-escapes-but-not-over-yield.rs index a9c13188ff38..0f9c56786da0 100644 --- a/tests/ui/coroutine/ref-escapes-but-not-over-yield.rs +++ b/tests/ui/coroutine/ref-escapes-but-not-over-yield.rs @@ -1,16 +1,17 @@ -#![feature(coroutines)] +#![feature(coroutines, stmt_expr_attributes)] fn foo(x: &i32) { // In this case, a reference to `b` escapes the coroutine, but not // because of a yield. We see that there is no yield in the scope of // `b` and give the more generic error message. let mut a = &3; - let mut b = move || { - yield(); + let mut b = #[coroutine] + move || { + yield (); let b = 5; a = &b; //~^ ERROR borrowed data escapes outside of coroutine }; } -fn main() { } +fn main() {} diff --git a/tests/ui/coroutine/ref-escapes-but-not-over-yield.stderr b/tests/ui/coroutine/ref-escapes-but-not-over-yield.stderr index 8811faf2fade..6fa7082c0b8b 100644 --- a/tests/ui/coroutine/ref-escapes-but-not-over-yield.stderr +++ b/tests/ui/coroutine/ref-escapes-but-not-over-yield.stderr @@ -1,5 +1,5 @@ error[E0521]: borrowed data escapes outside of coroutine - --> $DIR/ref-escapes-but-not-over-yield.rs:11:9 + --> $DIR/ref-escapes-but-not-over-yield.rs:12:9 | LL | let mut a = &3; | ----- `a` declared here, outside of the coroutine body diff --git a/tests/ui/coroutine/ref-upvar-not-send.rs b/tests/ui/coroutine/ref-upvar-not-send.rs index 487fdeea2dae..89bb5e5495f4 100644 --- a/tests/ui/coroutine/ref-upvar-not-send.rs +++ b/tests/ui/coroutine/ref-upvar-not-send.rs @@ -1,7 +1,7 @@ // For `Send` coroutines, suggest a `T: Sync` requirement for `&T` upvars, // and suggest a `T: Send` requirement for `&mut T` upvars. -#![feature(coroutines)] +#![feature(coroutines, stmt_expr_attributes)] fn assert_send(_: T) {} //~^ NOTE required by a bound in `assert_send` @@ -12,7 +12,7 @@ fn assert_send(_: T) {} fn main() { let x: &*mut () = &std::ptr::null_mut(); let y: &mut *mut () = &mut std::ptr::null_mut(); - assert_send(move || { + assert_send(#[coroutine] move || { //~^ ERROR coroutine cannot be sent between threads safely //~| NOTE coroutine is not `Send` yield; @@ -20,7 +20,7 @@ fn main() { }); //~^^ NOTE captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync` //~| NOTE has type `&*mut ()` which is not `Send`, because `*mut ()` is not `Sync` - assert_send(move || { + assert_send(#[coroutine] move || { //~^ ERROR coroutine cannot be sent between threads safely //~| NOTE coroutine is not `Send` yield; diff --git a/tests/ui/coroutine/ref-upvar-not-send.stderr b/tests/ui/coroutine/ref-upvar-not-send.stderr index 0f91bcf40533..4c7deab3f4c4 100644 --- a/tests/ui/coroutine/ref-upvar-not-send.stderr +++ b/tests/ui/coroutine/ref-upvar-not-send.stderr @@ -1,8 +1,8 @@ error: coroutine cannot be sent between threads safely - --> $DIR/ref-upvar-not-send.rs:15:17 + --> $DIR/ref-upvar-not-send.rs:15:30 | -LL | assert_send(move || { - | _________________^ +LL | assert_send(#[coroutine] move || { + | ______________________________^ LL | | LL | | LL | | yield; @@ -10,7 +10,7 @@ LL | | let _x = x; LL | | }); | |_____^ coroutine is not `Send` | - = help: the trait `Sync` is not implemented for `*mut ()`, which is required by `{coroutine@$DIR/ref-upvar-not-send.rs:15:17: 15:24}: Send` + = help: the trait `Sync` is not implemented for `*mut ()`, which is required by `{coroutine@$DIR/ref-upvar-not-send.rs:15:30: 15:37}: Send` note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync` --> $DIR/ref-upvar-not-send.rs:19:18 | @@ -23,10 +23,10 @@ LL | fn assert_send(_: T) {} | ^^^^ required by this bound in `assert_send` error: coroutine cannot be sent between threads safely - --> $DIR/ref-upvar-not-send.rs:23:17 + --> $DIR/ref-upvar-not-send.rs:23:30 | -LL | assert_send(move || { - | _________________^ +LL | assert_send(#[coroutine] move || { + | ______________________________^ LL | | LL | | LL | | yield; @@ -34,7 +34,7 @@ LL | | let _y = y; LL | | }); | |_____^ coroutine is not `Send` | - = help: within `{coroutine@$DIR/ref-upvar-not-send.rs:23:17: 23:24}`, the trait `Send` is not implemented for `*mut ()`, which is required by `{coroutine@$DIR/ref-upvar-not-send.rs:23:17: 23:24}: Send` + = help: within `{coroutine@$DIR/ref-upvar-not-send.rs:23:30: 23:37}`, the trait `Send` is not implemented for `*mut ()`, which is required by `{coroutine@$DIR/ref-upvar-not-send.rs:23:30: 23:37}: Send` note: captured value is not `Send` because `&mut` references cannot be sent unless their referent is `Send` --> $DIR/ref-upvar-not-send.rs:27:18 | diff --git a/tests/ui/coroutine/reinit-in-match-guard.rs b/tests/ui/coroutine/reinit-in-match-guard.rs index 4a5842047731..0a97d9fbcb2f 100644 --- a/tests/ui/coroutine/reinit-in-match-guard.rs +++ b/tests/ui/coroutine/reinit-in-match-guard.rs @@ -1,11 +1,11 @@ //@ build-pass -#![feature(coroutines)] - +#![feature(coroutines, stmt_expr_attributes)] #![allow(unused_assignments, dead_code)] fn main() { - let _ = || { + let _ = #[coroutine] + || { let mut x = vec![22_usize]; std::mem::drop(x); match y() { diff --git a/tests/ui/coroutine/resume-after-return.rs b/tests/ui/coroutine/resume-after-return.rs index 81f86de641f2..7028e1e81e55 100644 --- a/tests/ui/coroutine/resume-after-return.rs +++ b/tests/ui/coroutine/resume-after-return.rs @@ -1,17 +1,17 @@ //@ run-pass //@ needs-unwind +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] -#![feature(coroutines, coroutine_trait)] - -use std::ops::{CoroutineState, Coroutine}; -use std::pin::Pin; +use std::ops::{Coroutine, CoroutineState}; use std::panic; +use std::pin::Pin; fn main() { - let mut foo = || { + let mut foo = #[coroutine] + || { if true { - return + return; } yield; }; diff --git a/tests/ui/coroutine/resume-arg-late-bound.rs b/tests/ui/coroutine/resume-arg-late-bound.rs index 3c2ab41047e3..e84184da631b 100644 --- a/tests/ui/coroutine/resume-arg-late-bound.rs +++ b/tests/ui/coroutine/resume-arg-late-bound.rs @@ -1,14 +1,14 @@ //! Tests that we cannot produce a coroutine that accepts a resume argument //! with any lifetime and then stores it across a `yield`. -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] use std::ops::Coroutine; fn test(a: impl for<'a> Coroutine<&'a mut bool>) {} fn main() { - let gen = |arg: &mut bool| { + let gen = #[coroutine] |arg: &mut bool| { yield (); *arg = true; }; diff --git a/tests/ui/coroutine/resume-arg-late-bound.stderr b/tests/ui/coroutine/resume-arg-late-bound.stderr index 4a4ee08c529e..646abaf4f7bd 100644 --- a/tests/ui/coroutine/resume-arg-late-bound.stderr +++ b/tests/ui/coroutine/resume-arg-late-bound.stderr @@ -4,7 +4,7 @@ error: implementation of `Coroutine` is not general enough LL | test(gen); | ^^^^^^^^^ implementation of `Coroutine` is not general enough | - = note: `{coroutine@$DIR/resume-arg-late-bound.rs:11:15: 11:31}` must implement `Coroutine<&'1 mut bool>`, for any lifetime `'1`... + = note: `{coroutine@$DIR/resume-arg-late-bound.rs:11:28: 11:44}` must implement `Coroutine<&'1 mut bool>`, for any lifetime `'1`... = note: ...but it actually implements `Coroutine<&'2 mut bool>`, for some specific lifetime `'2` error: aborting due to 1 previous error diff --git a/tests/ui/coroutine/resume-arg-size.rs b/tests/ui/coroutine/resume-arg-size.rs index 81e96975c98f..59740a28f428 100644 --- a/tests/ui/coroutine/resume-arg-size.rs +++ b/tests/ui/coroutine/resume-arg-size.rs @@ -1,4 +1,4 @@ -#![feature(coroutines)] +#![feature(coroutines, stmt_expr_attributes)] #![allow(dropping_copy_types)] //@ run-pass @@ -7,7 +7,8 @@ use std::mem::size_of_val; fn main() { // Coroutine taking a `Copy`able resume arg. - let gen_copy = |mut x: usize| { + let gen_copy = #[coroutine] + |mut x: usize| { loop { drop(x); x = yield; @@ -15,7 +16,8 @@ fn main() { }; // Coroutine taking a non-`Copy` resume arg. - let gen_move = |mut x: Box| { + let gen_move = #[coroutine] + |mut x: Box| { loop { drop(x); x = yield; diff --git a/tests/ui/coroutine/resume-live-across-yield.rs b/tests/ui/coroutine/resume-live-across-yield.rs index 45851411daaa..b67619ee70fb 100644 --- a/tests/ui/coroutine/resume-live-across-yield.rs +++ b/tests/ui/coroutine/resume-live-across-yield.rs @@ -1,6 +1,6 @@ //@ run-pass -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] use std::ops::{Coroutine, CoroutineState}; use std::pin::Pin; @@ -18,7 +18,8 @@ impl Drop for Dropper { } fn main() { - let mut g = |mut _d| { + let mut g = #[coroutine] + |mut _d| { _d = yield; _d }; diff --git a/tests/ui/coroutine/retain-resume-ref.rs b/tests/ui/coroutine/retain-resume-ref.rs index c9f995ab0cf3..6e688c33979a 100644 --- a/tests/ui/coroutine/retain-resume-ref.rs +++ b/tests/ui/coroutine/retain-resume-ref.rs @@ -1,6 +1,6 @@ //! This test ensures that a mutable reference cannot be passed as a resume argument twice. -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] use std::marker::Unpin; use std::ops::{ @@ -12,7 +12,8 @@ use std::pin::Pin; fn main() { let mut thing = String::from("hello"); - let mut gen = |r| { + let mut gen = #[coroutine] + |r| { if false { yield r; } diff --git a/tests/ui/coroutine/retain-resume-ref.stderr b/tests/ui/coroutine/retain-resume-ref.stderr index eb8b78df6c99..e23023c6e23f 100644 --- a/tests/ui/coroutine/retain-resume-ref.stderr +++ b/tests/ui/coroutine/retain-resume-ref.stderr @@ -1,5 +1,5 @@ error[E0499]: cannot borrow `thing` as mutable more than once at a time - --> $DIR/retain-resume-ref.rs:23:25 + --> $DIR/retain-resume-ref.rs:24:25 | LL | gen.as_mut().resume(&mut thing); | ---------- first mutable borrow occurs here diff --git a/tests/ui/coroutine/size-moved-locals.rs b/tests/ui/coroutine/size-moved-locals.rs index eb5210087a0e..0f800de84544 100644 --- a/tests/ui/coroutine/size-moved-locals.rs +++ b/tests/ui/coroutine/size-moved-locals.rs @@ -24,6 +24,7 @@ impl Drop for Foo { } fn move_before_yield() -> impl Coroutine { + #[coroutine] static || { let first = Foo([0; FOO_SIZE]); let _second = first; @@ -35,6 +36,7 @@ fn move_before_yield() -> impl Coroutine { fn noop() {} fn move_before_yield_with_noop() -> impl Coroutine { + #[coroutine] static || { let first = Foo([0; FOO_SIZE]); noop(); @@ -47,6 +49,7 @@ fn move_before_yield_with_noop() -> impl Coroutine { // Today we don't have NRVO (we allocate space for both `first` and `second`,) // but we can overlap `first` with `_third`. fn overlap_move_points() -> impl Coroutine { + #[coroutine] static || { let first = Foo([0; FOO_SIZE]); yield; @@ -58,6 +61,7 @@ fn overlap_move_points() -> impl Coroutine { } fn overlap_x_and_y() -> impl Coroutine { + #[coroutine] static || { let x = Foo([0; FOO_SIZE]); yield; diff --git a/tests/ui/coroutine/sized-yield.rs b/tests/ui/coroutine/sized-yield.rs index 1368c88b5227..a4c91fafe6ca 100644 --- a/tests/ui/coroutine/sized-yield.rs +++ b/tests/ui/coroutine/sized-yield.rs @@ -1,11 +1,12 @@ -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] use std::ops::Coroutine; use std::pin::Pin; fn main() { let s = String::from("foo"); - let mut gen = move || { + let mut gen = #[coroutine] + move || { //~^ ERROR the size for values of type yield s[..]; }; diff --git a/tests/ui/coroutine/sized-yield.stderr b/tests/ui/coroutine/sized-yield.stderr index 4e8dc13201de..5d5dd6803c89 100644 --- a/tests/ui/coroutine/sized-yield.stderr +++ b/tests/ui/coroutine/sized-yield.stderr @@ -1,8 +1,7 @@ error[E0277]: the size for values of type `str` cannot be known at compilation time - --> $DIR/sized-yield.rs:8:19 + --> $DIR/sized-yield.rs:9:5 | -LL | let mut gen = move || { - | ___________________^ +LL | / move || { LL | | LL | | yield s[..]; LL | | }; @@ -12,7 +11,7 @@ LL | | }; = note: the yield type of a coroutine must have a statically known size error[E0277]: the size for values of type `str` cannot be known at compilation time - --> $DIR/sized-yield.rs:12:24 + --> $DIR/sized-yield.rs:13:24 | LL | Pin::new(&mut gen).resume(()); | ^^^^^^ doesn't have a size known at compile-time diff --git a/tests/ui/coroutine/smoke-resume-args.rs b/tests/ui/coroutine/smoke-resume-args.rs index 7d20cd2293d6..209c48140018 100644 --- a/tests/ui/coroutine/smoke-resume-args.rs +++ b/tests/ui/coroutine/smoke-resume-args.rs @@ -3,7 +3,7 @@ //@ revisions: default nomiropt //@[nomiropt]compile-flags: -Z mir-opt-level=0 -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] use std::fmt::Debug; use std::ops::{ @@ -50,7 +50,7 @@ fn expect_drops(expected_drops: usize, f: impl FnOnce() -> T) -> T { fn main() { drain( - &mut |mut b| { + &mut #[coroutine] |mut b| { while b != 0 { b = yield (b + 1); } @@ -59,21 +59,24 @@ fn main() { vec![(1, Yielded(2)), (-45, Yielded(-44)), (500, Yielded(501)), (0, Complete(-1))], ); - expect_drops(2, || drain(&mut |a| yield a, vec![(DropMe, Yielded(DropMe))])); + expect_drops(2, || drain(&mut #[coroutine] |a| yield a, vec![(DropMe, Yielded(DropMe))])); expect_drops(6, || { drain( - &mut |a| yield yield a, + &mut #[coroutine] |a| yield yield a, vec![(DropMe, Yielded(DropMe)), (DropMe, Yielded(DropMe)), (DropMe, Complete(DropMe))], ) }); #[allow(unreachable_code)] - expect_drops(2, || drain(&mut |a| yield return a, vec![(DropMe, Complete(DropMe))])); + expect_drops(2, || drain( + &mut #[coroutine] |a| yield return a, + vec![(DropMe, Complete(DropMe))] + )); expect_drops(2, || { drain( - &mut |a: DropMe| { + &mut #[coroutine] |a: DropMe| { if false { yield () } else { a } }, vec![(DropMe, Complete(DropMe))], @@ -83,7 +86,7 @@ fn main() { expect_drops(4, || { drain( #[allow(unused_assignments, unused_variables)] - &mut |mut a: DropMe| { + &mut #[coroutine] |mut a: DropMe| { a = yield; a = yield; a = yield; diff --git a/tests/ui/coroutine/smoke.rs b/tests/ui/coroutine/smoke.rs index 17d98a52a1c4..bfb183fde936 100644 --- a/tests/ui/coroutine/smoke.rs +++ b/tests/ui/coroutine/smoke.rs @@ -6,7 +6,7 @@ //@ needs-threads //@ compile-flags: --test -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] use std::ops::{CoroutineState, Coroutine}; use std::pin::Pin; @@ -14,7 +14,7 @@ use std::thread; #[test] fn simple() { - let mut foo = || { + let mut foo = #[coroutine] || { if false { yield; } @@ -29,7 +29,7 @@ fn simple() { #[test] fn return_capture() { let a = String::from("foo"); - let mut foo = || { + let mut foo = #[coroutine] || { if false { yield; } @@ -44,7 +44,7 @@ fn return_capture() { #[test] fn simple_yield() { - let mut foo = || { + let mut foo = #[coroutine] || { yield; }; @@ -61,7 +61,7 @@ fn simple_yield() { #[test] fn yield_capture() { let b = String::from("foo"); - let mut foo = || { + let mut foo = #[coroutine] || { yield b; }; @@ -77,7 +77,7 @@ fn yield_capture() { #[test] fn simple_yield_value() { - let mut foo = || { + let mut foo = #[coroutine] || { yield String::from("bar"); return String::from("foo") }; @@ -95,7 +95,7 @@ fn simple_yield_value() { #[test] fn return_after_yield() { let a = String::from("foo"); - let mut foo = || { + let mut foo = #[coroutine] || { yield; return a }; @@ -112,34 +112,34 @@ fn return_after_yield() { #[test] fn send_and_sync() { - assert_send_sync(|| { + assert_send_sync(#[coroutine] || { yield }); - assert_send_sync(|| { + assert_send_sync(#[coroutine] || { yield String::from("foo"); }); - assert_send_sync(|| { + assert_send_sync(#[coroutine] || { yield; return String::from("foo"); }); let a = 3; - assert_send_sync(|| { + assert_send_sync(#[coroutine] || { yield a; return }); let a = 3; - assert_send_sync(move || { + assert_send_sync(#[coroutine] move || { yield a; return }); let a = String::from("a"); - assert_send_sync(|| { + assert_send_sync(#[coroutine] || { yield ; drop(a); return }); let a = String::from("a"); - assert_send_sync(move || { + assert_send_sync(#[coroutine] move || { yield ; drop(a); return @@ -150,7 +150,7 @@ fn send_and_sync() { #[test] fn send_over_threads() { - let mut foo = || { yield }; + let mut foo = #[coroutine] || { yield }; thread::spawn(move || { match Pin::new(&mut foo).resume(()) { CoroutineState::Yielded(()) => {} @@ -163,7 +163,7 @@ fn send_over_threads() { }).join().unwrap(); let a = String::from("a"); - let mut foo = || { yield a }; + let mut foo = #[coroutine] || { yield a }; thread::spawn(move || { match Pin::new(&mut foo).resume(()) { CoroutineState::Yielded(ref s) if *s == "a" => {} diff --git a/tests/ui/coroutine/static-coroutine.rs b/tests/ui/coroutine/static-coroutine.rs index 9beaef3e4de3..eba6336d342f 100644 --- a/tests/ui/coroutine/static-coroutine.rs +++ b/tests/ui/coroutine/static-coroutine.rs @@ -1,12 +1,13 @@ //@ run-pass -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] -use std::pin::Pin; use std::ops::{Coroutine, CoroutineState}; +use std::pin::Pin; fn main() { - let mut coroutine = static || { + let mut coroutine = #[coroutine] + static || { let a = true; let b = &a; yield; diff --git a/tests/ui/coroutine/static-mut-reference-across-yield.rs b/tests/ui/coroutine/static-mut-reference-across-yield.rs index 0d8042ed8526..40d5fdf2d573 100644 --- a/tests/ui/coroutine/static-mut-reference-across-yield.rs +++ b/tests/ui/coroutine/static-mut-reference-across-yield.rs @@ -1,6 +1,6 @@ //@ build-pass -#![feature(coroutines)] +#![feature(coroutines, stmt_expr_attributes)] static mut A: [i32; 5] = [1, 2, 3, 4, 5]; @@ -8,13 +8,15 @@ fn is_send_sync(_: T) {} fn main() { unsafe { - let gen_index = static || { + let gen_index = #[coroutine] + static || { let u = A[{ yield; 1 }]; }; - let gen_match = static || match A { + let gen_match = #[coroutine] + static || match A { i if { yield; true diff --git a/tests/ui/coroutine/static-not-unpin.current.stderr b/tests/ui/coroutine/static-not-unpin.current.stderr index 518abdd62c79..7d6260ac569e 100644 --- a/tests/ui/coroutine/static-not-unpin.current.stderr +++ b/tests/ui/coroutine/static-not-unpin.current.stderr @@ -1,8 +1,8 @@ -error[E0277]: `{static coroutine@$DIR/static-not-unpin.rs:15:25: 15:34}` cannot be unpinned +error[E0277]: `{static coroutine@$DIR/static-not-unpin.rs:15:5: 15:14}` cannot be unpinned --> $DIR/static-not-unpin.rs:18:18 | LL | assert_unpin(coroutine); - | ------------ ^^^^^^^^^ the trait `Unpin` is not implemented for `{static coroutine@$DIR/static-not-unpin.rs:15:25: 15:34}` + | ------------ ^^^^^^^^^ the trait `Unpin` is not implemented for `{static coroutine@$DIR/static-not-unpin.rs:15:5: 15:14}` | | | required by a bound introduced by this call | @@ -11,7 +11,7 @@ LL | assert_unpin(coroutine); note: required by a bound in `assert_unpin` --> $DIR/static-not-unpin.rs:11:20 | -LL | fn assert_unpin(_: T) { +LL | fn assert_unpin(_: T) {} | ^^^^^ required by this bound in `assert_unpin` error: aborting due to 1 previous error diff --git a/tests/ui/coroutine/static-not-unpin.next.stderr b/tests/ui/coroutine/static-not-unpin.next.stderr index 518abdd62c79..7d6260ac569e 100644 --- a/tests/ui/coroutine/static-not-unpin.next.stderr +++ b/tests/ui/coroutine/static-not-unpin.next.stderr @@ -1,8 +1,8 @@ -error[E0277]: `{static coroutine@$DIR/static-not-unpin.rs:15:25: 15:34}` cannot be unpinned +error[E0277]: `{static coroutine@$DIR/static-not-unpin.rs:15:5: 15:14}` cannot be unpinned --> $DIR/static-not-unpin.rs:18:18 | LL | assert_unpin(coroutine); - | ------------ ^^^^^^^^^ the trait `Unpin` is not implemented for `{static coroutine@$DIR/static-not-unpin.rs:15:25: 15:34}` + | ------------ ^^^^^^^^^ the trait `Unpin` is not implemented for `{static coroutine@$DIR/static-not-unpin.rs:15:5: 15:14}` | | | required by a bound introduced by this call | @@ -11,7 +11,7 @@ LL | assert_unpin(coroutine); note: required by a bound in `assert_unpin` --> $DIR/static-not-unpin.rs:11:20 | -LL | fn assert_unpin(_: T) { +LL | fn assert_unpin(_: T) {} | ^^^^^ required by this bound in `assert_unpin` error: aborting due to 1 previous error diff --git a/tests/ui/coroutine/static-not-unpin.rs b/tests/ui/coroutine/static-not-unpin.rs index 3704cca77297..2bc25e3796d4 100644 --- a/tests/ui/coroutine/static-not-unpin.rs +++ b/tests/ui/coroutine/static-not-unpin.rs @@ -2,17 +2,17 @@ //@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver -#![feature(coroutines)] +#![feature(coroutines, stmt_expr_attributes)] //@ normalize-stderr-test "std::pin::Unpin" -> "std::marker::Unpin" use std::marker::Unpin; -fn assert_unpin(_: T) { -} +fn assert_unpin(_: T) {} fn main() { - let mut coroutine = static || { + let mut coroutine = #[coroutine] + static || { yield; }; assert_unpin(coroutine); //~ ERROR E0277 diff --git a/tests/ui/coroutine/static-reference-across-yield.rs b/tests/ui/coroutine/static-reference-across-yield.rs index cf19ccb54d53..e7ff658ebf64 100644 --- a/tests/ui/coroutine/static-reference-across-yield.rs +++ b/tests/ui/coroutine/static-reference-across-yield.rs @@ -4,10 +4,10 @@ static A: [i32; 5] = [1, 2, 3, 4, 5]; fn main() { - static || { + #[coroutine] static || { let u = A[{yield; 1}]; }; - static || { + #[coroutine] static || { match A { i if { yield; true } => (), _ => (), diff --git a/tests/ui/coroutine/too-live-local-in-immovable-gen.rs b/tests/ui/coroutine/too-live-local-in-immovable-gen.rs index 382e7ff38143..1c689ef7cefc 100644 --- a/tests/ui/coroutine/too-live-local-in-immovable-gen.rs +++ b/tests/ui/coroutine/too-live-local-in-immovable-gen.rs @@ -5,7 +5,7 @@ fn main() { unsafe { - static move || { //~ WARN unused coroutine that must be used + #[coroutine] static move || { //~ WARN unused coroutine that must be used // Tests that the coroutine transformation finds out that `a` is not live // during the yield expression. Type checking will also compute liveness // and it should also find out that `a` is not live. diff --git a/tests/ui/coroutine/too-live-local-in-immovable-gen.stderr b/tests/ui/coroutine/too-live-local-in-immovable-gen.stderr index 4a67dbe71e19..48df5c5beacd 100644 --- a/tests/ui/coroutine/too-live-local-in-immovable-gen.stderr +++ b/tests/ui/coroutine/too-live-local-in-immovable-gen.stderr @@ -1,7 +1,8 @@ warning: unused coroutine that must be used - --> $DIR/too-live-local-in-immovable-gen.rs:8:9 + --> $DIR/too-live-local-in-immovable-gen.rs:8:22 | -LL | / static move || { +LL | #[coroutine] static move || { + | ______________________^ LL | | // Tests that the coroutine transformation finds out that `a` is not live LL | | // during the yield expression. Type checking will also compute liveness LL | | // and it should also find out that `a` is not live. diff --git a/tests/ui/coroutine/too-many-parameters.rs b/tests/ui/coroutine/too-many-parameters.rs index 377d80c7b22e..3baaf0623479 100644 --- a/tests/ui/coroutine/too-many-parameters.rs +++ b/tests/ui/coroutine/too-many-parameters.rs @@ -1,6 +1,7 @@ #![feature(coroutines)] fn main() { + #[coroutine] |(), ()| { //~^ error: too many parameters for a coroutine yield; diff --git a/tests/ui/coroutine/too-many-parameters.stderr b/tests/ui/coroutine/too-many-parameters.stderr index c0917c7225ba..45dad8e349e2 100644 --- a/tests/ui/coroutine/too-many-parameters.stderr +++ b/tests/ui/coroutine/too-many-parameters.stderr @@ -1,5 +1,5 @@ error[E0628]: too many parameters for a coroutine (expected 0 or 1 parameters) - --> $DIR/too-many-parameters.rs:4:5 + --> $DIR/too-many-parameters.rs:5:5 | LL | |(), ()| { | ^^^^^^^^ diff --git a/tests/ui/coroutine/type-mismatch-error.rs b/tests/ui/coroutine/type-mismatch-error.rs index 0d04c21484cb..ee4e27c20da1 100644 --- a/tests/ui/coroutine/type-mismatch-error.rs +++ b/tests/ui/coroutine/type-mismatch-error.rs @@ -1,7 +1,7 @@ //! Test that we get the expected type mismatch error instead of "closure is expected to take 0 //! arguments" (which got introduced after implementing resume arguments). -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] use std::ops::Coroutine; @@ -9,6 +9,7 @@ fn f(_: G, _: G::Return) {} fn main() { f( + #[coroutine] |a: u8| { if false { yield (); diff --git a/tests/ui/coroutine/type-mismatch-error.stderr b/tests/ui/coroutine/type-mismatch-error.stderr index 737d9afdd79a..f10c30e25907 100644 --- a/tests/ui/coroutine/type-mismatch-error.stderr +++ b/tests/ui/coroutine/type-mismatch-error.stderr @@ -1,5 +1,5 @@ error[E0308]: `if` and `else` have incompatible types - --> $DIR/type-mismatch-error.rs:16:17 + --> $DIR/type-mismatch-error.rs:17:17 | LL | / if false { LL | | yield (); diff --git a/tests/ui/coroutine/type-mismatch-signature-deduction.rs b/tests/ui/coroutine/type-mismatch-signature-deduction.rs index d4ca622e80f5..5b04b3efaaa4 100644 --- a/tests/ui/coroutine/type-mismatch-signature-deduction.rs +++ b/tests/ui/coroutine/type-mismatch-signature-deduction.rs @@ -4,6 +4,7 @@ use std::ops::Coroutine; fn foo() -> impl Coroutine { //~^ ERROR type mismatch + #[coroutine] || { if false { return Ok(6); diff --git a/tests/ui/coroutine/type-mismatch-signature-deduction.stderr b/tests/ui/coroutine/type-mismatch-signature-deduction.stderr index f26e30a8e743..089271960375 100644 --- a/tests/ui/coroutine/type-mismatch-signature-deduction.stderr +++ b/tests/ui/coroutine/type-mismatch-signature-deduction.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/type-mismatch-signature-deduction.rs:14:9 + --> $DIR/type-mismatch-signature-deduction.rs:15:9 | LL | 5 | ^ expected `Result<{integer}, _>`, found integer @@ -7,7 +7,7 @@ LL | 5 = note: expected enum `Result<{integer}, _>` found type `{integer}` note: return type inferred to be `Result<{integer}, _>` here - --> $DIR/type-mismatch-signature-deduction.rs:9:20 + --> $DIR/type-mismatch-signature-deduction.rs:10:20 | LL | return Ok(6); | ^^^^^ @@ -18,7 +18,7 @@ LL | Ok(5) LL | Err(5) | ++++ + -error[E0271]: type mismatch resolving `<{coroutine@$DIR/type-mismatch-signature-deduction.rs:7:5: 7:7} as Coroutine>::Return == i32` +error[E0271]: type mismatch resolving `<{coroutine@$DIR/type-mismatch-signature-deduction.rs:8:5: 8:7} as Coroutine>::Return == i32` --> $DIR/type-mismatch-signature-deduction.rs:5:13 | LL | fn foo() -> impl Coroutine { diff --git a/tests/ui/coroutine/uninhabited-field.rs b/tests/ui/coroutine/uninhabited-field.rs index 79776d653b1f..d6ada07ce0cb 100644 --- a/tests/ui/coroutine/uninhabited-field.rs +++ b/tests/ui/coroutine/uninhabited-field.rs @@ -3,7 +3,7 @@ #![allow(unused)] #![feature(assert_matches)] #![feature(coroutine_trait)] -#![feature(coroutines)] +#![feature(coroutines, stmt_expr_attributes)] #![feature(never_type)] use std::assert_matches::assert_matches; use std::ops::Coroutine; @@ -13,7 +13,7 @@ use std::pin::Pin; fn conjure() -> T { loop {} } fn run(x: bool, y: bool) { - let mut c = || { + let mut c = #[coroutine] || { if x { let a : T; if y { diff --git a/tests/ui/coroutine/unsized-capture-across-yield.rs b/tests/ui/coroutine/unsized-capture-across-yield.rs index ef9cbc1d677d..c86b1823aaff 100644 --- a/tests/ui/coroutine/unsized-capture-across-yield.rs +++ b/tests/ui/coroutine/unsized-capture-across-yield.rs @@ -7,6 +7,7 @@ use std::ops::Coroutine; fn capture() -> impl Coroutine { let b: [u8] = *(Box::new([]) as Box<[u8]>); + #[coroutine] move || { println!("{:?}", &b); //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time diff --git a/tests/ui/coroutine/unsized-capture-across-yield.stderr b/tests/ui/coroutine/unsized-capture-across-yield.stderr index 436f0901a977..03551f1bbff5 100644 --- a/tests/ui/coroutine/unsized-capture-across-yield.stderr +++ b/tests/ui/coroutine/unsized-capture-across-yield.stderr @@ -8,7 +8,7 @@ LL | #![feature(unsized_locals)] = note: `#[warn(incomplete_features)]` on by default error[E0277]: the size for values of type `[u8]` cannot be known at compilation time - --> $DIR/unsized-capture-across-yield.rs:11:27 + --> $DIR/unsized-capture-across-yield.rs:12:27 | LL | move || { | -- this closure captures all values by move diff --git a/tests/ui/coroutine/unsized-local-across-yield.rs b/tests/ui/coroutine/unsized-local-across-yield.rs index 7a8ed60e46ae..cb8ced13a111 100644 --- a/tests/ui/coroutine/unsized-local-across-yield.rs +++ b/tests/ui/coroutine/unsized-local-across-yield.rs @@ -6,6 +6,7 @@ use std::ops::Coroutine; fn across() -> impl Coroutine { + #[coroutine] move || { let b: [u8] = *(Box::new([]) as Box<[u8]>); //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time diff --git a/tests/ui/coroutine/unsized-local-across-yield.stderr b/tests/ui/coroutine/unsized-local-across-yield.stderr index c4c3be77ac2b..4fe0f135a9d6 100644 --- a/tests/ui/coroutine/unsized-local-across-yield.stderr +++ b/tests/ui/coroutine/unsized-local-across-yield.stderr @@ -8,7 +8,7 @@ LL | #![feature(unsized_locals)] = note: `#[warn(incomplete_features)]` on by default error[E0277]: the size for values of type `[u8]` cannot be known at compilation time - --> $DIR/unsized-local-across-yield.rs:10:13 + --> $DIR/unsized-local-across-yield.rs:11:13 | LL | let b: [u8] = *(Box::new([]) as Box<[u8]>); | ^ doesn't have a size known at compile-time diff --git a/tests/ui/coroutine/yield-in-args-rev.rs b/tests/ui/coroutine/yield-in-args-rev.rs index b074e2bc9398..29d79df25fba 100644 --- a/tests/ui/coroutine/yield-in-args-rev.rs +++ b/tests/ui/coroutine/yield-in-args-rev.rs @@ -10,7 +10,7 @@ fn foo(_a: (), _b: &bool) {} fn bar() { - || { //~ WARN unused coroutine that must be used + #[coroutine] || { //~ WARN unused coroutine that must be used let b = true; foo(yield, &b); }; diff --git a/tests/ui/coroutine/yield-in-args-rev.stderr b/tests/ui/coroutine/yield-in-args-rev.stderr index dbf46739e8bf..10829d661854 100644 --- a/tests/ui/coroutine/yield-in-args-rev.stderr +++ b/tests/ui/coroutine/yield-in-args-rev.stderr @@ -1,7 +1,8 @@ warning: unused coroutine that must be used - --> $DIR/yield-in-args-rev.rs:13:5 + --> $DIR/yield-in-args-rev.rs:13:18 | -LL | / || { +LL | #[coroutine] || { + | __________________^ LL | | let b = true; LL | | foo(yield, &b); LL | | }; diff --git a/tests/ui/coroutine/yield-in-args.rs b/tests/ui/coroutine/yield-in-args.rs index b2827148d771..bc9909b310c3 100644 --- a/tests/ui/coroutine/yield-in-args.rs +++ b/tests/ui/coroutine/yield-in-args.rs @@ -3,6 +3,7 @@ fn foo(_b: &bool, _a: ()) {} fn main() { + #[coroutine] || { let b = true; foo(&b, yield); //~ ERROR diff --git a/tests/ui/coroutine/yield-in-args.stderr b/tests/ui/coroutine/yield-in-args.stderr index 7233f47884b7..1d2c54f9bdbf 100644 --- a/tests/ui/coroutine/yield-in-args.stderr +++ b/tests/ui/coroutine/yield-in-args.stderr @@ -1,5 +1,5 @@ error[E0626]: borrow may still be in use when coroutine yields - --> $DIR/yield-in-args.rs:8:13 + --> $DIR/yield-in-args.rs:9:13 | LL | foo(&b, yield); | ^^ ----- possible yield occurs here diff --git a/tests/ui/coroutine/yield-in-const.rs b/tests/ui/coroutine/yield-in-const.rs index 22651f32cf85..dc1b30155b9f 100644 --- a/tests/ui/coroutine/yield-in-const.rs +++ b/tests/ui/coroutine/yield-in-const.rs @@ -2,5 +2,6 @@ const A: u8 = { yield 3u8; 3u8}; //~^ ERROR yield expression outside +//~| ERROR `yield` can only be used in fn main() {} diff --git a/tests/ui/coroutine/yield-in-const.stderr b/tests/ui/coroutine/yield-in-const.stderr index d5748b053375..f02729412ccd 100644 --- a/tests/ui/coroutine/yield-in-const.stderr +++ b/tests/ui/coroutine/yield-in-const.stderr @@ -1,9 +1,15 @@ +error: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks + --> $DIR/yield-in-const.rs:3:17 + | +LL | const A: u8 = { yield 3u8; 3u8}; + | ^^^^^^^^^ + error[E0627]: yield expression outside of coroutine literal --> $DIR/yield-in-const.rs:3:17 | LL | const A: u8 = { yield 3u8; 3u8}; | ^^^^^^^^^ -error: aborting due to 1 previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0627`. diff --git a/tests/ui/coroutine/yield-in-function.rs b/tests/ui/coroutine/yield-in-function.rs index a99312043bdb..427c5d0e7f5e 100644 --- a/tests/ui/coroutine/yield-in-function.rs +++ b/tests/ui/coroutine/yield-in-function.rs @@ -2,3 +2,4 @@ fn main() { yield; } //~^ ERROR yield expression outside +//~| ERROR `yield` can only be used in diff --git a/tests/ui/coroutine/yield-in-function.stderr b/tests/ui/coroutine/yield-in-function.stderr index b9d4708bb8d8..dbebf310b04f 100644 --- a/tests/ui/coroutine/yield-in-function.stderr +++ b/tests/ui/coroutine/yield-in-function.stderr @@ -1,9 +1,20 @@ +error: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks + --> $DIR/yield-in-function.rs:3:13 + | +LL | fn main() { yield; } + | ^^^^^ + | +help: use `#[coroutine]` to make this closure a coroutine + | +LL | #[coroutine] fn main() { yield; } + | ++++++++++++ + error[E0627]: yield expression outside of coroutine literal --> $DIR/yield-in-function.rs:3:13 | LL | fn main() { yield; } | ^^^^^ -error: aborting due to 1 previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0627`. diff --git a/tests/ui/coroutine/yield-in-initializer.rs b/tests/ui/coroutine/yield-in-initializer.rs index 19218926b8a0..3caefac013ef 100644 --- a/tests/ui/coroutine/yield-in-initializer.rs +++ b/tests/ui/coroutine/yield-in-initializer.rs @@ -3,7 +3,7 @@ #![feature(coroutines)] fn main() { - static || { //~ WARN unused coroutine that must be used + #[coroutine] static || { //~ WARN unused coroutine that must be used loop { // Test that `opt` is not live across the yield, even when borrowed in a loop // See https://github.com/rust-lang/rust/issues/52792 diff --git a/tests/ui/coroutine/yield-in-initializer.stderr b/tests/ui/coroutine/yield-in-initializer.stderr index 614df43f2f58..1e22b7876687 100644 --- a/tests/ui/coroutine/yield-in-initializer.stderr +++ b/tests/ui/coroutine/yield-in-initializer.stderr @@ -1,7 +1,8 @@ warning: unused coroutine that must be used - --> $DIR/yield-in-initializer.rs:6:5 + --> $DIR/yield-in-initializer.rs:6:18 | -LL | / static || { +LL | #[coroutine] static || { + | __________________^ LL | | loop { LL | | // Test that `opt` is not live across the yield, even when borrowed in a loop LL | | // See https://github.com/rust-lang/rust/issues/52792 diff --git a/tests/ui/coroutine/yield-in-static.rs b/tests/ui/coroutine/yield-in-static.rs index 45e0380d46d9..99d08913e64c 100644 --- a/tests/ui/coroutine/yield-in-static.rs +++ b/tests/ui/coroutine/yield-in-static.rs @@ -2,5 +2,6 @@ static B: u8 = { yield 3u8; 3u8}; //~^ ERROR yield expression outside +//~| ERROR `yield` can only be used in fn main() {} diff --git a/tests/ui/coroutine/yield-in-static.stderr b/tests/ui/coroutine/yield-in-static.stderr index b56283cab669..d1fd4eab0fc3 100644 --- a/tests/ui/coroutine/yield-in-static.stderr +++ b/tests/ui/coroutine/yield-in-static.stderr @@ -1,9 +1,15 @@ +error: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks + --> $DIR/yield-in-static.rs:3:18 + | +LL | static B: u8 = { yield 3u8; 3u8}; + | ^^^^^^^^^ + error[E0627]: yield expression outside of coroutine literal --> $DIR/yield-in-static.rs:3:18 | LL | static B: u8 = { yield 3u8; 3u8}; | ^^^^^^^^^ -error: aborting due to 1 previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0627`. diff --git a/tests/ui/coroutine/yield-outside-coroutine-issue-78653.rs b/tests/ui/coroutine/yield-outside-coroutine-issue-78653.rs index 31025c33b1a2..6833bc990121 100644 --- a/tests/ui/coroutine/yield-outside-coroutine-issue-78653.rs +++ b/tests/ui/coroutine/yield-outside-coroutine-issue-78653.rs @@ -4,4 +4,5 @@ fn main() { yield || for i in 0 { } //~^ ERROR yield expression outside of coroutine literal //~| ERROR `{integer}` is not an iterator + //~| ERROR `yield` can only be used in } diff --git a/tests/ui/coroutine/yield-outside-coroutine-issue-78653.stderr b/tests/ui/coroutine/yield-outside-coroutine-issue-78653.stderr index 8f8bec994584..921e8d5d47a0 100644 --- a/tests/ui/coroutine/yield-outside-coroutine-issue-78653.stderr +++ b/tests/ui/coroutine/yield-outside-coroutine-issue-78653.stderr @@ -1,3 +1,14 @@ +error: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks + --> $DIR/yield-outside-coroutine-issue-78653.rs:4:5 + | +LL | yield || for i in 0 { } + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `#[coroutine]` to make this closure a coroutine + | +LL | #[coroutine] fn main() { + | ++++++++++++ + error[E0627]: yield expression outside of coroutine literal --> $DIR/yield-outside-coroutine-issue-78653.rs:4:5 | @@ -14,7 +25,7 @@ LL | yield || for i in 0 { } = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required for `{integer}` to implement `IntoIterator` -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0277, E0627. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/coroutine/yield-subtype.rs b/tests/ui/coroutine/yield-subtype.rs index 271f8362f17e..adee5075e832 100644 --- a/tests/ui/coroutine/yield-subtype.rs +++ b/tests/ui/coroutine/yield-subtype.rs @@ -8,7 +8,7 @@ fn bar<'a>() { let a: &'static str = "hi"; let b: &'a str = a; - || { //~ WARN unused coroutine that must be used + #[coroutine] || { //~ WARN unused coroutine that must be used yield a; yield b; }; diff --git a/tests/ui/coroutine/yield-subtype.stderr b/tests/ui/coroutine/yield-subtype.stderr index 5e7ae9f581eb..973415327a5d 100644 --- a/tests/ui/coroutine/yield-subtype.stderr +++ b/tests/ui/coroutine/yield-subtype.stderr @@ -1,7 +1,8 @@ warning: unused coroutine that must be used - --> $DIR/yield-subtype.rs:11:5 + --> $DIR/yield-subtype.rs:11:18 | -LL | / || { +LL | #[coroutine] || { + | __________________^ LL | | yield a; LL | | yield b; LL | | }; diff --git a/tests/ui/coroutine/yield-while-iterating.rs b/tests/ui/coroutine/yield-while-iterating.rs index 66ac6d3922a9..77f601e4f2c5 100644 --- a/tests/ui/coroutine/yield-while-iterating.rs +++ b/tests/ui/coroutine/yield-while-iterating.rs @@ -1,4 +1,4 @@ -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] use std::ops::{CoroutineState, Coroutine}; use std::cell::Cell; @@ -9,7 +9,7 @@ fn yield_during_iter_owned_data(x: Vec) { // reference to it. This winds up becoming a rather confusing // regionck error -- in particular, we would freeze with the // reference in scope, and it doesn't live long enough. - let _b = move || { + let _b =#[coroutine] move || { for p in &x { //~ ERROR yield(); } @@ -17,7 +17,7 @@ fn yield_during_iter_owned_data(x: Vec) { } fn yield_during_iter_borrowed_slice(x: &[i32]) { - let _b = move || { + let _b = #[coroutine] move || { for p in x { yield(); } @@ -26,7 +26,7 @@ fn yield_during_iter_borrowed_slice(x: &[i32]) { fn yield_during_iter_borrowed_slice_2() { let mut x = vec![22_i32]; - let _b = || { + let _b = #[coroutine] || { for p in &x { yield(); } @@ -38,7 +38,7 @@ fn yield_during_iter_borrowed_slice_3() { // OK to take a mutable ref to `x` and yield // up pointers from it: let mut x = vec![22_i32]; - let mut b = || { + let mut b = #[coroutine] || { for p in &mut x { yield p; } @@ -50,7 +50,7 @@ fn yield_during_iter_borrowed_slice_4() { // ...but not OK to do that while reading // from `x` too let mut x = vec![22_i32]; - let mut b = || { + let mut b = #[coroutine] || { for p in &mut x { yield p; } @@ -61,7 +61,7 @@ fn yield_during_iter_borrowed_slice_4() { fn yield_during_range_iter() { // Should be OK. - let mut b = || { + let mut b = #[coroutine] || { let v = vec![1,2,3]; let len = v.len(); for i in 0..len { diff --git a/tests/ui/coroutine/yield-while-iterating.stderr b/tests/ui/coroutine/yield-while-iterating.stderr index 5330121f3728..f81c914c4bd4 100644 --- a/tests/ui/coroutine/yield-while-iterating.stderr +++ b/tests/ui/coroutine/yield-while-iterating.stderr @@ -9,8 +9,8 @@ LL | yield(); error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable --> $DIR/yield-while-iterating.rs:58:20 | -LL | let mut b = || { - | -- mutable borrow occurs here +LL | let mut b = #[coroutine] || { + | -- mutable borrow occurs here LL | for p in &mut x { | - first borrow occurs due to use of `x` in coroutine ... diff --git a/tests/ui/coroutine/yield-while-local-borrowed.rs b/tests/ui/coroutine/yield-while-local-borrowed.rs index 7f8d1d4543d8..3db30c36712f 100644 --- a/tests/ui/coroutine/yield-while-local-borrowed.rs +++ b/tests/ui/coroutine/yield-while-local-borrowed.rs @@ -1,4 +1,4 @@ -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] use std::cell::Cell; use std::ops::{Coroutine, CoroutineState}; @@ -9,7 +9,7 @@ fn borrow_local_inline() { // // (This error occurs because the region shows up in the type of // `b` and gets extended by region inference.) - let mut b = move || { + let mut b = #[coroutine] move || { let a = &mut 3; //~^ ERROR borrow may still be in use when coroutine yields yield (); @@ -20,7 +20,7 @@ fn borrow_local_inline() { fn borrow_local_inline_done() { // No error here -- `a` is not in scope at the point of `yield`. - let mut b = move || { + let mut b = #[coroutine] move || { { let a = &mut 3; } @@ -34,7 +34,7 @@ fn borrow_local() { // // (This error occurs because the region shows up in the type of // `b` and gets extended by region inference.) - let mut b = move || { + let mut b = #[coroutine] move || { let a = 3; { let b = &a; diff --git a/tests/ui/coroutine/yield-while-ref-reborrowed.rs b/tests/ui/coroutine/yield-while-ref-reborrowed.rs index 07c591758586..2600d0b4124b 100644 --- a/tests/ui/coroutine/yield-while-ref-reborrowed.rs +++ b/tests/ui/coroutine/yield-while-ref-reborrowed.rs @@ -1,15 +1,16 @@ -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] -use std::ops::{CoroutineState, Coroutine}; use std::cell::Cell; +use std::ops::{Coroutine, CoroutineState}; use std::pin::Pin; fn reborrow_shared_ref(x: &i32) { // This is OK -- we have a borrow live over the yield, but it's of // data that outlives the coroutine. - let mut b = move || { + let mut b = #[coroutine] + move || { let a = &*x; - yield(); + yield (); println!("{}", a); }; Pin::new(&mut b).resume(()); @@ -18,9 +19,10 @@ fn reborrow_shared_ref(x: &i32) { fn reborrow_mutable_ref(x: &mut i32) { // This is OK -- we have a borrow live over the yield, but it's of // data that outlives the coroutine. - let mut b = move || { + let mut b = #[coroutine] + move || { let a = &mut *x; - yield(); + yield (); println!("{}", a); }; Pin::new(&mut b).resume(()); @@ -28,13 +30,14 @@ fn reborrow_mutable_ref(x: &mut i32) { fn reborrow_mutable_ref_2(x: &mut i32) { // ...but not OK to go on using `x`. - let mut b = || { + let mut b = #[coroutine] + || { let a = &mut *x; - yield(); + yield (); println!("{}", a); }; println!("{}", x); //~ ERROR Pin::new(&mut b).resume(()); } -fn main() { } +fn main() {} diff --git a/tests/ui/coroutine/yield-while-ref-reborrowed.stderr b/tests/ui/coroutine/yield-while-ref-reborrowed.stderr index 62ac02653112..7c9b766457db 100644 --- a/tests/ui/coroutine/yield-while-ref-reborrowed.stderr +++ b/tests/ui/coroutine/yield-while-ref-reborrowed.stderr @@ -1,8 +1,8 @@ error[E0501]: cannot borrow `x` as immutable because previous closure requires unique access - --> $DIR/yield-while-ref-reborrowed.rs:36:20 + --> $DIR/yield-while-ref-reborrowed.rs:39:20 | -LL | let mut b = || { - | -- coroutine construction occurs here +LL | || { + | -- coroutine construction occurs here LL | let a = &mut *x; | -- first borrow occurs due to use of `x` in coroutine ... diff --git a/tests/ui/drop/dynamic-drop.rs b/tests/ui/drop/dynamic-drop.rs index f848a1a340b2..b695b5702d94 100644 --- a/tests/ui/drop/dynamic-drop.rs +++ b/tests/ui/drop/dynamic-drop.rs @@ -1,7 +1,7 @@ //@ run-pass //@ needs-unwind -#![feature(coroutines, coroutine_trait)] +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] #![feature(if_let_guard)] #![allow(unused_assignments)] @@ -176,7 +176,7 @@ fn vec_simple(a: &Allocator) { fn coroutine(a: &Allocator, run_count: usize) { assert!(run_count < 4); - let mut gen = || { + let mut gen = #[coroutine] || { (a.alloc(), yield a.alloc(), a.alloc(), diff --git a/tests/ui/feature-gates/feature-gate-closure_track_caller.rs b/tests/ui/feature-gates/feature-gate-closure_track_caller.rs index 93bf83ecf53c..d90fb765a237 100644 --- a/tests/ui/feature-gates/feature-gate-closure_track_caller.rs +++ b/tests/ui/feature-gates/feature-gate-closure_track_caller.rs @@ -4,6 +4,6 @@ fn main() { let _closure = #[track_caller] || {}; //~ `#[track_caller]` on closures - let _coroutine = #[track_caller] || { yield; }; //~ `#[track_caller]` on closures + let _coroutine = #[coroutine] #[track_caller] || { yield; }; //~ `#[track_caller]` on closures let _future = #[track_caller] async {}; //~ `#[track_caller]` on closures } diff --git a/tests/ui/feature-gates/feature-gate-closure_track_caller.stderr b/tests/ui/feature-gates/feature-gate-closure_track_caller.stderr index 17b5e6016a46..0b12b73fd1ff 100644 --- a/tests/ui/feature-gates/feature-gate-closure_track_caller.stderr +++ b/tests/ui/feature-gates/feature-gate-closure_track_caller.stderr @@ -9,10 +9,10 @@ LL | let _closure = #[track_caller] || {}; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `#[track_caller]` on closures is currently unstable - --> $DIR/feature-gate-closure_track_caller.rs:7:22 + --> $DIR/feature-gate-closure_track_caller.rs:7:35 | -LL | let _coroutine = #[track_caller] || { yield; }; - | ^^^^^^^^^^^^^^^ +LL | let _coroutine = #[coroutine] #[track_caller] || { yield; }; + | ^^^^^^^^^^^^^^^ | = note: see issue #87417 for more information = help: add `#![feature(closure_track_caller)]` to the crate attributes to enable diff --git a/tests/ui/feature-gates/feature-gate-coroutines.e2024.stderr b/tests/ui/feature-gates/feature-gate-coroutines.e2024.stderr index 1cef163cef5c..3bb48e4a37a4 100644 --- a/tests/ui/feature-gates/feature-gate-coroutines.e2024.stderr +++ b/tests/ui/feature-gates/feature-gate-coroutines.e2024.stderr @@ -8,8 +8,19 @@ LL | yield true; = help: add `#![feature(coroutines)]` 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: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks + --> $DIR/feature-gate-coroutines.rs:5:5 + | +LL | yield true; + | ^^^^^^^^^^ + | +help: use `#[coroutine]` to make this closure a coroutine + | +LL | #[coroutine] fn main() { + | ++++++++++++ + error[E0658]: yield syntax is experimental - --> $DIR/feature-gate-coroutines.rs:9:16 + --> $DIR/feature-gate-coroutines.rs:10:16 | LL | let _ = || yield true; | ^^^^^^^^^^ @@ -18,13 +29,24 @@ LL | let _ = || yield true; = help: add `#![feature(coroutines)]` 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: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks + --> $DIR/feature-gate-coroutines.rs:10:16 + | +LL | let _ = || yield true; + | ^^^^^^^^^^ + | +help: use `#[coroutine]` to make this closure a coroutine + | +LL | let _ = #[coroutine] || yield true; + | ++++++++++++ + error[E0627]: yield expression outside of coroutine literal --> $DIR/feature-gate-coroutines.rs:5:5 | LL | yield true; | ^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 5 previous errors Some errors have detailed explanations: E0627, E0658. For more information about an error, try `rustc --explain E0627`. diff --git a/tests/ui/feature-gates/feature-gate-coroutines.none.stderr b/tests/ui/feature-gates/feature-gate-coroutines.none.stderr index 403f0549aef2..65e7737ef84d 100644 --- a/tests/ui/feature-gates/feature-gate-coroutines.none.stderr +++ b/tests/ui/feature-gates/feature-gate-coroutines.none.stderr @@ -9,7 +9,7 @@ LL | yield true; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: yield syntax is experimental - --> $DIR/feature-gate-coroutines.rs:9:16 + --> $DIR/feature-gate-coroutines.rs:10:16 | LL | let _ = || yield true; | ^^^^^^^^^^ @@ -19,7 +19,7 @@ LL | let _ = || yield true; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: yield syntax is experimental - --> $DIR/feature-gate-coroutines.rs:16:5 + --> $DIR/feature-gate-coroutines.rs:18:5 | LL | yield; | ^^^^^ @@ -29,7 +29,7 @@ LL | yield; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: yield syntax is experimental - --> $DIR/feature-gate-coroutines.rs:17:5 + --> $DIR/feature-gate-coroutines.rs:19:5 | LL | yield 0; | ^^^^^^^ @@ -49,8 +49,19 @@ LL | yield true; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +error: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks + --> $DIR/feature-gate-coroutines.rs:5:5 + | +LL | yield true; + | ^^^^^^^^^^ + | +help: use `#[coroutine]` to make this closure a coroutine + | +LL | #[coroutine] fn main() { + | ++++++++++++ + error[E0658]: yield syntax is experimental - --> $DIR/feature-gate-coroutines.rs:9:16 + --> $DIR/feature-gate-coroutines.rs:10:16 | LL | let _ = || yield true; | ^^^^^^^^^^ @@ -60,13 +71,24 @@ LL | let _ = || yield true; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +error: `yield` can only be used in `#[coroutine]` closures, or `gen` blocks + --> $DIR/feature-gate-coroutines.rs:10:16 + | +LL | let _ = || yield true; + | ^^^^^^^^^^ + | +help: use `#[coroutine]` to make this closure a coroutine + | +LL | let _ = #[coroutine] || yield true; + | ++++++++++++ + error[E0627]: yield expression outside of coroutine literal --> $DIR/feature-gate-coroutines.rs:5:5 | LL | yield true; | ^^^^^^^^^^ -error: aborting due to 7 previous errors +error: aborting due to 9 previous errors Some errors have detailed explanations: E0627, E0658. For more information about an error, try `rustc --explain E0627`. diff --git a/tests/ui/feature-gates/feature-gate-coroutines.rs b/tests/ui/feature-gates/feature-gate-coroutines.rs index b3df2351b680..28dce8596d39 100644 --- a/tests/ui/feature-gates/feature-gate-coroutines.rs +++ b/tests/ui/feature-gates/feature-gate-coroutines.rs @@ -5,9 +5,11 @@ fn main() { yield true; //~ ERROR yield syntax is experimental //~^ ERROR yield expression outside of coroutine literal //[none]~^^ ERROR yield syntax is experimental + //~^^^ ERROR `yield` can only be used let _ = || yield true; //~ ERROR yield syntax is experimental //[none]~^ ERROR yield syntax is experimental + //~^^ ERROR `yield` can only be used } #[cfg(FALSE)] diff --git a/tests/ui/impl-trait/issues/issue-58504.rs b/tests/ui/impl-trait/issues/issue-58504.rs index 4f7a35e81b80..856e1297e58b 100644 --- a/tests/ui/impl-trait/issues/issue-58504.rs +++ b/tests/ui/impl-trait/issues/issue-58504.rs @@ -3,7 +3,7 @@ use std::ops::Coroutine; fn mk_gen() -> impl Coroutine { - || { loop { yield; } } + #[coroutine] || { loop { yield; } } } fn main() { diff --git a/tests/ui/impl-trait/lifetimes.rs b/tests/ui/impl-trait/lifetimes.rs index 93a4801fa40e..df64b685eab8 100644 --- a/tests/ui/impl-trait/lifetimes.rs +++ b/tests/ui/impl-trait/lifetimes.rs @@ -115,7 +115,7 @@ impl<'unnecessary_lifetime> MyVec { } fn coroutine_doesnt_capture_unnecessary_lifetime<'s: 's>() -> impl Sized { - || yield + #[coroutine] || yield } } diff --git a/tests/ui/impl-trait/recursive-coroutine-boxed.next.stderr b/tests/ui/impl-trait/recursive-coroutine-boxed.next.stderr index c0b399746eaf..96db2030a405 100644 --- a/tests/ui/impl-trait/recursive-coroutine-boxed.next.stderr +++ b/tests/ui/impl-trait/recursive-coroutine-boxed.next.stderr @@ -1,5 +1,5 @@ error[E0282]: type annotations needed - --> $DIR/recursive-coroutine-boxed.rs:14:23 + --> $DIR/recursive-coroutine-boxed.rs:15:23 | LL | let mut gen = Box::pin(foo()); | ^^^^^^^^ cannot infer type of the type parameter `T` declared on the struct `Box` @@ -13,7 +13,7 @@ LL | let mut gen = Box::::pin(foo()); | +++++ error[E0308]: mismatched types - --> $DIR/recursive-coroutine-boxed.rs:13:5 + --> $DIR/recursive-coroutine-boxed.rs:14:18 | LL | fn foo() -> impl Coroutine { | --------------------------------------- @@ -21,7 +21,8 @@ LL | fn foo() -> impl Coroutine { | the expected opaque type | expected `impl Coroutine` because of return type ... -LL | / || { +LL | #[coroutine] || { + | __________________^ LL | | let mut gen = Box::pin(foo()); LL | | LL | | let mut r = gen.as_mut().resume(()); @@ -31,7 +32,7 @@ LL | | } | |_____^ types differ | = note: expected opaque type `impl Coroutine` - found coroutine `{coroutine@$DIR/recursive-coroutine-boxed.rs:13:5: 13:7}` + found coroutine `{coroutine@$DIR/recursive-coroutine-boxed.rs:14:18: 14:20}` error: aborting due to 2 previous errors diff --git a/tests/ui/impl-trait/recursive-coroutine-boxed.rs b/tests/ui/impl-trait/recursive-coroutine-boxed.rs index 02c75be0f3aa..24a77d731141 100644 --- a/tests/ui/impl-trait/recursive-coroutine-boxed.rs +++ b/tests/ui/impl-trait/recursive-coroutine-boxed.rs @@ -10,7 +10,8 @@ fn foo() -> impl Coroutine { // FIXME(-Znext-solver): this fails with a mismatched types as the // hidden type of the opaque ends up as {type error}. We should not // emit errors for such goals. - || { //[next]~ ERROR mismatched types + + #[coroutine] || { //[next]~ ERROR mismatched types let mut gen = Box::pin(foo()); //[next]~^ ERROR type annotations needed let mut r = gen.as_mut().resume(()); diff --git a/tests/ui/impl-trait/recursive-coroutine-indirect.current.stderr b/tests/ui/impl-trait/recursive-coroutine-indirect.current.stderr index ee87c483d0d0..9814187e179e 100644 --- a/tests/ui/impl-trait/recursive-coroutine-indirect.current.stderr +++ b/tests/ui/impl-trait/recursive-coroutine-indirect.current.stderr @@ -1,8 +1,8 @@ error[E0733]: recursion in a coroutine requires boxing - --> $DIR/recursive-coroutine-indirect.rs:11:5 + --> $DIR/recursive-coroutine-indirect.rs:11:18 | -LL | move || { - | ^^^^^^^ +LL | #[coroutine] move || { + | ^^^^^^^ LL | let x = coroutine_hold(); | - recursive call here diff --git a/tests/ui/impl-trait/recursive-coroutine-indirect.next.stderr b/tests/ui/impl-trait/recursive-coroutine-indirect.next.stderr index ee87c483d0d0..9814187e179e 100644 --- a/tests/ui/impl-trait/recursive-coroutine-indirect.next.stderr +++ b/tests/ui/impl-trait/recursive-coroutine-indirect.next.stderr @@ -1,8 +1,8 @@ error[E0733]: recursion in a coroutine requires boxing - --> $DIR/recursive-coroutine-indirect.rs:11:5 + --> $DIR/recursive-coroutine-indirect.rs:11:18 | -LL | move || { - | ^^^^^^^ +LL | #[coroutine] move || { + | ^^^^^^^ LL | let x = coroutine_hold(); | - recursive call here diff --git a/tests/ui/impl-trait/recursive-coroutine-indirect.rs b/tests/ui/impl-trait/recursive-coroutine-indirect.rs index bba9792fe3cf..cec2176049b8 100644 --- a/tests/ui/impl-trait/recursive-coroutine-indirect.rs +++ b/tests/ui/impl-trait/recursive-coroutine-indirect.rs @@ -8,7 +8,7 @@ #![feature(coroutines)] #![allow(unconditional_recursion)] fn coroutine_hold() -> impl Sized { - move || { //~ ERROR recursion in a coroutine requires boxing + #[coroutine] move || { //~ ERROR recursion in a coroutine requires boxing let x = coroutine_hold(); yield; x; diff --git a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.rs b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.rs index 432f80a1763e..8b9dac0e29b0 100644 --- a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.rs +++ b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.rs @@ -57,6 +57,8 @@ fn coroutine_sig() -> impl Sized { fn coroutine_capture() -> impl Sized { //~^ ERROR let x = coroutine_capture(); + + #[coroutine] move || { yield; x; diff --git a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr index d5b8c531fd6e..2d2731e4368f 100644 --- a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr +++ b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr @@ -98,10 +98,10 @@ LL | | yield; LL | | x; | | - coroutine captures itself here LL | | } - | |_____- returning here with type `{coroutine@$DIR/recursive-impl-trait-type-indirect.rs:60:5: 60:12}` + | |_____- returning here with type `{coroutine@$DIR/recursive-impl-trait-type-indirect.rs:62:5: 62:12}` error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:66:35 + --> $DIR/recursive-impl-trait-type-indirect.rs:68:35 | LL | fn substs_change() -> impl Sized { | ^^^^^^^^^^ recursive opaque type @@ -110,7 +110,7 @@ LL | (substs_change::<&T>(),) | ------------------------ returning here with type `(impl Sized,)` error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:76:26 + --> $DIR/recursive-impl-trait-type-indirect.rs:78:26 | LL | fn mutual_recursion() -> impl Sync { | ^^^^^^^^^ recursive opaque type @@ -122,7 +122,7 @@ LL | fn mutual_recursion_b() -> impl Sized { | ---------- returning this opaque type `impl Sized` error[E0720]: cannot resolve opaque type - --> $DIR/recursive-impl-trait-type-indirect.rs:81:28 + --> $DIR/recursive-impl-trait-type-indirect.rs:83:28 | LL | fn mutual_recursion() -> impl Sync { | --------- returning this opaque type `impl Sync` diff --git a/tests/ui/lint/must_not_suspend/tuple-mismatch.rs b/tests/ui/lint/must_not_suspend/tuple-mismatch.rs index 2f3c5d9ea294..ec409925d724 100644 --- a/tests/ui/lint/must_not_suspend/tuple-mismatch.rs +++ b/tests/ui/lint/must_not_suspend/tuple-mismatch.rs @@ -1,7 +1,8 @@ -#![feature(coroutines)] +#![feature(coroutines, stmt_expr_attributes)] fn main() { - let _coroutine = || { + let _coroutine = #[coroutine] + || { yield ((), ((), ())); yield ((), ()); //~^ ERROR mismatched types diff --git a/tests/ui/lint/must_not_suspend/tuple-mismatch.stderr b/tests/ui/lint/must_not_suspend/tuple-mismatch.stderr index 3adf26cfee22..102eadd7affd 100644 --- a/tests/ui/lint/must_not_suspend/tuple-mismatch.stderr +++ b/tests/ui/lint/must_not_suspend/tuple-mismatch.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/tuple-mismatch.rs:6:20 + --> $DIR/tuple-mismatch.rs:7:20 | LL | yield ((), ()); | ^^ expected `((), ())`, found `()` diff --git a/tests/ui/lint/unused/issue-74883-unused-paren-baren-yield.rs b/tests/ui/lint/unused/issue-74883-unused-paren-baren-yield.rs index c5dd281cb4e5..12e2bcb898ca 100644 --- a/tests/ui/lint/unused/issue-74883-unused-paren-baren-yield.rs +++ b/tests/ui/lint/unused/issue-74883-unused-paren-baren-yield.rs @@ -1,12 +1,12 @@ #![feature(coroutine_trait)] -#![feature(coroutines)] +#![feature(coroutines, stmt_expr_attributes)] #![deny(unused_braces, unused_parens)] use std::ops::Coroutine; use std::pin::Pin; fn main() { - let mut x = |_| { + let mut x = #[coroutine] |_| { while let Some(_) = (yield) {} while let Some(_) = {yield} {} diff --git a/tests/ui/lint/unused/unused-closure.rs b/tests/ui/lint/unused/unused-closure.rs index 9106edee6538..4633038cc9bb 100644 --- a/tests/ui/lint/unused/unused-closure.rs +++ b/tests/ui/lint/unused/unused-closure.rs @@ -2,7 +2,7 @@ //@ edition:2018 #![feature(async_closure)] -#![feature(coroutines)] +#![feature(coroutines, stmt_expr_attributes)] #![deny(unused_must_use)] fn unused() { @@ -26,7 +26,7 @@ fn unused() { fn ignored() { let _ = || {}; - let _ = || yield 42; + let _ = #[coroutine] || yield 42; } fn main() { diff --git a/tests/ui/liveness/liveness-upvars.rs b/tests/ui/liveness/liveness-upvars.rs index 7898b9788823..f76efba3e6b3 100644 --- a/tests/ui/liveness/liveness-upvars.rs +++ b/tests/ui/liveness/liveness-upvars.rs @@ -1,6 +1,6 @@ //@ edition:2018 //@ check-pass -#![feature(coroutines)] +#![feature(coroutines, stmt_expr_attributes)] #![warn(unused)] #![allow(unreachable_code)] @@ -131,7 +131,7 @@ pub fn async_coroutine() { pub fn coroutine() { let mut s: u32 = 0; - let _ = |_| { + let _ = #[coroutine] |_| { s = 0; yield (); s = 1; //~ WARN value assigned to `s` is never read diff --git a/tests/ui/nll/coroutine-distinct-lifetime.rs b/tests/ui/nll/coroutine-distinct-lifetime.rs index ff94a3d54b76..471fad686c4c 100644 --- a/tests/ui/nll/coroutine-distinct-lifetime.rs +++ b/tests/ui/nll/coroutine-distinct-lifetime.rs @@ -9,6 +9,7 @@ //@ check-pass fn foo(x: &mut u32) { + #[coroutine] move || { let s = &mut *x; yield; diff --git a/tests/ui/nll/coroutine-upvar-mutability.rs b/tests/ui/nll/coroutine-upvar-mutability.rs index 12853b16b9b7..a7d14173fb9f 100644 --- a/tests/ui/nll/coroutine-upvar-mutability.rs +++ b/tests/ui/nll/coroutine-upvar-mutability.rs @@ -4,6 +4,8 @@ fn mutate_upvar() { let x = 0; + + #[coroutine] move || { x = 1; //~^ ERROR diff --git a/tests/ui/nll/coroutine-upvar-mutability.stderr b/tests/ui/nll/coroutine-upvar-mutability.stderr index 8922eae31518..8b9be877c8f3 100644 --- a/tests/ui/nll/coroutine-upvar-mutability.stderr +++ b/tests/ui/nll/coroutine-upvar-mutability.stderr @@ -1,9 +1,9 @@ error[E0594]: cannot assign to `x`, as it is not declared as mutable - --> $DIR/coroutine-upvar-mutability.rs:8:9 + --> $DIR/coroutine-upvar-mutability.rs:10:9 | LL | let x = 0; | - help: consider changing this to be mutable: `mut x` -LL | move || { +... LL | x = 1; | ^^^^^ cannot assign diff --git a/tests/ui/nll/extra-unused-mut.rs b/tests/ui/nll/extra-unused-mut.rs index 786ba98508fb..b040dcc6e5db 100644 --- a/tests/ui/nll/extra-unused-mut.rs +++ b/tests/ui/nll/extra-unused-mut.rs @@ -18,6 +18,8 @@ fn mutable_upvar() { // #50897 fn coroutine_mutable_upvar() { let mut x = 0; + + #[coroutine] move || { x = 1; yield; @@ -36,13 +38,13 @@ struct Expr { // #51904 fn parse_dot_or_call_expr_with(mut attrs: Vec) { let x = Expr { attrs: vec![] }; - Some(Some(x)).map(|expr| + Some(Some(x)).map(|expr| { expr.map(|mut expr| { attrs.push(666); expr.attrs = attrs; expr }) - ); + }); } // Found when trying to bootstrap rustc diff --git a/tests/ui/nll/issue-48623-coroutine.rs b/tests/ui/nll/issue-48623-coroutine.rs index 3a4a27855d99..63348a2047c0 100644 --- a/tests/ui/nll/issue-48623-coroutine.rs +++ b/tests/ui/nll/issue-48623-coroutine.rs @@ -12,7 +12,7 @@ impl Drop for WithDrop { fn reborrow_from_coroutine(r: &mut ()) { let d = WithDrop; - move || { d; yield; &mut *r }; //~ WARN unused coroutine that must be used + #[coroutine] move || { d; yield; &mut *r }; //~ WARN unused coroutine that must be used } fn main() {} diff --git a/tests/ui/nll/issue-48623-coroutine.stderr b/tests/ui/nll/issue-48623-coroutine.stderr index 1b7b1735aacb..4e4cd28ef2ae 100644 --- a/tests/ui/nll/issue-48623-coroutine.stderr +++ b/tests/ui/nll/issue-48623-coroutine.stderr @@ -1,8 +1,8 @@ warning: unused coroutine that must be used - --> $DIR/issue-48623-coroutine.rs:15:5 + --> $DIR/issue-48623-coroutine.rs:15:18 | -LL | move || { d; yield; &mut *r }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[coroutine] move || { d; yield; &mut *r }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: coroutines are lazy and do nothing unless resumed = note: `#[warn(unused_must_use)]` on by default diff --git a/tests/ui/nll/issue-55850.rs b/tests/ui/nll/issue-55850.rs index fc873af94638..bf1e2e7caef6 100644 --- a/tests/ui/nll/issue-55850.rs +++ b/tests/ui/nll/issue-55850.rs @@ -23,7 +23,7 @@ where } fn bug<'a>() -> impl Iterator { - GenIter(move || { + GenIter(#[coroutine] move || { let mut s = String::new(); yield &s[..] //~ ERROR cannot yield value referencing local variable `s` [E0515] //~| ERROR borrow may still be in use when coroutine yields diff --git a/tests/ui/packed/packed-struct-drop-aligned.rs b/tests/ui/packed/packed-struct-drop-aligned.rs index 037b8cb78b72..ba3dcb10c61e 100644 --- a/tests/ui/packed/packed-struct-drop-aligned.rs +++ b/tests/ui/packed/packed-struct-drop-aligned.rs @@ -1,5 +1,5 @@ //@ run-pass -#![feature(coroutines)] +#![feature(coroutines, stmt_expr_attributes)] #![feature(coroutine_trait)] use std::cell::Cell; use std::mem; @@ -7,13 +7,12 @@ use std::ops::Coroutine; use std::pin::Pin; struct Aligned<'a> { - drop_count: &'a Cell + drop_count: &'a Cell, } #[inline(never)] fn check_align(ptr: *const Aligned) { - assert_eq!(ptr as usize % mem::align_of::(), - 0); + assert_eq!(ptr as usize % mem::align_of::(), 0); } impl<'a> Drop for Aligned<'a> { @@ -39,7 +38,8 @@ fn main() { assert_eq!(drop_count.get(), 2); let drop_count = &Cell::new(0); - let mut g = || { + let mut g = #[coroutine] + || { let mut p = Packed(NotCopy(0), Aligned { drop_count }); let _ = &p; p.1 = Aligned { drop_count }; diff --git a/tests/ui/polymorphization/coroutine.rs b/tests/ui/polymorphization/coroutine.rs index a989947f7873..22ceadfb194d 100644 --- a/tests/ui/polymorphization/coroutine.rs +++ b/tests/ui/polymorphization/coroutine.rs @@ -32,6 +32,7 @@ where #[rustc_polymorphize_error] pub fn unused_type() -> impl Coroutine<(), Yield = u32, Return = u32> + Unpin { + #[coroutine] || { //~^ ERROR item has unused generic parameters yield 1; @@ -41,6 +42,7 @@ pub fn unused_type() -> impl Coroutine<(), Yield = u32, Return = u32> + Unpin #[rustc_polymorphize_error] pub fn used_type_in_yield() -> impl Coroutine<(), Yield = Y, Return = u32> + Unpin { + #[coroutine] || { yield Y::default(); 2 @@ -49,6 +51,7 @@ pub fn used_type_in_yield() -> impl Coroutine<(), Yield = Y, Return #[rustc_polymorphize_error] pub fn used_type_in_return() -> impl Coroutine<(), Yield = u32, Return = R> + Unpin { + #[coroutine] || { yield 3; R::default() @@ -57,6 +60,7 @@ pub fn used_type_in_return() -> impl Coroutine<(), Yield = u32, Retu #[rustc_polymorphize_error] pub fn unused_const() -> impl Coroutine<(), Yield = u32, Return = u32> + Unpin { + #[coroutine] || { //~^ ERROR item has unused generic parameters yield 1; @@ -67,6 +71,7 @@ pub fn unused_const() -> impl Coroutine<(), Yield = u32, Return = #[rustc_polymorphize_error] pub fn used_const_in_yield() -> impl Coroutine<(), Yield = u32, Return = u32> + Unpin { + #[coroutine] || { yield Y; 2 @@ -76,6 +81,7 @@ pub fn used_const_in_yield() -> impl Coroutine<(), Yield = u32, Re #[rustc_polymorphize_error] pub fn used_const_in_return() -> impl Coroutine<(), Yield = u32, Return = u32> + Unpin { + #[coroutine] || { yield 4; R diff --git a/tests/ui/polymorphization/coroutine.stderr b/tests/ui/polymorphization/coroutine.stderr index 67b55a598831..07e29184226d 100644 --- a/tests/ui/polymorphization/coroutine.stderr +++ b/tests/ui/polymorphization/coroutine.stderr @@ -8,18 +8,20 @@ LL | #![feature(generic_const_exprs, coroutines, coroutine_trait, rustc_attrs)] = note: `#[warn(incomplete_features)]` on by default error: item has unused generic parameters - --> $DIR/coroutine.rs:35:5 + --> $DIR/coroutine.rs:36:5 | LL | pub fn unused_type() -> impl Coroutine<(), Yield = u32, Return = u32> + Unpin { | - generic parameter `T` is unused +LL | #[coroutine] LL | || { | ^^ error: item has unused generic parameters - --> $DIR/coroutine.rs:60:5 + --> $DIR/coroutine.rs:64:5 | LL | pub fn unused_const() -> impl Coroutine<(), Yield = u32, Return = u32> + Unpin { | ------------ generic parameter `T` is unused +LL | #[coroutine] LL | || { | ^^ diff --git a/tests/ui/print_type_sizes/coroutine.rs b/tests/ui/print_type_sizes/coroutine.rs index 61488c51f053..153357887894 100644 --- a/tests/ui/print_type_sizes/coroutine.rs +++ b/tests/ui/print_type_sizes/coroutine.rs @@ -7,6 +7,7 @@ use std::ops::Coroutine; fn coroutine(array: [u8; C]) -> impl Coroutine { + #[coroutine] move |()| { yield (); let _ = array; diff --git a/tests/ui/print_type_sizes/coroutine.stdout b/tests/ui/print_type_sizes/coroutine.stdout index 5d51339558ca..339bbddfc2a9 100644 --- a/tests/ui/print_type_sizes/coroutine.stdout +++ b/tests/ui/print_type_sizes/coroutine.stdout @@ -1,4 +1,4 @@ -print-type-size type: `{coroutine@$DIR/coroutine.rs:10:5: 10:14}`: 8193 bytes, alignment: 1 bytes +print-type-size type: `{coroutine@$DIR/coroutine.rs:11:5: 11:14}`: 8193 bytes, alignment: 1 bytes print-type-size discriminant: 1 bytes print-type-size variant `Unresumed`: 8192 bytes print-type-size upvar `.array`: 8192 bytes diff --git a/tests/ui/print_type_sizes/coroutine_discr_placement.rs b/tests/ui/print_type_sizes/coroutine_discr_placement.rs index 4b9f67a79997..d97b0b28ed0f 100644 --- a/tests/ui/print_type_sizes/coroutine_discr_placement.rs +++ b/tests/ui/print_type_sizes/coroutine_discr_placement.rs @@ -5,11 +5,12 @@ // Tests a coroutine that has its discriminant as the *final* field. // Avoid emitting panic handlers, like the rest of these tests... -#![feature(coroutines)] +#![feature(coroutines, stmt_expr_attributes)] #![allow(dropping_copy_types)] pub fn foo() { - let a = || { + let a = #[coroutine] + || { { let w: i32 = 4; yield; diff --git a/tests/ui/print_type_sizes/coroutine_discr_placement.stdout b/tests/ui/print_type_sizes/coroutine_discr_placement.stdout index 71a7f3c63815..4ce1ce46f6e8 100644 --- a/tests/ui/print_type_sizes/coroutine_discr_placement.stdout +++ b/tests/ui/print_type_sizes/coroutine_discr_placement.stdout @@ -1,4 +1,4 @@ -print-type-size type: `{coroutine@$DIR/coroutine_discr_placement.rs:12:13: 12:15}`: 8 bytes, alignment: 4 bytes +print-type-size type: `{coroutine@$DIR/coroutine_discr_placement.rs:13:5: 13:7}`: 8 bytes, alignment: 4 bytes print-type-size discriminant: 1 bytes print-type-size variant `Unresumed`: 0 bytes print-type-size variant `Suspend0`: 7 bytes diff --git a/tests/ui/rfcs/rfc-2091-track-caller/tracked-closure.rs b/tests/ui/rfcs/rfc-2091-track-caller/tracked-closure.rs index d5c8a529e1e3..9fdceefbf9b9 100644 --- a/tests/ui/rfcs/rfc-2091-track-caller/tracked-closure.rs +++ b/tests/ui/rfcs/rfc-2091-track-caller/tracked-closure.rs @@ -113,7 +113,7 @@ fn dyn_coroutine( } fn test_coroutine() { - let coroutine = #[track_caller] |arg: String| { + let coroutine = #[track_caller] #[coroutine] |arg: String| { yield ("first", arg.clone(), Location::caller()); yield ("second", arg.clone(), Location::caller()); }; @@ -136,7 +136,7 @@ fn test_coroutine() { assert_eq!(mono_loc.line(), mono_line); assert_eq!(mono_loc.column(), 42); - let non_tracked_coroutine = || { yield Location::caller(); }; + let non_tracked_coroutine = #[coroutine] || { yield Location::caller(); }; let non_tracked_line = line!() - 1; // This is the line of the coroutine, not its caller let non_tracked_loc = match Box::pin(non_tracked_coroutine).as_mut().resume(()) { CoroutineState::Yielded(val) => val, @@ -144,7 +144,7 @@ fn test_coroutine() { }; assert_eq!(non_tracked_loc.file(), file!()); assert_eq!(non_tracked_loc.line(), non_tracked_line); - assert_eq!(non_tracked_loc.column(), 44); + assert_eq!(non_tracked_loc.column(), 57); } diff --git a/tests/ui/sanitizer/cfi-coroutine.rs b/tests/ui/sanitizer/cfi-coroutine.rs index 5c6a489a7e89..ad994fcf7370 100644 --- a/tests/ui/sanitizer/cfi-coroutine.rs +++ b/tests/ui/sanitizer/cfi-coroutine.rs @@ -14,7 +14,7 @@ //@ compile-flags: --test -Z unstable-options //@ run-pass -#![feature(coroutines)] +#![feature(coroutines, stmt_expr_attributes)] #![feature(coroutine_trait)] #![feature(noop_waker)] #![feature(gen_blocks)] @@ -27,7 +27,7 @@ use std::async_iter::AsyncIterator; #[test] fn general_coroutine() { - let mut coro = |x: i32| { + let mut coro = #[coroutine] |x: i32| { yield x; "done" }; diff --git a/tests/ui/suggestions/issue-84973-blacklist.rs b/tests/ui/suggestions/issue-84973-blacklist.rs index 6a35d779c1cd..edc0637636b5 100644 --- a/tests/ui/suggestions/issue-84973-blacklist.rs +++ b/tests/ui/suggestions/issue-84973-blacklist.rs @@ -14,7 +14,7 @@ struct S; fn main() { f_copy("".to_string()); //~ ERROR: the trait bound `String: Copy` is not satisfied [E0277] f_clone(S); //~ ERROR: the trait bound `S: Clone` is not satisfied [E0277] - f_unpin(static || { yield; }); + f_unpin(#[coroutine] static || { yield; }); //~^ ERROR: cannot be unpinned [E0277] let cl = || (); diff --git a/tests/ui/suggestions/issue-84973-blacklist.stderr b/tests/ui/suggestions/issue-84973-blacklist.stderr index 333382283285..4fd063e46926 100644 --- a/tests/ui/suggestions/issue-84973-blacklist.stderr +++ b/tests/ui/suggestions/issue-84973-blacklist.stderr @@ -36,11 +36,11 @@ LL + #[derive(Clone)] LL | struct S; | -error[E0277]: `{static coroutine@$DIR/issue-84973-blacklist.rs:17:13: 17:22}` cannot be unpinned - --> $DIR/issue-84973-blacklist.rs:17:13 +error[E0277]: `{static coroutine@$DIR/issue-84973-blacklist.rs:17:26: 17:35}` cannot be unpinned + --> $DIR/issue-84973-blacklist.rs:17:26 | -LL | f_unpin(static || { yield; }); - | ------- ^^^^^^^^^^^^^^^^^^^^ the trait `Unpin` is not implemented for `{static coroutine@$DIR/issue-84973-blacklist.rs:17:13: 17:22}` +LL | f_unpin(#[coroutine] static || { yield; }); + | ------- ^^^^^^^^^^^^^^^^^^^^ the trait `Unpin` is not implemented for `{static coroutine@$DIR/issue-84973-blacklist.rs:17:26: 17:35}` | | | required by a bound introduced by this call | diff --git a/tests/ui/suggestions/unnamable-types.rs b/tests/ui/suggestions/unnamable-types.rs index a4e32d7c8065..dd2c3536eb92 100644 --- a/tests/ui/suggestions/unnamable-types.rs +++ b/tests/ui/suggestions/unnamable-types.rs @@ -1,7 +1,7 @@ // Test that we do not suggest to add type annotations for unnamable types. #![crate_type="lib"] -#![feature(coroutines)] +#![feature(coroutines, stmt_expr_attributes)] const A = 5; //~^ ERROR: missing type for `const` item @@ -34,6 +34,6 @@ const F = S { t: foo }; //~| HELP: provide a type for the constant -const G = || -> i32 { yield 0; return 1; }; +const G = #[coroutine] || -> i32 { yield 0; return 1; }; //~^ ERROR: missing type for `const` item //~| NOTE: however, the inferred type diff --git a/tests/ui/suggestions/unnamable-types.stderr b/tests/ui/suggestions/unnamable-types.stderr index d003b91691c0..6623678fd0c2 100644 --- a/tests/ui/suggestions/unnamable-types.stderr +++ b/tests/ui/suggestions/unnamable-types.stderr @@ -52,14 +52,14 @@ LL | const F = S { t: foo }; error: missing type for `const` item --> $DIR/unnamable-types.rs:37:8 | -LL | const G = || -> i32 { yield 0; return 1; }; +LL | const G = #[coroutine] || -> i32 { yield 0; return 1; }; | ^ | -note: however, the inferred type `{coroutine@$DIR/unnamable-types.rs:37:11: 37:20}` cannot be named - --> $DIR/unnamable-types.rs:37:11 +note: however, the inferred type `{coroutine@$DIR/unnamable-types.rs:37:24: 37:33}` cannot be named + --> $DIR/unnamable-types.rs:37:24 | -LL | const G = || -> i32 { yield 0; return 1; }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | const G = #[coroutine] || -> i32 { yield 0; return 1; }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 7 previous errors diff --git a/tests/ui/traits/next-solver/coroutine.fail.stderr b/tests/ui/traits/next-solver/coroutine.fail.stderr index 14e67727d0ba..e880d05a4dd3 100644 --- a/tests/ui/traits/next-solver/coroutine.fail.stderr +++ b/tests/ui/traits/next-solver/coroutine.fail.stderr @@ -1,16 +1,16 @@ -error[E0277]: the trait bound `{coroutine@$DIR/coroutine.rs:18:21: 18:23}: Coroutine` is not satisfied - --> $DIR/coroutine.rs:18:21 +error[E0277]: the trait bound `{coroutine@$DIR/coroutine.rs:20:9: 20:11}: Coroutine` is not satisfied + --> $DIR/coroutine.rs:20:9 | -LL | needs_coroutine(|| { - | _____---------------_^ - | | | - | | required by a bound introduced by this call +LL | needs_coroutine( + | --------------- required by a bound introduced by this call +LL | #[coroutine] +LL | / || { LL | | LL | | LL | | -LL | | yield (); -LL | | }); - | |_____^ the trait `Coroutine` is not implemented for `{coroutine@$DIR/coroutine.rs:18:21: 18:23}` +LL | | yield (); +LL | | }, + | |_________^ the trait `Coroutine` is not implemented for `{coroutine@$DIR/coroutine.rs:20:9: 20:11}` | note: required by a bound in `needs_coroutine` --> $DIR/coroutine.rs:14:28 @@ -18,19 +18,19 @@ note: required by a bound in `needs_coroutine` LL | fn needs_coroutine(_: impl Coroutine) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `needs_coroutine` -error[E0271]: type mismatch resolving `<{coroutine@$DIR/coroutine.rs:18:21: 18:23} as Coroutine>::Yield == B` - --> $DIR/coroutine.rs:18:21 +error[E0271]: type mismatch resolving `<{coroutine@$DIR/coroutine.rs:20:9: 20:11} as Coroutine>::Yield == B` + --> $DIR/coroutine.rs:20:9 | -LL | needs_coroutine(|| { - | _____---------------_^ - | | | - | | required by a bound introduced by this call +LL | needs_coroutine( + | --------------- required by a bound introduced by this call +LL | #[coroutine] +LL | / || { LL | | LL | | LL | | -LL | | yield (); -LL | | }); - | |_____^ types differ +LL | | yield (); +LL | | }, + | |_________^ types differ | note: required by a bound in `needs_coroutine` --> $DIR/coroutine.rs:14:41 @@ -38,19 +38,19 @@ note: required by a bound in `needs_coroutine` LL | fn needs_coroutine(_: impl Coroutine) {} | ^^^^^^^^^ required by this bound in `needs_coroutine` -error[E0271]: type mismatch resolving `<{coroutine@$DIR/coroutine.rs:18:21: 18:23} as Coroutine>::Return == C` - --> $DIR/coroutine.rs:18:21 +error[E0271]: type mismatch resolving `<{coroutine@$DIR/coroutine.rs:20:9: 20:11} as Coroutine>::Return == C` + --> $DIR/coroutine.rs:20:9 | -LL | needs_coroutine(|| { - | _____---------------_^ - | | | - | | required by a bound introduced by this call +LL | needs_coroutine( + | --------------- required by a bound introduced by this call +LL | #[coroutine] +LL | / || { LL | | LL | | LL | | -LL | | yield (); -LL | | }); - | |_____^ types differ +LL | | yield (); +LL | | }, + | |_________^ types differ | note: required by a bound in `needs_coroutine` --> $DIR/coroutine.rs:14:52 diff --git a/tests/ui/traits/next-solver/coroutine.rs b/tests/ui/traits/next-solver/coroutine.rs index 2b5bf01cefd7..1882a62cf29c 100644 --- a/tests/ui/traits/next-solver/coroutine.rs +++ b/tests/ui/traits/next-solver/coroutine.rs @@ -15,18 +15,24 @@ fn needs_coroutine(_: impl Coroutine) {} #[cfg(fail)] fn main() { - needs_coroutine(|| { - //[fail]~^ ERROR Coroutine` is not satisfied - //[fail]~| ERROR as Coroutine>::Yield == B` - //[fail]~| ERROR as Coroutine>::Return == C` - yield (); - }); + needs_coroutine( + #[coroutine] + || { + //[fail]~^ ERROR Coroutine` is not satisfied + //[fail]~| ERROR as Coroutine>::Yield == B` + //[fail]~| ERROR as Coroutine>::Return == C` + yield (); + }, + ); } #[cfg(pass)] fn main() { - needs_coroutine(|_: A| { - let _: A = yield B; - C - }) + needs_coroutine( + #[coroutine] + |_: A| { + let _: A = yield B; + C + }, + ) } diff --git a/tests/ui/type-alias-impl-trait/issue-53678-coroutine-and-const-fn.rs b/tests/ui/type-alias-impl-trait/issue-53678-coroutine-and-const-fn.rs index cd14bc1fd098..0d9126d39933 100644 --- a/tests/ui/type-alias-impl-trait/issue-53678-coroutine-and-const-fn.rs +++ b/tests/ui/type-alias-impl-trait/issue-53678-coroutine-and-const-fn.rs @@ -9,6 +9,7 @@ mod gen { pub type CoroOnce = impl Coroutine; pub const fn const_coroutine(yielding: Y, returning: R) -> CoroOnce { + #[coroutine] move || { yield yielding; diff --git a/tests/ui/type-alias-impl-trait/issue-58662-coroutine-with-lifetime.rs b/tests/ui/type-alias-impl-trait/issue-58662-coroutine-with-lifetime.rs index 78a1d5116bed..899e81ed562f 100644 --- a/tests/ui/type-alias-impl-trait/issue-58662-coroutine-with-lifetime.rs +++ b/tests/ui/type-alias-impl-trait/issue-58662-coroutine-with-lifetime.rs @@ -8,6 +8,7 @@ use std::pin::Pin; type RandCoroutine<'a> = impl Coroutine + 'a; fn rand_coroutine<'a>(rng: &'a ()) -> RandCoroutine<'a> { + #[coroutine] move || { let _rng = rng; loop { @@ -19,6 +20,7 @@ fn rand_coroutine<'a>(rng: &'a ()) -> RandCoroutine<'a> { pub type RandCoroutineWithIndirection<'c> = impl Coroutine + 'c; pub fn rand_coroutine_with_indirection<'a>(rng: &'a ()) -> RandCoroutineWithIndirection<'a> { fn helper<'b>(rng: &'b ()) -> impl 'b + Coroutine { + #[coroutine] move || { let _rng = rng; loop { diff --git a/tests/ui/type-alias-impl-trait/issue-94429.rs b/tests/ui/type-alias-impl-trait/issue-94429.rs index 306e73003fa9..11beed06a20c 100644 --- a/tests/ui/type-alias-impl-trait/issue-94429.rs +++ b/tests/ui/type-alias-impl-trait/issue-94429.rs @@ -14,6 +14,7 @@ impl Runnable for Implementor { fn run(&mut self) -> Self::Coro { //~^ ERROR: type mismatch resolving + #[coroutine] move || { yield 1; } diff --git a/tests/ui/type-alias-impl-trait/issue-94429.stderr b/tests/ui/type-alias-impl-trait/issue-94429.stderr index 5d081e6b1eff..4c2020becbe3 100644 --- a/tests/ui/type-alias-impl-trait/issue-94429.stderr +++ b/tests/ui/type-alias-impl-trait/issue-94429.stderr @@ -1,4 +1,4 @@ -error[E0271]: type mismatch resolving `<{coroutine@$DIR/issue-94429.rs:17:9: 17:16} as Coroutine>::Yield == ()` +error[E0271]: type mismatch resolving `<{coroutine@$DIR/issue-94429.rs:18:9: 18:16} as Coroutine>::Yield == ()` --> $DIR/issue-94429.rs:15:26 | LL | fn run(&mut self) -> Self::Coro { diff --git a/tests/ui/weird-exprs.rs b/tests/ui/weird-exprs.rs index 0009ed0e34c8..08b5517aae22 100644 --- a/tests/ui/weird-exprs.rs +++ b/tests/ui/weird-exprs.rs @@ -152,6 +152,7 @@ fn r#match() { } fn i_yield() { + #[coroutine] static || { yield yield yield yield yield yield yield yield yield; }; From ca4a18fafca1dc19eb73b1dc28d050153aa8286e Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 11 Apr 2024 14:14:15 +0000 Subject: [PATCH 23/36] Add some FnDef LUB coercion tests --- tests/ui/fn/fn_def_coercion.rs | 58 ++++++++ tests/ui/fn/fn_def_coercion.stderr | 154 ++++++++++++++++++++++ tests/ui/fn/fn_def_opaque_coercion.rs | 67 ++++++++++ tests/ui/fn/fn_def_opaque_coercion.stderr | 42 ++++++ 4 files changed, 321 insertions(+) create mode 100644 tests/ui/fn/fn_def_coercion.rs create mode 100644 tests/ui/fn/fn_def_coercion.stderr create mode 100644 tests/ui/fn/fn_def_opaque_coercion.rs create mode 100644 tests/ui/fn/fn_def_opaque_coercion.stderr diff --git a/tests/ui/fn/fn_def_coercion.rs b/tests/ui/fn/fn_def_coercion.rs new file mode 100644 index 000000000000..313be6f28cdc --- /dev/null +++ b/tests/ui/fn/fn_def_coercion.rs @@ -0,0 +1,58 @@ +//! Test that coercing between function items of the same function, +//! but with different generic args succeeds in typeck, but then fails +//! in borrowck when the lifetimes can't actually be merged. + +fn foo(t: T) -> T { + t +} + +fn f<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { + let mut x = foo::<&'a ()>; //~ ERROR: lifetime may not live long enough + x = foo::<&'b ()>; //~ ERROR: lifetime may not live long enough + x = foo::<&'c ()>; + x(a); + x(b); + x(c); +} + +fn g<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { + let x = foo::<&'c ()>; + let _: &'c () = x(a); //~ ERROR lifetime may not live long enough +} + +fn h<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { + let x = foo::<&'a ()>; + let _: &'a () = x(c); +} + +fn i<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { + let mut x = foo::<&'c ()>; + x = foo::<&'b ()>; //~ ERROR lifetime may not live long enough + x = foo::<&'a ()>; //~ ERROR lifetime may not live long enough + x(a); + x(b); + x(c); +} + +fn j<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { + let x = match true { + true => foo::<&'b ()>, //~ ERROR lifetime may not live long enough + false => foo::<&'a ()>, //~ ERROR lifetime may not live long enough + }; + x(a); + x(b); + x(c); +} + +fn k<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { + let x = match true { + true => foo::<&'c ()>, + false => foo::<&'a ()>, //~ ERROR lifetime may not live long enough + }; + + x(a); + x(b); //~ ERROR lifetime may not live long enough + x(c); +} + +fn main() {} diff --git a/tests/ui/fn/fn_def_coercion.stderr b/tests/ui/fn/fn_def_coercion.stderr new file mode 100644 index 000000000000..ec4a1bde7fd6 --- /dev/null +++ b/tests/ui/fn/fn_def_coercion.stderr @@ -0,0 +1,154 @@ +error: lifetime may not live long enough + --> $DIR/fn_def_coercion.rs:10:17 + | +LL | fn f<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | let mut x = foo::<&'a ()>; + | ^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'b` + | + = help: consider adding the following bound: `'a: 'b` + = note: requirement occurs because of a function pointer to `foo` + = note: the function `foo` is invariant over the parameter `T` + = help: see for more information about variance + +error: lifetime may not live long enough + --> $DIR/fn_def_coercion.rs:11:5 + | +LL | fn f<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | let mut x = foo::<&'a ()>; +LL | x = foo::<&'b ()>; + | ^^^^^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + = note: requirement occurs because of a function pointer to `foo` + = note: the function `foo` is invariant over the parameter `T` + = help: see for more information about variance + +help: `'a` and `'b` must be the same: replace one with the other + +error: lifetime may not live long enough + --> $DIR/fn_def_coercion.rs:20:12 + | +LL | fn g<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { + | -- -- lifetime `'c` defined here + | | + | lifetime `'a` defined here +LL | let x = foo::<&'c ()>; +LL | let _: &'c () = x(a); + | ^^^^^^ type annotation requires that `'a` must outlive `'c` + | + = help: consider adding the following bound: `'a: 'c` + +error: lifetime may not live long enough + --> $DIR/fn_def_coercion.rs:30:5 + | +LL | fn i<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | let mut x = foo::<&'c ()>; +LL | x = foo::<&'b ()>; + | ^^^^^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + = note: requirement occurs because of a function pointer to `foo` + = note: the function `foo` is invariant over the parameter `T` + = help: see for more information about variance + +error: lifetime may not live long enough + --> $DIR/fn_def_coercion.rs:31:5 + | +LL | fn i<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | x = foo::<&'a ()>; + | ^^^^^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'b` + | + = help: consider adding the following bound: `'a: 'b` + = note: requirement occurs because of a function pointer to `foo` + = note: the function `foo` is invariant over the parameter `T` + = help: see for more information about variance + +help: `'a` and `'b` must be the same: replace one with the other + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: lifetime may not live long enough + --> $DIR/fn_def_coercion.rs:39:17 + | +LL | fn j<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | let x = match true { +LL | true => foo::<&'b ()>, + | ^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + = note: requirement occurs because of a function pointer to `foo` + = note: the function `foo` is invariant over the parameter `T` + = help: see for more information about variance + +error: lifetime may not live long enough + --> $DIR/fn_def_coercion.rs:40:18 + | +LL | fn j<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | false => foo::<&'a ()>, + | ^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'b` + | + = help: consider adding the following bound: `'a: 'b` + = note: requirement occurs because of a function pointer to `foo` + = note: the function `foo` is invariant over the parameter `T` + = help: see for more information about variance + +help: `'a` and `'b` must be the same: replace one with the other + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: lifetime may not live long enough + --> $DIR/fn_def_coercion.rs:50:18 + | +LL | fn k<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { + | -- -- lifetime `'c` defined here + | | + | lifetime `'a` defined here +... +LL | false => foo::<&'a ()>, + | ^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'c` + | + = help: consider adding the following bound: `'a: 'c` + = note: requirement occurs because of a function pointer to `foo` + = note: the function `foo` is invariant over the parameter `T` + = help: see for more information about variance + +error: lifetime may not live long enough + --> $DIR/fn_def_coercion.rs:54:5 + | +LL | fn k<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | x(b); + | ^^^^ argument requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +help: the following changes may resolve your lifetime errors + | + = help: add bound `'a: 'c` + = help: add bound `'b: 'a` + +error: aborting due to 9 previous errors + diff --git a/tests/ui/fn/fn_def_opaque_coercion.rs b/tests/ui/fn/fn_def_opaque_coercion.rs new file mode 100644 index 000000000000..af7f65c2e3b7 --- /dev/null +++ b/tests/ui/fn/fn_def_opaque_coercion.rs @@ -0,0 +1,67 @@ +//! Test that coercing between function items of the same function, +//! but with different args works. + +#![feature(type_alias_impl_trait)] + +fn foo(t: T) -> T { + t +} + +type F = impl Sized; + +fn f(a: F) { + let mut x = foo::; + x = foo::<()>; + x(a); + x(()); +} + +type G = impl Sized; + +fn g(a: G) { + let x = foo::<()>; + let _: () = x(a); +} + +type H = impl Sized; + +fn h(a: H) { + let x = foo::; + let _: H = x(()); +} + +type I = impl Sized; + +fn i(a: I) { + let mut x = foo::<()>; + x = foo::; + x(a); + x(()); +} + +type J = impl Sized; + +fn j(a: J) { + let x = match true { + true => foo::, + false => foo::<()>, //~ ERROR: incompatible types + }; + x(a); + x(()); +} + +fn k() -> impl Sized { + fn bind T>(_: T, f: F) -> F { + f + } + let x = match true { + true => { + let f = foo; + bind(k(), f) + } + false => foo::<()>, //~ ERROR: incompatible types + }; + todo!() +} + +fn main() {} diff --git a/tests/ui/fn/fn_def_opaque_coercion.stderr b/tests/ui/fn/fn_def_opaque_coercion.stderr new file mode 100644 index 000000000000..521b0277eac4 --- /dev/null +++ b/tests/ui/fn/fn_def_opaque_coercion.stderr @@ -0,0 +1,42 @@ +error[E0308]: `match` arms have incompatible types + --> $DIR/fn_def_opaque_coercion.rs:47:18 + | +LL | type J = impl Sized; + | ---------- the expected opaque type +... +LL | let x = match true { + | _____________- +LL | | true => foo::, + | | -------- this is found to be of type `fn(J) -> J {foo::}` +LL | | false => foo::<()>, + | | ^^^^^^^^^ expected opaque type, found `()` +LL | | }; + | |_____- `match` arms have incompatible types + | + = note: expected fn item `fn(J) -> J {foo::}` + found fn item `fn(()) {foo::<()>}` + +error[E0308]: `match` arms have incompatible types + --> $DIR/fn_def_opaque_coercion.rs:62:18 + | +LL | fn k() -> impl Sized { + | ---------- the expected opaque type +... +LL | let x = match true { + | _____________- +LL | | true => { +LL | | let f = foo; +LL | | bind(k(), f) + | | ------------ this is found to be of type `fn(impl Sized) -> impl Sized {foo::}` +LL | | } +LL | | false => foo::<()>, + | | ^^^^^^^^^ expected opaque type, found `()` +LL | | }; + | |_____- `match` arms have incompatible types + | + = note: expected fn item `fn(impl Sized) -> impl Sized {foo::}` + found fn item `fn(()) {foo::<()>}` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. From 5c55d6a128638c56f1a8cac4bff5b5d206469e63 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 11 Apr 2024 14:25:26 +0000 Subject: [PATCH 24/36] Register hidden types when equating function definitions in coercion --- compiler/rustc_hir_typeck/src/coercion.rs | 2 +- tests/ui/fn/fn_def_opaque_coercion.rs | 8 +++-- tests/ui/fn/fn_def_opaque_coercion.stderr | 42 ----------------------- 3 files changed, 6 insertions(+), 46 deletions(-) delete mode 100644 tests/ui/fn/fn_def_opaque_coercion.stderr diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 9ebb5f95f05f..4165fa7f07d1 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -1139,7 +1139,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // are the same function and their parameters have a LUB. match self.commit_if_ok(|_| { self.at(cause, self.param_env).lub( - DefineOpaqueTypes::No, + DefineOpaqueTypes::Yes, prev_ty, new_ty, ) diff --git a/tests/ui/fn/fn_def_opaque_coercion.rs b/tests/ui/fn/fn_def_opaque_coercion.rs index af7f65c2e3b7..0a8810cf4f8a 100644 --- a/tests/ui/fn/fn_def_opaque_coercion.rs +++ b/tests/ui/fn/fn_def_opaque_coercion.rs @@ -1,5 +1,7 @@ //! Test that coercing between function items of the same function, -//! but with different args works. +//! but with different generic args works. + +//@check-pass #![feature(type_alias_impl_trait)] @@ -44,7 +46,7 @@ type J = impl Sized; fn j(a: J) { let x = match true { true => foo::, - false => foo::<()>, //~ ERROR: incompatible types + false => foo::<()>, }; x(a); x(()); @@ -59,7 +61,7 @@ fn k() -> impl Sized { let f = foo; bind(k(), f) } - false => foo::<()>, //~ ERROR: incompatible types + false => foo::<()>, }; todo!() } diff --git a/tests/ui/fn/fn_def_opaque_coercion.stderr b/tests/ui/fn/fn_def_opaque_coercion.stderr deleted file mode 100644 index 521b0277eac4..000000000000 --- a/tests/ui/fn/fn_def_opaque_coercion.stderr +++ /dev/null @@ -1,42 +0,0 @@ -error[E0308]: `match` arms have incompatible types - --> $DIR/fn_def_opaque_coercion.rs:47:18 - | -LL | type J = impl Sized; - | ---------- the expected opaque type -... -LL | let x = match true { - | _____________- -LL | | true => foo::, - | | -------- this is found to be of type `fn(J) -> J {foo::}` -LL | | false => foo::<()>, - | | ^^^^^^^^^ expected opaque type, found `()` -LL | | }; - | |_____- `match` arms have incompatible types - | - = note: expected fn item `fn(J) -> J {foo::}` - found fn item `fn(()) {foo::<()>}` - -error[E0308]: `match` arms have incompatible types - --> $DIR/fn_def_opaque_coercion.rs:62:18 - | -LL | fn k() -> impl Sized { - | ---------- the expected opaque type -... -LL | let x = match true { - | _____________- -LL | | true => { -LL | | let f = foo; -LL | | bind(k(), f) - | | ------------ this is found to be of type `fn(impl Sized) -> impl Sized {foo::}` -LL | | } -LL | | false => foo::<()>, - | | ^^^^^^^^^ expected opaque type, found `()` -LL | | }; - | |_____- `match` arms have incompatible types - | - = note: expected fn item `fn(impl Sized) -> impl Sized {foo::}` - found fn item `fn(()) {foo::<()>}` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0308`. From 94c1920497d8281c1cd7b3d39b198bac80a03bc2 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Fri, 19 Apr 2024 16:17:02 +0100 Subject: [PATCH 25/36] Stabilise `inline_const` --- compiler/rustc_ast_passes/src/feature_gate.rs | 1 - compiler/rustc_feature/src/accepted.rs | 2 ++ compiler/rustc_feature/src/unstable.rs | 2 -- compiler/rustc_middle/src/lib.rs | 2 +- compiler/rustc_mir_transform/src/lib.rs | 2 +- compiler/rustc_parse/src/parser/mod.rs | 2 -- compiler/rustc_serialize/src/lib.rs | 2 +- library/alloc/src/lib.rs | 2 +- library/core/src/lib.rs | 2 +- library/core/src/sync/atomic.rs | 6 ++-- library/core/tests/lib.rs | 2 +- .../portable-simd/crates/core_simd/src/lib.rs | 1 - .../src/language-features/inline-const-pat.md | 2 -- .../src/language-features/inline-const.md | 32 ------------------- .../feature-gate-inline_const.rs | 6 ---- .../feature-gate-inline_const.stderr | 13 -------- 16 files changed, 11 insertions(+), 68 deletions(-) delete mode 100644 src/doc/unstable-book/src/language-features/inline-const.md delete mode 100644 tests/ui/feature-gates/feature-gate-inline_const.rs delete mode 100644 tests/ui/feature-gates/feature-gate-inline_const.stderr diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 70a3ccb0f440..d86196cbaa9a 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -556,7 +556,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { half_open_range_patterns_in_slices, "half-open range patterns in slices are unstable" ); - gate_all!(inline_const, "inline-const is experimental"); gate_all!(inline_const_pat, "inline-const in pattern position is experimental"); gate_all!(associated_const_equality, "associated const equality is incomplete"); gate_all!(yeet_expr, "`do yeet` expression is experimental"); diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 1eee11604cef..c0e664f6eeda 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -211,6 +211,8 @@ declare_features! ( (accepted, inclusive_range_syntax, "1.26.0", Some(28237)), /// Allows inferring outlives requirements (RFC 2093). (accepted, infer_outlives_requirements, "1.30.0", Some(44493)), + /// Allow anonymous constants from an inline `const` block + (accepted, inline_const, "CURRENT_RUSTC_VERSION", Some(76001)), /// Allows irrefutable patterns in `if let` and `while let` statements (RFC 2086). (accepted, irrefutable_let_patterns, "1.33.0", Some(44495)), /// Allows `#[instruction_set(_)]` attribute. diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 9641d336c3f3..2647f09c8c96 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -501,8 +501,6 @@ declare_features! ( (unstable, impl_trait_in_fn_trait_return, "1.64.0", Some(99697)), /// Allows associated types in inherent impls. (incomplete, inherent_associated_types, "1.52.0", Some(8995)), - /// Allow anonymous constants from an inline `const` block - (unstable, inline_const, "1.49.0", Some(76001)), /// Allow anonymous constants from an inline `const` block in pattern position (unstable, inline_const_pat, "1.58.0", Some(76001)), /// Allows using `pointer` and `reference` in intra-doc links diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 80762e3e5c1b..501052b7411b 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -37,7 +37,7 @@ #![feature(coroutines)] #![feature(stmt_expr_attributes)] #![feature(if_let_guard)] -#![feature(inline_const)] +#![cfg_attr(bootstrap, feature(inline_const))] #![feature(iter_from_coroutine)] #![feature(negative_impls)] #![feature(never_type)] diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index b308a80f7bad..e42755ca7bf2 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -4,7 +4,7 @@ #![feature(cow_is_borrowed)] #![feature(decl_macro)] #![feature(impl_trait_in_assoc_type)] -#![feature(inline_const)] +#![cfg_attr(bootstrap, feature(inline_const))] #![feature(is_sorted)] #![feature(let_chains)] #![feature(map_try_insert)] diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 742f4bd3c834..7486da33b217 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1252,8 +1252,6 @@ impl<'a> Parser<'a> { fn parse_const_block(&mut self, span: Span, pat: bool) -> PResult<'a, P> { if pat { self.psess.gated_spans.gate(sym::inline_const_pat, span); - } else { - self.psess.gated_spans.gate(sym::inline_const, span); } self.eat_keyword(kw::Const); let (attrs, blk) = self.parse_inner_attrs_and_block()?; diff --git a/compiler/rustc_serialize/src/lib.rs b/compiler/rustc_serialize/src/lib.rs index 3e1d8f3828bb..19f4e6994acf 100644 --- a/compiler/rustc_serialize/src/lib.rs +++ b/compiler/rustc_serialize/src/lib.rs @@ -11,7 +11,7 @@ #![cfg_attr(bootstrap, feature(associated_type_bounds))] #![feature(const_option)] #![feature(core_intrinsics)] -#![feature(inline_const)] +#![cfg_attr(bootstrap, feature(inline_const))] #![feature(min_specialization)] #![feature(never_type)] #![feature(ptr_sub_ptr)] diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 88faf5a9c7d6..b417513aaa23 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -128,7 +128,6 @@ #![feature(fn_traits)] #![feature(hasher_prefixfree_extras)] #![feature(hint_assert_unchecked)] -#![feature(inline_const)] #![feature(inplace_iteration)] #![feature(iter_advance_by)] #![feature(iter_next_chunk)] @@ -169,6 +168,7 @@ // Language features: // tidy-alphabetical-start #![cfg_attr(bootstrap, feature(associated_type_bounds))] +#![cfg_attr(bootstrap, feature(inline_const))] #![cfg_attr(not(bootstrap), rustc_preserve_ub_checks)] #![cfg_attr(not(test), feature(coroutine_trait))] #![cfg_attr(test, feature(panic_update_hook))] diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 154565b6fee1..6925a7d1da1f 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -201,6 +201,7 @@ // // Language features: // tidy-alphabetical-start +#![cfg_attr(bootstrap, feature(inline_const))] #![feature(abi_unadjusted)] #![feature(adt_const_params)] #![feature(allow_internal_unsafe)] @@ -231,7 +232,6 @@ #![feature(fundamental)] #![feature(generic_arg_infer)] #![feature(if_let_guard)] -#![feature(inline_const)] #![feature(intra_doc_pointers)] #![feature(intrinsics)] #![feature(lang_items)] diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index c8fd997a5da6..7b5dfa00e46d 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -511,7 +511,7 @@ impl AtomicBool { /// # Examples /// /// ``` - /// #![feature(atomic_from_mut, inline_const)] + /// #![feature(atomic_from_mut)] /// use std::sync::atomic::{AtomicBool, Ordering}; /// /// let mut some_bools = [const { AtomicBool::new(false) }; 10]; @@ -1313,7 +1313,7 @@ impl AtomicPtr { /// # Examples /// /// ``` - /// #![feature(atomic_from_mut, inline_const)] + /// #![feature(atomic_from_mut)] /// use std::ptr::null_mut; /// use std::sync::atomic::{AtomicPtr, Ordering}; /// @@ -2303,7 +2303,7 @@ macro_rules! atomic_int { /// # Examples /// /// ``` - /// #![feature(atomic_from_mut, inline_const)] + /// #![feature(atomic_from_mut)] #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] /// #[doc = concat!("let mut some_ints = [const { ", stringify!($atomic_type), "::new(0) }; 10];")] diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 7bd962fa2609..d6e705a37a71 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -46,7 +46,7 @@ #![feature(hasher_prefixfree_extras)] #![feature(hashmap_internals)] #![feature(try_find)] -#![feature(inline_const)] +#![cfg_attr(bootstrap, feature(inline_const))] #![feature(is_sorted)] #![feature(layout_for_ptr)] #![feature(pattern)] diff --git a/library/portable-simd/crates/core_simd/src/lib.rs b/library/portable-simd/crates/core_simd/src/lib.rs index 48514e52587f..331b66262490 100644 --- a/library/portable-simd/crates/core_simd/src/lib.rs +++ b/library/portable-simd/crates/core_simd/src/lib.rs @@ -7,7 +7,6 @@ convert_float_to_int, core_intrinsics, decl_macro, - inline_const, intra_doc_pointers, repr_simd, simd_ffi, diff --git a/src/doc/unstable-book/src/language-features/inline-const-pat.md b/src/doc/unstable-book/src/language-features/inline-const-pat.md index 5f0f7547a0a8..c6f54d79cfce 100644 --- a/src/doc/unstable-book/src/language-features/inline-const-pat.md +++ b/src/doc/unstable-book/src/language-features/inline-const-pat.md @@ -2,8 +2,6 @@ The tracking issue for this feature is: [#76001] -See also [`inline_const`](inline-const.md) - ------ This feature allows you to use inline constant expressions in pattern position: diff --git a/src/doc/unstable-book/src/language-features/inline-const.md b/src/doc/unstable-book/src/language-features/inline-const.md deleted file mode 100644 index 7be70eed6ced..000000000000 --- a/src/doc/unstable-book/src/language-features/inline-const.md +++ /dev/null @@ -1,32 +0,0 @@ -# `inline_const` - -The tracking issue for this feature is: [#76001] - -See also [`inline_const_pat`](inline-const-pat.md) - ------- - -This feature allows you to use inline constant expressions. For example, you can -turn this code: - -```rust -# fn add_one(x: i32) -> i32 { x + 1 } -const MY_COMPUTATION: i32 = 1 + 2 * 3 / 4; - -fn main() { - let x = add_one(MY_COMPUTATION); -} -``` - -into this code: - -```rust -#![feature(inline_const)] - -# fn add_one(x: i32) -> i32 { x + 1 } -fn main() { - let x = add_one(const { 1 + 2 * 3 / 4 }); -} -``` - -[#76001]: https://github.com/rust-lang/rust/issues/76001 diff --git a/tests/ui/feature-gates/feature-gate-inline_const.rs b/tests/ui/feature-gates/feature-gate-inline_const.rs deleted file mode 100644 index 43ff90d234cb..000000000000 --- a/tests/ui/feature-gates/feature-gate-inline_const.rs +++ /dev/null @@ -1,6 +0,0 @@ -fn main() { - let _ = const { - //~^ ERROR inline-const is experimental [E0658] - true - }; -} diff --git a/tests/ui/feature-gates/feature-gate-inline_const.stderr b/tests/ui/feature-gates/feature-gate-inline_const.stderr deleted file mode 100644 index 6cf675065f34..000000000000 --- a/tests/ui/feature-gates/feature-gate-inline_const.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0658]: inline-const is experimental - --> $DIR/feature-gate-inline_const.rs:2:13 - | -LL | let _ = const { - | ^^^^^ - | - = note: see issue #76001 for more information - = help: add `#![feature(inline_const)]` 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: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0658`. From cfee72aa24725ab8310c9d8c7085368489de567e Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Fri, 19 Apr 2024 16:54:41 +0100 Subject: [PATCH 26/36] Fix tests and bless --- tests/codegen/const_scalar_pair.rs | 2 - tests/codegen/intrinsics/transmute.rs | 1 - tests/codegen/issues/issue-96274.rs | 1 - ...-type-metadata-id-itanium-cxx-abi-paths.rs | 2 +- .../simd-intrinsic-transmute-array.rs | 1 - tests/mir-opt/building/custom/arrays.rs | 2 +- tests/mir-opt/building/custom/consts.rs | 2 +- tests/mir-opt/building/custom/operators.rs | 2 +- tests/mir-opt/const_prop/invalid_constant.rs | 1 - tests/pretty/stmt_expr_attributes.rs | 1 - .../const-block-is-poly.rs | 2 +- .../const-block-is-poly.stderr | 6 +- .../const_kind_expr/relate_ty_with_infer_2.rs | 2 +- .../inline-const-in-const-generic-defaults.rs | 1 - .../dont-propagate-generic-instance-2.rs | 2 - .../closure-structural-match-issue-90013.rs | 1 - tests/ui/consts/const-block-const-bound.rs | 2 +- .../consts/const-blocks/fn-call-in-const.rs | 1 - .../heap/alloc_intrinsic_zero_sized.rs | 1 - .../heap/dealloc_intrinsic_zero_sized.rs | 1 - tests/ui/consts/issue-102117.rs | 2 +- .../ui/impl-trait/normalize-tait-in-const.rs | 1 - .../impl-trait/normalize-tait-in-const.stderr | 6 +- .../ui/inline-const/const-expr-array-init.rs | 2 - tests/ui/inline-const/const-expr-basic.rs | 2 - .../ui/inline-const/const-expr-generic-err.rs | 1 - .../const-expr-generic-err.stderr | 16 ++-- .../inline-const/const-expr-generic-err2.rs | 2 - .../const-expr-generic-err2.stderr | 2 +- tests/ui/inline-const/const-expr-generic.rs | 1 - tests/ui/inline-const/const-expr-inference.rs | 2 - .../inline-const/const-expr-lifetime-err.rs | 1 - .../const-expr-lifetime-err.stderr | 2 +- tests/ui/inline-const/const-expr-lifetime.rs | 1 - tests/ui/inline-const/const-expr-macro.rs | 2 - tests/ui/inline-const/const-expr-reference.rs | 2 - .../inline-const/const-match-pat-lifetime.rs | 1 - .../elided-lifetime-being-infer-vars.rs | 2 - tests/ui/inline-const/expr-unsafe-err.rs | 1 - tests/ui/inline-const/expr-unsafe-err.stderr | 2 +- tests/ui/inline-const/expr-unsafe.rs | 2 +- tests/ui/inline-const/expr-with-block-err.rs | 2 - .../inline-const/expr-with-block-err.stderr | 2 +- tests/ui/inline-const/expr-with-block.rs | 2 +- .../instance-doesnt-depend-on-type.rs | 2 - tests/ui/inline-const/interpolated.rs | 2 - tests/ui/inline-const/promotion.rs | 1 - tests/ui/inline-const/promotion.stderr | 2 +- tests/ui/inline-const/required-const.rs | 1 - tests/ui/inline-const/required-const.stderr | 6 +- .../ui/lifetimes/unusual-rib-combinations.rs | 2 - .../lifetimes/unusual-rib-combinations.stderr | 16 ++-- tests/ui/lint/invalid_from_utf8.rs | 1 - tests/ui/lint/invalid_from_utf8.stderr | 42 +++++----- tests/ui/lint/non-local-defs/consts.rs | 2 - tests/ui/lint/non-local-defs/consts.stderr | 16 ++-- .../non-local-defs/from-local-for-global.rs | 2 - .../from-local-for-global.stderr | 10 +-- .../ui/loops/dont-suggest-break-thru-item.rs | 2 - .../loops/dont-suggest-break-thru-item.stderr | 8 +- tests/ui/parser/bad-let-else-statement.rs | 1 - tests/ui/parser/bad-let-else-statement.stderr | 76 +++++++++---------- tests/ui/simd/const-err-trumps-simd-err.rs | 2 +- .../simd/intrinsic/generic-elements-pass.rs | 1 - 64 files changed, 117 insertions(+), 171 deletions(-) diff --git a/tests/codegen/const_scalar_pair.rs b/tests/codegen/const_scalar_pair.rs index 0aa430a8efa0..f142896c31f1 100644 --- a/tests/codegen/const_scalar_pair.rs +++ b/tests/codegen/const_scalar_pair.rs @@ -1,7 +1,5 @@ //@ compile-flags: --crate-type=lib -Copt-level=0 -Zmir-opt-level=0 -C debuginfo=2 -#![feature(inline_const)] - // Test that we don't generate a memory allocation for the constant // and read the fields from that, but instead just create the value pair directly. pub fn foo() -> (i32, i32) { diff --git a/tests/codegen/intrinsics/transmute.rs b/tests/codegen/intrinsics/transmute.rs index 76cdf7e191e4..04a91bb87f7c 100644 --- a/tests/codegen/intrinsics/transmute.rs +++ b/tests/codegen/intrinsics/transmute.rs @@ -4,7 +4,6 @@ #![crate_type = "lib"] #![feature(core_intrinsics)] #![feature(custom_mir)] -#![feature(inline_const)] #![allow(unreachable_code)] use std::intrinsics::{transmute, transmute_unchecked}; diff --git a/tests/codegen/issues/issue-96274.rs b/tests/codegen/issues/issue-96274.rs index d278796dd02a..ffefd5f43f8c 100644 --- a/tests/codegen/issues/issue-96274.rs +++ b/tests/codegen/issues/issue-96274.rs @@ -1,7 +1,6 @@ //@ compile-flags: -O #![crate_type = "lib"] -#![feature(inline_const)] use std::mem::MaybeUninit; diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-paths.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-paths.rs index ca781a99296b..6c3d991af9f1 100644 --- a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-paths.rs +++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-paths.rs @@ -5,7 +5,7 @@ //@ compile-flags: -Clto -Cno-prepopulate-passes -Copt-level=0 -Zsanitizer=cfi -Ctarget-feature=-crt-static #![crate_type="lib"] -#![feature(inline_const, type_alias_impl_trait)] +#![feature(type_alias_impl_trait)] extern crate core; diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs index 488be2a8629d..c416f4d28bb5 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs @@ -4,7 +4,6 @@ #![crate_type = "lib"] #![allow(non_camel_case_types)] #![feature(repr_simd, intrinsics)] -#![feature(inline_const)] #[repr(simd)] #[derive(Copy, Clone)] diff --git a/tests/mir-opt/building/custom/arrays.rs b/tests/mir-opt/building/custom/arrays.rs index fe6abc546879..e9a53b7aacb7 100644 --- a/tests/mir-opt/building/custom/arrays.rs +++ b/tests/mir-opt/building/custom/arrays.rs @@ -1,5 +1,5 @@ // skip-filecheck -#![feature(custom_mir, core_intrinsics, inline_const)] +#![feature(custom_mir, core_intrinsics)] extern crate core; use core::intrinsics::mir::*; diff --git a/tests/mir-opt/building/custom/consts.rs b/tests/mir-opt/building/custom/consts.rs index 42abf5019e55..1a410177fa54 100644 --- a/tests/mir-opt/building/custom/consts.rs +++ b/tests/mir-opt/building/custom/consts.rs @@ -1,5 +1,5 @@ // skip-filecheck -#![feature(custom_mir, core_intrinsics, inline_const)] +#![feature(custom_mir, core_intrinsics)] extern crate core; use core::intrinsics::mir::*; diff --git a/tests/mir-opt/building/custom/operators.rs b/tests/mir-opt/building/custom/operators.rs index bc72ed8dfe39..eb97bcc73b7e 100644 --- a/tests/mir-opt/building/custom/operators.rs +++ b/tests/mir-opt/building/custom/operators.rs @@ -1,6 +1,6 @@ // skip-filecheck //@ compile-flags: --crate-type=lib -#![feature(custom_mir, core_intrinsics, inline_const)] +#![feature(custom_mir, core_intrinsics)] use std::intrinsics::mir::*; // EMIT_MIR operators.f.built.after.mir diff --git a/tests/mir-opt/const_prop/invalid_constant.rs b/tests/mir-opt/const_prop/invalid_constant.rs index afd8746af5fb..2b7271f63ff2 100644 --- a/tests/mir-opt/const_prop/invalid_constant.rs +++ b/tests/mir-opt/const_prop/invalid_constant.rs @@ -4,7 +4,6 @@ // Verify that we can pretty print invalid constants. #![feature(adt_const_params)] -#![feature(inline_const)] #![allow(incomplete_features)] #[derive(Copy, Clone)] diff --git a/tests/pretty/stmt_expr_attributes.rs b/tests/pretty/stmt_expr_attributes.rs index 5076adf5aa47..5eb7d2fcae36 100644 --- a/tests/pretty/stmt_expr_attributes.rs +++ b/tests/pretty/stmt_expr_attributes.rs @@ -1,6 +1,5 @@ //@ pp-exact -#![feature(inline_const)] #![feature(inline_const_pat)] #![feature(rustc_attrs)] #![feature(stmt_expr_attributes)] diff --git a/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.rs b/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.rs index 7332a8f03c05..f1305202ad45 100644 --- a/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.rs +++ b/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.rs @@ -1,4 +1,4 @@ -#![feature(inline_const, generic_const_exprs)] +#![feature(generic_const_exprs)] //~^ WARN the feature `generic_const_exprs` is incomplete fn foo() { diff --git a/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.stderr b/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.stderr index a85e0cbcf7e9..03b0004bf0bd 100644 --- a/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.stderr +++ b/tests/ui/const-generics/generic_const_exprs/const-block-is-poly.stderr @@ -1,8 +1,8 @@ warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/const-block-is-poly.rs:1:26 + --> $DIR/const-block-is-poly.rs:1:12 | -LL | #![feature(inline_const, generic_const_exprs)] - | ^^^^^^^^^^^^^^^^^^^ +LL | #![feature(generic_const_exprs)] + | ^^^^^^^^^^^^^^^^^^^ | = note: see issue #76560 for more information = note: `#[warn(incomplete_features)]` on by default diff --git a/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_ty_with_infer_2.rs b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_ty_with_infer_2.rs index 4333ec9f5522..f9cf8210d651 100644 --- a/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_ty_with_infer_2.rs +++ b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_ty_with_infer_2.rs @@ -1,5 +1,5 @@ //@ check-pass -#![feature(inline_const, generic_const_exprs)] +#![feature(generic_const_exprs)] #![allow(incomplete_features)] use std::marker::PhantomData; diff --git a/tests/ui/const-generics/generic_const_exprs/inline-const-in-const-generic-defaults.rs b/tests/ui/const-generics/generic_const_exprs/inline-const-in-const-generic-defaults.rs index 3bc02f4c6bbf..073e0fe0a7fd 100644 --- a/tests/ui/const-generics/generic_const_exprs/inline-const-in-const-generic-defaults.rs +++ b/tests/ui/const-generics/generic_const_exprs/inline-const-in-const-generic-defaults.rs @@ -1,7 +1,6 @@ //@ check-pass #![feature(generic_const_exprs)] -#![feature(inline_const)] #![allow(incomplete_features)] pub struct ConstDefaultUnstable; diff --git a/tests/ui/const_prop/dont-propagate-generic-instance-2.rs b/tests/ui/const_prop/dont-propagate-generic-instance-2.rs index 768c9b3171a8..08064bc65899 100644 --- a/tests/ui/const_prop/dont-propagate-generic-instance-2.rs +++ b/tests/ui/const_prop/dont-propagate-generic-instance-2.rs @@ -1,7 +1,5 @@ //@ run-pass -#![feature(inline_const)] - // Makes sure we don't propagate generic instances of `Self: ?Sized` blanket impls. // This is relevant when we have an overlapping impl and builtin dyn instance. // See for more context. diff --git a/tests/ui/consts/closure-structural-match-issue-90013.rs b/tests/ui/consts/closure-structural-match-issue-90013.rs index 7a5d9b69ee4a..454341a77843 100644 --- a/tests/ui/consts/closure-structural-match-issue-90013.rs +++ b/tests/ui/consts/closure-structural-match-issue-90013.rs @@ -1,6 +1,5 @@ // Regression test for issue 90013. //@ check-pass -#![feature(inline_const)] fn main() { const { || {} }; diff --git a/tests/ui/consts/const-block-const-bound.rs b/tests/ui/consts/const-block-const-bound.rs index b0d5e19ad554..933eb6cfc0af 100644 --- a/tests/ui/consts/const-block-const-bound.rs +++ b/tests/ui/consts/const-block-const-bound.rs @@ -1,7 +1,7 @@ //@ known-bug: #103507 #![allow(unused)] -#![feature(const_trait_impl, inline_const, negative_impls)] +#![feature(const_trait_impl, negative_impls)] use std::marker::Destruct; diff --git a/tests/ui/consts/const-blocks/fn-call-in-const.rs b/tests/ui/consts/const-blocks/fn-call-in-const.rs index 9bf267b7de9a..a3e24ddae7d1 100644 --- a/tests/ui/consts/const-blocks/fn-call-in-const.rs +++ b/tests/ui/consts/const-blocks/fn-call-in-const.rs @@ -1,6 +1,5 @@ //@ run-pass -#![feature(inline_const)] #![allow(unused)] // Some type that is not copyable. diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_zero_sized.rs b/tests/ui/consts/const-eval/heap/alloc_intrinsic_zero_sized.rs index 6c4fca356260..2517560c2c34 100644 --- a/tests/ui/consts/const-eval/heap/alloc_intrinsic_zero_sized.rs +++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_zero_sized.rs @@ -1,7 +1,6 @@ //@ run-pass #![feature(core_intrinsics)] #![feature(const_heap)] -#![feature(inline_const)] use std::intrinsics; diff --git a/tests/ui/consts/const-eval/heap/dealloc_intrinsic_zero_sized.rs b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_zero_sized.rs index 146a87862e8c..c53bb36f4a2c 100644 --- a/tests/ui/consts/const-eval/heap/dealloc_intrinsic_zero_sized.rs +++ b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_zero_sized.rs @@ -1,7 +1,6 @@ //@ run-pass #![feature(core_intrinsics)] #![feature(const_heap)] -#![feature(inline_const)] use std::intrinsics; diff --git a/tests/ui/consts/issue-102117.rs b/tests/ui/consts/issue-102117.rs index 3ed90aed2350..6cb9832bcd81 100644 --- a/tests/ui/consts/issue-102117.rs +++ b/tests/ui/consts/issue-102117.rs @@ -1,4 +1,4 @@ -#![feature(inline_const, const_type_id)] +#![feature(const_type_id)] use std::alloc::Layout; use std::any::TypeId; diff --git a/tests/ui/impl-trait/normalize-tait-in-const.rs b/tests/ui/impl-trait/normalize-tait-in-const.rs index ccd073b80709..422c2e439cf0 100644 --- a/tests/ui/impl-trait/normalize-tait-in-const.rs +++ b/tests/ui/impl-trait/normalize-tait-in-const.rs @@ -3,7 +3,6 @@ #![feature(type_alias_impl_trait)] #![feature(const_trait_impl)] #![feature(const_refs_to_cell)] -#![feature(inline_const)] use std::marker::Destruct; diff --git a/tests/ui/impl-trait/normalize-tait-in-const.stderr b/tests/ui/impl-trait/normalize-tait-in-const.stderr index 7ae8306d74d5..fbd41b61730e 100644 --- a/tests/ui/impl-trait/normalize-tait-in-const.stderr +++ b/tests/ui/impl-trait/normalize-tait-in-const.stderr @@ -1,11 +1,11 @@ error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/normalize-tait-in-const.rs:25:42 + --> $DIR/normalize-tait-in-const.rs:24:42 | LL | const fn with_positive Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) { | ^^^^^^^^^^^^^^^^^ error[E0015]: cannot call non-const closure in constant functions - --> $DIR/normalize-tait-in-const.rs:26:5 + --> $DIR/normalize-tait-in-const.rs:25:5 | LL | fun(filter_positive()); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -21,7 +21,7 @@ LL + #![feature(effects)] | error[E0493]: destructor of `F` cannot be evaluated at compile-time - --> $DIR/normalize-tait-in-const.rs:25:79 + --> $DIR/normalize-tait-in-const.rs:24:79 | LL | const fn with_positive Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) { | ^^^ the destructor for this type cannot be evaluated in constant functions diff --git a/tests/ui/inline-const/const-expr-array-init.rs b/tests/ui/inline-const/const-expr-array-init.rs index 075c27c1cc92..eb126b61f2df 100644 --- a/tests/ui/inline-const/const-expr-array-init.rs +++ b/tests/ui/inline-const/const-expr-array-init.rs @@ -1,7 +1,5 @@ //@ build-pass -#![feature(inline_const)] - use std::cell::Cell; fn main() { diff --git a/tests/ui/inline-const/const-expr-basic.rs b/tests/ui/inline-const/const-expr-basic.rs index 6a19cc656d02..7f769d2b5c33 100644 --- a/tests/ui/inline-const/const-expr-basic.rs +++ b/tests/ui/inline-const/const-expr-basic.rs @@ -1,7 +1,5 @@ //@ run-pass -#![feature(inline_const)] - fn foo() -> i32 { const { let x = 5 + 10; diff --git a/tests/ui/inline-const/const-expr-generic-err.rs b/tests/ui/inline-const/const-expr-generic-err.rs index 3c4bbcb3dc9a..3249e826a96b 100644 --- a/tests/ui/inline-const/const-expr-generic-err.rs +++ b/tests/ui/inline-const/const-expr-generic-err.rs @@ -1,5 +1,4 @@ //@ build-fail -#![feature(inline_const)] fn foo() { const { assert!(std::mem::size_of::() == 0); } //~ ERROR E0080 diff --git a/tests/ui/inline-const/const-expr-generic-err.stderr b/tests/ui/inline-const/const-expr-generic-err.stderr index 7331c7f18e97..dcd6b62bbfc1 100644 --- a/tests/ui/inline-const/const-expr-generic-err.stderr +++ b/tests/ui/inline-const/const-expr-generic-err.stderr @@ -1,37 +1,37 @@ error[E0080]: evaluation of `foo::::{constant#0}` failed - --> $DIR/const-expr-generic-err.rs:5:13 + --> $DIR/const-expr-generic-err.rs:4:13 | LL | const { assert!(std::mem::size_of::() == 0); } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'assertion failed: std::mem::size_of::() == 0', $DIR/const-expr-generic-err.rs:5:13 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'assertion failed: std::mem::size_of::() == 0', $DIR/const-expr-generic-err.rs:4:13 | = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered - --> $DIR/const-expr-generic-err.rs:5:5 + --> $DIR/const-expr-generic-err.rs:4:5 | LL | const { assert!(std::mem::size_of::() == 0); } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: the above error was encountered while instantiating `fn foo::` - --> $DIR/const-expr-generic-err.rs:13:5 + --> $DIR/const-expr-generic-err.rs:12:5 | LL | foo::(); | ^^^^^^^^^^^^ error[E0080]: evaluation of `bar::<0>::{constant#0}` failed - --> $DIR/const-expr-generic-err.rs:9:13 + --> $DIR/const-expr-generic-err.rs:8:13 | LL | const { N - 1 } | ^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow note: erroneous constant encountered - --> $DIR/const-expr-generic-err.rs:9:5 + --> $DIR/const-expr-generic-err.rs:8:5 | LL | const { N - 1 } | ^^^^^^^^^^^^^^^ note: erroneous constant encountered - --> $DIR/const-expr-generic-err.rs:9:5 + --> $DIR/const-expr-generic-err.rs:8:5 | LL | const { N - 1 } | ^^^^^^^^^^^^^^^ @@ -39,7 +39,7 @@ LL | const { N - 1 } = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` note: the above error was encountered while instantiating `fn bar::<0>` - --> $DIR/const-expr-generic-err.rs:14:5 + --> $DIR/const-expr-generic-err.rs:13:5 | LL | bar::<0>(); | ^^^^^^^^^^ diff --git a/tests/ui/inline-const/const-expr-generic-err2.rs b/tests/ui/inline-const/const-expr-generic-err2.rs index e097cbe9dd6d..49cbdbfda5da 100644 --- a/tests/ui/inline-const/const-expr-generic-err2.rs +++ b/tests/ui/inline-const/const-expr-generic-err2.rs @@ -1,5 +1,3 @@ -#![feature(inline_const)] - fn foo() { let _ = [0u8; const { std::mem::size_of::() }]; //~^ ERROR: constant expression depends on a generic parameter diff --git a/tests/ui/inline-const/const-expr-generic-err2.stderr b/tests/ui/inline-const/const-expr-generic-err2.stderr index 5876a6c9e198..c6d77593c46f 100644 --- a/tests/ui/inline-const/const-expr-generic-err2.stderr +++ b/tests/ui/inline-const/const-expr-generic-err2.stderr @@ -1,5 +1,5 @@ error: constant expression depends on a generic parameter - --> $DIR/const-expr-generic-err2.rs:4:19 + --> $DIR/const-expr-generic-err2.rs:2:19 | LL | let _ = [0u8; const { std::mem::size_of::() }]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/inline-const/const-expr-generic.rs b/tests/ui/inline-const/const-expr-generic.rs index e634e1d4a47f..0c33b02d3a2e 100644 --- a/tests/ui/inline-const/const-expr-generic.rs +++ b/tests/ui/inline-const/const-expr-generic.rs @@ -1,5 +1,4 @@ //@ check-pass -#![feature(inline_const)] fn foo() -> usize { const { std::mem::size_of::() } diff --git a/tests/ui/inline-const/const-expr-inference.rs b/tests/ui/inline-const/const-expr-inference.rs index f3b97d3430ef..99cea3204a19 100644 --- a/tests/ui/inline-const/const-expr-inference.rs +++ b/tests/ui/inline-const/const-expr-inference.rs @@ -1,7 +1,5 @@ //@ check-pass -#![feature(inline_const)] - pub fn todo() -> T { const { todo!() } } diff --git a/tests/ui/inline-const/const-expr-lifetime-err.rs b/tests/ui/inline-const/const-expr-lifetime-err.rs index 0a032a7338ad..df1e5fcb4735 100644 --- a/tests/ui/inline-const/const-expr-lifetime-err.rs +++ b/tests/ui/inline-const/const-expr-lifetime-err.rs @@ -1,5 +1,4 @@ #![feature(const_mut_refs)] -#![feature(inline_const)] use std::marker::PhantomData; diff --git a/tests/ui/inline-const/const-expr-lifetime-err.stderr b/tests/ui/inline-const/const-expr-lifetime-err.stderr index 75877bc093a7..f97e2d25e6c2 100644 --- a/tests/ui/inline-const/const-expr-lifetime-err.stderr +++ b/tests/ui/inline-const/const-expr-lifetime-err.stderr @@ -1,5 +1,5 @@ error[E0597]: `y` does not live long enough - --> $DIR/const-expr-lifetime-err.rs:23:30 + --> $DIR/const-expr-lifetime-err.rs:22:30 | LL | fn foo<'a>() { | -- lifetime `'a` defined here diff --git a/tests/ui/inline-const/const-expr-lifetime.rs b/tests/ui/inline-const/const-expr-lifetime.rs index 5dac17645d7a..071e724a0faa 100644 --- a/tests/ui/inline-const/const-expr-lifetime.rs +++ b/tests/ui/inline-const/const-expr-lifetime.rs @@ -1,7 +1,6 @@ //@ run-pass #![feature(const_mut_refs)] -#![feature(inline_const)] use std::marker::PhantomData; diff --git a/tests/ui/inline-const/const-expr-macro.rs b/tests/ui/inline-const/const-expr-macro.rs index bf3cb3c3320f..cf07eb12f5a9 100644 --- a/tests/ui/inline-const/const-expr-macro.rs +++ b/tests/ui/inline-const/const-expr-macro.rs @@ -1,7 +1,5 @@ //@ run-pass -#![feature(inline_const)] - macro_rules! do_const_block{ ($val:block) => { const $val } } diff --git a/tests/ui/inline-const/const-expr-reference.rs b/tests/ui/inline-const/const-expr-reference.rs index b3753b0d371a..208271e37c31 100644 --- a/tests/ui/inline-const/const-expr-reference.rs +++ b/tests/ui/inline-const/const-expr-reference.rs @@ -1,7 +1,5 @@ //@ run-pass -#![feature(inline_const)] - const fn bar() -> i32 { const { 2 + 3 diff --git a/tests/ui/inline-const/const-match-pat-lifetime.rs b/tests/ui/inline-const/const-match-pat-lifetime.rs index f909e68e7be5..590c426c7737 100644 --- a/tests/ui/inline-const/const-match-pat-lifetime.rs +++ b/tests/ui/inline-const/const-match-pat-lifetime.rs @@ -1,7 +1,6 @@ //@ run-pass #![feature(const_mut_refs)] -#![feature(inline_const)] #![feature(inline_const_pat)] use std::marker::PhantomData; diff --git a/tests/ui/inline-const/elided-lifetime-being-infer-vars.rs b/tests/ui/inline-const/elided-lifetime-being-infer-vars.rs index a1c3c61484ae..e0a889ac3471 100644 --- a/tests/ui/inline-const/elided-lifetime-being-infer-vars.rs +++ b/tests/ui/inline-const/elided-lifetime-being-infer-vars.rs @@ -1,7 +1,5 @@ //@ check-pass -#![feature(inline_const)] - fn main() { let _my_usize = const { let a = 10_usize; diff --git a/tests/ui/inline-const/expr-unsafe-err.rs b/tests/ui/inline-const/expr-unsafe-err.rs index a05a29451683..d53d84b944f0 100644 --- a/tests/ui/inline-const/expr-unsafe-err.rs +++ b/tests/ui/inline-const/expr-unsafe-err.rs @@ -1,4 +1,3 @@ -#![feature(inline_const)] const unsafe fn require_unsafe() -> usize { 1 } diff --git a/tests/ui/inline-const/expr-unsafe-err.stderr b/tests/ui/inline-const/expr-unsafe-err.stderr index 45f850d1f99b..13a408b971c8 100644 --- a/tests/ui/inline-const/expr-unsafe-err.stderr +++ b/tests/ui/inline-const/expr-unsafe-err.stderr @@ -1,5 +1,5 @@ error[E0133]: call to unsafe function `require_unsafe` is unsafe and requires unsafe function or block - --> $DIR/expr-unsafe-err.rs:8:9 + --> $DIR/expr-unsafe-err.rs:7:9 | LL | require_unsafe(); | ^^^^^^^^^^^^^^^^ call to unsafe function diff --git a/tests/ui/inline-const/expr-unsafe.rs b/tests/ui/inline-const/expr-unsafe.rs index f9d1450503e2..cdd101f3e088 100644 --- a/tests/ui/inline-const/expr-unsafe.rs +++ b/tests/ui/inline-const/expr-unsafe.rs @@ -1,7 +1,7 @@ //@ check-pass #![warn(unused_unsafe)] -#![feature(inline_const)] + const unsafe fn require_unsafe() -> usize { 1 } fn main() { diff --git a/tests/ui/inline-const/expr-with-block-err.rs b/tests/ui/inline-const/expr-with-block-err.rs index f7547742ddcb..6f8507575588 100644 --- a/tests/ui/inline-const/expr-with-block-err.rs +++ b/tests/ui/inline-const/expr-with-block-err.rs @@ -1,5 +1,3 @@ -#![feature(inline_const)] - fn main() { const { 2 } - const { 1 }; //~^ ERROR mismatched types diff --git a/tests/ui/inline-const/expr-with-block-err.stderr b/tests/ui/inline-const/expr-with-block-err.stderr index a46d73950458..f127c11e9b7a 100644 --- a/tests/ui/inline-const/expr-with-block-err.stderr +++ b/tests/ui/inline-const/expr-with-block-err.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/expr-with-block-err.rs:4:13 + --> $DIR/expr-with-block-err.rs:2:13 | LL | const { 2 } - const { 1 }; | ^ expected `()`, found integer diff --git a/tests/ui/inline-const/expr-with-block.rs b/tests/ui/inline-const/expr-with-block.rs index 07a1c9a10f5c..a32afbcffadd 100644 --- a/tests/ui/inline-const/expr-with-block.rs +++ b/tests/ui/inline-const/expr-with-block.rs @@ -1,5 +1,5 @@ //@ check-pass -#![feature(inline_const)] + fn main() { match true { true => const {} diff --git a/tests/ui/inline-const/instance-doesnt-depend-on-type.rs b/tests/ui/inline-const/instance-doesnt-depend-on-type.rs index e69106a43af4..c53aab60b06f 100644 --- a/tests/ui/inline-const/instance-doesnt-depend-on-type.rs +++ b/tests/ui/inline-const/instance-doesnt-depend-on-type.rs @@ -1,8 +1,6 @@ //@ check-pass // issue: 114660 -#![feature(inline_const)] - fn main() { const { core::mem::transmute:: }; // Don't resolve the instance of this inline constant to be an intrinsic, diff --git a/tests/ui/inline-const/interpolated.rs b/tests/ui/inline-const/interpolated.rs index 582900e7aa01..38ed2a042e09 100644 --- a/tests/ui/inline-const/interpolated.rs +++ b/tests/ui/inline-const/interpolated.rs @@ -1,7 +1,5 @@ //@ check-pass -#![feature(inline_const)] - // This used to be unsupported since the parser first tries to check if we have // any nested items, and then checks for statements (and expressions). The heuristic // that we were using to detect the beginning of a const item was incorrect, so diff --git a/tests/ui/inline-const/promotion.rs b/tests/ui/inline-const/promotion.rs index 242959c6b516..2cfb8a0d19fc 100644 --- a/tests/ui/inline-const/promotion.rs +++ b/tests/ui/inline-const/promotion.rs @@ -1,4 +1,3 @@ -#![feature(inline_const)] #![allow(arithmetic_overflow, unconditional_panic)] // The only way to have promoteds that fail is in `const fn` called from `const`/`static`. diff --git a/tests/ui/inline-const/promotion.stderr b/tests/ui/inline-const/promotion.stderr index 7f06b97818bf..4e914c9e0872 100644 --- a/tests/ui/inline-const/promotion.stderr +++ b/tests/ui/inline-const/promotion.stderr @@ -1,5 +1,5 @@ error[E0716]: temporary value dropped while borrowed - --> $DIR/promotion.rs:17:37 + --> $DIR/promotion.rs:16:37 | LL | let _x: &'static i32 = &div_by_zero(); | ------------ ^^^^^^^^^^^^^ creates a temporary value which is freed while still in use diff --git a/tests/ui/inline-const/required-const.rs b/tests/ui/inline-const/required-const.rs index 3de0ab2a0c06..8f640e933d01 100644 --- a/tests/ui/inline-const/required-const.rs +++ b/tests/ui/inline-const/required-const.rs @@ -1,6 +1,5 @@ //@ build-fail //@ compile-flags: -Zmir-opt-level=3 -#![feature(inline_const)] fn foo() { if false { diff --git a/tests/ui/inline-const/required-const.stderr b/tests/ui/inline-const/required-const.stderr index 2a13d18547c5..6ca4c250223e 100644 --- a/tests/ui/inline-const/required-const.stderr +++ b/tests/ui/inline-const/required-const.stderr @@ -1,13 +1,13 @@ error[E0080]: evaluation of `foo::::{constant#0}` failed - --> $DIR/required-const.rs:7:17 + --> $DIR/required-const.rs:6:17 | LL | const { panic!() } - | ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/required-const.rs:7:17 + | ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/required-const.rs:6:17 | = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered - --> $DIR/required-const.rs:7:9 + --> $DIR/required-const.rs:6:9 | LL | const { panic!() } | ^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/lifetimes/unusual-rib-combinations.rs b/tests/ui/lifetimes/unusual-rib-combinations.rs index a2461cff9326..3bc87b9d480b 100644 --- a/tests/ui/lifetimes/unusual-rib-combinations.rs +++ b/tests/ui/lifetimes/unusual-rib-combinations.rs @@ -1,5 +1,3 @@ -#![feature(inline_const)] - struct S<'a>(&'a u8); fn foo() {} diff --git a/tests/ui/lifetimes/unusual-rib-combinations.stderr b/tests/ui/lifetimes/unusual-rib-combinations.stderr index 320e64a2f774..2857fc72ea14 100644 --- a/tests/ui/lifetimes/unusual-rib-combinations.stderr +++ b/tests/ui/lifetimes/unusual-rib-combinations.stderr @@ -1,11 +1,11 @@ error[E0106]: missing lifetime specifier - --> $DIR/unusual-rib-combinations.rs:24:15 + --> $DIR/unusual-rib-combinations.rs:22:15 | LL | fn d() {} | ^ expected named lifetime parameter error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/unusual-rib-combinations.rs:29:22 + --> $DIR/unusual-rib-combinations.rs:27:22 | LL | struct Bar Foo<'a>)>; | ^^ the type must not depend on the parameter `'a` @@ -13,25 +13,25 @@ LL | struct Bar Foo<'a>)>; = note: lifetime parameters may not be used in the type of const parameters error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/unusual-rib-combinations.rs:7:16 + --> $DIR/unusual-rib-combinations.rs:5:16 | LL | fn a() -> [u8; foo::()] { | ^^^^^^^ only `Fn` traits may use parentheses error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/unusual-rib-combinations.rs:14:15 + --> $DIR/unusual-rib-combinations.rs:12:15 | LL | fn b() {} | ^^^^ only `Fn` traits may use parentheses error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/unusual-rib-combinations.rs:18:10 + --> $DIR/unusual-rib-combinations.rs:16:10 | LL | fn c() {} | ^^^^ only `Fn` traits may use parentheses error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions - --> $DIR/unusual-rib-combinations.rs:18:6 + --> $DIR/unusual-rib-combinations.rs:16:6 | LL | fn c() {} | ^^^^^^^^ @@ -41,7 +41,7 @@ LL | fn c() {} = note: `#[deny(invalid_type_param_default)]` on by default error[E0308]: mismatched types - --> $DIR/unusual-rib-combinations.rs:7:16 + --> $DIR/unusual-rib-combinations.rs:5:16 | LL | fn a() -> [u8; foo::()] { | ^^^^^^^ expected `usize`, found fn item @@ -50,7 +50,7 @@ LL | fn a() -> [u8; foo::()] { found fn item `fn() {foo}` error: `S<'_>` is forbidden as the type of a const generic parameter - --> $DIR/unusual-rib-combinations.rs:24:15 + --> $DIR/unusual-rib-combinations.rs:22:15 | LL | fn d() {} | ^ diff --git a/tests/ui/lint/invalid_from_utf8.rs b/tests/ui/lint/invalid_from_utf8.rs index e87afe9094ca..2d1822a54ac3 100644 --- a/tests/ui/lint/invalid_from_utf8.rs +++ b/tests/ui/lint/invalid_from_utf8.rs @@ -1,6 +1,5 @@ //@ check-pass -#![feature(inline_const)] #![feature(concat_bytes)] #![warn(invalid_from_utf8_unchecked)] diff --git a/tests/ui/lint/invalid_from_utf8.stderr b/tests/ui/lint/invalid_from_utf8.stderr index 884165d4f123..07616e118010 100644 --- a/tests/ui/lint/invalid_from_utf8.stderr +++ b/tests/ui/lint/invalid_from_utf8.stderr @@ -1,5 +1,5 @@ warning: calls to `std::str::from_utf8_unchecked_mut` with a invalid literal are undefined behavior - --> $DIR/invalid_from_utf8.rs:21:9 + --> $DIR/invalid_from_utf8.rs:20:9 | LL | std::str::from_utf8_unchecked_mut(&mut [99, 108, 130, 105, 112, 112, 121]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------^ @@ -7,13 +7,13 @@ LL | std::str::from_utf8_unchecked_mut(&mut [99, 108, 130, 105, 112, 112 | the literal was valid UTF-8 up to the 2 bytes | note: the lint level is defined here - --> $DIR/invalid_from_utf8.rs:6:9 + --> $DIR/invalid_from_utf8.rs:5:9 | LL | #![warn(invalid_from_utf8_unchecked)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: calls to `std::str::from_utf8_unchecked_mut` with a invalid literal are undefined behavior - --> $DIR/invalid_from_utf8.rs:23:9 + --> $DIR/invalid_from_utf8.rs:22:9 | LL | std::str::from_utf8_unchecked_mut(&mut [b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------------------^ @@ -21,7 +21,7 @@ LL | std::str::from_utf8_unchecked_mut(&mut [b'c', b'l', b'\x82', b'i', | the literal was valid UTF-8 up to the 2 bytes warning: calls to `std::str::from_utf8_unchecked` with a invalid literal are undefined behavior - --> $DIR/invalid_from_utf8.rs:41:9 + --> $DIR/invalid_from_utf8.rs:40:9 | LL | std::str::from_utf8_unchecked(&[99, 108, 130, 105, 112, 112, 121]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------^ @@ -29,7 +29,7 @@ LL | std::str::from_utf8_unchecked(&[99, 108, 130, 105, 112, 112, 121]); | the literal was valid UTF-8 up to the 2 bytes warning: calls to `std::str::from_utf8_unchecked` with a invalid literal are undefined behavior - --> $DIR/invalid_from_utf8.rs:43:9 + --> $DIR/invalid_from_utf8.rs:42:9 | LL | std::str::from_utf8_unchecked(&[b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------------------^ @@ -37,7 +37,7 @@ LL | std::str::from_utf8_unchecked(&[b'c', b'l', b'\x82', b'i', b'p', b' | the literal was valid UTF-8 up to the 2 bytes warning: calls to `std::str::from_utf8_unchecked` with a invalid literal are undefined behavior - --> $DIR/invalid_from_utf8.rs:45:9 + --> $DIR/invalid_from_utf8.rs:44:9 | LL | std::str::from_utf8_unchecked(b"cl\x82ippy"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------------^ @@ -45,7 +45,7 @@ LL | std::str::from_utf8_unchecked(b"cl\x82ippy"); | the literal was valid UTF-8 up to the 2 bytes warning: calls to `std::str::from_utf8_unchecked` with a invalid literal are undefined behavior - --> $DIR/invalid_from_utf8.rs:47:9 + --> $DIR/invalid_from_utf8.rs:46:9 | LL | std::str::from_utf8_unchecked(concat_bytes!(b"cl", b"\x82ippy")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------^ @@ -53,7 +53,7 @@ LL | std::str::from_utf8_unchecked(concat_bytes!(b"cl", b"\x82ippy")); | the literal was valid UTF-8 up to the 2 bytes warning: calls to `std::str::from_utf8_mut` with a invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:64:9 + --> $DIR/invalid_from_utf8.rs:63:9 | LL | std::str::from_utf8_mut(&mut [99, 108, 130, 105, 112, 112, 121]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------^ @@ -61,13 +61,13 @@ LL | std::str::from_utf8_mut(&mut [99, 108, 130, 105, 112, 112, 121]); | the literal was valid UTF-8 up to the 2 bytes | note: the lint level is defined here - --> $DIR/invalid_from_utf8.rs:7:9 + --> $DIR/invalid_from_utf8.rs:6:9 | LL | #![warn(invalid_from_utf8)] | ^^^^^^^^^^^^^^^^^ warning: calls to `std::str::from_utf8_mut` with a invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:66:9 + --> $DIR/invalid_from_utf8.rs:65:9 | LL | std::str::from_utf8_mut(&mut [b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------------------^ @@ -75,7 +75,7 @@ LL | std::str::from_utf8_mut(&mut [b'c', b'l', b'\x82', b'i', b'p', b'p' | the literal was valid UTF-8 up to the 2 bytes warning: calls to `std::str::from_utf8` with a invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:84:9 + --> $DIR/invalid_from_utf8.rs:83:9 | LL | std::str::from_utf8(&[99, 108, 130, 105, 112, 112, 121]); | ^^^^^^^^^^^^^^^^^^^^^----------------------------------^ @@ -83,7 +83,7 @@ LL | std::str::from_utf8(&[99, 108, 130, 105, 112, 112, 121]); | the literal was valid UTF-8 up to the 2 bytes warning: calls to `std::str::from_utf8` with a invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:86:9 + --> $DIR/invalid_from_utf8.rs:85:9 | LL | std::str::from_utf8(&[b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']); | ^^^^^^^^^^^^^^^^^^^^^---------------------------------------------^ @@ -91,7 +91,7 @@ LL | std::str::from_utf8(&[b'c', b'l', b'\x82', b'i', b'p', b'p', b'y']) | the literal was valid UTF-8 up to the 2 bytes warning: calls to `std::str::from_utf8` with a invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:88:9 + --> $DIR/invalid_from_utf8.rs:87:9 | LL | std::str::from_utf8(b"cl\x82ippy"); | ^^^^^^^^^^^^^^^^^^^^-------------^ @@ -99,7 +99,7 @@ LL | std::str::from_utf8(b"cl\x82ippy"); | the literal was valid UTF-8 up to the 2 bytes warning: calls to `std::str::from_utf8` with a invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:90:9 + --> $DIR/invalid_from_utf8.rs:89:9 | LL | std::str::from_utf8(concat_bytes!(b"cl", b"\x82ippy")); | ^^^^^^^^^^^^^^^^^^^^---------------------------------^ @@ -107,7 +107,7 @@ LL | std::str::from_utf8(concat_bytes!(b"cl", b"\x82ippy")); | the literal was valid UTF-8 up to the 2 bytes warning: calls to `std::str::from_utf8_mut` with a invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:97:5 + --> $DIR/invalid_from_utf8.rs:96:5 | LL | let mut a = [99, 108, 130, 105, 112, 112, 121]; | ---------------------------------- the literal was valid UTF-8 up to the 2 bytes @@ -115,7 +115,7 @@ LL | std::str::from_utf8_mut(&mut a); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: calls to `std::str::from_utf8_mut` with a invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:101:5 + --> $DIR/invalid_from_utf8.rs:100:5 | LL | let mut a = [99, 108, 130, 105, 112, 112, 121]; | ---------------------------------- the literal was valid UTF-8 up to the 2 bytes @@ -124,7 +124,7 @@ LL | std::str::from_utf8_mut(c); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: calls to `std::str::from_utf8` with a invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:104:5 + --> $DIR/invalid_from_utf8.rs:103:5 | LL | let mut c = &[99, 108, 130, 105, 112, 112, 121]; | ---------------------------------- the literal was valid UTF-8 up to the 2 bytes @@ -132,7 +132,7 @@ LL | std::str::from_utf8(c); | ^^^^^^^^^^^^^^^^^^^^^^ warning: calls to `std::str::from_utf8` with a invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:107:5 + --> $DIR/invalid_from_utf8.rs:106:5 | LL | const INVALID_1: [u8; 7] = [99, 108, 130, 105, 112, 112, 121]; | ---------------------------------- the literal was valid UTF-8 up to the 2 bytes @@ -140,7 +140,7 @@ LL | std::str::from_utf8(&INVALID_1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: calls to `std::str::from_utf8` with a invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:110:5 + --> $DIR/invalid_from_utf8.rs:109:5 | LL | static INVALID_2: [u8; 7] = [99, 108, 130, 105, 112, 112, 121]; | ---------------------------------- the literal was valid UTF-8 up to the 2 bytes @@ -148,7 +148,7 @@ LL | std::str::from_utf8(&INVALID_2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: calls to `std::str::from_utf8` with a invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:113:5 + --> $DIR/invalid_from_utf8.rs:112:5 | LL | const INVALID_3: &'static [u8; 7] = &[99, 108, 130, 105, 112, 112, 121]; | ---------------------------------- the literal was valid UTF-8 up to the 2 bytes @@ -156,7 +156,7 @@ LL | std::str::from_utf8(INVALID_3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: calls to `std::str::from_utf8` with a invalid literal always return an error - --> $DIR/invalid_from_utf8.rs:116:5 + --> $DIR/invalid_from_utf8.rs:115:5 | LL | const INVALID_4: &'static [u8; 7] = { &[99, 108, 130, 105, 112, 112, 121] }; | ---------------------------------- the literal was valid UTF-8 up to the 2 bytes diff --git a/tests/ui/lint/non-local-defs/consts.rs b/tests/ui/lint/non-local-defs/consts.rs index 2652447dcf59..d8a497e43e50 100644 --- a/tests/ui/lint/non-local-defs/consts.rs +++ b/tests/ui/lint/non-local-defs/consts.rs @@ -2,8 +2,6 @@ //@ edition:2021 //@ rustc-env:CARGO_CRATE_NAME=non_local_def -#![feature(inline_const)] - struct Test; trait Uto {} diff --git a/tests/ui/lint/non-local-defs/consts.stderr b/tests/ui/lint/non-local-defs/consts.stderr index 5563ea9d93f0..d15b452b004e 100644 --- a/tests/ui/lint/non-local-defs/consts.stderr +++ b/tests/ui/lint/non-local-defs/consts.stderr @@ -1,5 +1,5 @@ warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/consts.rs:15:5 + --> $DIR/consts.rs:13:5 | LL | const Z: () = { | - help: use a const-anon item to suppress this lint: `_` @@ -14,7 +14,7 @@ LL | impl Uto for &Test {} = note: `#[warn(non_local_definitions)]` on by default warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/consts.rs:26:5 + --> $DIR/consts.rs:24:5 | LL | impl Uto2 for Test {} | ^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | impl Uto2 for Test {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/consts.rs:34:5 + --> $DIR/consts.rs:32:5 | LL | impl Uto3 for Test {} | ^^^^^^^^^^^^^^^^^^^^^ @@ -36,7 +36,7 @@ LL | impl Uto3 for Test {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/consts.rs:45:5 + --> $DIR/consts.rs:43:5 | LL | / impl Test { LL | | @@ -50,7 +50,7 @@ LL | | } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/consts.rs:52:9 + --> $DIR/consts.rs:50:9 | LL | / impl Test { LL | | @@ -64,7 +64,7 @@ LL | | } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/consts.rs:61:9 + --> $DIR/consts.rs:59:9 | LL | / impl Test { LL | | @@ -78,7 +78,7 @@ LL | | } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/consts.rs:74:9 + --> $DIR/consts.rs:72:9 | LL | impl Uto9 for Test {} | ^^^^^^^^^^^^^^^^^^^^^ @@ -89,7 +89,7 @@ LL | impl Uto9 for Test {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/consts.rs:81:9 + --> $DIR/consts.rs:79:9 | LL | impl Uto10 for Test {} | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/lint/non-local-defs/from-local-for-global.rs b/tests/ui/lint/non-local-defs/from-local-for-global.rs index 0ab3a6b19887..fea9679d7375 100644 --- a/tests/ui/lint/non-local-defs/from-local-for-global.rs +++ b/tests/ui/lint/non-local-defs/from-local-for-global.rs @@ -1,8 +1,6 @@ //@ check-pass //@ edition:2021 -#![feature(inline_const)] - struct Cat; struct Wrap(T); diff --git a/tests/ui/lint/non-local-defs/from-local-for-global.stderr b/tests/ui/lint/non-local-defs/from-local-for-global.stderr index bd592a721572..0cd385049aa6 100644 --- a/tests/ui/lint/non-local-defs/from-local-for-global.stderr +++ b/tests/ui/lint/non-local-defs/from-local-for-global.stderr @@ -1,5 +1,5 @@ warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/from-local-for-global.rs:10:5 + --> $DIR/from-local-for-global.rs:8:5 | LL | / impl From for () { LL | | @@ -16,7 +16,7 @@ LL | | } = note: `#[warn(non_local_definitions)]` on by default warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/from-local-for-global.rs:20:5 + --> $DIR/from-local-for-global.rs:18:5 | LL | / impl From>> for () { LL | | @@ -32,7 +32,7 @@ LL | | } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/from-local-for-global.rs:34:5 + --> $DIR/from-local-for-global.rs:32:5 | LL | impl StillNonLocal for &Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -43,7 +43,7 @@ LL | impl StillNonLocal for &Foo {} = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/from-local-for-global.rs:42:5 + --> $DIR/from-local-for-global.rs:40:5 | LL | / impl From for GlobalSameFunction { LL | | @@ -59,7 +59,7 @@ LL | | } = note: this lint may become deny-by-default in the edition 2024 and higher, see the tracking issue warning: non-local `impl` definition, they should be avoided as they go against expectation - --> $DIR/from-local-for-global.rs:50:5 + --> $DIR/from-local-for-global.rs:48:5 | LL | / impl From for GlobalSameFunction { LL | | diff --git a/tests/ui/loops/dont-suggest-break-thru-item.rs b/tests/ui/loops/dont-suggest-break-thru-item.rs index 34a9a57bfed0..b4262ec02bf4 100644 --- a/tests/ui/loops/dont-suggest-break-thru-item.rs +++ b/tests/ui/loops/dont-suggest-break-thru-item.rs @@ -1,7 +1,5 @@ //@ edition:2021 -#![feature(inline_const)] - fn closure() { loop { let closure = || { diff --git a/tests/ui/loops/dont-suggest-break-thru-item.stderr b/tests/ui/loops/dont-suggest-break-thru-item.stderr index c84a98198f55..642578ade60b 100644 --- a/tests/ui/loops/dont-suggest-break-thru-item.stderr +++ b/tests/ui/loops/dont-suggest-break-thru-item.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/dont-suggest-break-thru-item.rs:9:17 + --> $DIR/dont-suggest-break-thru-item.rs:7:17 | LL | / if true { LL | | Err(1) @@ -17,7 +17,7 @@ LL | return Err(1); | ++++++ + error[E0308]: mismatched types - --> $DIR/dont-suggest-break-thru-item.rs:23:17 + --> $DIR/dont-suggest-break-thru-item.rs:21:17 | LL | / if true { LL | | Err(1) @@ -35,7 +35,7 @@ LL | return Err(1); | ++++++ + error[E0308]: mismatched types - --> $DIR/dont-suggest-break-thru-item.rs:37:17 + --> $DIR/dont-suggest-break-thru-item.rs:35:17 | LL | / if true { LL | | Err(1) @@ -48,7 +48,7 @@ LL | | } found enum `Result<_, {integer}>` error[E0308]: mismatched types - --> $DIR/dont-suggest-break-thru-item.rs:49:17 + --> $DIR/dont-suggest-break-thru-item.rs:47:17 | LL | / if true { LL | | Err(1) diff --git a/tests/ui/parser/bad-let-else-statement.rs b/tests/ui/parser/bad-let-else-statement.rs index c3126a493e54..de41a07568fb 100644 --- a/tests/ui/parser/bad-let-else-statement.rs +++ b/tests/ui/parser/bad-let-else-statement.rs @@ -1,4 +1,3 @@ -#![feature(inline_const)] #![feature(yeet_expr)] #![allow(incomplete_features)] // Necessary for now, while explicit_tail_calls is incomplete #![feature(explicit_tail_calls)] diff --git a/tests/ui/parser/bad-let-else-statement.stderr b/tests/ui/parser/bad-let-else-statement.stderr index 12df8f849abd..3f7e176b3e31 100644 --- a/tests/ui/parser/bad-let-else-statement.stderr +++ b/tests/ui/parser/bad-let-else-statement.stderr @@ -1,5 +1,5 @@ error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:10:5 + --> $DIR/bad-let-else-statement.rs:9:5 | LL | } else { | ^ @@ -13,7 +13,7 @@ LL ~ }) else { | error: `for...else` loops are not supported - --> $DIR/bad-let-else-statement.rs:19:7 + --> $DIR/bad-let-else-statement.rs:18:7 | LL | let foo = for i in 1..2 { | --- `else` is attached to this loop @@ -28,7 +28,7 @@ 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:31:5 + --> $DIR/bad-let-else-statement.rs:30:5 | LL | } else { | ^ @@ -43,7 +43,7 @@ LL ~ }) else { | error: `loop...else` loops are not supported - --> $DIR/bad-let-else-statement.rs:40:7 + --> $DIR/bad-let-else-statement.rs:39:7 | LL | let foo = loop { | ---- `else` is attached to this loop @@ -58,7 +58,7 @@ 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:51:5 + --> $DIR/bad-let-else-statement.rs:50:5 | LL | } else { | ^ @@ -73,7 +73,7 @@ LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:62:5 + --> $DIR/bad-let-else-statement.rs:61:5 | LL | } else { | ^ @@ -87,7 +87,7 @@ LL ~ }) else { | error: `while...else` loops are not supported - --> $DIR/bad-let-else-statement.rs:71:7 + --> $DIR/bad-let-else-statement.rs:70:7 | LL | let foo = while false { | ----- `else` is attached to this loop @@ -102,7 +102,7 @@ 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:81:5 + --> $DIR/bad-let-else-statement.rs:80:5 | LL | } else { | ^ @@ -116,7 +116,7 @@ LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:91:5 + --> $DIR/bad-let-else-statement.rs:90:5 | LL | } else { | ^ @@ -130,7 +130,7 @@ LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:102:5 + --> $DIR/bad-let-else-statement.rs:101:5 | LL | } else { | ^ @@ -144,7 +144,7 @@ LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:112:5 + --> $DIR/bad-let-else-statement.rs:111:5 | LL | } else { | ^ @@ -158,7 +158,7 @@ LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:122:5 + --> $DIR/bad-let-else-statement.rs:121:5 | LL | } else { | ^ @@ -172,7 +172,7 @@ LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:132:5 + --> $DIR/bad-let-else-statement.rs:131:5 | LL | } else { | ^ @@ -186,7 +186,7 @@ LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:142:5 + --> $DIR/bad-let-else-statement.rs:141:5 | LL | } else { | ^ @@ -200,7 +200,7 @@ LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:152:5 + --> $DIR/bad-let-else-statement.rs:151:5 | LL | } else { | ^ @@ -214,7 +214,7 @@ LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:162:5 + --> $DIR/bad-let-else-statement.rs:161:5 | LL | } else { | ^ @@ -228,7 +228,7 @@ LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:172:5 + --> $DIR/bad-let-else-statement.rs:171:5 | LL | } else { | ^ @@ -242,7 +242,7 @@ LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:182:31 + --> $DIR/bad-let-else-statement.rs:181:31 | LL | let bad = format_args! {""} else { return; }; | ^ @@ -253,7 +253,7 @@ LL | let bad = format_args! ("") else { return; }; | ~ ~ error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:199:25 + --> $DIR/bad-let-else-statement.rs:198:25 | LL | let x = a! {} else { return; }; | ^ @@ -268,7 +268,7 @@ LL | let x = a! () else { return; }; | ~~ warning: irrefutable `let...else` pattern - --> $DIR/bad-let-else-statement.rs:7:5 + --> $DIR/bad-let-else-statement.rs:6:5 | LL | / let foo = { LL | | @@ -281,7 +281,7 @@ LL | | } else { = note: `#[warn(irrefutable_let_patterns)]` on by default warning: irrefutable `let...else` pattern - --> $DIR/bad-let-else-statement.rs:26:5 + --> $DIR/bad-let-else-statement.rs:25:5 | LL | / let foo = if true { LL | | @@ -295,7 +295,7 @@ LL | | } else { = help: consider removing the `else` clause warning: irrefutable `let...else` pattern - --> $DIR/bad-let-else-statement.rs:47:5 + --> $DIR/bad-let-else-statement.rs:46:5 | LL | / let foo = match true { LL | | @@ -308,7 +308,7 @@ LL | | } else { = help: consider removing the `else` clause warning: irrefutable `let...else` pattern - --> $DIR/bad-let-else-statement.rs:59:5 + --> $DIR/bad-let-else-statement.rs:58:5 | LL | / let foo = X { LL | | @@ -320,7 +320,7 @@ LL | | } else { = help: consider removing the `else` clause warning: irrefutable `let...else` pattern - --> $DIR/bad-let-else-statement.rs:78:5 + --> $DIR/bad-let-else-statement.rs:77:5 | LL | / let foo = const { LL | | @@ -332,7 +332,7 @@ LL | | } else { = help: consider removing the `else` clause warning: irrefutable `let...else` pattern - --> $DIR/bad-let-else-statement.rs:88:5 + --> $DIR/bad-let-else-statement.rs:87:5 | LL | / let foo = &{ LL | | @@ -344,7 +344,7 @@ LL | | } else { = help: consider removing the `else` clause warning: irrefutable `let...else` pattern - --> $DIR/bad-let-else-statement.rs:99:5 + --> $DIR/bad-let-else-statement.rs:98:5 | LL | / let foo = bar = { LL | | @@ -356,7 +356,7 @@ LL | | } else { = help: consider removing the `else` clause error[E0384]: cannot assign twice to immutable variable `bar` - --> $DIR/bad-let-else-statement.rs:99:15 + --> $DIR/bad-let-else-statement.rs:98:15 | LL | let bar = 0; | --- @@ -371,7 +371,7 @@ LL | | } else { | |_____^ cannot assign twice to immutable variable warning: irrefutable `let...else` pattern - --> $DIR/bad-let-else-statement.rs:109:5 + --> $DIR/bad-let-else-statement.rs:108:5 | LL | / let foo = 1 + { LL | | @@ -383,7 +383,7 @@ LL | | } else { = help: consider removing the `else` clause warning: irrefutable `let...else` pattern - --> $DIR/bad-let-else-statement.rs:119:5 + --> $DIR/bad-let-else-statement.rs:118:5 | LL | / let foo = 1..{ LL | | @@ -395,7 +395,7 @@ LL | | } else { = help: consider removing the `else` clause warning: irrefutable `let...else` pattern - --> $DIR/bad-let-else-statement.rs:129:5 + --> $DIR/bad-let-else-statement.rs:128:5 | LL | / let foo = return { LL | | @@ -407,7 +407,7 @@ LL | | } else { = help: consider removing the `else` clause warning: irrefutable `let...else` pattern - --> $DIR/bad-let-else-statement.rs:139:5 + --> $DIR/bad-let-else-statement.rs:138:5 | LL | / let foo = -{ LL | | @@ -419,7 +419,7 @@ LL | | } else { = help: consider removing the `else` clause warning: irrefutable `let...else` pattern - --> $DIR/bad-let-else-statement.rs:149:5 + --> $DIR/bad-let-else-statement.rs:148:5 | LL | / let foo = do yeet { LL | | @@ -431,7 +431,7 @@ LL | | } else { = help: consider removing the `else` clause warning: irrefutable `let...else` pattern - --> $DIR/bad-let-else-statement.rs:159:5 + --> $DIR/bad-let-else-statement.rs:158:5 | LL | / let foo = become { LL | | @@ -443,7 +443,7 @@ LL | | } else { = help: consider removing the `else` clause warning: irrefutable `let...else` pattern - --> $DIR/bad-let-else-statement.rs:169:5 + --> $DIR/bad-let-else-statement.rs:168:5 | LL | / let foo = |x: i32| { LL | | @@ -455,7 +455,7 @@ LL | | } else { = help: consider removing the `else` clause warning: irrefutable `let...else` pattern - --> $DIR/bad-let-else-statement.rs:179:5 + --> $DIR/bad-let-else-statement.rs:178:5 | LL | let ok = format_args!("") else { return; }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -464,7 +464,7 @@ LL | let ok = format_args!("") else { return; }; = help: consider removing the `else` clause warning: irrefutable `let...else` pattern - --> $DIR/bad-let-else-statement.rs:182:5 + --> $DIR/bad-let-else-statement.rs:181:5 | LL | let bad = format_args! {""} else { return; }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -473,7 +473,7 @@ LL | let bad = format_args! {""} else { return; }; = help: consider removing the `else` clause warning: irrefutable `let...else` pattern - --> $DIR/bad-let-else-statement.rs:189:19 + --> $DIR/bad-let-else-statement.rs:188:19 | LL | () => { {} } | ___________________^ @@ -493,7 +493,7 @@ LL | b!(1); b!(2); = note: this warning originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info) warning: irrefutable `let...else` pattern - --> $DIR/bad-let-else-statement.rs:189:19 + --> $DIR/bad-let-else-statement.rs:188:19 | LL | () => { {} } | ___________________^ diff --git a/tests/ui/simd/const-err-trumps-simd-err.rs b/tests/ui/simd/const-err-trumps-simd-err.rs index 06a747273ab7..fda044344517 100644 --- a/tests/ui/simd/const-err-trumps-simd-err.rs +++ b/tests/ui/simd/const-err-trumps-simd-err.rs @@ -5,7 +5,7 @@ #![feature(generic_arg_infer)] #![feature(core_intrinsics)] #![feature(repr_simd)] -#![feature(inline_const)] + use std::intrinsics::simd::*; #[repr(simd)] diff --git a/tests/ui/simd/intrinsic/generic-elements-pass.rs b/tests/ui/simd/intrinsic/generic-elements-pass.rs index 730030878193..a81d8ebdf50c 100644 --- a/tests/ui/simd/intrinsic/generic-elements-pass.rs +++ b/tests/ui/simd/intrinsic/generic-elements-pass.rs @@ -2,7 +2,6 @@ //@ ignore-emscripten FIXME(#45351) hits an LLVM assert #![feature(repr_simd, intrinsics)] -#![feature(inline_const)] #[repr(simd)] #[derive(Copy, Clone, Debug, PartialEq)] From 9d16364198733d9b54c2d0d64dea2e6a640f8948 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Fri, 19 Apr 2024 17:01:35 +0100 Subject: [PATCH 27/36] Fix and bless clippy tests --- .../ui-toml/suppress_lint_in_const/test.rs | 1 - .../suppress_lint_in_const/test.stderr | 12 ++--- .../tests/ui/arithmetic_side_effects.rs | 2 +- .../clippy/tests/ui/bool_to_int_with_if.fixed | 2 +- .../clippy/tests/ui/bool_to_int_with_if.rs | 2 +- src/tools/clippy/tests/ui/const_is_empty.rs | 1 - .../clippy/tests/ui/const_is_empty.stderr | 52 +++++++++---------- .../clippy/tests/ui/indexing_slicing_index.rs | 1 - .../tests/ui/indexing_slicing_index.stderr | 32 ++++++------ .../clippy/tests/ui/manual_float_methods.rs | 1 - .../tests/ui/manual_float_methods.stderr | 12 ++--- src/tools/clippy/tests/ui/never_loop.rs | 2 +- src/tools/clippy/tests/ui/panicking_macros.rs | 1 - .../clippy/tests/ui/panicking_macros.stderr | 32 ++++++------ 14 files changed, 74 insertions(+), 79 deletions(-) diff --git a/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.rs b/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.rs index 4ae75544c60c..232bccf6a154 100644 --- a/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.rs +++ b/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.rs @@ -1,4 +1,3 @@ -#![feature(inline_const)] #![warn(clippy::indexing_slicing)] // We also check the out_of_bounds_indexing lint here, because it lints similar things and // we want to avoid false positives. diff --git a/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.stderr b/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.stderr index 120f5c35cb03..5ce2ed2ffaee 100644 --- a/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.stderr +++ b/src/tools/clippy/tests/ui-toml/suppress_lint_in_const/test.stderr @@ -1,5 +1,5 @@ error: indexing may panic - --> tests/ui-toml/suppress_lint_in_const/test.rs:27:5 + --> tests/ui-toml/suppress_lint_in_const/test.rs:26:5 | LL | x[index]; | ^^^^^^^^ @@ -9,7 +9,7 @@ LL | x[index]; = help: to override `-D warnings` add `#[allow(clippy::indexing_slicing)]` error: indexing may panic - --> tests/ui-toml/suppress_lint_in_const/test.rs:42:5 + --> tests/ui-toml/suppress_lint_in_const/test.rs:41:5 | LL | v[0]; | ^^^^ @@ -17,7 +17,7 @@ LL | v[0]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> tests/ui-toml/suppress_lint_in_const/test.rs:43:5 + --> tests/ui-toml/suppress_lint_in_const/test.rs:42:5 | LL | v[10]; | ^^^^^ @@ -25,7 +25,7 @@ LL | v[10]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> tests/ui-toml/suppress_lint_in_const/test.rs:44:5 + --> tests/ui-toml/suppress_lint_in_const/test.rs:43:5 | LL | v[1 << 3]; | ^^^^^^^^^ @@ -33,7 +33,7 @@ LL | v[1 << 3]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> tests/ui-toml/suppress_lint_in_const/test.rs:50:5 + --> tests/ui-toml/suppress_lint_in_const/test.rs:49:5 | LL | v[N]; | ^^^^ @@ -41,7 +41,7 @@ LL | v[N]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> tests/ui-toml/suppress_lint_in_const/test.rs:51:5 + --> tests/ui-toml/suppress_lint_in_const/test.rs:50:5 | LL | v[M]; | ^^^^ diff --git a/src/tools/clippy/tests/ui/arithmetic_side_effects.rs b/src/tools/clippy/tests/ui/arithmetic_side_effects.rs index b454c29aef4d..fdec14a1528f 100644 --- a/src/tools/clippy/tests/ui/arithmetic_side_effects.rs +++ b/src/tools/clippy/tests/ui/arithmetic_side_effects.rs @@ -10,7 +10,7 @@ arithmetic_overflow, unconditional_panic )] -#![feature(const_mut_refs, inline_const)] +#![feature(const_mut_refs)] #![warn(clippy::arithmetic_side_effects)] extern crate proc_macro_derive; diff --git a/src/tools/clippy/tests/ui/bool_to_int_with_if.fixed b/src/tools/clippy/tests/ui/bool_to_int_with_if.fixed index 167263d31df8..f7dad28b0369 100644 --- a/src/tools/clippy/tests/ui/bool_to_int_with_if.fixed +++ b/src/tools/clippy/tests/ui/bool_to_int_with_if.fixed @@ -1,4 +1,4 @@ -#![feature(let_chains, inline_const)] +#![feature(let_chains)] #![warn(clippy::bool_to_int_with_if)] #![allow(unused, dead_code, clippy::unnecessary_operation, clippy::no_effect)] diff --git a/src/tools/clippy/tests/ui/bool_to_int_with_if.rs b/src/tools/clippy/tests/ui/bool_to_int_with_if.rs index f3f055eb7f06..d22871d2c8f2 100644 --- a/src/tools/clippy/tests/ui/bool_to_int_with_if.rs +++ b/src/tools/clippy/tests/ui/bool_to_int_with_if.rs @@ -1,4 +1,4 @@ -#![feature(let_chains, inline_const)] +#![feature(let_chains)] #![warn(clippy::bool_to_int_with_if)] #![allow(unused, dead_code, clippy::unnecessary_operation, clippy::no_effect)] diff --git a/src/tools/clippy/tests/ui/const_is_empty.rs b/src/tools/clippy/tests/ui/const_is_empty.rs index ae37a82e4f93..04e0de91ecfb 100644 --- a/src/tools/clippy/tests/ui/const_is_empty.rs +++ b/src/tools/clippy/tests/ui/const_is_empty.rs @@ -1,4 +1,3 @@ -#![feature(inline_const)] #![warn(clippy::const_is_empty)] #![allow(clippy::needless_late_init, unused_must_use)] diff --git a/src/tools/clippy/tests/ui/const_is_empty.stderr b/src/tools/clippy/tests/ui/const_is_empty.stderr index 0e09da77bb46..7f80b520b1a4 100644 --- a/src/tools/clippy/tests/ui/const_is_empty.stderr +++ b/src/tools/clippy/tests/ui/const_is_empty.stderr @@ -1,5 +1,5 @@ error: this expression always evaluates to true - --> tests/ui/const_is_empty.rs:6:8 + --> tests/ui/const_is_empty.rs:5:8 | LL | if "".is_empty() { | ^^^^^^^^^^^^^ @@ -8,151 +8,151 @@ LL | if "".is_empty() { = help: to override `-D warnings` add `#[allow(clippy::const_is_empty)]` error: this expression always evaluates to false - --> tests/ui/const_is_empty.rs:9:8 + --> tests/ui/const_is_empty.rs:8:8 | LL | if "foobar".is_empty() { | ^^^^^^^^^^^^^^^^^^^ error: this expression always evaluates to true - --> tests/ui/const_is_empty.rs:15:8 + --> tests/ui/const_is_empty.rs:14:8 | LL | if b"".is_empty() { | ^^^^^^^^^^^^^^ error: this expression always evaluates to false - --> tests/ui/const_is_empty.rs:18:8 + --> tests/ui/const_is_empty.rs:17:8 | LL | if b"foobar".is_empty() { | ^^^^^^^^^^^^^^^^^^^^ error: this expression always evaluates to true - --> tests/ui/const_is_empty.rs:35:8 + --> tests/ui/const_is_empty.rs:34:8 | LL | if empty2.is_empty() { | ^^^^^^^^^^^^^^^^^ error: this expression always evaluates to false - --> tests/ui/const_is_empty.rs:38:8 + --> tests/ui/const_is_empty.rs:37:8 | LL | if non_empty2.is_empty() { | ^^^^^^^^^^^^^^^^^^^^^ error: this expression always evaluates to true - --> tests/ui/const_is_empty.rs:60:13 + --> tests/ui/const_is_empty.rs:59:13 | LL | let _ = EMPTY_STR.is_empty(); | ^^^^^^^^^^^^^^^^^^^^ error: this expression always evaluates to false - --> tests/ui/const_is_empty.rs:62:13 + --> tests/ui/const_is_empty.rs:61:13 | LL | let _ = NON_EMPTY_STR.is_empty(); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: this expression always evaluates to true - --> tests/ui/const_is_empty.rs:64:13 + --> tests/ui/const_is_empty.rs:63:13 | LL | let _ = EMPTY_BSTR.is_empty(); | ^^^^^^^^^^^^^^^^^^^^^ error: this expression always evaluates to false - --> tests/ui/const_is_empty.rs:66:13 + --> tests/ui/const_is_empty.rs:65:13 | LL | let _ = NON_EMPTY_BSTR.is_empty(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: this expression always evaluates to true - --> tests/ui/const_is_empty.rs:68:13 + --> tests/ui/const_is_empty.rs:67:13 | LL | let _ = EMPTY_ARRAY.is_empty(); | ^^^^^^^^^^^^^^^^^^^^^^ error: this expression always evaluates to true - --> tests/ui/const_is_empty.rs:70:13 + --> tests/ui/const_is_empty.rs:69:13 | LL | let _ = EMPTY_ARRAY_REPEAT.is_empty(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this expression always evaluates to true - --> tests/ui/const_is_empty.rs:72:13 + --> tests/ui/const_is_empty.rs:71:13 | LL | let _ = EMPTY_U8_SLICE.is_empty(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: this expression always evaluates to false - --> tests/ui/const_is_empty.rs:74:13 + --> tests/ui/const_is_empty.rs:73:13 | LL | let _ = NON_EMPTY_U8_SLICE.is_empty(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this expression always evaluates to false - --> tests/ui/const_is_empty.rs:76:13 + --> tests/ui/const_is_empty.rs:75:13 | LL | let _ = NON_EMPTY_ARRAY.is_empty(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this expression always evaluates to false - --> tests/ui/const_is_empty.rs:78:13 + --> tests/ui/const_is_empty.rs:77:13 | LL | let _ = NON_EMPTY_ARRAY_REPEAT.is_empty(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this expression always evaluates to true - --> tests/ui/const_is_empty.rs:80:13 + --> tests/ui/const_is_empty.rs:79:13 | LL | let _ = EMPTY_REF_ARRAY.is_empty(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this expression always evaluates to false - --> tests/ui/const_is_empty.rs:82:13 + --> tests/ui/const_is_empty.rs:81:13 | LL | let _ = NON_EMPTY_REF_ARRAY.is_empty(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this expression always evaluates to true - --> tests/ui/const_is_empty.rs:84:13 + --> tests/ui/const_is_empty.rs:83:13 | LL | let _ = EMPTY_SLICE.is_empty(); | ^^^^^^^^^^^^^^^^^^^^^^ error: this expression always evaluates to false - --> tests/ui/const_is_empty.rs:86:13 + --> tests/ui/const_is_empty.rs:85:13 | LL | let _ = NON_EMPTY_SLICE.is_empty(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this expression always evaluates to false - --> tests/ui/const_is_empty.rs:88:13 + --> tests/ui/const_is_empty.rs:87:13 | LL | let _ = NON_EMPTY_SLICE_REPEAT.is_empty(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this expression always evaluates to false - --> tests/ui/const_is_empty.rs:94:13 + --> tests/ui/const_is_empty.rs:93:13 | LL | let _ = value.is_empty(); | ^^^^^^^^^^^^^^^^ error: this expression always evaluates to false - --> tests/ui/const_is_empty.rs:97:13 + --> tests/ui/const_is_empty.rs:96:13 | LL | let _ = x.is_empty(); | ^^^^^^^^^^^^ error: this expression always evaluates to true - --> tests/ui/const_is_empty.rs:99:13 + --> tests/ui/const_is_empty.rs:98:13 | LL | let _ = "".is_empty(); | ^^^^^^^^^^^^^ error: this expression always evaluates to true - --> tests/ui/const_is_empty.rs:101:13 + --> tests/ui/const_is_empty.rs:100:13 | LL | let _ = b"".is_empty(); | ^^^^^^^^^^^^^^ error: this expression always evaluates to true - --> tests/ui/const_is_empty.rs:155:13 + --> tests/ui/const_is_empty.rs:154:13 | LL | let _ = val.is_empty(); | ^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/indexing_slicing_index.rs b/src/tools/clippy/tests/ui/indexing_slicing_index.rs index 27ee2f91594b..2e726141649e 100644 --- a/src/tools/clippy/tests/ui/indexing_slicing_index.rs +++ b/src/tools/clippy/tests/ui/indexing_slicing_index.rs @@ -1,6 +1,5 @@ //@compile-flags: -Zdeduplicate-diagnostics=yes -#![feature(inline_const)] #![warn(clippy::indexing_slicing)] // We also check the out_of_bounds_indexing lint here, because it lints similar things and // we want to avoid false positives. diff --git a/src/tools/clippy/tests/ui/indexing_slicing_index.stderr b/src/tools/clippy/tests/ui/indexing_slicing_index.stderr index 5f62ec9b5565..386f91becf14 100644 --- a/src/tools/clippy/tests/ui/indexing_slicing_index.stderr +++ b/src/tools/clippy/tests/ui/indexing_slicing_index.stderr @@ -1,5 +1,5 @@ error: indexing may panic - --> tests/ui/indexing_slicing_index.rs:16:20 + --> tests/ui/indexing_slicing_index.rs:15:20 | LL | const REF: &i32 = &ARR[idx()]; // This should be linted, since `suppress-restriction-lint-in-const` default is false. | ^^^^^^^^^^ @@ -10,19 +10,19 @@ LL | const REF: &i32 = &ARR[idx()]; // This should be linted, since `suppress-re = help: to override `-D warnings` add `#[allow(clippy::indexing_slicing)]` error[E0080]: evaluation of `main::{constant#3}` failed - --> tests/ui/indexing_slicing_index.rs:48:14 + --> tests/ui/indexing_slicing_index.rs:47:14 | LL | const { &ARR[idx4()] }; | ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4 note: erroneous constant encountered - --> tests/ui/indexing_slicing_index.rs:48:5 + --> tests/ui/indexing_slicing_index.rs:47:5 | LL | const { &ARR[idx4()] }; | ^^^^^^^^^^^^^^^^^^^^^^ error: indexing may panic - --> tests/ui/indexing_slicing_index.rs:29:5 + --> tests/ui/indexing_slicing_index.rs:28:5 | LL | x[index]; | ^^^^^^^^ @@ -30,7 +30,7 @@ LL | x[index]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: index is out of bounds - --> tests/ui/indexing_slicing_index.rs:32:5 + --> tests/ui/indexing_slicing_index.rs:31:5 | LL | x[4]; | ^^^^ @@ -39,13 +39,13 @@ LL | x[4]; = help: to override `-D warnings` add `#[allow(clippy::out_of_bounds_indexing)]` error: index is out of bounds - --> tests/ui/indexing_slicing_index.rs:34:5 + --> tests/ui/indexing_slicing_index.rs:33:5 | LL | x[1 << 3]; | ^^^^^^^^^ error: indexing may panic - --> tests/ui/indexing_slicing_index.rs:45:14 + --> tests/ui/indexing_slicing_index.rs:44:14 | LL | const { &ARR[idx()] }; | ^^^^^^^^^^ @@ -54,7 +54,7 @@ LL | const { &ARR[idx()] }; = note: the suggestion might not be applicable in constant blocks error: indexing may panic - --> tests/ui/indexing_slicing_index.rs:48:14 + --> tests/ui/indexing_slicing_index.rs:47:14 | LL | const { &ARR[idx4()] }; | ^^^^^^^^^^^ @@ -63,13 +63,13 @@ LL | const { &ARR[idx4()] }; = note: the suggestion might not be applicable in constant blocks error: index is out of bounds - --> tests/ui/indexing_slicing_index.rs:55:5 + --> tests/ui/indexing_slicing_index.rs:54:5 | LL | y[4]; | ^^^^ error: indexing may panic - --> tests/ui/indexing_slicing_index.rs:58:5 + --> tests/ui/indexing_slicing_index.rs:57:5 | LL | v[0]; | ^^^^ @@ -77,7 +77,7 @@ LL | v[0]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> tests/ui/indexing_slicing_index.rs:60:5 + --> tests/ui/indexing_slicing_index.rs:59:5 | LL | v[10]; | ^^^^^ @@ -85,7 +85,7 @@ LL | v[10]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> tests/ui/indexing_slicing_index.rs:62:5 + --> tests/ui/indexing_slicing_index.rs:61:5 | LL | v[1 << 3]; | ^^^^^^^^^ @@ -93,13 +93,13 @@ LL | v[1 << 3]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: index is out of bounds - --> tests/ui/indexing_slicing_index.rs:70:5 + --> tests/ui/indexing_slicing_index.rs:69:5 | LL | x[N]; | ^^^^ error: indexing may panic - --> tests/ui/indexing_slicing_index.rs:73:5 + --> tests/ui/indexing_slicing_index.rs:72:5 | LL | v[N]; | ^^^^ @@ -107,7 +107,7 @@ LL | v[N]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> tests/ui/indexing_slicing_index.rs:75:5 + --> tests/ui/indexing_slicing_index.rs:74:5 | LL | v[M]; | ^^^^ @@ -115,7 +115,7 @@ LL | v[M]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: index is out of bounds - --> tests/ui/indexing_slicing_index.rs:79:13 + --> tests/ui/indexing_slicing_index.rs:78:13 | LL | let _ = x[4]; | ^^^^ diff --git a/src/tools/clippy/tests/ui/manual_float_methods.rs b/src/tools/clippy/tests/ui/manual_float_methods.rs index f3e95d6807d3..80781ecda721 100644 --- a/src/tools/clippy/tests/ui/manual_float_methods.rs +++ b/src/tools/clippy/tests/ui/manual_float_methods.rs @@ -2,7 +2,6 @@ //@aux-build:proc_macros.rs #![allow(clippy::needless_if, unused)] #![warn(clippy::manual_is_infinite, clippy::manual_is_finite)] -#![feature(inline_const)] #[macro_use] extern crate proc_macros; diff --git a/src/tools/clippy/tests/ui/manual_float_methods.stderr b/src/tools/clippy/tests/ui/manual_float_methods.stderr index dae96839262d..930df0b97cb3 100644 --- a/src/tools/clippy/tests/ui/manual_float_methods.stderr +++ b/src/tools/clippy/tests/ui/manual_float_methods.stderr @@ -1,5 +1,5 @@ error: manually checking if a float is infinite - --> tests/ui/manual_float_methods.rs:23:8 + --> tests/ui/manual_float_methods.rs:22:8 | LL | if x == f32::INFINITY || x == f32::NEG_INFINITY {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the dedicated method instead: `x.is_infinite()` @@ -8,7 +8,7 @@ LL | if x == f32::INFINITY || x == f32::NEG_INFINITY {} = help: to override `-D warnings` add `#[allow(clippy::manual_is_infinite)]` error: manually checking if a float is finite - --> tests/ui/manual_float_methods.rs:24:8 + --> tests/ui/manual_float_methods.rs:23:8 | LL | if x != f32::INFINITY && x != f32::NEG_INFINITY {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -29,13 +29,13 @@ LL | if !x.is_infinite() {} | ~~~~~~~~~~~~~~~~ error: manually checking if a float is infinite - --> tests/ui/manual_float_methods.rs:25:8 + --> tests/ui/manual_float_methods.rs:24:8 | LL | if x == INFINITE || x == NEG_INFINITE {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the dedicated method instead: `x.is_infinite()` error: manually checking if a float is finite - --> tests/ui/manual_float_methods.rs:26:8 + --> tests/ui/manual_float_methods.rs:25:8 | LL | if x != INFINITE && x != NEG_INFINITE {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -54,13 +54,13 @@ LL | if !x.is_infinite() {} | ~~~~~~~~~~~~~~~~ error: manually checking if a float is infinite - --> tests/ui/manual_float_methods.rs:28:8 + --> tests/ui/manual_float_methods.rs:27:8 | LL | if x == f64::INFINITY || x == f64::NEG_INFINITY {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the dedicated method instead: `x.is_infinite()` error: manually checking if a float is finite - --> tests/ui/manual_float_methods.rs:29:8 + --> tests/ui/manual_float_methods.rs:28:8 | LL | if x != f64::INFINITY && x != f64::NEG_INFINITY {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/never_loop.rs b/src/tools/clippy/tests/ui/never_loop.rs index 92f173d9db4a..93c69209c698 100644 --- a/src/tools/clippy/tests/ui/never_loop.rs +++ b/src/tools/clippy/tests/ui/never_loop.rs @@ -1,4 +1,4 @@ -#![feature(inline_const, try_blocks)] +#![feature(try_blocks)] #![allow( clippy::eq_op, clippy::single_match, diff --git a/src/tools/clippy/tests/ui/panicking_macros.rs b/src/tools/clippy/tests/ui/panicking_macros.rs index dccfbd409e50..2bbf5792ec4c 100644 --- a/src/tools/clippy/tests/ui/panicking_macros.rs +++ b/src/tools/clippy/tests/ui/panicking_macros.rs @@ -1,5 +1,4 @@ #![allow(clippy::assertions_on_constants, clippy::eq_op, clippy::let_unit_value)] -#![feature(inline_const)] #![warn(clippy::unimplemented, clippy::unreachable, clippy::todo, clippy::panic)] extern crate core; diff --git a/src/tools/clippy/tests/ui/panicking_macros.stderr b/src/tools/clippy/tests/ui/panicking_macros.stderr index 06025859c0c6..7c0f0a7d3764 100644 --- a/src/tools/clippy/tests/ui/panicking_macros.stderr +++ b/src/tools/clippy/tests/ui/panicking_macros.stderr @@ -1,5 +1,5 @@ error: `panic` should not be present in production code - --> tests/ui/panicking_macros.rs:23:5 + --> tests/ui/panicking_macros.rs:22:5 | LL | panic!(); | ^^^^^^^^ @@ -8,19 +8,19 @@ LL | panic!(); = help: to override `-D warnings` add `#[allow(clippy::panic)]` error: `panic` should not be present in production code - --> tests/ui/panicking_macros.rs:26:5 + --> tests/ui/panicking_macros.rs:25:5 | LL | panic!("message"); | ^^^^^^^^^^^^^^^^^ error: `panic` should not be present in production code - --> tests/ui/panicking_macros.rs:28:5 + --> tests/ui/panicking_macros.rs:27:5 | LL | panic!("{} {}", "panic with", "multiple arguments"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `todo` should not be present in production code - --> tests/ui/panicking_macros.rs:35:5 + --> tests/ui/panicking_macros.rs:34:5 | LL | todo!(); | ^^^^^^^ @@ -29,19 +29,19 @@ LL | todo!(); = help: to override `-D warnings` add `#[allow(clippy::todo)]` error: `todo` should not be present in production code - --> tests/ui/panicking_macros.rs:38:5 + --> tests/ui/panicking_macros.rs:37:5 | LL | todo!("message"); | ^^^^^^^^^^^^^^^^ error: `todo` should not be present in production code - --> tests/ui/panicking_macros.rs:40:5 + --> tests/ui/panicking_macros.rs:39:5 | LL | todo!("{} {}", "panic with", "multiple arguments"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `unimplemented` should not be present in production code - --> tests/ui/panicking_macros.rs:47:5 + --> tests/ui/panicking_macros.rs:46:5 | LL | unimplemented!(); | ^^^^^^^^^^^^^^^^ @@ -50,19 +50,19 @@ LL | unimplemented!(); = help: to override `-D warnings` add `#[allow(clippy::unimplemented)]` error: `unimplemented` should not be present in production code - --> tests/ui/panicking_macros.rs:50:5 + --> tests/ui/panicking_macros.rs:49:5 | LL | unimplemented!("message"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: `unimplemented` should not be present in production code - --> tests/ui/panicking_macros.rs:52:5 + --> tests/ui/panicking_macros.rs:51:5 | LL | unimplemented!("{} {}", "panic with", "multiple arguments"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: usage of the `unreachable!` macro - --> tests/ui/panicking_macros.rs:59:5 + --> tests/ui/panicking_macros.rs:58:5 | LL | unreachable!(); | ^^^^^^^^^^^^^^ @@ -71,37 +71,37 @@ LL | unreachable!(); = help: to override `-D warnings` add `#[allow(clippy::unreachable)]` error: usage of the `unreachable!` macro - --> tests/ui/panicking_macros.rs:62:5 + --> tests/ui/panicking_macros.rs:61:5 | LL | unreachable!("message"); | ^^^^^^^^^^^^^^^^^^^^^^^ error: usage of the `unreachable!` macro - --> tests/ui/panicking_macros.rs:64:5 + --> tests/ui/panicking_macros.rs:63:5 | LL | unreachable!("{} {}", "panic with", "multiple arguments"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `panic` should not be present in production code - --> tests/ui/panicking_macros.rs:71:5 + --> tests/ui/panicking_macros.rs:70:5 | LL | panic!(); | ^^^^^^^^ error: `todo` should not be present in production code - --> tests/ui/panicking_macros.rs:73:5 + --> tests/ui/panicking_macros.rs:72:5 | LL | todo!(); | ^^^^^^^ error: `unimplemented` should not be present in production code - --> tests/ui/panicking_macros.rs:75:5 + --> tests/ui/panicking_macros.rs:74:5 | LL | unimplemented!(); | ^^^^^^^^^^^^^^^^ error: usage of the `unreachable!` macro - --> tests/ui/panicking_macros.rs:77:5 + --> tests/ui/panicking_macros.rs:76:5 | LL | unreachable!(); | ^^^^^^^^^^^^^^ From f8a1cad07c71d96c25ec578c0e88a4e22f0a2f39 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Sat, 20 Apr 2024 20:35:04 +0100 Subject: [PATCH 28/36] Add `cfg_attr(bootstrap)` to doc tests --- library/core/src/sync/atomic.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 7b5dfa00e46d..073459fcb003 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -512,6 +512,7 @@ impl AtomicBool { /// /// ``` /// #![feature(atomic_from_mut)] + /// # #![cfg_attr(bootstrap, feature(inline_const))] /// use std::sync::atomic::{AtomicBool, Ordering}; /// /// let mut some_bools = [const { AtomicBool::new(false) }; 10]; @@ -1314,6 +1315,7 @@ impl AtomicPtr { /// /// ``` /// #![feature(atomic_from_mut)] + /// # #![cfg_attr(bootstrap, feature(inline_const))] /// use std::ptr::null_mut; /// use std::sync::atomic::{AtomicPtr, Ordering}; /// @@ -2304,6 +2306,7 @@ macro_rules! atomic_int { /// /// ``` /// #![feature(atomic_from_mut)] + /// # #![cfg_attr(bootstrap, feature(inline_const))] #[doc = concat!($extra_feature, "use std::sync::atomic::{", stringify!($atomic_type), ", Ordering};")] /// #[doc = concat!("let mut some_ints = [const { ", stringify!($atomic_type), "::new(0) }; 10];")] From 8169c4c121f64fa456126d547b4a0d846bd53de2 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Sat, 20 Apr 2024 22:28:02 +0100 Subject: [PATCH 29/36] Fix miri test --- src/tools/miri/tests/pass/portable-simd.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/tests/pass/portable-simd.rs b/src/tools/miri/tests/pass/portable-simd.rs index cdb441b450b3..1fc713d48dcc 100644 --- a/src/tools/miri/tests/pass/portable-simd.rs +++ b/src/tools/miri/tests/pass/portable-simd.rs @@ -1,5 +1,5 @@ //@compile-flags: -Zmiri-strict-provenance -#![feature(portable_simd, adt_const_params, inline_const, core_intrinsics)] +#![feature(portable_simd, adt_const_params, core_intrinsics)] #![allow(incomplete_features, internal_features)] use std::intrinsics::simd as intrinsics; use std::ptr; From 153b1f0421ec0da1d504fa9505acad35503db2ee Mon Sep 17 00:00:00 2001 From: Urgau Date: Wed, 24 Apr 2024 15:34:57 +0200 Subject: [PATCH 30/36] Improve diagnostic for unknown --print request --- compiler/rustc_session/src/config.rs | 9 ++++++--- src/tools/tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/valid-print-requests/Makefile | 4 ---- .../valid-print-requests/valid-print-requests.stderr | 2 -- tests/ui/invalid-compile-flags/print.rs | 1 + tests/ui/invalid-compile-flags/print.stderr | 4 ++++ 6 files changed, 11 insertions(+), 10 deletions(-) delete mode 100644 tests/run-make/valid-print-requests/Makefile delete mode 100644 tests/run-make/valid-print-requests/valid-print-requests.stderr create mode 100644 tests/ui/invalid-compile-flags/print.rs create mode 100644 tests/ui/invalid-compile-flags/print.stderr diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index d5b22f841d27..c5ca16ba7441 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1888,9 +1888,12 @@ fn collect_print_requests( let prints = PRINT_KINDS.iter().map(|(name, _)| format!("`{name}`")).collect::>(); let prints = prints.join(", "); - early_dcx.early_fatal(format!( - "unknown print request `{req}`. Valid print requests are: {prints}" - )); + + let mut diag = + early_dcx.early_struct_fatal(format!("unknown print request: `{req}`")); + #[allow(rustc::diagnostic_outside_of_impl)] + diag.help(format!("valid print requests are: {prints}")); + diag.emit() } }; diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index f0ed0ae806fd..93188b4fbaeb 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -317,7 +317,6 @@ run-make/unstable-flag-required/Makefile run-make/use-suggestions-rust-2018/Makefile run-make/used-cdylib-macos/Makefile run-make/used/Makefile -run-make/valid-print-requests/Makefile run-make/volatile-intrinsics/Makefile run-make/wasm-exceptions-nostd/Makefile run-make/wasm-override-linker/Makefile diff --git a/tests/run-make/valid-print-requests/Makefile b/tests/run-make/valid-print-requests/Makefile deleted file mode 100644 index 99430e98d1c2..000000000000 --- a/tests/run-make/valid-print-requests/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -include ../tools.mk - -all: - $(RUSTC) --print uwu 2>&1 | diff - valid-print-requests.stderr diff --git a/tests/run-make/valid-print-requests/valid-print-requests.stderr b/tests/run-make/valid-print-requests/valid-print-requests.stderr deleted file mode 100644 index 22bb102f9c98..000000000000 --- a/tests/run-make/valid-print-requests/valid-print-requests.stderr +++ /dev/null @@ -1,2 +0,0 @@ -error: unknown print request `uwu`. Valid print requests are: `all-target-specs-json`, `calling-conventions`, `cfg`, `code-models`, `crate-name`, `deployment-target`, `file-names`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `tls-models` - diff --git a/tests/ui/invalid-compile-flags/print.rs b/tests/ui/invalid-compile-flags/print.rs new file mode 100644 index 000000000000..0d0a9d22750d --- /dev/null +++ b/tests/ui/invalid-compile-flags/print.rs @@ -0,0 +1 @@ +//@ compile-flags: --print yyyy diff --git a/tests/ui/invalid-compile-flags/print.stderr b/tests/ui/invalid-compile-flags/print.stderr new file mode 100644 index 000000000000..0a032aabdfe8 --- /dev/null +++ b/tests/ui/invalid-compile-flags/print.stderr @@ -0,0 +1,4 @@ +error: unknown print request: `yyyy` + | + = help: valid print requests are: `all-target-specs-json`, `calling-conventions`, `cfg`, `code-models`, `crate-name`, `deployment-target`, `file-names`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `tls-models` + From 21906002ed01067d4257660696f92b205c72a882 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 24 Apr 2024 13:54:41 +0000 Subject: [PATCH 31/36] Strengthen tracking issue policy with consequences --- .github/ISSUE_TEMPLATE/tracking_issue.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/tracking_issue.md b/.github/ISSUE_TEMPLATE/tracking_issue.md index 5f17f30b3b0b..598628936112 100644 --- a/.github/ISSUE_TEMPLATE/tracking_issue.md +++ b/.github/ISSUE_TEMPLATE/tracking_issue.md @@ -28,6 +28,8 @@ Tracking issues are used to record the overall progress of implementation. They are also used as hubs connecting to other relevant issues, e.g., bugs or open design questions. A tracking issue is however *not* meant for large scale discussion, questions, or bug reports about a feature. Instead, open a dedicated issue for the specific matter and add the relevant feature gate label. +Discussion comments will get marked as off-topic or deleted. +Repeated discussions on the tracking issue may lead to the tracking issue getting locked. ### Steps $DIR/suggest-return-closure.rs:23:9 | LL | let x = String::new(); | - binding `x` declared here ... LL | |c| { | --- value captured here LL | x.push(c); | ^ borrowed value does not live long enough ... LL | } | -- borrow later used here | | | `x` dropped here while still borrowed ``` Suggest cloning in more cases involving closures: ``` error[E0507]: cannot move out of `foo` in pattern guard --> $DIR/issue-27282-move-ref-mut-into-guard.rs:11:19 | LL | if { (|| { let mut bar = foo; bar.take() })(); false } => {}, | ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait | | | `foo` is moved here | = note: variables bound in patterns cannot be moved from until after the end of the pattern guard help: consider cloning the value if the performance cost is acceptable | LL | if { (|| { let mut bar = foo.clone(); bar.take() })(); false } => {}, | ++++++++ ``` --- .../src/diagnostics/conflict_errors.rs | 6 +- .../src/diagnostics/explain_borrow.rs | 2 +- .../src/traits/error_reporting/mod.rs | 11 +++- .../src/traits/error_reporting/suggestions.rs | 6 +- .../error_reporting/type_err_ctxt_ext.rs | 2 +- tests/ui/coroutine/borrowing.stderr | 2 + tests/ui/coroutine/dropck.stderr | 3 + tests/ui/fn/suggest-return-closure.rs | 1 + tests/ui/fn/suggest-return-closure.stderr | 9 ++- tests/ui/nll/closure-borrow-spans.stderr | 6 ++ .../escape-upvar-nested.stderr | 3 + .../escape-upvar-ref.stderr | 2 + .../propagate-multiple-requirements.stderr | 2 + .../issue-27282-move-ref-mut-into-guard.fixed | 23 +++++++ .../issue-27282-move-ref-mut-into-guard.rs | 6 +- ...issue-27282-move-ref-mut-into-guard.stderr | 16 +++-- .../nll/issue-27282-mutation-in-guard.stderr | 8 +++ ...-42574-diagnostic-in-nested-closure.stderr | 2 + tests/ui/nll/match-guards-always-borrow.fixed | 66 +++++++++++++++++++ tests/ui/nll/match-guards-always-borrow.rs | 6 +- .../ui/nll/match-guards-always-borrow.stderr | 20 ++++-- ...insensitive-scopes-issue-117146.nll.stderr | 2 + ...sitive-scopes-issue-117146.polonius.stderr | 2 + .../nll/user-annotations/method-ufcs-1.stderr | 4 +- .../nll/user-annotations/method-ufcs-2.stderr | 4 +- .../regions/regions-addr-of-upvar-self.stderr | 2 + tests/ui/regions/regions-nested-fns-2.stderr | 3 + tests/ui/regions/regions-nested-fns.stderr | 3 + tests/ui/regions/regions-steal-closure.stderr | 1 + .../send-is-not-static-ensures-scoping.stderr | 3 + ...oxed-closures-failed-recursive-fn-1.stderr | 7 +- 31 files changed, 202 insertions(+), 31 deletions(-) create mode 100644 tests/ui/nll/issue-27282-move-ref-mut-into-guard.fixed create mode 100644 tests/ui/nll/match-guards-always-borrow.fixed diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 4878da530b0f..ed8c9bd51cfe 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1964,7 +1964,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { pub(crate) fn find_expr(&self, span: Span) -> Option<&hir::Expr<'_>> { let tcx = self.infcx.tcx; let body_id = tcx.hir_node(self.mir_hir_id()).body_id()?; - let mut expr_finder = FindExprBySpan::new(span); + let mut expr_finder = FindExprBySpan::new(span, tcx); expr_finder.visit_expr(tcx.hir().body(body_id).value); expr_finder.result } @@ -1998,14 +1998,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { }; let mut expr_finder = - FindExprBySpan::new(self.body.local_decls[*index1].source_info.span); + FindExprBySpan::new(self.body.local_decls[*index1].source_info.span, tcx); expr_finder.visit_expr(hir.body(body_id).value); let Some(index1) = expr_finder.result else { note_default_suggestion(); return; }; - expr_finder = FindExprBySpan::new(self.body.local_decls[*index2].source_info.span); + expr_finder = FindExprBySpan::new(self.body.local_decls[*index2].source_info.span, tcx); expr_finder.visit_expr(hir.body(body_id).value); let Some(index2) = expr_finder.result else { note_default_suggestion(); diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 418eabe3ae24..5ebdb69050b2 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -76,7 +76,7 @@ impl<'tcx> BorrowExplanation<'tcx> { && let Some(body_id) = node.body_id() { let body = tcx.hir().body(body_id); - let mut expr_finder = FindExprBySpan::new(span); + let mut expr_finder = FindExprBySpan::new(span, tcx); expr_finder.visit_expr(body.value); if let Some(mut expr) = expr_finder.result { while let hir::ExprKind::AddrOf(_, _, inner) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 837b784f2725..4731f11ad323 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -50,15 +50,22 @@ pub struct FindExprBySpan<'hir> { pub span: Span, pub result: Option<&'hir hir::Expr<'hir>>, pub ty_result: Option<&'hir hir::Ty<'hir>>, + pub tcx: TyCtxt<'hir>, } impl<'hir> FindExprBySpan<'hir> { - pub fn new(span: Span) -> Self { - Self { span, result: None, ty_result: None } + pub fn new(span: Span, tcx: TyCtxt<'hir>) -> Self { + Self { span, result: None, ty_result: None, tcx } } } impl<'v> Visitor<'v> for FindExprBySpan<'v> { + type NestedFilter = rustc_middle::hir::nested_filter::OnlyBodies; + + fn nested_visit_map(&mut self) -> Self::Map { + self.tcx.hir() + } + fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) { if self.span == ex.span { self.result = Some(ex); diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 9d3caaa01abd..cc879c42ce95 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -901,7 +901,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { // Remove all the desugaring and macro contexts. span.remove_mark(); } - let mut expr_finder = FindExprBySpan::new(span); + let mut expr_finder = FindExprBySpan::new(span, self.tcx); let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) else { return; }; @@ -1367,7 +1367,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { return false; }; let body = self.tcx.hir().body(body_id); - let mut expr_finder = FindExprBySpan::new(span); + let mut expr_finder = FindExprBySpan::new(span, self.tcx); expr_finder.visit_expr(body.value); let Some(expr) = expr_finder.result else { return false; @@ -1469,7 +1469,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { // Remove all the hir desugaring contexts while maintaining the macro contexts. span.remove_mark(); } - let mut expr_finder = super::FindExprBySpan::new(span); + let mut expr_finder = super::FindExprBySpan::new(span, self.tcx); let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) else { return false; }; diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 0e309689680a..1971136e54c7 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -2457,7 +2457,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { && let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) { - let mut expr_finder = FindExprBySpan::new(span); + let mut expr_finder = FindExprBySpan::new(span, self.tcx); expr_finder.visit_expr(self.tcx.hir().body(body_id).value); if let Some(hir::Expr { diff --git a/tests/ui/coroutine/borrowing.stderr b/tests/ui/coroutine/borrowing.stderr index 9132e5d84edd..4f8b97377777 100644 --- a/tests/ui/coroutine/borrowing.stderr +++ b/tests/ui/coroutine/borrowing.stderr @@ -4,6 +4,7 @@ error[E0597]: `a` does not live long enough LL | let _b = { | -- borrow later stored here LL | let a = 3; + | - binding `a` declared here LL | Pin::new(&mut #[coroutine] || yield &a).resume(()) | -- ^ borrowed value does not live long enough | | @@ -18,6 +19,7 @@ error[E0597]: `a` does not live long enough LL | let _b = { | -- borrow later stored here LL | let a = 3; + | - binding `a` declared here LL | #[coroutine] || { | -- value captured here by coroutine LL | yield &a diff --git a/tests/ui/coroutine/dropck.stderr b/tests/ui/coroutine/dropck.stderr index d6cd7c4cd47a..78fdeec972f7 100644 --- a/tests/ui/coroutine/dropck.stderr +++ b/tests/ui/coroutine/dropck.stderr @@ -18,6 +18,9 @@ LL | } error[E0597]: `ref_` does not live long enough --> $DIR/dropck.rs:16:18 | +LL | let ref_ = Box::leak(Box::new(Some(cell.borrow_mut()))); + | ---- binding `ref_` declared here +... LL | || { | -- value captured here by coroutine LL | // but the coroutine can use it to drop a `Ref<'a, i32>`. diff --git a/tests/ui/fn/suggest-return-closure.rs b/tests/ui/fn/suggest-return-closure.rs index 81f202728679..30e25ca8edcc 100644 --- a/tests/ui/fn/suggest-return-closure.rs +++ b/tests/ui/fn/suggest-return-closure.rs @@ -18,6 +18,7 @@ fn fn_mut() -> _ { //~| NOTE for more information on `Fn` traits and closure types let x = String::new(); //~^ HELP: consider changing this to be mutable + //~| NOTE binding `x` declared here |c| { //~ NOTE: value captured here x.push(c); //~^ ERROR: does not live long enough diff --git a/tests/ui/fn/suggest-return-closure.stderr b/tests/ui/fn/suggest-return-closure.stderr index 8e80a11fe1b0..d276ce8be2ba 100644 --- a/tests/ui/fn/suggest-return-closure.stderr +++ b/tests/ui/fn/suggest-return-closure.stderr @@ -21,7 +21,7 @@ LL | fn fn_mut() -> _ { = note: for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types - --> $DIR/suggest-return-closure.rs:31:13 + --> $DIR/suggest-return-closure.rs:32:13 | LL | fn fun() -> _ { | ^ @@ -32,7 +32,7 @@ LL | fn fun() -> _ { = note: for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable - --> $DIR/suggest-return-closure.rs:22:9 + --> $DIR/suggest-return-closure.rs:23:9 | LL | let x = String::new(); | - help: consider changing this to be mutable: `mut x` @@ -41,8 +41,11 @@ LL | x.push(c); | ^ cannot borrow as mutable error[E0597]: `x` does not live long enough - --> $DIR/suggest-return-closure.rs:22:9 + --> $DIR/suggest-return-closure.rs:23:9 | +LL | let x = String::new(); + | - binding `x` declared here +... LL | |c| { | --- value captured here LL | x.push(c); diff --git a/tests/ui/nll/closure-borrow-spans.stderr b/tests/ui/nll/closure-borrow-spans.stderr index cac22c2ecda4..c466cad25d2e 100644 --- a/tests/ui/nll/closure-borrow-spans.stderr +++ b/tests/ui/nll/closure-borrow-spans.stderr @@ -25,6 +25,8 @@ LL | f.use_ref(); error[E0597]: `x` does not live long enough --> $DIR/closure-borrow-spans.rs:19:16 | +LL | let x = 1; + | - binding `x` declared here LL | f = || x; | -- ^ borrowed value does not live long enough | | @@ -85,6 +87,8 @@ LL | f.use_ref(); error[E0597]: `x` does not live long enough --> $DIR/closure-borrow-spans.rs:52:16 | +LL | let mut x = 1; + | ----- binding `x` declared here LL | f = || x = 0; | -- ^ borrowed value does not live long enough | | @@ -145,6 +149,8 @@ LL | f.use_ref(); error[E0597]: `x` does not live long enough --> $DIR/closure-borrow-spans.rs:86:16 | +LL | let x = &mut z; + | - binding `x` declared here LL | f = || *x = 0; | -- ^^ borrowed value does not live long enough | | diff --git a/tests/ui/nll/closure-requirements/escape-upvar-nested.stderr b/tests/ui/nll/closure-requirements/escape-upvar-nested.stderr index aa73e91cc77e..8e47ab780f21 100644 --- a/tests/ui/nll/closure-requirements/escape-upvar-nested.stderr +++ b/tests/ui/nll/closure-requirements/escape-upvar-nested.stderr @@ -37,6 +37,9 @@ LL | fn test() { error[E0597]: `y` does not live long enough --> $DIR/escape-upvar-nested.rs:21:40 | +LL | let y = 22; + | - binding `y` declared here +LL | LL | let mut closure = || { | -- value captured here LL | let mut closure1 = || p = &y; diff --git a/tests/ui/nll/closure-requirements/escape-upvar-ref.stderr b/tests/ui/nll/closure-requirements/escape-upvar-ref.stderr index 949dcc78703a..c428150aa2f4 100644 --- a/tests/ui/nll/closure-requirements/escape-upvar-ref.stderr +++ b/tests/ui/nll/closure-requirements/escape-upvar-ref.stderr @@ -23,6 +23,8 @@ LL | fn test() { error[E0597]: `y` does not live long enough --> $DIR/escape-upvar-ref.rs:23:35 | +LL | let y = 22; + | - binding `y` declared here LL | let mut closure = || p = &y; | -- ^ borrowed value does not live long enough | | diff --git a/tests/ui/nll/closure-requirements/propagate-multiple-requirements.stderr b/tests/ui/nll/closure-requirements/propagate-multiple-requirements.stderr index 81b5f09b0415..15f48d88c379 100644 --- a/tests/ui/nll/closure-requirements/propagate-multiple-requirements.stderr +++ b/tests/ui/nll/closure-requirements/propagate-multiple-requirements.stderr @@ -1,6 +1,8 @@ error[E0597]: `local_arr` does not live long enough --> $DIR/propagate-multiple-requirements.rs:15:14 | +LL | let local_arr = other_local_arr; + | --------- binding `local_arr` declared here LL | let mut out: &mut &'static [i32] = &mut (&[1] as _); | ------------------- type annotation requires that `local_arr` is borrowed for `'static` LL | once(|mut z: &[i32], mut out_val: &mut &[i32]| { diff --git a/tests/ui/nll/issue-27282-move-ref-mut-into-guard.fixed b/tests/ui/nll/issue-27282-move-ref-mut-into-guard.fixed new file mode 100644 index 000000000000..7692be7ccc80 --- /dev/null +++ b/tests/ui/nll/issue-27282-move-ref-mut-into-guard.fixed @@ -0,0 +1,23 @@ +// Issue 27282: Example 1: This sidesteps the AST checks disallowing +// mutable borrows in match guards by hiding the mutable borrow in a +// guard behind a move (of the ref mut pattern id) within a closure. +//@ run-rustfix +#![feature(if_let_guard)] + +fn main() { + match Some(&4) { + None => {}, + ref mut foo + if { (|| { let mut bar = foo.clone(); bar.take() })(); false } => {}, + //~^ ERROR cannot move out of `foo` in pattern guard [E0507] + Some(s) => std::process::exit(*s), + } + + match Some(&4) { + None => {}, + ref mut foo + if let Some(()) = { (|| { let mut bar = foo.clone(); bar.take() })(); None } => {}, + //~^ ERROR cannot move out of `foo` in pattern guard [E0507] + Some(s) => std::process::exit(*s), + } +} diff --git a/tests/ui/nll/issue-27282-move-ref-mut-into-guard.rs b/tests/ui/nll/issue-27282-move-ref-mut-into-guard.rs index 833ca8afd618..f3d0a184e03c 100644 --- a/tests/ui/nll/issue-27282-move-ref-mut-into-guard.rs +++ b/tests/ui/nll/issue-27282-move-ref-mut-into-guard.rs @@ -1,14 +1,14 @@ // Issue 27282: Example 1: This sidesteps the AST checks disallowing // mutable borrows in match guards by hiding the mutable borrow in a // guard behind a move (of the ref mut pattern id) within a closure. - +//@ run-rustfix #![feature(if_let_guard)] fn main() { match Some(&4) { None => {}, ref mut foo - if { (|| { let bar = foo; bar.take() })(); false } => {}, + if { (|| { let mut bar = foo; bar.take() })(); false } => {}, //~^ ERROR cannot move out of `foo` in pattern guard [E0507] Some(s) => std::process::exit(*s), } @@ -16,7 +16,7 @@ fn main() { match Some(&4) { None => {}, ref mut foo - if let Some(()) = { (|| { let bar = foo; bar.take() })(); None } => {}, + if let Some(()) = { (|| { let mut bar = foo; bar.take() })(); None } => {}, //~^ ERROR cannot move out of `foo` in pattern guard [E0507] Some(s) => std::process::exit(*s), } diff --git a/tests/ui/nll/issue-27282-move-ref-mut-into-guard.stderr b/tests/ui/nll/issue-27282-move-ref-mut-into-guard.stderr index 4a512560c875..7781e77894b8 100644 --- a/tests/ui/nll/issue-27282-move-ref-mut-into-guard.stderr +++ b/tests/ui/nll/issue-27282-move-ref-mut-into-guard.stderr @@ -1,22 +1,30 @@ error[E0507]: cannot move out of `foo` in pattern guard --> $DIR/issue-27282-move-ref-mut-into-guard.rs:11:19 | -LL | if { (|| { let bar = foo; bar.take() })(); false } => {}, - | ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait +LL | if { (|| { let mut bar = foo; bar.take() })(); false } => {}, + | ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait | | | `foo` is moved here | = note: variables bound in patterns cannot be moved from until after the end of the pattern guard +help: consider cloning the value if the performance cost is acceptable + | +LL | if { (|| { let mut bar = foo.clone(); bar.take() })(); false } => {}, + | ++++++++ error[E0507]: cannot move out of `foo` in pattern guard --> $DIR/issue-27282-move-ref-mut-into-guard.rs:19:34 | -LL | if let Some(()) = { (|| { let bar = foo; bar.take() })(); None } => {}, - | ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait +LL | if let Some(()) = { (|| { let mut bar = foo; bar.take() })(); None } => {}, + | ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait | | | `foo` is moved here | = note: variables bound in patterns cannot be moved from until after the end of the pattern guard +help: consider cloning the value if the performance cost is acceptable + | +LL | if let Some(()) = { (|| { let mut bar = foo.clone(); bar.take() })(); None } => {}, + | ++++++++ error: aborting due to 2 previous errors diff --git a/tests/ui/nll/issue-27282-mutation-in-guard.stderr b/tests/ui/nll/issue-27282-mutation-in-guard.stderr index 0b5d723172c7..f73e4aaa489a 100644 --- a/tests/ui/nll/issue-27282-mutation-in-guard.stderr +++ b/tests/ui/nll/issue-27282-mutation-in-guard.stderr @@ -7,6 +7,10 @@ LL | (|| { let bar = foo; bar.take() })(); | `foo` is moved here | = note: variables bound in patterns cannot be moved from until after the end of the pattern guard +help: consider cloning the value if the performance cost is acceptable + | +LL | (|| { let bar = foo.clone(); bar.take() })(); + | ++++++++ error[E0507]: cannot move out of `foo` in pattern guard --> $DIR/issue-27282-mutation-in-guard.rs:20:18 @@ -17,6 +21,10 @@ LL | (|| { let bar = foo; bar.take() })(); | `foo` is moved here | = note: variables bound in patterns cannot be moved from until after the end of the pattern guard +help: consider cloning the value if the performance cost is acceptable + | +LL | (|| { let bar = foo.clone(); bar.take() })(); + | ++++++++ error: aborting due to 2 previous errors diff --git a/tests/ui/nll/issue-42574-diagnostic-in-nested-closure.stderr b/tests/ui/nll/issue-42574-diagnostic-in-nested-closure.stderr index f7a525ee9b04..e3f44467550c 100644 --- a/tests/ui/nll/issue-42574-diagnostic-in-nested-closure.stderr +++ b/tests/ui/nll/issue-42574-diagnostic-in-nested-closure.stderr @@ -11,6 +11,8 @@ LL | || doit(data); error[E0597]: `data` does not live long enough --> $DIR/issue-42574-diagnostic-in-nested-closure.rs:6:13 | +LL | fn doit(data: &'static mut ()) { + | ---- binding `data` declared here LL | || doit(data); | -- -----^^^^- | | | | diff --git a/tests/ui/nll/match-guards-always-borrow.fixed b/tests/ui/nll/match-guards-always-borrow.fixed new file mode 100644 index 000000000000..56e743bf196a --- /dev/null +++ b/tests/ui/nll/match-guards-always-borrow.fixed @@ -0,0 +1,66 @@ +#![feature(if_let_guard)] +#![allow(unused_mut)] +//@ run-rustfix + +// Here is arielb1's basic example from rust-lang/rust#27282 +// that AST borrowck is flummoxed by: + +fn should_reject_destructive_mutate_in_guard() { + match Some(&4) { + None => {}, + ref mut foo if { + (|| { let mut bar = foo.clone(); bar.take() })(); + //~^ ERROR cannot move out of `foo` in pattern guard [E0507] + false } => { }, + Some(s) => std::process::exit(*s), + } + + match Some(&4) { + None => {}, + ref mut foo if let Some(()) = { + (|| { let mut bar = foo.clone(); bar.take() })(); + //~^ ERROR cannot move out of `foo` in pattern guard [E0507] + None } => { }, + Some(s) => std::process::exit(*s), + } +} + +// Here below is a case that needs to keep working: we only use the +// binding via immutable-borrow in the guard, and we mutate in the arm +// body. +fn allow_mutate_in_arm_body() { + match Some(&4) { + None => {}, + ref mut foo if foo.is_some() => { foo.take(); () } + Some(s) => std::process::exit(*s), + } + + match Some(&4) { + None => {}, + ref mut foo if let Some(_) = foo => { foo.take(); () } + Some(s) => std::process::exit(*s), + } +} + +// Here below is a case that needs to keep working: we only use the +// binding via immutable-borrow in the guard, and we move into the arm +// body. +fn allow_move_into_arm_body() { + match Some(&4) { + None => {}, + mut foo if foo.is_some() => { foo.unwrap(); () } + Some(s) => std::process::exit(*s), + } + + match Some(&4) { + None => {}, + mut foo if let Some(_) = foo => { foo.unwrap(); () } + Some(s) => std::process::exit(*s), + } +} + +fn main() { + should_reject_destructive_mutate_in_guard(); + allow_mutate_in_arm_body(); + allow_move_into_arm_body(); +} diff --git a/tests/ui/nll/match-guards-always-borrow.rs b/tests/ui/nll/match-guards-always-borrow.rs index ff63cc092734..927d55c42a6e 100644 --- a/tests/ui/nll/match-guards-always-borrow.rs +++ b/tests/ui/nll/match-guards-always-borrow.rs @@ -1,4 +1,6 @@ #![feature(if_let_guard)] +#![allow(unused_mut)] +//@ run-rustfix // Here is arielb1's basic example from rust-lang/rust#27282 // that AST borrowck is flummoxed by: @@ -7,7 +9,7 @@ fn should_reject_destructive_mutate_in_guard() { match Some(&4) { None => {}, ref mut foo if { - (|| { let bar = foo; bar.take() })(); + (|| { let mut bar = foo; bar.take() })(); //~^ ERROR cannot move out of `foo` in pattern guard [E0507] false } => { }, Some(s) => std::process::exit(*s), @@ -16,7 +18,7 @@ fn should_reject_destructive_mutate_in_guard() { match Some(&4) { None => {}, ref mut foo if let Some(()) = { - (|| { let bar = foo; bar.take() })(); + (|| { let mut bar = foo; bar.take() })(); //~^ ERROR cannot move out of `foo` in pattern guard [E0507] None } => { }, Some(s) => std::process::exit(*s), diff --git a/tests/ui/nll/match-guards-always-borrow.stderr b/tests/ui/nll/match-guards-always-borrow.stderr index afd853c403ee..bb0c5bd4c976 100644 --- a/tests/ui/nll/match-guards-always-borrow.stderr +++ b/tests/ui/nll/match-guards-always-borrow.stderr @@ -1,22 +1,30 @@ error[E0507]: cannot move out of `foo` in pattern guard - --> $DIR/match-guards-always-borrow.rs:10:14 + --> $DIR/match-guards-always-borrow.rs:12:14 | -LL | (|| { let bar = foo; bar.take() })(); - | ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait +LL | (|| { let mut bar = foo; bar.take() })(); + | ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait | | | `foo` is moved here | = note: variables bound in patterns cannot be moved from until after the end of the pattern guard +help: consider cloning the value if the performance cost is acceptable + | +LL | (|| { let mut bar = foo.clone(); bar.take() })(); + | ++++++++ error[E0507]: cannot move out of `foo` in pattern guard - --> $DIR/match-guards-always-borrow.rs:19:14 + --> $DIR/match-guards-always-borrow.rs:21:14 | -LL | (|| { let bar = foo; bar.take() })(); - | ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait +LL | (|| { let mut bar = foo; bar.take() })(); + | ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait | | | `foo` is moved here | = note: variables bound in patterns cannot be moved from until after the end of the pattern guard +help: consider cloning the value if the performance cost is acceptable + | +LL | (|| { let mut bar = foo.clone(); bar.take() })(); + | ++++++++ error: aborting due to 2 previous errors diff --git a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr index 5227ca8ec17d..1d086c658dfc 100644 --- a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr +++ b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr @@ -1,6 +1,8 @@ error[E0597]: `a` does not live long enough --> $DIR/location-insensitive-scopes-issue-117146.rs:10:18 | +LL | let a = (); + | - binding `a` declared here LL | let b = |_| &a; | --- -^ | | || diff --git a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr index 5227ca8ec17d..1d086c658dfc 100644 --- a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr +++ b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr @@ -1,6 +1,8 @@ error[E0597]: `a` does not live long enough --> $DIR/location-insensitive-scopes-issue-117146.rs:10:18 | +LL | let a = (); + | - binding `a` declared here LL | let b = |_| &a; | --- -^ | | || diff --git a/tests/ui/nll/user-annotations/method-ufcs-1.stderr b/tests/ui/nll/user-annotations/method-ufcs-1.stderr index c7c08c948abd..c42ea0172cf7 100644 --- a/tests/ui/nll/user-annotations/method-ufcs-1.stderr +++ b/tests/ui/nll/user-annotations/method-ufcs-1.stderr @@ -33,7 +33,9 @@ error[E0597]: `a` does not live long enough | LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) { | -- lifetime `'a` defined here -... +LL | let a = 22; + | - binding `a` declared here +LL | let b = 44; LL | let _closure = || { | -- value captured here LL | let c = 66; diff --git a/tests/ui/nll/user-annotations/method-ufcs-2.stderr b/tests/ui/nll/user-annotations/method-ufcs-2.stderr index b7861a3bd069..287337c7d52d 100644 --- a/tests/ui/nll/user-annotations/method-ufcs-2.stderr +++ b/tests/ui/nll/user-annotations/method-ufcs-2.stderr @@ -34,7 +34,9 @@ error[E0597]: `b` does not live long enough | LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) { | -- lifetime `'a` defined here -... +LL | let a = 22; +LL | let b = 44; + | - binding `b` declared here LL | let _closure = || { | -- value captured here LL | let c = 66; diff --git a/tests/ui/regions/regions-addr-of-upvar-self.stderr b/tests/ui/regions/regions-addr-of-upvar-self.stderr index c16a6f8585b6..3a028cc9e211 100644 --- a/tests/ui/regions/regions-addr-of-upvar-self.stderr +++ b/tests/ui/regions/regions-addr-of-upvar-self.stderr @@ -20,6 +20,8 @@ LL | let p: &'static mut usize = &mut self.food; error[E0597]: `self` does not live long enough --> $DIR/regions-addr-of-upvar-self.rs:8:46 | +LL | pub fn chase_cat(&mut self) { + | --------- binding `self` declared here LL | let _f = || { | -- value captured here LL | let p: &'static mut usize = &mut self.food; diff --git a/tests/ui/regions/regions-nested-fns-2.stderr b/tests/ui/regions/regions-nested-fns-2.stderr index 254497639a17..02359fe1213d 100644 --- a/tests/ui/regions/regions-nested-fns-2.stderr +++ b/tests/ui/regions/regions-nested-fns-2.stderr @@ -1,6 +1,9 @@ error[E0597]: `y` does not live long enough --> $DIR/regions-nested-fns-2.rs:7:25 | +LL | let y = 3; + | - binding `y` declared here +LL | ignore( LL | |z| { | --- value captured here LL | if false { &y } else { z } diff --git a/tests/ui/regions/regions-nested-fns.stderr b/tests/ui/regions/regions-nested-fns.stderr index ee43f9fa5724..23b3f78dd4eb 100644 --- a/tests/ui/regions/regions-nested-fns.stderr +++ b/tests/ui/regions/regions-nested-fns.stderr @@ -27,6 +27,9 @@ LL | } error[E0597]: `y` does not live long enough --> $DIR/regions-nested-fns.rs:10:15 | +LL | let y = 3; + | - binding `y` declared here +... LL | ignore:: FnMut(&'z isize)>>(Box::new(|z| { | --- value captured here LL | ay = x; diff --git a/tests/ui/regions/regions-steal-closure.stderr b/tests/ui/regions/regions-steal-closure.stderr index 9324eb892a67..50068b32fa3a 100644 --- a/tests/ui/regions/regions-steal-closure.stderr +++ b/tests/ui/regions/regions-steal-closure.stderr @@ -4,6 +4,7 @@ error[E0597]: `i` does not live long enough LL | let mut cl_box = { | ---------- borrow later stored here LL | let mut i = 3; + | ----- binding `i` declared here LL | box_it(Box::new(|| i += 1)) | -- ^ borrowed value does not live long enough | | diff --git a/tests/ui/span/send-is-not-static-ensures-scoping.stderr b/tests/ui/span/send-is-not-static-ensures-scoping.stderr index bae0befcacaa..c15547e84125 100644 --- a/tests/ui/span/send-is-not-static-ensures-scoping.stderr +++ b/tests/ui/span/send-is-not-static-ensures-scoping.stderr @@ -16,6 +16,9 @@ error[E0597]: `y` does not live long enough | LL | let bad = { | --- borrow later stored here +LL | let x = 1; +LL | let y = &x; + | - binding `y` declared here ... LL | scoped(|| { | -- value captured here diff --git a/tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.stderr b/tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.stderr index 23aa18d7156a..fc6f610ddd4c 100644 --- a/tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.stderr +++ b/tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.stderr @@ -1,6 +1,9 @@ error[E0597]: `factorial` does not live long enough --> $DIR/unboxed-closures-failed-recursive-fn-1.rs:15:17 | +LL | let mut factorial: Option u32>> = None; + | ------------- binding `factorial` declared here +LL | LL | let f = |x: u32| -> u32 { | --------------- value captured here LL | let g = factorial.as_ref().unwrap(); @@ -30,7 +33,9 @@ error[E0597]: `factorial` does not live long enough --> $DIR/unboxed-closures-failed-recursive-fn-1.rs:28:17 | LL | let mut factorial: Option u32 + 'static>> = None; - | ----------------------------------------- type annotation requires that `factorial` is borrowed for `'static` + | ------------- ----------------------------------------- type annotation requires that `factorial` is borrowed for `'static` + | | + | binding `factorial` declared here LL | LL | let f = |x: u32| -> u32 { | --------------- value captured here From d68f2a6b71df3a4524c390f683dbd7a925ed207f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 18 Apr 2024 22:18:19 +0000 Subject: [PATCH 35/36] Mention when type parameter could be `Clone` ``` error[E0382]: use of moved value: `t` --> $DIR/use_of_moved_value_copy_suggestions.rs:7:9 | LL | fn duplicate_t(t: T) -> (T, T) { | - move occurs because `t` has type `T`, which does not implement the `Copy` trait ... LL | (t, t) | - ^ value used here after move | | | value moved here | help: if `T` implemented `Clone`, you could clone the value --> $DIR/use_of_moved_value_copy_suggestions.rs:4:16 | LL | fn duplicate_t(t: T) -> (T, T) { | ^ consider constraining this type parameter with `Clone` ... LL | (t, t) | - you could clone this value help: consider restricting type parameter `T` | LL | fn duplicate_t(t: T) -> (T, T) { | ++++++ ``` The `help` is new. On ADTs, we also extend the output with span labels: ``` error[E0507]: cannot move out of static item `FOO` --> $DIR/issue-17718-static-move.rs:6:14 | LL | let _a = FOO; | ^^^ move occurs because `FOO` has type `Foo`, which does not implement the `Copy` trait | note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/issue-17718-static-move.rs:1:1 | LL | struct Foo; | ^^^^^^^^^^ consider implementing `Clone` for this type ... LL | let _a = FOO; | --- you could clone this value help: consider borrowing here | LL | let _a = &FOO; | + ``` --- .../src/diagnostics/conflict_errors.rs | 47 +++++- .../src/diagnostics/move_errors.rs | 12 +- tests/ui/associated-types/issue-25700.stderr | 5 +- .../typeck-auto-trait-no-supertraits-2.stderr | 7 + tests/ui/binop/binop-consume-args.stderr | 140 ++++++++++++++++++ tests/ui/binop/binop-move-semantics.stderr | 41 +++++ .../borrowck-move-out-of-static-item.stderr | 5 +- .../borrowck-move-subcomponent.stderr | 5 +- .../borrowck/borrowck-overloaded-call.stderr | 5 +- tests/ui/borrowck/clone-on-ref.stderr | 12 +- tests/ui/borrowck/issue-101119.stderr | 5 +- tests/ui/borrowck/issue-103624.stderr | 5 +- .../issue-119915-bad-clone-suggestion.stderr | 5 +- .../borrowck/issue-17718-static-move.stderr | 5 +- tests/ui/borrowck/issue-20801.stderr | 20 ++- .../borrowck/move-error-in-promoted-2.stderr | 5 +- tests/ui/borrowck/move-error-snippets.stderr | 7 +- ...e-in-static-initializer-issue-38520.stderr | 10 +- tests/ui/box/leak-alloc.stderr | 5 +- .../derives/deriving-with-repr-packed.stderr | 5 +- tests/ui/error-codes/E0504.stderr | 5 +- tests/ui/error-codes/E0505.stderr | 5 +- tests/ui/error-codes/E0507.stderr | 5 +- tests/ui/error-codes/E0508-fail.stderr | 5 +- tests/ui/error-codes/E0508.stderr | 5 +- tests/ui/error-codes/E0509.stderr | 5 +- tests/ui/issues/issue-17385.stderr | 10 +- tests/ui/issues/issue-24357.rs | 2 + tests/ui/issues/issue-24357.stderr | 7 +- tests/ui/issues/issue-4335.stderr | 8 + tests/ui/mir/issue-102389.stderr | 5 +- .../moves/borrow-closures-instead-of-move.rs | 4 +- .../borrow-closures-instead-of-move.stderr | 16 ++ tests/ui/moves/issue-72649-uninit-in-loop.rs | 8 + .../moves/issue-72649-uninit-in-loop.stderr | 34 +++-- .../issue-75904-move-closure-loop.stderr | 5 +- tests/ui/moves/move-fn-self-receiver.stderr | 10 +- tests/ui/moves/move-out-of-array-1.stderr | 5 +- ...-on-type-no-recursive-stack-closure.stderr | 7 + .../use_of_moved_value_copy_suggestions.fixed | 4 +- .../use_of_moved_value_copy_suggestions.rs | 4 +- ...use_of_moved_value_copy_suggestions.stderr | 50 +++++-- .../issue-21232-partial-init-and-use.stderr | 10 +- tests/ui/nll/move-errors.stderr | 30 +++- .../borrowck-pat-ref-mut-and-ref.stderr | 10 +- tests/ui/suggestions/option-content-move3.rs | 17 +++ .../suggestions/option-content-move3.stderr | 35 +++++ .../union-borrow-move-parent-sibling.stderr | 5 +- tests/ui/union/union-move.stderr | 10 +- tests/ui/unop-move-semantics.stderr | 34 +++++ tests/ui/variance/variance-issue-20533.stderr | 15 +- 51 files changed, 640 insertions(+), 86 deletions(-) create mode 100644 tests/ui/suggestions/option-content-move3.rs create mode 100644 tests/ui/suggestions/option-content-move3.stderr diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index ed8c9bd51cfe..8215dc68c086 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -347,7 +347,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { mpi: MovePathIndex, err: &mut Diag<'tcx>, in_pattern: &mut bool, - move_spans: UseSpans<'_>, + move_spans: UseSpans<'tcx>, ) { let move_span = match move_spans { UseSpans::ClosureUse { capture_kind_span, .. } => capture_kind_span, @@ -491,11 +491,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { .. } = move_spans { - self.suggest_cloning(err, ty, expr, None); + self.suggest_cloning(err, ty, expr, None, Some(move_spans)); } else if self.suggest_hoisting_call_outside_loop(err, expr) { // The place where the the type moves would be misleading to suggest clone. // #121466 - self.suggest_cloning(err, ty, expr, None); + self.suggest_cloning(err, ty, expr, None, Some(move_spans)); } } if let Some(pat) = finder.pat { @@ -1085,6 +1085,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ty: Ty<'tcx>, mut expr: &'cx hir::Expr<'cx>, mut other_expr: Option<&'cx hir::Expr<'cx>>, + use_spans: Option>, ) { if let hir::ExprKind::Struct(_, _, Some(_)) = expr.kind { // We have `S { foo: val, ..base }`. In `check_aggregate_rvalue` we have a single @@ -1197,8 +1198,44 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { .all(|field| self.implements_clone(field.ty(self.infcx.tcx, args))) }) { + let ty_span = self.infcx.tcx.def_span(def.did()); + let mut span: MultiSpan = ty_span.into(); + span.push_span_label(ty_span, "consider implementing `Clone` for this type"); + span.push_span_label(expr.span, "you could clone this value"); err.span_note( - self.infcx.tcx.def_span(def.did()), + span, + format!("if `{ty}` implemented `Clone`, you could clone the value"), + ); + } else if let ty::Param(param) = ty.kind() + && let Some(_clone_trait_def) = self.infcx.tcx.lang_items().clone_trait() + && let generics = self.infcx.tcx.generics_of(self.mir_def_id()) + && let generic_param = generics.type_param(*param, self.infcx.tcx) + && let param_span = self.infcx.tcx.def_span(generic_param.def_id) + && if let Some(UseSpans::FnSelfUse { kind, .. }) = use_spans + && let CallKind::FnCall { fn_trait_id, self_ty } = kind + && let ty::Param(_) = self_ty.kind() + && ty == self_ty + && [ + self.infcx.tcx.lang_items().fn_once_trait(), + self.infcx.tcx.lang_items().fn_mut_trait(), + self.infcx.tcx.lang_items().fn_trait(), + ] + .contains(&Some(fn_trait_id)) + { + // Do not suggest `F: FnOnce() + Clone`. + false + } else { + true + } + { + let mut span: MultiSpan = param_span.into(); + span.push_span_label( + param_span, + "consider constraining this type parameter with `Clone`", + ); + span.push_span_label(expr.span, "you could clone this value"); + err.span_help( + span, format!("if `{ty}` implemented `Clone`, you could clone the value"), ); } @@ -1403,7 +1440,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if let Some(expr) = self.find_expr(borrow_span) && let Some(ty) = typeck_results.node_type_opt(expr.hir_id) { - self.suggest_cloning(&mut err, ty, expr, self.find_expr(span)); + self.suggest_cloning(&mut err, ty, expr, self.find_expr(span), Some(move_spans)); } self.buffer_error(err); } diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index bc02c5be93d6..1bbf36355cbe 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -447,7 +447,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { }; if let Some(expr) = self.find_expr(span) { - self.suggest_cloning(err, place_ty, expr, self.find_expr(other_span)); + self.suggest_cloning(err, place_ty, expr, self.find_expr(other_span), None); } err.subdiagnostic( @@ -482,7 +482,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { }; if let Some(expr) = self.find_expr(use_span) { - self.suggest_cloning(err, place_ty, expr, self.find_expr(span)); + self.suggest_cloning( + err, + place_ty, + expr, + self.find_expr(span), + Some(use_spans), + ); } err.subdiagnostic( @@ -595,7 +601,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let place_desc = &format!("`{}`", self.local_names[*local].unwrap()); if let Some(expr) = self.find_expr(binding_span) { - self.suggest_cloning(err, bind_to.ty, expr, None); + self.suggest_cloning(err, bind_to.ty, expr, None, None); } err.subdiagnostic( diff --git a/tests/ui/associated-types/issue-25700.stderr b/tests/ui/associated-types/issue-25700.stderr index fb0e63c207a5..8d40e6905e07 100644 --- a/tests/ui/associated-types/issue-25700.stderr +++ b/tests/ui/associated-types/issue-25700.stderr @@ -12,7 +12,10 @@ note: if `S<()>` implemented `Clone`, you could clone the value --> $DIR/issue-25700.rs:1:1 | LL | struct S(#[allow(dead_code)] Option<&'static T>); - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | drop(t); + | - you could clone this value error: aborting due to 1 previous error diff --git a/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr b/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr index dcf1c02bceef..4c1de72798c4 100644 --- a/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr +++ b/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr @@ -23,6 +23,13 @@ LL | fn copy(x: T) -> (T, T) { (x, x) } | | value moved here | move occurs because `x` has type `T`, which does not implement the `Copy` trait | +help: if `T` implemented `Clone`, you could clone the value + --> $DIR/typeck-auto-trait-no-supertraits-2.rs:8:9 + | +LL | fn copy(x: T) -> (T, T) { (x, x) } + | ^ - you could clone this value + | | + | consider constraining this type parameter with `Clone` help: consider further restricting this bound | LL | fn copy(x: T) -> (T, T) { (x, x) } diff --git a/tests/ui/binop/binop-consume-args.stderr b/tests/ui/binop/binop-consume-args.stderr index 6fbbb55437eb..1b59216b3c76 100644 --- a/tests/ui/binop/binop-consume-args.stderr +++ b/tests/ui/binop/binop-consume-args.stderr @@ -8,6 +8,13 @@ LL | lhs + rhs; LL | drop(lhs); | ^^^ value used here after move | +help: if `A` implemented `Clone`, you could clone the value + --> $DIR/binop-consume-args.rs:5:8 + | +LL | fn add, B>(lhs: A, rhs: B) { + | ^ consider constraining this type parameter with `Clone` +LL | lhs + rhs; + | --- you could clone this value note: calling this operator moves the left-hand side --> $SRC_DIR/core/src/ops/arith.rs:LL:COL help: consider further restricting this bound @@ -26,6 +33,13 @@ LL | drop(lhs); LL | drop(rhs); | ^^^ value used here after move | +help: if `B` implemented `Clone`, you could clone the value + --> $DIR/binop-consume-args.rs:5:30 + | +LL | fn add, B>(lhs: A, rhs: B) { + | ^ consider constraining this type parameter with `Clone` +LL | lhs + rhs; + | --- you could clone this value help: consider restricting type parameter `B` | LL | fn add, B: Copy>(lhs: A, rhs: B) { @@ -41,6 +55,13 @@ LL | lhs - rhs; LL | drop(lhs); | ^^^ value used here after move | +help: if `A` implemented `Clone`, you could clone the value + --> $DIR/binop-consume-args.rs:11:8 + | +LL | fn sub, B>(lhs: A, rhs: B) { + | ^ consider constraining this type parameter with `Clone` +LL | lhs - rhs; + | --- you could clone this value note: calling this operator moves the left-hand side --> $SRC_DIR/core/src/ops/arith.rs:LL:COL help: consider further restricting this bound @@ -59,6 +80,13 @@ LL | drop(lhs); LL | drop(rhs); | ^^^ value used here after move | +help: if `B` implemented `Clone`, you could clone the value + --> $DIR/binop-consume-args.rs:11:30 + | +LL | fn sub, B>(lhs: A, rhs: B) { + | ^ consider constraining this type parameter with `Clone` +LL | lhs - rhs; + | --- you could clone this value help: consider restricting type parameter `B` | LL | fn sub, B: Copy>(lhs: A, rhs: B) { @@ -74,6 +102,13 @@ LL | lhs * rhs; LL | drop(lhs); | ^^^ value used here after move | +help: if `A` implemented `Clone`, you could clone the value + --> $DIR/binop-consume-args.rs:17:8 + | +LL | fn mul, B>(lhs: A, rhs: B) { + | ^ consider constraining this type parameter with `Clone` +LL | lhs * rhs; + | --- you could clone this value note: calling this operator moves the left-hand side --> $SRC_DIR/core/src/ops/arith.rs:LL:COL help: consider further restricting this bound @@ -92,6 +127,13 @@ LL | drop(lhs); LL | drop(rhs); | ^^^ value used here after move | +help: if `B` implemented `Clone`, you could clone the value + --> $DIR/binop-consume-args.rs:17:30 + | +LL | fn mul, B>(lhs: A, rhs: B) { + | ^ consider constraining this type parameter with `Clone` +LL | lhs * rhs; + | --- you could clone this value help: consider restricting type parameter `B` | LL | fn mul, B: Copy>(lhs: A, rhs: B) { @@ -107,6 +149,13 @@ LL | lhs / rhs; LL | drop(lhs); | ^^^ value used here after move | +help: if `A` implemented `Clone`, you could clone the value + --> $DIR/binop-consume-args.rs:23:8 + | +LL | fn div, B>(lhs: A, rhs: B) { + | ^ consider constraining this type parameter with `Clone` +LL | lhs / rhs; + | --- you could clone this value note: calling this operator moves the left-hand side --> $SRC_DIR/core/src/ops/arith.rs:LL:COL help: consider further restricting this bound @@ -125,6 +174,13 @@ LL | drop(lhs); LL | drop(rhs); | ^^^ value used here after move | +help: if `B` implemented `Clone`, you could clone the value + --> $DIR/binop-consume-args.rs:23:30 + | +LL | fn div, B>(lhs: A, rhs: B) { + | ^ consider constraining this type parameter with `Clone` +LL | lhs / rhs; + | --- you could clone this value help: consider restricting type parameter `B` | LL | fn div, B: Copy>(lhs: A, rhs: B) { @@ -140,6 +196,13 @@ LL | lhs % rhs; LL | drop(lhs); | ^^^ value used here after move | +help: if `A` implemented `Clone`, you could clone the value + --> $DIR/binop-consume-args.rs:29:8 + | +LL | fn rem, B>(lhs: A, rhs: B) { + | ^ consider constraining this type parameter with `Clone` +LL | lhs % rhs; + | --- you could clone this value note: calling this operator moves the left-hand side --> $SRC_DIR/core/src/ops/arith.rs:LL:COL help: consider further restricting this bound @@ -158,6 +221,13 @@ LL | drop(lhs); LL | drop(rhs); | ^^^ value used here after move | +help: if `B` implemented `Clone`, you could clone the value + --> $DIR/binop-consume-args.rs:29:30 + | +LL | fn rem, B>(lhs: A, rhs: B) { + | ^ consider constraining this type parameter with `Clone` +LL | lhs % rhs; + | --- you could clone this value help: consider restricting type parameter `B` | LL | fn rem, B: Copy>(lhs: A, rhs: B) { @@ -173,6 +243,13 @@ LL | lhs & rhs; LL | drop(lhs); | ^^^ value used here after move | +help: if `A` implemented `Clone`, you could clone the value + --> $DIR/binop-consume-args.rs:35:11 + | +LL | fn bitand, B>(lhs: A, rhs: B) { + | ^ consider constraining this type parameter with `Clone` +LL | lhs & rhs; + | --- you could clone this value note: calling this operator moves the left-hand side --> $SRC_DIR/core/src/ops/bit.rs:LL:COL help: consider further restricting this bound @@ -191,6 +268,13 @@ LL | drop(lhs); LL | drop(rhs); | ^^^ value used here after move | +help: if `B` implemented `Clone`, you could clone the value + --> $DIR/binop-consume-args.rs:35:36 + | +LL | fn bitand, B>(lhs: A, rhs: B) { + | ^ consider constraining this type parameter with `Clone` +LL | lhs & rhs; + | --- you could clone this value help: consider restricting type parameter `B` | LL | fn bitand, B: Copy>(lhs: A, rhs: B) { @@ -206,6 +290,13 @@ LL | lhs | rhs; LL | drop(lhs); | ^^^ value used here after move | +help: if `A` implemented `Clone`, you could clone the value + --> $DIR/binop-consume-args.rs:41:10 + | +LL | fn bitor, B>(lhs: A, rhs: B) { + | ^ consider constraining this type parameter with `Clone` +LL | lhs | rhs; + | --- you could clone this value note: calling this operator moves the left-hand side --> $SRC_DIR/core/src/ops/bit.rs:LL:COL help: consider further restricting this bound @@ -224,6 +315,13 @@ LL | drop(lhs); LL | drop(rhs); | ^^^ value used here after move | +help: if `B` implemented `Clone`, you could clone the value + --> $DIR/binop-consume-args.rs:41:34 + | +LL | fn bitor, B>(lhs: A, rhs: B) { + | ^ consider constraining this type parameter with `Clone` +LL | lhs | rhs; + | --- you could clone this value help: consider restricting type parameter `B` | LL | fn bitor, B: Copy>(lhs: A, rhs: B) { @@ -239,6 +337,13 @@ LL | lhs ^ rhs; LL | drop(lhs); | ^^^ value used here after move | +help: if `A` implemented `Clone`, you could clone the value + --> $DIR/binop-consume-args.rs:47:11 + | +LL | fn bitxor, B>(lhs: A, rhs: B) { + | ^ consider constraining this type parameter with `Clone` +LL | lhs ^ rhs; + | --- you could clone this value note: calling this operator moves the left-hand side --> $SRC_DIR/core/src/ops/bit.rs:LL:COL help: consider further restricting this bound @@ -257,6 +362,13 @@ LL | drop(lhs); LL | drop(rhs); | ^^^ value used here after move | +help: if `B` implemented `Clone`, you could clone the value + --> $DIR/binop-consume-args.rs:47:36 + | +LL | fn bitxor, B>(lhs: A, rhs: B) { + | ^ consider constraining this type parameter with `Clone` +LL | lhs ^ rhs; + | --- you could clone this value help: consider restricting type parameter `B` | LL | fn bitxor, B: Copy>(lhs: A, rhs: B) { @@ -272,6 +384,13 @@ LL | lhs << rhs; LL | drop(lhs); | ^^^ value used here after move | +help: if `A` implemented `Clone`, you could clone the value + --> $DIR/binop-consume-args.rs:53:8 + | +LL | fn shl, B>(lhs: A, rhs: B) { + | ^ consider constraining this type parameter with `Clone` +LL | lhs << rhs; + | --- you could clone this value note: calling this operator moves the left-hand side --> $SRC_DIR/core/src/ops/bit.rs:LL:COL help: consider further restricting this bound @@ -290,6 +409,13 @@ LL | drop(lhs); LL | drop(rhs); | ^^^ value used here after move | +help: if `B` implemented `Clone`, you could clone the value + --> $DIR/binop-consume-args.rs:53:30 + | +LL | fn shl, B>(lhs: A, rhs: B) { + | ^ consider constraining this type parameter with `Clone` +LL | lhs << rhs; + | --- you could clone this value help: consider restricting type parameter `B` | LL | fn shl, B: Copy>(lhs: A, rhs: B) { @@ -305,6 +431,13 @@ LL | lhs >> rhs; LL | drop(lhs); | ^^^ value used here after move | +help: if `A` implemented `Clone`, you could clone the value + --> $DIR/binop-consume-args.rs:59:8 + | +LL | fn shr, B>(lhs: A, rhs: B) { + | ^ consider constraining this type parameter with `Clone` +LL | lhs >> rhs; + | --- you could clone this value note: calling this operator moves the left-hand side --> $SRC_DIR/core/src/ops/bit.rs:LL:COL help: consider further restricting this bound @@ -323,6 +456,13 @@ LL | drop(lhs); LL | drop(rhs); | ^^^ value used here after move | +help: if `B` implemented `Clone`, you could clone the value + --> $DIR/binop-consume-args.rs:59:30 + | +LL | fn shr, B>(lhs: A, rhs: B) { + | ^ consider constraining this type parameter with `Clone` +LL | lhs >> rhs; + | --- you could clone this value help: consider restricting type parameter `B` | LL | fn shr, B: Copy>(lhs: A, rhs: B) { diff --git a/tests/ui/binop/binop-move-semantics.stderr b/tests/ui/binop/binop-move-semantics.stderr index 1dd8c9a87d47..83c27590e901 100644 --- a/tests/ui/binop/binop-move-semantics.stderr +++ b/tests/ui/binop/binop-move-semantics.stderr @@ -11,6 +11,13 @@ LL | | x; | |_____value used here after move | `x` moved due to usage in operator | +help: if `T` implemented `Clone`, you could clone the value + --> $DIR/binop-move-semantics.rs:5:16 + | +LL | fn double_move>(x: T) { + | ^ consider constraining this type parameter with `Clone` +LL | x + | - you could clone this value note: calling this operator moves the left-hand side --> $SRC_DIR/core/src/ops/arith.rs:LL:COL help: consider further restricting this bound @@ -51,6 +58,14 @@ LL | x ... LL | use_mut(n); use_imm(m); | - borrow later used here + | +help: if `T` implemented `Clone`, you could clone the value + --> $DIR/binop-move-semantics.rs:17:18 + | +LL | fn move_borrowed>(x: T, mut y: T) { + | ^ consider constraining this type parameter with `Clone` +LL | let m = &x; + | -- you could clone this value error[E0505]: cannot move out of `y` because it is borrowed --> $DIR/binop-move-semantics.rs:23:5 @@ -65,6 +80,15 @@ LL | y; | ^ move out of `y` occurs here LL | use_mut(n); use_imm(m); | - borrow later used here + | +help: if `T` implemented `Clone`, you could clone the value + --> $DIR/binop-move-semantics.rs:17:18 + | +LL | fn move_borrowed>(x: T, mut y: T) { + | ^ consider constraining this type parameter with `Clone` +LL | let m = &x; +LL | let n = &mut y; + | ------ you could clone this value error[E0507]: cannot move out of `*m` which is behind a mutable reference --> $DIR/binop-move-semantics.rs:30:5 @@ -80,12 +104,29 @@ LL | | *n; | note: calling this operator moves the left-hand side --> $SRC_DIR/core/src/ops/arith.rs:LL:COL +help: if `T` implemented `Clone`, you could clone the value + --> $DIR/binop-move-semantics.rs:26:24 + | +LL | fn illegal_dereference>(mut x: T, y: T) { + | ^ consider constraining this type parameter with `Clone` +... +LL | *m + | -- you could clone this value error[E0507]: cannot move out of `*n` which is behind a shared reference --> $DIR/binop-move-semantics.rs:32:5 | LL | *n; | ^^ move occurs because `*n` has type `T`, which does not implement the `Copy` trait + | +help: if `T` implemented `Clone`, you could clone the value + --> $DIR/binop-move-semantics.rs:26:24 + | +LL | fn illegal_dereference>(mut x: T, y: T) { + | ^ consider constraining this type parameter with `Clone` +... +LL | *n; + | -- you could clone this value error[E0502]: cannot borrow `f` as immutable because it is also borrowed as mutable --> $DIR/binop-move-semantics.rs:54:5 diff --git a/tests/ui/borrowck/borrowck-move-out-of-static-item.stderr b/tests/ui/borrowck/borrowck-move-out-of-static-item.stderr index 86bddacbdc72..b4b60d40d914 100644 --- a/tests/ui/borrowck/borrowck-move-out-of-static-item.stderr +++ b/tests/ui/borrowck/borrowck-move-out-of-static-item.stderr @@ -8,7 +8,10 @@ note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/borrowck-move-out-of-static-item.rs:3:1 | LL | struct Foo { - | ^^^^^^^^^^ + | ^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | test(BAR); + | --- you could clone this value error: aborting due to 1 previous error diff --git a/tests/ui/borrowck/borrowck-move-subcomponent.stderr b/tests/ui/borrowck/borrowck-move-subcomponent.stderr index 4d9477f85811..cc6c3bdeb102 100644 --- a/tests/ui/borrowck/borrowck-move-subcomponent.stderr +++ b/tests/ui/borrowck/borrowck-move-subcomponent.stderr @@ -14,7 +14,10 @@ note: if `S` implemented `Clone`, you could clone the value --> $DIR/borrowck-move-subcomponent.rs:6:1 | LL | struct S { - | ^^^^^^^^ + | ^^^^^^^^ consider implementing `Clone` for this type +... +LL | let pb = &a; + | -- you could clone this value error: aborting due to 1 previous error diff --git a/tests/ui/borrowck/borrowck-overloaded-call.stderr b/tests/ui/borrowck/borrowck-overloaded-call.stderr index 1602058c183f..c3b7b0b6080c 100644 --- a/tests/ui/borrowck/borrowck-overloaded-call.stderr +++ b/tests/ui/borrowck/borrowck-overloaded-call.stderr @@ -34,7 +34,10 @@ note: if `SFnOnce` implemented `Clone`, you could clone the value --> $DIR/borrowck-overloaded-call.rs:41:1 | LL | struct SFnOnce { - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | s(" world".to_string()); + | - you could clone this value error: aborting due to 3 previous errors diff --git a/tests/ui/borrowck/clone-on-ref.stderr b/tests/ui/borrowck/clone-on-ref.stderr index f0eaf4bac7df..19f040556f8a 100644 --- a/tests/ui/borrowck/clone-on-ref.stderr +++ b/tests/ui/borrowck/clone-on-ref.stderr @@ -32,6 +32,13 @@ LL | LL | println!("{b}"); | --- borrow later used here | +help: if `T` implemented `Clone`, you could clone the value + --> $DIR/clone-on-ref.rs:11:8 + | +LL | fn bar(x: T) { + | ^ consider constraining this type parameter with `Clone` +LL | let a = &x; + | -- you could clone this value help: consider further restricting this bound | LL | fn bar(x: T) { @@ -56,7 +63,10 @@ note: if `A` implemented `Clone`, you could clone the value --> $DIR/clone-on-ref.rs:19:1 | LL | struct A; - | ^^^^^^^^ + | ^^^^^^^^ consider implementing `Clone` for this type +LL | fn qux(x: A) { +LL | let a = &x; + | -- you could clone this value help: consider annotating `A` with `#[derive(Clone)]` | LL + #[derive(Clone)] diff --git a/tests/ui/borrowck/issue-101119.stderr b/tests/ui/borrowck/issue-101119.stderr index b4775496f4f4..a894fa63ace2 100644 --- a/tests/ui/borrowck/issue-101119.stderr +++ b/tests/ui/borrowck/issue-101119.stderr @@ -22,7 +22,10 @@ note: if `State` implemented `Clone`, you could clone the value --> $DIR/issue-101119.rs:1:1 | LL | struct State; - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | fill_segment(state); + | ----- you could clone this value error: aborting due to 1 previous error diff --git a/tests/ui/borrowck/issue-103624.stderr b/tests/ui/borrowck/issue-103624.stderr index 94421c35c65d..603055beadce 100644 --- a/tests/ui/borrowck/issue-103624.stderr +++ b/tests/ui/borrowck/issue-103624.stderr @@ -13,8 +13,11 @@ LL | self.b; note: if `StructB` implemented `Clone`, you could clone the value --> $DIR/issue-103624.rs:23:1 | +LL | self.b; + | ------ you could clone this value +... LL | struct StructB {} - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ consider implementing `Clone` for this type error[E0521]: borrowed data escapes outside of method --> $DIR/issue-103624.rs:14:9 diff --git a/tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr b/tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr index 701f00d079d3..dde17d1f6523 100644 --- a/tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr +++ b/tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr @@ -15,7 +15,10 @@ note: if `Example` implemented `Clone`, you could clone the value --> $DIR/issue-119915-bad-clone-suggestion.rs:3:1 | LL | struct Example(PhantomData<(fn(E), fn(FakeParam))>); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | unsafe { self.change() } + | ---- you could clone this value error: aborting due to 1 previous error diff --git a/tests/ui/borrowck/issue-17718-static-move.stderr b/tests/ui/borrowck/issue-17718-static-move.stderr index e2c3a9d5a266..057ac6d7e3df 100644 --- a/tests/ui/borrowck/issue-17718-static-move.stderr +++ b/tests/ui/borrowck/issue-17718-static-move.stderr @@ -8,7 +8,10 @@ note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/issue-17718-static-move.rs:1:1 | LL | struct Foo; - | ^^^^^^^^^^ + | ^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | let _a = FOO; + | --- you could clone this value help: consider borrowing here | LL | let _a = &FOO; diff --git a/tests/ui/borrowck/issue-20801.stderr b/tests/ui/borrowck/issue-20801.stderr index 1da6f0bef023..20a4bd4e4237 100644 --- a/tests/ui/borrowck/issue-20801.stderr +++ b/tests/ui/borrowck/issue-20801.stderr @@ -23,7 +23,10 @@ note: if `T` implemented `Clone`, you could clone the value --> $DIR/issue-20801.rs:3:1 | LL | struct T(u8); - | ^^^^^^^^ + | ^^^^^^^^ consider implementing `Clone` for this type +... +LL | let a = unsafe { *mut_ref() }; + | ---------- you could clone this value help: consider removing the dereference here | LL - let a = unsafe { *mut_ref() }; @@ -40,7 +43,10 @@ note: if `T` implemented `Clone`, you could clone the value --> $DIR/issue-20801.rs:3:1 | LL | struct T(u8); - | ^^^^^^^^ + | ^^^^^^^^ consider implementing `Clone` for this type +... +LL | let b = unsafe { *imm_ref() }; + | ---------- you could clone this value help: consider removing the dereference here | LL - let b = unsafe { *imm_ref() }; @@ -57,7 +63,10 @@ note: if `T` implemented `Clone`, you could clone the value --> $DIR/issue-20801.rs:3:1 | LL | struct T(u8); - | ^^^^^^^^ + | ^^^^^^^^ consider implementing `Clone` for this type +... +LL | let c = unsafe { *mut_ptr() }; + | ---------- you could clone this value help: consider removing the dereference here | LL - let c = unsafe { *mut_ptr() }; @@ -74,7 +83,10 @@ note: if `T` implemented `Clone`, you could clone the value --> $DIR/issue-20801.rs:3:1 | LL | struct T(u8); - | ^^^^^^^^ + | ^^^^^^^^ consider implementing `Clone` for this type +... +LL | let d = unsafe { *const_ptr() }; + | ------------ you could clone this value help: consider removing the dereference here | LL - let d = unsafe { *const_ptr() }; diff --git a/tests/ui/borrowck/move-error-in-promoted-2.stderr b/tests/ui/borrowck/move-error-in-promoted-2.stderr index 43f4e820857a..1e9b1d5209cb 100644 --- a/tests/ui/borrowck/move-error-in-promoted-2.stderr +++ b/tests/ui/borrowck/move-error-in-promoted-2.stderr @@ -11,7 +11,10 @@ note: if `S` implemented `Clone`, you could clone the value --> $DIR/move-error-in-promoted-2.rs:3:1 | LL | struct S; - | ^^^^^^^^ + | ^^^^^^^^ consider implementing `Clone` for this type +... +LL | &([S][0],); + | ------ you could clone this value error: aborting due to 1 previous error diff --git a/tests/ui/borrowck/move-error-snippets.stderr b/tests/ui/borrowck/move-error-snippets.stderr index 40b64398aef6..97d140515184 100644 --- a/tests/ui/borrowck/move-error-snippets.stderr +++ b/tests/ui/borrowck/move-error-snippets.stderr @@ -13,7 +13,12 @@ note: if `A` implemented `Clone`, you could clone the value --> $DIR/move-error-snippets.rs:9:1 | LL | struct A; - | ^^^^^^^^ + | ^^^^^^^^ consider implementing `Clone` for this type + | + ::: $DIR/move-error-snippets-ext.rs:5:17 + | +LL | let a = $c; + | -- you could clone this value = note: this error originates in the macro `aaa` which comes from the expansion of the macro `sss` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider borrowing here | diff --git a/tests/ui/borrowck/move-in-static-initializer-issue-38520.stderr b/tests/ui/borrowck/move-in-static-initializer-issue-38520.stderr index a4e70b506462..009e85a8031e 100644 --- a/tests/ui/borrowck/move-in-static-initializer-issue-38520.stderr +++ b/tests/ui/borrowck/move-in-static-initializer-issue-38520.stderr @@ -8,7 +8,10 @@ note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/move-in-static-initializer-issue-38520.rs:5:1 | LL | struct Foo(usize); - | ^^^^^^^^^^ + | ^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | static Y: usize = get(*&X); + | --- you could clone this value error[E0507]: cannot move out of a shared reference --> $DIR/move-in-static-initializer-issue-38520.rs:13:22 @@ -20,7 +23,10 @@ note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/move-in-static-initializer-issue-38520.rs:5:1 | LL | struct Foo(usize); - | ^^^^^^^^^^ + | ^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | const Z: usize = get(*&X); + | --- you could clone this value error: aborting due to 2 previous errors diff --git a/tests/ui/box/leak-alloc.stderr b/tests/ui/box/leak-alloc.stderr index 53ff5f0107df..bdaa9449f913 100644 --- a/tests/ui/box/leak-alloc.stderr +++ b/tests/ui/box/leak-alloc.stderr @@ -16,7 +16,10 @@ note: if `Alloc` implemented `Clone`, you could clone the value --> $DIR/leak-alloc.rs:8:1 | LL | struct Alloc {} - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | let boxed = Box::new_in(10, alloc.by_ref()); + | ----- you could clone this value error: aborting due to 1 previous error diff --git a/tests/ui/derives/deriving-with-repr-packed.stderr b/tests/ui/derives/deriving-with-repr-packed.stderr index 26ac532263fd..a8523d25cab9 100644 --- a/tests/ui/derives/deriving-with-repr-packed.stderr +++ b/tests/ui/derives/deriving-with-repr-packed.stderr @@ -40,7 +40,10 @@ note: if `Y` implemented `Clone`, you could clone the value --> $DIR/deriving-with-repr-packed.rs:16:1 | LL | struct Y(usize); - | ^^^^^^^^ + | ^^^^^^^^ consider implementing `Clone` for this type +... +LL | struct X(Y); + | - you could clone this value = note: `#[derive(Debug)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/error-codes/E0504.stderr b/tests/ui/error-codes/E0504.stderr index 900cb706bd97..343bca9a72e2 100644 --- a/tests/ui/error-codes/E0504.stderr +++ b/tests/ui/error-codes/E0504.stderr @@ -18,7 +18,10 @@ note: if `FancyNum` implemented `Clone`, you could clone the value --> $DIR/E0504.rs:1:1 | LL | struct FancyNum { - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | let fancy_ref = &fancy_num; + | ---------- you could clone this value error: aborting due to 1 previous error diff --git a/tests/ui/error-codes/E0505.stderr b/tests/ui/error-codes/E0505.stderr index ce01298a70d9..266df9ea32a7 100644 --- a/tests/ui/error-codes/E0505.stderr +++ b/tests/ui/error-codes/E0505.stderr @@ -15,7 +15,10 @@ note: if `Value` implemented `Clone`, you could clone the value --> $DIR/E0505.rs:1:1 | LL | struct Value {} - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | let _ref_to_val: &Value = &x; + | -- you could clone this value error: aborting due to 1 previous error diff --git a/tests/ui/error-codes/E0507.stderr b/tests/ui/error-codes/E0507.stderr index 60a4daa9d382..70d99ea2cce5 100644 --- a/tests/ui/error-codes/E0507.stderr +++ b/tests/ui/error-codes/E0507.stderr @@ -15,7 +15,10 @@ note: if `TheDarkKnight` implemented `Clone`, you could clone the value --> $DIR/E0507.rs:3:1 | LL | struct TheDarkKnight; - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | x.borrow().nothing_is_true(); + | ---------- you could clone this value error: aborting due to 1 previous error diff --git a/tests/ui/error-codes/E0508-fail.stderr b/tests/ui/error-codes/E0508-fail.stderr index 96d3bcb67a57..fcfac399e0df 100644 --- a/tests/ui/error-codes/E0508-fail.stderr +++ b/tests/ui/error-codes/E0508-fail.stderr @@ -11,7 +11,10 @@ note: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/E0508-fail.rs:1:1 | LL | struct NonCopy; - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | let _value = array[0]; + | -------- you could clone this value help: consider borrowing here | LL | let _value = &array[0]; diff --git a/tests/ui/error-codes/E0508.stderr b/tests/ui/error-codes/E0508.stderr index c1b622e24321..b9fa0f4d17a5 100644 --- a/tests/ui/error-codes/E0508.stderr +++ b/tests/ui/error-codes/E0508.stderr @@ -11,7 +11,10 @@ note: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/E0508.rs:1:1 | LL | struct NonCopy; - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | let _value = array[0]; + | -------- you could clone this value help: consider borrowing here | LL | let _value = &array[0]; diff --git a/tests/ui/error-codes/E0509.stderr b/tests/ui/error-codes/E0509.stderr index 75c372d04401..628a253e0859 100644 --- a/tests/ui/error-codes/E0509.stderr +++ b/tests/ui/error-codes/E0509.stderr @@ -11,7 +11,10 @@ note: if `FancyNum` implemented `Clone`, you could clone the value --> $DIR/E0509.rs:1:1 | LL | struct FancyNum { - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | let fancy_field = drop_struct.fancy; + | ----------------- you could clone this value help: consider borrowing here | LL | let fancy_field = &drop_struct.fancy; diff --git a/tests/ui/issues/issue-17385.stderr b/tests/ui/issues/issue-17385.stderr index 988db0fb1fc4..3c451a859e94 100644 --- a/tests/ui/issues/issue-17385.stderr +++ b/tests/ui/issues/issue-17385.stderr @@ -12,7 +12,10 @@ note: if `X` implemented `Clone`, you could clone the value --> $DIR/issue-17385.rs:1:1 | LL | struct X(isize); - | ^^^^^^^^ + | ^^^^^^^^ consider implementing `Clone` for this type +... +LL | drop(foo); + | --- you could clone this value error[E0382]: use of moved value: `e` --> $DIR/issue-17385.rs:25:11 @@ -28,7 +31,10 @@ note: if `Enum` implemented `Clone`, you could clone the value --> $DIR/issue-17385.rs:3:1 | LL | enum Enum { - | ^^^^^^^^^ + | ^^^^^^^^^ consider implementing `Clone` for this type +... +LL | drop(e); + | - you could clone this value error: aborting due to 2 previous errors diff --git a/tests/ui/issues/issue-24357.rs b/tests/ui/issues/issue-24357.rs index d1a9e37251ee..63c061594d87 100644 --- a/tests/ui/issues/issue-24357.rs +++ b/tests/ui/issues/issue-24357.rs @@ -1,10 +1,12 @@ struct NoCopy; //~ NOTE if `NoCopy` implemented `Clone`, you could clone the value +//~^ NOTE consider implementing `Clone` for this type fn main() { let x = NoCopy; //~^ NOTE move occurs because `x` has type `NoCopy` let f = move || { let y = x; }; //~^ NOTE value moved into closure here //~| NOTE variable moved due to use in closure + //~| NOTE you could clone this value let z = x; //~^ ERROR use of moved value: `x` //~| NOTE value used here after move diff --git a/tests/ui/issues/issue-24357.stderr b/tests/ui/issues/issue-24357.stderr index 6d50eea7e21a..2d85077fe4c2 100644 --- a/tests/ui/issues/issue-24357.stderr +++ b/tests/ui/issues/issue-24357.stderr @@ -1,5 +1,5 @@ error[E0382]: use of moved value: `x` - --> $DIR/issue-24357.rs:8:12 + --> $DIR/issue-24357.rs:10:12 | LL | let x = NoCopy; | - move occurs because `x` has type `NoCopy`, which does not implement the `Copy` trait @@ -16,7 +16,10 @@ note: if `NoCopy` implemented `Clone`, you could clone the value --> $DIR/issue-24357.rs:1:1 | LL | struct NoCopy; - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | let f = move || { let y = x; }; + | - you could clone this value error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-4335.stderr b/tests/ui/issues/issue-4335.stderr index 8b4aff54dc3c..14b5cfa9f9ac 100644 --- a/tests/ui/issues/issue-4335.stderr +++ b/tests/ui/issues/issue-4335.stderr @@ -7,6 +7,14 @@ LL | id(Box::new(|| *v)) | -- ^^ move occurs because `*v` has type `T`, which does not implement the `Copy` trait | | | captured by this `FnMut` closure + | +help: if `T` implemented `Clone`, you could clone the value + --> $DIR/issue-4335.rs:5:10 + | +LL | fn f<'r, T>(v: &'r T) -> Box T + 'r> { + | ^ consider constraining this type parameter with `Clone` +LL | id(Box::new(|| *v)) + | -- you could clone this value error: aborting due to 1 previous error diff --git a/tests/ui/mir/issue-102389.stderr b/tests/ui/mir/issue-102389.stderr index 838eaffb5a0d..162d7ac031a6 100644 --- a/tests/ui/mir/issue-102389.stderr +++ b/tests/ui/mir/issue-102389.stderr @@ -8,7 +8,10 @@ note: if `Enum` implemented `Clone`, you could clone the value --> $DIR/issue-102389.rs:1:1 | LL | enum Enum { A, B, C } - | ^^^^^^^^^ + | ^^^^^^^^^ consider implementing `Clone` for this type +... +LL | array[*inbounds as usize] + | --------- you could clone this value error: aborting due to 1 previous error diff --git a/tests/ui/moves/borrow-closures-instead-of-move.rs b/tests/ui/moves/borrow-closures-instead-of-move.rs index 51771ced7f22..e4bca54e995f 100644 --- a/tests/ui/moves/borrow-closures-instead-of-move.rs +++ b/tests/ui/moves/borrow-closures-instead-of-move.rs @@ -1,4 +1,4 @@ -fn takes_fn(f: impl Fn()) { +fn takes_fn(f: impl Fn()) { //~ HELP if `impl Fn()` implemented `Clone` loop { takes_fnonce(f); //~^ ERROR use of moved value @@ -6,7 +6,7 @@ fn takes_fn(f: impl Fn()) { } } -fn takes_fn_mut(m: impl FnMut()) { +fn takes_fn_mut(m: impl FnMut()) { //~ HELP if `impl FnMut()` implemented `Clone` if maybe() { takes_fnonce(m); //~^ HELP consider mutably borrowing diff --git a/tests/ui/moves/borrow-closures-instead-of-move.stderr b/tests/ui/moves/borrow-closures-instead-of-move.stderr index 9a84ddef7e64..ab6ff417efb6 100644 --- a/tests/ui/moves/borrow-closures-instead-of-move.stderr +++ b/tests/ui/moves/borrow-closures-instead-of-move.stderr @@ -15,6 +15,14 @@ LL | fn takes_fnonce(_: impl FnOnce()) {} | ------------ ^^^^^^^^^^^^^ this parameter takes ownership of the value | | | in this function +help: if `impl Fn()` implemented `Clone`, you could clone the value + --> $DIR/borrow-closures-instead-of-move.rs:1:16 + | +LL | fn takes_fn(f: impl Fn()) { + | ^^^^^^^^^ consider constraining this type parameter with `Clone` +LL | loop { +LL | takes_fnonce(f); + | - you could clone this value help: consider borrowing `f` | LL | takes_fnonce(&f); @@ -39,6 +47,14 @@ LL | fn takes_fnonce(_: impl FnOnce()) {} | ------------ ^^^^^^^^^^^^^ this parameter takes ownership of the value | | | in this function +help: if `impl FnMut()` implemented `Clone`, you could clone the value + --> $DIR/borrow-closures-instead-of-move.rs:9:20 + | +LL | fn takes_fn_mut(m: impl FnMut()) { + | ^^^^^^^^^^^^ consider constraining this type parameter with `Clone` +LL | if maybe() { +LL | takes_fnonce(m); + | - you could clone this value help: consider mutably borrowing `m` | LL | takes_fnonce(&mut m); diff --git a/tests/ui/moves/issue-72649-uninit-in-loop.rs b/tests/ui/moves/issue-72649-uninit-in-loop.rs index 86f389cb3af1..8f2e01bdf1ab 100644 --- a/tests/ui/moves/issue-72649-uninit-in-loop.rs +++ b/tests/ui/moves/issue-72649-uninit-in-loop.rs @@ -7,6 +7,10 @@ struct NonCopy; //~| NOTE if `NonCopy` implemented `Clone` //~| NOTE if `NonCopy` implemented `Clone` //~| NOTE if `NonCopy` implemented `Clone` +//~| NOTE consider implementing `Clone` for this type +//~| NOTE consider implementing `Clone` for this type +//~| NOTE consider implementing `Clone` for this type +//~| NOTE consider implementing `Clone` for this type fn good() { loop { @@ -21,6 +25,7 @@ fn moved_here_1() { //~^ NOTE move occurs because `value` has type `NonCopy`, which does not implement the `Copy` trait let _used = value; //~^ NOTE value moved here + //~| NOTE you could clone this value let _used2 = value; //~ ERROR use of moved value: `value` //~^ NOTE value used here after move } @@ -32,6 +37,7 @@ fn moved_here_2() { loop { //~ NOTE inside of this loop let _used = value; //~^ NOTE value moved here + //~| NOTE you could clone this value loop { let _used2 = value; //~ ERROR use of moved value: `value` //~^ NOTE value used here after move @@ -45,6 +51,7 @@ fn moved_loop_1() { loop { //~ NOTE inside of this loop let _used = value; //~ ERROR use of moved value: `value` //~^ NOTE value moved here, in previous iteration of loop + //~| NOTE you could clone this value } } @@ -56,6 +63,7 @@ fn moved_loop_2() { loop { //~ NOTE inside of this loop let _used2 = value; //~ ERROR use of moved value: `value` //~^ NOTE value moved here, in previous iteration of loop + //~| NOTE you could clone this value } } diff --git a/tests/ui/moves/issue-72649-uninit-in-loop.stderr b/tests/ui/moves/issue-72649-uninit-in-loop.stderr index a613f35a35e0..3a93769ac454 100644 --- a/tests/ui/moves/issue-72649-uninit-in-loop.stderr +++ b/tests/ui/moves/issue-72649-uninit-in-loop.stderr @@ -1,12 +1,12 @@ error[E0382]: use of moved value: `value` - --> $DIR/issue-72649-uninit-in-loop.rs:24:22 + --> $DIR/issue-72649-uninit-in-loop.rs:29:22 | LL | let value = NonCopy{}; | ----- move occurs because `value` has type `NonCopy`, which does not implement the `Copy` trait LL | LL | let _used = value; | ----- value moved here -LL | +... LL | let _used2 = value; | ^^^^^ value used here after move | @@ -14,10 +14,13 @@ note: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/issue-72649-uninit-in-loop.rs:5:1 | LL | struct NonCopy; - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | let _used = value; + | ----- you could clone this value error[E0382]: use of moved value: `value` - --> $DIR/issue-72649-uninit-in-loop.rs:36:26 + --> $DIR/issue-72649-uninit-in-loop.rs:42:26 | LL | let value = NonCopy{}; | ----- move occurs because `value` has type `NonCopy`, which does not implement the `Copy` trait @@ -34,10 +37,13 @@ note: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/issue-72649-uninit-in-loop.rs:5:1 | LL | struct NonCopy; - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | let _used = value; + | ----- you could clone this value error[E0382]: use of moved value: `value` - --> $DIR/issue-72649-uninit-in-loop.rs:46:21 + --> $DIR/issue-72649-uninit-in-loop.rs:52:21 | LL | let value = NonCopy{}; | ----- move occurs because `value` has type `NonCopy`, which does not implement the `Copy` trait @@ -51,10 +57,13 @@ note: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/issue-72649-uninit-in-loop.rs:5:1 | LL | struct NonCopy; - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | let _used = value; + | ----- you could clone this value error[E0382]: use of moved value: `value` - --> $DIR/issue-72649-uninit-in-loop.rs:57:22 + --> $DIR/issue-72649-uninit-in-loop.rs:64:22 | LL | let mut value = NonCopy{}; | --------- move occurs because `value` has type `NonCopy`, which does not implement the `Copy` trait @@ -68,10 +77,13 @@ note: if `NonCopy` implemented `Clone`, you could clone the value --> $DIR/issue-72649-uninit-in-loop.rs:5:1 | LL | struct NonCopy; - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | let _used2 = value; + | ----- you could clone this value error[E0381]: used binding `value` isn't initialized - --> $DIR/issue-72649-uninit-in-loop.rs:65:21 + --> $DIR/issue-72649-uninit-in-loop.rs:73:21 | LL | let value: NonCopy; | ----- binding declared here but left uninitialized @@ -84,7 +96,7 @@ LL | let value: NonCopy = /* value */; | +++++++++++++ error[E0381]: used binding `value` isn't initialized - --> $DIR/issue-72649-uninit-in-loop.rs:73:21 + --> $DIR/issue-72649-uninit-in-loop.rs:81:21 | LL | let mut value: NonCopy; | --------- binding declared here but left uninitialized diff --git a/tests/ui/moves/issue-75904-move-closure-loop.stderr b/tests/ui/moves/issue-75904-move-closure-loop.stderr index b6ad906bbdb0..815e91b0f4df 100644 --- a/tests/ui/moves/issue-75904-move-closure-loop.stderr +++ b/tests/ui/moves/issue-75904-move-closure-loop.stderr @@ -15,7 +15,10 @@ note: if `NotCopy` implemented `Clone`, you could clone the value --> $DIR/issue-75904-move-closure-loop.rs:5:1 | LL | struct NotCopy; - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | a; + | - you could clone this value error: aborting due to 1 previous error diff --git a/tests/ui/moves/move-fn-self-receiver.stderr b/tests/ui/moves/move-fn-self-receiver.stderr index e6bf52276ac2..f2c6008d27ea 100644 --- a/tests/ui/moves/move-fn-self-receiver.stderr +++ b/tests/ui/moves/move-fn-self-receiver.stderr @@ -106,7 +106,10 @@ note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/move-fn-self-receiver.rs:5:1 | LL | struct Foo; - | ^^^^^^^^^^ + | ^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | let ret = mut_foo.use_mut_self(); + | ------- you could clone this value error[E0382]: use of moved value: `rc_foo` --> $DIR/move-fn-self-receiver.rs:55:5 @@ -142,7 +145,10 @@ note: if `Foo` implemented `Clone`, you could clone the value --> $DIR/move-fn-self-receiver.rs:5:1 | LL | struct Foo; - | ^^^^^^^^^^ + | ^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | foo_add + Foo; + | ------- you could clone this value note: calling this operator moves the left-hand side --> $SRC_DIR/core/src/ops/arith.rs:LL:COL diff --git a/tests/ui/moves/move-out-of-array-1.stderr b/tests/ui/moves/move-out-of-array-1.stderr index 9e4a08e0cef5..8a030f021920 100644 --- a/tests/ui/moves/move-out-of-array-1.stderr +++ b/tests/ui/moves/move-out-of-array-1.stderr @@ -11,7 +11,10 @@ note: if `D` implemented `Clone`, you could clone the value --> $DIR/move-out-of-array-1.rs:5:1 | LL | struct D { _x: u8 } - | ^^^^^^^^ + | ^^^^^^^^ consider implementing `Clone` for this type +... +LL | a[i] + | ---- you could clone this value error: aborting due to 1 previous error diff --git a/tests/ui/moves/moves-based-on-type-no-recursive-stack-closure.stderr b/tests/ui/moves/moves-based-on-type-no-recursive-stack-closure.stderr index 4759b45892cc..a8473bb81983 100644 --- a/tests/ui/moves/moves-based-on-type-no-recursive-stack-closure.stderr +++ b/tests/ui/moves/moves-based-on-type-no-recursive-stack-closure.stderr @@ -17,6 +17,13 @@ LL | let mut r = R {c: Box::new(f)}; LL | f(&mut r, false) | ^ value borrowed here after move | +help: if `F` implemented `Clone`, you could clone the value + --> $DIR/moves-based-on-type-no-recursive-stack-closure.rs:30:16 + | +LL | fn conspirator(mut f: F) where F: FnMut(&mut R, bool) { + | ^ consider constraining this type parameter with `Clone` +LL | let mut r = R {c: Box::new(f)}; + | - you could clone this value help: consider mutably borrowing `f` | LL | let mut r = R {c: Box::new(&mut f)}; diff --git a/tests/ui/moves/use_of_moved_value_copy_suggestions.fixed b/tests/ui/moves/use_of_moved_value_copy_suggestions.fixed index e726c8145c3b..bfb855c7fb1f 100644 --- a/tests/ui/moves/use_of_moved_value_copy_suggestions.fixed +++ b/tests/ui/moves/use_of_moved_value_copy_suggestions.fixed @@ -3,6 +3,7 @@ fn duplicate_t(t: T) -> (T, T) { //~^ HELP consider restricting type parameter `T` + //~| HELP if `T` implemented `Clone`, you could clone the value (t, t) //~ use of moved value: `t` } @@ -72,10 +73,11 @@ where #[rustfmt::skip] fn existing_colon(t: T) { //~^ HELP consider restricting type parameter `T` + //~| HELP if `T` implemented `Clone`, you could clone the value [t, t]; //~ use of moved value: `t` } -fn existing_colon_in_where(t: T) +fn existing_colon_in_where(t: T) //~ HELP if `T` implemented `Clone`, you could clone the value where T:, T: Copy //~^ HELP consider further restricting type parameter `T` diff --git a/tests/ui/moves/use_of_moved_value_copy_suggestions.rs b/tests/ui/moves/use_of_moved_value_copy_suggestions.rs index ee08ce0fa5ba..fbe5a1d74c37 100644 --- a/tests/ui/moves/use_of_moved_value_copy_suggestions.rs +++ b/tests/ui/moves/use_of_moved_value_copy_suggestions.rs @@ -3,6 +3,7 @@ fn duplicate_t(t: T) -> (T, T) { //~^ HELP consider restricting type parameter `T` + //~| HELP if `T` implemented `Clone`, you could clone the value (t, t) //~ use of moved value: `t` } @@ -72,10 +73,11 @@ where #[rustfmt::skip] fn existing_colon(t: T) { //~^ HELP consider restricting type parameter `T` + //~| HELP if `T` implemented `Clone`, you could clone the value [t, t]; //~ use of moved value: `t` } -fn existing_colon_in_where(t: T) +fn existing_colon_in_where(t: T) //~ HELP if `T` implemented `Clone`, you could clone the value where T:, //~^ HELP consider further restricting type parameter `T` diff --git a/tests/ui/moves/use_of_moved_value_copy_suggestions.stderr b/tests/ui/moves/use_of_moved_value_copy_suggestions.stderr index 3e37fcb2141f..c03204c7b9f1 100644 --- a/tests/ui/moves/use_of_moved_value_copy_suggestions.stderr +++ b/tests/ui/moves/use_of_moved_value_copy_suggestions.stderr @@ -1,21 +1,29 @@ error[E0382]: use of moved value: `t` - --> $DIR/use_of_moved_value_copy_suggestions.rs:6:9 + --> $DIR/use_of_moved_value_copy_suggestions.rs:7:9 | LL | fn duplicate_t(t: T) -> (T, T) { | - move occurs because `t` has type `T`, which does not implement the `Copy` trait -LL | +... LL | (t, t) | - ^ value used here after move | | | value moved here | +help: if `T` implemented `Clone`, you could clone the value + --> $DIR/use_of_moved_value_copy_suggestions.rs:4:16 + | +LL | fn duplicate_t(t: T) -> (T, T) { + | ^ consider constraining this type parameter with `Clone` +... +LL | (t, t) + | - you could clone this value help: consider restricting type parameter `T` | LL | fn duplicate_t(t: T) -> (T, T) { | ++++++ error[E0382]: use of moved value: `t` - --> $DIR/use_of_moved_value_copy_suggestions.rs:11:9 + --> $DIR/use_of_moved_value_copy_suggestions.rs:12:9 | LL | fn duplicate_opt(t: Option) -> (Option, Option) { | - move occurs because `t` has type `Option`, which does not implement the `Copy` trait @@ -31,7 +39,7 @@ LL | fn duplicate_opt(t: Option) -> (Option, Option) { | ++++++ error[E0382]: use of moved value: `t` - --> $DIR/use_of_moved_value_copy_suggestions.rs:16:9 + --> $DIR/use_of_moved_value_copy_suggestions.rs:17:9 | LL | fn duplicate_tup1(t: (T,)) -> ((T,), (T,)) { | - move occurs because `t` has type `(T,)`, which does not implement the `Copy` trait @@ -47,7 +55,7 @@ LL | fn duplicate_tup1(t: (T,)) -> ((T,), (T,)) { | ++++++ error[E0382]: use of moved value: `t` - --> $DIR/use_of_moved_value_copy_suggestions.rs:21:9 + --> $DIR/use_of_moved_value_copy_suggestions.rs:22:9 | LL | fn duplicate_tup2(t: (A, B)) -> ((A, B), (A, B)) { | - move occurs because `t` has type `(A, B)`, which does not implement the `Copy` trait @@ -63,7 +71,7 @@ LL | fn duplicate_tup2(t: (A, B)) -> ((A, B), (A, B)) { | ++++++ ++++++ error[E0382]: use of moved value: `t` - --> $DIR/use_of_moved_value_copy_suggestions.rs:26:9 + --> $DIR/use_of_moved_value_copy_suggestions.rs:27:9 | LL | fn duplicate_custom(t: S) -> (S, S) { | - move occurs because `t` has type `S`, which does not implement the `Copy` trait @@ -79,7 +87,7 @@ LL | fn duplicate_custom(t: S) -> (S, S) { | ++++++++++++++ error[E0382]: use of moved value: `t` - --> $DIR/use_of_moved_value_copy_suggestions.rs:44:9 + --> $DIR/use_of_moved_value_copy_suggestions.rs:45:9 | LL | fn duplicate_custom_1(t: S) -> (S, S) where { | - move occurs because `t` has type `S`, which does not implement the `Copy` trait @@ -95,7 +103,7 @@ LL | fn duplicate_custom_1(t: S) -> (S, S) where { | ++++++++++++++ error[E0382]: use of moved value: `t` - --> $DIR/use_of_moved_value_copy_suggestions.rs:52:9 + --> $DIR/use_of_moved_value_copy_suggestions.rs:53:9 | LL | fn duplicate_custom_2(t: S) -> (S, S) | - move occurs because `t` has type `S`, which does not implement the `Copy` trait @@ -111,7 +119,7 @@ LL | T: A + Copy + Trait, | ++++++++++++++ error[E0382]: use of moved value: `t` - --> $DIR/use_of_moved_value_copy_suggestions.rs:61:9 + --> $DIR/use_of_moved_value_copy_suggestions.rs:62:9 | LL | fn duplicate_custom_3(t: S) -> (S, S) | - move occurs because `t` has type `S`, which does not implement the `Copy` trait @@ -127,7 +135,7 @@ LL | T: A + Copy + Trait, | ++++++++++++++ error[E0382]: use of moved value: `t` - --> $DIR/use_of_moved_value_copy_suggestions.rs:69:9 + --> $DIR/use_of_moved_value_copy_suggestions.rs:70:9 | LL | fn duplicate_custom_4(t: S) -> (S, S) | - move occurs because `t` has type `S`, which does not implement the `Copy` trait @@ -143,23 +151,31 @@ LL | fn duplicate_custom_4(t: S) -> (S, S) | ++++++++++++++ error[E0382]: use of moved value: `t` - --> $DIR/use_of_moved_value_copy_suggestions.rs:75:9 + --> $DIR/use_of_moved_value_copy_suggestions.rs:77:9 | LL | fn existing_colon(t: T) { | - move occurs because `t` has type `T`, which does not implement the `Copy` trait -LL | +... LL | [t, t]; | - ^ value used here after move | | | value moved here | +help: if `T` implemented `Clone`, you could clone the value + --> $DIR/use_of_moved_value_copy_suggestions.rs:74:19 + | +LL | fn existing_colon(t: T) { + | ^ consider constraining this type parameter with `Clone` +... +LL | [t, t]; + | - you could clone this value help: consider restricting type parameter `T` | LL | fn existing_colon(t: T) { | ++++ error[E0382]: use of moved value: `t` - --> $DIR/use_of_moved_value_copy_suggestions.rs:83:9 + --> $DIR/use_of_moved_value_copy_suggestions.rs:85:9 | LL | fn existing_colon_in_where(t: T) | - move occurs because `t` has type `T`, which does not implement the `Copy` trait @@ -169,6 +185,14 @@ LL | [t, t]; | | | value moved here | +help: if `T` implemented `Clone`, you could clone the value + --> $DIR/use_of_moved_value_copy_suggestions.rs:80:28 + | +LL | fn existing_colon_in_where(t: T) + | ^ consider constraining this type parameter with `Clone` +... +LL | [t, t]; + | - you could clone this value help: consider further restricting type parameter `T` | LL | T:, T: Copy diff --git a/tests/ui/nll/issue-21232-partial-init-and-use.stderr b/tests/ui/nll/issue-21232-partial-init-and-use.stderr index 2aff375f0a77..496a298a36ce 100644 --- a/tests/ui/nll/issue-21232-partial-init-and-use.stderr +++ b/tests/ui/nll/issue-21232-partial-init-and-use.stderr @@ -32,7 +32,10 @@ note: if `S>` implemented `Clone`, you could clone the value --> $DIR/issue-21232-partial-init-and-use.rs:15:1 | LL | struct S { - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | let mut s: S = S::new(); drop(s); + | - you could clone this value error[E0382]: assign to part of moved value: `t` --> $DIR/issue-21232-partial-init-and-use.rs:116:5 @@ -83,7 +86,10 @@ note: if `S>` implemented `Clone`, you could clone the value --> $DIR/issue-21232-partial-init-and-use.rs:15:1 | LL | struct S { - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | let mut s: S = S::new(); drop(s); + | - you could clone this value error[E0382]: assign to part of moved value: `t` --> $DIR/issue-21232-partial-init-and-use.rs:142:5 diff --git a/tests/ui/nll/move-errors.stderr b/tests/ui/nll/move-errors.stderr index 842ecaf524b4..d13841213795 100644 --- a/tests/ui/nll/move-errors.stderr +++ b/tests/ui/nll/move-errors.stderr @@ -8,7 +8,10 @@ note: if `A` implemented `Clone`, you could clone the value --> $DIR/move-errors.rs:1:1 | LL | struct A(String); - | ^^^^^^^^ + | ^^^^^^^^ consider implementing `Clone` for this type +... +LL | let b = *a; + | -- you could clone this value help: consider removing the dereference here | LL - let b = *a; @@ -28,7 +31,10 @@ note: if `A` implemented `Clone`, you could clone the value --> $DIR/move-errors.rs:1:1 | LL | struct A(String); - | ^^^^^^^^ + | ^^^^^^^^ consider implementing `Clone` for this type +... +LL | let b = a[0]; + | ---- you could clone this value help: consider borrowing here | LL | let b = &a[0]; @@ -44,7 +50,10 @@ note: if `A` implemented `Clone`, you could clone the value --> $DIR/move-errors.rs:1:1 | LL | struct A(String); - | ^^^^^^^^ + | ^^^^^^^^ consider implementing `Clone` for this type +... +LL | let s = **r; + | --- you could clone this value help: consider removing the dereference here | LL - let s = **r; @@ -61,7 +70,10 @@ note: if `A` implemented `Clone`, you could clone the value --> $DIR/move-errors.rs:1:1 | LL | struct A(String); - | ^^^^^^^^ + | ^^^^^^^^ consider implementing `Clone` for this type +... +LL | let s = *r; + | -- you could clone this value help: consider removing the dereference here | LL - let s = *r; @@ -81,7 +93,10 @@ note: if `A` implemented `Clone`, you could clone the value --> $DIR/move-errors.rs:1:1 | LL | struct A(String); - | ^^^^^^^^ + | ^^^^^^^^ consider implementing `Clone` for this type +... +LL | let a = [A("".to_string())][0]; + | ---------------------- you could clone this value help: consider borrowing here | LL | let a = &[A("".to_string())][0]; @@ -126,7 +141,10 @@ note: if `A` implemented `Clone`, you could clone the value --> $DIR/move-errors.rs:1:1 | LL | struct A(String); - | ^^^^^^^^ + | ^^^^^^^^ consider implementing `Clone` for this type +... +LL | b = *a; + | -- you could clone this value error[E0508]: cannot move out of type `[B; 1]`, a non-copy array --> $DIR/move-errors.rs:74:11 diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr index 00964cb8336e..e925fe78f339 100644 --- a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr @@ -337,7 +337,10 @@ note: if `U` implemented `Clone`, you could clone the value --> $DIR/borrowck-pat-ref-mut-and-ref.rs:17:5 | LL | struct U; - | ^^^^^^^^ + | ^^^^^^^^ consider implementing `Clone` for this type +... +LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} + | - you could clone this value error[E0507]: cannot move out of `b` in pattern guard --> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:66 @@ -350,7 +353,10 @@ note: if `U` implemented `Clone`, you could clone the value --> $DIR/borrowck-pat-ref-mut-and-ref.rs:17:5 | LL | struct U; - | ^^^^^^^^ + | ^^^^^^^^ consider implementing `Clone` for this type +... +LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} + | - you could clone this value = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0507]: cannot move out of `a` in pattern guard diff --git a/tests/ui/suggestions/option-content-move3.rs b/tests/ui/suggestions/option-content-move3.rs new file mode 100644 index 000000000000..afd8fd0c3a2f --- /dev/null +++ b/tests/ui/suggestions/option-content-move3.rs @@ -0,0 +1,17 @@ +#[derive(Debug, Clone)] +struct NotCopyable; + +fn func H, H: FnMut()>(_: F) {} + +fn parse() { + let mut var = NotCopyable; + func(|| { + // Shouldn't suggest `move ||.as_ref()` here + move || { //~ ERROR cannot move out of `var` + let x = var; //~ ERROR cannot move out of `var` + println!("{x:?}"); + } + }); +} + +fn main() {} diff --git a/tests/ui/suggestions/option-content-move3.stderr b/tests/ui/suggestions/option-content-move3.stderr new file mode 100644 index 000000000000..2d28d9b5ea7f --- /dev/null +++ b/tests/ui/suggestions/option-content-move3.stderr @@ -0,0 +1,35 @@ +error[E0507]: cannot move out of `var`, a captured variable in an `FnMut` closure + --> $DIR/option-content-move3.rs:11:21 + | +LL | let mut var = NotCopyable; + | ------- captured outer variable +... +LL | move || { + | ------- captured by this `FnMut` closure +LL | let x = var; + | ^^^ move occurs because `var` has type `NotCopyable`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | let x = &var; + | + + +error[E0507]: cannot move out of `var`, a captured variable in an `FnMut` closure + --> $DIR/option-content-move3.rs:10:9 + | +LL | let mut var = NotCopyable; + | ------- captured outer variable +LL | func(|| { + | -- captured by this `FnMut` closure +LL | // Shouldn't suggest `move ||.as_ref()` here +LL | move || { + | ^^^^^^^ `var` is moved here +LL | let x = var; + | --- + | | + | variable moved due to use in closure + | move occurs because `var` has type `NotCopyable`, which does not implement the `Copy` trait + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/union/union-borrow-move-parent-sibling.stderr b/tests/ui/union/union-borrow-move-parent-sibling.stderr index 782fa63280ed..f8e9609cb1c5 100644 --- a/tests/ui/union/union-borrow-move-parent-sibling.stderr +++ b/tests/ui/union/union-borrow-move-parent-sibling.stderr @@ -54,7 +54,10 @@ note: if `MockVec` implemented `Clone`, you could clone the value --> $DIR/union-borrow-move-parent-sibling.rs:25:1 | LL | struct MockVec { - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | let a = (u.x.0).0; + | --------- you could clone this value help: consider borrowing here | LL | let a = &(u.x.0).0; diff --git a/tests/ui/union/union-move.stderr b/tests/ui/union/union-move.stderr index 5ebb2716e5a0..d520fb00ea9d 100644 --- a/tests/ui/union/union-move.stderr +++ b/tests/ui/union/union-move.stderr @@ -20,7 +20,10 @@ note: if `U1` implemented `Clone`, you could clone the value --> $DIR/union-move.rs:9:1 | LL | union U1 { - | ^^^^^^^^ + | ^^^^^^^^ consider implementing `Clone` for this type +... +LL | move_out(x.f1_nocopy); + | ----------- you could clone this value error[E0382]: use of moved value: `x` --> $DIR/union-move.rs:42:18 @@ -44,7 +47,10 @@ note: if `U1` implemented `Clone`, you could clone the value --> $DIR/union-move.rs:9:1 | LL | union U1 { - | ^^^^^^^^ + | ^^^^^^^^ consider implementing `Clone` for this type +... +LL | move_out(x.f2_nocopy); + | ----------- you could clone this value error[E0509]: cannot move out of type `U2`, which implements the `Drop` trait --> $DIR/union-move.rs:49:18 diff --git a/tests/ui/unop-move-semantics.stderr b/tests/ui/unop-move-semantics.stderr index 187dd66b2fe5..bc9b3ea99038 100644 --- a/tests/ui/unop-move-semantics.stderr +++ b/tests/ui/unop-move-semantics.stderr @@ -33,6 +33,14 @@ LL | !x; ... LL | use_mut(n); use_imm(m); | - borrow later used here + | +help: if `T` implemented `Clone`, you could clone the value + --> $DIR/unop-move-semantics.rs:11:18 + | +LL | fn move_borrowed>(x: T, mut y: T) { + | ^ consider constraining this type parameter with `Clone` +LL | let m = &x; + | -- you could clone this value error[E0505]: cannot move out of `y` because it is borrowed --> $DIR/unop-move-semantics.rs:17:6 @@ -47,6 +55,15 @@ LL | !y; | ^ move out of `y` occurs here LL | use_mut(n); use_imm(m); | - borrow later used here + | +help: if `T` implemented `Clone`, you could clone the value + --> $DIR/unop-move-semantics.rs:11:18 + | +LL | fn move_borrowed>(x: T, mut y: T) { + | ^ consider constraining this type parameter with `Clone` +LL | let m = &x; +LL | let n = &mut y; + | ------ you could clone this value error[E0507]: cannot move out of `*m` which is behind a mutable reference --> $DIR/unop-move-semantics.rs:24:6 @@ -59,6 +76,14 @@ LL | !*m; | note: calling this operator moves the value --> $SRC_DIR/core/src/ops/bit.rs:LL:COL +help: if `T` implemented `Clone`, you could clone the value + --> $DIR/unop-move-semantics.rs:20:24 + | +LL | fn illegal_dereference>(mut x: T, y: T) { + | ^ consider constraining this type parameter with `Clone` +... +LL | !*m; + | -- you could clone this value error[E0507]: cannot move out of `*n` which is behind a shared reference --> $DIR/unop-move-semantics.rs:26:6 @@ -68,6 +93,15 @@ LL | !*n; | || | |move occurs because `*n` has type `T`, which does not implement the `Copy` trait | `*n` moved due to usage in operator + | +help: if `T` implemented `Clone`, you could clone the value + --> $DIR/unop-move-semantics.rs:20:24 + | +LL | fn illegal_dereference>(mut x: T, y: T) { + | ^ consider constraining this type parameter with `Clone` +... +LL | !*n; + | -- you could clone this value error: aborting due to 5 previous errors diff --git a/tests/ui/variance/variance-issue-20533.stderr b/tests/ui/variance/variance-issue-20533.stderr index 4515d313ec0a..03cada07a9e3 100644 --- a/tests/ui/variance/variance-issue-20533.stderr +++ b/tests/ui/variance/variance-issue-20533.stderr @@ -14,7 +14,10 @@ note: if `AffineU32` implemented `Clone`, you could clone the value --> $DIR/variance-issue-20533.rs:26:1 | LL | struct AffineU32(u32); - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | let x = foo(&a); + | -- you could clone this value error[E0505]: cannot move out of `a` because it is borrowed --> $DIR/variance-issue-20533.rs:41:14 @@ -32,7 +35,10 @@ note: if `AffineU32` implemented `Clone`, you could clone the value --> $DIR/variance-issue-20533.rs:26:1 | LL | struct AffineU32(u32); - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | let x = bar(&a); + | -- you could clone this value error[E0505]: cannot move out of `a` because it is borrowed --> $DIR/variance-issue-20533.rs:47:14 @@ -50,7 +56,10 @@ note: if `AffineU32` implemented `Clone`, you could clone the value --> $DIR/variance-issue-20533.rs:26:1 | LL | struct AffineU32(u32); - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | let x = baz(&a); + | -- you could clone this value error[E0505]: cannot move out of `a` because it is borrowed --> $DIR/variance-issue-20533.rs:53:14 From ad9a5a5f9f5dcd440eff22f29c11b4129d2ee338 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 19 Apr 2024 04:26:42 +0000 Subject: [PATCH 36/36] Suggest cloning captured binding in `move` closure ``` error[E0507]: cannot move out of `bar`, a captured variable in an `FnMut` closure --> $DIR/borrowck-move-by-capture.rs:9:29 | LL | let bar: Box<_> = Box::new(3); | --- captured outer variable LL | let _g = to_fn_mut(|| { | -- captured by this `FnMut` closure LL | let _h = to_fn_once(move || -> isize { *bar }); | ^^^^^^^^^^^^^^^^ ---- | | | | | variable moved due to use in closure | | move occurs because `bar` has type `Box`, which does not implement the `Copy` trait | `bar` is moved here | help: clone the value before moving it into the closure | LL ~ let value = bar.clone(); LL ~ let _h = to_fn_once(move || -> isize { value }); | ``` --- .../src/diagnostics/conflict_errors.rs | 2 +- .../src/diagnostics/move_errors.rs | 142 +++++++++++++++++- .../src/traits/error_reporting/mod.rs | 11 +- .../borrowck/borrowck-move-by-capture.stderr | 6 + tests/ui/suggestions/option-content-move2.rs | 14 +- .../suggestions/option-content-move2.stderr | 21 ++- tests/ui/suggestions/option-content-move3.rs | 19 ++- .../suggestions/option-content-move3.stderr | 74 ++++++++- 8 files changed, 267 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 8215dc68c086..93ea8fb6979a 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1241,7 +1241,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } - fn implements_clone(&self, ty: Ty<'tcx>) -> bool { + pub(crate) fn implements_clone(&self, ty: Ty<'tcx>) -> bool { let Some(clone_trait_def) = self.infcx.tcx.lang_items().clone_trait() else { return false }; self.infcx .type_implements_trait(clone_trait_def, [ty], self.param_env) diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 1bbf36355cbe..288b846daf56 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -2,10 +2,13 @@ #![allow(rustc::untranslatable_diagnostic)] use rustc_errors::{Applicability, Diag}; +use rustc_hir::intravisit::Visitor; +use rustc_hir::{CaptureBy, ExprKind, HirId, Node}; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty}; use rustc_mir_dataflow::move_paths::{LookupResult, MovePathIndex}; use rustc_span::{BytePos, ExpnKind, MacroKind, Span}; +use rustc_trait_selection::traits::error_reporting::FindExprBySpan; use crate::diagnostics::CapturedMessageOpt; use crate::diagnostics::{DescribePlaceOpt, UseSpans}; @@ -303,6 +306,121 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { self.cannot_move_out_of(span, &description) } + fn suggest_clone_of_captured_var_in_move_closure( + &self, + err: &mut Diag<'_>, + upvar_hir_id: HirId, + upvar_name: &str, + use_spans: Option>, + ) { + let tcx = self.infcx.tcx; + let typeck_results = tcx.typeck(self.mir_def_id()); + let Some(use_spans) = use_spans else { return }; + // We only care about the case where a closure captured a binding. + let UseSpans::ClosureUse { args_span, .. } = use_spans else { return }; + let Some(body_id) = tcx.hir_node(self.mir_hir_id()).body_id() else { return }; + // Fetch the type of the expression corresponding to the closure-captured binding. + let Some(captured_ty) = typeck_results.node_type_opt(upvar_hir_id) else { return }; + if !self.implements_clone(captured_ty) { + // We only suggest cloning the captured binding if the type can actually be cloned. + return; + }; + // Find the closure that captured the binding. + let mut expr_finder = FindExprBySpan::new(args_span, tcx); + expr_finder.include_closures = true; + expr_finder.visit_expr(tcx.hir().body(body_id).value); + let Some(closure_expr) = expr_finder.result else { return }; + let ExprKind::Closure(closure) = closure_expr.kind else { return }; + // We'll only suggest cloning the binding if it's a `move` closure. + let CaptureBy::Value { .. } = closure.capture_clause else { return }; + // Find the expression within the closure where the binding is consumed. + let mut suggested = false; + let use_span = use_spans.var_or_use(); + let mut expr_finder = FindExprBySpan::new(use_span, tcx); + expr_finder.include_closures = true; + expr_finder.visit_expr(tcx.hir().body(body_id).value); + let Some(use_expr) = expr_finder.result else { return }; + let parent = tcx.parent_hir_node(use_expr.hir_id); + if let Node::Expr(expr) = parent + && let ExprKind::Assign(lhs, ..) = expr.kind + && lhs.hir_id == use_expr.hir_id + { + // Cloning the value being assigned makes no sense: + // + // error[E0507]: cannot move out of `var`, a captured variable in an `FnMut` closure + // --> $DIR/option-content-move2.rs:11:9 + // | + // LL | let mut var = None; + // | ------- captured outer variable + // LL | func(|| { + // | -- captured by this `FnMut` closure + // LL | // Shouldn't suggest `move ||.as_ref()` here + // LL | move || { + // | ^^^^^^^ `var` is moved here + // LL | + // LL | var = Some(NotCopyable); + // | --- + // | | + // | variable moved due to use in closure + // | move occurs because `var` has type `Option`, which does not implement the `Copy` trait + // | + return; + } + + // Search for an appropriate place for the structured `.clone()` suggestion to be applied. + // If we encounter a statement before the borrow error, we insert a statement there. + for (_, node) in tcx.hir().parent_iter(closure_expr.hir_id) { + if let Node::Stmt(stmt) = node { + let padding = tcx + .sess + .source_map() + .indentation_before(stmt.span) + .unwrap_or_else(|| " ".to_string()); + err.multipart_suggestion_verbose( + "clone the value before moving it into the closure", + vec![ + ( + stmt.span.shrink_to_lo(), + format!("let value = {upvar_name}.clone();\n{padding}"), + ), + (use_span, "value".to_string()), + ], + Applicability::MachineApplicable, + ); + suggested = true; + break; + } else if let Node::Expr(expr) = node + && let ExprKind::Closure(_) = expr.kind + { + // We want to suggest cloning only on the first closure, not + // subsequent ones (like `ui/suggestions/option-content-move2.rs`). + break; + } + } + if !suggested { + // If we couldn't find a statement for us to insert a new `.clone()` statement before, + // we have a bare expression, so we suggest the creation of a new block inline to go + // from `move || val` to `{ let value = val.clone(); move || value }`. + let padding = tcx + .sess + .source_map() + .indentation_before(closure_expr.span) + .unwrap_or_else(|| " ".to_string()); + err.multipart_suggestion_verbose( + "clone the value before moving it into the closure", + vec![ + ( + closure_expr.span.shrink_to_lo(), + format!("{{\n{padding}let value = {upvar_name}.clone();\n{padding}"), + ), + (use_spans.var_or_use(), "value".to_string()), + (closure_expr.span.shrink_to_hi(), format!("\n{padding}}}")), + ], + Applicability::MachineApplicable, + ); + } + } + fn report_cannot_move_from_borrowed_content( &mut self, move_place: Place<'tcx>, @@ -310,10 +428,11 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { span: Span, use_spans: Option>, ) -> Diag<'tcx> { + let tcx = self.infcx.tcx; // Inspect the type of the content behind the // borrow to provide feedback about why this // was a move rather than a copy. - let ty = deref_target_place.ty(self.body, self.infcx.tcx).ty; + let ty = deref_target_place.ty(self.body, tcx).ty; let upvar_field = self .prefixes(move_place.as_ref(), PrefixSet::All) .find_map(|p| self.is_upvar_field_projection(p)); @@ -363,8 +482,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let upvar = &self.upvars[upvar_field.unwrap().index()]; let upvar_hir_id = upvar.get_root_variable(); - let upvar_name = upvar.to_string(self.infcx.tcx); - let upvar_span = self.infcx.tcx.hir().span(upvar_hir_id); + let upvar_name = upvar.to_string(tcx); + let upvar_span = tcx.hir().span(upvar_hir_id); let place_name = self.describe_any_place(move_place.as_ref()); @@ -380,12 +499,21 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { closure_kind_ty, closure_kind, place_description, ); - self.cannot_move_out_of(span, &place_description) + let closure_span = tcx.def_span(def_id); + let mut err = self + .cannot_move_out_of(span, &place_description) .with_span_label(upvar_span, "captured outer variable") .with_span_label( - self.infcx.tcx.def_span(def_id), + closure_span, format!("captured by this `{closure_kind}` closure"), - ) + ); + self.suggest_clone_of_captured_var_in_move_closure( + &mut err, + upvar_hir_id, + &upvar_name, + use_spans, + ); + err } _ => { let source = self.borrowed_content_source(deref_base); @@ -415,7 +543,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { ), (_, _, _) => self.cannot_move_out_of( span, - &source.describe_for_unnamed_place(self.infcx.tcx), + &source.describe_for_unnamed_place(tcx), ), } } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 4731f11ad323..e50edfdc656c 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -50,12 +50,13 @@ pub struct FindExprBySpan<'hir> { pub span: Span, pub result: Option<&'hir hir::Expr<'hir>>, pub ty_result: Option<&'hir hir::Ty<'hir>>, + pub include_closures: bool, pub tcx: TyCtxt<'hir>, } impl<'hir> FindExprBySpan<'hir> { pub fn new(span: Span, tcx: TyCtxt<'hir>) -> Self { - Self { span, result: None, ty_result: None, tcx } + Self { span, result: None, ty_result: None, tcx, include_closures: false } } } @@ -70,9 +71,17 @@ impl<'v> Visitor<'v> for FindExprBySpan<'v> { if self.span == ex.span { self.result = Some(ex); } else { + if let hir::ExprKind::Closure(..) = ex.kind + && self.include_closures + && let closure_header_sp = self.span.with_hi(ex.span.hi()) + && closure_header_sp == ex.span + { + self.result = Some(ex); + } hir::intravisit::walk_expr(self, ex); } } + fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) { if self.span == ty.span { self.ty_result = Some(ty); diff --git a/tests/ui/borrowck/borrowck-move-by-capture.stderr b/tests/ui/borrowck/borrowck-move-by-capture.stderr index 01647011207f..9915acfe0653 100644 --- a/tests/ui/borrowck/borrowck-move-by-capture.stderr +++ b/tests/ui/borrowck/borrowck-move-by-capture.stderr @@ -11,6 +11,12 @@ LL | let _h = to_fn_once(move || -> isize { *bar }); | | variable moved due to use in closure | | move occurs because `bar` has type `Box`, which does not implement the `Copy` trait | `bar` is moved here + | +help: clone the value before moving it into the closure + | +LL ~ let value = bar.clone(); +LL ~ let _h = to_fn_once(move || -> isize { value }); + | error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/option-content-move2.rs b/tests/ui/suggestions/option-content-move2.rs index 88e8a5b7aeef..b0104d9bafb7 100644 --- a/tests/ui/suggestions/option-content-move2.rs +++ b/tests/ui/suggestions/option-content-move2.rs @@ -1,8 +1,10 @@ struct NotCopyable; +#[derive(Clone)] +struct NotCopyableButCloneable; fn func H, H: FnMut()>(_: F) {} -fn parse() { +fn foo() { let mut var = None; func(|| { // Shouldn't suggest `move ||.as_ref()` here @@ -12,5 +14,15 @@ fn parse() { } }); } +fn bar() { + let mut var = None; + func(|| { + // Shouldn't suggest `move ||.as_ref()` nor to `clone()` here + move || { + //~^ ERROR: cannot move out of `var` + var = Some(NotCopyableButCloneable); + } + }); +} fn main() {} diff --git a/tests/ui/suggestions/option-content-move2.stderr b/tests/ui/suggestions/option-content-move2.stderr index 0297c031ecca..be97cba17b90 100644 --- a/tests/ui/suggestions/option-content-move2.stderr +++ b/tests/ui/suggestions/option-content-move2.stderr @@ -1,5 +1,5 @@ error[E0507]: cannot move out of `var`, a captured variable in an `FnMut` closure - --> $DIR/option-content-move2.rs:9:9 + --> $DIR/option-content-move2.rs:11:9 | LL | let mut var = None; | ------- captured outer variable @@ -15,6 +15,23 @@ LL | var = Some(NotCopyable); | variable moved due to use in closure | move occurs because `var` has type `Option`, which does not implement the `Copy` trait -error: aborting due to 1 previous error +error[E0507]: cannot move out of `var`, a captured variable in an `FnMut` closure + --> $DIR/option-content-move2.rs:21:9 + | +LL | let mut var = None; + | ------- captured outer variable +LL | func(|| { + | -- captured by this `FnMut` closure +LL | // Shouldn't suggest `move ||.as_ref()` nor to `clone()` here +LL | move || { + | ^^^^^^^ `var` is moved here +LL | +LL | var = Some(NotCopyableButCloneable); + | --- + | | + | variable moved due to use in closure + | move occurs because `var` has type `Option`, which does not implement the `Copy` trait + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/suggestions/option-content-move3.rs b/tests/ui/suggestions/option-content-move3.rs index afd8fd0c3a2f..a245309d97fd 100644 --- a/tests/ui/suggestions/option-content-move3.rs +++ b/tests/ui/suggestions/option-content-move3.rs @@ -1,10 +1,23 @@ -#[derive(Debug, Clone)] +#[derive(Debug)] struct NotCopyable; +#[derive(Debug, Clone)] +struct NotCopyableButCloneable; fn func H, H: FnMut()>(_: F) {} -fn parse() { - let mut var = NotCopyable; +fn foo() { + let var = NotCopyable; + func(|| { + // Shouldn't suggest `move ||.as_ref()` here + move || { //~ ERROR cannot move out of `var` + let x = var; //~ ERROR cannot move out of `var` + println!("{x:?}"); + } + }); +} + +fn bar() { + let var = NotCopyableButCloneable; func(|| { // Shouldn't suggest `move ||.as_ref()` here move || { //~ ERROR cannot move out of `var` diff --git a/tests/ui/suggestions/option-content-move3.stderr b/tests/ui/suggestions/option-content-move3.stderr index 2d28d9b5ea7f..a20dcce1ee31 100644 --- a/tests/ui/suggestions/option-content-move3.stderr +++ b/tests/ui/suggestions/option-content-move3.stderr @@ -1,24 +1,32 @@ error[E0507]: cannot move out of `var`, a captured variable in an `FnMut` closure - --> $DIR/option-content-move3.rs:11:21 + --> $DIR/option-content-move3.rs:13:21 | -LL | let mut var = NotCopyable; - | ------- captured outer variable +LL | let var = NotCopyable; + | --- captured outer variable ... LL | move || { | ------- captured by this `FnMut` closure LL | let x = var; | ^^^ move occurs because `var` has type `NotCopyable`, which does not implement the `Copy` trait | +note: if `NotCopyable` implemented `Clone`, you could clone the value + --> $DIR/option-content-move3.rs:2:1 + | +LL | struct NotCopyable; + | ^^^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | let x = var; + | --- you could clone this value help: consider borrowing here | LL | let x = &var; | + error[E0507]: cannot move out of `var`, a captured variable in an `FnMut` closure - --> $DIR/option-content-move3.rs:10:9 + --> $DIR/option-content-move3.rs:12:9 | -LL | let mut var = NotCopyable; - | ------- captured outer variable +LL | let var = NotCopyable; + | --- captured outer variable LL | func(|| { | -- captured by this `FnMut` closure LL | // Shouldn't suggest `move ||.as_ref()` here @@ -29,7 +37,59 @@ LL | let x = var; | | | variable moved due to use in closure | move occurs because `var` has type `NotCopyable`, which does not implement the `Copy` trait + | +note: if `NotCopyable` implemented `Clone`, you could clone the value + --> $DIR/option-content-move3.rs:2:1 + | +LL | struct NotCopyable; + | ^^^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type +... +LL | let x = var; + | --- you could clone this value -error: aborting due to 2 previous errors +error[E0507]: cannot move out of `var`, a captured variable in an `FnMut` closure + --> $DIR/option-content-move3.rs:24:21 + | +LL | let var = NotCopyableButCloneable; + | --- captured outer variable +... +LL | move || { + | ------- captured by this `FnMut` closure +LL | let x = var; + | ^^^ move occurs because `var` has type `NotCopyableButCloneable`, which does not implement the `Copy` trait + | +help: consider borrowing here + | +LL | let x = &var; + | + + +error[E0507]: cannot move out of `var`, a captured variable in an `FnMut` closure + --> $DIR/option-content-move3.rs:23:9 + | +LL | let var = NotCopyableButCloneable; + | --- captured outer variable +LL | func(|| { + | -- captured by this `FnMut` closure +LL | // Shouldn't suggest `move ||.as_ref()` here +LL | move || { + | ^^^^^^^ `var` is moved here +LL | let x = var; + | --- + | | + | variable moved due to use in closure + | move occurs because `var` has type `NotCopyableButCloneable`, which does not implement the `Copy` trait + | +help: clone the value before moving it into the closure + | +LL ~ { +LL + let value = var.clone(); +LL ~ move || { +LL ~ let x = value; +LL | println!("{x:?}"); +LL ~ } +LL + } + | + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0507`.