From 60ee6fbaa464d4d65313a7919c07113ef6068140 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Thu, 31 Oct 2024 11:39:45 +0100 Subject: [PATCH 001/606] Update tests. --- example/mini_core.rs | 2 +- example/mini_core_hello_world.rs | 4 ++-- example/mod_bench.rs | 2 +- example/std_example.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/example/mini_core.rs b/example/mini_core.rs index cdd151613df8..685e03c07c18 100644 --- a/example/mini_core.rs +++ b/example/mini_core.rs @@ -681,7 +681,7 @@ impl Index for [T] { } } -extern { +extern "C" { type VaListImpl; } diff --git a/example/mini_core_hello_world.rs b/example/mini_core_hello_world.rs index dcfa34cb729d..1d51e0a1856b 100644 --- a/example/mini_core_hello_world.rs +++ b/example/mini_core_hello_world.rs @@ -258,13 +258,13 @@ fn main() { assert_eq!(((|()| 42u8) as fn(()) -> u8)(()), 42); - extern { + extern "C" { #[linkage = "weak"] static ABC: *const u8; } { - extern { + extern "C" { #[linkage = "weak"] static ABC: *const u8; } diff --git a/example/mod_bench.rs b/example/mod_bench.rs index cae911c1073d..e8a9cade7474 100644 --- a/example/mod_bench.rs +++ b/example/mod_bench.rs @@ -3,7 +3,7 @@ #![allow(internal_features)] #[link(name = "c")] -extern {} +extern "C" {} #[panic_handler] fn panic_handler(_: &core::panic::PanicInfo<'_>) -> ! { diff --git a/example/std_example.rs b/example/std_example.rs index 9e43b4635f0d..5fa1e0afb060 100644 --- a/example/std_example.rs +++ b/example/std_example.rs @@ -7,7 +7,7 @@ use std::arch::x86_64::*; use std::io::Write; use std::ops::Coroutine; -extern { +extern "C" { pub fn printf(format: *const i8, ...) -> i32; } From 0f89f3ffd438d145a0896c6c86de3bf46d7e14df Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sun, 15 Dec 2024 11:03:37 +0000 Subject: [PATCH 002/606] Use a C-safe return type for `__rust_[ui]128_*` overflowing intrinsics Combined with [1], this will change the overflowing multiplication operations to return an `extern "C"`-safe type. Link: https://github.com/rust-lang/compiler-builtins/pull/735 [1] --- src/int.rs | 119 +++++++++++++++++++++---------------------- src/intrinsic/mod.rs | 6 ++- 2 files changed, 62 insertions(+), 63 deletions(-) diff --git a/src/int.rs b/src/int.rs index 7b9d1feb8d71..fe6a65bed03b 100644 --- a/src/int.rs +++ b/src/int.rs @@ -322,36 +322,26 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { }, } } else { - match new_kind { - Int(I128) | Uint(U128) => { - let func_name = match oop { - OverflowOp::Add => match new_kind { - Int(I128) => "__rust_i128_addo", - Uint(U128) => "__rust_u128_addo", - _ => unreachable!(), - }, - OverflowOp::Sub => match new_kind { - Int(I128) => "__rust_i128_subo", - Uint(U128) => "__rust_u128_subo", - _ => unreachable!(), - }, - OverflowOp::Mul => match new_kind { - Int(I128) => "__rust_i128_mulo", // TODO(antoyo): use __muloti4d instead? - Uint(U128) => "__rust_u128_mulo", - _ => unreachable!(), - }, - }; - return self.operation_with_overflow(func_name, lhs, rhs); - } - _ => match oop { - OverflowOp::Mul => match new_kind { - Int(I32) => "__mulosi4", - Int(I64) => "__mulodi4", - _ => unreachable!(), - }, - _ => unimplemented!("overflow operation for {:?}", new_kind), + let (func_name, width) = match oop { + OverflowOp::Add => match new_kind { + Int(I128) => ("__rust_i128_addo", 128), + Uint(U128) => ("__rust_u128_addo", 128), + _ => unreachable!(), }, - } + OverflowOp::Sub => match new_kind { + Int(I128) => ("__rust_i128_subo", 128), + Uint(U128) => ("__rust_u128_subo", 128), + _ => unreachable!(), + }, + OverflowOp::Mul => match new_kind { + Int(I32) => ("__mulosi4", 32), + Int(I64) => ("__mulodi4", 64), + Int(I128) => ("__rust_i128_mulo", 128), // TODO(antoyo): use __muloti4d instead? + Uint(U128) => ("__rust_u128_mulo", 128), + _ => unreachable!(), + }, + }; + return self.operation_with_overflow(func_name, lhs, rhs, width); }; let intrinsic = self.context.get_builtin_function(name); @@ -364,80 +354,87 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { (res.dereference(self.location).to_rvalue(), overflow) } + /// Non-`__builtin_*` overflow operations with a `fn(T, T, &mut i32) -> T` signature. pub fn operation_with_overflow( &self, func_name: &str, lhs: RValue<'gcc>, rhs: RValue<'gcc>, + width: u64, ) -> (RValue<'gcc>, RValue<'gcc>) { let a_type = lhs.get_type(); let b_type = rhs.get_type(); debug_assert!(a_type.dyncast_array().is_some()); debug_assert!(b_type.dyncast_array().is_some()); + let overflow_type = self.i32_type; + let overflow_param_type = overflow_type.make_pointer(); + let res_type = a_type; + + let overflow_value = + self.current_func().new_local(self.location, overflow_type, "overflow"); + let overflow_addr = overflow_value.get_address(self.location); + let param_a = self.context.new_parameter(self.location, a_type, "a"); let param_b = self.context.new_parameter(self.location, b_type, "b"); - let result_field = self.context.new_field(self.location, a_type, "result"); - let overflow_field = self.context.new_field(self.location, self.bool_type, "overflow"); + let param_overflow = + self.context.new_parameter(self.location, overflow_param_type, "overflow"); - let ret_ty = Ty::new_tup(self.tcx, &[self.tcx.types.i128, self.tcx.types.bool]); + let a_elem_type = a_type.dyncast_array().expect("non-array a value"); + debug_assert!(a_elem_type.is_integral()); + let res_ty = match width { + 32 => self.tcx.types.i32, + 64 => self.tcx.types.i64, + 128 => self.tcx.types.i128, + _ => unreachable!("unexpected integer size"), + }; let layout = self .tcx - .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ret_ty)) + .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(res_ty)) .unwrap(); let arg_abi = ArgAbi { layout, mode: PassMode::Direct(ArgAttributes::new()) }; let mut fn_abi = FnAbi { - args: vec![arg_abi.clone(), arg_abi.clone()].into_boxed_slice(), + args: vec![arg_abi.clone(), arg_abi.clone(), arg_abi.clone()].into_boxed_slice(), ret: arg_abi, c_variadic: false, - fixed_count: 2, + fixed_count: 3, conv: Conv::C, can_unwind: false, }; fn_abi.adjust_for_foreign_abi(self.cx, spec::abi::Abi::C { unwind: false }).unwrap(); - let indirect = matches!(fn_abi.ret.mode, PassMode::Indirect { .. }); + let ret_indirect = matches!(fn_abi.ret.mode, PassMode::Indirect { .. }); + + let result = if ret_indirect { + let res_value = self.current_func().new_local(self.location, res_type, "result_value"); + let res_addr = res_value.get_address(self.location); + let res_param_type = res_type.make_pointer(); + let param_res = self.context.new_parameter(self.location, res_param_type, "result"); - let return_type = self - .context - .new_struct_type(self.location, "result_overflow", &[result_field, overflow_field]); - let result = if indirect { - let return_value = - self.current_func().new_local(self.location, return_type.as_type(), "return_value"); - let return_param_type = return_type.as_type().make_pointer(); - let return_param = - self.context.new_parameter(self.location, return_param_type, "return_value"); let func = self.context.new_function( self.location, FunctionType::Extern, self.type_void(), - &[return_param, param_a, param_b], + &[param_res, param_a, param_b, param_overflow], func_name, false, ); - self.llbb().add_eval( - self.location, - self.context.new_call(self.location, func, &[ - return_value.get_address(self.location), - lhs, - rhs, - ]), - ); - return_value.to_rvalue() + let _void = + self.context.new_call(self.location, func, &[res_addr, lhs, rhs, overflow_addr]); + res_value.to_rvalue() } else { let func = self.context.new_function( self.location, FunctionType::Extern, - return_type.as_type(), - &[param_a, param_b], + res_type, + &[param_a, param_b, param_overflow], func_name, false, ); - self.context.new_call(self.location, func, &[lhs, rhs]) + self.context.new_call(self.location, func, &[lhs, rhs, overflow_addr]) }; - let overflow = result.access_field(self.location, overflow_field); - let int_result = result.access_field(self.location, result_field); - (int_result, overflow) + + (result, self.context.new_cast(self.location, overflow_value, self.bool_type).to_rvalue()) } pub fn gcc_icmp( diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 42d189d1b7d3..48606f5f91c0 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -1001,7 +1001,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { 128 => "__rust_i128_addo", _ => unreachable!(), }; - let (int_result, overflow) = self.operation_with_overflow(func_name, lhs, rhs); + let (int_result, overflow) = + self.operation_with_overflow(func_name, lhs, rhs, width); self.llbb().add_assignment(self.location, res, int_result); overflow }; @@ -1071,7 +1072,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { 128 => "__rust_i128_subo", _ => unreachable!(), }; - let (int_result, overflow) = self.operation_with_overflow(func_name, lhs, rhs); + let (int_result, overflow) = + self.operation_with_overflow(func_name, lhs, rhs, width); self.llbb().add_assignment(self.location, res, int_result); overflow }; From 4600047767f36d12dff51e2b844ed67f81d7adda Mon Sep 17 00:00:00 2001 From: Kyle Huey Date: Fri, 17 Jan 2025 09:44:09 -0800 Subject: [PATCH 003/606] When LLVM's location discriminator value limit is exceeded, emit locations with dummy spans instead of dropping them entirely Revert most of #133194 (except the test and the comment fixes). Then refix not emitting locations at all when the correct location discriminator value exceeds LLVM's capacity. --- src/debuginfo.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/debuginfo.rs b/src/debuginfo.rs index d3aeb7f3bdeb..4b84b1dbfd39 100644 --- a/src/debuginfo.rs +++ b/src/debuginfo.rs @@ -113,15 +113,15 @@ fn make_mir_scope<'gcc, 'tcx>( let scope_data = &mir.source_scopes[scope]; let parent_scope = if let Some(parent) = scope_data.parent_scope { make_mir_scope(cx, _instance, mir, variables, debug_context, instantiated, parent); - debug_context.scopes[parent].unwrap() + debug_context.scopes[parent] } else { // The root is the function itself. let file = cx.sess().source_map().lookup_source_file(mir.span.lo()); - debug_context.scopes[scope] = Some(DebugScope { + debug_context.scopes[scope] = DebugScope { file_start_pos: file.start_pos, file_end_pos: file.end_position(), - ..debug_context.scopes[scope].unwrap() - }); + ..debug_context.scopes[scope] + }; instantiated.insert(scope); return; }; @@ -130,7 +130,7 @@ fn make_mir_scope<'gcc, 'tcx>( if !vars.contains(scope) && scope_data.inlined.is_none() { // Do not create a DIScope if there are no variables defined in this // MIR `SourceScope`, and it's not `inlined`, to avoid debuginfo bloat. - debug_context.scopes[scope] = Some(parent_scope); + debug_context.scopes[scope] = parent_scope; instantiated.insert(scope); return; } @@ -157,12 +157,12 @@ fn make_mir_scope<'gcc, 'tcx>( // TODO(tempdragon): dbg_scope: Add support for scope extension here. inlined_at.or(p_inlined_at); - debug_context.scopes[scope] = Some(DebugScope { + debug_context.scopes[scope] = DebugScope { dbg_scope, inlined_at, file_start_pos: loc.file.start_pos, file_end_pos: loc.file.end_position(), - }); + }; instantiated.insert(scope); } @@ -232,12 +232,12 @@ impl<'gcc, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { } // Initialize fn debug context (including scopes). - let empty_scope = Some(DebugScope { + let empty_scope = DebugScope { dbg_scope: self.dbg_scope_fn(instance, fn_abi, Some(llfn)), inlined_at: None, file_start_pos: BytePos(0), file_end_pos: BytePos(0), - }); + }; let mut fn_debug_context = FunctionDebugContext { scopes: IndexVec::from_elem(empty_scope, mir.source_scopes.as_slice()), inlined_function_scopes: Default::default(), From 49e047f5aa09d8179dce0d36df8a8263b144de81 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 8 Jan 2025 15:00:25 +0000 Subject: [PATCH 004/606] Treat undef bytes as equal to any other byte --- src/common.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/common.rs b/src/common.rs index f43743fc2a41..bd5d6ba387cf 100644 --- a/src/common.rs +++ b/src/common.rs @@ -64,6 +64,11 @@ impl<'gcc, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { if type_is_pointer(typ) { self.context.new_null(typ) } else { self.const_int(typ, 0) } } + fn is_undef(&self, _val: RValue<'gcc>) -> bool { + // FIXME: actually check for undef + false + } + fn const_undef(&self, typ: Type<'gcc>) -> RValue<'gcc> { let local = self.current_func.borrow().expect("func").new_local(None, typ, "undefined"); if typ.is_struct().is_some() { From 301d2478e04264d1336572a810c33108ec0a278f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 14 Dec 2024 09:13:12 +0100 Subject: [PATCH 005/606] remove support for the #[start] attribute --- build_system/src/test.rs | 26 ----------------------- example/alloc_example.rs | 7 ++++--- example/mini_core_hello_world.rs | 2 +- example/mod_bench.rs | 36 -------------------------------- src/context.rs | 1 - tests/run/abort1.rs | 7 ++++--- tests/run/abort2.rs | 7 ++++--- tests/run/array.rs | 7 ++++--- tests/run/assign.rs | 7 ++++--- tests/run/closure.rs | 7 ++++--- tests/run/condition.rs | 7 ++++--- tests/run/empty_main.rs | 7 ++++--- tests/run/exit.rs | 7 ++++--- tests/run/exit_code.rs | 7 ++++--- tests/run/fun_ptr.rs | 7 ++++--- tests/run/mut_ref.rs | 7 ++++--- tests/run/operations.rs | 7 ++++--- tests/run/ptr_cast.rs | 7 ++++--- tests/run/return-tuple.rs | 7 ++++--- tests/run/slice.rs | 7 ++++--- tests/run/static.rs | 7 ++++--- tests/run/structs.rs | 7 ++++--- tests/run/tuple.rs | 7 ++++--- 23 files changed, 77 insertions(+), 121 deletions(-) delete mode 100644 example/mod_bench.rs diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 7cc7336612c7..0e790a4befc9 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -426,19 +426,6 @@ fn std_tests(env: &Env, args: &TestArg) -> Result<(), String> { run_command_with_env(&command, None, Some(env))?; maybe_run_command_in_vm(&[&cargo_target_dir.join("track-caller-attribute")], env, args)?; - // FIXME: create a function "display_if_not_quiet" or something along the line. - println!("[AOT] mod_bench"); - let mut command = args.config_info.rustc_command_vec(); - command.extend_from_slice(&[ - &"example/mod_bench.rs", - &"--crate-type", - &"bin", - &"--target", - &args.config_info.target_triple, - ]); - run_command_with_env(&command, None, Some(env))?; - // FIXME: the compiled binary is not run. - Ok(()) } @@ -696,19 +683,6 @@ fn test_libcore(env: &Env, args: &TestArg) -> Result<(), String> { Ok(()) } -// echo "[BENCH COMPILE] mod_bench" -// -// COMPILE_MOD_BENCH_INLINE="$RUSTC example/mod_bench.rs --crate-type bin -Zmir-opt-level=3 -O --crate-name mod_bench_inline" -// COMPILE_MOD_BENCH_LLVM_0="rustc example/mod_bench.rs --crate-type bin -Copt-level=0 -o $cargo_target_dir/mod_bench_llvm_0 -Cpanic=abort" -// COMPILE_MOD_BENCH_LLVM_1="rustc example/mod_bench.rs --crate-type bin -Copt-level=1 -o $cargo_target_dir/mod_bench_llvm_1 -Cpanic=abort" -// COMPILE_MOD_BENCH_LLVM_2="rustc example/mod_bench.rs --crate-type bin -Copt-level=2 -o $cargo_target_dir/mod_bench_llvm_2 -Cpanic=abort" -// COMPILE_MOD_BENCH_LLVM_3="rustc example/mod_bench.rs --crate-type bin -Copt-level=3 -o $cargo_target_dir/mod_bench_llvm_3 -Cpanic=abort" -// -// Use 100 runs, because a single compilations doesn't take more than ~150ms, so it isn't very slow -// hyperfine --runs ${COMPILE_RUNS:-100} "$COMPILE_MOD_BENCH_INLINE" "$COMPILE_MOD_BENCH_LLVM_0" "$COMPILE_MOD_BENCH_LLVM_1" "$COMPILE_MOD_BENCH_LLVM_2" "$COMPILE_MOD_BENCH_LLVM_3" -// echo "[BENCH RUN] mod_bench" -// hyperfine --runs ${RUN_RUNS:-10} $cargo_target_dir/mod_bench{,_inline} $cargo_target_dir/mod_bench_llvm_* - fn extended_rand_tests(env: &Env, args: &TestArg) -> Result<(), String> { if !args.is_using_gcc_master_branch() { println!("Not using GCC master branch. Skipping `extended_rand_tests`."); diff --git a/example/alloc_example.rs b/example/alloc_example.rs index 6ed8b9157f21..9a0b46d5b221 100644 --- a/example/alloc_example.rs +++ b/example/alloc_example.rs @@ -1,5 +1,6 @@ -#![feature(start, core_intrinsics, alloc_error_handler, lang_items)] +#![feature(core_intrinsics, alloc_error_handler, lang_items)] #![no_std] +#![no_main] #![allow(internal_features)] extern crate alloc; @@ -37,8 +38,8 @@ unsafe extern "C" fn _Unwind_Resume() { core::intrinsics::unreachable(); } -#[start] -fn main(_argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(_argc: core::ffi::c_int, _argv: *const *const u8) -> core::ffi::c_int { let world: Box<&str> = Box::new("Hello World!\0"); unsafe { puts(*world as *const str as *const u8); diff --git a/example/mini_core_hello_world.rs b/example/mini_core_hello_world.rs index 1d51e0a1856b..4cbe66c5e4c6 100644 --- a/example/mini_core_hello_world.rs +++ b/example/mini_core_hello_world.rs @@ -1,7 +1,7 @@ // Adapted from https://github.com/sunfishcode/mir2cranelift/blob/master/rust-examples/nocore-hello-world.rs #![feature( - no_core, unboxed_closures, start, lang_items, never_type, linkage, + no_core, unboxed_closures, lang_items, never_type, linkage, extern_types, thread_local )] #![no_core] diff --git a/example/mod_bench.rs b/example/mod_bench.rs deleted file mode 100644 index e8a9cade7474..000000000000 --- a/example/mod_bench.rs +++ /dev/null @@ -1,36 +0,0 @@ -#![feature(start, core_intrinsics, lang_items)] -#![no_std] -#![allow(internal_features)] - -#[link(name = "c")] -extern "C" {} - -#[panic_handler] -fn panic_handler(_: &core::panic::PanicInfo<'_>) -> ! { - core::intrinsics::abort(); -} - -#[lang="eh_personality"] -fn eh_personality(){} - -// Required for rustc_codegen_llvm -#[no_mangle] -unsafe extern "C" fn _Unwind_Resume() { - core::intrinsics::unreachable(); -} - -#[start] -fn main(_argc: isize, _argv: *const *const u8) -> isize { - for i in 2..100_000_000 { - black_box((i + 1) % i); - } - - 0 -} - -#[inline(never)] -fn black_box(i: u32) { - if i != 1 { - core::intrinsics::abort(); - } -} diff --git a/src/context.rs b/src/context.rs index c81c53359fd1..30732c74eb3e 100644 --- a/src/context.rs +++ b/src/context.rs @@ -513,7 +513,6 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { } else { // If the symbol already exists, it is an error: for example, the user wrote // #[no_mangle] extern "C" fn main(..) {..} - // instead of #[start] None } } diff --git a/tests/run/abort1.rs b/tests/run/abort1.rs index 696197d73772..385e41a68817 100644 --- a/tests/run/abort1.rs +++ b/tests/run/abort1.rs @@ -3,11 +3,12 @@ // Run-time: // status: signal -#![feature(auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)] +#![feature(auto_traits, lang_items, no_core, intrinsics, rustc_attrs)] #![allow(internal_features)] #![no_std] #![no_core] +#![no_main] /* * Core @@ -49,7 +50,7 @@ fn test_fail() -> ! { unsafe { intrinsics::abort() }; } -#[start] -fn main(mut argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { test_fail(); } diff --git a/tests/run/abort2.rs b/tests/run/abort2.rs index 714cd6c0f381..6c66a930e074 100644 --- a/tests/run/abort2.rs +++ b/tests/run/abort2.rs @@ -3,11 +3,12 @@ // Run-time: // status: signal -#![feature(auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)] +#![feature(auto_traits, lang_items, no_core, intrinsics, rustc_attrs)] #![allow(internal_features)] #![no_std] #![no_core] +#![no_main] /* * Core @@ -50,8 +51,8 @@ fn fail() -> i32 { 0 } -#[start] -fn main(mut argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { fail(); 0 } diff --git a/tests/run/array.rs b/tests/run/array.rs index c3c08c29c6db..e18a4ced6bc4 100644 --- a/tests/run/array.rs +++ b/tests/run/array.rs @@ -7,10 +7,11 @@ // 5 // 10 -#![feature(no_core, start)] +#![feature(no_core)] #![no_std] #![no_core] +#![no_main] extern crate mini_core; @@ -28,8 +29,8 @@ fn make_array() -> [u8; 3] { [42, 10, 5] } -#[start] -fn main(argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { let array = [42, 7, 5]; let array2 = make_array(); unsafe { diff --git a/tests/run/assign.rs b/tests/run/assign.rs index 2a47f0c2966e..4d414c577a65 100644 --- a/tests/run/assign.rs +++ b/tests/run/assign.rs @@ -6,10 +6,11 @@ // 10 #![allow(internal_features, unused_attributes)] -#![feature(auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs, track_caller)] +#![feature(auto_traits, lang_items, no_core, intrinsics, rustc_attrs, track_caller)] #![no_std] #![no_core] +#![no_main] /* * Core @@ -142,8 +143,8 @@ fn inc(num: isize) -> isize { } -#[start] -fn main(mut argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { argc = inc(argc); unsafe { libc::printf(b"%ld\n\0" as *const u8 as *const i8, argc); diff --git a/tests/run/closure.rs b/tests/run/closure.rs index 46c47bc54ed0..c7a236f74f9e 100644 --- a/tests/run/closure.rs +++ b/tests/run/closure.rs @@ -8,10 +8,11 @@ // Int argument: 2 // Both args: 11 -#![feature(no_core, start)] +#![feature(no_core)] #![no_std] #![no_core] +#![no_main] extern crate mini_core; @@ -22,8 +23,8 @@ mod libc { } } -#[start] -fn main(mut argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { let string = "Arg: %d\n\0"; let mut closure = || { unsafe { diff --git a/tests/run/condition.rs b/tests/run/condition.rs index 039ef94eaa71..b02359702ed2 100644 --- a/tests/run/condition.rs +++ b/tests/run/condition.rs @@ -5,10 +5,11 @@ // stdout: true // 1 -#![feature(no_core, start)] +#![feature(no_core)] #![no_std] #![no_core] +#![no_main] extern crate mini_core; @@ -19,8 +20,8 @@ mod libc { } } -#[start] -fn main(argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { unsafe { if argc == 1 { libc::printf(b"true\n\0" as *const u8 as *const i8); diff --git a/tests/run/empty_main.rs b/tests/run/empty_main.rs index e66a859ad698..042e44080c53 100644 --- a/tests/run/empty_main.rs +++ b/tests/run/empty_main.rs @@ -3,11 +3,12 @@ // Run-time: // status: 0 -#![feature(auto_traits, lang_items, no_core, start)] +#![feature(auto_traits, lang_items, no_core)] #![allow(internal_features)] #![no_std] #![no_core] +#![no_main] /* * Core @@ -34,7 +35,7 @@ pub(crate) unsafe auto trait Freeze {} * Code */ -#[start] -fn main(_argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { 0 } diff --git a/tests/run/exit.rs b/tests/run/exit.rs index bf1cbeef3020..9a7c91c0adb2 100644 --- a/tests/run/exit.rs +++ b/tests/run/exit.rs @@ -3,11 +3,12 @@ // Run-time: // status: 2 -#![feature(auto_traits, lang_items, no_core, start, intrinsics)] +#![feature(auto_traits, lang_items, no_core, intrinsics)] #![allow(internal_features)] #![no_std] #![no_core] +#![no_main] mod libc { #[link(name = "c")] @@ -41,8 +42,8 @@ pub(crate) unsafe auto trait Freeze {} * Code */ -#[start] -fn main(mut argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { unsafe { libc::exit(2); } diff --git a/tests/run/exit_code.rs b/tests/run/exit_code.rs index be7a233efdaa..c50d2b0d7107 100644 --- a/tests/run/exit_code.rs +++ b/tests/run/exit_code.rs @@ -3,11 +3,12 @@ // Run-time: // status: 1 -#![feature(auto_traits, lang_items, no_core, start)] +#![feature(auto_traits, lang_items, no_core)] #![allow(internal_features)] #![no_std] #![no_core] +#![no_main] /* * Core @@ -34,7 +35,7 @@ pub(crate) unsafe auto trait Freeze {} * Code */ -#[start] -fn main(mut argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { 1 } diff --git a/tests/run/fun_ptr.rs b/tests/run/fun_ptr.rs index ed1bf72bb275..98b351e50449 100644 --- a/tests/run/fun_ptr.rs +++ b/tests/run/fun_ptr.rs @@ -4,10 +4,11 @@ // status: 0 // stdout: 1 -#![feature(no_core, start)] +#![feature(no_core)] #![no_std] #![no_core] +#![no_main] extern crate mini_core; @@ -26,8 +27,8 @@ fn call_func(func: fn(i16) -> i8, param: i16) -> i8 { func(param) } -#[start] -fn main(argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { unsafe { let result = call_func(i16_as_i8, argc as i16) as isize; libc::printf(b"%ld\n\0" as *const u8 as *const i8, result); diff --git a/tests/run/mut_ref.rs b/tests/run/mut_ref.rs index 3ae793382164..9be64f991ee0 100644 --- a/tests/run/mut_ref.rs +++ b/tests/run/mut_ref.rs @@ -8,10 +8,11 @@ // 11 #![allow(internal_features, unused_attributes)] -#![feature(auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs, track_caller)] +#![feature(auto_traits, lang_items, no_core, intrinsics, rustc_attrs, track_caller)] #![no_std] #![no_core] +#![no_main] /* * Core @@ -148,8 +149,8 @@ fn update_num(num: &mut isize) { *num = *num + 5; } -#[start] -fn main(mut argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { let mut test = test(argc); unsafe { libc::printf(b"%ld\n\0" as *const u8 as *const i8, test.field); diff --git a/tests/run/operations.rs b/tests/run/operations.rs index 0e44fc580b8c..c92d3cc0b8fb 100644 --- a/tests/run/operations.rs +++ b/tests/run/operations.rs @@ -6,10 +6,11 @@ // 10 #![allow(internal_features, unused_attributes)] -#![feature(auto_traits, lang_items, no_core, start, intrinsics, arbitrary_self_types, rustc_attrs)] +#![feature(auto_traits, lang_items, no_core, intrinsics, arbitrary_self_types, rustc_attrs)] #![no_std] #![no_core] +#![no_main] /* * Core @@ -231,8 +232,8 @@ pub fn panic_const_mul_overflow() -> ! { * Code */ -#[start] -fn main(mut argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { unsafe { libc::printf(b"%ld\n\0" as *const u8 as *const i8, 40 + argc); libc::printf(b"%ld\n\0" as *const u8 as *const i8, 40 - argc); diff --git a/tests/run/ptr_cast.rs b/tests/run/ptr_cast.rs index 2b8812ad51c5..0ba49e7187fc 100644 --- a/tests/run/ptr_cast.rs +++ b/tests/run/ptr_cast.rs @@ -4,10 +4,11 @@ // status: 0 // stdout: 1 -#![feature(no_core, start)] +#![feature(no_core)] #![no_std] #![no_core] +#![no_main] extern crate mini_core; @@ -24,8 +25,8 @@ fn make_array() -> [u8; 3] { [42, 10, 5] } -#[start] -fn main(argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { unsafe { let ptr = ONE as *mut usize; let value = ptr as usize; diff --git a/tests/run/return-tuple.rs b/tests/run/return-tuple.rs index f2a5a2e4384d..3cc1e274001e 100644 --- a/tests/run/return-tuple.rs +++ b/tests/run/return-tuple.rs @@ -6,11 +6,12 @@ // 10 // 42 -#![feature(auto_traits, lang_items, no_core, start, intrinsics)] +#![feature(auto_traits, lang_items, no_core, intrinsics)] #![allow(internal_features)] #![no_std] #![no_core] +#![no_main] #[lang = "copy"] pub unsafe trait Copy {} @@ -61,8 +62,8 @@ fn int_cast(a: u16, b: i16) -> (u8, u16, u32, usize, i8, i16, i32, isize, u8, u3 ) } -#[start] -fn main(argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { let (a, b, c, d, e, f, g, h, i, j) = int_cast(10, 42); unsafe { libc::printf(b"%d\n\0" as *const u8 as *const i8, c); diff --git a/tests/run/slice.rs b/tests/run/slice.rs index fba93fc15549..825fcb8a081e 100644 --- a/tests/run/slice.rs +++ b/tests/run/slice.rs @@ -4,10 +4,11 @@ // status: 0 // stdout: 5 -#![feature(no_core, start)] +#![feature(no_core)] #![no_std] #![no_core] +#![no_main] extern crate mini_core; @@ -26,8 +27,8 @@ fn index_slice(s: &[u32]) -> u32 { } } -#[start] -fn main(mut argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { let array = [42, 7, 5]; unsafe { libc::printf(b"%ld\n\0" as *const u8 as *const i8, index_slice(&array)); diff --git a/tests/run/static.rs b/tests/run/static.rs index a17ea2a48936..80c8782c4b1a 100644 --- a/tests/run/static.rs +++ b/tests/run/static.rs @@ -9,11 +9,12 @@ // 12 // 1 -#![feature(auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)] +#![feature(auto_traits, lang_items, no_core, intrinsics, rustc_attrs)] #![allow(internal_features)] #![no_std] #![no_core] +#![no_main] /* * Core @@ -98,8 +99,8 @@ static mut WITH_REF: WithRef = WithRef { refe: unsafe { &TEST }, }; -#[start] -fn main(mut argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { unsafe { libc::printf(b"%ld\n\0" as *const u8 as *const i8, CONSTANT); libc::printf(b"%ld\n\0" as *const u8 as *const i8, TEST2.field); diff --git a/tests/run/structs.rs b/tests/run/structs.rs index d6455667400c..59b8f358863f 100644 --- a/tests/run/structs.rs +++ b/tests/run/structs.rs @@ -5,11 +5,12 @@ // stdout: 1 // 2 -#![feature(auto_traits, lang_items, no_core, start, intrinsics)] +#![feature(auto_traits, lang_items, no_core, intrinsics)] #![allow(internal_features)] #![no_std] #![no_core] +#![no_main] /* * Core @@ -55,8 +56,8 @@ fn one() -> isize { 1 } -#[start] -fn main(mut argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { let test = Test { field: one(), }; diff --git a/tests/run/tuple.rs b/tests/run/tuple.rs index 8a7d85ae867e..ed60a56a68c4 100644 --- a/tests/run/tuple.rs +++ b/tests/run/tuple.rs @@ -4,11 +4,12 @@ // status: 0 // stdout: 3 -#![feature(auto_traits, lang_items, no_core, start, intrinsics)] +#![feature(auto_traits, lang_items, no_core, intrinsics)] #![allow(internal_features)] #![no_std] #![no_core] +#![no_main] /* * Core @@ -42,8 +43,8 @@ mod libc { * Code */ -#[start] -fn main(mut argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { let test: (isize, isize, isize) = (3, 1, 4); unsafe { libc::printf(b"%ld\n\0" as *const u8 as *const i8, test.0); From 0692ca3d20787e43a3ff3674c0cc7e7487de6508 Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Fri, 24 Jan 2025 16:05:26 -0500 Subject: [PATCH 006/606] Make CodegenCx and Builder generic Co-authored-by: Oli Scherer --- src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 7329080ce1f7..34aead1a6300 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -442,7 +442,6 @@ impl WriteBackendMethods for GccCodegenBackend { } fn autodiff( _cgcx: &CodegenContext, - _tcx: TyCtxt<'_>, _module: &ModuleCodegen, _diff_fncs: Vec, _config: &ModuleConfig, From d6d7c1581e211b9847ffc488645ec7bc342990f7 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 24 Jan 2025 23:12:17 +0100 Subject: [PATCH 007/606] Merge commit '9f33f846ddc06afd7ffd839ee4f18babac3f3204' --- .github/workflows/ci.yml | 10 +++--- .github/workflows/failures.yml | 6 ++-- .github/workflows/gcc12.yml | 2 +- .github/workflows/m68k.yml | 8 ++--- .github/workflows/release.yml | 13 +++++--- build_system/src/build.rs | 10 ++++-- build_system/src/config.rs | 57 ++++++++++++++++++++++++++-------- build_system/src/info.rs | 4 ++- build_system/src/main.rs | 4 +-- build_system/src/test.rs | 7 +++-- libgccjit.version | 2 +- messages.ftl | 3 -- 12 files changed, 85 insertions(+), 41 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 73ec6b84a155..f96912e6b7a8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,14 +13,14 @@ env: jobs: build: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 strategy: fail-fast: false matrix: libgccjit_version: - - { gcc: "gcc-13.deb" } - - { gcc: "gcc-13-without-int128.deb" } + - { gcc: "gcc-15.deb" } + - { gcc: "gcc-15-without-int128.deb" } commands: [ "--std-tests", # FIXME: re-enable asm tests when GCC can emit in the right syntax. @@ -108,13 +108,13 @@ jobs: cargo clippy --all-targets --features master -- -D warnings duplicates: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - run: python tools/check_intrinsics_duplicates.py build_system: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - name: Test build system diff --git a/.github/workflows/failures.yml b/.github/workflows/failures.yml index f33d9fcc5825..d080bbfe91fe 100644 --- a/.github/workflows/failures.yml +++ b/.github/workflows/failures.yml @@ -13,7 +13,7 @@ env: jobs: build: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 strategy: fail-fast: false @@ -56,12 +56,12 @@ jobs: - name: Download artifact if: matrix.libgccjit_version.gcc != 'libgccjit12.so' - run: curl -LO https://github.com/rust-lang/gcc/releases/latest/download/gcc-13.deb + run: curl -LO https://github.com/rust-lang/gcc/releases/latest/download/gcc-15.deb - name: Setup path to libgccjit if: matrix.libgccjit_version.gcc != 'libgccjit12.so' run: | - sudo dpkg --force-overwrite -i gcc-13.deb + sudo dpkg --force-overwrite -i gcc-15.deb echo 'gcc-path = "/usr/lib"' > config.toml echo "LIBRARY_PATH=/usr/lib" >> $GITHUB_ENV echo "LD_LIBRARY_PATH=/usr/lib" >> $GITHUB_ENV diff --git a/.github/workflows/gcc12.yml b/.github/workflows/gcc12.yml index 4c2ce91e86ee..bb9e020dc6a4 100644 --- a/.github/workflows/gcc12.yml +++ b/.github/workflows/gcc12.yml @@ -17,7 +17,7 @@ env: jobs: build: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 strategy: fail-fast: false diff --git a/.github/workflows/m68k.yml b/.github/workflows/m68k.yml index 07bb372b3606..ed1fc02bd913 100644 --- a/.github/workflows/m68k.yml +++ b/.github/workflows/m68k.yml @@ -17,7 +17,7 @@ env: jobs: build: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 strategy: fail-fast: false @@ -47,17 +47,17 @@ jobs: - name: Install packages run: | sudo apt-get update - sudo apt-get install qemu qemu-user-static + sudo apt-get install qemu-system qemu-user-static - name: Download artifact - run: curl -LO https://github.com/cross-cg-gcc-tools/cross-gcc/releases/latest/download/gcc-m68k-13.deb + run: curl -LO https://github.com/cross-cg-gcc-tools/cross-gcc/releases/latest/download/gcc-m68k-15.deb - name: Download VM artifact run: curl -LO https://github.com/cross-cg-gcc-tools/vms/releases/latest/download/debian-m68k.img - name: Setup path to libgccjit run: | - sudo dpkg -i gcc-m68k-13.deb + sudo dpkg -i gcc-m68k-15.deb echo 'gcc-path = "/usr/lib/"' > config.toml - name: Set env diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 60e0943c87da..886ce90b4713 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,7 +13,7 @@ env: jobs: build: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 strategy: fail-fast: false @@ -37,11 +37,11 @@ jobs: run: sudo apt-get install ninja-build ripgrep - name: Download artifact - run: curl -LO https://github.com/rust-lang/gcc/releases/latest/download/gcc-13.deb + run: curl -LO https://github.com/rust-lang/gcc/releases/latest/download/gcc-15.deb - name: Setup path to libgccjit run: | - sudo dpkg --force-overwrite -i gcc-13.deb + sudo dpkg --force-overwrite -i gcc-15.deb echo 'gcc-path = "/usr/lib/"' > config.toml - name: Set env @@ -76,4 +76,9 @@ jobs: - name: Run y.sh cargo build run: | EMBED_LTO_BITCODE=1 CHANNEL="release" ./y.sh cargo build --release --manifest-path tests/hello-world/Cargo.toml - # TODO: grep the asm output for "call my_func" and fail if it is found. + call_found=$(objdump -dj .text tests/hello-world/target/release/hello_world | grep -c "call .*mylib.*my_func" ) ||: + if [ $call_found -gt 0 ]; then + echo "ERROR: call my_func found in asm" + echo "Test is done with LTO enabled, hence inlining should occur across crates" + exit 1 + fi diff --git a/build_system/src/build.rs b/build_system/src/build.rs index d0ced211a616..e98377f15a94 100644 --- a/build_system/src/build.rs +++ b/build_system/src/build.rs @@ -150,6 +150,8 @@ pub fn build_sysroot(env: &HashMap, config: &ConfigInfo) -> Resu "debug" }; + // We have a different environment variable than RUSTFLAGS to make sure those flags are only + // sent to rustc_codegen_gcc and not the LLVM backend. if let Ok(cg_rustflags) = std::env::var("CG_RUSTFLAGS") { rustflags.push(' '); rustflags.push_str(&cg_rustflags); @@ -184,8 +186,12 @@ pub fn build_sysroot(env: &HashMap, config: &ConfigInfo) -> Resu fn build_codegen(args: &mut BuildArg) -> Result<(), String> { let mut env = HashMap::new(); - env.insert("LD_LIBRARY_PATH".to_string(), args.config_info.gcc_path.clone()); - env.insert("LIBRARY_PATH".to_string(), args.config_info.gcc_path.clone()); + let gcc_path = + args.config_info.gcc_path.clone().expect( + "The config module should have emitted an error if the GCC path wasn't provided", + ); + env.insert("LD_LIBRARY_PATH".to_string(), gcc_path.clone()); + env.insert("LIBRARY_PATH".to_string(), gcc_path); if args.config_info.no_default_features { env.insert("RUSTFLAGS".to_string(), "-Csymbol-mangling-version=v0".to_string()); diff --git a/build_system/src/config.rs b/build_system/src/config.rs index 37b4b68950e4..4f9fcc971514 100644 --- a/build_system/src/config.rs +++ b/build_system/src/config.rs @@ -112,7 +112,7 @@ pub struct ConfigInfo { pub sysroot_panic_abort: bool, pub cg_backend_path: String, pub sysroot_path: String, - pub gcc_path: String, + pub gcc_path: Option, config_file: Option, // This is used in particular in rust compiler bootstrap because it doesn't run at the root // of the `cg_gcc` folder, making it complicated for us to get access to local files we need @@ -173,6 +173,14 @@ impl ConfigInfo { "--release-sysroot" => self.sysroot_release_channel = true, "--release" => self.channel = Channel::Release, "--sysroot-panic-abort" => self.sysroot_panic_abort = true, + "--gcc-path" => match args.next() { + Some(arg) if !arg.is_empty() => { + self.gcc_path = Some(arg.into()); + } + _ => { + return Err("Expected a value after `--gcc-path`, found nothing".to_string()); + } + }, "--cg_gcc-path" => match args.next() { Some(arg) if !arg.is_empty() => { self.cg_gcc_path = Some(arg.into()); @@ -260,8 +268,9 @@ impl ConfigInfo { create_symlink(&libgccjit_so, output_dir.join(&format!("{}.0", libgccjit_so_name)))?; } - self.gcc_path = output_dir.display().to_string(); - println!("Using `{}` as path for libgccjit", self.gcc_path); + let gcc_path = output_dir.display().to_string(); + println!("Using `{}` as path for libgccjit", gcc_path); + self.gcc_path = Some(gcc_path); Ok(()) } @@ -273,6 +282,15 @@ impl ConfigInfo { } pub fn setup_gcc_path(&mut self) -> Result<(), String> { + // If the user used the `--gcc-path` option, no need to look at `config.toml` content + // since we already have everything we need. + if let Some(gcc_path) = &self.gcc_path { + println!( + "`--gcc-path` was provided, ignoring config file. Using `{}` as path for libgccjit", + gcc_path + ); + return Ok(()); + } let config_file = match self.config_file.as_deref() { Some(config_file) => config_file.into(), None => self.compute_path("config.toml"), @@ -283,12 +301,15 @@ impl ConfigInfo { self.download_gccjit_if_needed()?; return Ok(()); } - self.gcc_path = match gcc_path { - Some(path) => path, - None => { - return Err(format!("missing `gcc-path` value from `{}`", config_file.display(),)); - } + let Some(gcc_path) = gcc_path else { + return Err(format!("missing `gcc-path` value from `{}`", config_file.display())); }; + println!( + "GCC path retrieved from `{}`. Using `{}` as path for libgccjit", + config_file.display(), + gcc_path + ); + self.gcc_path = Some(gcc_path); Ok(()) } @@ -299,10 +320,17 @@ impl ConfigInfo { ) -> Result<(), String> { env.insert("CARGO_INCREMENTAL".to_string(), "0".to_string()); - if self.gcc_path.is_empty() && !use_system_gcc { - self.setup_gcc_path()?; - } - env.insert("GCC_PATH".to_string(), self.gcc_path.clone()); + let gcc_path = if !use_system_gcc { + if self.gcc_path.is_none() { + self.setup_gcc_path()?; + } + self.gcc_path.clone().expect( + "The config module should have emitted an error if the GCC path wasn't provided", + ) + } else { + String::new() + }; + env.insert("GCC_PATH".to_string(), gcc_path.clone()); if self.cargo_target_dir.is_empty() { match env.get("CARGO_TARGET_DIR").filter(|dir| !dir.is_empty()) { @@ -381,6 +409,8 @@ impl ConfigInfo { } // This environment variable is useful in case we want to change options of rustc commands. + // We have a different environment variable than RUSTFLAGS to make sure those flags are + // only sent to rustc_codegen_gcc and not the LLVM backend. if let Some(cg_rustflags) = env.get("CG_RUSTFLAGS") { rustflags.extend_from_slice(&split_args(&cg_rustflags)?); } @@ -414,7 +444,7 @@ impl ConfigInfo { "{target}:{sysroot}:{gcc_path}", target = self.cargo_target_dir, sysroot = sysroot.display(), - gcc_path = self.gcc_path, + gcc_path = gcc_path, ); env.insert("LIBRARY_PATH".to_string(), ld_library_path.clone()); env.insert("LD_LIBRARY_PATH".to_string(), ld_library_path.clone()); @@ -459,6 +489,7 @@ impl ConfigInfo { --release-sysroot : Build sysroot in release mode --sysroot-panic-abort : Build the sysroot without unwinding support --config-file : Location of the config file to be used + --gcc-path : Location of the GCC root folder --cg_gcc-path : Location of the rustc_codegen_gcc root folder (used when ran from another directory) --no-default-features : Add `--no-default-features` flag to cargo commands diff --git a/build_system/src/info.rs b/build_system/src/info.rs index ea38791d38c9..bd891de2eb4c 100644 --- a/build_system/src/info.rs +++ b/build_system/src/info.rs @@ -14,6 +14,8 @@ pub fn run() -> Result<(), String> { } config.no_download = true; config.setup_gcc_path()?; - println!("{}", config.gcc_path); + if let Some(gcc_path) = config.gcc_path { + println!("{}", gcc_path); + } Ok(()) } diff --git a/build_system/src/main.rs b/build_system/src/main.rs index 3a860e2b1360..393617183061 100644 --- a/build_system/src/main.rs +++ b/build_system/src/main.rs @@ -34,11 +34,11 @@ Options: --help : Displays this help message. Commands: - cargo : Executes a cargo command. + cargo : Executes a cargo command. rustc : Compiles the program using the GCC compiler. clean : Cleans the build directory, removing all compiled files and artifacts. prepare : Prepares the environment for building, including fetching dependencies and setting up configurations. - build : Compiles the project. + build : Compiles the project. test : Runs tests for the project. info : Displays information about the build environment and project configuration. clone-gcc : Clones the GCC compiler from a specified source. diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 0e790a4befc9..6c29c7d1825b 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -1229,8 +1229,11 @@ pub fn run() -> Result<(), String> { if !args.use_system_gcc { args.config_info.setup_gcc_path()?; - env.insert("LIBRARY_PATH".to_string(), args.config_info.gcc_path.clone()); - env.insert("LD_LIBRARY_PATH".to_string(), args.config_info.gcc_path.clone()); + let gcc_path = args.config_info.gcc_path.clone().expect( + "The config module should have emitted an error if the GCC path wasn't provided", + ); + env.insert("LIBRARY_PATH".to_string(), gcc_path.clone()); + env.insert("LD_LIBRARY_PATH".to_string(), gcc_path); } build_if_no_backend(&env, &args)?; diff --git a/libgccjit.version b/libgccjit.version index ff58accec1d4..417fd5b03935 100644 --- a/libgccjit.version +++ b/libgccjit.version @@ -1 +1 @@ -45648c2edd4ecd862d9f08196d3d6c6ccba79f07 +e607be166673a8de9fc07f6f02c60426e556c5f2 diff --git a/messages.ftl b/messages.ftl index 85fa17a6ba50..882fff8673a1 100644 --- a/messages.ftl +++ b/messages.ftl @@ -5,9 +5,6 @@ codegen_gcc_unknown_ctarget_feature_prefix = codegen_gcc_invalid_minimum_alignment = invalid minimum global alignment: {$err} -codegen_gcc_lto_not_supported = - LTO is not supported. You may get a linker error. - codegen_gcc_forbidden_ctarget_feature = target feature `{$feature}` cannot be toggled with `-Ctarget-feature`: {$reason} From 24ce0a2efa314eff96af73f5b6c5d0e3392abf38 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sun, 12 Jan 2025 20:18:45 +0000 Subject: [PATCH 008/606] Stabilize `const_black_box` This has been unstably const since [1], but a tracking issue was never created. Per discussion on Zulip [2], there should not be any blockers to making this const-stable. The function does not provide any functionality at compile time but does allow code reuse between const- and non-const functions, so stabilize it here. [1]: https://github.com/rust-lang/rust/pull/92226 [2]: https://rust-lang.zulipchat.com/#narrow/channel/146212-t-compiler.2Fconst-eval/topic/const_black_box --- tests/run/int.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/run/int.rs b/tests/run/int.rs index bfe73c38435a..58a26801b678 100644 --- a/tests/run/int.rs +++ b/tests/run/int.rs @@ -3,8 +3,6 @@ // Run-time: // status: 0 -#![feature(const_black_box)] - /* * Code */ From bc6b9bf526b2aafefe5d212cdde85e01b16351ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Mon, 27 Jan 2025 23:27:43 +0100 Subject: [PATCH 009/606] Add CI success job --- .github/workflows/ci.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f96912e6b7a8..689a7dee435f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -121,3 +121,23 @@ jobs: run: | cd build_system cargo test + + + # Summary job for the merge queue. + # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB! + success: + needs: [build, duplicates, build_system] + # We need to ensure this job does *not* get skipped if its dependencies fail, + # because a skipped job is considered a success by GitHub. So we have to + # overwrite `if:`. We use `!cancelled()` to ensure the job does still not get run + # when the workflow is canceled manually. + if: ${{ !cancelled() }} + runs-on: ubuntu-latest + steps: + # Manually check the status of all dependencies. `if: failure()` does not work. + - name: Conclusion + run: | + # Print the dependent jobs to see them in the CI log + jq -C <<< '${{ toJson(needs) }}' + # Check if all jobs that we depend on (in the needs array) were successful. + jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}' From 600999a4fe7af3c7eae9349f6530c5c7b12ce1cd Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 27 Jan 2025 18:30:17 +0100 Subject: [PATCH 010/606] ABI-required target features: warn when they are missing in base CPU (rather than silently enabling them) --- src/gcc_util.rs | 50 +------------------------------------------------ src/lib.rs | 5 +++-- 2 files changed, 4 insertions(+), 51 deletions(-) diff --git a/src/gcc_util.rs b/src/gcc_util.rs index 560aff43d653..4e8c8aaaf5c8 100644 --- a/src/gcc_util.rs +++ b/src/gcc_util.rs @@ -1,10 +1,8 @@ -use std::iter::FromIterator; - #[cfg(feature = "master")] use gccjit::Context; use rustc_codegen_ssa::codegen_attrs::check_tied_features; use rustc_codegen_ssa::errors::TargetFeatureDisableOrEnable; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::unord::UnordSet; use rustc_session::Session; use rustc_target::target_features::RUSTC_SPECIFIC_FEATURES; @@ -45,12 +43,6 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec Vec Date: Fri, 10 Jan 2025 04:36:11 +0000 Subject: [PATCH 011/606] Do not treat vtable supertraits as distinct when bound with different bound vars --- src/common.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/common.rs b/src/common.rs index bd5d6ba387cf..20a3482aaa27 100644 --- a/src/common.rs +++ b/src/common.rs @@ -234,7 +234,12 @@ impl<'gcc, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { GlobalAlloc::VTable(ty, dyn_ty) => { let alloc = self .tcx - .global_alloc(self.tcx.vtable_allocation((ty, dyn_ty.principal()))) + .global_alloc(self.tcx.vtable_allocation(( + ty, + dyn_ty.principal().map(|principal| { + self.tcx.instantiate_bound_regions_with_erased(principal) + }), + ))) .unwrap_memory(); let init = const_alloc_to_gcc(self, alloc); self.static_addr_of(init, alloc.inner().align, None) From 12feb0e21fe1cc79ee31951322b3bc587e07befe Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 10 Jan 2025 20:26:10 +0000 Subject: [PATCH 012/606] Use ExistentialTraitRef throughout codegen --- src/context.rs | 6 +++--- src/debuginfo.rs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/context.rs b/src/context.rs index 30732c74eb3e..570ef938dc44 100644 --- a/src/context.rs +++ b/src/context.rs @@ -14,7 +14,7 @@ use rustc_middle::ty::layout::{ FnAbiError, FnAbiOf, FnAbiOfHelpers, FnAbiRequest, HasTyCtxt, HasTypingEnv, LayoutError, LayoutOfHelpers, }; -use rustc_middle::ty::{self, Instance, PolyExistentialTraitRef, Ty, TyCtxt}; +use rustc_middle::ty::{self, ExistentialTraitRef, Instance, Ty, TyCtxt}; use rustc_session::Session; use rustc_span::source_map::respan; use rustc_span::{DUMMY_SP, Span}; @@ -90,7 +90,7 @@ pub struct CodegenCx<'gcc, 'tcx> { pub function_instances: RefCell, Function<'gcc>>>, /// Cache generated vtables pub vtables: - RefCell, Option>), RValue<'gcc>>>, + RefCell, Option>), RValue<'gcc>>>, // TODO(antoyo): improve the SSA API to not require those. /// Mapping from function pointer type to indexes of on stack parameters. @@ -401,7 +401,7 @@ impl<'gcc, 'tcx> BackendTypes for CodegenCx<'gcc, 'tcx> { impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { fn vtables( &self, - ) -> &RefCell, Option>), RValue<'gcc>>> { + ) -> &RefCell, Option>), RValue<'gcc>>> { &self.vtables } diff --git a/src/debuginfo.rs b/src/debuginfo.rs index 4b84b1dbfd39..86d3de225f71 100644 --- a/src/debuginfo.rs +++ b/src/debuginfo.rs @@ -7,7 +7,7 @@ use rustc_data_structures::sync::Lrc; use rustc_index::bit_set::DenseBitSet; use rustc_index::{Idx, IndexVec}; use rustc_middle::mir::{self, Body, SourceScope}; -use rustc_middle::ty::{Instance, PolyExistentialTraitRef, Ty}; +use rustc_middle::ty::{ExistentialTraitRef, Instance, Ty}; use rustc_session::config::DebugInfo; use rustc_span::{BytePos, Pos, SourceFile, SourceFileAndLine, Span, Symbol}; use rustc_target::abi::Size; @@ -214,7 +214,7 @@ impl<'gcc, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { fn create_vtable_debuginfo( &self, _ty: Ty<'tcx>, - _trait_ref: Option>, + _trait_ref: Option>, _vtable: Self::Value, ) { // TODO(antoyo) From adee0849a2971663984f6d7c1612097d4cbbcbd3 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sat, 1 Feb 2025 10:31:25 -0500 Subject: [PATCH 013/606] Add success job for all CI workflows --- .github/workflows/ci.yml | 1 - .github/workflows/failures.yml | 2 +- .github/workflows/gcc12.yml | 2 +- .github/workflows/m68k.yml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/stdarch.yml | 2 +- 6 files changed, 5 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 689a7dee435f..688a9f7d7bf7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -122,7 +122,6 @@ jobs: cd build_system cargo test - # Summary job for the merge queue. # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB! success: diff --git a/.github/workflows/failures.yml b/.github/workflows/failures.yml index d080bbfe91fe..b9f6f9d84f46 100644 --- a/.github/workflows/failures.yml +++ b/.github/workflows/failures.yml @@ -12,7 +12,7 @@ env: RUST_BACKTRACE: 1 jobs: - build: + success: runs-on: ubuntu-24.04 strategy: diff --git a/.github/workflows/gcc12.yml b/.github/workflows/gcc12.yml index bb9e020dc6a4..0308eec51cdf 100644 --- a/.github/workflows/gcc12.yml +++ b/.github/workflows/gcc12.yml @@ -16,7 +16,7 @@ env: GCC_EXEC_PREFIX: /usr/lib/gcc/ jobs: - build: + success: runs-on: ubuntu-24.04 strategy: diff --git a/.github/workflows/m68k.yml b/.github/workflows/m68k.yml index ed1fc02bd913..e031ad59f4b5 100644 --- a/.github/workflows/m68k.yml +++ b/.github/workflows/m68k.yml @@ -16,7 +16,7 @@ env: OVERWRITE_TARGET_TRIPLE: m68k-unknown-linux-gnu jobs: - build: + success: runs-on: ubuntu-24.04 strategy: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 886ce90b4713..4367cbccab11 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,7 @@ env: RUST_BACKTRACE: 1 jobs: - build: + success: runs-on: ubuntu-24.04 strategy: diff --git a/.github/workflows/stdarch.yml b/.github/workflows/stdarch.yml index d5ae6144496f..ea8bec02eef1 100644 --- a/.github/workflows/stdarch.yml +++ b/.github/workflows/stdarch.yml @@ -12,7 +12,7 @@ env: RUST_BACKTRACE: 1 jobs: - build: + success: runs-on: ubuntu-24.04 strategy: From ff2cd0fb6390d775c753733abefab6b81d45eb64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sat, 1 Feb 2025 19:13:41 +0100 Subject: [PATCH 014/606] Remove duplicated CI triggers There shouldn't be a need to run all CI jobs on all pushes. --- .github/workflows/ci.yml | 1 - .github/workflows/gcc12.yml | 1 - .github/workflows/m68k.yml | 1 - .github/workflows/release.yml | 1 - .github/workflows/stdarch.yml | 1 - 5 files changed, 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 688a9f7d7bf7..bf974f65c1e1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,7 +1,6 @@ name: CI on: - - push - pull_request permissions: diff --git a/.github/workflows/gcc12.yml b/.github/workflows/gcc12.yml index 0308eec51cdf..0d49336ea208 100644 --- a/.github/workflows/gcc12.yml +++ b/.github/workflows/gcc12.yml @@ -1,7 +1,6 @@ name: CI libgccjit 12 on: - - push - pull_request permissions: diff --git a/.github/workflows/m68k.yml b/.github/workflows/m68k.yml index e031ad59f4b5..af5f084205e5 100644 --- a/.github/workflows/m68k.yml +++ b/.github/workflows/m68k.yml @@ -3,7 +3,6 @@ name: m68k CI on: - - push - pull_request permissions: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4367cbccab11..4582cf577fe6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,7 +1,6 @@ name: CI with sysroot compiled in release mode on: - - push - pull_request permissions: diff --git a/.github/workflows/stdarch.yml b/.github/workflows/stdarch.yml index ea8bec02eef1..a1df0207d54f 100644 --- a/.github/workflows/stdarch.yml +++ b/.github/workflows/stdarch.yml @@ -1,7 +1,6 @@ name: stdarch tests with sysroot compiled in release mode on: - - push - pull_request permissions: From befc31c588585db6650d228f50727070e2ccd96b Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sat, 1 Feb 2025 12:19:35 -0500 Subject: [PATCH 015/606] Move back to a success job so because the required checks only work without a matrix --- .github/workflows/failures.yml | 21 ++++++++++++++++++++- .github/workflows/gcc12.yml | 21 ++++++++++++++++++++- .github/workflows/m68k.yml | 21 ++++++++++++++++++++- .github/workflows/release.yml | 21 ++++++++++++++++++++- .github/workflows/stdarch.yml | 21 ++++++++++++++++++++- 5 files changed, 100 insertions(+), 5 deletions(-) diff --git a/.github/workflows/failures.yml b/.github/workflows/failures.yml index b9f6f9d84f46..ab3e4002e87f 100644 --- a/.github/workflows/failures.yml +++ b/.github/workflows/failures.yml @@ -12,7 +12,7 @@ env: RUST_BACKTRACE: 1 jobs: - success: + build: runs-on: ubuntu-24.04 strategy: @@ -108,3 +108,22 @@ jobs: echo "Error: 'the compiler unexpectedly panicked' found in output logs. CI Error!!" exit 1 fi + + # Summary job for the merge queue. + # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB! + success_failures: + needs: [build] + # We need to ensure this job does *not* get skipped if its dependencies fail, + # because a skipped job is considered a success by GitHub. So we have to + # overwrite `if:`. We use `!cancelled()` to ensure the job does still not get run + # when the workflow is canceled manually. + if: ${{ !cancelled() }} + runs-on: ubuntu-latest + steps: + # Manually check the status of all dependencies. `if: failure()` does not work. + - name: Conclusion + run: | + # Print the dependent jobs to see them in the CI log + jq -C <<< '${{ toJson(needs) }}' + # Check if all jobs that we depend on (in the needs array) were successful. + jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}' diff --git a/.github/workflows/gcc12.yml b/.github/workflows/gcc12.yml index 0308eec51cdf..33d5d1a52df8 100644 --- a/.github/workflows/gcc12.yml +++ b/.github/workflows/gcc12.yml @@ -16,7 +16,7 @@ env: GCC_EXEC_PREFIX: /usr/lib/gcc/ jobs: - success: + build: runs-on: ubuntu-24.04 strategy: @@ -85,3 +85,22 @@ jobs: #- name: Run tests #run: | #./y.sh test --release --clean --build-sysroot ${{ matrix.commands }} --no-default-features + + # Summary job for the merge queue. + # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB! + success_gcc12: + needs: [build] + # We need to ensure this job does *not* get skipped if its dependencies fail, + # because a skipped job is considered a success by GitHub. So we have to + # overwrite `if:`. We use `!cancelled()` to ensure the job does still not get run + # when the workflow is canceled manually. + if: ${{ !cancelled() }} + runs-on: ubuntu-latest + steps: + # Manually check the status of all dependencies. `if: failure()` does not work. + - name: Conclusion + run: | + # Print the dependent jobs to see them in the CI log + jq -C <<< '${{ toJson(needs) }}' + # Check if all jobs that we depend on (in the needs array) were successful. + jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}' diff --git a/.github/workflows/m68k.yml b/.github/workflows/m68k.yml index e031ad59f4b5..a7090338a7f1 100644 --- a/.github/workflows/m68k.yml +++ b/.github/workflows/m68k.yml @@ -16,7 +16,7 @@ env: OVERWRITE_TARGET_TRIPLE: m68k-unknown-linux-gnu jobs: - success: + build: runs-on: ubuntu-24.04 strategy: @@ -105,3 +105,22 @@ jobs: - name: Run tests run: | ./y.sh test --release --clean --build-sysroot --sysroot-features compiler_builtins/no-f16-f128 ${{ matrix.commands }} + + # Summary job for the merge queue. + # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB! + success_m68k: + needs: [build] + # We need to ensure this job does *not* get skipped if its dependencies fail, + # because a skipped job is considered a success by GitHub. So we have to + # overwrite `if:`. We use `!cancelled()` to ensure the job does still not get run + # when the workflow is canceled manually. + if: ${{ !cancelled() }} + runs-on: ubuntu-latest + steps: + # Manually check the status of all dependencies. `if: failure()` does not work. + - name: Conclusion + run: | + # Print the dependent jobs to see them in the CI log + jq -C <<< '${{ toJson(needs) }}' + # Check if all jobs that we depend on (in the needs array) were successful. + jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4367cbccab11..7284b7f7398a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,7 @@ env: RUST_BACKTRACE: 1 jobs: - success: + build: runs-on: ubuntu-24.04 strategy: @@ -82,3 +82,22 @@ jobs: echo "Test is done with LTO enabled, hence inlining should occur across crates" exit 1 fi + + # Summary job for the merge queue. + # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB! + success_release: + needs: [build] + # We need to ensure this job does *not* get skipped if its dependencies fail, + # because a skipped job is considered a success by GitHub. So we have to + # overwrite `if:`. We use `!cancelled()` to ensure the job does still not get run + # when the workflow is canceled manually. + if: ${{ !cancelled() }} + runs-on: ubuntu-latest + steps: + # Manually check the status of all dependencies. `if: failure()` does not work. + - name: Conclusion + run: | + # Print the dependent jobs to see them in the CI log + jq -C <<< '${{ toJson(needs) }}' + # Check if all jobs that we depend on (in the needs array) were successful. + jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}' diff --git a/.github/workflows/stdarch.yml b/.github/workflows/stdarch.yml index ea8bec02eef1..9438e557ecd9 100644 --- a/.github/workflows/stdarch.yml +++ b/.github/workflows/stdarch.yml @@ -12,7 +12,7 @@ env: RUST_BACKTRACE: 1 jobs: - success: + build: runs-on: ubuntu-24.04 strategy: @@ -102,3 +102,22 @@ jobs: # TODO: remove --skip test_mm512_stream_ps when stdarch is updated in rustc. # TODO: remove --skip test_tile_ when it's implemented. STDARCH_TEST_EVERYTHING=1 CHANNEL=release CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER="${{ matrix.cargo_runner }}" TARGET=x86_64-unknown-linux-gnu CG_RUSTFLAGS="-Ainternal_features --cfg stdarch_intel_sde" ./y.sh cargo test --manifest-path build/build_sysroot/sysroot_src/library/stdarch/Cargo.toml -- --skip rtm --skip tbm --skip sse4a --skip test_mm512_stream_ps --skip test_tile_ + + # Summary job for the merge queue. + # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB! + success_stdarch: + needs: [build] + # We need to ensure this job does *not* get skipped if its dependencies fail, + # because a skipped job is considered a success by GitHub. So we have to + # overwrite `if:`. We use `!cancelled()` to ensure the job does still not get run + # when the workflow is canceled manually. + if: ${{ !cancelled() }} + runs-on: ubuntu-latest + steps: + # Manually check the status of all dependencies. `if: failure()` does not work. + - name: Conclusion + run: | + # Print the dependent jobs to see them in the CI log + jq -C <<< '${{ toJson(needs) }}' + # Check if all jobs that we depend on (in the needs array) were successful. + jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}' From ad2be68b490180012d7775a2ae3e0fd8e9cabda4 Mon Sep 17 00:00:00 2001 From: Kevin Hamacher Date: Mon, 27 Jan 2025 19:05:14 +0100 Subject: [PATCH 016/606] Make globals always have 2+ chars as suffix As discussed on chat, there currently is the bug where certain suffixes are interpreted by the (m68k) assembler. Example: `move.l #global.w,-44(%fp)` `.w` is interpreted by the assembler as a size hint for `#global`. --- src/context.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/context.rs b/src/context.rs index c81c53359fd1..2a33beef63b9 100644 --- a/src/context.rs +++ b/src/context.rs @@ -606,7 +606,10 @@ impl<'b, 'tcx> CodegenCx<'b, 'tcx> { let mut name = String::with_capacity(prefix.len() + 6); name.push_str(prefix); name.push('.'); - name.push_str(&(idx as u64).to_base(ALPHANUMERIC_ONLY)); + // Offset the index by the base so that always at least two characters + // are generated. This avoids cases where the suffix is interpreted as + // size by the assembler (for m68k: .b, .w, .l). + name.push_str(&(idx as u64 + ALPHANUMERIC_ONLY as u64).to_base(ALPHANUMERIC_ONLY)); name } } From 5d12c54b345d6bf6e7d25b904c1b7fbb0287429e Mon Sep 17 00:00:00 2001 From: Kevin Hamacher Date: Mon, 27 Jan 2025 18:49:49 +0100 Subject: [PATCH 017/606] Add M68000 entry to arch_to_gcc --- src/gcc_util.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gcc_util.rs b/src/gcc_util.rs index 560aff43d653..f463ee406174 100644 --- a/src/gcc_util.rs +++ b/src/gcc_util.rs @@ -242,6 +242,7 @@ pub fn to_gcc_features<'a>(sess: &Session, s: &'a str) -> SmallVec<[&'a str; 2]> fn arch_to_gcc(name: &str) -> &str { match name { + "M68000" => "68000", "M68020" => "68020", _ => name, } From e0d8fb949cafac87d072e7bb873eeb115fe22706 Mon Sep 17 00:00:00 2001 From: Askar Safin Date: Mon, 3 Feb 2025 06:44:41 +0300 Subject: [PATCH 018/606] tree-wide: parallel: Fully removed all `Lrc`, replaced with `Arc` --- src/debuginfo.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/debuginfo.rs b/src/debuginfo.rs index 86d3de225f71..12cbde0ad0d3 100644 --- a/src/debuginfo.rs +++ b/src/debuginfo.rs @@ -1,9 +1,9 @@ use std::ops::Range; +use std::sync::Arc; use gccjit::{Location, RValue}; use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, VariableKind}; use rustc_codegen_ssa::traits::{DebugInfoBuilderMethods, DebugInfoCodegenMethods}; -use rustc_data_structures::sync::Lrc; use rustc_index::bit_set::DenseBitSet; use rustc_index::{Idx, IndexVec}; use rustc_middle::mir::{self, Body, SourceScope}; @@ -172,7 +172,7 @@ fn make_mir_scope<'gcc, 'tcx>( // `lookup_char_pos` return the right information instead. pub struct DebugLoc { /// Information about the original source file. - pub file: Lrc, + pub file: Arc, /// The (1-based) line number. pub line: u32, /// The (1-based) column number. From 4c932ff8379e70893d3cdc835c289547ba3bee26 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 25 Jan 2025 23:32:44 +0100 Subject: [PATCH 019/606] Update repositories URL for repositories moved to `rust-lang` organization --- Readme.md | 4 ++-- build_system/src/clone_gcc.rs | 2 +- doc/add-attribute.md | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Readme.md b/Readme.md index e92c16ece2f1..d0e4dbba6d35 100644 --- a/Readme.md +++ b/Readme.md @@ -23,7 +23,7 @@ A secondary goal is to check if using the gcc backend will provide any run-time ## Building **This requires a patched libgccjit in order to work. -You need to use my [fork of gcc](https://github.com/antoyo/gcc) which already includes these patches.** +You need to use my [fork of gcc](https://github.com/rust-lang/gcc) which already includes these patches.** ```bash $ cp config.example.toml config.toml @@ -40,7 +40,7 @@ to do a few more things. To build it (most of these instructions come from [here](https://gcc.gnu.org/onlinedocs/jit/internals/index.html), so don't hesitate to take a look there if you encounter an issue): ```bash -$ git clone https://github.com/antoyo/gcc +$ git clone https://github.com/rust-lang/gcc $ sudo apt install flex libmpfr-dev libgmp-dev libmpc3 libmpc-dev $ mkdir gcc-build gcc-install $ cd gcc-build diff --git a/build_system/src/clone_gcc.rs b/build_system/src/clone_gcc.rs index e28ee873eb6b..b49dd47f3521 100644 --- a/build_system/src/clone_gcc.rs +++ b/build_system/src/clone_gcc.rs @@ -61,7 +61,7 @@ pub fn run() -> Result<(), String> { return Ok(()); }; - let result = git_clone("https://github.com/antoyo/gcc", Some(&args.out_path), false)?; + let result = git_clone("https://github.com/rust-lang/gcc", Some(&args.out_path), false)?; if result.ran_clone { let gcc_commit = args.config_info.get_gcc_commit()?; println!("Checking out GCC commit `{}`...", gcc_commit); diff --git a/doc/add-attribute.md b/doc/add-attribute.md index ae3bcc5e2ebe..267c18195255 100644 --- a/doc/add-attribute.md +++ b/doc/add-attribute.md @@ -14,4 +14,4 @@ Finally, you need to update this repository by calling the relevant API you adde To test it, build `gcc`, run `cargo update -p gccjit` and then you can test the generated output for a given Rust crate. -[gccjit.rs]: https://github.com/antoyo/gccjit.rs +[gccjit.rs]: https://github.com/rust-lang/gccjit.rs From beb24b3301e6f9b831f16ddd542930024ffe8239 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 4 Feb 2025 15:15:28 +0100 Subject: [PATCH 020/606] intrinsics: unify rint, roundeven, nearbyint in a single round_ties_even intrinsic --- src/intrinsic/mod.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 48606f5f91c0..83d0db0fb54a 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -84,14 +84,11 @@ fn get_simple_intrinsic<'gcc, 'tcx>( sym::ceilf64 => "ceil", sym::truncf32 => "truncf", sym::truncf64 => "trunc", - sym::rintf32 => "rintf", - sym::rintf64 => "rint", - sym::nearbyintf32 => "nearbyintf", - sym::nearbyintf64 => "nearbyint", + // We match the LLVM backend and lower this to `rint`. + sym::round_ties_even_f32 => "rintf", + sym::round_ties_even_f64 => "rint", sym::roundf32 => "roundf", sym::roundf64 => "round", - sym::roundevenf32 => "roundevenf", - sym::roundevenf64 => "roundeven", sym::abort => "abort", _ => return None, }; From 819ab9b0656e3efbabdf680856d957ec746bc58a Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Sat, 2 Nov 2024 17:49:42 -0700 Subject: [PATCH 021/606] cg_gcc: Directly use rustc_abi instead of reexports --- src/abi.rs | 6 +++--- src/builder.rs | 2 +- src/consts.rs | 2 +- src/context.rs | 2 +- src/debuginfo.rs | 4 ++-- src/declare.rs | 2 +- src/int.rs | 7 +++---- src/intrinsic/mod.rs | 14 +++++++------- src/intrinsic/simd.rs | 2 +- src/type_.rs | 2 +- src/type_of.rs | 7 ++++--- 11 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/abi.rs b/src/abi.rs index 14fc23593f0e..d94fc5525288 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -8,7 +8,7 @@ use rustc_middle::ty::Ty; use rustc_middle::ty::layout::LayoutOf; #[cfg(feature = "master")] use rustc_session::config; -use rustc_target::abi::call::{ArgAttributes, CastTarget, FnAbi, PassMode, Reg, RegKind}; +use rustc_target::callconv::{ArgAttributes, CastTarget, FnAbi, PassMode, Reg, RegKind}; use crate::builder::Builder; use crate::context::CodegenCx; @@ -132,10 +132,10 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { if cx.sess().opts.optimize == config::OptLevel::No { return ty; } - if attrs.regular.contains(rustc_target::abi::call::ArgAttribute::NoAlias) { + if attrs.regular.contains(rustc_target::callconv::ArgAttribute::NoAlias) { ty = ty.make_restrict() } - if attrs.regular.contains(rustc_target::abi::call::ArgAttribute::NonNull) { + if attrs.regular.contains(rustc_target::callconv::ArgAttribute::NonNull) { non_null_args.push(arg_index as i32 + 1); } ty diff --git a/src/builder.rs b/src/builder.rs index 89e5cf1b8c6b..bba19d062583 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -29,7 +29,7 @@ use rustc_middle::ty::layout::{ use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_span::Span; use rustc_span::def_id::DefId; -use rustc_target::abi::call::FnAbi; +use rustc_target::callconv::FnAbi; use rustc_target::spec::{HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, Target, WasmCAbi, X86Abi}; use crate::common::{SignType, TypeReflection, type_is_pointer}; diff --git a/src/consts.rs b/src/consts.rs index 1631ecfeecf3..fb0ca31c5433 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -1,6 +1,7 @@ #[cfg(feature = "master")] use gccjit::{FnAttribute, VarAttribute, Visibility}; use gccjit::{Function, GlobalKind, LValue, RValue, ToRValue, Type}; +use rustc_abi::{self as abi, Align, HasDataLayout, Primitive, Size, WrappingRange}; use rustc_codegen_ssa::traits::{ BaseTypeCodegenMethods, ConstCodegenMethods, StaticCodegenMethods, }; @@ -14,7 +15,6 @@ use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Instance}; use rustc_middle::{bug, span_bug}; use rustc_span::def_id::DefId; -use rustc_target::abi::{self, Align, HasDataLayout, Primitive, Size, WrappingRange}; use crate::base; use crate::context::CodegenCx; diff --git a/src/context.rs b/src/context.rs index 570ef938dc44..1e1f577bb3a1 100644 --- a/src/context.rs +++ b/src/context.rs @@ -3,6 +3,7 @@ use std::cell::{Cell, RefCell}; use gccjit::{ Block, CType, Context, Function, FunctionPtrType, FunctionType, LValue, Location, RValue, Type, }; +use rustc_abi::{HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx}; use rustc_codegen_ssa::base::wants_msvc_seh; use rustc_codegen_ssa::errors as ssa_errors; use rustc_codegen_ssa::traits::{BackendTypes, BaseTypeCodegenMethods, MiscCodegenMethods}; @@ -18,7 +19,6 @@ use rustc_middle::ty::{self, ExistentialTraitRef, Instance, Ty, TyCtxt}; use rustc_session::Session; use rustc_span::source_map::respan; use rustc_span::{DUMMY_SP, Span}; -use rustc_target::abi::{HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx}; use rustc_target::spec::{ HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, Target, TlsModel, WasmCAbi, X86Abi, }; diff --git a/src/debuginfo.rs b/src/debuginfo.rs index 86d3de225f71..3f6fdea9fb8c 100644 --- a/src/debuginfo.rs +++ b/src/debuginfo.rs @@ -1,6 +1,7 @@ use std::ops::Range; use gccjit::{Location, RValue}; +use rustc_abi::Size; use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, VariableKind}; use rustc_codegen_ssa::traits::{DebugInfoBuilderMethods, DebugInfoCodegenMethods}; use rustc_data_structures::sync::Lrc; @@ -10,8 +11,7 @@ use rustc_middle::mir::{self, Body, SourceScope}; use rustc_middle::ty::{ExistentialTraitRef, Instance, Ty}; use rustc_session::config::DebugInfo; use rustc_span::{BytePos, Pos, SourceFile, SourceFileAndLine, Span, Symbol}; -use rustc_target::abi::Size; -use rustc_target::abi::call::FnAbi; +use rustc_target::callconv::FnAbi; use crate::builder::Builder; use crate::context::CodegenCx; diff --git a/src/declare.rs b/src/declare.rs index 442488b7fd65..7cdbe3c0c629 100644 --- a/src/declare.rs +++ b/src/declare.rs @@ -4,7 +4,7 @@ use gccjit::{Function, FunctionType, GlobalKind, LValue, RValue, Type}; use rustc_codegen_ssa::traits::BaseTypeCodegenMethods; use rustc_middle::ty::Ty; use rustc_span::Symbol; -use rustc_target::abi::call::FnAbi; +use rustc_target::callconv::FnAbi; use crate::abi::{FnAbiGcc, FnAbiGccExt}; use crate::context::CodegenCx; diff --git a/src/int.rs b/src/int.rs index fe6a65bed03b..4a1db8d662a9 100644 --- a/src/int.rs +++ b/src/int.rs @@ -3,12 +3,11 @@ //! 128-bit integers on 32-bit platforms and thus require to be handled manually. use gccjit::{BinaryOp, ComparisonOp, FunctionType, Location, RValue, ToRValue, Type, UnaryOp}; +use rustc_abi::{Endian, ExternAbi}; use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; use rustc_codegen_ssa::traits::{BackendTypes, BaseTypeCodegenMethods, BuilderMethods, OverflowOp}; use rustc_middle::ty::{self, Ty}; -use rustc_target::abi::Endian; -use rustc_target::abi::call::{ArgAbi, ArgAttributes, Conv, FnAbi, PassMode}; -use rustc_target::spec; +use rustc_target::callconv::{ArgAbi, ArgAttributes, Conv, FnAbi, PassMode}; use crate::builder::{Builder, ToGccComp}; use crate::common::{SignType, TypeReflection}; @@ -401,7 +400,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { conv: Conv::C, can_unwind: false, }; - fn_abi.adjust_for_foreign_abi(self.cx, spec::abi::Abi::C { unwind: false }).unwrap(); + fn_abi.adjust_for_foreign_abi(self.cx, ExternAbi::C { unwind: false }).unwrap(); let ret_indirect = matches!(fn_abi.ret.mode, PassMode::Indirect { .. }); diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 48606f5f91c0..a1123fafe2f3 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -7,6 +7,9 @@ use std::iter; #[cfg(feature = "master")] use gccjit::FunctionType; use gccjit::{ComparisonOp, Function, RValue, ToRValue, Type, UnaryOp}; +#[cfg(feature = "master")] +use rustc_abi::ExternAbi; +use rustc_abi::HasDataLayout; use rustc_codegen_ssa::MemFlags; use rustc_codegen_ssa::base::wants_msvc_seh; use rustc_codegen_ssa::common::IntPredicate; @@ -25,11 +28,8 @@ use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt}; use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf}; use rustc_middle::ty::{self, Instance, Ty}; use rustc_span::{Span, Symbol, sym}; -use rustc_target::abi::HasDataLayout; -use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode}; +use rustc_target::callconv::{ArgAbi, FnAbi, PassMode}; use rustc_target::spec::PanicStrategy; -#[cfg(feature = "master")] -use rustc_target::spec::abi::Abi; #[cfg(feature = "master")] use crate::abi::FnAbiGccExt; @@ -1238,7 +1238,7 @@ fn get_rust_try_fn<'a, 'gcc, 'tcx>( tcx.types.unit, false, rustc_hir::Safety::Unsafe, - Abi::Rust, + ExternAbi::Rust, )), ); // `unsafe fn(*mut i8, *mut i8) -> ()` @@ -1249,7 +1249,7 @@ fn get_rust_try_fn<'a, 'gcc, 'tcx>( tcx.types.unit, false, rustc_hir::Safety::Unsafe, - Abi::Rust, + ExternAbi::Rust, )), ); // `unsafe fn(unsafe fn(*mut i8) -> (), *mut i8, unsafe fn(*mut i8, *mut i8) -> ()) -> i32` @@ -1258,7 +1258,7 @@ fn get_rust_try_fn<'a, 'gcc, 'tcx>( tcx.types.i32, false, rustc_hir::Safety::Unsafe, - Abi::Rust, + ExternAbi::Rust, )); let rust_try = gen_fn(cx, "__rust_try", rust_fn_sig, codegen); cx.rust_try_fn.set(Some(rust_try)); diff --git a/src/intrinsic/simd.rs b/src/intrinsic/simd.rs index 1be452e5d05d..12a7dab155b4 100644 --- a/src/intrinsic/simd.rs +++ b/src/intrinsic/simd.rs @@ -3,6 +3,7 @@ use std::iter::FromIterator; use gccjit::{BinaryOp, RValue, ToRValue, Type}; #[cfg(feature = "master")] use gccjit::{ComparisonOp, UnaryOp}; +use rustc_abi::{Align, Size}; use rustc_codegen_ssa::base::compare_simd_types; use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; #[cfg(feature = "master")] @@ -17,7 +18,6 @@ use rustc_middle::mir::BinOp; use rustc_middle::ty::layout::HasTyCtxt; use rustc_middle::ty::{self, Ty}; use rustc_span::{Span, Symbol, sym}; -use rustc_target::abi::{Align, Size}; use crate::builder::Builder; #[cfg(not(feature = "master"))] diff --git a/src/type_.rs b/src/type_.rs index 4ea5544721de..cb08723431a9 100644 --- a/src/type_.rs +++ b/src/type_.rs @@ -4,13 +4,13 @@ use std::convert::TryInto; #[cfg(feature = "master")] use gccjit::CType; use gccjit::{RValue, Struct, Type}; +use rustc_abi::{AddressSpace, Align, Integer, Size}; use rustc_codegen_ssa::common::TypeKind; use rustc_codegen_ssa::traits::{ BaseTypeCodegenMethods, DerivedTypeCodegenMethods, TypeMembershipCodegenMethods, }; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::{bug, ty}; -use rustc_target::abi::{AddressSpace, Align, Integer, Size}; use crate::common::TypeReflection; use crate::context::CodegenCx; diff --git a/src/type_of.rs b/src/type_of.rs index 0efdf36da485..8b8b54753e7f 100644 --- a/src/type_of.rs +++ b/src/type_of.rs @@ -3,7 +3,9 @@ use std::fmt::Write; use gccjit::{Struct, Type}; use rustc_abi as abi; use rustc_abi::Primitive::*; -use rustc_abi::{BackendRepr, FieldsShape, Integer, PointeeInfo, Size, Variants}; +use rustc_abi::{ + BackendRepr, FieldsShape, Integer, PointeeInfo, Reg, Size, TyAbiInterface, Variants, +}; use rustc_codegen_ssa::traits::{ BaseTypeCodegenMethods, DerivedTypeCodegenMethods, LayoutTypeCodegenMethods, }; @@ -11,8 +13,7 @@ use rustc_middle::bug; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, CoroutineArgsExt, Ty, TypeVisitableExt}; -use rustc_target::abi::TyAbiInterface; -use rustc_target::abi::call::{CastTarget, FnAbi, Reg}; +use rustc_target::callconv::{CastTarget, FnAbi}; use crate::abi::{FnAbiGcc, FnAbiGccExt, GccType}; use crate::context::CodegenCx; From 2214ba9f1a9a3d88098ae34912d5c646b57f59a6 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Wed, 5 Feb 2025 12:16:57 -0500 Subject: [PATCH 022/606] Run the CI on push on the master branch --- .github/workflows/ci.yml | 5 ++++- .github/workflows/failures.yml | 5 ++++- .github/workflows/gcc12.yml | 5 ++++- .github/workflows/m68k.yml | 5 ++++- .github/workflows/release.yml | 5 ++++- .github/workflows/stdarch.yml | 5 ++++- 6 files changed, 24 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bf974f65c1e1..ef024258ffc8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,7 +1,10 @@ name: CI on: - - pull_request + push: + branches: + - master + pull_request: permissions: contents: read diff --git a/.github/workflows/failures.yml b/.github/workflows/failures.yml index ab3e4002e87f..bc42eb1468ea 100644 --- a/.github/workflows/failures.yml +++ b/.github/workflows/failures.yml @@ -2,7 +2,10 @@ name: Failures on: - - pull_request + push: + branches: + - master + pull_request: permissions: contents: read diff --git a/.github/workflows/gcc12.yml b/.github/workflows/gcc12.yml index d6b7e5a2a13a..da9a1506855c 100644 --- a/.github/workflows/gcc12.yml +++ b/.github/workflows/gcc12.yml @@ -1,7 +1,10 @@ name: CI libgccjit 12 on: - - pull_request + push: + branches: + - master + pull_request: permissions: contents: read diff --git a/.github/workflows/m68k.yml b/.github/workflows/m68k.yml index 90fa5acc3fb0..21731f7087e2 100644 --- a/.github/workflows/m68k.yml +++ b/.github/workflows/m68k.yml @@ -3,7 +3,10 @@ name: m68k CI on: - - pull_request + push: + branches: + - master + pull_request: permissions: contents: read diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2f6e3b475319..47a40286554e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,7 +1,10 @@ name: CI with sysroot compiled in release mode on: - - pull_request + push: + branches: + - master + pull_request: permissions: contents: read diff --git a/.github/workflows/stdarch.yml b/.github/workflows/stdarch.yml index 350e099d8870..4b9f48e7b183 100644 --- a/.github/workflows/stdarch.yml +++ b/.github/workflows/stdarch.yml @@ -1,7 +1,10 @@ name: stdarch tests with sysroot compiled in release mode on: - - pull_request + push: + branches: + - master + pull_request: permissions: contents: read From 09d907627b6f86fae8cc926a353a44bd723ccf59 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Fri, 7 Feb 2025 16:48:39 +0100 Subject: [PATCH 023/606] fix backslashes in path used for `asm_tests` --- build_system/src/test.rs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index efd7b2b8df3a..096b4c4a7154 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -542,20 +542,21 @@ fn asm_tests(env: &Env, args: &TestArg) -> Result<(), String> { env.insert("COMPILETEST_FORCE_STAGE0".to_string(), "1".to_string()); - let extra = - if args.is_using_gcc_master_branch() { "" } else { " -Csymbol-mangling-version=v0" }; - - let rustc_args = &format!( - r#"-Zpanic-abort-tests \ - -Zcodegen-backend="{pwd}/target/{channel}/librustc_codegen_gcc.{dylib_ext}" \ - --sysroot "{sysroot_dir}" -Cpanic=abort{extra}"#, + let codegen_backend_path = format!( + "{pwd}/target/{channel}/librustc_codegen_gcc.{dylib_ext}", pwd = std::env::current_dir() .map_err(|error| format!("`current_dir` failed: {:?}", error))? .display(), channel = args.config_info.channel.as_str(), dylib_ext = args.config_info.dylib_ext, - sysroot_dir = args.config_info.sysroot_path, - extra = extra, + ); + + let extra = + if args.is_using_gcc_master_branch() { "" } else { " -Csymbol-mangling-version=v0" }; + + let rustc_args = format!( + "-Zpanic-abort-tests -Zcodegen-backend={codegen_backend_path} --sysroot {} -Cpanic=abort{extra}", + args.config_info.sysroot_path ); run_command_with_env( From 21b60aad987f5e61658901675cd64a5736ee5eef Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 7 Feb 2025 14:47:21 +0000 Subject: [PATCH 024/606] Remove Linkage::Private This is the same as Linkage::Internal except that it doesn't emit any symbol. Some backends may not support it and it isn't all that useful anyway. --- src/base.rs | 2 -- src/mono_item.rs | 5 +---- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/base.rs b/src/base.rs index c9701fb9885c..f2fc09800447 100644 --- a/src/base.rs +++ b/src/base.rs @@ -51,7 +51,6 @@ pub fn global_linkage_to_gcc(linkage: Linkage) -> GlobalKind { Linkage::WeakODR => unimplemented!(), Linkage::Appending => unimplemented!(), Linkage::Internal => GlobalKind::Internal, - Linkage::Private => GlobalKind::Internal, Linkage::ExternalWeak => GlobalKind::Imported, // TODO(antoyo): should be weak linkage. Linkage::Common => unimplemented!(), } @@ -68,7 +67,6 @@ pub fn linkage_to_gcc(linkage: Linkage) -> FunctionType { Linkage::WeakODR => unimplemented!(), Linkage::Appending => unimplemented!(), Linkage::Internal => FunctionType::Internal, - Linkage::Private => FunctionType::Internal, Linkage::ExternalWeak => unimplemented!(), Linkage::Common => unimplemented!(), } diff --git a/src/mono_item.rs b/src/mono_item.rs index 239902df7f04..a2df7b2596fc 100644 --- a/src/mono_item.rs +++ b/src/mono_item.rs @@ -61,10 +61,7 @@ impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { // compiler-rt, then we want to implicitly compile everything with hidden // visibility as we're going to link this object all over the place but // don't want the symbols to get exported. - if linkage != Linkage::Internal - && linkage != Linkage::Private - && self.tcx.is_compiler_builtins(LOCAL_CRATE) - { + if linkage != Linkage::Internal && self.tcx.is_compiler_builtins(LOCAL_CRATE) { #[cfg(feature = "master")] decl.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden)); } else { From a90648d25533cd67d978d611dcddeb6f4b6caa39 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 7 Feb 2025 14:52:07 +0000 Subject: [PATCH 025/606] Remove Linkage::Appending It can only be used for certain LLVM internal variables like llvm.global_ctors which users are not allowed to define. --- src/base.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/base.rs b/src/base.rs index f2fc09800447..962f4b161d78 100644 --- a/src/base.rs +++ b/src/base.rs @@ -49,7 +49,6 @@ pub fn global_linkage_to_gcc(linkage: Linkage) -> GlobalKind { Linkage::LinkOnceODR => unimplemented!(), Linkage::WeakAny => unimplemented!(), Linkage::WeakODR => unimplemented!(), - Linkage::Appending => unimplemented!(), Linkage::Internal => GlobalKind::Internal, Linkage::ExternalWeak => GlobalKind::Imported, // TODO(antoyo): should be weak linkage. Linkage::Common => unimplemented!(), @@ -65,7 +64,6 @@ pub fn linkage_to_gcc(linkage: Linkage) -> FunctionType { Linkage::LinkOnceODR => unimplemented!(), Linkage::WeakAny => FunctionType::Exported, // FIXME(antoyo): should be similar to linkonce. Linkage::WeakODR => unimplemented!(), - Linkage::Appending => unimplemented!(), Linkage::Internal => FunctionType::Internal, Linkage::ExternalWeak => unimplemented!(), Linkage::Common => unimplemented!(), From 83f7576a770d394c79c8ef28e1687e3ad0f747d9 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Tue, 4 Feb 2025 22:56:30 -0800 Subject: [PATCH 026/606] compiler: remove reexports from rustc_target::callconv --- src/abi.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/abi.rs b/src/abi.rs index d94fc5525288..717baebcd8cd 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -1,6 +1,7 @@ #[cfg(feature = "master")] use gccjit::FnAttribute; use gccjit::{ToLValue, ToRValue, Type}; +use rustc_abi::{Reg, RegKind}; use rustc_codegen_ssa::traits::{AbiBuilderMethods, BaseTypeCodegenMethods}; use rustc_data_structures::fx::FxHashSet; use rustc_middle::bug; @@ -8,7 +9,7 @@ use rustc_middle::ty::Ty; use rustc_middle::ty::layout::LayoutOf; #[cfg(feature = "master")] use rustc_session::config; -use rustc_target::callconv::{ArgAttributes, CastTarget, FnAbi, PassMode, Reg, RegKind}; +use rustc_target::callconv::{ArgAttributes, CastTarget, FnAbi, PassMode}; use crate::builder::Builder; use crate::context::CodegenCx; From 180f350fc67eed3142fdc7b2e7e6955e4922642e Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 8 Feb 2025 22:12:13 +0000 Subject: [PATCH 027/606] Rustfmt --- src/builder.rs | 21 +- src/intrinsic/llvm.rs | 22 +- src/intrinsic/simd.rs | 464 +++++++++++++++++++++--------------------- 3 files changed, 258 insertions(+), 249 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index bba19d062583..1c3d6cc899a6 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -155,14 +155,11 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { // NOTE: not sure why, but we have the wrong type here. let int_type = compare_exchange.get_param(2).to_rvalue().get_type(); let src = self.context.new_bitcast(self.location, src, int_type); - self.context.new_call(self.location, compare_exchange, &[ - dst, - expected, - src, - weak, - order, - failure_order, - ]) + self.context.new_call( + self.location, + compare_exchange, + &[dst, expected, src, weak, order, failure_order], + ) } pub fn assign(&self, lvalue: LValue<'gcc>, value: RValue<'gcc>) { @@ -1076,9 +1073,11 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let align = dest.val.align.restrict_for_offset(dest.layout.field(self.cx(), 0).size); cg_elem.val.store(self, PlaceRef::new_sized_aligned(current_val, cg_elem.layout, align)); - let next = self.inbounds_gep(self.backend_type(cg_elem.layout), current.to_rvalue(), &[ - self.const_usize(1), - ]); + let next = self.inbounds_gep( + self.backend_type(cg_elem.layout), + current.to_rvalue(), + &[self.const_usize(1)], + ); self.llbb().add_assignment(self.location, current, next); self.br(header_bb); diff --git a/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index 231307def291..2d731f88d7d3 100644 --- a/src/intrinsic/llvm.rs +++ b/src/intrinsic/llvm.rs @@ -687,11 +687,12 @@ pub fn adjust_intrinsic_return_value<'a, 'gcc, 'tcx>( let field2 = builder.context.new_field(None, args[1].get_type(), "carryResult"); let struct_type = builder.context.new_struct_type(None, "addcarryResult", &[field1, field2]); - return_value = - builder.context.new_struct_constructor(None, struct_type.as_type(), None, &[ - return_value, - last_arg.dereference(None).to_rvalue(), - ]); + return_value = builder.context.new_struct_constructor( + None, + struct_type.as_type(), + None, + &[return_value, last_arg.dereference(None).to_rvalue()], + ); } } "__builtin_ia32_stmxcsr" => { @@ -716,11 +717,12 @@ pub fn adjust_intrinsic_return_value<'a, 'gcc, 'tcx>( let field2 = builder.context.new_field(None, return_value.get_type(), "success"); let struct_type = builder.context.new_struct_type(None, "rdrand_result", &[field1, field2]); - return_value = - builder.context.new_struct_constructor(None, struct_type.as_type(), None, &[ - random_number, - success_variable.to_rvalue(), - ]); + return_value = builder.context.new_struct_constructor( + None, + struct_type.as_type(), + None, + &[random_number, success_variable.to_rvalue()], + ); } "fma" => { let f16_type = builder.context.new_c_type(CType::Float16); diff --git a/src/intrinsic/simd.rs b/src/intrinsic/simd.rs index 12a7dab155b4..84cd5b002fbb 100644 --- a/src/intrinsic/simd.rs +++ b/src/intrinsic/simd.rs @@ -62,11 +62,10 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( let arg_tys = sig.inputs(); if name == sym::simd_select_bitmask { - require_simd!(arg_tys[1], InvalidMonomorphization::SimdArgument { - span, - name, - ty: arg_tys[1] - }); + require_simd!( + arg_tys[1], + InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] } + ); let (len, _) = arg_tys[1].simd_size_and_type(bx.tcx()); let expected_int_bits = (len.max(8) - 1).next_power_of_two(); @@ -140,14 +139,17 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx()); - require!(in_len == out_len, InvalidMonomorphization::ReturnLengthInputType { - span, - name, - in_len, - in_ty, - ret_ty, - out_len - }); + require!( + in_len == out_len, + InvalidMonomorphization::ReturnLengthInputType { + span, + name, + in_len, + in_ty, + ret_ty, + out_len + } + ); require!( bx.type_kind(bx.element_type(llret_ty)) == TypeKind::Integer, InvalidMonomorphization::ReturnIntegerType { span, name, ret_ty, out_ty } @@ -269,23 +271,17 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( let lo_nibble = bx.context.new_rvalue_from_vector(None, long_byte_vector_type, &lo_nibble_elements); - let mask = bx.context.new_rvalue_from_vector(None, long_byte_vector_type, &vec![ - bx.context - .new_rvalue_from_int( - bx.u8_type, 0x0f - ); - byte_vector_type_size - as _ - ]); + let mask = bx.context.new_rvalue_from_vector( + None, + long_byte_vector_type, + &vec![bx.context.new_rvalue_from_int(bx.u8_type, 0x0f); byte_vector_type_size as _], + ); - let four_vec = bx.context.new_rvalue_from_vector(None, long_byte_vector_type, &vec![ - bx.context - .new_rvalue_from_int( - bx.u8_type, 4 - ); - byte_vector_type_size - as _ - ]); + let four_vec = bx.context.new_rvalue_from_vector( + None, + long_byte_vector_type, + &vec![bx.context.new_rvalue_from_int(bx.u8_type, 4); byte_vector_type_size as _], + ); // Step 2: Byte-swap the input. let swapped = simd_bswap(bx, args[0].immediate()); @@ -388,21 +384,14 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx()); - require!(out_len == n, InvalidMonomorphization::ReturnLength { - span, - name, - in_len: n, - ret_ty, - out_len - }); - require!(in_elem == out_ty, InvalidMonomorphization::ReturnElement { - span, - name, - in_elem, - in_ty, - ret_ty, - out_ty - }); + require!( + out_len == n, + InvalidMonomorphization::ReturnLength { span, name, in_len: n, ret_ty, out_len } + ); + require!( + in_elem == out_ty, + InvalidMonomorphization::ReturnElement { span, name, in_elem, in_ty, ret_ty, out_ty } + ); let vector = args[2].immediate(); @@ -411,13 +400,16 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( #[cfg(feature = "master")] if name == sym::simd_insert { - require!(in_elem == arg_tys[2], InvalidMonomorphization::InsertedType { - span, - name, - in_elem, - in_ty, - out_ty: arg_tys[2] - }); + require!( + in_elem == arg_tys[2], + InvalidMonomorphization::InsertedType { + span, + name, + in_elem, + in_ty, + out_ty: arg_tys[2] + } + ); let vector = args[0].immediate(); let index = args[1].immediate(); let value = args[2].immediate(); @@ -431,13 +423,10 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( #[cfg(feature = "master")] if name == sym::simd_extract { - require!(ret_ty == in_elem, InvalidMonomorphization::ReturnType { - span, - name, - in_elem, - in_ty, - ret_ty - }); + require!( + ret_ty == in_elem, + InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty } + ); let vector = args[0].immediate(); return Ok(bx.context.new_vector_access(None, vector, args[1].immediate()).to_rvalue()); } @@ -445,18 +434,15 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( if name == sym::simd_select { let m_elem_ty = in_elem; let m_len = in_len; - require_simd!(arg_tys[1], InvalidMonomorphization::SimdArgument { - span, - name, - ty: arg_tys[1] - }); + require_simd!( + arg_tys[1], + InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] } + ); let (v_len, _) = arg_tys[1].simd_size_and_type(bx.tcx()); - require!(m_len == v_len, InvalidMonomorphization::MismatchedLengths { - span, - name, - m_len, - v_len - }); + require!( + m_len == v_len, + InvalidMonomorphization::MismatchedLengths { span, name, m_len, v_len } + ); match *m_elem_ty.kind() { ty::Int(_) => {} _ => return_error!(InvalidMonomorphization::MaskType { span, name, ty: m_elem_ty }), @@ -468,25 +454,27 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx()); - require!(in_len == out_len, InvalidMonomorphization::ReturnLengthInputType { - span, - name, - in_len, - in_ty, - ret_ty, - out_len - }); + require!( + in_len == out_len, + InvalidMonomorphization::ReturnLengthInputType { + span, + name, + in_len, + in_ty, + ret_ty, + out_len + } + ); match *in_elem.kind() { ty::RawPtr(p_ty, _) => { let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| { bx.tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), ty) }); - require!(metadata.is_unit(), InvalidMonomorphization::CastWidePointer { - span, - name, - ty: in_elem - }); + require!( + metadata.is_unit(), + InvalidMonomorphization::CastWidePointer { span, name, ty: in_elem } + ); } _ => { return_error!(InvalidMonomorphization::ExpectedPointer { span, name, ty: in_elem }) @@ -497,11 +485,10 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| { bx.tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), ty) }); - require!(metadata.is_unit(), InvalidMonomorphization::CastWidePointer { - span, - name, - ty: out_elem - }); + require!( + metadata.is_unit(), + InvalidMonomorphization::CastWidePointer { span, name, ty: out_elem } + ); } _ => { return_error!(InvalidMonomorphization::ExpectedPointer { span, name, ty: out_elem }) @@ -524,14 +511,17 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx()); - require!(in_len == out_len, InvalidMonomorphization::ReturnLengthInputType { - span, - name, - in_len, - in_ty, - ret_ty, - out_len - }); + require!( + in_len == out_len, + InvalidMonomorphization::ReturnLengthInputType { + span, + name, + in_len, + in_ty, + ret_ty, + out_len + } + ); match *in_elem.kind() { ty::RawPtr(_, _) => {} @@ -560,14 +550,17 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx()); - require!(in_len == out_len, InvalidMonomorphization::ReturnLengthInputType { - span, - name, - in_len, - in_ty, - ret_ty, - out_len - }); + require!( + in_len == out_len, + InvalidMonomorphization::ReturnLengthInputType { + span, + name, + in_len, + in_ty, + ret_ty, + out_len + } + ); match *in_elem.kind() { ty::Uint(ty::UintTy::Usize) => {} @@ -596,14 +589,17 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( if name == sym::simd_cast || name == sym::simd_as { require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx()); - require!(in_len == out_len, InvalidMonomorphization::ReturnLengthInputType { - span, - name, - in_len, - in_ty, - ret_ty, - out_len - }); + require!( + in_len == out_len, + InvalidMonomorphization::ReturnLengthInputType { + span, + name, + in_len, + in_ty, + ret_ty, + out_len + } + ); // casting cares about nominal type, not just structural type if in_elem == out_elem { return Ok(args[0].immediate()); @@ -629,14 +625,17 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( match (in_style, out_style) { (Style::Unsupported, Style::Unsupported) => { - require!(false, InvalidMonomorphization::UnsupportedCast { - span, - name, - in_ty, - in_elem, - ret_ty, - out_elem - }); + require!( + false, + InvalidMonomorphization::UnsupportedCast { + span, + name, + in_ty, + in_elem, + ret_ty, + out_elem + } + ); } _ => return Ok(bx.context.convert_vector(None, args[0].immediate(), llret_ty)), } @@ -914,45 +913,47 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( // All types must be simd vector types require_simd!(in_ty, InvalidMonomorphization::SimdFirst { span, name, ty: in_ty }); - require_simd!(arg_tys[1], InvalidMonomorphization::SimdSecond { - span, - name, - ty: arg_tys[1] - }); - require_simd!(arg_tys[2], InvalidMonomorphization::SimdThird { - span, - name, - ty: arg_tys[2] - }); + require_simd!( + arg_tys[1], + InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] } + ); + require_simd!( + arg_tys[2], + InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] } + ); require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); // Of the same length: let (out_len, _) = arg_tys[1].simd_size_and_type(bx.tcx()); let (out_len2, _) = arg_tys[2].simd_size_and_type(bx.tcx()); - require!(in_len == out_len, InvalidMonomorphization::SecondArgumentLength { - span, - name, - in_len, - in_ty, - arg_ty: arg_tys[1], - out_len - }); - require!(in_len == out_len2, InvalidMonomorphization::ThirdArgumentLength { - span, - name, - in_len, - in_ty, - arg_ty: arg_tys[2], - out_len: out_len2 - }); + require!( + in_len == out_len, + InvalidMonomorphization::SecondArgumentLength { + span, + name, + in_len, + in_ty, + arg_ty: arg_tys[1], + out_len + } + ); + require!( + in_len == out_len2, + InvalidMonomorphization::ThirdArgumentLength { + span, + name, + in_len, + in_ty, + arg_ty: arg_tys[2], + out_len: out_len2 + } + ); // The return type must match the first argument type - require!(ret_ty == in_ty, InvalidMonomorphization::ExpectedReturnType { - span, - name, - in_ty, - ret_ty - }); + require!( + ret_ty == in_ty, + InvalidMonomorphization::ExpectedReturnType { span, name, in_ty, ret_ty } + ); // This counts how many pointers fn ptr_count(t: Ty<'_>) -> usize { @@ -979,15 +980,18 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( (ptr_count(element_ty1), non_ptr(element_ty1)) } _ => { - require!(false, InvalidMonomorphization::ExpectedElementType { - span, - name, - expected_element: element_ty1, - second_arg: arg_tys[1], - in_elem, - in_ty, - mutability: ExpectedPointerMutability::Not, - }); + require!( + false, + InvalidMonomorphization::ExpectedElementType { + span, + name, + expected_element: element_ty1, + second_arg: arg_tys[1], + in_elem, + in_ty, + mutability: ExpectedPointerMutability::Not, + } + ); unreachable!(); } }; @@ -1000,12 +1004,15 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( match *element_ty2.kind() { ty::Int(_) => (), _ => { - require!(false, InvalidMonomorphization::ThirdArgElementType { - span, - name, - expected_element: element_ty2, - third_arg: arg_tys[2] - }); + require!( + false, + InvalidMonomorphization::ThirdArgElementType { + span, + name, + expected_element: element_ty2, + third_arg: arg_tys[2] + } + ); } } @@ -1029,36 +1036,40 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( // All types must be simd vector types require_simd!(in_ty, InvalidMonomorphization::SimdFirst { span, name, ty: in_ty }); - require_simd!(arg_tys[1], InvalidMonomorphization::SimdSecond { - span, - name, - ty: arg_tys[1] - }); - require_simd!(arg_tys[2], InvalidMonomorphization::SimdThird { - span, - name, - ty: arg_tys[2] - }); + require_simd!( + arg_tys[1], + InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] } + ); + require_simd!( + arg_tys[2], + InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] } + ); // Of the same length: let (element_len1, _) = arg_tys[1].simd_size_and_type(bx.tcx()); let (element_len2, _) = arg_tys[2].simd_size_and_type(bx.tcx()); - require!(in_len == element_len1, InvalidMonomorphization::SecondArgumentLength { - span, - name, - in_len, - in_ty, - arg_ty: arg_tys[1], - out_len: element_len1 - }); - require!(in_len == element_len2, InvalidMonomorphization::ThirdArgumentLength { - span, - name, - in_len, - in_ty, - arg_ty: arg_tys[2], - out_len: element_len2 - }); + require!( + in_len == element_len1, + InvalidMonomorphization::SecondArgumentLength { + span, + name, + in_len, + in_ty, + arg_ty: arg_tys[1], + out_len: element_len1 + } + ); + require!( + in_len == element_len2, + InvalidMonomorphization::ThirdArgumentLength { + span, + name, + in_len, + in_ty, + arg_ty: arg_tys[2], + out_len: element_len2 + } + ); // This counts how many pointers fn ptr_count(t: Ty<'_>) -> usize { @@ -1086,15 +1097,18 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( (ptr_count(element_ty1), non_ptr(element_ty1)) } _ => { - require!(false, InvalidMonomorphization::ExpectedElementType { - span, - name, - expected_element: element_ty1, - second_arg: arg_tys[1], - in_elem, - in_ty, - mutability: ExpectedPointerMutability::Mut, - }); + require!( + false, + InvalidMonomorphization::ExpectedElementType { + span, + name, + expected_element: element_ty1, + second_arg: arg_tys[1], + in_elem, + in_ty, + mutability: ExpectedPointerMutability::Mut, + } + ); unreachable!(); } }; @@ -1106,12 +1120,15 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( match *element_ty2.kind() { ty::Int(_) => (), _ => { - require!(false, InvalidMonomorphization::ThirdArgElementType { - span, - name, - expected_element: element_ty2, - third_arg: arg_tys[2] - }); + require!( + false, + InvalidMonomorphization::ThirdArgElementType { + span, + name, + expected_element: element_ty2, + third_arg: arg_tys[2] + } + ); } } @@ -1278,13 +1295,10 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( ($name:ident : $vec_op:expr, $float_reduce:ident, $ordered:expr, $op:ident, $identity:expr) => { if name == sym::$name { - require!(ret_ty == in_elem, InvalidMonomorphization::ReturnType { - span, - name, - in_elem, - in_ty, - ret_ty - }); + require!( + ret_ty == in_elem, + InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty } + ); return match *in_elem.kind() { ty::Int(_) | ty::Uint(_) => { let r = bx.vector_reduce_op(args[0].immediate(), $vec_op); @@ -1350,13 +1364,10 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( macro_rules! minmax_red { ($name:ident: $int_red:ident, $float_red:ident) => { if name == sym::$name { - require!(ret_ty == in_elem, InvalidMonomorphization::ReturnType { - span, - name, - in_elem, - in_ty, - ret_ty - }); + require!( + ret_ty == in_elem, + InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty } + ); return match *in_elem.kind() { ty::Int(_) | ty::Uint(_) => Ok(bx.$int_red(args[0].immediate())), ty::Float(_) => Ok(bx.$float_red(args[0].immediate())), @@ -1380,13 +1391,10 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( ($name:ident : $op:expr, $boolean:expr) => { if name == sym::$name { let input = if !$boolean { - require!(ret_ty == in_elem, InvalidMonomorphization::ReturnType { - span, - name, - in_elem, - in_ty, - ret_ty - }); + require!( + ret_ty == in_elem, + InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty } + ); args[0].immediate() } else { match *in_elem.kind() { From cb499a29a8d26cf58e4b26ea70fd49c9486e7528 Mon Sep 17 00:00:00 2001 From: c8ef Date: Tue, 11 Feb 2025 03:17:38 +0800 Subject: [PATCH 028/606] remove some intrinsics (#625) --- src/builder.rs | 10 +--------- src/intrinsic/llvm.rs | 42 +----------------------------------------- 2 files changed, 2 insertions(+), 50 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 89e5cf1b8c6b..8268819c5fae 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -371,16 +371,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let previous_arg_count = args.len(); let orig_args = args; let args = { - let function_address_names = self.function_address_names.borrow(); - let original_function_name = function_address_names.get(&func_ptr); func_ptr = llvm::adjust_function(self.context, &func_name, func_ptr, args); - llvm::adjust_intrinsic_arguments( - self, - gcc_func, - args.into(), - &func_name, - original_function_name, - ) + llvm::adjust_intrinsic_arguments(self, gcc_func, args.into(), &func_name) }; let args_adjusted = args.len() != previous_arg_count; let args = self.check_ptr_call("call", func_ptr, &args); diff --git a/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index 231307def291..afa434ce74e3 100644 --- a/src/intrinsic/llvm.rs +++ b/src/intrinsic/llvm.rs @@ -1,6 +1,6 @@ use std::borrow::Cow; -use gccjit::{CType, Context, Function, FunctionPtrType, RValue, ToRValue, UnaryOp}; +use gccjit::{CType, Context, Function, FunctionPtrType, RValue, ToRValue}; use rustc_codegen_ssa::traits::BuilderMethods; use crate::builder::Builder; @@ -43,7 +43,6 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>( gcc_func: FunctionPtrType<'gcc>, mut args: Cow<'b, [RValue<'gcc>]>, func_name: &str, - original_function_name: Option<&String>, ) -> Cow<'b, [RValue<'gcc>]> { // TODO: this might not be a good way to workaround the missing tile builtins. if func_name == "__builtin_trap" { @@ -541,33 +540,6 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>( let c = builder.context.new_rvalue_from_vector(None, arg3_type, &[new_args[2]; 2]); args = vec![a, b, c, new_args[3]].into(); } - "__builtin_ia32_vfmaddsubpd256" - | "__builtin_ia32_vfmaddsubps" - | "__builtin_ia32_vfmaddsubps256" - | "__builtin_ia32_vfmaddsubpd" => { - if let Some(original_function_name) = original_function_name { - match &**original_function_name { - "llvm.x86.fma.vfmsubadd.pd.256" - | "llvm.x86.fma.vfmsubadd.ps" - | "llvm.x86.fma.vfmsubadd.ps.256" - | "llvm.x86.fma.vfmsubadd.pd" => { - // NOTE: since both llvm.x86.fma.vfmsubadd.ps and llvm.x86.fma.vfmaddsub.ps maps to - // __builtin_ia32_vfmaddsubps, only add minus if this comes from a - // subadd LLVM intrinsic, e.g. _mm256_fmsubadd_pd. - let mut new_args = args.to_vec(); - let arg3 = &mut new_args[2]; - *arg3 = builder.context.new_unary_op( - None, - UnaryOp::Minus, - arg3.get_type(), - *arg3, - ); - args = new_args.into(); - } - _ => (), - } - } - } "__builtin_ia32_ldmxcsr" => { // The builtin __builtin_ia32_ldmxcsr takes an integer value while llvm.x86.sse.ldmxcsr takes a pointer, // so dereference the pointer. @@ -913,16 +885,6 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function "llvm.ctlz.v4i64" => "__builtin_ia32_vplzcntq_256_mask", "llvm.ctlz.v2i64" => "__builtin_ia32_vplzcntq_128_mask", "llvm.ctpop.v32i16" => "__builtin_ia32_vpopcountw_v32hi", - "llvm.x86.fma.vfmsub.sd" => "__builtin_ia32_vfmsubsd3", - "llvm.x86.fma.vfmsub.ss" => "__builtin_ia32_vfmsubss3", - "llvm.x86.fma.vfmsubadd.pd" => "__builtin_ia32_vfmaddsubpd", - "llvm.x86.fma.vfmsubadd.pd.256" => "__builtin_ia32_vfmaddsubpd256", - "llvm.x86.fma.vfmsubadd.ps" => "__builtin_ia32_vfmaddsubps", - "llvm.x86.fma.vfmsubadd.ps.256" => "__builtin_ia32_vfmaddsubps256", - "llvm.x86.fma.vfnmadd.sd" => "__builtin_ia32_vfnmaddsd3", - "llvm.x86.fma.vfnmadd.ss" => "__builtin_ia32_vfnmaddss3", - "llvm.x86.fma.vfnmsub.sd" => "__builtin_ia32_vfnmsubsd3", - "llvm.x86.fma.vfnmsub.ss" => "__builtin_ia32_vfnmsubss3", "llvm.x86.avx512.conflict.d.512" => "__builtin_ia32_vpconflictsi_512_mask", "llvm.x86.avx512.conflict.d.256" => "__builtin_ia32_vpconflictsi_256_mask", "llvm.x86.avx512.conflict.d.128" => "__builtin_ia32_vpconflictsi_128_mask", @@ -1000,8 +962,6 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function "llvm.fshr.v32i16" => "__builtin_ia32_vpshrdv_v32hi", "llvm.fshr.v16i16" => "__builtin_ia32_vpshrdv_v16hi", "llvm.fshr.v8i16" => "__builtin_ia32_vpshrdv_v8hi", - "llvm.x86.fma.vfmadd.sd" => "__builtin_ia32_vfmaddsd3", - "llvm.x86.fma.vfmadd.ss" => "__builtin_ia32_vfmaddss3", "llvm.x86.rdrand.64" => "__builtin_ia32_rdrand64_step", // The above doc points to unknown builtins for the following, so override them: From 65da92e77c60a7144145b02719272b2c99419705 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Mon, 10 Feb 2025 11:19:02 -0800 Subject: [PATCH 029/606] cg_gcc: stop caring about compiling for unknown targets --- src/int.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/int.rs b/src/int.rs index 4a1db8d662a9..f3552d9b12fc 100644 --- a/src/int.rs +++ b/src/int.rs @@ -400,7 +400,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { conv: Conv::C, can_unwind: false, }; - fn_abi.adjust_for_foreign_abi(self.cx, ExternAbi::C { unwind: false }).unwrap(); + fn_abi.adjust_for_foreign_abi(self.cx, ExternAbi::C { unwind: false }); let ret_indirect = matches!(fn_abi.ret.mode, PassMode::Indirect { .. }); From d7f2227e63c9f496837530f338fc864532907704 Mon Sep 17 00:00:00 2001 From: Askar Safin Date: Tue, 11 Feb 2025 09:47:13 +0300 Subject: [PATCH 030/606] compiler/rustc_codegen_gcc/src/back/lto.rs: delete "unsafe impl Sync/Send" --- src/back/lto.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/back/lto.rs b/src/back/lto.rs index e419bd180990..cb4caec8c326 100644 --- a/src/back/lto.rs +++ b/src/back/lto.rs @@ -710,10 +710,6 @@ pub struct ThinBuffer { context: Arc, } -// TODO: check if this makes sense to make ThinBuffer Send and Sync. -unsafe impl Send for ThinBuffer {} -unsafe impl Sync for ThinBuffer {} - impl ThinBuffer { pub(crate) fn new(context: &Arc) -> Self { Self { context: Arc::clone(context) } From c817210c70bed03133395890a09908ae06e44c94 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Wed, 12 Feb 2025 15:22:13 +0100 Subject: [PATCH 031/606] handle NaN in unordered comparisons --- src/builder.rs | 45 +++++++++++++++++++++++++++++++++++++- tests/failing-ui-tests.txt | 1 - tests/run/float.rs | 32 +++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 tests/run/float.rs diff --git a/src/builder.rs b/src/builder.rs index 8268819c5fae..fc2f6862c161 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -1284,7 +1284,50 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } fn fcmp(&mut self, op: RealPredicate, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> { - self.context.new_comparison(self.location, op.to_gcc_comparison(), lhs, rhs) + // LLVM has a concept of "unordered compares", where eg ULT returns true if either the two + // arguments are unordered (i.e. either is NaN), or the lhs is less than the rhs. GCC does + // not natively have this concept, so in some cases we must manually handle NaNs + let must_handle_nan = match op { + RealPredicate::RealPredicateFalse => unreachable!(), + RealPredicate::RealOEQ => false, + RealPredicate::RealOGT => false, + RealPredicate::RealOGE => false, + RealPredicate::RealOLT => false, + RealPredicate::RealOLE => false, + RealPredicate::RealONE => false, + RealPredicate::RealORD => unreachable!(), + RealPredicate::RealUNO => unreachable!(), + RealPredicate::RealUEQ => false, + RealPredicate::RealUGT => true, + RealPredicate::RealUGE => true, + RealPredicate::RealULT => true, + RealPredicate::RealULE => true, + RealPredicate::RealUNE => false, + RealPredicate::RealPredicateTrue => unreachable!(), + }; + + let cmp = self.context.new_comparison(self.location, op.to_gcc_comparison(), lhs, rhs); + + if must_handle_nan { + let is_nan = self.context.new_binary_op( + self.location, + BinaryOp::LogicalOr, + self.cx.bool_type, + // compare a value to itself to check whether it is NaN + self.context.new_comparison(self.location, ComparisonOp::NotEquals, lhs, lhs), + self.context.new_comparison(self.location, ComparisonOp::NotEquals, rhs, rhs), + ); + + self.context.new_binary_op( + self.location, + BinaryOp::LogicalOr, + self.cx.bool_type, + is_nan, + cmp, + ) + } else { + cmp + } } /* Miscellaneous instructions */ diff --git a/tests/failing-ui-tests.txt b/tests/failing-ui-tests.txt index 082958bfe1f8..579ac3749e95 100644 --- a/tests/failing-ui-tests.txt +++ b/tests/failing-ui-tests.txt @@ -5,7 +5,6 @@ tests/ui/asm/x86_64/multiple-clobber-abi.rs tests/ui/functions-closures/parallel-codegen-closures.rs tests/ui/linkage-attr/linkage1.rs tests/ui/lto/dylib-works.rs -tests/ui/numbers-arithmetic/saturating-float-casts.rs tests/ui/sepcomp/sepcomp-cci.rs tests/ui/sepcomp/sepcomp-extern.rs tests/ui/sepcomp/sepcomp-fns-backwards.rs diff --git a/tests/run/float.rs b/tests/run/float.rs new file mode 100644 index 000000000000..e0a57e6fed1a --- /dev/null +++ b/tests/run/float.rs @@ -0,0 +1,32 @@ +// Compiler: +// +// Run-time: +// status: 0 + +#![feature(const_black_box)] + +/* + * Code + */ + +fn main() { + use std::hint::black_box; + + macro_rules! check { + ($ty:ty, $expr:expr) => {{ + const EXPECTED: $ty = $expr; + assert_eq!($expr, EXPECTED); + }}; + } + + check!(i32, (black_box(0.0f32) as i32)); + + check!(u64, (black_box(f32::NAN) as u64)); + check!(u128, (black_box(f32::NAN) as u128)); + + check!(i64, (black_box(f64::NAN) as i64)); + check!(u64, (black_box(f64::NAN) as u64)); + + check!(i16, (black_box(f32::MIN) as i16)); + check!(i16, (black_box(f32::MAX) as i16)); +} From 4f59a687f136ac0ce29ad68ea02066e06fb9fc88 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Wed, 12 Feb 2025 19:54:51 -0500 Subject: [PATCH 032/606] Support sysv64 and ms ABIs --- Cargo.lock | 8 ++++---- Cargo.toml | 2 +- src/abi.rs | 46 ++++++++++++++++++++++++++++++++++++++++++++++ src/context.rs | 8 +++++++- src/declare.rs | 25 ++++++++++++++----------- src/lib.rs | 4 ++-- 6 files changed, 74 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 636e75b94a3f..832603aa7925 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -56,18 +56,18 @@ dependencies = [ [[package]] name = "gccjit" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72fd91f4adbf02b53cfc73c97bc33c5f253009043f30c56a5ec08dd5c8094dc8" +checksum = "2895ddec764de7ac76fe6c056050c4801a80109c066f177a00a9cc8dee02b29b" dependencies = [ "gccjit_sys", ] [[package]] name = "gccjit_sys" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fb7b8f48a75e2cfe78c3d9a980b32771c34ffd12d196021ab3f98c49fbd2f0d" +checksum = "ac133db68db8a6a8b2c51ef4b18d8ea16682d5814c4641272fe37bbbc223d5f3" dependencies = [ "libc", ] diff --git a/Cargo.toml b/Cargo.toml index 63d37358561e..b50f2a626d57 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,7 @@ master = ["gccjit/master"] default = ["master"] [dependencies] -gccjit = "2.4" +gccjit = "2.5" #gccjit = { git = "https://github.com/rust-lang/gccjit.rs" } # Local copy. diff --git a/src/abi.rs b/src/abi.rs index 14fc23593f0e..35e9b356741e 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -9,6 +9,8 @@ use rustc_middle::ty::layout::LayoutOf; #[cfg(feature = "master")] use rustc_session::config; use rustc_target::abi::call::{ArgAttributes, CastTarget, FnAbi, PassMode, Reg, RegKind}; +#[cfg(feature = "master")] +use rustc_target::callconv::Conv; use crate::builder::Builder; use crate::context::CodegenCx; @@ -104,6 +106,8 @@ pub trait FnAbiGccExt<'gcc, 'tcx> { // TODO(antoyo): return a function pointer type instead? fn gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> FnAbiGcc<'gcc>; fn ptr_to_gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc>; + #[cfg(feature = "master")] + fn gcc_cconv(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Option>; } impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { @@ -226,4 +230,46 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { ); pointer_type } + + #[cfg(feature = "master")] + fn gcc_cconv(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Option> { + conv_to_fn_attribute(self.conv, &cx.tcx.sess.target.arch) + } +} + +#[cfg(feature = "master")] +pub fn conv_to_fn_attribute<'gcc>(conv: Conv, _arch: &str) -> Option> { + // TODO: handle the calling conventions returning None. + let attribute = match conv { + Conv::C + | Conv::Rust + | Conv::CCmseNonSecureCall + | Conv::CCmseNonSecureEntry + | Conv::RiscvInterrupt { .. } => return None, + Conv::Cold => return None, + Conv::PreserveMost => return None, + Conv::PreserveAll => return None, + /*Conv::GpuKernel => { + if arch == "amdgpu" { + return None + } else if arch == "nvptx64" { + return None + } else { + panic!("Architecture {arch} does not support GpuKernel calling convention"); + } + }*/ + Conv::AvrInterrupt => return None, + Conv::AvrNonBlockingInterrupt => return None, + Conv::ArmAapcs => return None, + Conv::Msp430Intr => return None, + Conv::PtxKernel => return None, + Conv::X86Fastcall => return None, + Conv::X86Intr => return None, + Conv::X86Stdcall => return None, + Conv::X86ThisCall => return None, + Conv::X86VectorCall => return None, + Conv::X86_64SysV => FnAttribute::SysvAbi, + Conv::X86_64Win64 => FnAttribute::MsAbi, + }; + Some(attribute) } diff --git a/src/context.rs b/src/context.rs index 2a33beef63b9..38d012c8ca6d 100644 --- a/src/context.rs +++ b/src/context.rs @@ -23,6 +23,8 @@ use rustc_target::spec::{ HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, Target, TlsModel, WasmCAbi, X86Abi, }; +#[cfg(feature = "master")] +use crate::abi::conv_to_fn_attribute; use crate::callee::get_fn; use crate::common::SignType; @@ -509,7 +511,11 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { fn declare_c_main(&self, fn_type: Self::Type) -> Option { let entry_name = self.sess().target.entry_name.as_ref(); if !self.functions.borrow().contains_key(entry_name) { - Some(self.declare_entry_fn(entry_name, fn_type, ())) + #[cfg(feature = "master")] + let conv = conv_to_fn_attribute(self.sess().target.entry_abi, &self.sess().target.arch); + #[cfg(not(feature = "master"))] + let conv = None; + Some(self.declare_entry_fn(entry_name, fn_type, conv)) } else { // If the symbol already exists, it is an error: for example, the user wrote // #[no_mangle] extern "C" fn main(..) {..} diff --git a/src/declare.rs b/src/declare.rs index 442488b7fd65..d4a4d7f4b82f 100644 --- a/src/declare.rs +++ b/src/declare.rs @@ -58,7 +58,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { variadic: bool, ) -> Function<'gcc> { self.linkage.set(FunctionType::Extern); - declare_raw_fn(self, name, () /*llvm::CCallConv*/, return_type, params, variadic) + declare_raw_fn(self, name, None, return_type, params, variadic) } pub fn declare_global( @@ -92,7 +92,8 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { &self, name: &str, _fn_type: Type<'gcc>, - callconv: (), /*llvm::CCallConv*/ + #[cfg(feature = "master")] callconv: Option>, + #[cfg(not(feature = "master"))] callconv: Option<()>, ) -> RValue<'gcc> { // TODO(antoyo): use the fn_type parameter. let const_string = self.context.new_type::().make_pointer().make_pointer(); @@ -123,14 +124,11 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { #[cfg(feature = "master")] fn_attributes, } = fn_abi.gcc_type(self); - let func = declare_raw_fn( - self, - name, - (), /*fn_abi.llvm_cconv()*/ - return_type, - &arguments_type, - is_c_variadic, - ); + #[cfg(feature = "master")] + let conv = fn_abi.gcc_cconv(self); + #[cfg(not(feature = "master"))] + let conv = None; + let func = declare_raw_fn(self, name, conv, return_type, &arguments_type, is_c_variadic); self.on_stack_function_params.borrow_mut().insert(func, on_stack_param_indices); #[cfg(feature = "master")] for fn_attr in fn_attributes { @@ -162,7 +160,8 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { fn declare_raw_fn<'gcc>( cx: &CodegenCx<'gcc, '_>, name: &str, - _callconv: (), /*llvm::CallConv*/ + #[cfg(feature = "master")] callconv: Option>, + #[cfg(not(feature = "master"))] _callconv: Option<()>, return_type: Type<'gcc>, param_types: &[Type<'gcc>], variadic: bool, @@ -192,6 +191,10 @@ fn declare_raw_fn<'gcc>( let name = &mangle_name(name); let func = cx.context.new_function(None, cx.linkage.get(), return_type, ¶ms, name, variadic); + #[cfg(feature = "master")] + if let Some(attribute) = callconv { + func.add_attribute(attribute); + } cx.functions.borrow_mut().insert(name.to_string(), func); #[cfg(feature = "master")] diff --git a/src/lib.rs b/src/lib.rs index f6ad0c79de54..68e0bc061add 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -187,10 +187,10 @@ impl CodegenBackend for GccCodegenBackend { crate::DEFAULT_LOCALE_RESOURCE } - fn init(&self, sess: &Session) { + fn init(&self, _sess: &Session) { #[cfg(feature = "master")] { - let target_cpu = target_cpu(sess); + let target_cpu = target_cpu(_sess); // Get the second TargetInfo with the correct CPU features by setting the arch. let context = Context::default(); From feb78f904e9e66e4fed9fe2e7e6363bb79d22be5 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 6 Feb 2025 20:08:29 +0000 Subject: [PATCH 033/606] Implement and use BikeshedGuaranteedNoDrop for union/unsafe field validity --- example/mini_core.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/example/mini_core.rs b/example/mini_core.rs index 5a4ee0a198ce..2ff1d757fd4e 100644 --- a/example/mini_core.rs +++ b/example/mini_core.rs @@ -54,6 +54,9 @@ impl LegacyReceiver for Box {} #[lang = "copy"] pub trait Copy {} +#[lang = "bikeshed_guaranteed_no_drop"] +pub trait BikeshedGuaranteedNoDrop {} + impl Copy for bool {} impl Copy for u8 {} impl Copy for u16 {} From 3ecc012f6f59419fbdfddd9bac3a4b21d2275078 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Wed, 12 Feb 2025 22:05:29 +0100 Subject: [PATCH 034/606] fix clobbered or lateout registers overlapping with input registers --- libgccjit.version | 2 +- src/asm.rs | 72 +++++++++++++++++++++++++------------- tests/failing-ui-tests.txt | 1 - tests/run/asm.rs | 31 ++++++++++++++++ 4 files changed, 79 insertions(+), 27 deletions(-) diff --git a/libgccjit.version b/libgccjit.version index 417fd5b03935..dfdc222c00fc 100644 --- a/libgccjit.version +++ b/libgccjit.version @@ -1 +1 @@ -e607be166673a8de9fc07f6f02c60426e556c5f2 +d6f5a708104a98199ac0f01a3b6b279a0f7c66d3 diff --git a/src/asm.rs b/src/asm.rs index 415f8affab90..9f4b84d22c08 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -36,7 +36,8 @@ use crate::type_of::LayoutGccExt; // // 3. Clobbers. GCC has a separate list of clobbers, and clobbers don't have indexes. // Contrary, Rust expresses clobbers through "out" operands that aren't tied to -// a variable (`_`), and such "clobbers" do have index. +// a variable (`_`), and such "clobbers" do have index. Input operands cannot also +// be clobbered. // // 4. Furthermore, GCC Extended Asm does not support explicit register constraints // (like `out("eax")`) directly, offering so-called "local register variables" @@ -161,6 +162,16 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { // Also, we don't emit any asm operands immediately; we save them to // the one of the buffers to be emitted later. + let mut input_registers = vec![]; + + for op in rust_operands { + if let InlineAsmOperandRef::In { reg, .. } = *op { + if let ConstraintOrRegister::Register(reg_name) = reg_to_gcc(reg) { + input_registers.push(reg_name); + } + } + } + // 1. Normal variables (and saving operands to buffers). for (rust_idx, op) in rust_operands.iter().enumerate() { match *op { @@ -183,25 +194,39 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { continue; } (Register(reg_name), None) => { - // `clobber_abi` can add lots of clobbers that are not supported by the target, - // such as AVX-512 registers, so we just ignore unsupported registers - let is_target_supported = - reg.reg_class().supported_types(asm_arch, true).iter().any( - |&(_, feature)| { - if let Some(feature) = feature { - self.tcx - .asm_target_features(instance.def_id()) - .contains(&feature) - } else { - true // Register class is unconditionally supported - } - }, - ); + if input_registers.contains(®_name) { + // the `clobber_abi` operand is converted into a series of + // `lateout("reg") _` operands. Of course, a user could also + // explicitly define such an output operand. + // + // GCC does not allow input registers to be clobbered, so if this out register + // is also used as an in register, do not add it to the clobbers list. + // it will be treated as a lateout register with `out_place: None` + if !late { + bug!("input registers can only be used as lateout regisers"); + } + ("r", dummy_output_type(self.cx, reg.reg_class())) + } else { + // `clobber_abi` can add lots of clobbers that are not supported by the target, + // such as AVX-512 registers, so we just ignore unsupported registers + let is_target_supported = + reg.reg_class().supported_types(asm_arch, true).iter().any( + |&(_, feature)| { + if let Some(feature) = feature { + self.tcx + .asm_target_features(instance.def_id()) + .contains(&feature) + } else { + true // Register class is unconditionally supported + } + }, + ); - if is_target_supported && !clobbers.contains(®_name) { - clobbers.push(reg_name); + if is_target_supported && !clobbers.contains(®_name) { + clobbers.push(reg_name); + } + continue; } - continue; } }; @@ -230,13 +255,10 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { } InlineAsmOperandRef::InOut { reg, late, in_value, out_place } => { - let constraint = - if let ConstraintOrRegister::Constraint(constraint) = reg_to_gcc(reg) { - constraint - } else { - // left for the next pass - continue; - }; + let ConstraintOrRegister::Constraint(constraint) = reg_to_gcc(reg) else { + // left for the next pass + continue; + }; // Rustc frontend guarantees that input and output types are "compatible", // so we can just use input var's type for the output variable. diff --git a/tests/failing-ui-tests.txt b/tests/failing-ui-tests.txt index 579ac3749e95..0babc748f98b 100644 --- a/tests/failing-ui-tests.txt +++ b/tests/failing-ui-tests.txt @@ -1,7 +1,6 @@ tests/ui/allocator/no_std-alloc-error-handler-custom.rs tests/ui/allocator/no_std-alloc-error-handler-default.rs tests/ui/asm/may_unwind.rs -tests/ui/asm/x86_64/multiple-clobber-abi.rs tests/ui/functions-closures/parallel-codegen-closures.rs tests/ui/linkage-attr/linkage1.rs tests/ui/lto/dylib-works.rs diff --git a/tests/run/asm.rs b/tests/run/asm.rs index 4e05d026868e..9ede19a061f3 100644 --- a/tests/run/asm.rs +++ b/tests/run/asm.rs @@ -174,6 +174,37 @@ fn asm() { mem_cpy(array2.as_mut_ptr(), array1.as_ptr(), 3); } assert_eq!(array1, array2); + + // in and clobber registers cannot overlap. This tests that the lateout register without an + // output place (indicated by the `_`) is not added to the list of clobbered registers + let x = 8; + let y: i32; + unsafe { + asm!( + "mov rax, rdi", + in("rdi") x, + lateout("rdi") _, + out("rax") y, + ); + } + assert_eq!((x, y), (8, 8)); + + // sysv64 is the default calling convention on unix systems. The rdi register is + // used to pass arguments in the sysv64 calling convention, so this register will be clobbered + #[cfg(unix)] + { + let x = 16; + let y: i32; + unsafe { + asm!( + "mov rax, rdi", + in("rdi") x, + out("rax") y, + clobber_abi("sysv64"), + ); + } + assert_eq!((x, y), (16, 16)); + } } #[cfg(not(target_arch = "x86_64"))] From fd526a248c05b846507291a6281c06e10c2d05f7 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Mon, 13 Jan 2025 15:52:08 +0000 Subject: [PATCH 035/606] Make `-O` mean `-C opt-level=3` --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index ce88ac390216..6455bcec6851 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -476,7 +476,7 @@ fn to_gcc_opt_level(optlevel: Option) -> OptimizationLevel { Some(level) => match level { OptLevel::No => OptimizationLevel::None, OptLevel::Less => OptimizationLevel::Limited, - OptLevel::Default => OptimizationLevel::Standard, + OptLevel::More => OptimizationLevel::Standard, OptLevel::Aggressive => OptimizationLevel::Aggressive, OptLevel::Size | OptLevel::SizeMin => OptimizationLevel::Limited, }, From 5e0c773e8000c56fa1c258b57b2b64e453a3f57a Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Wed, 5 Feb 2025 03:43:54 -0800 Subject: [PATCH 036/606] Set both `nuw` and `nsw` in slice size calculation There's an old note in the code to do this, and now that LLVM-C has an API for it, we might as well. --- src/builder.rs | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 1c3d6cc899a6..b8e37b604801 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -665,6 +665,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { a + b } + // TODO(antoyo): should we also override the `unchecked_` versions? fn sub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { self.gcc_sub(a, b) } @@ -832,31 +833,6 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { set_rvalue_location(self, self.gcc_not(a)) } - fn unchecked_sadd(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { - set_rvalue_location(self, self.gcc_add(a, b)) - } - - fn unchecked_uadd(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { - set_rvalue_location(self, self.gcc_add(a, b)) - } - - fn unchecked_ssub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { - set_rvalue_location(self, self.gcc_sub(a, b)) - } - - fn unchecked_usub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { - // TODO(antoyo): should generate poison value? - set_rvalue_location(self, self.gcc_sub(a, b)) - } - - fn unchecked_smul(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { - set_rvalue_location(self, self.gcc_mul(a, b)) - } - - fn unchecked_umul(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { - set_rvalue_location(self, self.gcc_mul(a, b)) - } - fn fadd_fast(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> { // NOTE: it seems like we cannot enable fast-mode for a single operation in GCC. set_rvalue_location(self, lhs + rhs) From 53aa977e4bd4f5d79303061c1a6b6dbeb8cbf51c Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Thu, 13 Feb 2025 19:44:42 +0100 Subject: [PATCH 037/606] refactor and support reg_byte registers --- src/asm.rs | 213 +++++++++++++++++++++++++---------------------- tests/run/asm.rs | 22 +++++ 2 files changed, 135 insertions(+), 100 deletions(-) diff --git a/src/asm.rs b/src/asm.rs index 9f4b84d22c08..dbdf37ee6c9e 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -611,114 +611,127 @@ fn estimate_template_length( } /// Converts a register class to a GCC constraint code. -fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister { - let constraint = match reg { - // For vector registers LLVM wants the register name to match the type size. +fn reg_to_gcc(reg_or_reg_class: InlineAsmRegOrRegClass) -> ConstraintOrRegister { + match reg_or_reg_class { InlineAsmRegOrRegClass::Reg(reg) => { - match reg { - InlineAsmReg::X86(_) => { - // TODO(antoyo): add support for vector register. - // - // // For explicit registers, we have to create a register variable: https://stackoverflow.com/a/31774784/389119 - return ConstraintOrRegister::Register(match reg.name() { - // Some of registers' names does not map 1-1 from rust to gcc - "st(0)" => "st", + ConstraintOrRegister::Register(explicit_reg_to_gcc(reg)) + } + InlineAsmRegOrRegClass::RegClass(reg_class) => { + ConstraintOrRegister::Constraint(reg_class_to_gcc(reg_class)) + } + } +} - name => name, - }); +fn explicit_reg_to_gcc(reg: InlineAsmReg) -> &'static str { + // For explicit registers, we have to create a register variable: https://stackoverflow.com/a/31774784/389119 + match reg { + InlineAsmReg::X86(reg) => { + // TODO(antoyo): add support for vector register. + match reg.reg_class() { + X86InlineAsmRegClass::reg_byte => { + // GCC does not support the `b` suffix, so we just strip it + // see https://github.com/rust-lang/rustc_codegen_gcc/issues/485 + reg.name().trim_end_matches('b') } + _ => match reg.name() { + // Some of registers' names does not map 1-1 from rust to gcc + "st(0)" => "st", - _ => unimplemented!(), + name => name, + }, } } - // They can be retrieved from https://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html - InlineAsmRegOrRegClass::RegClass(reg) => match reg { - InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::reg) => "r", - InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg) => "w", - InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => "x", - InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => { - unreachable!("clobber-only") - } - InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => "r", - InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg) - | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low16) - | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low8) - | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16) - | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low8) - | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low4) - | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg) - | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg) => "t", - InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg) => "r", - InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_upper) => "d", - InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_pair) => "r", - InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_iw) => "w", - InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_ptr) => "e", - InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => "r", - InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => "w", - InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => "r", - InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::preg) => { - unreachable!("clobber-only") - } - InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => "r", - InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => "f", - InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => "r", - InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_addr) => "a", - InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_data) => "d", - InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::reg) => "r", - InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::freg) => "f", - InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => "d", // more specific than "r" - InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => "f", - InlineAsmRegClass::Msp430(Msp430InlineAsmRegClass::reg) => "r", - // https://github.com/gcc-mirror/gcc/blob/master/gcc/config/nvptx/nvptx.md -> look for - // "define_constraint". - InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg16) => "h", - InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg32) => "r", - InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg64) => "l", - InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg) => "r", - InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => "b", - InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => "f", - InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::vreg) => "v", - InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr) - | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) => { - unreachable!("clobber-only") - } - InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => "r", - InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => "f", - InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => { - unreachable!("clobber-only") - } - InlineAsmRegClass::X86(X86InlineAsmRegClass::reg) => "r", - InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd) => "Q", - InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_byte) => "q", - InlineAsmRegClass::X86(X86InlineAsmRegClass::xmm_reg) - | InlineAsmRegClass::X86(X86InlineAsmRegClass::ymm_reg) => "x", - InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => "v", - InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => "Yk", - InlineAsmRegClass::X86( - X86InlineAsmRegClass::kreg0 - | X86InlineAsmRegClass::x87_reg - | X86InlineAsmRegClass::mmx_reg - | X86InlineAsmRegClass::tmm_reg, - ) => unreachable!("clobber-only"), - InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { - bug!("GCC backend does not support SPIR-V") - } - InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => "r", - InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => "r", - InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg_addr) => "a", - InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => "f", - InlineAsmRegClass::S390x(S390xInlineAsmRegClass::vreg) => "v", - InlineAsmRegClass::S390x(S390xInlineAsmRegClass::areg) => { - unreachable!("clobber-only") - } - InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg) => "r", - InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::yreg) => unreachable!("clobber-only"), - InlineAsmRegClass::Err => unreachable!(), - }, - }; + _ => unimplemented!(), + } +} - ConstraintOrRegister::Constraint(constraint) +/// They can be retrieved from https://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html +fn reg_class_to_gcc(reg_class: InlineAsmRegClass) -> &'static str { + match reg_class { + InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::reg) => "r", + InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg) => "w", + InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => "x", + InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => { + unreachable!("clobber-only") + } + InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg) + | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low16) + | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low8) + | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16) + | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low8) + | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low4) + | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg) + | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg) => "t", + InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_upper) => "d", + InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_pair) => "r", + InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_iw) => "w", + InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_ptr) => "e", + InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => "w", + InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::preg) => { + unreachable!("clobber-only") + } + InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => "f", + InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_addr) => "a", + InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_data) => "d", + InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::freg) => "f", + InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => "d", // more specific than "r" + InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => "f", + InlineAsmRegClass::Msp430(Msp430InlineAsmRegClass::reg) => "r", + // https://github.com/gcc-mirror/gcc/blob/master/gcc/config/nvptx/nvptx.md -> look for + // "define_constraint". + InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg16) => "h", + InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg32) => "r", + InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg64) => "l", + + InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => "b", + InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => "f", + InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::vreg) => "v", + InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr) + | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) => { + unreachable!("clobber-only") + } + InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => "f", + InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => { + unreachable!("clobber-only") + } + InlineAsmRegClass::X86(X86InlineAsmRegClass::reg) => "r", + InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd) => "Q", + InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_byte) => "q", + InlineAsmRegClass::X86(X86InlineAsmRegClass::xmm_reg) + | InlineAsmRegClass::X86(X86InlineAsmRegClass::ymm_reg) => "x", + InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => "v", + InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => "Yk", + InlineAsmRegClass::X86( + X86InlineAsmRegClass::kreg0 + | X86InlineAsmRegClass::x87_reg + | X86InlineAsmRegClass::mmx_reg + | X86InlineAsmRegClass::tmm_reg, + ) => unreachable!("clobber-only"), + InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { + bug!("GCC backend does not support SPIR-V") + } + InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => "r", + InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg_addr) => "a", + InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => "f", + InlineAsmRegClass::S390x(S390xInlineAsmRegClass::vreg) => "v", + InlineAsmRegClass::S390x(S390xInlineAsmRegClass::areg) => { + unreachable!("clobber-only") + } + InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::yreg) => unreachable!("clobber-only"), + InlineAsmRegClass::Err => unreachable!(), + } } /// Type to use for outputs that are discarded. It doesn't really matter what diff --git a/tests/run/asm.rs b/tests/run/asm.rs index 9ede19a061f3..2dbf43be664d 100644 --- a/tests/run/asm.rs +++ b/tests/run/asm.rs @@ -205,6 +205,28 @@ fn asm() { } assert_eq!((x, y), (16, 16)); } + + // the `b` suffix for registers in the `reg_byte` register class is not supported in GCC + // and needs to be stripped in order to use these registers. + unsafe { + core::arch::asm!( + "", + out("al") _, + out("bl") _, + out("cl") _, + out("dl") _, + out("sil") _, + out("dil") _, + out("r8b") _, + out("r9b") _, + out("r10b") _, + out("r11b") _, + out("r12b") _, + out("r13b") _, + out("r14b") _, + out("r15b") _, + ); + } } #[cfg(not(target_arch = "x86_64"))] From 51911a745de6fab88f7eb75b2b8bea9787c5a153 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Fri, 14 Feb 2025 20:25:43 -0800 Subject: [PATCH 038/606] Emit `trunc nuw` for unchecked shifts and `to_immediate_scalar` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - For shifts this shrinks the IR by no longer needing an `assume` while still providing the UB information - Having this on the `i8`→`i1` truncations will hopefully help with some places that have to load `i8`s or pass those in LLVM structs without range information --- src/builder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/builder.rs b/src/builder.rs index b8e37b604801..76846692459d 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -1694,7 +1694,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { fn to_immediate_scalar(&mut self, val: Self::Value, scalar: abi::Scalar) -> Self::Value { if scalar.is_bool() { - return self.trunc(val, self.cx().type_i1()); + return self.unchecked_utrunc(val, self.cx().type_i1()); } val } From 9ebb68ddda0247df044241daaf4856144c9c0998 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 15 Feb 2025 16:07:18 -0800 Subject: [PATCH 039/606] Rework `OperandRef::extract_field` to stop calling `to_immediate_scalar` on things which are already immediates That means it stops trying to truncate things that are already `i1`s. --- src/builder.rs | 12 ++++++++---- src/intrinsic/mod.rs | 11 ++++++++--- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 76846692459d..c8b7616e6450 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -989,10 +989,14 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { OperandValue::Ref(place.val) } else if place.layout.is_gcc_immediate() { let load = self.load(place.layout.gcc_type(self), place.val.llval, place.val.align); - if let abi::BackendRepr::Scalar(ref scalar) = place.layout.backend_repr { - scalar_load_metadata(self, load, scalar); - } - OperandValue::Immediate(self.to_immediate(load, place.layout)) + OperandValue::Immediate( + if let abi::BackendRepr::Scalar(ref scalar) = place.layout.backend_repr { + scalar_load_metadata(self, load, scalar); + self.to_immediate_scalar(load, *scalar) + } else { + load + }, + ) } else if let abi::BackendRepr::ScalarPair(ref a, ref b) = place.layout.backend_repr { let b_offset = a.size(self).align_to(b.align(self).abi); diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index a1123fafe2f3..5322b731d8bb 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -9,7 +9,7 @@ use gccjit::FunctionType; use gccjit::{ComparisonOp, Function, RValue, ToRValue, Type, UnaryOp}; #[cfg(feature = "master")] use rustc_abi::ExternAbi; -use rustc_abi::HasDataLayout; +use rustc_abi::{BackendRepr, HasDataLayout}; use rustc_codegen_ssa::MemFlags; use rustc_codegen_ssa::base::wants_msvc_seh; use rustc_codegen_ssa::common::IntPredicate; @@ -181,14 +181,19 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc sym::volatile_load | sym::unaligned_volatile_load => { let tp_ty = fn_args.type_at(0); let ptr = args[0].immediate(); + let layout = self.layout_of(tp_ty); let load = if let PassMode::Cast { cast: ref ty, pad_i32: _ } = fn_abi.ret.mode { let gcc_ty = ty.gcc_type(self); self.volatile_load(gcc_ty, ptr) } else { - self.volatile_load(self.layout_of(tp_ty).gcc_type(self), ptr) + self.volatile_load(layout.gcc_type(self), ptr) }; // TODO(antoyo): set alignment. - self.to_immediate(load, self.layout_of(tp_ty)) + if let BackendRepr::Scalar(scalar) = layout.backend_repr { + self.to_immediate_scalar(load, scalar) + } else { + load + } } sym::volatile_store => { let dst = args[0].deref(self.cx()); From be635722bd4264f0fd0de4cccb9ca4f9f74fafd9 Mon Sep 17 00:00:00 2001 From: Zachary S Date: Sat, 25 Jan 2025 20:15:24 -0600 Subject: [PATCH 040/606] Remove `BackendRepr::Uninhabited`, replaced with an `uninhabited: bool` field in `LayoutData`. Also update comments that refered to BackendRepr::Uninhabited. --- src/intrinsic/mod.rs | 2 +- src/type_of.rs | 13 +++++-------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 5322b731d8bb..433868e238a4 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -315,7 +315,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc let layout = self.layout_of(tp_ty).layout; let _use_integer_compare = match layout.backend_repr() { Scalar(_) | ScalarPair(_, _) => true, - Uninhabited | Vector { .. } => false, + Vector { .. } => false, Memory { .. } => { // For rusty ABIs, small aggregates are actually passed // as `RegKind::Integer` (see `FnAbi::adjust_for_abi`), diff --git a/src/type_of.rs b/src/type_of.rs index 8b8b54753e7f..bac4fc51300a 100644 --- a/src/type_of.rs +++ b/src/type_of.rs @@ -84,7 +84,7 @@ fn uncached_gcc_type<'gcc, 'tcx>( false, ); } - BackendRepr::Uninhabited | BackendRepr::Memory { .. } => {} + BackendRepr::Memory { .. } => {} } let name = match *layout.ty.kind() { @@ -179,19 +179,16 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { fn is_gcc_immediate(&self) -> bool { match self.backend_repr { BackendRepr::Scalar(_) | BackendRepr::Vector { .. } => true, - BackendRepr::ScalarPair(..) | BackendRepr::Uninhabited | BackendRepr::Memory { .. } => { - false - } + BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => false, } } fn is_gcc_scalar_pair(&self) -> bool { match self.backend_repr { BackendRepr::ScalarPair(..) => true, - BackendRepr::Uninhabited - | BackendRepr::Scalar(_) - | BackendRepr::Vector { .. } - | BackendRepr::Memory { .. } => false, + BackendRepr::Scalar(_) | BackendRepr::Vector { .. } | BackendRepr::Memory { .. } => { + false + } } } From aa038c2d95bb041a170cb1bbea8ef0fd2fd14ca4 Mon Sep 17 00:00:00 2001 From: DianQK Date: Thu, 6 Feb 2025 21:59:36 +0800 Subject: [PATCH 041/606] Add `new_regular` and `new_allocator` to `ModuleCodegen` --- src/back/lto.rs | 9 ++++----- src/base.rs | 11 +++++------ 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/back/lto.rs b/src/back/lto.rs index cb4caec8c326..e5221c7da319 100644 --- a/src/back/lto.rs +++ b/src/back/lto.rs @@ -632,17 +632,16 @@ pub unsafe fn optimize_thin_module( Arc::new(SyncContext::new(context)) } }; - let module = ModuleCodegen { - module_llvm: GccContext { + let module = ModuleCodegen::new_regular( + thin_module.name().to_string(), + GccContext { context, should_combine_object_files, // TODO(antoyo): use the correct relocation model here. relocation_model: RelocModel::Pic, temp_dir: None, }, - name: thin_module.name().to_string(), - kind: ModuleKind::Regular, - }; + ); /*{ let target = &*module.module_llvm.tm; let llmod = module.module_llvm.llmod(); diff --git a/src/base.rs b/src/base.rs index 962f4b161d78..9b495174a3fa 100644 --- a/src/base.rs +++ b/src/base.rs @@ -4,10 +4,10 @@ use std::sync::Arc; use std::time::Instant; use gccjit::{CType, Context, FunctionType, GlobalKind}; +use rustc_codegen_ssa::ModuleCodegen; use rustc_codegen_ssa::base::maybe_create_entry_wrapper; use rustc_codegen_ssa::mono_item::MonoItemExt; use rustc_codegen_ssa::traits::DebugInfoCodegenMethods; -use rustc_codegen_ssa::{ModuleCodegen, ModuleKind}; use rustc_middle::dep_graph; use rustc_middle::mir::mono::Linkage; #[cfg(feature = "master")] @@ -237,16 +237,15 @@ pub fn compile_codegen_unit( } } - ModuleCodegen { - name: cgu_name.to_string(), - module_llvm: GccContext { + ModuleCodegen::new_regular( + cgu_name.to_string(), + GccContext { context: Arc::new(SyncContext::new(context)), relocation_model: tcx.sess.relocation_model(), should_combine_object_files: false, temp_dir: None, }, - kind: ModuleKind::Regular, - } + ) } (module, cost) From 9b8701d27ebc49b2ade98d910b411d6f0a57a0ac Mon Sep 17 00:00:00 2001 From: DianQK Date: Thu, 6 Feb 2025 22:00:19 +0800 Subject: [PATCH 042/606] Save pre-link bitcode to `ModuleCodegen` --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 6455bcec6851..9d91aab72ab3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -393,7 +393,7 @@ impl WriteBackendMethods for GccCodegenBackend { unsafe fn optimize( _cgcx: &CodegenContext, _dcx: DiagCtxtHandle<'_>, - module: &ModuleCodegen, + module: &mut ModuleCodegen, config: &ModuleConfig, ) -> Result<(), FatalError> { module.module_llvm.context.set_optimization_level(to_gcc_opt_level(config.opt_level)); From 15f0dca5317ac3cac7be8f509761fa6248fad0c0 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 23 Feb 2025 17:34:50 +0100 Subject: [PATCH 043/606] remove support for rustc_intrinsic_must_be_overridden from the compiler --- example/mini_core.rs | 65 +++++++++-------------------------------- tests/run/abort1.rs | 5 +--- tests/run/abort2.rs | 5 +--- tests/run/assign.rs | 5 +--- tests/run/mut_ref.rs | 5 +--- tests/run/operations.rs | 5 +--- tests/run/static.rs | 5 +--- 7 files changed, 19 insertions(+), 76 deletions(-) diff --git a/example/mini_core.rs b/example/mini_core.rs index 2ff1d757fd4e..3dad35bc4ce4 100644 --- a/example/mini_core.rs +++ b/example/mini_core.rs @@ -591,70 +591,31 @@ pub union MaybeUninit { pub mod intrinsics { #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn abort() -> ! { - loop {} - } + pub fn abort() -> !; #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn size_of() -> usize { - loop {} - } + pub fn size_of() -> usize; #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub unsafe fn size_of_val(_val: *const T) -> usize { - loop {} - } + pub unsafe fn size_of_val(_val: *const T) -> usize; #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn min_align_of() -> usize { - loop {} - } + pub fn min_align_of() -> usize; #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub unsafe fn min_align_of_val(_val: *const T) -> usize { - loop {} - } + pub unsafe fn min_align_of_val(_val: *const T) -> usize; #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub unsafe fn copy(_src: *const T, _dst: *mut T, _count: usize) { - loop {} - } + pub unsafe fn copy(_src: *const T, _dst: *mut T, _count: usize); #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub unsafe fn transmute(_e: T) -> U { - loop {} - } + pub unsafe fn transmute(_e: T) -> U; #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub unsafe fn ctlz_nonzero(_x: T) -> u32 { - loop {} - } + pub unsafe fn ctlz_nonzero(_x: T) -> u32; #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn needs_drop() -> bool { - loop {} - } + pub fn needs_drop() -> bool; #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn bitreverse(_x: T) -> T { - loop {} - } + pub fn bitreverse(_x: T) -> T; #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn bswap(_x: T) -> T { - loop {} - } + pub fn bswap(_x: T) -> T; #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub unsafe fn write_bytes(_dst: *mut T, _val: u8, _count: usize) { - loop {} - } + pub unsafe fn write_bytes(_dst: *mut T, _val: u8, _count: usize); #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub unsafe fn unreachable() -> ! { - loop {} - } + pub unsafe fn unreachable() -> !; } pub mod libc { diff --git a/tests/run/abort1.rs b/tests/run/abort1.rs index 385e41a68817..fe46d9ae4184 100644 --- a/tests/run/abort1.rs +++ b/tests/run/abort1.rs @@ -36,10 +36,7 @@ mod intrinsics { #[rustc_nounwind] #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn abort() -> ! { - loop {} - } + pub fn abort() -> !; } /* diff --git a/tests/run/abort2.rs b/tests/run/abort2.rs index 6c66a930e074..4123f4f4beeb 100644 --- a/tests/run/abort2.rs +++ b/tests/run/abort2.rs @@ -36,10 +36,7 @@ mod intrinsics { #[rustc_nounwind] #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn abort() -> ! { - loop {} - } + pub fn abort() -> !; } /* diff --git a/tests/run/assign.rs b/tests/run/assign.rs index 4d414c577a65..286155852d50 100644 --- a/tests/run/assign.rs +++ b/tests/run/assign.rs @@ -59,10 +59,7 @@ mod libc { mod intrinsics { #[rustc_nounwind] #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn abort() -> ! { - loop {} - } + pub fn abort() -> !; } #[lang = "panic"] diff --git a/tests/run/mut_ref.rs b/tests/run/mut_ref.rs index 9be64f991ee0..b0215860406e 100644 --- a/tests/run/mut_ref.rs +++ b/tests/run/mut_ref.rs @@ -61,10 +61,7 @@ mod libc { mod intrinsics { #[rustc_nounwind] #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn abort() -> ! { - loop {} - } + pub fn abort() -> !; } #[lang = "panic"] diff --git a/tests/run/operations.rs b/tests/run/operations.rs index c92d3cc0b8fb..8ba7a4c5ed8c 100644 --- a/tests/run/operations.rs +++ b/tests/run/operations.rs @@ -67,10 +67,7 @@ mod libc { mod intrinsics { #[rustc_nounwind] #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn abort() -> ! { - loop {} - } + pub fn abort() -> !; } #[lang = "panic"] diff --git a/tests/run/static.rs b/tests/run/static.rs index 80c8782c4b1a..c3c8121b1e19 100644 --- a/tests/run/static.rs +++ b/tests/run/static.rs @@ -49,10 +49,7 @@ mod intrinsics { #[rustc_nounwind] #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn abort() -> ! { - loop {} - } + pub fn abort() -> !; } mod libc { From e92466e22a6f98f7be019a6709b8f120cc5981a3 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 24 Feb 2025 08:07:11 +0000 Subject: [PATCH 044/606] Remove an unnecessary lifetime --- src/common.rs | 4 ++-- src/consts.rs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/common.rs b/src/common.rs index 20a3482aaa27..0ee13498ccad 100644 --- a/src/common.rs +++ b/src/common.rs @@ -59,7 +59,7 @@ pub fn type_is_pointer(typ: Type<'_>) -> bool { typ.get_pointee().is_some() } -impl<'gcc, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { +impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> { fn const_null(&self, typ: Type<'gcc>) -> RValue<'gcc> { if type_is_pointer(typ) { self.context.new_null(typ) } else { self.const_int(typ, 0) } } @@ -263,7 +263,7 @@ impl<'gcc, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { } } - fn const_data_from_alloc(&self, alloc: ConstAllocation<'tcx>) -> Self::Value { + fn const_data_from_alloc(&self, alloc: ConstAllocation<'_>) -> Self::Value { const_alloc_to_gcc(self, alloc) } diff --git a/src/consts.rs b/src/consts.rs index fb0ca31c5433..c514b7a428bc 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -302,9 +302,9 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { } } -pub fn const_alloc_to_gcc<'gcc, 'tcx>( - cx: &CodegenCx<'gcc, 'tcx>, - alloc: ConstAllocation<'tcx>, +pub fn const_alloc_to_gcc<'gcc>( + cx: &CodegenCx<'gcc, '_>, + alloc: ConstAllocation<'_>, ) -> RValue<'gcc> { let alloc = alloc.inner(); let mut llvals = Vec::with_capacity(alloc.provenance().ptrs().len() + 1); From 71c189a2effd3ea4e8d4653b938c9d90cdb78845 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 24 Feb 2025 11:31:43 +0000 Subject: [PATCH 045/606] Generalize BaseTypeCodegenMethods --- src/type_.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/type_.rs b/src/type_.rs index cb08723431a9..4e0a250b5509 100644 --- a/src/type_.rs +++ b/src/type_.rs @@ -123,7 +123,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { } } -impl<'gcc, 'tcx> BaseTypeCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { +impl<'gcc, 'tcx> BaseTypeCodegenMethods for CodegenCx<'gcc, 'tcx> { fn type_i8(&self) -> Type<'gcc> { self.i8_type } From 334eb82117cddee4813e860e54d1aa9db91da461 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 24 Feb 2025 12:23:45 +0000 Subject: [PATCH 046/606] Remove an unused lifetime param --- src/abi.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/abi.rs b/src/abi.rs index 717baebcd8cd..9fe6baa3d257 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -16,7 +16,7 @@ use crate::context::CodegenCx; use crate::intrinsic::ArgAbiExt; use crate::type_of::LayoutGccExt; -impl<'a, 'gcc, 'tcx> AbiBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { +impl AbiBuilderMethods for Builder<'_, '_, '_> { fn get_param(&mut self, index: usize) -> Self::Value { let func = self.current_func(); let param = func.get_param(index as i32); From 78481458d172e0a85dc56a08f315d7fc6c1757cc Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Tue, 25 Feb 2025 09:20:10 +0100 Subject: [PATCH 047/606] remove `simd_fpow` and `simd_fpowi` --- src/intrinsic/simd.rs | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/src/intrinsic/simd.rs b/src/intrinsic/simd.rs index 84cd5b002fbb..8b454ab2a424 100644 --- a/src/intrinsic/simd.rs +++ b/src/intrinsic/simd.rs @@ -772,8 +772,6 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( sym::simd_floor => "floor", sym::simd_fma => "fma", sym::simd_relaxed_fma => "fma", // FIXME: this should relax to non-fused multiply-add when necessary - sym::simd_fpowi => "__builtin_powi", - sym::simd_fpow => "pow", sym::simd_fsin => "sin", sym::simd_fsqrt => "sqrt", sym::simd_round => "round", @@ -788,24 +786,16 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( let mut vector_elements = vec![]; for i in 0..in_len { let index = bx.context.new_rvalue_from_long(bx.ulong_type, i as i64); - // we have to treat fpowi specially, since fpowi's second argument is always an i32 let mut arguments = vec![]; - if name == sym::simd_fpowi { - arguments = vec![ - bx.extract_element(args[0].immediate(), index).to_rvalue(), - args[1].immediate(), - ]; - } else { - for arg in args { - let mut element = bx.extract_element(arg.immediate(), index).to_rvalue(); - // FIXME: it would probably be better to not have casts here and use the proper - // instructions. - if let Some(typ) = cast_type { - element = bx.context.new_cast(None, element, typ); - } - arguments.push(element); + for arg in args { + let mut element = bx.extract_element(arg.immediate(), index).to_rvalue(); + // FIXME: it would probably be better to not have casts here and use the proper + // instructions. + if let Some(typ) = cast_type { + element = bx.context.new_cast(None, element, typ); } - }; + arguments.push(element); + } let mut result = bx.context.new_call(None, function, &arguments); if cast_type.is_some() { result = bx.context.new_cast(None, result, elem_ty); @@ -829,8 +819,6 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( | sym::simd_floor | sym::simd_fma | sym::simd_relaxed_fma - | sym::simd_fpow - | sym::simd_fpowi | sym::simd_fsin | sym::simd_fsqrt | sym::simd_round From 7721431d57f7c8eea818d39d7a284459bb15f6e3 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Thu, 27 Feb 2025 09:09:52 -0800 Subject: [PATCH 048/606] Stop using `hash_raw_entry` in `CodegenCx::const_str` That unstable feature completed fcp-close, so the compiler needs to be migrated away to allow its removal. In this case, `cg_llvm` and `cg_gcc` were using raw entries to optimize their `const_str_cache` lookup and insertion. We can change that to separate `get` and (on miss) `insert` calls, so we still have the fast path avoiding string allocation when the cache hits. --- src/common.rs | 13 ++++++------- src/lib.rs | 2 +- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/common.rs b/src/common.rs index 20a3482aaa27..ce1a20088647 100644 --- a/src/common.rs +++ b/src/common.rs @@ -146,13 +146,12 @@ impl<'gcc, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { } fn const_str(&self, s: &str) -> (RValue<'gcc>, RValue<'gcc>) { - let str_global = *self - .const_str_cache - .borrow_mut() - .raw_entry_mut() - .from_key(s) - .or_insert_with(|| (s.to_owned(), self.global_string(s))) - .1; + let mut const_str_cache = self.const_str_cache.borrow_mut(); + let str_global = const_str_cache.get(s).copied().unwrap_or_else(|| { + let g = self.global_string(s); + const_str_cache.insert(s.to_owned(), g); + g + }); let len = s.len(); let cs = self.const_ptrcast( str_global.get_address(None), diff --git a/src/lib.rs b/src/lib.rs index 6455bcec6851..741386876790 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,7 +16,7 @@ #![allow(internal_features)] #![doc(rust_logo)] #![feature(rustdoc_internals)] -#![feature(rustc_private, decl_macro, never_type, trusted_len, hash_raw_entry, let_chains)] +#![feature(rustc_private, decl_macro, never_type, trusted_len, let_chains)] #![allow(broken_intra_doc_links)] #![recursion_limit = "256"] #![warn(rust_2018_idioms)] From 975dee20ef70423c00a617867fa78e7ae9f63fce Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 28 Feb 2025 16:29:07 +0100 Subject: [PATCH 049/606] =?UTF-8?q?rename=20BackendRepr::Vector=20?= =?UTF-8?q?=E2=86=92=20SimdVector?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/intrinsic/mod.rs | 2 +- src/type_of.rs | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index f8672c072999..f38622074f18 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -312,7 +312,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc let layout = self.layout_of(tp_ty).layout; let _use_integer_compare = match layout.backend_repr() { Scalar(_) | ScalarPair(_, _) => true, - Vector { .. } => false, + SimdVector { .. } => false, Memory { .. } => { // For rusty ABIs, small aggregates are actually passed // as `RegKind::Integer` (see `FnAbi::adjust_for_abi`), diff --git a/src/type_of.rs b/src/type_of.rs index bac4fc51300a..ae98b3d0b56e 100644 --- a/src/type_of.rs +++ b/src/type_of.rs @@ -63,7 +63,7 @@ fn uncached_gcc_type<'gcc, 'tcx>( ) -> Type<'gcc> { match layout.backend_repr { BackendRepr::Scalar(_) => bug!("handled elsewhere"), - BackendRepr::Vector { ref element, count } => { + BackendRepr::SimdVector { ref element, count } => { let element = layout.scalar_gcc_type_at(cx, element, Size::ZERO); let element = // NOTE: gcc doesn't allow pointer types in vectors. @@ -178,7 +178,7 @@ pub trait LayoutGccExt<'tcx> { impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { fn is_gcc_immediate(&self) -> bool { match self.backend_repr { - BackendRepr::Scalar(_) | BackendRepr::Vector { .. } => true, + BackendRepr::Scalar(_) | BackendRepr::SimdVector { .. } => true, BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => false, } } @@ -186,9 +186,9 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { fn is_gcc_scalar_pair(&self) -> bool { match self.backend_repr { BackendRepr::ScalarPair(..) => true, - BackendRepr::Scalar(_) | BackendRepr::Vector { .. } | BackendRepr::Memory { .. } => { - false - } + BackendRepr::Scalar(_) + | BackendRepr::SimdVector { .. } + | BackendRepr::Memory { .. } => false, } } From 80046158ba9a2bd6900529251ac6a87a07f4030c Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Fri, 28 Feb 2025 19:55:42 -0800 Subject: [PATCH 050/606] Use `BinOp::Cmp` for `iNN::signum` This way it can use the nice new LLVM intrinsic in LLVM20. --- library/core/src/intrinsics/mod.rs | 10 ++++++---- library/core/src/num/int_macros.rs | 5 +---- ..._way_compare_char.LowerIntrinsics.panic-unwind.diff | 2 +- ...ay_compare_signed.LowerIntrinsics.panic-unwind.diff | 2 +- ..._compare_unsigned.LowerIntrinsics.panic-unwind.diff | 2 +- 5 files changed, 10 insertions(+), 11 deletions(-) diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 38a60338e74e..81087c5417a0 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -2528,13 +2528,15 @@ pub const fn bswap(_x: T) -> T; #[rustc_intrinsic] pub const fn bitreverse(_x: T) -> T; -/// Does a three-way comparison between the two integer arguments. +/// Does a three-way comparison between the two arguments, +/// which must be of character or integer (signed or unsigned) type. /// -/// This is included as an intrinsic as it's useful to let it be one thing -/// in MIR, rather than the multiple checks and switches that make its IR -/// large and difficult to optimize. +/// This was originally added because it greatly simplified the MIR in `cmp` +/// implementations, and then LLVM 20 added a backend intrinsic for it too. /// /// The stabilized version of this intrinsic is [`Ord::cmp`]. +#[rustc_intrinsic_const_stable_indirect] +#[rustc_nounwind] #[rustc_intrinsic] pub const fn three_way_compare(_lhs: T, _rhss: T) -> crate::cmp::Ordering; diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 7d99aaa17314..273db46e4b45 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -3571,10 +3571,7 @@ macro_rules! int_impl { // so delegate it to `Ord` which is already producing -1/0/+1 // exactly like we need and can be the place to deal with the complexity. - // FIXME(const-hack): replace with cmp - if self < 0 { -1 } - else if self == 0 { 0 } - else { 1 } + crate::intrinsics::three_way_compare(self, 0) as Self } /// Returns `true` if `self` is positive and `false` if the number is zero or diff --git a/tests/mir-opt/lower_intrinsics.three_way_compare_char.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.three_way_compare_char.LowerIntrinsics.panic-unwind.diff index 596ad70b3bfa..f29bc5dfc6e4 100644 --- a/tests/mir-opt/lower_intrinsics.three_way_compare_char.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.three_way_compare_char.LowerIntrinsics.panic-unwind.diff @@ -18,7 +18,7 @@ _4 = copy _1; StorageLive(_5); _5 = copy _2; -- _3 = three_way_compare::(move _4, move _5) -> [return: bb1, unwind continue]; +- _3 = three_way_compare::(move _4, move _5) -> [return: bb1, unwind unreachable]; + _3 = Cmp(move _4, move _5); + goto -> bb1; } diff --git a/tests/mir-opt/lower_intrinsics.three_way_compare_signed.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.three_way_compare_signed.LowerIntrinsics.panic-unwind.diff index 987c21666927..654cb2503df5 100644 --- a/tests/mir-opt/lower_intrinsics.three_way_compare_signed.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.three_way_compare_signed.LowerIntrinsics.panic-unwind.diff @@ -15,7 +15,7 @@ _4 = copy _1; StorageLive(_5); _5 = copy _2; -- _3 = three_way_compare::(move _4, move _5) -> [return: bb1, unwind continue]; +- _3 = three_way_compare::(move _4, move _5) -> [return: bb1, unwind unreachable]; + _3 = Cmp(move _4, move _5); + goto -> bb1; } diff --git a/tests/mir-opt/lower_intrinsics.three_way_compare_unsigned.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.three_way_compare_unsigned.LowerIntrinsics.panic-unwind.diff index d7ec6dcfa2c3..82c89b7ce549 100644 --- a/tests/mir-opt/lower_intrinsics.three_way_compare_unsigned.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.three_way_compare_unsigned.LowerIntrinsics.panic-unwind.diff @@ -18,7 +18,7 @@ _4 = copy _1; StorageLive(_5); _5 = copy _2; -- _3 = three_way_compare::(move _4, move _5) -> [return: bb1, unwind continue]; +- _3 = three_way_compare::(move _4, move _5) -> [return: bb1, unwind unreachable]; + _3 = Cmp(move _4, move _5); + goto -> bb1; } From c25f12a667cd83fb79e6f7098e3191f9b1ab6416 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 2 Mar 2025 18:41:28 +0000 Subject: [PATCH 051/606] Revert "Auto merge of #135335 - oli-obk:push-zxwssomxxtnq, r=saethlin" This reverts commit a7a6c64a657f68113301c2ffe0745b49a16442d1, reversing changes made to ebbe63891f1fae21734cb97f2f863b08b1d44bf8. --- src/common.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/common.rs b/src/common.rs index 20a3482aaa27..2052a6aa2159 100644 --- a/src/common.rs +++ b/src/common.rs @@ -64,11 +64,6 @@ impl<'gcc, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { if type_is_pointer(typ) { self.context.new_null(typ) } else { self.const_int(typ, 0) } } - fn is_undef(&self, _val: RValue<'gcc>) -> bool { - // FIXME: actually check for undef - false - } - fn const_undef(&self, typ: Type<'gcc>) -> RValue<'gcc> { let local = self.current_func.borrow().expect("func").new_local(None, typ, "undefined"); if typ.is_struct().is_some() { From ae07d7d368f3487999e68c5c2aa00a9ba2539905 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 25 Feb 2025 14:13:16 +1100 Subject: [PATCH 052/606] Simplify `implied_target_features`. Currently its argument is an iterator, but in practice it's always a singleton. --- src/gcc_util.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gcc_util.rs b/src/gcc_util.rs index 4e8c8aaaf5c8..6eae0c24f48a 100644 --- a/src/gcc_util.rs +++ b/src/gcc_util.rs @@ -48,7 +48,7 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec Date: Tue, 25 Feb 2025 15:25:54 +1100 Subject: [PATCH 053/606] Change signature of `target_features_cfg`. Currently it is called twice, once with `allow_unstable` set to true and once with it set to false. This results in some duplicated work. Most notably, for the LLVM backend, `LLVMRustHasFeature` is called twice for every feature, and it's moderately slow. For very short running compilations on platforms with many features (e.g. a `check` build of hello-world on x86) this is a significant fraction of runtime. This commit changes `target_features_cfg` so it is only called once, and it now returns a pair of feature sets. This halves the number of `LLVMRustHasFeature` calls. --- src/lib.rs | 68 +++++++++++++++++++++++++++++------------------------- 1 file changed, 37 insertions(+), 31 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index f090597f9533..d478b2af46c2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -259,8 +259,8 @@ impl CodegenBackend for GccCodegenBackend { .join(sess) } - fn target_features_cfg(&self, sess: &Session, allow_unstable: bool) -> Vec { - target_features_cfg(sess, allow_unstable, &self.target_info) + fn target_features_cfg(&self, sess: &Session) -> (Vec, Vec) { + target_features_cfg(sess, &self.target_info) } } @@ -486,35 +486,41 @@ fn to_gcc_opt_level(optlevel: Option) -> OptimizationLevel { /// Returns the features that should be set in `cfg(target_feature)`. fn target_features_cfg( sess: &Session, - allow_unstable: bool, target_info: &LockedTargetInfo, -) -> Vec { +) -> (Vec, Vec) { // TODO(antoyo): use global_gcc_features. - sess.target - .rust_target_features() - .iter() - .filter_map(|&(feature, gate, _)| { - if allow_unstable - || (gate.in_cfg() && (sess.is_nightly_build() || gate.requires_nightly().is_none())) - { - Some(feature) - } else { - None - } - }) - .filter(|feature| { - // TODO: we disable Neon for now since we don't support the LLVM intrinsics for it. - if *feature == "neon" { - return false; - } - target_info.cpu_supports(feature) - /* - adx, aes, avx, avx2, avx512bf16, avx512bitalg, avx512bw, avx512cd, avx512dq, avx512er, avx512f, avx512fp16, avx512ifma, - avx512pf, avx512vbmi, avx512vbmi2, avx512vl, avx512vnni, avx512vp2intersect, avx512vpopcntdq, - bmi1, bmi2, cmpxchg16b, ermsb, f16c, fma, fxsr, gfni, lzcnt, movbe, pclmulqdq, popcnt, rdrand, rdseed, rtm, - sha, sse, sse2, sse3, sse4.1, sse4.2, sse4a, ssse3, tbm, vaes, vpclmulqdq, xsave, xsavec, xsaveopt, xsaves - */ - }) - .map(Symbol::intern) - .collect() + let f = |allow_unstable| { + sess.target + .rust_target_features() + .iter() + .filter_map(|&(feature, gate, _)| { + if allow_unstable + || (gate.in_cfg() + && (sess.is_nightly_build() || gate.requires_nightly().is_none())) + { + Some(feature) + } else { + None + } + }) + .filter(|feature| { + // TODO: we disable Neon for now since we don't support the LLVM intrinsics for it. + if *feature == "neon" { + return false; + } + target_info.cpu_supports(feature) + /* + adx, aes, avx, avx2, avx512bf16, avx512bitalg, avx512bw, avx512cd, avx512dq, avx512er, avx512f, avx512fp16, avx512ifma, + avx512pf, avx512vbmi, avx512vbmi2, avx512vl, avx512vnni, avx512vp2intersect, avx512vpopcntdq, + bmi1, bmi2, cmpxchg16b, ermsb, f16c, fma, fxsr, gfni, lzcnt, movbe, pclmulqdq, popcnt, rdrand, rdseed, rtm, + sha, sse, sse2, sse3, sse4.1, sse4.2, sse4a, ssse3, tbm, vaes, vpclmulqdq, xsave, xsavec, xsaveopt, xsaves + */ + }) + .map(Symbol::intern) + .collect() + }; + + let target_features = f(false); + let unstable_target_features = f(true); + (target_features, unstable_target_features) } From a11fbeec1fc0ad1b8c8814dd2fa4704c4d5e8e0e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 7 Mar 2025 17:09:12 +0100 Subject: [PATCH 054/606] Small code improvement in rustdoc hidden stripper --- src/librustdoc/passes/strip_hidden.rs | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs index bcdca862862d..692ce21d6cfb 100644 --- a/src/librustdoc/passes/strip_hidden.rs +++ b/src/librustdoc/passes/strip_hidden.rs @@ -91,19 +91,21 @@ impl DocFolder for Stripper<'_, '_> { if let clean::ImportItem(clean::Import { source, .. }) = &i.kind && let Some(source_did) = source.did - && let Some(import_def_id) = i.def_id().and_then(|def_id| def_id.as_local()) { - let reexports = reexport_chain(self.tcx, import_def_id, source_did); - - // Check if any reexport in the chain has a hidden source - let has_hidden_source = reexports - .iter() - .filter_map(|reexport| reexport.id()) - .any(|reexport_did| self.tcx.is_doc_hidden(reexport_did)) - || self.tcx.is_doc_hidden(source_did); - - if has_hidden_source { + if self.tcx.is_doc_hidden(source_did) { return None; + } else if let Some(import_def_id) = i.def_id().and_then(|def_id| def_id.as_local()) { + let reexports = reexport_chain(self.tcx, import_def_id, source_did); + + // Check if any reexport in the chain has a hidden source + let has_hidden_source = reexports + .iter() + .filter_map(|reexport| reexport.id()) + .any(|reexport_did| self.tcx.is_doc_hidden(reexport_did)); + + if has_hidden_source { + return None; + } } } From 70b588882781ff091a0bff927f8ff74c0d234798 Mon Sep 17 00:00:00 2001 From: Thalia Archibald Date: Tue, 4 Mar 2025 20:28:38 -0800 Subject: [PATCH 055/606] compiler: Use size_of from the prelude instead of imported Use `std::mem::{size_of, size_of_val, align_of, align_of_val}` from the prelude instead of importing or qualifying them. These functions were added to all preludes in Rust 1.80. --- src/builder.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index c8b7616e6450..6573b5b165e6 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -2439,9 +2439,5 @@ fn get_maybe_pointer_size(value: RValue<'_>) -> u32 { #[cfg(not(feature = "master"))] fn get_maybe_pointer_size(value: RValue<'_>) -> u32 { let type_ = value.get_type(); - if type_.get_pointee().is_some() { - std::mem::size_of::<*const ()>() as _ - } else { - type_.get_size() - } + if type_.get_pointee().is_some() { size_of::<*const ()>() as _ } else { type_.get_size() } } From 572da5cd261381451669d7d35c199e2227f9e6db Mon Sep 17 00:00:00 2001 From: Madhav Madhusoodanan Date: Sat, 8 Mar 2025 16:47:58 +0530 Subject: [PATCH 056/606] cleaned up tests by bringing objects under `mini_core` into scope --- example/mini_core.rs | 109 +++++++++--------- tests/run/abort1.rs | 41 +------ tests/run/abort2.rs | 41 +------ tests/run/array.rs | 10 +- tests/run/assign.rs | 127 +-------------------- tests/run/closure.rs | 39 ++----- tests/run/condition.rs | 26 ++--- tests/run/empty_main.rs | 30 +---- tests/run/exit.rs | 37 +------ tests/run/exit_code.rs | 30 +---- tests/run/float.rs | 4 - tests/run/fun_ptr.rs | 9 +- tests/run/int.rs | 4 - tests/run/mut_ref.rs | 131 +--------------------- tests/run/operations.rs | 225 +------------------------------------- tests/run/ptr_cast.rs | 9 +- tests/run/return-tuple.rs | 47 +------- tests/run/slice.rs | 13 +-- tests/run/static.rs | 78 +------------ tests/run/structs.rs | 45 +------- tests/run/tuple.rs | 37 +------ 21 files changed, 124 insertions(+), 968 deletions(-) diff --git a/example/mini_core.rs b/example/mini_core.rs index bd7a4612a92c..8d749c7a8f17 100644 --- a/example/mini_core.rs +++ b/example/mini_core.rs @@ -51,6 +51,10 @@ impl LegacyReceiver for &T {} impl LegacyReceiver for &mut T {} impl LegacyReceiver for Box {} +#[lang = "receiver"] +trait Receiver { +} + #[lang = "copy"] pub trait Copy {} @@ -139,6 +143,14 @@ impl Mul for usize { } } +impl Mul for isize { + type Output = Self; + + fn mul(self, rhs: Self) -> Self::Output { + self * rhs + } +} + #[lang = "add"] pub trait Add { type Output; @@ -162,6 +174,14 @@ impl Add for i8 { } } +impl Add for i32 { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + impl Add for usize { type Output = Self; @@ -193,6 +213,14 @@ impl Sub for usize { } } +impl Sub for isize { + type Output = Self; + + fn sub(self, rhs: Self) -> Self { + self - rhs + } +} + impl Sub for u8 { type Output = Self; @@ -588,70 +616,43 @@ pub union MaybeUninit { pub mod intrinsics { #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn abort() -> ! { - loop {} - } + pub fn abort() -> !; + #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn size_of() -> usize { - loop {} - } + pub fn size_of() -> usize; + #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub unsafe fn size_of_val(_val: *const T) -> usize { - loop {} - } + pub unsafe fn size_of_val(_val: *const T) -> usize; + #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn min_align_of() -> usize { - loop {} - } + pub fn min_align_of() -> usize; + #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub unsafe fn min_align_of_val(_val: *const T) -> usize { - loop {} - } + pub unsafe fn min_align_of_val(_val: *const T) -> usize; + #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub unsafe fn copy(_src: *const T, _dst: *mut T, _count: usize) { - loop {} - } + pub unsafe fn copy(_src: *const T, _dst: *mut T, _count: usize); + #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub unsafe fn transmute(_e: T) -> U { - loop {} - } + pub unsafe fn transmute(_e: T) -> U; + #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub unsafe fn ctlz_nonzero(_x: T) -> u32 { - loop {} - } + pub unsafe fn ctlz_nonzero(_x: T) -> u32; + #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn needs_drop() -> bool { - loop {} - } + pub fn needs_drop() -> bool; + #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn bitreverse(_x: T) -> T { - loop {} - } + pub fn bitreverse(_x: T) -> T; + #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn bswap(_x: T) -> T { - loop {} - } + pub fn bswap(_x: T) -> T; + #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub unsafe fn write_bytes(_dst: *mut T, _val: u8, _count: usize) { - loop {} - } + pub unsafe fn write_bytes(_dst: *mut T, _val: u8, _count: usize); + #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub unsafe fn unreachable() -> ! { - loop {} - } + pub unsafe fn unreachable() -> !; } pub mod libc { @@ -664,6 +665,10 @@ pub mod libc { pub fn memcpy(dst: *mut u8, src: *const u8, size: usize); pub fn memmove(dst: *mut u8, src: *const u8, size: usize); pub fn strncpy(dst: *mut u8, src: *const u8, size: usize); + pub fn fflush(stream: *mut i32) -> i32; + pub fn exit(status: i32); + + pub static stdout: *mut i32; } } diff --git a/tests/run/abort1.rs b/tests/run/abort1.rs index 696197d73772..6561aaf25f6e 100644 --- a/tests/run/abort1.rs +++ b/tests/run/abort1.rs @@ -3,47 +3,12 @@ // Run-time: // status: signal -#![feature(auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)] -#![allow(internal_features)] - +#![feature(no_core, start)] #![no_std] #![no_core] -/* - * Core - */ - -// Because we don't have core yet. -#[lang = "sized"] -pub trait Sized {} - -#[lang = "copy"] -trait Copy { -} - -impl Copy for isize {} - -#[lang = "receiver"] -trait Receiver { -} - -#[lang = "freeze"] -pub(crate) unsafe auto trait Freeze {} - -mod intrinsics { - use super::Sized; - - #[rustc_nounwind] - #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn abort() -> ! { - loop {} - } -} - -/* - * Code - */ +extern crate mini_core; +use mini_core::*; fn test_fail() -> ! { unsafe { intrinsics::abort() }; diff --git a/tests/run/abort2.rs b/tests/run/abort2.rs index 714cd6c0f381..a9f176577fc7 100644 --- a/tests/run/abort2.rs +++ b/tests/run/abort2.rs @@ -3,47 +3,12 @@ // Run-time: // status: signal -#![feature(auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)] -#![allow(internal_features)] - +#![feature(no_core, start)] #![no_std] #![no_core] -/* - * Core - */ - -// Because we don't have core yet. -#[lang = "sized"] -pub trait Sized {} - -#[lang = "copy"] -trait Copy { -} - -impl Copy for isize {} - -#[lang = "receiver"] -trait Receiver { -} - -#[lang = "freeze"] -pub(crate) unsafe auto trait Freeze {} - -mod intrinsics { - use super::Sized; - - #[rustc_nounwind] - #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn abort() -> ! { - loop {} - } -} - -/* - * Code - */ +extern crate mini_core; +use mini_core::*; fn fail() -> i32 { unsafe { intrinsics::abort() }; diff --git a/tests/run/array.rs b/tests/run/array.rs index c3c08c29c6db..b405102baff6 100644 --- a/tests/run/array.rs +++ b/tests/run/array.rs @@ -8,19 +8,11 @@ // 10 #![feature(no_core, start)] - #![no_std] #![no_core] extern crate mini_core; - -mod libc { - #[link(name = "c")] - extern "C" { - pub fn printf(format: *const i8, ...) -> i32; - pub fn puts(s: *const u8) -> i32; - } -} +use mini_core::*; static mut ONE: usize = 1; diff --git a/tests/run/assign.rs b/tests/run/assign.rs index 2a47f0c2966e..99a61337ada4 100644 --- a/tests/run/assign.rs +++ b/tests/run/assign.rs @@ -5,132 +5,12 @@ // 7 8 // 10 -#![allow(internal_features, unused_attributes)] -#![feature(auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs, track_caller)] - +#![feature(no_core, start)] #![no_std] #![no_core] -/* - * Core - */ - -// Because we don't have core yet. -#[lang = "sized"] -pub trait Sized {} - -#[lang = "copy"] -trait Copy { -} - -impl Copy for isize {} -impl Copy for *mut i32 {} -impl Copy for usize {} -impl Copy for u8 {} -impl Copy for i8 {} -impl Copy for i32 {} - -#[lang = "receiver"] -trait Receiver { -} - -#[lang = "freeze"] -pub(crate) unsafe auto trait Freeze {} - -#[lang = "panic_location"] -struct PanicLocation { - file: &'static str, - line: u32, - column: u32, -} - -mod libc { - #[link(name = "c")] - extern "C" { - pub fn puts(s: *const u8) -> i32; - pub fn fflush(stream: *mut i32) -> i32; - pub fn printf(format: *const i8, ...) -> i32; - - pub static stdout: *mut i32; - } -} - -mod intrinsics { - #[rustc_nounwind] - #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn abort() -> ! { - loop {} - } -} - -#[lang = "panic"] -#[track_caller] -#[no_mangle] -pub fn panic(_msg: &'static str) -> ! { - unsafe { - libc::puts("Panicking\0" as *const str as *const u8); - libc::fflush(libc::stdout); - intrinsics::abort(); - } -} - -#[lang = "add"] -trait Add { - type Output; - - fn add(self, rhs: RHS) -> Self::Output; -} - -impl Add for u8 { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -impl Add for i8 { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -impl Add for i32 { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -impl Add for usize { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -impl Add for isize { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -#[track_caller] -#[lang = "panic_const_add_overflow"] -pub fn panic_const_add_overflow() -> ! { - panic("attempt to add with overflow"); -} - -/* - * Code - */ +extern crate mini_core; +use mini_core::*; fn inc_ref(num: &mut isize) -> isize { *num = *num + 5; @@ -141,7 +21,6 @@ fn inc(num: isize) -> isize { num + 1 } - #[start] fn main(mut argc: isize, _argv: *const *const u8) -> isize { argc = inc(argc); diff --git a/tests/run/closure.rs b/tests/run/closure.rs index 46c47bc54ed0..c8f06265c6b9 100644 --- a/tests/run/closure.rs +++ b/tests/run/closure.rs @@ -9,54 +9,37 @@ // Both args: 11 #![feature(no_core, start)] - #![no_std] #![no_core] extern crate mini_core; - -mod libc { - #[link(name = "c")] - extern "C" { - pub fn printf(format: *const i8, ...) -> i32; - } -} +use mini_core::*; #[start] fn main(mut argc: isize, _argv: *const *const u8) -> isize { let string = "Arg: %d\n\0"; - let mut closure = || { - unsafe { - libc::printf(string as *const str as *const i8, argc); - } + let mut closure = || unsafe { + libc::printf(string as *const str as *const i8, argc); }; closure(); - let mut closure = || { - unsafe { - libc::printf("Argument: %d\n\0" as *const str as *const i8, argc); - } + let mut closure = || unsafe { + libc::printf("Argument: %d\n\0" as *const str as *const i8, argc); }; closure(); - let mut closure = |string| { - unsafe { - libc::printf(string as *const str as *const i8, argc); - } + let mut closure = |string| unsafe { + libc::printf(string as *const str as *const i8, argc); }; closure("String arg: %d\n\0"); - let mut closure = |arg: isize| { - unsafe { - libc::printf("Int argument: %d\n\0" as *const str as *const i8, arg); - } + let mut closure = |arg: isize| unsafe { + libc::printf("Int argument: %d\n\0" as *const str as *const i8, arg); }; closure(argc + 1); - let mut closure = |string, arg: isize| { - unsafe { - libc::printf(string as *const str as *const i8, arg); - } + let mut closure = |string, arg: isize| unsafe { + libc::printf(string as *const str as *const i8, arg); }; closure("Both args: %d\n\0", argc + 10); diff --git a/tests/run/condition.rs b/tests/run/condition.rs index 039ef94eaa71..d3714587401a 100644 --- a/tests/run/condition.rs +++ b/tests/run/condition.rs @@ -6,18 +6,11 @@ // 1 #![feature(no_core, start)] - #![no_std] #![no_core] extern crate mini_core; - -mod libc { - #[link(name = "c")] - extern "C" { - pub fn printf(format: *const i8, ...) -> i32; - } -} +use mini_core::*; #[start] fn main(argc: isize, _argv: *const *const u8) -> isize { @@ -26,15 +19,14 @@ fn main(argc: isize, _argv: *const *const u8) -> isize { libc::printf(b"true\n\0" as *const u8 as *const i8); } - let string = - match argc { - 1 => b"1\n\0", - 2 => b"2\n\0", - 3 => b"3\n\0", - 4 => b"4\n\0", - 5 => b"5\n\0", - _ => b"_\n\0", - }; + let string = match argc { + 1 => b"1\n\0", + 2 => b"2\n\0", + 3 => b"3\n\0", + 4 => b"4\n\0", + 5 => b"5\n\0", + _ => b"_\n\0", + }; libc::printf(string as *const u8 as *const i8); } 0 diff --git a/tests/run/empty_main.rs b/tests/run/empty_main.rs index e66a859ad698..c4a24e9b1854 100644 --- a/tests/run/empty_main.rs +++ b/tests/run/empty_main.rs @@ -3,36 +3,12 @@ // Run-time: // status: 0 -#![feature(auto_traits, lang_items, no_core, start)] -#![allow(internal_features)] - +#![feature(no_core, start)] #![no_std] #![no_core] -/* - * Core - */ - -// Because we don't have core yet. -#[lang = "sized"] -pub trait Sized {} - -#[lang = "copy"] -trait Copy { -} - -impl Copy for isize {} - -#[lang = "receiver"] -trait Receiver { -} - -#[lang = "freeze"] -pub(crate) unsafe auto trait Freeze {} - -/* - * Code - */ +extern crate mini_core; +use mini_core::*; #[start] fn main(_argc: isize, _argv: *const *const u8) -> isize { diff --git a/tests/run/exit.rs b/tests/run/exit.rs index bf1cbeef3020..3d66d8fbdb21 100644 --- a/tests/run/exit.rs +++ b/tests/run/exit.rs @@ -3,43 +3,12 @@ // Run-time: // status: 2 -#![feature(auto_traits, lang_items, no_core, start, intrinsics)] -#![allow(internal_features)] - +#![feature(no_core, start)] #![no_std] #![no_core] -mod libc { - #[link(name = "c")] - extern "C" { - pub fn exit(status: i32); - } -} - -/* - * Core - */ - -// Because we don't have core yet. -#[lang = "sized"] -pub trait Sized {} - -#[lang = "copy"] -trait Copy { -} - -impl Copy for isize {} - -#[lang = "receiver"] -trait Receiver { -} - -#[lang = "freeze"] -pub(crate) unsafe auto trait Freeze {} - -/* - * Code - */ +extern crate mini_core; +use mini_core::*; #[start] fn main(mut argc: isize, _argv: *const *const u8) -> isize { diff --git a/tests/run/exit_code.rs b/tests/run/exit_code.rs index be7a233efdaa..b18d08879f0d 100644 --- a/tests/run/exit_code.rs +++ b/tests/run/exit_code.rs @@ -3,36 +3,12 @@ // Run-time: // status: 1 -#![feature(auto_traits, lang_items, no_core, start)] -#![allow(internal_features)] - +#![feature(no_core, start)] #![no_std] #![no_core] -/* - * Core - */ - -// Because we don't have core yet. -#[lang = "sized"] -pub trait Sized {} - -#[lang = "copy"] -trait Copy { -} - -impl Copy for isize {} - -#[lang = "receiver"] -trait Receiver { -} - -#[lang = "freeze"] -pub(crate) unsafe auto trait Freeze {} - -/* - * Code - */ +extern crate mini_core; +use mini_core::*; #[start] fn main(mut argc: isize, _argv: *const *const u8) -> isize { diff --git a/tests/run/float.rs b/tests/run/float.rs index e0a57e6fed1a..424fa1cf4ad5 100644 --- a/tests/run/float.rs +++ b/tests/run/float.rs @@ -5,10 +5,6 @@ #![feature(const_black_box)] -/* - * Code - */ - fn main() { use std::hint::black_box; diff --git a/tests/run/fun_ptr.rs b/tests/run/fun_ptr.rs index ed1bf72bb275..45b4ebcd9f05 100644 --- a/tests/run/fun_ptr.rs +++ b/tests/run/fun_ptr.rs @@ -5,18 +5,11 @@ // stdout: 1 #![feature(no_core, start)] - #![no_std] #![no_core] extern crate mini_core; - -mod libc { - #[link(name = "c")] - extern "C" { - pub fn printf(format: *const i8, ...) -> i32; - } -} +use mini_core::*; fn i16_as_i8(a: i16) -> i8 { a as i8 diff --git a/tests/run/int.rs b/tests/run/int.rs index bfe73c38435a..47b5dea46f8d 100644 --- a/tests/run/int.rs +++ b/tests/run/int.rs @@ -5,10 +5,6 @@ #![feature(const_black_box)] -/* - * Code - */ - fn main() { use std::hint::black_box; diff --git a/tests/run/mut_ref.rs b/tests/run/mut_ref.rs index 3ae793382164..5c91bc96ca00 100644 --- a/tests/run/mut_ref.rs +++ b/tests/run/mut_ref.rs @@ -1,4 +1,3 @@ - // Compiler: // // Run-time: @@ -7,141 +6,19 @@ // 6 // 11 -#![allow(internal_features, unused_attributes)] -#![feature(auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs, track_caller)] - +#![feature(no_core, start)] #![no_std] #![no_core] -/* - * Core - */ - -// Because we don't have core yet. -#[lang = "sized"] -pub trait Sized {} - -#[lang = "copy"] -trait Copy { -} - -impl Copy for isize {} -impl Copy for *mut i32 {} -impl Copy for usize {} -impl Copy for u8 {} -impl Copy for i8 {} -impl Copy for i32 {} - -#[lang = "receiver"] -trait Receiver { -} - -#[lang = "freeze"] -pub(crate) unsafe auto trait Freeze {} - -#[lang = "panic_location"] -struct PanicLocation { - file: &'static str, - line: u32, - column: u32, -} - -mod libc { - #[link(name = "c")] - extern "C" { - pub fn puts(s: *const u8) -> i32; - pub fn fflush(stream: *mut i32) -> i32; - pub fn printf(format: *const i8, ...) -> i32; - - pub static stdout: *mut i32; - } -} - -mod intrinsics { - #[rustc_nounwind] - #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn abort() -> ! { - loop {} - } -} - -#[lang = "panic"] -#[track_caller] -#[no_mangle] -pub fn panic(_msg: &'static str) -> ! { - unsafe { - libc::puts("Panicking\0" as *const str as *const u8); - libc::fflush(libc::stdout); - intrinsics::abort(); - } -} - -#[lang = "add"] -trait Add { - type Output; - - fn add(self, rhs: RHS) -> Self::Output; -} - -impl Add for u8 { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -impl Add for i8 { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -impl Add for i32 { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -impl Add for usize { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -impl Add for isize { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -#[track_caller] -#[lang = "panic_const_add_overflow"] -pub fn panic_const_add_overflow() -> ! { - panic("attempt to add with overflow"); -} - -/* - * Code - */ +extern crate mini_core; +use mini_core::*; struct Test { field: isize, } fn test(num: isize) -> Test { - Test { - field: num + 1, - } + Test { field: num + 1 } } fn update_num(num: &mut isize) { diff --git a/tests/run/operations.rs b/tests/run/operations.rs index 0e44fc580b8c..a298cf2a68d5 100644 --- a/tests/run/operations.rs +++ b/tests/run/operations.rs @@ -5,231 +5,12 @@ // 39 // 10 -#![allow(internal_features, unused_attributes)] -#![feature(auto_traits, lang_items, no_core, start, intrinsics, arbitrary_self_types, rustc_attrs)] - +#![feature(no_core, start)] #![no_std] #![no_core] -/* - * Core - */ - -// Because we don't have core yet. -#[lang = "sized"] -pub trait Sized {} - -#[lang = "copy"] -trait Copy { -} - -impl Copy for isize {} -impl Copy for *mut i32 {} -impl Copy for usize {} -impl Copy for u8 {} -impl Copy for i8 {} -impl Copy for i16 {} -impl Copy for i32 {} - -#[lang = "deref"] -pub trait Deref { - type Target: ?Sized; - - fn deref(&self) -> &Self::Target; -} - -#[lang = "legacy_receiver"] -trait LegacyReceiver { -} - -#[lang = "freeze"] -pub(crate) unsafe auto trait Freeze {} - -#[lang = "panic_location"] -struct PanicLocation { - file: &'static str, - line: u32, - column: u32, -} - -mod libc { - #[link(name = "c")] - extern "C" { - pub fn printf(format: *const i8, ...) -> i32; - pub fn puts(s: *const u8) -> i32; - pub fn fflush(stream: *mut i32) -> i32; - - pub static stdout: *mut i32; - } -} - -mod intrinsics { - #[rustc_nounwind] - #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn abort() -> ! { - loop {} - } -} - -#[lang = "panic"] -#[track_caller] -#[no_mangle] -pub fn panic(_msg: &'static str) -> ! { - unsafe { - libc::puts("Panicking\0" as *const str as *const u8); - libc::fflush(libc::stdout); - intrinsics::abort(); - } -} - -#[lang = "add"] -trait Add { - type Output; - - fn add(self, rhs: RHS) -> Self::Output; -} - -impl Add for u8 { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -impl Add for i8 { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -impl Add for i32 { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -impl Add for usize { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -impl Add for isize { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -#[lang = "sub"] -pub trait Sub { - type Output; - - fn sub(self, rhs: RHS) -> Self::Output; -} - -impl Sub for usize { - type Output = Self; - - fn sub(self, rhs: Self) -> Self { - self - rhs - } -} - -impl Sub for isize { - type Output = Self; - - fn sub(self, rhs: Self) -> Self { - self - rhs - } -} - -impl Sub for u8 { - type Output = Self; - - fn sub(self, rhs: Self) -> Self { - self - rhs - } -} - -impl Sub for i8 { - type Output = Self; - - fn sub(self, rhs: Self) -> Self { - self - rhs - } -} - -impl Sub for i16 { - type Output = Self; - - fn sub(self, rhs: Self) -> Self { - self - rhs - } -} - -#[lang = "mul"] -pub trait Mul { - type Output; - - #[must_use] - fn mul(self, rhs: RHS) -> Self::Output; -} - -impl Mul for u8 { - type Output = Self; - - fn mul(self, rhs: Self) -> Self::Output { - self * rhs - } -} - -impl Mul for usize { - type Output = Self; - - fn mul(self, rhs: Self) -> Self::Output { - self * rhs - } -} - -impl Mul for isize { - type Output = Self; - - fn mul(self, rhs: Self) -> Self::Output { - self * rhs - } -} - -#[track_caller] -#[lang = "panic_const_add_overflow"] -pub fn panic_const_add_overflow() -> ! { - panic("attempt to add with overflow"); -} - -#[track_caller] -#[lang = "panic_const_sub_overflow"] -pub fn panic_const_sub_overflow() -> ! { - panic("attempt to subtract with overflow"); -} - -#[track_caller] -#[lang = "panic_const_mul_overflow"] -pub fn panic_const_mul_overflow() -> ! { - panic("attempt to multiply with overflow"); -} - -/* - * Code - */ +extern crate mini_core; +use mini_core::*; #[start] fn main(mut argc: isize, _argv: *const *const u8) -> isize { diff --git a/tests/run/ptr_cast.rs b/tests/run/ptr_cast.rs index 2b8812ad51c5..eb4cf3eafd0e 100644 --- a/tests/run/ptr_cast.rs +++ b/tests/run/ptr_cast.rs @@ -5,18 +5,11 @@ // stdout: 1 #![feature(no_core, start)] - #![no_std] #![no_core] extern crate mini_core; - -mod libc { - #[link(name = "c")] - extern "C" { - pub fn printf(format: *const i8, ...) -> i32; - } -} +use mini_core::*; static mut ONE: usize = 1; diff --git a/tests/run/return-tuple.rs b/tests/run/return-tuple.rs index f2a5a2e4384d..c3069933e085 100644 --- a/tests/run/return-tuple.rs +++ b/tests/run/return-tuple.rs @@ -6,53 +6,12 @@ // 10 // 42 -#![feature(auto_traits, lang_items, no_core, start, intrinsics)] -#![allow(internal_features)] - +#![feature(no_core, start)] #![no_std] #![no_core] -#[lang = "copy"] -pub unsafe trait Copy {} - -impl Copy for bool {} -impl Copy for u8 {} -impl Copy for u16 {} -impl Copy for u32 {} -impl Copy for u64 {} -impl Copy for usize {} -impl Copy for i8 {} -impl Copy for i16 {} -impl Copy for i32 {} -impl Copy for isize {} -impl Copy for f32 {} -impl Copy for char {} - -mod libc { - #[link(name = "c")] - extern "C" { - pub fn printf(format: *const i8, ...) -> i32; - } -} - -/* - * Core - */ - -// Because we don't have core yet. -#[lang = "sized"] -pub trait Sized {} - -#[lang = "legacy_receiver"] -trait LegacyReceiver { -} - -#[lang = "freeze"] -pub(crate) unsafe auto trait Freeze {} - -/* - * Code - */ +extern crate mini_core; +use mini_core::*; fn int_cast(a: u16, b: i16) -> (u8, u16, u32, usize, i8, i16, i32, isize, u8, u32) { ( diff --git a/tests/run/slice.rs b/tests/run/slice.rs index fba93fc15549..6f2f8b9a9cec 100644 --- a/tests/run/slice.rs +++ b/tests/run/slice.rs @@ -5,25 +5,16 @@ // stdout: 5 #![feature(no_core, start)] - #![no_std] #![no_core] extern crate mini_core; - -mod libc { - #[link(name = "c")] - extern "C" { - pub fn printf(format: *const i8, ...) -> i32; - } -} +use mini_core::*; static mut TWO: usize = 2; fn index_slice(s: &[u32]) -> u32 { - unsafe { - s[TWO] - } + unsafe { s[TWO] } } #[start] diff --git a/tests/run/static.rs b/tests/run/static.rs index a17ea2a48936..5fc167ce4e47 100644 --- a/tests/run/static.rs +++ b/tests/run/static.rs @@ -9,72 +9,12 @@ // 12 // 1 -#![feature(auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)] -#![allow(internal_features)] - +#![feature(no_core, start)] #![no_std] #![no_core] -/* - * Core - */ - -// Because we don't have core yet. -#[lang = "sized"] -pub trait Sized {} - -#[lang = "destruct"] -pub trait Destruct {} - -#[lang = "drop"] -pub trait Drop {} - -#[lang = "copy"] -trait Copy { -} - -impl Copy for isize {} -impl Copy for *mut T {} - -#[lang = "receiver"] -trait Receiver { -} - -#[lang = "freeze"] -pub(crate) unsafe auto trait Freeze {} - -mod intrinsics { - use super::Sized; - - #[rustc_nounwind] - #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn abort() -> ! { - loop {} - } -} - -mod libc { - #[link(name = "c")] - extern "C" { - pub fn printf(format: *const i8, ...) -> i32; - } -} - -#[lang = "structural_peq"] -pub trait StructuralPartialEq {} - -#[lang = "drop_in_place"] -#[allow(unconditional_recursion)] -pub unsafe fn drop_in_place(to_drop: *mut T) { - // Code here does not matter - this is replaced by the - // real drop glue by the compiler. - drop_in_place(to_drop); -} - -/* - * Code - */ +extern crate mini_core; +use mini_core::*; struct Test { field: isize, @@ -86,17 +26,11 @@ struct WithRef { static mut CONSTANT: isize = 10; -static mut TEST: Test = Test { - field: 12, -}; +static mut TEST: Test = Test { field: 12 }; -static mut TEST2: Test = Test { - field: 14, -}; +static mut TEST2: Test = Test { field: 14 }; -static mut WITH_REF: WithRef = WithRef { - refe: unsafe { &TEST }, -}; +static mut WITH_REF: WithRef = WithRef { refe: unsafe { &TEST } }; #[start] fn main(mut argc: isize, _argv: *const *const u8) -> isize { diff --git a/tests/run/structs.rs b/tests/run/structs.rs index d6455667400c..641c6c71d1e0 100644 --- a/tests/run/structs.rs +++ b/tests/run/structs.rs @@ -5,43 +5,12 @@ // stdout: 1 // 2 -#![feature(auto_traits, lang_items, no_core, start, intrinsics)] -#![allow(internal_features)] - +#![feature(no_core, start)] #![no_std] #![no_core] -/* - * Core - */ - -// Because we don't have core yet. -#[lang = "sized"] -pub trait Sized {} - -#[lang = "copy"] -trait Copy { -} - -impl Copy for isize {} - -#[lang = "receiver"] -trait Receiver { -} - -#[lang = "freeze"] -pub(crate) unsafe auto trait Freeze {} - -mod libc { - #[link(name = "c")] - extern "C" { - pub fn printf(format: *const i8, ...) -> i32; - } -} - -/* - * Code - */ +extern crate mini_core; +use mini_core::*; struct Test { field: isize, @@ -57,12 +26,8 @@ fn one() -> isize { #[start] fn main(mut argc: isize, _argv: *const *const u8) -> isize { - let test = Test { - field: one(), - }; - let two = Two { - two: 2, - }; + let test = Test { field: one() }; + let two = Two { two: 2 }; unsafe { libc::printf(b"%ld\n\0" as *const u8 as *const i8, test.field); libc::printf(b"%ld\n\0" as *const u8 as *const i8, two.two); diff --git a/tests/run/tuple.rs b/tests/run/tuple.rs index 8a7d85ae867e..1f2d24eeacc5 100644 --- a/tests/run/tuple.rs +++ b/tests/run/tuple.rs @@ -4,43 +4,12 @@ // status: 0 // stdout: 3 -#![feature(auto_traits, lang_items, no_core, start, intrinsics)] -#![allow(internal_features)] - +#![feature(no_core, start)] #![no_std] #![no_core] -/* - * Core - */ - -// Because we don't have core yet. -#[lang = "sized"] -pub trait Sized {} - -#[lang = "copy"] -trait Copy { -} - -impl Copy for isize {} - -#[lang = "receiver"] -trait Receiver { -} - -#[lang = "freeze"] -pub(crate) unsafe auto trait Freeze {} - -mod libc { - #[link(name = "c")] - extern "C" { - pub fn printf(format: *const i8, ...) -> i32; - } -} - -/* - * Code - */ +extern crate mini_core; +use mini_core::*; #[start] fn main(mut argc: isize, _argv: *const *const u8) -> isize { From 7989568b8edd6531ed062614b71c327677b581ba Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 12 Mar 2025 08:03:54 +0100 Subject: [PATCH 057/606] intrinsics: remove unnecessary leading underscore from argument names --- example/mini_core.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/example/mini_core.rs b/example/mini_core.rs index 3dad35bc4ce4..5544aee9eaf1 100644 --- a/example/mini_core.rs +++ b/example/mini_core.rs @@ -595,25 +595,25 @@ pub mod intrinsics { #[rustc_intrinsic] pub fn size_of() -> usize; #[rustc_intrinsic] - pub unsafe fn size_of_val(_val: *const T) -> usize; + pub unsafe fn size_of_val(val: *const T) -> usize; #[rustc_intrinsic] pub fn min_align_of() -> usize; #[rustc_intrinsic] - pub unsafe fn min_align_of_val(_val: *const T) -> usize; + pub unsafe fn min_align_of_val(val: *const T) -> usize; #[rustc_intrinsic] - pub unsafe fn copy(_src: *const T, _dst: *mut T, _count: usize); + pub unsafe fn copy(src: *const T, dst: *mut T, count: usize); #[rustc_intrinsic] - pub unsafe fn transmute(_e: T) -> U; + pub unsafe fn transmute(e: T) -> U; #[rustc_intrinsic] - pub unsafe fn ctlz_nonzero(_x: T) -> u32; + pub unsafe fn ctlz_nonzero(x: T) -> u32; #[rustc_intrinsic] pub fn needs_drop() -> bool; #[rustc_intrinsic] - pub fn bitreverse(_x: T) -> T; + pub fn bitreverse(x: T) -> T; #[rustc_intrinsic] - pub fn bswap(_x: T) -> T; + pub fn bswap(x: T) -> T; #[rustc_intrinsic] - pub unsafe fn write_bytes(_dst: *mut T, _val: u8, _count: usize); + pub unsafe fn write_bytes(dst: *mut T, val: u8, count: usize); #[rustc_intrinsic] pub unsafe fn unreachable() -> !; } From 8e235258f38e43c4b565c5393d96aa5381d366bf Mon Sep 17 00:00:00 2001 From: Adwin White Date: Mon, 17 Mar 2025 18:17:09 +0800 Subject: [PATCH 058/606] fix(debuginfo): avoid overflow when handling expanding recursive type --- .../src/debuginfo/metadata/type_map.rs | 48 +++++++++++++++++++ .../rustc_codegen_llvm/src/debuginfo/mod.rs | 2 + tests/debuginfo/recursive-enum.rs | 17 ++++++- 3 files changed, 66 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs index af1d503ad6a4..8fd13eee379d 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs @@ -247,6 +247,16 @@ pub(super) fn stub<'ll, 'tcx>( StubInfo { metadata, unique_type_id } } +struct AdtStackPopGuard<'ll, 'tcx, 'a> { + cx: &'a CodegenCx<'ll, 'tcx>, +} + +impl<'ll, 'tcx, 'a> Drop for AdtStackPopGuard<'ll, 'tcx, 'a> { + fn drop(&mut self) { + debug_context(self.cx).adt_stack.borrow_mut().pop(); + } +} + /// This function enables creating debuginfo nodes that can recursively refer to themselves. /// It will first insert the given stub into the type map and only then execute the `members` /// and `generics` closures passed in. These closures have access to the stub so they can @@ -261,6 +271,44 @@ pub(super) fn build_type_with_children<'ll, 'tcx>( ) -> DINodeCreationResult<'ll> { assert_eq!(debug_context(cx).type_map.di_node_for_unique_id(stub_info.unique_type_id), None); + let mut _adt_stack_pop_guard = None; + if let UniqueTypeId::Ty(ty, ..) = stub_info.unique_type_id + && let ty::Adt(adt_def, args) = ty.kind() + { + let def_id = adt_def.did(); + // If any sub type reference the original type definition and the sub type has a type + // parameter that strictly contains the original parameter, the original type is a recursive + // type that can expanding indefinitely. Example, + // ``` + // enum Recursive { + // Recurse(*const Recursive>), + // Item(T), + // } + // ``` + let is_expanding_recursive = + debug_context(cx).adt_stack.borrow().iter().any(|(parent_def_id, parent_args)| { + if def_id == *parent_def_id { + args.iter().zip(parent_args.iter()).any(|(arg, parent_arg)| { + if let (Some(arg), Some(parent_arg)) = (arg.as_type(), parent_arg.as_type()) + { + arg != parent_arg && arg.contains(parent_arg) + } else { + false + } + }) + } else { + false + } + }); + if is_expanding_recursive { + // FIXME: indicate that this is an expanding recursive type in stub metadata? + return DINodeCreationResult::new(stub_info.metadata, false); + } else { + debug_context(cx).adt_stack.borrow_mut().push((def_id, args)); + _adt_stack_pop_guard = Some(AdtStackPopGuard { cx }); + } + } + debug_context(cx).type_map.insert(stub_info.unique_type_id, stub_info.metadata); let members: SmallVec<_> = diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index 10819a53b1df..bbe69382d084 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -65,6 +65,7 @@ pub(crate) struct CodegenUnitDebugContext<'ll, 'tcx> { created_files: RefCell, &'ll DIFile>>, type_map: metadata::TypeMap<'ll, 'tcx>, + adt_stack: RefCell)>>, namespace_map: RefCell>, recursion_marker_type: OnceCell<&'ll DIType>, } @@ -79,6 +80,7 @@ impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> { builder, created_files: Default::default(), type_map: Default::default(), + adt_stack: Default::default(), namespace_map: RefCell::new(Default::default()), recursion_marker_type: OnceCell::new(), } diff --git a/tests/debuginfo/recursive-enum.rs b/tests/debuginfo/recursive-enum.rs index c2c3e71b8a4f..b861e6d617c8 100644 --- a/tests/debuginfo/recursive-enum.rs +++ b/tests/debuginfo/recursive-enum.rs @@ -4,7 +4,7 @@ // gdb-command:run // Test whether compiling a recursive enum definition crashes debug info generation. The test case -// is taken from issue #11083. +// is taken from issue #11083 and #135093. #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] @@ -18,6 +18,21 @@ struct WindowCallbacks<'a> { pos_callback: Option>, } +enum ExpandingRecursive { + Recurse(Indirect), + Item(T), +} + +struct Indirect { + rec: *const ExpandingRecursive>, +} + + fn main() { let x = WindowCallbacks { pos_callback: None }; + + // EXPANDING RECURSIVE + let expanding_recursive: ExpandingRecursive = ExpandingRecursive::Recurse(Indirect { + rec: &ExpandingRecursive::Item(Option::Some(42)), + }); } From d5c4ed04842235b08119fde271151f7f17b57139 Mon Sep 17 00:00:00 2001 From: Adwin White Date: Mon, 17 Mar 2025 19:43:31 +0800 Subject: [PATCH 059/606] (re)move fixed crash tests --- tests/crashes/100618.rs | 12 -------- tests/crashes/115994.rs | 17 ----------- tests/crashes/121538.rs | 30 ------------------- .../recursive-type-with-gat.rs} | 1 - 4 files changed, 60 deletions(-) delete mode 100644 tests/crashes/100618.rs delete mode 100644 tests/crashes/115994.rs delete mode 100644 tests/crashes/121538.rs rename tests/{crashes/107362.rs => debuginfo/recursive-type-with-gat.rs} (96%) diff --git a/tests/crashes/100618.rs b/tests/crashes/100618.rs deleted file mode 100644 index 911c4098badc..000000000000 --- a/tests/crashes/100618.rs +++ /dev/null @@ -1,12 +0,0 @@ -//@ known-bug: #100618 -//@ compile-flags: -Cdebuginfo=2 - -//@ only-x86_64 -enum Foo { - Value(T), - Recursive(&'static Foo>), -} - -fn main() { - let _x = Foo::Value(()); -} diff --git a/tests/crashes/115994.rs b/tests/crashes/115994.rs deleted file mode 100644 index 23d1507136f7..000000000000 --- a/tests/crashes/115994.rs +++ /dev/null @@ -1,17 +0,0 @@ -//@ known-bug: #115994 -//@ compile-flags: -Cdebuginfo=2 --crate-type lib - -// To prevent "overflow while adding drop-check rules". -use std::mem::ManuallyDrop; - -pub enum Foo { - Leaf(U), - - Branch(BoxedFoo>), -} - -pub type BoxedFoo = ManuallyDrop>>; - -pub fn test() -> Foo { - todo!() -} diff --git a/tests/crashes/121538.rs b/tests/crashes/121538.rs deleted file mode 100644 index f18bad84b572..000000000000 --- a/tests/crashes/121538.rs +++ /dev/null @@ -1,30 +0,0 @@ -//@ known-bug: #121538 -//@ compile-flags: -Cdebuginfo=2 - -use std::marker::PhantomData; - -struct Digit { - elem: T -} - -struct Node { m: PhantomData<&'static T> } - -enum FingerTree { - Single(T), - - Deep( - Digit, - Node>>, - ) -} - -enum Wrapper { - Simple, - Other(FingerTree), -} - -fn main() { - let w = - Some(Wrapper::Simple::); - -} diff --git a/tests/crashes/107362.rs b/tests/debuginfo/recursive-type-with-gat.rs similarity index 96% rename from tests/crashes/107362.rs rename to tests/debuginfo/recursive-type-with-gat.rs index 8d55d611eb13..b8a67d8d24b4 100644 --- a/tests/crashes/107362.rs +++ b/tests/debuginfo/recursive-type-with-gat.rs @@ -1,4 +1,3 @@ -//@ known-bug: #107362 //@ compile-flags: -Cdebuginfo=2 pub trait Functor From b25a593b40e88019a5c76198f5c69e2fcced368d Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 2 Dec 2023 14:17:33 +0000 Subject: [PATCH 060/606] Remove implicit #[no_mangle] for #[rustc_std_internal_symbol] --- src/allocator.rs | 13 +++++++------ src/lib.rs | 1 + 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/allocator.rs b/src/allocator.rs index 416f3231a13c..f4ebd42ee2dc 100644 --- a/src/allocator.rs +++ b/src/allocator.rs @@ -8,6 +8,7 @@ use rustc_ast::expand::allocator::{ use rustc_middle::bug; use rustc_middle::ty::TyCtxt; use rustc_session::config::OomStrategy; +use rustc_symbol_mangling::mangle_internal_symbol; use crate::GccContext; #[cfg(feature = "master")] @@ -53,8 +54,8 @@ pub(crate) unsafe fn codegen( panic!("invalid allocator output") } }; - let from_name = global_fn_name(method.name); - let to_name = default_fn_name(method.name); + let from_name = mangle_internal_symbol(tcx, &global_fn_name(method.name)); + let to_name = mangle_internal_symbol(tcx, &default_fn_name(method.name)); create_wrapper_function(tcx, context, &from_name, &to_name, &types, output); } @@ -64,13 +65,13 @@ pub(crate) unsafe fn codegen( create_wrapper_function( tcx, context, - "__rust_alloc_error_handler", - alloc_error_handler_name(alloc_error_handler_kind), + &mangle_internal_symbol(tcx, "__rust_alloc_error_handler"), + &mangle_internal_symbol(tcx, alloc_error_handler_name(alloc_error_handler_kind)), &[usize, usize], None, ); - let name = OomStrategy::SYMBOL.to_string(); + let name = mangle_internal_symbol(tcx, OomStrategy::SYMBOL); let global = context.new_global(None, GlobalKind::Exported, i8, name); #[cfg(feature = "master")] global.add_attribute(VarAttribute::Visibility(symbol_visibility_to_gcc( @@ -80,7 +81,7 @@ pub(crate) unsafe fn codegen( let value = context.new_rvalue_from_int(i8, value as i32); global.global_set_initializer_rvalue(value); - let name = NO_ALLOC_SHIM_IS_UNSTABLE.to_string(); + let name = mangle_internal_symbol(tcx, NO_ALLOC_SHIM_IS_UNSTABLE); let global = context.new_global(None, GlobalKind::Exported, i8, name); #[cfg(feature = "master")] global.add_attribute(VarAttribute::Visibility(symbol_visibility_to_gcc( diff --git a/src/lib.rs b/src/lib.rs index d478b2af46c2..bfa23174a19d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -52,6 +52,7 @@ extern crate rustc_metadata; extern crate rustc_middle; extern crate rustc_session; extern crate rustc_span; +extern crate rustc_symbol_mangling; extern crate rustc_target; // This prevents duplicating functions and statics that are already part of the host rustc process. From e89c84913690bad837b658ade502cb0af7df768b Mon Sep 17 00:00:00 2001 From: xizheyin Date: Mon, 17 Mar 2025 20:40:01 +0800 Subject: [PATCH 061/606] Clean up librustdoc::html::render to be better encapsulated Signed-off-by: xizheyin --- src/librustdoc/formats/cache.rs | 14 ++--- src/librustdoc/html/render/mod.rs | 93 ++++++++++++++++++++----------- 2 files changed, 68 insertions(+), 39 deletions(-) diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 2648641e53e7..2a612fa9b8cd 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -574,20 +574,20 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It ); let aliases = item.attrs.get_doc_aliases(); let deprecation = item.deprecation(tcx); - let index_item = IndexItem { - ty: item.type_(), - defid: Some(defid), + let index_item = IndexItem::new( + item.type_(), + Some(defid), name, path, desc, - parent: parent_did, - parent_idx: None, - exact_path: None, + parent_did, + None, + None, impl_id, search_type, aliases, deprecation, - }; + ); cache.search_index.push(index_item); } diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 2237e0f987bc..b9a2e65b0907 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -13,6 +13,9 @@ //! is cloned per-thread and contains information about what is currently being //! rendered. //! +//! The main entry point to the rendering system is the implementation of +//! `FormatRenderer` on `Context`. +//! //! In order to speed up rendering (mostly because of markdown rendering), the //! rendering process has been parallelized. This parallelization is only //! exposed through the `crate` method on the context, and then also from the @@ -90,7 +93,7 @@ pub(crate) fn ensure_trailing_slash(v: &str) -> impl fmt::Display { /// Specifies whether rendering directly implemented trait items or ones from a certain Deref /// impl. #[derive(Copy, Clone, Debug)] -pub(crate) enum AssocItemRender<'a> { +enum AssocItemRender<'a> { All, DerefFor { trait_: &'a clean::Path, type_: &'a clean::Type, deref_mut_: bool }, } @@ -98,7 +101,7 @@ pub(crate) enum AssocItemRender<'a> { /// For different handling of associated items from the Deref target of a type rather than the type /// itself. #[derive(Copy, Clone, PartialEq)] -pub(crate) enum RenderMode { +enum RenderMode { Normal, ForDeref { mut_: bool }, } @@ -110,23 +113,55 @@ pub(crate) enum RenderMode { /// by hand to a large JS file at the end of cache-creation. #[derive(Debug)] pub(crate) struct IndexItem { - pub(crate) ty: ItemType, - pub(crate) defid: Option, - pub(crate) name: Symbol, - pub(crate) path: String, - pub(crate) desc: String, - pub(crate) parent: Option, - pub(crate) parent_idx: Option, - pub(crate) exact_path: Option, - pub(crate) impl_id: Option, - pub(crate) search_type: Option, - pub(crate) aliases: Box<[Symbol]>, - pub(crate) deprecation: Option, + ty: ItemType, + defid: Option, + name: Symbol, + path: String, + desc: String, + parent: Option, + parent_idx: Option, + exact_path: Option, + impl_id: Option, + search_type: Option, + aliases: Box<[Symbol]>, + deprecation: Option, +} + +impl IndexItem { + pub fn new( + ty: ItemType, + defid: Option, + name: Symbol, + path: String, + desc: String, + parent: Option, + parent_idx: Option, + exact_path: Option, + impl_id: Option, + search_type: Option, + aliases: Box<[Symbol]>, + deprecation: Option, + ) -> Self { + Self { + ty, + defid, + name, + path, + desc, + parent, + parent_idx, + exact_path, + impl_id, + search_type, + aliases, + deprecation, + } + } } /// A type used for the search index. #[derive(Debug, Eq, PartialEq)] -pub(crate) struct RenderType { +struct RenderType { id: Option, generics: Option>, bindings: Option)>>, @@ -137,7 +172,7 @@ impl RenderType { // The contents of the lists are always integers in self-terminating hex // form, handled by `RenderTypeId::write_to_string`, so no commas are // needed to separate the items. - pub fn write_to_string(&self, string: &mut String) { + fn write_to_string(&self, string: &mut String) { fn write_optional_id(id: Option, string: &mut String) { // 0 is a sentinel, everything else is one-indexed match id { @@ -177,7 +212,7 @@ impl RenderType { } #[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub(crate) enum RenderTypeId { +enum RenderTypeId { DefId(DefId), Primitive(clean::PrimitiveType), AssociatedType(Symbol), @@ -186,7 +221,7 @@ pub(crate) enum RenderTypeId { } impl RenderTypeId { - pub fn write_to_string(&self, string: &mut String) { + fn write_to_string(&self, string: &mut String) { let id: i32 = match &self { // 0 is a sentinel, everything else is one-indexed // concrete type @@ -209,7 +244,7 @@ pub(crate) struct IndexItemFunctionType { } impl IndexItemFunctionType { - pub fn write_to_string<'a>( + fn write_to_string<'a>( &'a self, string: &mut String, backref_queue: &mut VecDeque<&'a IndexItemFunctionType>, @@ -309,7 +344,7 @@ impl ItemEntry { } impl ItemEntry { - pub(crate) fn print(&self) -> impl fmt::Display { + fn print(&self) -> impl fmt::Display { fmt::from_fn(move |f| write!(f, "{}", self.url, Escape(&self.name))) } } @@ -760,7 +795,7 @@ fn short_item_info( // Render the list of items inside one of the sections "Trait Implementations", // "Auto Trait Implementations," "Blanket Trait Implementations" (on struct/enum pages). -pub(crate) fn render_impls( +fn render_impls( cx: &Context<'_>, mut w: impl Write, impls: &[&Impl], @@ -1201,7 +1236,7 @@ impl<'a> AssocItemLink<'a> { } } -pub fn write_section_heading( +fn write_section_heading( title: &str, id: &str, extra_class: Option<&str>, @@ -1226,7 +1261,7 @@ fn write_impl_section_heading(title: &str, id: &str) -> impl fmt::Display { write_section_heading(title, id, None, "") } -pub(crate) fn render_all_impls( +fn render_all_impls( mut w: impl Write, cx: &Context<'_>, containing_item: &clean::Item, @@ -1473,10 +1508,7 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) -> } } -pub(crate) fn notable_traits_button( - ty: &clean::Type, - cx: &Context<'_>, -) -> Option { +fn notable_traits_button(ty: &clean::Type, cx: &Context<'_>) -> Option { if ty.is_unit() { // Very common fast path. return None; @@ -1588,10 +1620,7 @@ fn notable_traits_decl(ty: &clean::Type, cx: &Context<'_>) -> (String, String) { (format!("{:#}", ty.print(cx)), out) } -pub(crate) fn notable_traits_json<'a>( - tys: impl Iterator, - cx: &Context<'_>, -) -> String { +fn notable_traits_json<'a>(tys: impl Iterator, cx: &Context<'_>) -> String { let mut mp: Vec<(String, String)> = tys.map(|ty| notable_traits_decl(ty, cx)).collect(); mp.sort_by(|(name1, _html1), (name2, _html2)| name1.cmp(name2)); struct NotableTraitsMap(Vec<(String, String)>); @@ -2171,7 +2200,7 @@ fn render_rightside( }) } -pub(crate) fn render_impl_summary( +fn render_impl_summary( cx: &Context<'_>, i: &Impl, parent: &clean::Item, From a6e4d0308632f09c1041454a82d16527222e4b32 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Sun, 23 Mar 2025 22:37:48 +0000 Subject: [PATCH 062/606] Test Command::current_dir with verbatim path --- .../process/win-command-curdir-no-verbatim.rs | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 tests/ui/process/win-command-curdir-no-verbatim.rs diff --git a/tests/ui/process/win-command-curdir-no-verbatim.rs b/tests/ui/process/win-command-curdir-no-verbatim.rs new file mode 100644 index 000000000000..99943e1c8abc --- /dev/null +++ b/tests/ui/process/win-command-curdir-no-verbatim.rs @@ -0,0 +1,36 @@ +// Test that windows verbatim paths in `Command::current_dir` are converted to +// non-verbatim paths before passing to the subprocess. + +//@ run-pass +//@ only-windows +//@ needs-subprocess + +use std::env; +use std::process::Command; + +fn main() { + if env::args().skip(1).any(|s| s == "--child") { + child(); + } else { + parent(); + } +} + +fn parent() { + let exe = env::current_exe().unwrap(); + let dir = env::current_dir().unwrap(); + let status = Command::new(&exe) + .arg("--child") + .current_dir(dir.canonicalize().unwrap()) + .spawn() + .unwrap() + .wait() + .unwrap(); + assert_eq!(status.code(), Some(0)); +} + +fn child() { + let current_dir = env::current_dir().unwrap(); + let current_dir = current_dir.as_os_str().as_encoded_bytes(); + assert!(!current_dir.starts_with(br"\\?\")); +} From 59e5920e298d7690d455b13adf31b11485b25dcd Mon Sep 17 00:00:00 2001 From: Thalia Archibald Date: Wed, 5 Mar 2025 15:28:38 -0800 Subject: [PATCH 063/606] Reject test executables when not supported by target Currently, compiling tests for SOLID produces an ICE, because SOLID does not support executables. --- compiler/rustc_session/src/output.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/compiler/rustc_session/src/output.rs b/compiler/rustc_session/src/output.rs index b37a80274c0c..2b7420cb1b27 100644 --- a/compiler/rustc_session/src/output.rs +++ b/compiler/rustc_session/src/output.rs @@ -177,6 +177,13 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec Date: Mon, 24 Mar 2025 21:55:14 +0100 Subject: [PATCH 064/606] Test linking and running no_std binaries --- tests/ui/no_std/simple-runs.rs | 41 ++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 tests/ui/no_std/simple-runs.rs diff --git a/tests/ui/no_std/simple-runs.rs b/tests/ui/no_std/simple-runs.rs new file mode 100644 index 000000000000..8931ac7ed11b --- /dev/null +++ b/tests/ui/no_std/simple-runs.rs @@ -0,0 +1,41 @@ +//! Check that `no_std` binaries can link and run without depending on `libstd`. + +//@ run-pass +//@ compile-flags: -Cpanic=abort +//@ ignore-wasm different `main` convention + +#![no_std] +#![no_main] + +use core::ffi::{c_char, c_int}; +use core::panic::PanicInfo; + +// # Linux +// +// Linking `libc` is required by crt1.o, otherwise the linker fails with: +// > /usr/bin/ld: in function `_start': undefined reference to `__libc_start_main' +// +// # Apple +// +// Linking `libSystem` is required, otherwise the linker fails with: +// > ld: dynamic executables or dylibs must link with libSystem.dylib +// +// With the new linker introduced in Xcode 15, the error is instead: +// > Undefined symbols: "dyld_stub_binder", referenced from: +// +// This _can_ be worked around by raising the deployment target with +// MACOSX_DEPLOYMENT_TARGET=13.0, though it's a bit hard to test that while +// still allowing the test suite to support running with older Xcode versions. +#[cfg_attr(all(not(target_vendor = "apple"), unix), link(name = "c"))] +#[cfg_attr(target_vendor = "apple", link(name = "System"))] +extern "C" {} + +#[panic_handler] +fn panic_handler(_info: &PanicInfo<'_>) -> ! { + loop {} +} + +#[no_mangle] +extern "C" fn main(_argc: c_int, _argv: *const *const c_char) -> c_int { + 0 +} From 5743d381af27a24d12e5272043fa4e21dfa5794a Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Mon, 19 Aug 2024 15:20:02 +0200 Subject: [PATCH 065/606] Rename `is_like_osx` to `is_like_darwin` --- src/consts.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/consts.rs b/src/consts.rs index c514b7a428bc..0dc0a9182988 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -131,7 +131,7 @@ impl<'gcc, 'tcx> StaticCodegenMethods for CodegenCx<'gcc, 'tcx> { // will use load-unaligned instructions instead, and thus avoiding the crash. // // We could remove this hack whenever we decide to drop macOS 10.10 support. - if self.tcx.sess.target.options.is_like_osx { + if self.tcx.sess.target.options.is_like_darwin { // The `inspect` method is okay here because we checked for provenance, and // because we are doing this access to inspect the final interpreter state // (not as part of the interpreter execution). From 89625360ec4fa11bdc073a74607c7ff0f624fb96 Mon Sep 17 00:00:00 2001 From: xizheyin Date: Wed, 26 Mar 2025 11:27:52 +0800 Subject: [PATCH 066/606] Add ui test cast-array-issue-138836 Signed-off-by: xizheyin --- tests/ui/cast/cast-array-issue-138836.rs | 5 +++++ tests/ui/cast/cast-array-issue-138836.stderr | 12 ++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 tests/ui/cast/cast-array-issue-138836.rs create mode 100644 tests/ui/cast/cast-array-issue-138836.stderr diff --git a/tests/ui/cast/cast-array-issue-138836.rs b/tests/ui/cast/cast-array-issue-138836.rs new file mode 100644 index 000000000000..6fd65d5878ac --- /dev/null +++ b/tests/ui/cast/cast-array-issue-138836.rs @@ -0,0 +1,5 @@ +fn main() { + let a: [u8; 3] = [1,2,3]; + let b = &a; + let c = b as *const [u32; 3]; //~ ERROR mismatched types [E0308] +} diff --git a/tests/ui/cast/cast-array-issue-138836.stderr b/tests/ui/cast/cast-array-issue-138836.stderr new file mode 100644 index 000000000000..fe20d429a498 --- /dev/null +++ b/tests/ui/cast/cast-array-issue-138836.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/cast-array-issue-138836.rs:4:13 + | +LL | let c = b as *const [u32; 3]; + | ^^^^^^^^^^^^^^^^^^^^ expected `[u8; 3]`, found `[u32; 3]` + | + = note: expected array `[u8; 3]` + found array `[u32; 3]` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. From 2c70c8a6e0b220377536e4e13172bfdfcd95c50f Mon Sep 17 00:00:00 2001 From: Christopher Durham Date: Wed, 26 Mar 2025 13:52:22 -0400 Subject: [PATCH 067/606] mark cfg_match! semitransparent --- library/core/src/macros/mod.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 5f200b31d1ae..5571d8ad594a 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -237,9 +237,10 @@ pub macro assert_matches { /// ``` #[unstable(feature = "cfg_match", issue = "115585")] #[rustc_diagnostic_item = "cfg_match"] +#[rustc_macro_transparency = "semitransparent"] pub macro cfg_match { ({ $($tt:tt)* }) => {{ - cfg_match! { $($tt)* } + $crate::cfg_match! { $($tt)* } }}, (_ => { $($output:tt)* }) => { $($output)* @@ -249,10 +250,10 @@ pub macro cfg_match { $($( $rest:tt )+)? ) => { #[cfg($cfg)] - cfg_match! { _ => $output } + $crate::cfg_match! { _ => $output } $( #[cfg(not($cfg))] - cfg_match! { $($rest)+ } + $crate::cfg_match! { $($rest)+ } )? }, } From a34c42fefabc774af2d8b2c5a5a100c0697d2ba9 Mon Sep 17 00:00:00 2001 From: xizheyin Date: Wed, 26 Mar 2025 11:31:58 +0800 Subject: [PATCH 068/606] Expect an array when expected and acutal types are both arrays during cast Signed-off-by: xizheyin --- compiler/rustc_hir_typeck/src/cast.rs | 37 ++++++++++---------- tests/ui/cast/cast-array-issue-138836.rs | 2 +- tests/ui/cast/cast-array-issue-138836.stderr | 9 ++--- tests/ui/consts/const-cast-wrong-type.rs | 2 +- tests/ui/consts/const-cast-wrong-type.stderr | 6 ++-- 5 files changed, 27 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 8f5fddd19d7f..b19d9efe2c6f 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -1042,30 +1042,31 @@ impl<'a, 'tcx> CastCheck<'tcx> { m_cast: ty::TypeAndMut<'tcx>, ) -> Result> { // array-ptr-cast: allow mut-to-mut, mut-to-const, const-to-const - if m_expr.mutbl >= m_cast.mutbl { - if let ty::Array(ety, _) = m_expr.ty.kind() { - // Due to the limitations of LLVM global constants, - // region pointers end up pointing at copies of - // vector elements instead of the original values. - // To allow raw pointers to work correctly, we - // need to special-case obtaining a raw pointer - // from a region pointer to a vector. + if m_expr.mutbl >= m_cast.mutbl + && let ty::Array(ety, _) = m_expr.ty.kind() + && fcx.can_eq(fcx.param_env, *ety, m_cast.ty) + { + // Due to the limitations of LLVM global constants, + // region pointers end up pointing at copies of + // vector elements instead of the original values. + // To allow raw pointers to work correctly, we + // need to special-case obtaining a raw pointer + // from a region pointer to a vector. - // Coerce to a raw pointer so that we generate RawPtr in MIR. - let array_ptr_type = Ty::new_ptr(fcx.tcx, m_expr.ty, m_expr.mutbl); - fcx.coerce(self.expr, self.expr_ty, array_ptr_type, AllowTwoPhase::No, None) - .unwrap_or_else(|_| { - bug!( + // Coerce to a raw pointer so that we generate RawPtr in MIR. + let array_ptr_type = Ty::new_ptr(fcx.tcx, m_expr.ty, m_expr.mutbl); + fcx.coerce(self.expr, self.expr_ty, array_ptr_type, AllowTwoPhase::No, None) + .unwrap_or_else(|_| { + bug!( "could not cast from reference to array to pointer to array ({:?} to {:?})", self.expr_ty, array_ptr_type, ) - }); + }); - // this will report a type mismatch if needed - fcx.demand_eqtype(self.span, *ety, m_cast.ty); - return Ok(CastKind::ArrayPtrCast); - } + // this will report a type mismatch if needed + fcx.demand_eqtype(self.span, *ety, m_cast.ty); + return Ok(CastKind::ArrayPtrCast); } Err(CastError::IllegalCast) diff --git a/tests/ui/cast/cast-array-issue-138836.rs b/tests/ui/cast/cast-array-issue-138836.rs index 6fd65d5878ac..3f8098e76fd2 100644 --- a/tests/ui/cast/cast-array-issue-138836.rs +++ b/tests/ui/cast/cast-array-issue-138836.rs @@ -1,5 +1,5 @@ fn main() { let a: [u8; 3] = [1,2,3]; let b = &a; - let c = b as *const [u32; 3]; //~ ERROR mismatched types [E0308] + let c = b as *const [u32; 3]; //~ ERROR casting `&[u8; 3]` as `*const [u32; 3]` is invalid } diff --git a/tests/ui/cast/cast-array-issue-138836.stderr b/tests/ui/cast/cast-array-issue-138836.stderr index fe20d429a498..309474c29f93 100644 --- a/tests/ui/cast/cast-array-issue-138836.stderr +++ b/tests/ui/cast/cast-array-issue-138836.stderr @@ -1,12 +1,9 @@ -error[E0308]: mismatched types +error[E0606]: casting `&[u8; 3]` as `*const [u32; 3]` is invalid --> $DIR/cast-array-issue-138836.rs:4:13 | LL | let c = b as *const [u32; 3]; - | ^^^^^^^^^^^^^^^^^^^^ expected `[u8; 3]`, found `[u32; 3]` - | - = note: expected array `[u8; 3]` - found array `[u32; 3]` + | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0606`. diff --git a/tests/ui/consts/const-cast-wrong-type.rs b/tests/ui/consts/const-cast-wrong-type.rs index 6e055a2bcd34..9936a660936b 100644 --- a/tests/ui/consts/const-cast-wrong-type.rs +++ b/tests/ui/consts/const-cast-wrong-type.rs @@ -1,5 +1,5 @@ const a: [u8; 3] = ['h' as u8, 'i' as u8, 0 as u8]; -const b: *const i8 = &a as *const i8; //~ ERROR mismatched types +const b: *const i8 = &a as *const i8; //~ ERROR casting `&[u8; 3]` as `*const i8` is invalid fn main() { } diff --git a/tests/ui/consts/const-cast-wrong-type.stderr b/tests/ui/consts/const-cast-wrong-type.stderr index 44361f15d8a9..0730bac22354 100644 --- a/tests/ui/consts/const-cast-wrong-type.stderr +++ b/tests/ui/consts/const-cast-wrong-type.stderr @@ -1,9 +1,9 @@ -error[E0308]: mismatched types +error[E0606]: casting `&[u8; 3]` as `*const i8` is invalid --> $DIR/const-cast-wrong-type.rs:2:22 | LL | const b: *const i8 = &a as *const i8; - | ^^^^^^^^^^^^^^^ expected `u8`, found `i8` + | ^^^^^^^^^^^^^^^ error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0606`. From 9f089e080c47bc282aa98f1e8c72ff44076afbb9 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 27 Mar 2025 09:33:02 +1100 Subject: [PATCH 069/606] Add `{ast,hir,thir}::PatKind::Missing` variants. "Missing" patterns are possible in bare fn types (`fn f(u32)`) and similar places. Currently these are represented in the AST with `ast::PatKind::Ident` with no `by_ref`, no `mut`, an empty ident, and no sub-pattern. This flows through to `{hir,thir}::PatKind::Binding` for HIR and THIR. This is a bit nasty. It's very non-obvious, and easy to forget to check for the exceptional empty identifier case. This commit adds a new variant, `PatKind::Missing`, to do it properly. The process I followed: - Add a `Missing` variant to `{ast,hir,thir}::PatKind`. - Chang `parse_param_general` to produce `ast::PatKind::Missing` instead of `ast::PatKind::Missing`. - Look through `kw::Empty` occurrences to find functions where an existing empty ident check needs replacing with a `PatKind::Missing` check: `print_param`, `check_trait_item`, `is_named_param`. - Add a `PatKind::Missing => unreachable!(),` arm to every exhaustive match identified by the compiler. - Find which arms are actually reachable by running the test suite, changing them to something appropriate, usually by looking at what would happen to a `PatKind::Ident`/`PatKind::Binding` with no ref, no `mut`, an empty ident, and no subpattern. Quite a few of the `unreachable!()` arms were never reached. This makes sense because `PatKind::Missing` can't happen in every pattern, only in places like bare fn tys and trait fn decls. I also tried an alternative approach: modifying `ast::Param::pat` to hold an `Option>` instead of a `P`, but that quickly turned into a very large and painful change. Adding `PatKind::Missing` is much easier. --- compiler/rustc_ast/src/ast.rs | 8 +++++- compiler/rustc_ast/src/mut_visit.rs | 2 +- compiler/rustc_ast/src/visit.rs | 2 +- compiler/rustc_ast_lowering/src/lib.rs | 3 ++- compiler/rustc_ast_lowering/src/pat.rs | 1 + .../rustc_ast_passes/src/ast_validation.rs | 2 +- compiler/rustc_ast_pretty/src/pprust/state.rs | 11 +++----- compiler/rustc_hir/src/hir.rs | 6 ++++- compiler/rustc_hir/src/intravisit.rs | 2 +- .../rustc_hir_analysis/src/check/region.rs | 1 + compiler/rustc_hir_pretty/src/lib.rs | 1 + compiler/rustc_hir_typeck/src/expr.rs | 3 ++- .../rustc_hir_typeck/src/expr_use_visitor.rs | 2 ++ compiler/rustc_hir_typeck/src/pat.rs | 11 +++++--- compiler/rustc_lint/src/builtin.rs | 26 +++++++++---------- compiler/rustc_lint/src/unused.rs | 3 ++- compiler/rustc_middle/src/thir.rs | 3 +++ compiler/rustc_middle/src/thir/visit.rs | 3 ++- .../src/builder/matches/match_pair.rs | 2 +- .../src/builder/matches/mod.rs | 1 + .../rustc_mir_build/src/check_unsafety.rs | 1 + .../rustc_mir_build/src/thir/pattern/mod.rs | 2 ++ compiler/rustc_mir_build/src/thir/print.rs | 1 + compiler/rustc_parse/src/parser/item.rs | 4 +-- compiler/rustc_passes/src/input_stats.rs | 2 ++ compiler/rustc_pattern_analysis/src/rustc.rs | 2 +- src/librustdoc/clean/utils.rs | 1 + .../clippy_lints/src/equatable_if_let.rs | 1 + .../src/matches/match_same_arms.rs | 1 + .../clippy_lints/src/matches/single_match.rs | 1 + .../clippy_lints/src/unnested_or_patterns.rs | 1 + .../clippy/clippy_lints/src/utils/author.rs | 1 + .../clippy/clippy_utils/src/ast_utils/mod.rs | 1 + .../clippy/clippy_utils/src/hir_utils.rs | 1 + src/tools/clippy/clippy_utils/src/lib.rs | 1 + src/tools/rustfmt/src/items.rs | 6 +---- src/tools/rustfmt/src/patterns.rs | 2 ++ tests/ui/macros/stringify.rs | 2 ++ tests/ui/unpretty/expanded-exhaustive.rs | 5 ++++ tests/ui/unpretty/expanded-exhaustive.stdout | 3 +++ 40 files changed, 86 insertions(+), 46 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 064f05ef1f3e..944ae65ffc67 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -563,6 +563,7 @@ impl Pat { /// This is intended for use by diagnostics. pub fn to_ty(&self) -> Option> { let kind = match &self.kind { + PatKind::Missing => unreachable!(), // In a type expression `_` is an inference variable. PatKind::Wild => TyKind::Infer, // An IDENT pattern with no binding mode would be valid as path to a type. E.g. `u32`. @@ -625,7 +626,8 @@ impl Pat { | PatKind::Guard(s, _) => s.walk(it), // These patterns do not contain subpatterns, skip. - PatKind::Wild + PatKind::Missing + | PatKind::Wild | PatKind::Rest | PatKind::Never | PatKind::Expr(_) @@ -676,6 +678,7 @@ impl Pat { /// Return a name suitable for diagnostics. pub fn descr(&self) -> Option { match &self.kind { + PatKind::Missing => unreachable!(), PatKind::Wild => Some("_".to_string()), PatKind::Ident(BindingMode::NONE, ident, None) => Some(format!("{ident}")), PatKind::Ref(pat, mutbl) => pat.descr().map(|d| format!("&{}{d}", mutbl.prefix_str())), @@ -769,6 +772,9 @@ pub enum RangeSyntax { // Adding a new variant? Please update `test_pat` in `tests/ui/macros/stringify.rs`. #[derive(Clone, Encodable, Decodable, Debug)] pub enum PatKind { + /// A missing pattern, e.g. for an anonymous param in a bare fn like `fn f(u32)`. + Missing, + /// Represents a wildcard pattern (`_`). Wild, diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 274fe312f7fa..8c6ddf2a69c9 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1572,7 +1572,7 @@ pub fn walk_pat(vis: &mut T, pat: &mut P) { vis.visit_id(id); match kind { PatKind::Err(_guar) => {} - PatKind::Wild | PatKind::Rest | PatKind::Never => {} + PatKind::Missing | PatKind::Wild | PatKind::Rest | PatKind::Never => {} PatKind::Ident(_binding_mode, ident, sub) => { vis.visit_ident(ident); visit_opt(sub, |sub| vis.visit_pat(sub)); diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 2716601ca4f9..3d78f65f634b 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -727,7 +727,7 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) -> V::Res try_visit!(visitor.visit_pat(subpattern)); try_visit!(visitor.visit_expr(guard_condition)); } - PatKind::Wild | PatKind::Rest | PatKind::Never => {} + PatKind::Missing | PatKind::Wild | PatKind::Rest | PatKind::Never => {} PatKind::Err(_guar) => {} PatKind::Tuple(elems) | PatKind::Slice(elems) | PatKind::Or(elems) => { walk_list!(visitor, visit_pat, elems); diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index ced9064fd9f4..4041e5d092aa 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1495,6 +1495,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Option] { self.arena.alloc_from_iter(decl.inputs.iter().map(|param| match param.pat.kind { + PatKind::Missing => None, PatKind::Ident(_, ident, _) => { if ident.name != kw::Empty { Some(self.lower_ident(ident)) @@ -1506,7 +1507,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { _ => { self.dcx().span_delayed_bug( param.pat.span, - "non-ident/wild param pat must trigger an error", + "non-missing/ident/wild param pat must trigger an error", ); None } diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index 07cc64a1358e..f94d788a9b0e 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -26,6 +26,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let pat_hir_id = self.lower_node_id(pattern.id); let node = loop { match &pattern.kind { + PatKind::Missing => break hir::PatKind::Missing, PatKind::Wild => break hir::PatKind::Wild, PatKind::Never => break hir::PatKind::Never, PatKind::Ident(binding_mode, ident, sub) => { diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index a1487ca74be8..ab6d4644f7e9 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -239,7 +239,7 @@ impl<'a> AstValidator<'a> { fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, Option, bool)) { for Param { pat, .. } in &decl.inputs { match pat.kind { - PatKind::Ident(BindingMode::NONE, _, None) | PatKind::Wild => {} + PatKind::Missing | PatKind::Ident(BindingMode::NONE, _, None) | PatKind::Wild => {} PatKind::Ident(BindingMode::MUT, ident, None) => { report_err(pat.span, Some(ident), true) } diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index cdb181794498..f9e17fb0539d 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1622,9 +1622,9 @@ impl<'a> State<'a> { fn print_pat(&mut self, pat: &ast::Pat) { self.maybe_print_comment(pat.span.lo()); self.ann.pre(self, AnnNode::Pat(pat)); - /* Pat isn't normalized, but the beauty of it - is that it doesn't matter */ + /* Pat isn't normalized, but the beauty of it is that it doesn't matter */ match &pat.kind { + PatKind::Missing => unreachable!(), PatKind::Wild => self.word("_"), PatKind::Never => self.word("!"), PatKind::Ident(BindingMode(by_ref, mutbl), ident, sub) => { @@ -1946,12 +1946,7 @@ impl<'a> State<'a> { if let Some(eself) = input.to_self() { self.print_explicit_self(&eself); } else { - let invalid = if let PatKind::Ident(_, ident, _) = input.pat.kind { - ident.name == kw::Empty - } else { - false - }; - if !invalid { + if !matches!(input.pat.kind, PatKind::Missing) { self.print_pat(&input.pat); self.word(":"); self.space(); diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 751c379b21a6..08e37accb8a3 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1516,6 +1516,7 @@ impl<'hir> Pat<'hir> { use PatKind::*; match self.kind { + Missing => unreachable!(), Wild | Never | Expr(_) | Range(..) | Binding(.., None) | Err(_) => true, Box(s) | Deref(s) | Ref(s, _) | Binding(.., Some(s)) | Guard(s, _) => s.walk_short_(it), Struct(_, fields, _) => fields.iter().all(|field| field.pat.walk_short_(it)), @@ -1543,7 +1544,7 @@ impl<'hir> Pat<'hir> { use PatKind::*; match self.kind { - Wild | Never | Expr(_) | Range(..) | Binding(.., None) | Err(_) => {} + Missing | Wild | Never | Expr(_) | Range(..) | Binding(.., None) | Err(_) => {} Box(s) | Deref(s) | Ref(s, _) | Binding(.., Some(s)) | Guard(s, _) => s.walk_(it), Struct(_, fields, _) => fields.iter().for_each(|field| field.pat.walk_(it)), TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().for_each(|p| p.walk_(it)), @@ -1681,6 +1682,9 @@ pub enum TyPatKind<'hir> { #[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum PatKind<'hir> { + /// A missing pattern, e.g. for an anonymous param in a bare fn like `fn f(u32)`. + Missing, + /// Represents a wildcard pattern (i.e., `_`). Wild, diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 506358341b50..ea3f396761b1 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -744,7 +744,7 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) -> V: visit_opt!(visitor, visit_pat_expr, lower_bound); visit_opt!(visitor, visit_pat_expr, upper_bound); } - PatKind::Never | PatKind::Wild | PatKind::Err(_) => (), + PatKind::Missing | PatKind::Never | PatKind::Wild | PatKind::Err(_) => (), PatKind::Slice(prepatterns, ref slice_pattern, postpatterns) => { walk_list!(visitor, visit_pat, prepatterns); visit_opt!(visitor, visit_pat, slice_pattern); diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index 255f5fee52a8..d63fef8c0ef2 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -701,6 +701,7 @@ fn resolve_local<'tcx>( PatKind::Ref(_, _) | PatKind::Binding(hir::BindingMode(hir::ByRef::No, _), ..) + | PatKind::Missing | PatKind::Wild | PatKind::Never | PatKind::Expr(_) diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index ddaca89ccf82..a4961fc2c850 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1875,6 +1875,7 @@ impl<'a> State<'a> { // Pat isn't normalized, but the beauty of it // is that it doesn't matter match pat.kind { + PatKind::Missing => unreachable!(), PatKind::Wild => self.word("_"), PatKind::Never => self.word("!"), PatKind::Binding(BindingMode(by_ref, mutbl), _, ident, sub) => { diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index a75f6f4caac9..0ed03a03c1b4 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -482,7 +482,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // All of these constitute a read, or match on something that isn't `!`, // which would require a `NeverToAny` coercion. - hir::PatKind::Binding(_, _, _, _) + hir::PatKind::Missing + | hir::PatKind::Binding(_, _, _, _) | hir::PatKind::Struct(_, _, _) | hir::PatKind::TupleStruct(_, _, _) | hir::PatKind::Tuple(_, _) diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index c71a5ea8b976..d50f235ad4d1 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -611,6 +611,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx for pat in pats { self.cat_pattern(discr_place.clone(), pat, &mut |place, pat| { match &pat.kind { + PatKind::Missing => unreachable!(), PatKind::Binding(.., opt_sub_pat) => { // If the opt_sub_pat is None, then the binding does not count as // a wildcard for the purpose of borrowing discr. @@ -1884,6 +1885,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx | PatKind::Expr(..) | PatKind::Range(..) | PatKind::Never + | PatKind::Missing | PatKind::Wild | PatKind::Err(_) => { // always ok diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index f1f956779c94..0d4ecbc867b7 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -341,7 +341,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let ty = match pat.kind { - PatKind::Wild | PatKind::Err(_) => expected, + PatKind::Missing | PatKind::Wild | PatKind::Err(_) => expected, // We allow any type here; we ensure that the type is uninhabited during match checking. PatKind::Never => expected, PatKind::Expr(PatExpr { kind: PatExprKind::Path(qpath), hir_id, span }) => { @@ -505,9 +505,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }, // Ref patterns are complicated, we handle them in `check_pat_ref`. - PatKind::Ref(..) => AdjustMode::Pass, + PatKind::Ref(..) + // No need to do anything on a missing pattern. + | PatKind::Missing // A `_` pattern works with any expected type, so there's no need to do anything. - PatKind::Wild + | PatKind::Wild // A malformed pattern doesn't have an expected type, so let's just accept any type. | PatKind::Err(_) // Bindings also work with whatever the expected type is, @@ -1037,7 +1039,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | PatKind::Tuple(..) | PatKind::Slice(..) => "binding", - PatKind::Wild + PatKind::Missing + | PatKind::Wild | PatKind::Never | PatKind::Binding(..) | PatKind::Box(..) diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 9dccd4a0552c..0b5cdf99de5a 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -778,21 +778,19 @@ impl EarlyLintPass for AnonymousParameters { } if let ast::AssocItemKind::Fn(box Fn { ref sig, .. }) = it.kind { for arg in sig.decl.inputs.iter() { - if let ast::PatKind::Ident(_, ident, None) = arg.pat.kind { - if ident.name == kw::Empty { - let ty_snip = cx.sess().source_map().span_to_snippet(arg.ty.span); + if let ast::PatKind::Missing = arg.pat.kind { + let ty_snip = cx.sess().source_map().span_to_snippet(arg.ty.span); - let (ty_snip, appl) = if let Ok(ref snip) = ty_snip { - (snip.as_str(), Applicability::MachineApplicable) - } else { - ("", Applicability::HasPlaceholders) - }; - cx.emit_span_lint( - ANONYMOUS_PARAMETERS, - arg.pat.span, - BuiltinAnonymousParams { suggestion: (arg.pat.span, appl), ty_snip }, - ); - } + let (ty_snip, appl) = if let Ok(ref snip) = ty_snip { + (snip.as_str(), Applicability::MachineApplicable) + } else { + ("", Applicability::HasPlaceholders) + }; + cx.emit_span_lint( + ANONYMOUS_PARAMETERS, + arg.pat.span, + BuiltinAnonymousParams { suggestion: (arg.pat.span, appl), ty_snip }, + ); } } } diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 7b43aac90c74..806bca78f787 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -1201,7 +1201,8 @@ impl EarlyLintPass for UnusedParens { // Do not lint on `(..)` as that will result in the other arms being useless. Paren(_) // The other cases do not contain sub-patterns. - | Wild | Never | Rest | Expr(..) | MacCall(..) | Range(..) | Ident(.., None) | Path(..) | Err(_) => {}, + | Missing | Wild | Never | Rest | Expr(..) | MacCall(..) | Range(..) | Ident(.., None) + | Path(..) | Err(_) => {}, // These are list-like patterns; parens can always be removed. TupleStruct(_, _, ps) | Tuple(ps) | Slice(ps) | Or(ps) => for p in ps { self.check_unused_parens_pat(cx, p, false, false, keep_space); diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 6783bbf8bf42..413717e45ebf 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -747,6 +747,9 @@ pub struct Ascription<'tcx> { #[derive(Clone, Debug, HashStable, TypeVisitable)] pub enum PatKind<'tcx> { + /// A missing pattern, e.g. for an anonymous param in a bare fn like `fn f(u32)`. + Missing, + /// A wildcard pattern: `_`. Wild, diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index 7d62ab7970d0..f3da2a5cc8e4 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -250,7 +250,8 @@ pub(crate) fn for_each_immediate_subpat<'a, 'tcx>( mut callback: impl FnMut(&'a Pat<'tcx>), ) { match &pat.kind { - PatKind::Wild + PatKind::Missing + | PatKind::Wild | PatKind::Binding { subpattern: None, .. } | PatKind::Constant { value: _ } | PatKind::Range(_) diff --git a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs index 29d400a957b4..11672163b658 100644 --- a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs +++ b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs @@ -118,7 +118,7 @@ impl<'tcx> MatchPairTree<'tcx> { let place = place_builder.try_to_place(cx); let mut subpairs = Vec::new(); let test_case = match pattern.kind { - PatKind::Wild | PatKind::Error(_) => None, + PatKind::Missing | PatKind::Wild | PatKind::Error(_) => None, PatKind::Or { ref pats } => Some(TestCase::Or { pats: pats.iter().map(|pat| FlatPat::new(place_builder.clone(), pat, cx)).collect(), diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs index 3acf2a6a2a61..977d4f3e931b 100644 --- a/compiler/rustc_mir_build/src/builder/matches/mod.rs +++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs @@ -920,6 +920,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { PatKind::Constant { .. } | PatKind::Range { .. } + | PatKind::Missing | PatKind::Wild | PatKind::Never | PatKind::Error(_) => {} diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 7f2e7d5ca838..9572dfc52dac 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -313,6 +313,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { fn visit_pat(&mut self, pat: &'a Pat<'tcx>) { if self.in_union_destructure { match pat.kind { + PatKind::Missing => unreachable!(), // binding to a variable allows getting stuff out of variable PatKind::Binding { .. } // match is conditional on having this value diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 4bfeab44bf4b..f36a895849a1 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -290,6 +290,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { let mut span = pat.span; let kind = match pat.kind { + hir::PatKind::Missing => PatKind::Missing, + hir::PatKind::Wild => PatKind::Wild, hir::PatKind::Never => PatKind::Never, diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs index 16cef0ec3acb..ac71bb845a88 100644 --- a/compiler/rustc_mir_build/src/thir/print.rs +++ b/compiler/rustc_mir_build/src/thir/print.rs @@ -664,6 +664,7 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> { print_indented!(self, "kind: PatKind {", depth_lvl); match pat_kind { + PatKind::Missing => unreachable!(), PatKind::Wild => { print_indented!(self, "Wild", depth_lvl + 1); } diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index aad185783755..0f5d8d9fbedd 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -2941,9 +2941,7 @@ impl<'a> Parser<'a> { } match ty { Ok(ty) => { - let ident = Ident::new(kw::Empty, this.prev_token.span); - let bm = BindingMode::NONE; - let pat = this.mk_pat_ident(ty.span, bm, ident); + let pat = this.mk_pat(ty.span, PatKind::Missing); (pat, ty) } // If this is a C-variadic argument and we hit an error, return the error. diff --git a/compiler/rustc_passes/src/input_stats.rs b/compiler/rustc_passes/src/input_stats.rs index 1278e98afcf6..718154481722 100644 --- a/compiler/rustc_passes/src/input_stats.rs +++ b/compiler/rustc_passes/src/input_stats.rs @@ -295,6 +295,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { record_variants!( (self, p, p.kind, Some(p.hir_id), hir, Pat, PatKind), [ + Missing, Wild, Binding, Struct, @@ -597,6 +598,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { record_variants!( (self, p, p.kind, None, ast, Pat, PatKind), [ + Missing, Wild, Ident, Struct, diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index a25a80cd45f7..e81527340524 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -457,7 +457,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { PatKind::AscribeUserType { subpattern, .. } | PatKind::ExpandedConstant { subpattern, .. } => return self.lower_pat(subpattern), PatKind::Binding { subpattern: Some(subpat), .. } => return self.lower_pat(subpat), - PatKind::Binding { subpattern: None, .. } | PatKind::Wild => { + PatKind::Missing | PatKind::Binding { subpattern: None, .. } | PatKind::Wild => { ctor = Wildcard; fields = vec![]; arity = 0; diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index f81db58950cb..afcca81a485f 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -304,6 +304,7 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol { Symbol::intern(&match &p.kind { // FIXME(never_patterns): does this make sense? + PatKind::Missing => unreachable!(), PatKind::Wild | PatKind::Err(_) | PatKind::Never diff --git a/src/tools/clippy/clippy_lints/src/equatable_if_let.rs b/src/tools/clippy/clippy_lints/src/equatable_if_let.rs index cd9ab2764ac4..3afb687040f4 100644 --- a/src/tools/clippy/clippy_lints/src/equatable_if_let.rs +++ b/src/tools/clippy/clippy_lints/src/equatable_if_let.rs @@ -45,6 +45,7 @@ fn unary_pattern(pat: &Pat<'_>) -> bool { pats.iter().all(unary_pattern) } match &pat.kind { + PatKind::Missing => unreachable!(), PatKind::Slice(_, _, _) | PatKind::Range(_, _, _) | PatKind::Binding(..) diff --git a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs index 250f17fa9025..a21597ffb93d 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs @@ -253,6 +253,7 @@ fn iter_matching_struct_fields<'a>( impl<'a> NormalizedPat<'a> { fn from_pat(cx: &LateContext<'_>, arena: &'a DroplessArena, pat: &'a Pat<'_>) -> Self { match pat.kind { + PatKind::Missing => unreachable!(), PatKind::Wild | PatKind::Binding(.., None) => Self::Wild, PatKind::Binding(.., Some(pat)) | PatKind::Box(pat) diff --git a/src/tools/clippy/clippy_lints/src/matches/single_match.rs b/src/tools/clippy/clippy_lints/src/matches/single_match.rs index 56fbd626eefc..836c46240ce7 100644 --- a/src/tools/clippy/clippy_lints/src/matches/single_match.rs +++ b/src/tools/clippy/clippy_lints/src/matches/single_match.rs @@ -406,6 +406,7 @@ impl<'a> PatState<'a> { pats.iter().map(|p| p.pat), ), + PatKind::Missing => unreachable!(), PatKind::Wild | PatKind::Binding(_, _, _, None) | PatKind::Expr(_) diff --git a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs index f43715d6752e..8966e6851ac2 100644 --- a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs +++ b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs @@ -224,6 +224,7 @@ fn transform_with_focus_on_idx(alternatives: &mut ThinVec>, focus_idx: us // We're trying to find whatever kind (~"constructor") we found in `alternatives[start..]`. let changed = match &mut focus_kind { + Missing => unreachable!(), // These pattern forms are "leafs" and do not have sub-patterns. // Therefore they are not some form of constructor `C`, // with which a pattern `C(p_0)` may be formed, diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index 4309cd2c9abd..b7dcd2ffb0ee 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -676,6 +676,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { } match pat.value.kind { + PatKind::Missing => unreachable!(), PatKind::Wild => kind!("Wild"), PatKind::Never => kind!("Never"), PatKind::Binding(ann, _, name, sub) => { diff --git a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs index 6023ae9cc7b1..ed99f966d2b7 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs @@ -33,6 +33,7 @@ pub fn eq_id(l: Ident, r: Ident) -> bool { pub fn eq_pat(l: &Pat, r: &Pat) -> bool { use PatKind::*; match (&l.kind, &r.kind) { + (Missing, _) | (_, Missing) => unreachable!(), (Paren(l), _) => eq_pat(l, r), (_, Paren(r)) => eq_pat(l, r), (Wild, Wild) | (Rest, Rest) => true, diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index 9938e64d2426..b813cd361ed8 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -1124,6 +1124,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { pub fn hash_pat(&mut self, pat: &Pat<'_>) { std::mem::discriminant(&pat.kind).hash(&mut self.s); match pat.kind { + PatKind::Missing => unreachable!(), PatKind::Binding(BindingMode(by_ref, mutability), _, _, pat) => { std::mem::discriminant(&by_ref).hash(&mut self.s); std::mem::discriminant(&mutability).hash(&mut self.s); diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 1307ff79bc5d..bdcbe1437d0e 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -1857,6 +1857,7 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool { } match pat.kind { + PatKind::Missing => unreachable!(), PatKind::Wild | PatKind::Never => false, // If `!` typechecked then the type is empty, so not refutable. PatKind::Binding(_, _, _, pat) => pat.is_some_and(|pat| is_refutable(cx, pat)), PatKind::Box(pat) | PatKind::Ref(pat, _) => is_refutable(cx, pat), diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index 3fb3284e3d7f..81ff6327a4fc 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -2433,11 +2433,7 @@ pub(crate) fn span_hi_for_param(context: &RewriteContext<'_>, param: &ast::Param } pub(crate) fn is_named_param(param: &ast::Param) -> bool { - if let ast::PatKind::Ident(_, ident, _) = param.pat.kind { - ident.name != symbol::kw::Empty - } else { - true - } + !matches!(param.pat.kind, ast::PatKind::Missing) } #[derive(Copy, Clone, Debug, PartialEq, Eq)] diff --git a/src/tools/rustfmt/src/patterns.rs b/src/tools/rustfmt/src/patterns.rs index bafed41e39f4..8ec3de286dcb 100644 --- a/src/tools/rustfmt/src/patterns.rs +++ b/src/tools/rustfmt/src/patterns.rs @@ -42,6 +42,7 @@ pub(crate) fn is_short_pattern( fn is_short_pattern_inner(context: &RewriteContext<'_>, pat: &ast::Pat) -> bool { match &pat.kind { + ast::PatKind::Missing => unreachable!(), ast::PatKind::Rest | ast::PatKind::Never | ast::PatKind::Wild | ast::PatKind::Err(_) => { true } @@ -100,6 +101,7 @@ impl Rewrite for Pat { fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult { match self.kind { + PatKind::Missing => unreachable!(), PatKind::Or(ref pats) => { let pat_strs = pats .iter() diff --git a/tests/ui/macros/stringify.rs b/tests/ui/macros/stringify.rs index 40033f546d30..3490d3efc599 100644 --- a/tests/ui/macros/stringify.rs +++ b/tests/ui/macros/stringify.rs @@ -515,6 +515,8 @@ fn test_meta() { #[test] fn test_pat() { + // PatKind::Missing: untestable in isolation. + // PatKind::Wild c1!(pat, [ _ ], "_"); diff --git a/tests/ui/unpretty/expanded-exhaustive.rs b/tests/ui/unpretty/expanded-exhaustive.rs index 31af323ecdab..4d1f12e34900 100644 --- a/tests/ui/unpretty/expanded-exhaustive.rs +++ b/tests/ui/unpretty/expanded-exhaustive.rs @@ -574,6 +574,11 @@ mod items { } mod patterns { + /// PatKind::Missing + fn pat_missing() { + let _: fn(u32, T, &str); + } + /// PatKind::Wild fn pat_wild() { let _; diff --git a/tests/ui/unpretty/expanded-exhaustive.stdout b/tests/ui/unpretty/expanded-exhaustive.stdout index 19ae66f7a07a..d8da941a3407 100644 --- a/tests/ui/unpretty/expanded-exhaustive.stdout +++ b/tests/ui/unpretty/expanded-exhaustive.stdout @@ -361,6 +361,7 @@ mod expressions { + { builtin # offset_of(T, field) }; @@ -517,6 +518,8 @@ mod items { } } mod patterns { + /// PatKind::Missing + fn pat_missing() { let _: fn(u32, T, &str); } /// PatKind::Wild fn pat_wild() { let _; } /// PatKind::Ident From 909f4492475988ba5e1b84efadacb16eb7d7ff0e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 27 Mar 2025 17:00:27 +1100 Subject: [PATCH 070/606] Remove `kw::Extra` checks that are no longer necessary. Thanks to the introduction of `PatKind::Missing`. --- compiler/rustc_ast_lowering/src/lib.rs | 8 +------- compiler/rustc_passes/src/liveness.rs | 5 +---- compiler/rustc_resolve/src/late.rs | 13 ++++--------- 3 files changed, 6 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 4041e5d092aa..a3e0f9603161 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1496,13 +1496,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Option] { self.arena.alloc_from_iter(decl.inputs.iter().map(|param| match param.pat.kind { PatKind::Missing => None, - PatKind::Ident(_, ident, _) => { - if ident.name != kw::Empty { - Some(self.lower_ident(ident)) - } else { - None - } - } + PatKind::Ident(_, ident, _) => Some(self.lower_ident(ident)), PatKind::Wild => Some(Ident::new(kw::Underscore, self.lower_span(param.pat.span))), _ => { self.dcx().span_delayed_bug( diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index ed70d9ee91f5..07e3b28bcf65 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -96,7 +96,7 @@ use rustc_middle::query::Providers; use rustc_middle::span_bug; use rustc_middle::ty::{self, RootVariableMinCaptureList, Ty, TyCtxt}; use rustc_session::lint; -use rustc_span::{BytePos, Span, Symbol, kw, sym}; +use rustc_span::{BytePos, Span, Symbol, sym}; use tracing::{debug, instrument}; use self::LiveNodeKind::*; @@ -1481,9 +1481,6 @@ impl<'tcx> Liveness<'_, 'tcx> { fn should_warn(&self, var: Variable) -> Option { let name = self.ir.variable_name(var); - if name == kw::Empty { - return None; - } let name = name.as_str(); if name.as_bytes()[0] == b'_' { return None; diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 533e216ddb29..117d2ccdde38 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -3999,22 +3999,17 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.report_error(ident.span, error(ident)); } - // Record as bound if it's valid: - let ident_valid = ident.name != kw::Empty; - if ident_valid { - bindings.last_mut().unwrap().1.insert(ident); - } + // Record as bound. + bindings.last_mut().unwrap().1.insert(ident); if already_bound_or { // `Variant1(a) | Variant2(a)`, ok // Reuse definition from the first `a`. self.innermost_rib_bindings(ValueNS)[&ident] } else { + // A completely fresh binding is added to the set. let res = Res::Local(pat_id); - if ident_valid { - // A completely fresh binding add to the set if it's valid. - self.innermost_rib_bindings(ValueNS).insert(ident, res); - } + self.innermost_rib_bindings(ValueNS).insert(ident, res); res } } From 2f5aa084c8bb6e1a4b014396a44087fd65a4c1c8 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 14 Mar 2025 15:56:33 +0000 Subject: [PATCH 071/606] Avoid wrapping constant allocations in packed structs when not necessary This way LLVM will set the string merging flag if the alloc is a nul terminated string, reducing binary sizes. --- src/consts.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/consts.rs b/src/consts.rs index c514b7a428bc..474475f311f7 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -364,6 +364,7 @@ pub fn const_alloc_to_gcc<'gcc>( llvals.push(cx.const_bytes(bytes)); } + // FIXME(bjorn3) avoid wrapping in a struct when there is only a single element. cx.const_struct(&llvals, true) } From 65bf8a8866557408b9e23ce3a99ec44c29dcb625 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 28 Mar 2025 14:48:13 +0100 Subject: [PATCH 072/606] machine clock: make 'monotonic' explicit --- src/tools/miri/src/clock.rs | 30 +++++++++++++----------- src/tools/miri/src/concurrency/thread.rs | 16 ++++++------- src/tools/miri/src/lib.rs | 2 +- src/tools/miri/src/machine.rs | 8 +++---- src/tools/miri/src/shims/time.rs | 8 ++++--- 5 files changed, 34 insertions(+), 30 deletions(-) diff --git a/src/tools/miri/src/clock.rs b/src/tools/miri/src/clock.rs index c9bffc449f7f..34465e9cac60 100644 --- a/src/tools/miri/src/clock.rs +++ b/src/tools/miri/src/clock.rs @@ -62,12 +62,12 @@ impl Instant { /// A monotone clock used for `Instant` simulation. #[derive(Debug)] -pub struct Clock { - kind: ClockKind, +pub struct MonotonicClock { + kind: MonotonicClockKind, } #[derive(Debug)] -enum ClockKind { +enum MonotonicClockKind { Host { /// The "epoch" for this machine's monotone clock: /// the moment we consider to be time = 0. @@ -79,13 +79,13 @@ enum ClockKind { }, } -impl Clock { +impl MonotonicClock { /// Create a new clock based on the availability of communication with the host. pub fn new(communicate: bool) -> Self { let kind = if communicate { - ClockKind::Host { epoch: StdInstant::now() } + MonotonicClockKind::Host { epoch: StdInstant::now() } } else { - ClockKind::Virtual { nanoseconds: 0.into() } + MonotonicClockKind::Virtual { nanoseconds: 0.into() } }; Self { kind } @@ -94,10 +94,10 @@ impl Clock { /// Let the time pass for a small interval. pub fn tick(&self) { match &self.kind { - ClockKind::Host { .. } => { + MonotonicClockKind::Host { .. } => { // Time will pass without us doing anything. } - ClockKind::Virtual { nanoseconds } => { + MonotonicClockKind::Virtual { nanoseconds } => { nanoseconds.update(|x| x + NANOSECONDS_PER_BASIC_BLOCK); } } @@ -106,8 +106,8 @@ impl Clock { /// Sleep for the desired duration. pub fn sleep(&self, duration: Duration) { match &self.kind { - ClockKind::Host { .. } => std::thread::sleep(duration), - ClockKind::Virtual { nanoseconds } => { + MonotonicClockKind::Host { .. } => std::thread::sleep(duration), + MonotonicClockKind::Virtual { nanoseconds } => { // Just pretend that we have slept for some time. let nanos: u128 = duration.as_nanos(); nanoseconds.update(|x| { @@ -121,15 +121,17 @@ impl Clock { /// Return the `epoch` instant (time = 0), to convert between monotone instants and absolute durations. pub fn epoch(&self) -> Instant { match &self.kind { - ClockKind::Host { epoch } => Instant { kind: InstantKind::Host(*epoch) }, - ClockKind::Virtual { .. } => Instant { kind: InstantKind::Virtual { nanoseconds: 0 } }, + MonotonicClockKind::Host { epoch } => Instant { kind: InstantKind::Host(*epoch) }, + MonotonicClockKind::Virtual { .. } => + Instant { kind: InstantKind::Virtual { nanoseconds: 0 } }, } } pub fn now(&self) -> Instant { match &self.kind { - ClockKind::Host { .. } => Instant { kind: InstantKind::Host(StdInstant::now()) }, - ClockKind::Virtual { nanoseconds } => + MonotonicClockKind::Host { .. } => + Instant { kind: InstantKind::Host(StdInstant::now()) }, + MonotonicClockKind::Virtual { nanoseconds } => Instant { kind: InstantKind::Virtual { nanoseconds: nanoseconds.get() } }, } } diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs index 94629964ea60..72fa918e8e51 100644 --- a/src/tools/miri/src/concurrency/thread.rs +++ b/src/tools/miri/src/concurrency/thread.rs @@ -347,7 +347,7 @@ enum Timeout { impl Timeout { /// How long do we have to wait from now until the specified time? - fn get_wait_time(&self, clock: &Clock) -> Duration { + fn get_wait_time(&self, clock: &MonotonicClock) -> Duration { match self { Timeout::Monotonic(instant) => instant.duration_since(clock.now()), Timeout::RealTime(time) => @@ -683,7 +683,7 @@ impl<'tcx> ThreadManager<'tcx> { } /// Get the wait time for the next timeout, or `None` if no timeout is pending. - fn next_callback_wait_time(&self, clock: &Clock) -> Option { + fn next_callback_wait_time(&self, clock: &MonotonicClock) -> Option { self.threads .iter() .filter_map(|t| { @@ -702,7 +702,7 @@ impl<'tcx> ThreadManager<'tcx> { /// used in stateless model checkers such as Loom: run the active thread as /// long as we can and switch only when we have to (the active thread was /// blocked, terminated, or has explicitly asked to be preempted). - fn schedule(&mut self, clock: &Clock) -> InterpResult<'tcx, SchedulingAction> { + fn schedule(&mut self, clock: &MonotonicClock) -> InterpResult<'tcx, SchedulingAction> { // This thread and the program can keep going. if self.threads[self.active_thread].state.is_enabled() && !self.yield_active_thread { // The currently active thread is still enabled, just continue with it. @@ -772,7 +772,7 @@ trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> { for (id, thread) in this.machine.threads.threads.iter_enumerated_mut() { match &thread.state { ThreadState::Blocked { timeout: Some(timeout), .. } - if timeout.get_wait_time(&this.machine.clock) == Duration::ZERO => + if timeout.get_wait_time(&this.machine.monotonic_clock) == Duration::ZERO => { let old_state = mem::replace(&mut thread.state, ThreadState::Enabled); let ThreadState::Blocked { callback, .. } = old_state else { unreachable!() }; @@ -1006,8 +1006,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } TimeoutClock::Monotonic => Timeout::Monotonic(match anchor { - TimeoutAnchor::Absolute => this.machine.clock.epoch(), - TimeoutAnchor::Relative => this.machine.clock.now(), + TimeoutAnchor::Absolute => this.machine.monotonic_clock.epoch(), + TimeoutAnchor::Relative => this.machine.monotonic_clock.now(), }), }; anchor.add_lossy(duration) @@ -1152,7 +1152,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.machine.handle_abnormal_termination(); throw_machine_stop!(TerminationInfo::Interrupted); } - match this.machine.threads.schedule(&this.machine.clock)? { + match this.machine.threads.schedule(&this.machine.monotonic_clock)? { SchedulingAction::ExecuteStep => { if !this.step()? { // See if this thread can do something else. @@ -1167,7 +1167,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.run_timeout_callback()?; } SchedulingAction::Sleep(duration) => { - this.machine.clock.sleep(duration); + this.machine.monotonic_clock.sleep(duration); } } } diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index 03f76cfa6524..5921ba866390 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -121,7 +121,7 @@ pub use crate::borrow_tracker::stacked_borrows::{ }; pub use crate::borrow_tracker::tree_borrows::{EvalContextExt as _, Tree}; pub use crate::borrow_tracker::{BorTag, BorrowTrackerMethod, EvalContextExt as _, RetagFields}; -pub use crate::clock::{Clock, Instant}; +pub use crate::clock::{Instant, MonotonicClock}; pub use crate::concurrency::cpu_affinity::MAX_CPUS; pub use crate::concurrency::data_race::{ AtomicFenceOrd, AtomicReadOrd, AtomicRwOrd, AtomicWriteOrd, EvalContextExt as _, diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index bd901a4ed19e..3de20f92afa4 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -486,7 +486,7 @@ pub struct MiriMachine<'tcx> { pub(crate) epoll_interests: shims::EpollInterestTable, /// This machine's monotone clock. - pub(crate) clock: Clock, + pub(crate) monotonic_clock: MonotonicClock, /// The set of threads. pub(crate) threads: ThreadManager<'tcx>, @@ -710,7 +710,7 @@ impl<'tcx> MiriMachine<'tcx> { preemption_rate: config.preemption_rate, report_progress: config.report_progress, basic_block_count: 0, - clock: Clock::new(config.isolated_op == IsolatedOp::Allow), + monotonic_clock: MonotonicClock::new(config.isolated_op == IsolatedOp::Allow), #[cfg(unix)] native_lib: config.native_lib.as_ref().map(|lib_file_path| { let host_triple = rustc_session::config::host_tuple(); @@ -892,7 +892,7 @@ impl VisitProvenance for MiriMachine<'_> { tcx: _, isolated_op: _, validation: _, - clock: _, + monotonic_clock: _, layouts: _, static_roots: _, profiler: _, @@ -1563,7 +1563,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { ecx.maybe_preempt_active_thread(); // Make sure some time passes. - ecx.machine.clock.tick(); + ecx.machine.monotonic_clock.tick(); interp_ok(()) } diff --git a/src/tools/miri/src/shims/time.rs b/src/tools/miri/src/shims/time.rs index 64b3ce6b4e49..d7c445b47cb0 100644 --- a/src/tools/miri/src/shims/time.rs +++ b/src/tools/miri/src/shims/time.rs @@ -79,7 +79,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.check_no_isolation("`clock_gettime` with `REALTIME` clocks")?; system_time_to_duration(&SystemTime::now())? } else if relative_clocks.contains(&clk_id) { - this.machine.clock.now().duration_since(this.machine.clock.epoch()) + this.machine.monotonic_clock.now().duration_since(this.machine.monotonic_clock.epoch()) } else { return this.set_last_error_and_return_i32(LibcError("EINVAL")); }; @@ -248,7 +248,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // QueryPerformanceCounter uses a hardware counter as its basis. // Miri will emulate a counter with a resolution of 1 nanosecond. - let duration = this.machine.clock.now().duration_since(this.machine.clock.epoch()); + let duration = + this.machine.monotonic_clock.now().duration_since(this.machine.monotonic_clock.epoch()); let qpc = i64::try_from(duration.as_nanos()).map_err(|_| { err_unsup_format!("programs running longer than 2^63 nanoseconds are not supported") })?; @@ -287,7 +288,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // This returns a u64, with time units determined dynamically by `mach_timebase_info`. // We return plain nanoseconds. - let duration = this.machine.clock.now().duration_since(this.machine.clock.epoch()); + let duration = + this.machine.monotonic_clock.now().duration_since(this.machine.monotonic_clock.epoch()); let res = u64::try_from(duration.as_nanos()).map_err(|_| { err_unsup_format!("programs running longer than 2^64 nanoseconds are not supported") })?; From 6a915967f1d0033ce9e1a920885829d9ffe32716 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 29 Mar 2025 00:53:12 -0700 Subject: [PATCH 073/606] Promise `array::from_fn` in generated in order of increasing indices --- library/core/src/array/mod.rs | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 28329bb09084..efa7bed7c8e1 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -55,12 +55,16 @@ pub fn repeat(val: T) -> [T; N] { from_trusted_iterator(repeat_n(val, N)) } -/// Creates an array of type [T; N], where each element `T` is the returned value from `cb` -/// using that element's index. +/// Creates an array where each element is produced by calling `f` with +/// that element's index while walking forward through the array. /// -/// # Arguments +/// This is essentially the same as writing +/// ```text +/// [f(0), f(1), f(2), …, f(N - 2), f(N - 1)] +/// ``` +/// and is similar to `(0..i).map(f)`, just for arrays not iterators. /// -/// * `cb`: Callback where the passed argument is the current array index. +/// If `N == 0`, this produces an empty array without ever calling `f`. /// /// # Example /// @@ -82,13 +86,30 @@ pub fn repeat(val: T) -> [T; N] { /// // indexes are: 0 1 2 3 4 /// assert_eq!(bool_arr, [true, false, true, false, true]); /// ``` +/// +/// You can also capture things, for example to create an array full of clones +/// where you can't just use `[item; N]` because it's not `Copy`: +/// ``` +/// # // TBH `array::repeat` would be better for this, but it's not stable yet. +/// let my_string = String::from("Hello"); +/// let clones: [String; 42] = std::array::from_fn(|_| my_string.clone()); +/// assert!(clones.iter().all(|x| *x == my_string)); +/// ``` +/// +/// The array is generated in ascending index order, starting from the front +/// and going towards the back, so you can use closures with mutable state: +/// ``` +/// let mut state = 1; +/// let a = std::array::from_fn(|_| { let x = state; state *= 2; x }); +/// assert_eq!(a, [1, 2, 4, 8, 16, 32]); +/// ``` #[inline] #[stable(feature = "array_from_fn", since = "1.63.0")] -pub fn from_fn(cb: F) -> [T; N] +pub fn from_fn(f: F) -> [T; N] where F: FnMut(usize) -> T, { - try_from_fn(NeverShortCircuit::wrap_mut_1(cb)).0 + try_from_fn(NeverShortCircuit::wrap_mut_1(f)).0 } /// Creates an array `[T; N]` where each fallible array element `T` is returned by the `cb` call. From 3a4dd1b7b279435b4289b9b9a45db6647f1d3f9c Mon Sep 17 00:00:00 2001 From: joboet Date: Sat, 29 Mar 2025 13:08:18 +0100 Subject: [PATCH 074/606] std: make `cmath` functions safe --- library/std/src/f128.rs | 32 +++++----- library/std/src/f16.rs | 32 +++++----- library/std/src/f32.rs | 34 +++++----- library/std/src/f64.rs | 34 +++++----- library/std/src/sys/cmath.rs | 118 +++++++++++++++++------------------ 5 files changed, 125 insertions(+), 125 deletions(-) diff --git a/library/std/src/f128.rs b/library/std/src/f128.rs index ede219690511..217528fdf1c1 100644 --- a/library/std/src/f128.rs +++ b/library/std/src/f128.rs @@ -666,7 +666,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn cbrt(self) -> f128 { - unsafe { cmath::cbrtf128(self) } + cmath::cbrtf128(self) } /// Compute the distance between the origin and a point (`x`, `y`) on the @@ -703,7 +703,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn hypot(self, other: f128) -> f128 { - unsafe { cmath::hypotf128(self, other) } + cmath::hypotf128(self, other) } /// Computes the sine of a number (in radians). @@ -789,7 +789,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn tan(self) -> f128 { - unsafe { cmath::tanf128(self) } + cmath::tanf128(self) } /// Computes the arcsine of a number. Return value is in radians in @@ -824,7 +824,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn asin(self) -> f128 { - unsafe { cmath::asinf128(self) } + cmath::asinf128(self) } /// Computes the arccosine of a number. Return value is in radians in @@ -859,7 +859,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn acos(self) -> f128 { - unsafe { cmath::acosf128(self) } + cmath::acosf128(self) } /// Computes the arctangent of a number. Return value is in radians in the @@ -893,7 +893,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn atan(self) -> f128 { - unsafe { cmath::atanf128(self) } + cmath::atanf128(self) } /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`) in radians. @@ -939,7 +939,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn atan2(self, other: f128) -> f128 { - unsafe { cmath::atan2f128(self, other) } + cmath::atan2f128(self, other) } /// Simultaneously computes the sine and cosine of the number, `x`. Returns @@ -1008,7 +1008,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn exp_m1(self) -> f128 { - unsafe { cmath::expm1f128(self) } + cmath::expm1f128(self) } /// Returns `ln(1+n)` (natural logarithm) more accurately than if @@ -1055,7 +1055,7 @@ impl f128 { #[rustc_allow_incoherent_impl] #[unstable(feature = "f128", issue = "116909")] pub fn ln_1p(self) -> f128 { - unsafe { cmath::log1pf128(self) } + cmath::log1pf128(self) } /// Hyperbolic sine function. @@ -1090,7 +1090,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn sinh(self) -> f128 { - unsafe { cmath::sinhf128(self) } + cmath::sinhf128(self) } /// Hyperbolic cosine function. @@ -1125,7 +1125,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn cosh(self) -> f128 { - unsafe { cmath::coshf128(self) } + cmath::coshf128(self) } /// Hyperbolic tangent function. @@ -1160,7 +1160,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn tanh(self) -> f128 { - unsafe { cmath::tanhf128(self) } + cmath::tanhf128(self) } /// Inverse hyperbolic sine function. @@ -1289,7 +1289,7 @@ impl f128 { // #[unstable(feature = "float_gamma", issue = "99842")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn gamma(self) -> f128 { - unsafe { cmath::tgammaf128(self) } + cmath::tgammaf128(self) } /// Natural logarithm of the absolute value of the gamma function @@ -1325,7 +1325,7 @@ impl f128 { #[must_use = "method returns a new number and does not mutate the original value"] pub fn ln_gamma(self) -> (f128, i32) { let mut signgamp: i32 = 0; - let x = unsafe { cmath::lgammaf128_r(self, &mut signgamp) }; + let x = cmath::lgammaf128_r(self, &mut signgamp); (x, signgamp) } @@ -1365,7 +1365,7 @@ impl f128 { // #[unstable(feature = "float_erf", issue = "136321")] #[inline] pub fn erf(self) -> f128 { - unsafe { cmath::erff128(self) } + cmath::erff128(self) } /// Complementary error function. @@ -1398,6 +1398,6 @@ impl f128 { // #[unstable(feature = "float_erf", issue = "136321")] #[inline] pub fn erfc(self) -> f128 { - unsafe { cmath::erfcf128(self) } + cmath::erfcf128(self) } } diff --git a/library/std/src/f16.rs b/library/std/src/f16.rs index 286993d736b9..4dadcbb51855 100644 --- a/library/std/src/f16.rs +++ b/library/std/src/f16.rs @@ -665,7 +665,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn cbrt(self) -> f16 { - (unsafe { cmath::cbrtf(self as f32) }) as f16 + cmath::cbrtf(self as f32) as f16 } /// Compute the distance between the origin and a point (`x`, `y`) on the @@ -701,7 +701,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn hypot(self, other: f16) -> f16 { - (unsafe { cmath::hypotf(self as f32, other as f32) }) as f16 + cmath::hypotf(self as f32, other as f32) as f16 } /// Computes the sine of a number (in radians). @@ -787,7 +787,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn tan(self) -> f16 { - (unsafe { cmath::tanf(self as f32) }) as f16 + cmath::tanf(self as f32) as f16 } /// Computes the arcsine of a number. Return value is in radians in @@ -822,7 +822,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn asin(self) -> f16 { - (unsafe { cmath::asinf(self as f32) }) as f16 + cmath::asinf(self as f32) as f16 } /// Computes the arccosine of a number. Return value is in radians in @@ -857,7 +857,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn acos(self) -> f16 { - (unsafe { cmath::acosf(self as f32) }) as f16 + cmath::acosf(self as f32) as f16 } /// Computes the arctangent of a number. Return value is in radians in the @@ -891,7 +891,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn atan(self) -> f16 { - (unsafe { cmath::atanf(self as f32) }) as f16 + cmath::atanf(self as f32) as f16 } /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`) in radians. @@ -937,7 +937,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn atan2(self, other: f16) -> f16 { - (unsafe { cmath::atan2f(self as f32, other as f32) }) as f16 + cmath::atan2f(self as f32, other as f32) as f16 } /// Simultaneously computes the sine and cosine of the number, `x`. Returns @@ -1006,7 +1006,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn exp_m1(self) -> f16 { - (unsafe { cmath::expm1f(self as f32) }) as f16 + cmath::expm1f(self as f32) as f16 } /// Returns `ln(1+n)` (natural logarithm) more accurately than if @@ -1053,7 +1053,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn ln_1p(self) -> f16 { - (unsafe { cmath::log1pf(self as f32) }) as f16 + cmath::log1pf(self as f32) as f16 } /// Hyperbolic sine function. @@ -1088,7 +1088,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn sinh(self) -> f16 { - (unsafe { cmath::sinhf(self as f32) }) as f16 + cmath::sinhf(self as f32) as f16 } /// Hyperbolic cosine function. @@ -1123,7 +1123,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn cosh(self) -> f16 { - (unsafe { cmath::coshf(self as f32) }) as f16 + cmath::coshf(self as f32) as f16 } /// Hyperbolic tangent function. @@ -1158,7 +1158,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn tanh(self) -> f16 { - (unsafe { cmath::tanhf(self as f32) }) as f16 + cmath::tanhf(self as f32) as f16 } /// Inverse hyperbolic sine function. @@ -1287,7 +1287,7 @@ impl f16 { // #[unstable(feature = "float_gamma", issue = "99842")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn gamma(self) -> f16 { - (unsafe { cmath::tgammaf(self as f32) }) as f16 + cmath::tgammaf(self as f32) as f16 } /// Natural logarithm of the absolute value of the gamma function @@ -1323,7 +1323,7 @@ impl f16 { #[must_use = "method returns a new number and does not mutate the original value"] pub fn ln_gamma(self) -> (f16, i32) { let mut signgamp: i32 = 0; - let x = (unsafe { cmath::lgammaf_r(self as f32, &mut signgamp) }) as f16; + let x = cmath::lgammaf_r(self as f32, &mut signgamp) as f16; (x, signgamp) } @@ -1363,7 +1363,7 @@ impl f16 { // #[unstable(feature = "float_erf", issue = "136321")] #[inline] pub fn erf(self) -> f16 { - (unsafe { cmath::erff(self as f32) }) as f16 + cmath::erff(self as f32) as f16 } /// Complementary error function. @@ -1396,6 +1396,6 @@ impl f16 { // #[unstable(feature = "float_erf", issue = "136321")] #[inline] pub fn erfc(self) -> f16 { - (unsafe { cmath::erfcf(self as f32) }) as f16 + cmath::erfcf(self as f32) as f16 } } diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs index 980e7f7793af..baf7002f3803 100644 --- a/library/std/src/f32.rs +++ b/library/std/src/f32.rs @@ -599,7 +599,7 @@ impl f32 { filing an issue describing your use-case too)." )] pub fn abs_sub(self, other: f32) -> f32 { - unsafe { cmath::fdimf(self, other) } + cmath::fdimf(self, other) } /// Returns the cube root of a number. @@ -626,7 +626,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn cbrt(self) -> f32 { - unsafe { cmath::cbrtf(self) } + cmath::cbrtf(self) } /// Compute the distance between the origin and a point (`x`, `y`) on the @@ -657,7 +657,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn hypot(self, other: f32) -> f32 { - unsafe { cmath::hypotf(self, other) } + cmath::hypotf(self, other) } /// Computes the sine of a number (in radians). @@ -730,7 +730,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn tan(self) -> f32 { - unsafe { cmath::tanf(self) } + cmath::tanf(self) } /// Computes the arcsine of a number. Return value is in radians in @@ -760,7 +760,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn asin(self) -> f32 { - unsafe { cmath::asinf(self) } + cmath::asinf(self) } /// Computes the arccosine of a number. Return value is in radians in @@ -790,7 +790,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn acos(self) -> f32 { - unsafe { cmath::acosf(self) } + cmath::acosf(self) } /// Computes the arctangent of a number. Return value is in radians in the @@ -819,7 +819,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn atan(self) -> f32 { - unsafe { cmath::atanf(self) } + cmath::atanf(self) } /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`) in radians. @@ -860,7 +860,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn atan2(self, other: f32) -> f32 { - unsafe { cmath::atan2f(self, other) } + cmath::atan2f(self, other) } /// Simultaneously computes the sine and cosine of the number, `x`. Returns @@ -919,7 +919,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn exp_m1(self) -> f32 { - unsafe { cmath::expm1f(self) } + cmath::expm1f(self) } /// Returns `ln(1+n)` (natural logarithm) more accurately than if @@ -957,7 +957,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn ln_1p(self) -> f32 { - unsafe { cmath::log1pf(self) } + cmath::log1pf(self) } /// Hyperbolic sine function. @@ -987,7 +987,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn sinh(self) -> f32 { - unsafe { cmath::sinhf(self) } + cmath::sinhf(self) } /// Hyperbolic cosine function. @@ -1017,7 +1017,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn cosh(self) -> f32 { - unsafe { cmath::coshf(self) } + cmath::coshf(self) } /// Hyperbolic tangent function. @@ -1047,7 +1047,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn tanh(self) -> f32 { - unsafe { cmath::tanhf(self) } + cmath::tanhf(self) } /// Inverse hyperbolic sine function. @@ -1158,7 +1158,7 @@ impl f32 { #[unstable(feature = "float_gamma", issue = "99842")] #[inline] pub fn gamma(self) -> f32 { - unsafe { cmath::tgammaf(self) } + cmath::tgammaf(self) } /// Natural logarithm of the absolute value of the gamma function @@ -1188,7 +1188,7 @@ impl f32 { #[inline] pub fn ln_gamma(self) -> (f32, i32) { let mut signgamp: i32 = 0; - let x = unsafe { cmath::lgammaf_r(self, &mut signgamp) }; + let x = cmath::lgammaf_r(self, &mut signgamp); (x, signgamp) } @@ -1224,7 +1224,7 @@ impl f32 { #[unstable(feature = "float_erf", issue = "136321")] #[inline] pub fn erf(self) -> f32 { - unsafe { cmath::erff(self) } + cmath::erff(self) } /// Complementary error function. @@ -1253,6 +1253,6 @@ impl f32 { #[unstable(feature = "float_erf", issue = "136321")] #[inline] pub fn erfc(self) -> f32 { - unsafe { cmath::erfcf(self) } + cmath::erfcf(self) } } diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs index 2aaab3ffc835..84fd9bfb7b68 100644 --- a/library/std/src/f64.rs +++ b/library/std/src/f64.rs @@ -599,7 +599,7 @@ impl f64 { filing an issue describing your use-case too)." )] pub fn abs_sub(self, other: f64) -> f64 { - unsafe { cmath::fdim(self, other) } + cmath::fdim(self, other) } /// Returns the cube root of a number. @@ -626,7 +626,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn cbrt(self) -> f64 { - unsafe { cmath::cbrt(self) } + cmath::cbrt(self) } /// Compute the distance between the origin and a point (`x`, `y`) on the @@ -657,7 +657,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn hypot(self, other: f64) -> f64 { - unsafe { cmath::hypot(self, other) } + cmath::hypot(self, other) } /// Computes the sine of a number (in radians). @@ -730,7 +730,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn tan(self) -> f64 { - unsafe { cmath::tan(self) } + cmath::tan(self) } /// Computes the arcsine of a number. Return value is in radians in @@ -760,7 +760,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn asin(self) -> f64 { - unsafe { cmath::asin(self) } + cmath::asin(self) } /// Computes the arccosine of a number. Return value is in radians in @@ -790,7 +790,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn acos(self) -> f64 { - unsafe { cmath::acos(self) } + cmath::acos(self) } /// Computes the arctangent of a number. Return value is in radians in the @@ -819,7 +819,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn atan(self) -> f64 { - unsafe { cmath::atan(self) } + cmath::atan(self) } /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`) in radians. @@ -860,7 +860,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn atan2(self, other: f64) -> f64 { - unsafe { cmath::atan2(self, other) } + cmath::atan2(self, other) } /// Simultaneously computes the sine and cosine of the number, `x`. Returns @@ -919,7 +919,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn exp_m1(self) -> f64 { - unsafe { cmath::expm1(self) } + cmath::expm1(self) } /// Returns `ln(1+n)` (natural logarithm) more accurately than if @@ -957,7 +957,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn ln_1p(self) -> f64 { - unsafe { cmath::log1p(self) } + cmath::log1p(self) } /// Hyperbolic sine function. @@ -987,7 +987,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn sinh(self) -> f64 { - unsafe { cmath::sinh(self) } + cmath::sinh(self) } /// Hyperbolic cosine function. @@ -1017,7 +1017,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn cosh(self) -> f64 { - unsafe { cmath::cosh(self) } + cmath::cosh(self) } /// Hyperbolic tangent function. @@ -1047,7 +1047,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn tanh(self) -> f64 { - unsafe { cmath::tanh(self) } + cmath::tanh(self) } /// Inverse hyperbolic sine function. @@ -1158,7 +1158,7 @@ impl f64 { #[unstable(feature = "float_gamma", issue = "99842")] #[inline] pub fn gamma(self) -> f64 { - unsafe { cmath::tgamma(self) } + cmath::tgamma(self) } /// Natural logarithm of the absolute value of the gamma function @@ -1188,7 +1188,7 @@ impl f64 { #[inline] pub fn ln_gamma(self) -> (f64, i32) { let mut signgamp: i32 = 0; - let x = unsafe { cmath::lgamma_r(self, &mut signgamp) }; + let x = cmath::lgamma_r(self, &mut signgamp); (x, signgamp) } @@ -1224,7 +1224,7 @@ impl f64 { #[unstable(feature = "float_erf", issue = "136321")] #[inline] pub fn erf(self) -> f64 { - unsafe { cmath::erf(self) } + cmath::erf(self) } /// Complementary error function. @@ -1253,6 +1253,6 @@ impl f64 { #[unstable(feature = "float_erf", issue = "136321")] #[inline] pub fn erfc(self) -> f64 { - unsafe { cmath::erfc(self) } + cmath::erfc(self) } } diff --git a/library/std/src/sys/cmath.rs b/library/std/src/sys/cmath.rs index c9969b4e376e..668fd9285340 100644 --- a/library/std/src/sys/cmath.rs +++ b/library/std/src/sys/cmath.rs @@ -3,70 +3,70 @@ // These symbols are all defined by `libm`, // or by `compiler-builtins` on unsupported platforms. unsafe extern "C" { - pub fn acos(n: f64) -> f64; - pub fn asin(n: f64) -> f64; - pub fn atan(n: f64) -> f64; - pub fn atan2(a: f64, b: f64) -> f64; - pub fn cbrt(n: f64) -> f64; - pub fn cbrtf(n: f32) -> f32; - pub fn cosh(n: f64) -> f64; - pub fn expm1(n: f64) -> f64; - pub fn expm1f(n: f32) -> f32; - pub fn fdim(a: f64, b: f64) -> f64; - pub fn fdimf(a: f32, b: f32) -> f32; + pub safe fn acos(n: f64) -> f64; + pub safe fn asin(n: f64) -> f64; + pub safe fn atan(n: f64) -> f64; + pub safe fn atan2(a: f64, b: f64) -> f64; + pub safe fn cbrt(n: f64) -> f64; + pub safe fn cbrtf(n: f32) -> f32; + pub safe fn cosh(n: f64) -> f64; + pub safe fn expm1(n: f64) -> f64; + pub safe fn expm1f(n: f32) -> f32; + pub safe fn fdim(a: f64, b: f64) -> f64; + pub safe fn fdimf(a: f32, b: f32) -> f32; #[cfg_attr(target_env = "msvc", link_name = "_hypot")] - pub fn hypot(x: f64, y: f64) -> f64; + pub safe fn hypot(x: f64, y: f64) -> f64; #[cfg_attr(target_env = "msvc", link_name = "_hypotf")] - pub fn hypotf(x: f32, y: f32) -> f32; - pub fn log1p(n: f64) -> f64; - pub fn log1pf(n: f32) -> f32; - pub fn sinh(n: f64) -> f64; - pub fn tan(n: f64) -> f64; - pub fn tanh(n: f64) -> f64; - pub fn tgamma(n: f64) -> f64; - pub fn tgammaf(n: f32) -> f32; - pub fn lgamma_r(n: f64, s: &mut i32) -> f64; + pub safe fn hypotf(x: f32, y: f32) -> f32; + pub safe fn log1p(n: f64) -> f64; + pub safe fn log1pf(n: f32) -> f32; + pub safe fn sinh(n: f64) -> f64; + pub safe fn tan(n: f64) -> f64; + pub safe fn tanh(n: f64) -> f64; + pub safe fn tgamma(n: f64) -> f64; + pub safe fn tgammaf(n: f32) -> f32; + pub safe fn lgamma_r(n: f64, s: &mut i32) -> f64; #[cfg(not(target_os = "aix"))] - pub fn lgammaf_r(n: f32, s: &mut i32) -> f32; - pub fn erf(n: f64) -> f64; - pub fn erff(n: f32) -> f32; - pub fn erfc(n: f64) -> f64; - pub fn erfcf(n: f32) -> f32; + pub safe fn lgammaf_r(n: f32, s: &mut i32) -> f32; + pub safe fn erf(n: f64) -> f64; + pub safe fn erff(n: f32) -> f32; + pub safe fn erfc(n: f64) -> f64; + pub safe fn erfcf(n: f32) -> f32; - pub fn acosf128(n: f128) -> f128; - pub fn asinf128(n: f128) -> f128; - pub fn atanf128(n: f128) -> f128; - pub fn atan2f128(a: f128, b: f128) -> f128; - pub fn cbrtf128(n: f128) -> f128; - pub fn coshf128(n: f128) -> f128; - pub fn expm1f128(n: f128) -> f128; - pub fn hypotf128(x: f128, y: f128) -> f128; - pub fn log1pf128(n: f128) -> f128; - pub fn sinhf128(n: f128) -> f128; - pub fn tanf128(n: f128) -> f128; - pub fn tanhf128(n: f128) -> f128; - pub fn tgammaf128(n: f128) -> f128; - pub fn lgammaf128_r(n: f128, s: &mut i32) -> f128; - pub fn erff128(n: f128) -> f128; - pub fn erfcf128(n: f128) -> f128; + pub safe fn acosf128(n: f128) -> f128; + pub safe fn asinf128(n: f128) -> f128; + pub safe fn atanf128(n: f128) -> f128; + pub safe fn atan2f128(a: f128, b: f128) -> f128; + pub safe fn cbrtf128(n: f128) -> f128; + pub safe fn coshf128(n: f128) -> f128; + pub safe fn expm1f128(n: f128) -> f128; + pub safe fn hypotf128(x: f128, y: f128) -> f128; + pub safe fn log1pf128(n: f128) -> f128; + pub safe fn sinhf128(n: f128) -> f128; + pub safe fn tanf128(n: f128) -> f128; + pub safe fn tanhf128(n: f128) -> f128; + pub safe fn tgammaf128(n: f128) -> f128; + pub safe fn lgammaf128_r(n: f128, s: &mut i32) -> f128; + pub safe fn erff128(n: f128) -> f128; + pub safe fn erfcf128(n: f128) -> f128; cfg_if::cfg_if! { if #[cfg(not(all(target_os = "windows", target_env = "msvc", target_arch = "x86")))] { - pub fn acosf(n: f32) -> f32; - pub fn asinf(n: f32) -> f32; - pub fn atan2f(a: f32, b: f32) -> f32; - pub fn atanf(n: f32) -> f32; - pub fn coshf(n: f32) -> f32; - pub fn sinhf(n: f32) -> f32; - pub fn tanf(n: f32) -> f32; - pub fn tanhf(n: f32) -> f32; + pub safe fn acosf(n: f32) -> f32; + pub safe fn asinf(n: f32) -> f32; + pub safe fn atan2f(a: f32, b: f32) -> f32; + pub safe fn atanf(n: f32) -> f32; + pub safe fn coshf(n: f32) -> f32; + pub safe fn sinhf(n: f32) -> f32; + pub safe fn tanf(n: f32) -> f32; + pub safe fn tanhf(n: f32) -> f32; }} } // On AIX, we don't have lgammaf_r only the f64 version, so we can // use the f64 version lgamma_r #[cfg(target_os = "aix")] -pub unsafe fn lgammaf_r(n: f32, s: &mut i32) -> f32 { +pub fn lgammaf_r(n: f32, s: &mut i32) -> f32 { lgamma_r(n.into(), s) as f32 } @@ -76,42 +76,42 @@ pub unsafe fn lgammaf_r(n: f32, s: &mut i32) -> f32 { cfg_if::cfg_if! { if #[cfg(all(target_os = "windows", target_env = "msvc", target_arch = "x86"))] { #[inline] - pub unsafe fn acosf(n: f32) -> f32 { + pub fn acosf(n: f32) -> f32 { f64::acos(n as f64) as f32 } #[inline] - pub unsafe fn asinf(n: f32) -> f32 { + pub fn asinf(n: f32) -> f32 { f64::asin(n as f64) as f32 } #[inline] - pub unsafe fn atan2f(n: f32, b: f32) -> f32 { + pub fn atan2f(n: f32, b: f32) -> f32 { f64::atan2(n as f64, b as f64) as f32 } #[inline] - pub unsafe fn atanf(n: f32) -> f32 { + pub fn atanf(n: f32) -> f32 { f64::atan(n as f64) as f32 } #[inline] - pub unsafe fn coshf(n: f32) -> f32 { + pub fn coshf(n: f32) -> f32 { f64::cosh(n as f64) as f32 } #[inline] - pub unsafe fn sinhf(n: f32) -> f32 { + pub fn sinhf(n: f32) -> f32 { f64::sinh(n as f64) as f32 } #[inline] - pub unsafe fn tanf(n: f32) -> f32 { + pub fn tanf(n: f32) -> f32 { f64::tan(n as f64) as f32 } #[inline] - pub unsafe fn tanhf(n: f32) -> f32 { + pub fn tanhf(n: f32) -> f32 { f64::tanh(n as f64) as f32 } }} From 18c787f48f08352ad5167b99920c395e3d703f62 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 30 Mar 2025 04:21:20 +0000 Subject: [PATCH 075/606] Fix up partial res of segment in primitive resolution hack --- compiler/rustc_resolve/src/late.rs | 5 +++++ tests/ui/resolve/auxiliary/empty.rs | 1 + tests/ui/resolve/prim-crate-partial-res.rs | 8 ++++++++ tests/ui/resolve/prim-crate-partial-res.stderr | 17 +++++++++++++++++ 4 files changed, 31 insertions(+) create mode 100644 tests/ui/resolve/auxiliary/empty.rs create mode 100644 tests/ui/resolve/prim-crate-partial-res.rs create mode 100644 tests/ui/resolve/prim-crate-partial-res.stderr diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 0d23ae501f04..606d25c558a1 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -4598,6 +4598,11 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } }; + // Fix up partial res of segment from `resolve_path` call. + if let Some(id) = path[0].id { + self.r.partial_res_map.insert(id, PartialRes::new(Res::PrimTy(prim))); + } + PartialRes::with_unresolved_segments(Res::PrimTy(prim), path.len() - 1) } PathResult::Module(ModuleOrUniformRoot::Module(module)) => { diff --git a/tests/ui/resolve/auxiliary/empty.rs b/tests/ui/resolve/auxiliary/empty.rs new file mode 100644 index 000000000000..bd9ec079d80d --- /dev/null +++ b/tests/ui/resolve/auxiliary/empty.rs @@ -0,0 +1 @@ +// Intentionally empty. diff --git a/tests/ui/resolve/prim-crate-partial-res.rs b/tests/ui/resolve/prim-crate-partial-res.rs new file mode 100644 index 000000000000..955f4fa2aee7 --- /dev/null +++ b/tests/ui/resolve/prim-crate-partial-res.rs @@ -0,0 +1,8 @@ +//@ aux-build: empty.rs + +extern crate empty as usize; + +fn foo() -> usize<()> { 0 } +//~^ ERROR type arguments are not allowed on builtin type `usize` + +fn main() {} diff --git a/tests/ui/resolve/prim-crate-partial-res.stderr b/tests/ui/resolve/prim-crate-partial-res.stderr new file mode 100644 index 000000000000..d10d37c9f1b0 --- /dev/null +++ b/tests/ui/resolve/prim-crate-partial-res.stderr @@ -0,0 +1,17 @@ +error[E0109]: type arguments are not allowed on builtin type `usize` + --> $DIR/prim-crate-partial-res.rs:5:19 + | +LL | fn foo() -> usize<()> { 0 } + | ----- ^^ type argument not allowed + | | + | not allowed on builtin type `usize` + | +help: primitive type `usize` doesn't have generic parameters + | +LL - fn foo() -> usize<()> { 0 } +LL + fn foo() -> usize { 0 } + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0109`. From 19648ce5cd12b11889eccacac50c70ca8ac78fee Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sun, 23 Mar 2025 18:45:08 -0700 Subject: [PATCH 076/606] codegen test for non-memcmp array comparison --- tests/codegen/array-cmp.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/codegen/array-cmp.rs b/tests/codegen/array-cmp.rs index 2565a385b61b..f9b7be898828 100644 --- a/tests/codegen/array-cmp.rs +++ b/tests/codegen/array-cmp.rs @@ -17,3 +17,15 @@ pub fn compare() -> bool { [0x00, 0x00, 0x48, 0x41] } } + +// CHECK-LABEL: @array_of_tuple_le +// CHECK: call{{.+}}i8 @llvm.scmp.i8.i16 +// CHECK: call{{.+}}i8 @llvm.ucmp.i8.i16 +// CHECK: call{{.+}}i8 @llvm.scmp.i8.i16 +// CHECK: call{{.+}}i8 @llvm.ucmp.i8.i16 +// CHECK: %[[RET:.+]] = icmp slt i8 {{.+}}, 1 +// CHECK: ret i8 %[[RET]] +#[no_mangle] +pub fn array_of_tuple_le(a: &[(i16, u16); 2], b: &[(i16, u16); 2]) -> bool { + a <= b +} From 04d9d864b39c56aa6efa6b5f7845b4735d7a6428 Mon Sep 17 00:00:00 2001 From: xizheyin Date: Mon, 31 Mar 2025 14:53:39 +0800 Subject: [PATCH 077/606] std: clarify Mutex::get_mut more clearly Signed-off-by: xizheyin --- library/std/src/sync/poison/mutex.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/library/std/src/sync/poison/mutex.rs b/library/std/src/sync/poison/mutex.rs index 9362c764173a..adb74bb6f3de 100644 --- a/library/std/src/sync/poison/mutex.rs +++ b/library/std/src/sync/poison/mutex.rs @@ -582,7 +582,9 @@ impl Mutex { /// Returns a mutable reference to the underlying data. /// /// Since this call borrows the `Mutex` mutably, no actual locking needs to - /// take place -- the mutable borrow statically guarantees no locks exist. + /// take place -- the mutable borrow statically guarantees no new locks can be acquired + /// while this reference exists. Note that this method does not clear any previous abandoned locks + /// (e.g., via [`forget()`] on a [`MutexGuard`]). /// /// # Errors /// @@ -599,6 +601,8 @@ impl Mutex { /// *mutex.get_mut().unwrap() = 10; /// assert_eq!(*mutex.lock().unwrap(), 10); /// ``` + /// + /// [`forget()`]: mem::forget #[stable(feature = "mutex_get_mut", since = "1.6.0")] pub fn get_mut(&mut self) -> LockResult<&mut T> { let data = self.data.get_mut(); From 76034a648d63f88d00e3b24f369ba356c6e52282 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 31 Mar 2025 11:51:06 +0200 Subject: [PATCH 078/606] do not run EnvVars::cleanup if there was an interpreter error --- src/tools/miri/src/eval.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs index ed13f670a90e..7586b5efd4b2 100644 --- a/src/tools/miri/src/eval.rs +++ b/src/tools/miri/src/eval.rs @@ -459,8 +459,13 @@ pub fn eval_entry<'tcx>( ecx.handle_ice(); panic::resume_unwind(panic_payload) }); - // `Ok` can never happen. + // `Ok` can never happen; the interpreter loop always exits with an "error" + // (but that "error" might be just "regular program termination"). let Err(err) = res.report_err(); + // Show diagnostic, if any. + let (return_code, leak_check) = report_error(&ecx, err)?; + + // If we get here there was no fatal error. // Machine cleanup. Only do this if all threads have terminated; threads that are still running // might cause Stacked Borrows errors (https://github.com/rust-lang/miri/issues/2396). @@ -472,8 +477,7 @@ pub fn eval_entry<'tcx>( EnvVars::cleanup(&mut ecx).expect("error during env var cleanup"); } - // Process the result. - let (return_code, leak_check) = report_error(&ecx, err)?; + // Possibly check for memory leaks. if leak_check && !ignore_leaks { // Check for thread leaks. if !ecx.have_all_terminated() { From 54bb849affcbede09ab1327c6cd996e5c5948cdd Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 28 Mar 2025 22:31:20 +0300 Subject: [PATCH 079/606] hygiene: Rename semi-transparent to semi-opaque The former is just too long, see the examples in `hygiene.rs` --- .../src/attributes/transparency.rs | 2 +- compiler/rustc_feature/src/builtin_attrs.rs | 2 +- compiler/rustc_resolve/src/lib.rs | 6 +-- compiler/rustc_span/src/hygiene.rs | 47 +++++++++---------- compiler/rustc_span/src/lib.rs | 2 +- compiler/rustc_span/src/symbol.rs | 1 + tests/ui/hygiene/rustc-macro-transparency.rs | 12 ++--- .../hygiene/rustc-macro-transparency.stderr | 12 ++--- tests/ui/hygiene/unpretty-debug.stdout | 2 +- tests/ui/proc-macro/meta-macro-hygiene.stdout | 6 +-- .../nonterminal-token-hygiene.stdout | 4 +- 11 files changed, 48 insertions(+), 48 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/transparency.rs b/compiler/rustc_attr_parsing/src/attributes/transparency.rs index ad83a1f7af80..ce42b0507ed5 100644 --- a/compiler/rustc_attr_parsing/src/attributes/transparency.rs +++ b/compiler/rustc_attr_parsing/src/attributes/transparency.rs @@ -20,7 +20,7 @@ impl SingleAttributeParser for TransparencyParser { fn convert(cx: &AcceptContext<'_>, args: &ArgParser<'_>) -> Option { match args.name_value().and_then(|nv| nv.value_as_str()) { Some(sym::transparent) => Some(Transparency::Transparent), - Some(sym::semitransparent) => Some(Transparency::SemiTransparent), + Some(sym::semiopaque | sym::semitransparent) => Some(Transparency::SemiOpaque), Some(sym::opaque) => Some(Transparency::Opaque), Some(other) => { cx.dcx().span_err(cx.attr_span, format!("unknown macro transparency: `{other}`")); diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 1e33e2e9393f..a8f0da736c63 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -752,7 +752,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), rustc_attr!( rustc_macro_transparency, Normal, - template!(NameValueStr: "transparent|semitransparent|opaque"), ErrorFollowing, + template!(NameValueStr: "transparent|semiopaque|opaque"), ErrorFollowing, EncodeCrossCrate::Yes, "used internally for testing macro hygiene", ), rustc_attr!( diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 612e091770f0..1eac3f848b62 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1998,16 +1998,16 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { result, result.map(|r| r.expn_data()) ); - // Then find the last semi-transparent mark from the end if it exists. + // Then find the last semi-opaque mark from the end if it exists. for (mark, transparency) in iter { - if transparency == Transparency::SemiTransparent { + if transparency == Transparency::SemiOpaque { result = Some(mark); } else { break; } } debug!( - "resolve_crate_root: found semi-transparent mark {:?} {:?}", + "resolve_crate_root: found semi-opaque mark {:?} {:?}", result, result.map(|r| r.expn_data()) ); diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index e7a8dee27f56..c2e7cb457755 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -66,10 +66,10 @@ pub struct SyntaxContextData { outer_expn: ExpnId, outer_transparency: Transparency, parent: SyntaxContext, - /// This context, but with all transparent and semi-transparent expansions filtered away. + /// This context, but with all transparent and semi-opaque expansions filtered away. opaque: SyntaxContext, /// This context, but with all transparent expansions filtered away. - opaque_and_semitransparent: SyntaxContext, + opaque_and_semiopaque: SyntaxContext, /// Name of the crate to which `$crate` with this context would resolve. dollar_crate_name: Symbol, } @@ -78,14 +78,14 @@ impl SyntaxContextData { fn new( (parent, outer_expn, outer_transparency): SyntaxContextKey, opaque: SyntaxContext, - opaque_and_semitransparent: SyntaxContext, + opaque_and_semiopaque: SyntaxContext, ) -> SyntaxContextData { SyntaxContextData { outer_expn, outer_transparency, parent, opaque, - opaque_and_semitransparent, + opaque_and_semiopaque, dollar_crate_name: kw::DollarCrate, } } @@ -96,7 +96,7 @@ impl SyntaxContextData { outer_transparency: Transparency::Opaque, parent: SyntaxContext::root(), opaque: SyntaxContext::root(), - opaque_and_semitransparent: SyntaxContext::root(), + opaque_and_semiopaque: SyntaxContext::root(), dollar_crate_name: kw::DollarCrate, } } @@ -207,13 +207,13 @@ pub enum Transparency { /// Identifier produced by a transparent expansion is always resolved at call-site. /// Call-site spans in procedural macros, hygiene opt-out in `macro` should use this. Transparent, - /// Identifier produced by a semi-transparent expansion may be resolved + /// Identifier produced by a semi-opaque expansion may be resolved /// either at call-site or at definition-site. /// If it's a local variable, label or `$crate` then it's resolved at def-site. /// Otherwise it's resolved at call-site. /// `macro_rules` macros behave like this, built-in macros currently behave like this too, /// but that's an implementation detail. - SemiTransparent, + SemiOpaque, /// Identifier produced by an opaque expansion is always resolved at definition-site. /// Def-site spans in procedural macros, identifiers from `macro` by default use this. Opaque, @@ -221,7 +221,7 @@ pub enum Transparency { impl Transparency { pub fn fallback(macro_rules: bool) -> Self { - if macro_rules { Transparency::SemiTransparent } else { Transparency::Opaque } + if macro_rules { Transparency::SemiOpaque } else { Transparency::Opaque } } } @@ -469,7 +469,7 @@ impl HygieneData { fn normalize_to_macro_rules(&self, ctxt: SyntaxContext) -> SyntaxContext { debug_assert!(!self.syntax_context_data[ctxt.0 as usize].is_decode_placeholder()); - self.syntax_context_data[ctxt.0 as usize].opaque_and_semitransparent + self.syntax_context_data[ctxt.0 as usize].opaque_and_semiopaque } fn outer_expn(&self, ctxt: SyntaxContext) -> ExpnId { @@ -562,7 +562,7 @@ impl HygieneData { } let call_site_ctxt = self.expn_data(expn_id).call_site.ctxt(); - let mut call_site_ctxt = if transparency == Transparency::SemiTransparent { + let mut call_site_ctxt = if transparency == Transparency::SemiOpaque { self.normalize_to_macros_2_0(call_site_ctxt) } else { self.normalize_to_macro_rules(call_site_ctxt) @@ -608,33 +608,32 @@ impl HygieneData { self.syntax_context_data.push(SyntaxContextData::decode_placeholder()); self.syntax_context_map.insert(key, ctxt); - // Opaque and semi-transparent versions of the parent. Note that they may be equal to the + // Opaque and semi-opaque versions of the parent. Note that they may be equal to the // parent itself. E.g. `parent_opaque` == `parent` if the expn chain contains only opaques, - // and `parent_opaque_and_semitransparent` == `parent` if the expn contains only opaques - // and semi-transparents. + // and `parent_opaque_and_semiopaque` == `parent` if the expn contains only (semi-)opaques. let parent_opaque = self.syntax_context_data[parent.0 as usize].opaque; - let parent_opaque_and_semitransparent = - self.syntax_context_data[parent.0 as usize].opaque_and_semitransparent; + let parent_opaque_and_semiopaque = + self.syntax_context_data[parent.0 as usize].opaque_and_semiopaque; - // Evaluate opaque and semi-transparent versions of the new syntax context. - let (opaque, opaque_and_semitransparent) = match transparency { - Transparency::Transparent => (parent_opaque, parent_opaque_and_semitransparent), - Transparency::SemiTransparent => ( + // Evaluate opaque and semi-opaque versions of the new syntax context. + let (opaque, opaque_and_semiopaque) = match transparency { + Transparency::Transparent => (parent_opaque, parent_opaque_and_semiopaque), + Transparency::SemiOpaque => ( parent_opaque, - // Will be the same as `ctxt` if the expn chain contains only opaques and semi-transparents. - self.alloc_ctxt(parent_opaque_and_semitransparent, expn_id, transparency), + // Will be the same as `ctxt` if the expn chain contains only (semi-)opaques. + self.alloc_ctxt(parent_opaque_and_semiopaque, expn_id, transparency), ), Transparency::Opaque => ( // Will be the same as `ctxt` if the expn chain contains only opaques. self.alloc_ctxt(parent_opaque, expn_id, transparency), - // Will be the same as `ctxt` if the expn chain contains only opaques and semi-transparents. - self.alloc_ctxt(parent_opaque_and_semitransparent, expn_id, transparency), + // Will be the same as `ctxt` if the expn chain contains only (semi-)opaques. + self.alloc_ctxt(parent_opaque_and_semiopaque, expn_id, transparency), ), }; // Fill the full data, now that we have it. self.syntax_context_data[ctxt.as_u32() as usize] = - SyntaxContextData::new(key, opaque, opaque_and_semitransparent); + SyntaxContextData::new(key, opaque, opaque_and_semiopaque); ctxt } } diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 9e6ba2e1b9ce..625ece787b90 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -1112,7 +1112,7 @@ impl Span { /// Equivalent of `Span::mixed_site` from the proc macro API, /// except that the location is taken from the `self` span. pub fn with_mixed_site_ctxt(self, expn_id: ExpnId) -> Span { - self.with_ctxt_from_mark(expn_id, Transparency::SemiTransparent) + self.with_ctxt_from_mark(expn_id, Transparency::SemiOpaque) } /// Produces a span with the same location as `self` and context produced by a macro with the diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 47dd80c432ea..02f89c527e63 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1871,6 +1871,7 @@ symbols! { select_unpredictable, self_in_typedefs, self_struct_ctor, + semiopaque, semitransparent, sha2, sha3, diff --git a/tests/ui/hygiene/rustc-macro-transparency.rs b/tests/ui/hygiene/rustc-macro-transparency.rs index 5f36993af2f3..1a78a7543cfd 100644 --- a/tests/ui/hygiene/rustc-macro-transparency.rs +++ b/tests/ui/hygiene/rustc-macro-transparency.rs @@ -6,9 +6,9 @@ macro transparent() { let transparent = 0; } #[rustc_macro_transparency = "semitransparent"] -macro semitransparent() { - struct SemiTransparent; - let semitransparent = 0; +macro semiopaque() { + struct SemiOpaque; + let semiopaque = 0; } #[rustc_macro_transparency = "opaque"] macro opaque() { @@ -18,14 +18,14 @@ macro opaque() { fn main() { transparent!(); - semitransparent!(); + semiopaque!(); opaque!(); Transparent; // OK - SemiTransparent; // OK + SemiOpaque; // OK Opaque; //~ ERROR cannot find value `Opaque` in this scope transparent; // OK - semitransparent; //~ ERROR expected value, found macro `semitransparent` + semiopaque; //~ ERROR expected value, found macro `semiopaque` opaque; //~ ERROR expected value, found macro `opaque` } diff --git a/tests/ui/hygiene/rustc-macro-transparency.stderr b/tests/ui/hygiene/rustc-macro-transparency.stderr index 1d2a1e124986..1bea8a0ee4f3 100644 --- a/tests/ui/hygiene/rustc-macro-transparency.stderr +++ b/tests/ui/hygiene/rustc-macro-transparency.stderr @@ -4,17 +4,17 @@ error[E0425]: cannot find value `Opaque` in this scope LL | Opaque; | ^^^^^^ not found in this scope -error[E0423]: expected value, found macro `semitransparent` +error[E0423]: expected value, found macro `semiopaque` --> $DIR/rustc-macro-transparency.rs:29:5 | -LL | struct SemiTransparent; - | ----------------------- similarly named unit struct `SemiTransparent` defined here +LL | struct SemiOpaque; + | ------------------ similarly named unit struct `SemiOpaque` defined here ... -LL | semitransparent; - | ^^^^^^^^^^^^^^^ +LL | semiopaque; + | ^^^^^^^^^^ | | | not a value - | help: a unit struct with a similar name exists: `SemiTransparent` + | help: a unit struct with a similar name exists (notice the capitalization): `SemiOpaque` error[E0423]: expected value, found macro `opaque` --> $DIR/rustc-macro-transparency.rs:30:5 diff --git a/tests/ui/hygiene/unpretty-debug.stdout b/tests/ui/hygiene/unpretty-debug.stdout index e475cfac2fc1..f35bd7a7cb2c 100644 --- a/tests/ui/hygiene/unpretty-debug.stdout +++ b/tests/ui/hygiene/unpretty-debug.stdout @@ -24,5 +24,5 @@ crate0::{{expn1}}: parent: crate0::{{expn0}}, call_site_ctxt: #0, def_site_ctxt: SyntaxContexts: #0: parent: #0, outer_mark: (crate0::{{expn0}}, Opaque) -#1: parent: #0, outer_mark: (crate0::{{expn1}}, SemiTransparent) +#1: parent: #0, outer_mark: (crate0::{{expn1}}, SemiOpaque) */ diff --git a/tests/ui/proc-macro/meta-macro-hygiene.stdout b/tests/ui/proc-macro/meta-macro-hygiene.stdout index 1ee7179e84c0..1734b9afe92e 100644 --- a/tests/ui/proc-macro/meta-macro-hygiene.stdout +++ b/tests/ui/proc-macro/meta-macro-hygiene.stdout @@ -60,11 +60,11 @@ SyntaxContexts: #0: parent: #0, outer_mark: (crate0::{{expn0}}, Opaque) #1: parent: #0, outer_mark: (crate0::{{expn1}}, Opaque) #2: parent: #0, outer_mark: (crate0::{{expn1}}, Transparent) -#3: parent: #0, outer_mark: (crate0::{{expn2}}, SemiTransparent) +#3: parent: #0, outer_mark: (crate0::{{expn2}}, SemiOpaque) #4: parent: #0, outer_mark: (crate0::{{expn3}}, Opaque) #5: parent: #3, outer_mark: (crate0::{{expn3}}, Transparent) -#6: parent: #0, outer_mark: (crate0::{{expn3}}, SemiTransparent) +#6: parent: #0, outer_mark: (crate0::{{expn3}}, SemiOpaque) #7: parent: #0, outer_mark: (crate0::{{expn4}}, Opaque) #8: parent: #4, outer_mark: (crate0::{{expn4}}, Transparent) -#9: parent: #4, outer_mark: (crate0::{{expn4}}, SemiTransparent) +#9: parent: #4, outer_mark: (crate0::{{expn4}}, SemiOpaque) */ diff --git a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout index 6fd6cb474693..0f1b19ffdeab 100644 --- a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout +++ b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout @@ -82,10 +82,10 @@ SyntaxContexts: #0: parent: #0, outer_mark: (crate0::{{expn0}}, Opaque) #1: parent: #0, outer_mark: (crate0::{{expn1}}, Opaque) #2: parent: #0, outer_mark: (crate0::{{expn1}}, Transparent) -#3: parent: #0, outer_mark: (crate0::{{expn2}}, SemiTransparent) +#3: parent: #0, outer_mark: (crate0::{{expn2}}, SemiOpaque) #4: parent: #3, outer_mark: (crate0::{{expn3}}, Opaque) #5: parent: #0, outer_mark: (crate0::{{expn3}}, Opaque) #6: parent: #0, outer_mark: (crate0::{{expn4}}, Opaque) #7: parent: #4, outer_mark: (crate0::{{expn4}}, Transparent) -#8: parent: #5, outer_mark: (crate0::{{expn4}}, SemiTransparent) +#8: parent: #5, outer_mark: (crate0::{{expn4}}, SemiOpaque) */ From bb495d6d3e6dae294f08162097bd85f904e9f90b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 18 Apr 2024 20:18:13 +1000 Subject: [PATCH 080/606] Remove `NtBlock`, `Nonterminal`, and `TokenKind::Interpolated`. `NtBlock` is the last remaining variant of `Nonterminal`, so once it is gone then `Nonterminal` can be removed as well. --- compiler/rustc_ast/src/ast_traits.rs | 14 -- compiler/rustc_ast/src/mut_visit.rs | 40 +----- compiler/rustc_ast/src/token.rs | 127 +++--------------- compiler/rustc_ast/src/tokenstream.rs | 26 +--- compiler/rustc_ast_pretty/src/pprust/mod.rs | 6 +- compiler/rustc_ast_pretty/src/pprust/state.rs | 12 +- compiler/rustc_attr_parsing/src/parser.rs | 20 +-- compiler/rustc_builtin_macros/src/cfg_eval.rs | 6 +- compiler/rustc_expand/src/config.rs | 8 +- compiler/rustc_expand/src/mbe/diagnostics.rs | 4 +- compiler/rustc_expand/src/mbe/transcribe.rs | 19 ++- .../rustc_expand/src/proc_macro_server.rs | 9 -- compiler/rustc_parse/src/parser/expr.rs | 38 +++--- compiler/rustc_parse/src/parser/item.rs | 2 +- compiler/rustc_parse/src/parser/mod.rs | 33 +---- .../rustc_parse/src/parser/nonterminal.rs | 120 ++++++----------- compiler/rustc_parse/src/parser/stmt.rs | 10 +- tests/ui/macros/macro-as-fn-body.rs | 2 +- 18 files changed, 108 insertions(+), 388 deletions(-) diff --git a/compiler/rustc_ast/src/ast_traits.rs b/compiler/rustc_ast/src/ast_traits.rs index c9e2e9911ef0..7f98e7ba8a61 100644 --- a/compiler/rustc_ast/src/ast_traits.rs +++ b/compiler/rustc_ast/src/ast_traits.rs @@ -6,7 +6,6 @@ use std::fmt; use std::marker::PhantomData; use crate::ptr::P; -use crate::token::Nonterminal; use crate::tokenstream::LazyAttrTokenStream; use crate::{ Arm, AssocItem, AttrItem, AttrKind, AttrVec, Attribute, Block, Crate, Expr, ExprField, @@ -206,19 +205,6 @@ impl HasTokens for Attribute { } } -impl HasTokens for Nonterminal { - fn tokens(&self) -> Option<&LazyAttrTokenStream> { - match self { - Nonterminal::NtBlock(block) => block.tokens(), - } - } - fn tokens_mut(&mut self) -> Option<&mut Option> { - match self { - Nonterminal::NtBlock(block) => block.tokens_mut(), - } - } -} - /// A trait for AST nodes having (or not having) attributes. pub trait HasAttrs { /// This is `true` if this `HasAttrs` might support 'custom' (proc-macro) inner diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index f7d13acdfc40..3d4fa546984a 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -843,9 +843,9 @@ fn visit_lazy_tts(vis: &mut T, lazy_tts: &mut Option(vis: &mut T, t: &mut Token) { let Token { kind, span } = t; @@ -863,45 +863,11 @@ pub fn visit_token(vis: &mut T, t: &mut Token) { token::NtLifetime(ident, _is_raw) => { vis.visit_ident(ident); } - token::Interpolated(nt) => { - let nt = Arc::make_mut(nt); - visit_nonterminal(vis, nt); - } _ => {} } vis.visit_span(span); } -// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. -/// Applies the visitor to elements of interpolated nodes. -// -// N.B., this can occur only when applying a visitor to partially expanded -// code, where parsed pieces have gotten implanted ito *other* macro -// invocations. This is relevant for macro hygiene, but possibly not elsewhere. -// -// One problem here occurs because the types for flat_map_item, flat_map_stmt, -// etc., allow the visitor to return *multiple* items; this is a problem for the -// nodes here, because they insist on having exactly one piece. One solution -// would be to mangle the MutVisitor trait to include one-to-many and -// one-to-one versions of these entry points, but that would probably confuse a -// lot of people and help very few. Instead, I'm just going to put in dynamic -// checks. I think the performance impact of this will be pretty much -// nonexistent. The danger is that someone will apply a `MutVisitor` to a -// partially expanded node, and will be confused by the fact that their -// `flat_map_item` or `flat_map_stmt` isn't getting called on `NtItem` or `NtStmt` -// nodes. Hopefully they'll wind up reading this comment, and doing something -// appropriate. -// -// BTW, design choice: I considered just changing the type of, e.g., `NtItem` to -// contain multiple items, but decided against it when I looked at -// `parse_item_or_view_item` and tried to figure out what I would do with -// multiple items there.... -fn visit_nonterminal(vis: &mut T, nt: &mut token::Nonterminal) { - match nt { - token::NtBlock(block) => vis.visit_block(block), - } -} - // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. fn visit_defaultness(vis: &mut T, defaultness: &mut Defaultness) { match defaultness { diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index d57a369eebf2..de80bb47aff2 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -1,13 +1,10 @@ use std::borrow::Cow; use std::fmt; -use std::sync::Arc; pub use LitKind::*; -pub use Nonterminal::*; pub use NtExprKind::*; pub use NtPatKind::*; pub use TokenKind::*; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_span::edition::Edition; use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, kw, sym}; @@ -16,7 +13,6 @@ use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, kw, sym}; use rustc_span::{Ident, Symbol}; use crate::ast; -use crate::ptr::P; use crate::util::case::Case; #[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] @@ -35,8 +31,8 @@ pub enum InvisibleOrigin { // `proc_macro::Delimiter::to_internal`, i.e. returned by a proc macro. ProcMacro, - // Converted from `TokenKind::Interpolated` in - // `TokenStream::flatten_token`. Treated similarly to `ProcMacro`. + // Converted from `TokenKind::NtLifetime` in `TokenStream::flatten_token`. + // Treated similarly to `ProcMacro`. FlattenToken, } @@ -337,9 +333,7 @@ impl From for bool { } } -// SAFETY: due to the `Clone` impl below, all fields of all variants other than -// `Interpolated` must impl `Copy`. -#[derive(PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] +#[derive(Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] pub enum TokenKind { /* Expression-operator symbols. */ /// `=` @@ -468,21 +462,6 @@ pub enum TokenKind { /// the `lifetime` metavariable in the macro's RHS. NtLifetime(Ident, IdentIsRaw), - /// An embedded AST node, as produced by a macro. This only exists for - /// historical reasons. We'd like to get rid of it, for multiple reasons. - /// - It's conceptually very strange. Saying a token can contain an AST - /// node is like saying, in natural language, that a word can contain a - /// sentence. - /// - It requires special handling in a bunch of places in the parser. - /// - It prevents `Token` from implementing `Copy`. - /// It adds complexity and likely slows things down. Please don't add new - /// occurrences of this token kind! - /// - /// The span in the surrounding `Token` is that of the metavariable in the - /// macro's RHS. The span within the Nonterminal is that of the fragment - /// passed to the macro at the call site. - Interpolated(Arc), - /// A doc comment token. /// `Symbol` is the doc comment's data excluding its "quotes" (`///`, `/**`, etc) /// similarly to symbols in string literal tokens. @@ -492,19 +471,6 @@ pub enum TokenKind { Eof, } -impl Clone for TokenKind { - fn clone(&self) -> Self { - // `TokenKind` would impl `Copy` if it weren't for `Interpolated`. So - // for all other variants, this implementation of `clone` is just like - // a copy. This is faster than the `derive(Clone)` version which has a - // separate path for every variant. - match self { - Interpolated(nt) => Interpolated(Arc::clone(nt)), - _ => unsafe { std::ptr::read(self) }, - } - } -} - #[derive(Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] pub struct Token { pub kind: TokenKind, @@ -600,7 +566,7 @@ impl Token { | FatArrow | Pound | Dollar | Question | SingleQuote => true, OpenDelim(..) | CloseDelim(..) | Literal(..) | DocComment(..) | Ident(..) - | NtIdent(..) | Lifetime(..) | NtLifetime(..) | Interpolated(..) | Eof => false, + | NtIdent(..) | Lifetime(..) | NtLifetime(..) | Eof => false, } } @@ -631,7 +597,6 @@ impl Token { PathSep | // global path Lifetime(..) | // labeled loop Pound => true, // expression attributes - Interpolated(ref nt) => matches!(&**nt, NtBlock(..)), OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( MetaVarKind::Block | MetaVarKind::Expr { .. } | @@ -703,7 +668,6 @@ impl Token { match self.kind { OpenDelim(Delimiter::Brace) | Literal(..) | Minus => true, Ident(name, IdentIsRaw::No) if name.is_bool_lit() => true, - Interpolated(ref nt) => matches!(&**nt, NtBlock(..)), OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( MetaVarKind::Expr { .. } | MetaVarKind::Block | MetaVarKind::Literal, ))) => true, @@ -831,31 +795,20 @@ impl Token { /// Is this a pre-parsed expression dropped into the token stream /// (which happens while parsing the result of macro expansion)? pub fn is_metavar_expr(&self) -> bool { - #[allow(irrefutable_let_patterns)] // FIXME: temporary - if let Interpolated(nt) = &self.kind - && let NtBlock(_) = &**nt - { - true - } else if matches!( + matches!( self.is_metavar_seq(), - Some(MetaVarKind::Expr { .. } | MetaVarKind::Literal | MetaVarKind::Path) - ) { - true - } else { - matches!(self.is_metavar_seq(), Some(MetaVarKind::Path)) - } + Some( + MetaVarKind::Expr { .. } + | MetaVarKind::Literal + | MetaVarKind::Path + | MetaVarKind::Block + ) + ) } - /// Is the token an interpolated block (`$b:block`)? - pub fn is_whole_block(&self) -> bool { - #[allow(irrefutable_let_patterns)] // FIXME: temporary - if let Interpolated(nt) = &self.kind - && let NtBlock(..) = &**nt - { - return true; - } - - false + /// Are we at a block from a metavar (`$b:block`)? + pub fn is_metavar_block(&self) -> bool { + matches!(self.is_metavar_seq(), Some(MetaVarKind::Block)) } /// Returns `true` if the token is either the `mut` or `const` keyword. @@ -1024,7 +977,7 @@ impl Token { | PercentEq | CaretEq | AndEq | OrEq | ShlEq | ShrEq | At | DotDotDot | DotDotEq | Comma | Semi | PathSep | RArrow | LArrow | FatArrow | Pound | Dollar | Question | OpenDelim(..) | CloseDelim(..) | Literal(..) | Ident(..) | NtIdent(..) - | Lifetime(..) | NtLifetime(..) | Interpolated(..) | DocComment(..) | Eof, + | Lifetime(..) | NtLifetime(..) | DocComment(..) | Eof, _, ) => { return None; @@ -1063,12 +1016,6 @@ pub enum NtExprKind { Expr2021 { inferred: bool }, } -#[derive(Clone, Encodable, Decodable)] -/// For interpolation during macro expansion. -pub enum Nonterminal { - NtBlock(P), -} - #[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, HashStable_Generic)] pub enum NonterminalKind { Item, @@ -1152,47 +1099,6 @@ impl fmt::Display for NonterminalKind { } } -impl Nonterminal { - pub fn use_span(&self) -> Span { - match self { - NtBlock(block) => block.span, - } - } - - pub fn descr(&self) -> &'static str { - match self { - NtBlock(..) => "block", - } - } -} - -impl PartialEq for Nonterminal { - fn eq(&self, _rhs: &Self) -> bool { - // FIXME: Assume that all nonterminals are not equal, we can't compare them - // correctly based on data from AST. This will prevent them from matching each other - // in macros. The comparison will become possible only when each nonterminal has an - // attached token stream from which it was parsed. - false - } -} - -impl fmt::Debug for Nonterminal { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match *self { - NtBlock(..) => f.pad("NtBlock(..)"), - } - } -} - -impl HashStable for Nonterminal -where - CTX: crate::HashStableContext, -{ - fn hash_stable(&self, _hcx: &mut CTX, _hasher: &mut StableHasher) { - panic!("interpolated tokens should not be present in the HIR") - } -} - // Some types are used a lot. Make sure they don't unintentionally get bigger. #[cfg(target_pointer_width = "64")] mod size_asserts { @@ -1202,7 +1108,6 @@ mod size_asserts { // tidy-alphabetical-start static_assert_size!(Lit, 12); static_assert_size!(LitKind, 2); - static_assert_size!(Nonterminal, 8); static_assert_size!(Token, 24); static_assert_size!(TokenKind, 16); // tidy-alphabetical-end diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index fb331e74aeb8..3b457303cac1 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -25,7 +25,7 @@ use rustc_span::{DUMMY_SP, Span, SpanDecoder, SpanEncoder, Symbol, sym}; use crate::ast::AttrStyle; use crate::ast_traits::{HasAttrs, HasTokens}; -use crate::token::{self, Delimiter, InvisibleOrigin, Nonterminal, Token, TokenKind}; +use crate::token::{self, Delimiter, InvisibleOrigin, Token, TokenKind}; use crate::{AttrVec, Attribute}; /// Part of a `TokenStream`. @@ -305,11 +305,6 @@ pub struct AttrsTarget { } /// A `TokenStream` is an abstract sequence of tokens, organized into [`TokenTree`]s. -/// -/// The goal is for procedural macros to work with `TokenStream`s and `TokenTree`s -/// instead of a representation of the abstract syntax tree. -/// Today's `TokenTree`s can still contain AST via `token::Interpolated` for -/// backwards compatibility. #[derive(Clone, Debug, Default, Encodable, Decodable)] pub struct TokenStream(pub(crate) Arc>); @@ -476,12 +471,6 @@ impl TokenStream { TokenStream::new(tts) } - pub fn from_nonterminal_ast(nt: &Nonterminal) -> TokenStream { - match nt { - Nonterminal::NtBlock(block) => TokenStream::from_ast(block), - } - } - fn flatten_token(token: &Token, spacing: Spacing) -> TokenTree { match token.kind { token::NtIdent(ident, is_raw) => { @@ -493,12 +482,6 @@ impl TokenStream { Delimiter::Invisible(InvisibleOrigin::FlattenToken), TokenStream::token_alone(token::Lifetime(ident.name, is_raw), ident.span), ), - token::Interpolated(ref nt) => TokenTree::Delimited( - DelimSpan::from_single(token.span), - DelimSpacing::new(Spacing::JointHidden, spacing), - Delimiter::Invisible(InvisibleOrigin::FlattenToken), - TokenStream::from_nonterminal_ast(&nt).flattened(), - ), _ => TokenTree::Token(token.clone(), spacing), } } @@ -516,10 +499,9 @@ impl TokenStream { pub fn flattened(&self) -> TokenStream { fn can_skip(stream: &TokenStream) -> bool { stream.iter().all(|tree| match tree { - TokenTree::Token(token, _) => !matches!( - token.kind, - token::NtIdent(..) | token::NtLifetime(..) | token::Interpolated(..) - ), + TokenTree::Token(token, _) => { + !matches!(token.kind, token::NtIdent(..) | token::NtLifetime(..)) + } TokenTree::Delimited(.., inner) => can_skip(inner), }) } diff --git a/compiler/rustc_ast_pretty/src/pprust/mod.rs b/compiler/rustc_ast_pretty/src/pprust/mod.rs index 97cb6e52d562..551506f2aef8 100644 --- a/compiler/rustc_ast_pretty/src/pprust/mod.rs +++ b/compiler/rustc_ast_pretty/src/pprust/mod.rs @@ -5,14 +5,10 @@ pub mod state; use std::borrow::Cow; use rustc_ast as ast; -use rustc_ast::token::{Nonterminal, Token, TokenKind}; +use rustc_ast::token::{Token, TokenKind}; use rustc_ast::tokenstream::{TokenStream, TokenTree}; pub use state::{AnnNode, Comments, PpAnn, PrintState, State, print_crate}; -pub fn nonterminal_to_string(nt: &Nonterminal) -> String { - State::new().nonterminal_to_string(nt) -} - /// Print the token kind precisely, without converting `$crate` into its respective crate name. pub fn token_kind_to_string(tok: &TokenKind) -> Cow<'static, str> { State::new().token_kind_to_string(tok) diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 3dbfc191f8f5..64a0a2ed97de 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -11,7 +11,7 @@ use std::sync::Arc; use rustc_ast::attr::AttrIdGenerator; use rustc_ast::ptr::P; -use rustc_ast::token::{self, CommentKind, Delimiter, IdentIsRaw, Nonterminal, Token, TokenKind}; +use rustc_ast::token::{self, CommentKind, Delimiter, IdentIsRaw, Token, TokenKind}; use rustc_ast::tokenstream::{Spacing, TokenStream, TokenTree}; use rustc_ast::util::classify; use rustc_ast::util::comments::{Comment, CommentStyle}; @@ -876,14 +876,6 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere } } - fn nonterminal_to_string(&self, nt: &Nonterminal) -> String { - // We extract the token stream from the AST fragment and pretty print - // it, rather than using AST pretty printing, because `Nonterminal` is - // slated for removal in #124141. (This method will also then be - // removed.) - self.tts_to_string(&TokenStream::from_nonterminal_ast(nt)) - } - /// Print the token kind precisely, without converting `$crate` into its respective crate name. fn token_kind_to_string(&self, tok: &TokenKind) -> Cow<'static, str> { self.token_kind_to_string_ext(tok, None) @@ -976,8 +968,6 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere doc_comment_to_string(comment_kind, attr_style, data).into() } token::Eof => "".into(), - - token::Interpolated(ref nt) => self.nonterminal_to_string(&nt).into(), } } diff --git a/compiler/rustc_attr_parsing/src/parser.rs b/compiler/rustc_attr_parsing/src/parser.rs index a8a1460591cf..384fae59873f 100644 --- a/compiler/rustc_attr_parsing/src/parser.rs +++ b/compiler/rustc_attr_parsing/src/parser.rs @@ -485,25 +485,7 @@ impl<'a> MetaItemListParserContext<'a> { } // or a path. - let path = - if let Some(TokenTree::Token(Token { kind: token::Interpolated(_), span, .. }, _)) = - self.inside_delimiters.peek() - { - self.inside_delimiters.next(); - // We go into this path if an expr ended up in an attribute that - // expansion did not turn into a literal. Say, `#[repr(align(macro!()))]` - // where the macro didn't expand to a literal. An error is already given - // for this at this point, and then we do continue. This makes this path - // reachable... - let e = self.dcx.span_delayed_bug( - *span, - "expr in place where literal is expected (builtin attr parsing)", - ); - - return Some(MetaItemOrLitParser::Err(*span, e)); - } else { - self.next_path()? - }; + let path = self.next_path()?; // Paths can be followed by: // - `(more meta items)` (another list) diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs index b3ba90731184..ea0bbd0e31ad 100644 --- a/compiler/rustc_builtin_macros/src/cfg_eval.rs +++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs @@ -92,11 +92,11 @@ impl CfgEval<'_> { // the location of `#[cfg]` and `#[cfg_attr]` in the token stream. The tokenization // process is lossless, so this process is invisible to proc-macros. - // 'Flatten' all nonterminals (i.e. `TokenKind::Interpolated`) + // 'Flatten' all nonterminals (i.e. `TokenKind::Nt{Ident,Lifetime}`) // to `None`-delimited groups containing the corresponding tokens. This // is normally delayed until the proc-macro server actually needs to - // provide a `TokenKind::Interpolated` to a proc-macro. We do this earlier, - // so that we can handle cases like: + // provide tokens to a proc-macro. We do this earlier, so that we can + // handle cases like: // // ```rust // #[cfg_eval] #[cfg] $item diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index bcc2703c39b3..27924544de52 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -238,13 +238,7 @@ impl<'a> StripUnconfigured<'a> { Some(AttrTokenTree::Delimited(sp, spacing, delim, inner)) } AttrTokenTree::Token( - Token { - kind: - TokenKind::NtIdent(..) - | TokenKind::NtLifetime(..) - | TokenKind::Interpolated(..), - .. - }, + Token { kind: TokenKind::NtIdent(..) | TokenKind::NtLifetime(..), .. }, _, ) => { panic!("Nonterminal should have been flattened: {:?}", tree); diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs index e60a9e83184f..30961a2b4044 100644 --- a/compiler/rustc_expand/src/mbe/diagnostics.rs +++ b/compiler/rustc_expand/src/mbe/diagnostics.rs @@ -66,9 +66,7 @@ pub(super) fn failed_to_match_macro( } if let MatcherLoc::Token { token: expected_token } = &remaining_matcher - && (matches!(expected_token.kind, TokenKind::Interpolated(_)) - || matches!(token.kind, TokenKind::Interpolated(_)) - || matches!(expected_token.kind, TokenKind::OpenDelim(Delimiter::Invisible(_))) + && (matches!(expected_token.kind, TokenKind::OpenDelim(Delimiter::Invisible(_))) || matches!(token.kind, TokenKind::OpenDelim(Delimiter::Invisible(_)))) { err.note("captured metavariables except for `:tt`, `:ident` and `:lifetime` cannot be compared to other tokens"); diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index 6e47ed6eb67c..79a5c7ea31be 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -1,5 +1,4 @@ use std::mem; -use std::sync::Arc; use rustc_ast::mut_visit::{self, MutVisitor}; use rustc_ast::token::{ @@ -307,7 +306,9 @@ pub(super) fn transcribe<'a>( let tt = match cur_matched { MatchedSingle(ParseNtResult::Tt(tt)) => { // `tt`s are emitted into the output stream directly as "raw tokens", - // without wrapping them into groups. + // without wrapping them into groups. Other variables are emitted into + // the output stream as groups with `Delimiter::Invisible` to maintain + // parsing priorities. maybe_use_metavar_location(psess, &stack, sp, tt, &mut marker) } MatchedSingle(ParseNtResult::Ident(ident, is_raw)) => { @@ -325,6 +326,11 @@ pub(super) fn transcribe<'a>( MatchedSingle(ParseNtResult::Item(item)) => { mk_delimited(item.span, MetaVarKind::Item, TokenStream::from_ast(item)) } + MatchedSingle(ParseNtResult::Block(block)) => mk_delimited( + block.span, + MetaVarKind::Block, + TokenStream::from_ast(block), + ), MatchedSingle(ParseNtResult::Stmt(stmt)) => { let stream = if let StmtKind::Empty = stmt.kind { // FIXME: Properly collect tokens for empty statements. @@ -385,15 +391,6 @@ pub(super) fn transcribe<'a>( MatchedSingle(ParseNtResult::Vis(vis)) => { mk_delimited(vis.span, MetaVarKind::Vis, TokenStream::from_ast(vis)) } - MatchedSingle(ParseNtResult::Nt(nt)) => { - // Other variables are emitted into the output stream as groups with - // `Delimiter::Invisible` to maintain parsing priorities. - // `Interpolated` is currently used for such groups in rustc parser. - marker.visit_span(&mut sp); - let use_span = nt.use_span(); - with_metavar_spans(|mspans| mspans.insert(use_span, sp)); - TokenTree::token_alone(token::Interpolated(Arc::clone(nt)), sp) - } MatchedSeq(..) => { // We were unable to descend far enough. This is an error. return Err(dcx.create_err(VarStillRepeating { span: sp, ident })); diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index ee6306e39610..2706a5eb3d7f 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -309,15 +309,6 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec { - let stream = TokenStream::from_nonterminal_ast(&nt); - trees.push(TokenTree::Group(Group { - delimiter: pm::Delimiter::None, - stream: Some(stream), - span: DelimSpan::from_single(span), - })) - } - OpenDelim(..) | CloseDelim(..) => unreachable!(), Eof => unreachable!(), } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index e1e6b93abf35..83df18ae2867 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -637,9 +637,7 @@ impl<'a> Parser<'a> { /// Returns the span of expr if it was not interpolated, or the span of the interpolated token. fn interpolated_or_expr_span(&self, expr: &Expr) -> Span { match self.prev_token.kind { - TokenKind::NtIdent(..) | TokenKind::NtLifetime(..) | TokenKind::Interpolated(..) => { - self.prev_token.span - } + TokenKind::NtIdent(..) | TokenKind::NtLifetime(..) => self.prev_token.span, TokenKind::CloseDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(_))) => { // `expr.span` is the interpolated span, because invisible open // and close delims both get marked with the same span, one @@ -1386,15 +1384,7 @@ impl<'a> Parser<'a> { maybe_recover_from_interpolated_ty_qpath!(self, true); let span = self.token.span; - if let token::Interpolated(nt) = &self.token.kind { - match &**nt { - token::NtBlock(block) => { - let block = block.clone(); - self.bump(); - return Ok(self.mk_expr(self.prev_token.span, ExprKind::Block(block, None))); - } - }; - } else if let Some(expr) = self.eat_metavar_seq_with_matcher( + if let Some(expr) = self.eat_metavar_seq_with_matcher( |mv_kind| matches!(mv_kind, MetaVarKind::Expr { .. }), |this| { // Force collection (as opposed to just `parse_expr`) is required to avoid the @@ -1415,9 +1405,13 @@ impl<'a> Parser<'a> { self.eat_metavar_seq(MetaVarKind::Literal, |this| this.parse_literal_maybe_minus()) { return Ok(lit); - } else if let Some(path) = self.eat_metavar_seq(MetaVarKind::Path, |this| { - this.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type)) - }) { + } else if let Some(block) = + self.eat_metavar_seq(MetaVarKind::Block, |this| this.parse_block()) + { + return Ok(self.mk_expr(span, ExprKind::Block(block, None))); + } else if let Some(path) = + self.eat_metavar_seq(MetaVarKind::Path, |this| this.parse_path(PathStyle::Type)) + { return Ok(self.mk_expr(span, ExprKind::Path(None, path))); } @@ -1671,7 +1665,7 @@ impl<'a> Parser<'a> { } else if self.eat_keyword(exp!(Loop)) { self.parse_expr_loop(label, lo) } else if self.check_noexpect(&token::OpenDelim(Delimiter::Brace)) - || self.token.is_whole_block() + || self.token.is_metavar_block() { self.parse_expr_block(label, lo, BlockCheckMode::Default) } else if !ate_colon @@ -2349,7 +2343,7 @@ impl<'a> Parser<'a> { } } - if self.token.is_whole_block() { + if self.token.is_metavar_block() { self.dcx().emit_err(errors::InvalidBlockMacroSegment { span: self.token.span, context: lo.to(self.token.span), @@ -2472,7 +2466,7 @@ impl<'a> Parser<'a> { if self.may_recover() && self.token.can_begin_expr() && !matches!(self.token.kind, TokenKind::OpenDelim(Delimiter::Brace)) - && !self.token.is_whole_block() + && !self.token.is_metavar_block() { let snapshot = self.create_snapshot_for_diagnostic(); let restrictions = @@ -3519,7 +3513,7 @@ impl<'a> Parser<'a> { self.token.is_keyword(kw::Do) && self.is_keyword_ahead(1, &[kw::Catch]) && self - .look_ahead(2, |t| *t == token::OpenDelim(Delimiter::Brace) || t.is_whole_block()) + .look_ahead(2, |t| *t == token::OpenDelim(Delimiter::Brace) || t.is_metavar_block()) && !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL) } @@ -3530,7 +3524,7 @@ impl<'a> Parser<'a> { fn is_try_block(&self) -> bool { self.token.is_keyword(kw::Try) && self - .look_ahead(1, |t| *t == token::OpenDelim(Delimiter::Brace) || t.is_whole_block()) + .look_ahead(1, |t| *t == token::OpenDelim(Delimiter::Brace) || t.is_metavar_block()) && self.token_uninterpolated_span().at_least_rust_2018() } @@ -3564,12 +3558,12 @@ impl<'a> Parser<'a> { // `async move {` self.is_keyword_ahead(lookahead + 1, &[kw::Move, kw::Use]) && self.look_ahead(lookahead + 2, |t| { - *t == token::OpenDelim(Delimiter::Brace) || t.is_whole_block() + *t == token::OpenDelim(Delimiter::Brace) || t.is_metavar_block() }) ) || ( // `async {` self.look_ahead(lookahead + 1, |t| { - *t == token::OpenDelim(Delimiter::Brace) || t.is_whole_block() + *t == token::OpenDelim(Delimiter::Brace) || t.is_metavar_block() }) )) } diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index a8208e4717bd..83c0bceb20a4 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -2543,7 +2543,7 @@ impl<'a> Parser<'a> { self.expect_semi()?; *sig_hi = self.prev_token.span; (AttrVec::new(), None) - } else if self.check(exp!(OpenBrace)) || self.token.is_whole_block() { + } else if self.check(exp!(OpenBrace)) || self.token.is_metavar_block() { self.parse_block_common(self.token.span, BlockCheckMode::Default, None) .map(|(attrs, body)| (attrs, Some(body)))? } else if self.token == token::Eq { diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 392a1c1057ab..bb9393b8918b 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -13,7 +13,6 @@ mod ty; use std::assert_matches::debug_assert_matches; use std::ops::Range; -use std::sync::Arc; use std::{fmt, mem, slice}; use attr_wrapper::{AttrWrapper, UsePreAttrPos}; @@ -24,8 +23,8 @@ pub use pat::{CommaRecoveryMode, RecoverColon, RecoverComma}; use path::PathStyle; use rustc_ast::ptr::P; use rustc_ast::token::{ - self, Delimiter, IdentIsRaw, InvisibleOrigin, MetaVarKind, Nonterminal, NtExprKind, NtPatKind, - Token, TokenKind, + self, Delimiter, IdentIsRaw, InvisibleOrigin, MetaVarKind, NtExprKind, NtPatKind, Token, + TokenKind, }; use rustc_ast::tokenstream::{AttrsTarget, Spacing, TokenStream, TokenTree}; use rustc_ast::util::case::Case; @@ -98,21 +97,6 @@ pub enum ForceCollect { No, } -#[macro_export] -macro_rules! maybe_whole { - ($p:expr, $constructor:ident, |$x:ident| $e:expr) => { - #[allow(irrefutable_let_patterns)] // FIXME: temporary - if let token::Interpolated(nt) = &$p.token.kind - && let token::$constructor(x) = &**nt - { - #[allow(unused_mut)] - let mut $x = x.clone(); - $p.bump(); - return Ok($e); - } - }; -} - /// If the next tokens are ill-formed `$ty::` recover them as `<$ty>::`. #[macro_export] macro_rules! maybe_recover_from_interpolated_ty_qpath { @@ -459,7 +443,6 @@ pub fn token_descr(token: &Token) -> String { (Some(TokenDescription::MetaVar(kind)), _) => format!("`{kind}` metavariable"), (None, TokenKind::NtIdent(..)) => format!("identifier `{s}`"), (None, TokenKind::NtLifetime(..)) => format!("lifetime `{s}`"), - (None, TokenKind::Interpolated(node)) => format!("{} `{s}`", node.descr()), (None, _) => format!("`{s}`"), } } @@ -828,8 +811,10 @@ impl<'a> Parser<'a> { fn check_inline_const(&self, dist: usize) -> bool { self.is_keyword_ahead(dist, &[kw::Const]) && self.look_ahead(dist + 1, |t| match &t.kind { - token::Interpolated(nt) => matches!(&**nt, token::NtBlock(..)), token::OpenDelim(Delimiter::Brace) => true, + token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar( + MetaVarKind::Block, + ))) => true, _ => false, }) } @@ -1375,7 +1360,7 @@ impl<'a> Parser<'a> { // Avoid const blocks and const closures to be parsed as const items if (self.check_const_closure() == is_closure) && !self - .look_ahead(1, |t| *t == token::OpenDelim(Delimiter::Brace) || t.is_whole_block()) + .look_ahead(1, |t| *t == token::OpenDelim(Delimiter::Brace) || t.is_metavar_block()) && self.eat_keyword_case(exp!(Const), case) { Const::Yes(self.prev_token_uninterpolated_span()) @@ -1732,7 +1717,6 @@ impl<'a> Parser<'a> { pub fn token_uninterpolated_span(&self) -> Span { match &self.token.kind { token::NtIdent(ident, _) | token::NtLifetime(ident, _) => ident.span, - token::Interpolated(nt) => nt.use_span(), token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(_))) => { self.look_ahead(1, |t| t.span) } @@ -1744,7 +1728,6 @@ impl<'a> Parser<'a> { pub fn prev_token_uninterpolated_span(&self) -> Span { match &self.prev_token.kind { token::NtIdent(ident, _) | token::NtLifetime(ident, _) => ident.span, - token::Interpolated(nt) => nt.use_span(), token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(_))) => { self.look_ahead(0, |t| t.span) } @@ -1801,6 +1784,7 @@ pub enum ParseNtResult { Ident(Ident, IdentIsRaw), Lifetime(Ident, IdentIsRaw), Item(P), + Block(P), Stmt(P), Pat(P, NtPatKind), Expr(P, NtExprKind), @@ -1809,7 +1793,4 @@ pub enum ParseNtResult { Meta(P), Path(P), Vis(P), - - /// This variant will eventually be removed, along with `Token::Interpolate`. - Nt(Arc), } diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index b4e540d670d1..576de7766849 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -1,14 +1,7 @@ -use std::sync::Arc; - -use rustc_ast::HasTokens; use rustc_ast::ptr::P; -use rustc_ast::token::Nonterminal::*; use rustc_ast::token::NtExprKind::*; use rustc_ast::token::NtPatKind::*; -use rustc_ast::token::{ - self, Delimiter, InvisibleOrigin, MetaVarKind, Nonterminal, NonterminalKind, Token, -}; -use rustc_ast_pretty::pprust; +use rustc_ast::token::{self, Delimiter, InvisibleOrigin, MetaVarKind, NonterminalKind, Token}; use rustc_errors::PResult; use rustc_span::{Ident, kw}; @@ -45,13 +38,6 @@ impl<'a> Parser<'a> { } } - /// Old variant of `may_be_ident`. Being phased out. - fn nt_may_be_ident(nt: &Nonterminal) -> bool { - match nt { - NtBlock(_) => false, - } - } - match kind { // `expr_2021` and earlier NonterminalKind::Expr(Expr2021 { .. }) => { @@ -83,16 +69,12 @@ impl<'a> Parser<'a> { | token::Ident(..) | token::NtIdent(..) | token::NtLifetime(..) - | token::Interpolated(_) | token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(_))) => true, _ => token.can_begin_type(), }, NonterminalKind::Block => match &token.kind { token::OpenDelim(Delimiter::Brace) => true, token::NtLifetime(..) => true, - token::Interpolated(nt) => match &**nt { - NtBlock(_) => true, - }, token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(k))) => match k { MetaVarKind::Block | MetaVarKind::Stmt @@ -112,7 +94,6 @@ impl<'a> Parser<'a> { }, NonterminalKind::Path | NonterminalKind::Meta => match &token.kind { token::PathSep | token::Ident(..) | token::NtIdent(..) => true, - token::Interpolated(nt) => nt_may_be_ident(nt), token::OpenDelim(Delimiter::Invisible(InvisibleOrigin::MetaVar(kind))) => { may_be_ident(*kind) } @@ -136,62 +117,52 @@ impl<'a> Parser<'a> { // A `macro_rules!` invocation may pass a captured item/expr to a proc-macro, // which requires having captured tokens available. Since we cannot determine // in advance whether or not a proc-macro will be (transitively) invoked, - // we always capture tokens for any `Nonterminal` which needs them. - let mut nt = match kind { + // we always capture tokens for any nonterminal that needs them. + match kind { // Note that TT is treated differently to all the others. - NonterminalKind::TT => return Ok(ParseNtResult::Tt(self.parse_token_tree())), + NonterminalKind::TT => Ok(ParseNtResult::Tt(self.parse_token_tree())), NonterminalKind::Item => match self.parse_item(ForceCollect::Yes)? { - Some(item) => return Ok(ParseNtResult::Item(item)), - None => { - return Err(self - .dcx() - .create_err(UnexpectedNonterminal::Item(self.token.span))); - } + Some(item) => Ok(ParseNtResult::Item(item)), + None => Err(self.dcx().create_err(UnexpectedNonterminal::Item(self.token.span))), }, NonterminalKind::Block => { // While a block *expression* may have attributes (e.g. `#[my_attr] { ... }`), // the ':block' matcher does not support them - NtBlock(self.collect_tokens_no_attrs(|this| this.parse_block())?) + Ok(ParseNtResult::Block(self.collect_tokens_no_attrs(|this| this.parse_block())?)) } NonterminalKind::Stmt => match self.parse_stmt(ForceCollect::Yes)? { - Some(stmt) => return Ok(ParseNtResult::Stmt(P(stmt))), + Some(stmt) => Ok(ParseNtResult::Stmt(P(stmt))), None => { - return Err(self - .dcx() - .create_err(UnexpectedNonterminal::Statement(self.token.span))); + Err(self.dcx().create_err(UnexpectedNonterminal::Statement(self.token.span))) } }, - NonterminalKind::Pat(pat_kind) => { - return Ok(ParseNtResult::Pat( - self.collect_tokens_no_attrs(|this| match pat_kind { - PatParam { .. } => this.parse_pat_no_top_alt(None, None), - PatWithOr => this.parse_pat_no_top_guard( - None, - RecoverComma::No, - RecoverColon::No, - CommaRecoveryMode::EitherTupleOrPipe, - ), - })?, - pat_kind, - )); - } + NonterminalKind::Pat(pat_kind) => Ok(ParseNtResult::Pat( + self.collect_tokens_no_attrs(|this| match pat_kind { + PatParam { .. } => this.parse_pat_no_top_alt(None, None), + PatWithOr => this.parse_pat_no_top_guard( + None, + RecoverComma::No, + RecoverColon::No, + CommaRecoveryMode::EitherTupleOrPipe, + ), + })?, + pat_kind, + )), NonterminalKind::Expr(expr_kind) => { - return Ok(ParseNtResult::Expr(self.parse_expr_force_collect()?, expr_kind)); + Ok(ParseNtResult::Expr(self.parse_expr_force_collect()?, expr_kind)) } NonterminalKind::Literal => { // The `:literal` matcher does not support attributes. - return Ok(ParseNtResult::Literal( + Ok(ParseNtResult::Literal( self.collect_tokens_no_attrs(|this| this.parse_literal_maybe_minus())?, - )); + )) } - NonterminalKind::Ty => { - return Ok(ParseNtResult::Ty( - self.collect_tokens_no_attrs(|this| this.parse_ty_no_question_mark_recover())?, - )); - } - // this could be handled like a token, since it is one + NonterminalKind::Ty => Ok(ParseNtResult::Ty( + self.collect_tokens_no_attrs(|this| this.parse_ty_no_question_mark_recover())?, + )), + // This could be handled like a token, since it is one. NonterminalKind::Ident => { - return if let Some((ident, is_raw)) = get_macro_ident(&self.token) { + if let Some((ident, is_raw)) = get_macro_ident(&self.token) { self.bump(); Ok(ParseNtResult::Ident(ident, is_raw)) } else { @@ -199,25 +170,22 @@ impl<'a> Parser<'a> { span: self.token.span, token: self.token.clone(), })) - }; - } - NonterminalKind::Path => { - return Ok(ParseNtResult::Path(P( - self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))? - ))); + } } + NonterminalKind::Path => Ok(ParseNtResult::Path(P( + self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))? + ))), NonterminalKind::Meta => { - return Ok(ParseNtResult::Meta(P(self.parse_attr_item(ForceCollect::Yes)?))); + Ok(ParseNtResult::Meta(P(self.parse_attr_item(ForceCollect::Yes)?))) } NonterminalKind::Vis => { - return Ok(ParseNtResult::Vis(P(self.collect_tokens_no_attrs(|this| { - this.parse_visibility(FollowedByType::Yes) - })?))); + Ok(ParseNtResult::Vis(P(self + .collect_tokens_no_attrs(|this| this.parse_visibility(FollowedByType::Yes))?))) } NonterminalKind::Lifetime => { // We want to keep `'keyword` parsing, just like `keyword` is still // an ident for nonterminal purposes. - return if let Some((ident, is_raw)) = self.token.lifetime() { + if let Some((ident, is_raw)) = self.token.lifetime() { self.bump(); Ok(ParseNtResult::Lifetime(ident, is_raw)) } else { @@ -225,21 +193,9 @@ impl<'a> Parser<'a> { span: self.token.span, token: self.token.clone(), })) - }; + } } - }; - - // If tokens are supported at all, they should be collected. - if matches!(nt.tokens_mut(), Some(None)) { - panic!( - "Missing tokens for nt {:?} at {:?}: {:?}", - nt, - nt.use_span(), - pprust::nonterminal_to_string(&nt) - ); } - - Ok(ParseNtResult::Nt(Arc::new(nt))) } } diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 97cd4d2117f8..953bc3030126 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -23,8 +23,8 @@ use super::{ AttrWrapper, BlockMode, FnParseMode, ForceCollect, Parser, Restrictions, SemiColonMode, Trailing, UsePreAttrPos, }; -use crate::errors::MalformedLoopLabel; -use crate::{errors, exp, maybe_whole}; +use crate::errors::{self, MalformedLoopLabel}; +use crate::exp; impl<'a> Parser<'a> { /// Parses a statement. This stops just before trailing semicolons on everything but items. @@ -681,7 +681,9 @@ impl<'a> Parser<'a> { blk_mode: BlockCheckMode, loop_header: Option, ) -> PResult<'a, (AttrVec, P)> { - maybe_whole!(self, NtBlock, |block| (AttrVec::new(), block)); + if let Some(block) = self.eat_metavar_seq(MetaVarKind::Block, |this| this.parse_block()) { + return Ok((AttrVec::new(), block)); + } let maybe_ident = self.prev_token.clone(); self.maybe_recover_unexpected_block_label(loop_header); @@ -896,7 +898,7 @@ impl<'a> Parser<'a> { { if self.token == token::Colon && self.look_ahead(1, |token| { - token.is_whole_block() + token.is_metavar_block() || matches!( token.kind, token::Ident( diff --git a/tests/ui/macros/macro-as-fn-body.rs b/tests/ui/macros/macro-as-fn-body.rs index e0542edc2a52..188c7f7f728c 100644 --- a/tests/ui/macros/macro-as-fn-body.rs +++ b/tests/ui/macros/macro-as-fn-body.rs @@ -1,7 +1,7 @@ // //@ run-pass // -// Description - ensure Interpolated blocks can act as valid function bodies +// Description - ensure block metavariables can act as valid function bodies // Covered cases: free functions, struct methods, and default trait functions macro_rules! def_fn { From 027251ff7da03a6c190bfb1e1756a23085e3ff35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Wed, 2 Apr 2025 07:02:25 +0200 Subject: [PATCH 081/606] Use a session counter to make anon dep nodes unique --- .../rustc_query_system/src/dep_graph/graph.rs | 9 ++------- .../src/dep_graph/serialized.rs | 15 ++++++++++++++- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 127dcd825da5..abd6120bf9df 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -1167,8 +1167,7 @@ pub(super) struct CurrentDepGraph { /// ID from the previous session. In order to side-step this problem, we make /// sure that anonymous `NodeId`s allocated in different sessions don't overlap. /// This is implemented by mixing a session-key into the ID fingerprint of - /// each anon node. The session-key is just a random number generated when - /// the `DepGraph` is created. + /// each anon node. The session-key is a hash of the number of previous sessions. anon_id_seed: Fingerprint, /// These are simple counters that are for profiling and @@ -1186,12 +1185,8 @@ impl CurrentDepGraph { record_stats: bool, previous: Arc, ) -> Self { - use std::time::{SystemTime, UNIX_EPOCH}; - - let duration = SystemTime::now().duration_since(UNIX_EPOCH).unwrap(); - let nanos = duration.as_nanos(); let mut stable_hasher = StableHasher::new(); - nanos.hash(&mut stable_hasher); + previous.session_count().hash(&mut stable_hasher); let anon_id_seed = stable_hasher.finish(); #[cfg(debug_assertions)] diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs index 7750d6d1fef4..9a639ede662c 100644 --- a/compiler/rustc_query_system/src/dep_graph/serialized.rs +++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs @@ -92,6 +92,9 @@ pub struct SerializedDepGraph { /// Stores a map from fingerprints to nodes per dep node kind. /// This is the reciprocal of `nodes`. index: Vec>, + /// The number of previous compilation sessions. This is used to generate + /// unique anon dep nodes per session. + session_count: u64, } impl SerializedDepGraph { @@ -146,6 +149,11 @@ impl SerializedDepGraph { pub fn node_count(&self) -> usize { self.nodes.len() } + + #[inline] + pub fn session_count(&self) -> u64 { + self.session_count + } } /// A packed representation of an edge's start index and byte width. @@ -252,6 +260,8 @@ impl SerializedDepGraph { .map(|_| UnhashMap::with_capacity_and_hasher(d.read_u32() as usize, Default::default())) .collect(); + let session_count = d.read_u64(); + for (idx, node) in nodes.iter_enumerated() { if index[node.kind.as_usize()].insert(node.hash, idx).is_some() { // Side effect nodes can have duplicates @@ -273,6 +283,7 @@ impl SerializedDepGraph { edge_list_indices, edge_list_data, index, + session_count, }) } } @@ -601,7 +612,7 @@ impl EncoderState { stats: _, kind_stats, marker: _, - previous: _, + previous, } = self; let node_count = total_node_count.try_into().unwrap(); @@ -612,6 +623,8 @@ impl EncoderState { count.encode(&mut encoder); } + previous.session_count.checked_add(1).unwrap().encode(&mut encoder); + debug!(?node_count, ?edge_count); debug!("position: {:?}", encoder.position()); IntEncodedWithFixedSize(node_count).encode(&mut encoder); From 4d8f7577b5f2f7c72d1e258c07b882d0afcf0956 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 16 May 2024 09:22:37 +1000 Subject: [PATCH 082/606] Impl `Copy` for `Token` and `TokenKind`. --- compiler/rustc_ast/src/token.rs | 4 ++-- compiler/rustc_ast/src/tokenstream.rs | 2 +- compiler/rustc_expand/src/mbe/diagnostics.rs | 2 +- compiler/rustc_expand/src/mbe/macro_parser.rs | 4 ++-- compiler/rustc_expand/src/mbe/macro_rules.rs | 8 ++++---- compiler/rustc_expand/src/mbe/quoted.rs | 4 ++-- compiler/rustc_expand/src/mbe/transcribe.rs | 4 ++-- .../rustc_parse/src/lexer/unicode_chars.rs | 2 +- .../rustc_parse/src/parser/attr_wrapper.rs | 4 ++-- .../rustc_parse/src/parser/diagnostics.rs | 10 +++++----- compiler/rustc_parse/src/parser/expr.rs | 20 +++++++++---------- compiler/rustc_parse/src/parser/item.rs | 5 ++--- compiler/rustc_parse/src/parser/mod.rs | 8 ++++---- .../rustc_parse/src/parser/nonterminal.rs | 4 ++-- compiler/rustc_parse/src/parser/pat.rs | 6 +++--- compiler/rustc_parse/src/parser/path.rs | 4 ++-- compiler/rustc_parse/src/parser/stmt.rs | 2 +- compiler/rustc_parse/src/parser/tests.rs | 2 +- compiler/rustc_parse/src/parser/ty.rs | 4 ++-- src/tools/rustfmt/src/macros.rs | 14 ++++++------- 20 files changed, 56 insertions(+), 57 deletions(-) diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index de80bb47aff2..9d56cc83ac8c 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -333,7 +333,7 @@ impl From for bool { } } -#[derive(Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] +#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] pub enum TokenKind { /* Expression-operator symbols. */ /// `=` @@ -471,7 +471,7 @@ pub enum TokenKind { Eof, } -#[derive(Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] +#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] pub struct Token { pub kind: TokenKind, pub span: Span, diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index 3b457303cac1..8260842fb879 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -482,7 +482,7 @@ impl TokenStream { Delimiter::Invisible(InvisibleOrigin::FlattenToken), TokenStream::token_alone(token::Lifetime(ident.name, is_raw), ident.span), ), - _ => TokenTree::Token(token.clone(), spacing), + _ => TokenTree::Token(*token, spacing), } } diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs index 30961a2b4044..b663e959744f 100644 --- a/compiler/rustc_expand/src/mbe/diagnostics.rs +++ b/compiler/rustc_expand/src/mbe/diagnostics.rs @@ -160,7 +160,7 @@ impl<'dcx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'dcx, 'match .is_none_or(|failure| failure.is_better_position(*approx_position)) { self.best_failure = Some(BestFailure { - token: token.clone(), + token: *token, position_in_tokenstream: *approx_position, msg, remaining_matcher: self diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs index d709fd792817..0065f83eb4ee 100644 --- a/compiler/rustc_expand/src/mbe/macro_parser.rs +++ b/compiler/rustc_expand/src/mbe/macro_parser.rs @@ -179,7 +179,7 @@ pub(super) fn compute_locs(matcher: &[TokenTree]) -> Vec { for tt in tts { match tt { TokenTree::Token(token) => { - locs.push(MatcherLoc::Token { token: token.clone() }); + locs.push(MatcherLoc::Token { token: *token }); } TokenTree::Delimited(span, _, delimited) => { let open_token = Token::new(token::OpenDelim(delimited.delim), span.open); @@ -648,7 +648,7 @@ impl TtParser { // There are no possible next positions AND we aren't waiting for the black-box // parser: syntax error. return Failure(T::build_failure( - parser.token.clone(), + parser.token, parser.approx_token_stream_pos(), "no rules expected this token in macro call", )); diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 77ec598e62a1..7ddd64d81d5a 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -778,7 +778,7 @@ impl<'tt> FirstSets<'tt> { // token could be the separator token itself. if let (Some(sep), true) = (&seq_rep.separator, subfirst.maybe_empty) { - first.add_one_maybe(TtHandle::from_token(sep.clone())); + first.add_one_maybe(TtHandle::from_token(*sep)); } // Reverse scan: Sequence comes before `first`. @@ -841,7 +841,7 @@ impl<'tt> FirstSets<'tt> { // If the sequence contents can be empty, then the first // token could be the separator token itself. if let (Some(sep), true) = (&seq_rep.separator, subfirst.maybe_empty) { - first.add_one_maybe(TtHandle::from_token(sep.clone())); + first.add_one_maybe(TtHandle::from_token(*sep)); } assert!(first.maybe_empty); @@ -917,7 +917,7 @@ impl<'tt> Clone for TtHandle<'tt> { // This variant *must* contain a `mbe::TokenTree::Token`, and not // any other variant of `mbe::TokenTree`. TtHandle::Token(mbe::TokenTree::Token(tok)) => { - TtHandle::Token(mbe::TokenTree::Token(tok.clone())) + TtHandle::Token(mbe::TokenTree::Token(*tok)) } _ => unreachable!(), @@ -1093,7 +1093,7 @@ fn check_matcher_core<'tt>( let mut new; let my_suffix = if let Some(sep) = &seq_rep.separator { new = suffix_first.clone(); - new.add_one_maybe(TtHandle::from_token(sep.clone())); + new.add_one_maybe(TtHandle::from_token(*sep)); &new } else { &suffix_first diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs index 0ea53627fe78..3f0372599565 100644 --- a/compiler/rustc_expand/src/mbe/quoted.rs +++ b/compiler/rustc_expand/src/mbe/quoted.rs @@ -283,7 +283,7 @@ fn parse_tree<'a>( } // `tree` is an arbitrary token. Keep it. - tokenstream::TokenTree::Token(token, _) => TokenTree::Token(token.clone()), + tokenstream::TokenTree::Token(token, _) => TokenTree::Token(*token), // `tree` is the beginning of a delimited set of tokens (e.g., `(` or `{`). We need to // descend into the delimited set and further parse it. @@ -321,7 +321,7 @@ fn parse_kleene_op( match iter.next() { Some(tokenstream::TokenTree::Token(token, _)) => match kleene_op(token) { Some(op) => Ok(Ok((op, token.span))), - None => Ok(Err(token.clone())), + None => Ok(Err(*token)), }, tree => Err(tree.map_or(span, tokenstream::TokenTree::span)), } diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index 79a5c7ea31be..39186319b1cc 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -164,7 +164,7 @@ pub(super) fn transcribe<'a>( if repeat_idx < repeat_len { frame.idx = 0; if let Some(sep) = sep { - result.push(TokenTree::Token(sep.clone(), Spacing::Alone)); + result.push(TokenTree::Token(*sep, Spacing::Alone)); } continue; } @@ -438,7 +438,7 @@ pub(super) fn transcribe<'a>( // Nothing much to do here. Just push the token to the result, being careful to // preserve syntax context. mbe::TokenTree::Token(token) => { - let mut token = token.clone(); + let mut token = *token; mut_visit::visit_token(&mut marker, &mut token); let tt = TokenTree::Token(token, Spacing::Alone); result.push(tt); diff --git a/compiler/rustc_parse/src/lexer/unicode_chars.rs b/compiler/rustc_parse/src/lexer/unicode_chars.rs index ff03b42484b4..2bfa1ea4e058 100644 --- a/compiler/rustc_parse/src/lexer/unicode_chars.rs +++ b/compiler/rustc_parse/src/lexer/unicode_chars.rs @@ -376,7 +376,7 @@ pub(super) fn check_for_substitution( ascii_name, }) }; - (token.clone(), sugg) + (*token, sugg) } /// Extract string if found at current position with given delimiters diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs index cff998fa1379..f1bd6a227309 100644 --- a/compiler/rustc_parse/src/parser/attr_wrapper.rs +++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs @@ -120,7 +120,7 @@ impl ToAttrTokenStream for LazyAttrTokenStreamImpl { // produce an empty `TokenStream` if no calls were made, and omit the // final token otherwise. let mut cursor_snapshot = self.cursor_snapshot.clone(); - let tokens = iter::once(FlatToken::Token(self.start_token.clone())) + let tokens = iter::once(FlatToken::Token(self.start_token)) .chain(iter::repeat_with(|| FlatToken::Token(cursor_snapshot.next()))) .take(self.num_calls as usize); @@ -186,7 +186,7 @@ impl ToAttrTokenStream for LazyAttrTokenStreamImpl { impl<'a> Parser<'a> { pub(super) fn collect_pos(&self) -> CollectPos { CollectPos { - start_token: (self.token.clone(), self.token_spacing), + start_token: (self.token, self.token_spacing), cursor_snapshot: self.token_cursor.clone(), start_pos: self.num_bump_calls, } diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index ef044fe9d638..bb63e91aecfa 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -322,7 +322,7 @@ impl<'a> Parser<'a> { let mut recovered_ident = None; // we take this here so that the correct original token is retained in // the diagnostic, regardless of eager recovery. - let bad_token = self.token.clone(); + let bad_token = self.token; // suggest prepending a keyword in identifier position with `r#` let suggest_raw = if let Some((ident, IdentIsRaw::No)) = self.token.ident() @@ -382,7 +382,7 @@ impl<'a> Parser<'a> { // if the previous token is a valid keyword // that might use a generic, then suggest a correct // generic placement (later on) - let maybe_keyword = self.prev_token.clone(); + let maybe_keyword = self.prev_token; if valid_prev_keywords.into_iter().any(|x| maybe_keyword.is_keyword(x)) { // if we have a valid keyword, attempt to parse generics // also obtain the keywords symbol @@ -530,7 +530,7 @@ impl<'a> Parser<'a> { // let y = 42; let guar = self.dcx().emit_err(ExpectedSemi { span: self.token.span, - token: self.token.clone(), + token: self.token, unexpected_token_label: None, sugg: ExpectedSemiSugg::ChangeToSemi(self.token.span), }); @@ -555,7 +555,7 @@ impl<'a> Parser<'a> { let span = self.prev_token.span.shrink_to_hi(); let guar = self.dcx().emit_err(ExpectedSemi { span, - token: self.token.clone(), + token: self.token, unexpected_token_label: Some(self.token.span), sugg: ExpectedSemiSugg::AddSemi(span), }); @@ -801,7 +801,7 @@ impl<'a> Parser<'a> { let span = self.prev_token.span.shrink_to_hi(); let mut err = self.dcx().create_err(ExpectedSemi { span, - token: self.token.clone(), + token: self.token, unexpected_token_label: Some(self.token.span), sugg: ExpectedSemiSugg::AddSemi(span), }); diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 83df18ae2867..c4ba62a7a4c4 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -344,7 +344,7 @@ impl<'a> Parser<'a> { fn error_found_expr_would_be_stmt(&self, lhs: &Expr) { self.dcx().emit_err(errors::FoundExprWouldBeStmt { span: self.token.span, - token: self.token.clone(), + token: self.token, suggestion: ExprParenthesesNeeded::surrounding(lhs.span), }); } @@ -417,7 +417,7 @@ impl<'a> Parser<'a> { cur_op_span: Span, ) -> PResult<'a, P> { let rhs = if self.is_at_start_of_range_notation_rhs() { - let maybe_lt = self.token.clone(); + let maybe_lt = self.token; let attrs = self.parse_outer_attributes()?; Some( self.parse_expr_assoc_with(Bound::Excluded(prec), attrs) @@ -611,7 +611,7 @@ impl<'a> Parser<'a> { /// Recover on `not expr` in favor of `!expr`. fn recover_not_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> { - let negated_token = self.look_ahead(1, |t| t.clone()); + let negated_token = self.look_ahead(1, |t| *t); let sub_diag = if negated_token.is_numeric_lit() { errors::NotAsNegationOperatorSub::SuggestNotBitwise @@ -1606,7 +1606,7 @@ impl<'a> Parser<'a> { } fn parse_expr_path_start(&mut self) -> PResult<'a, P> { - let maybe_eq_tok = self.prev_token.clone(); + let maybe_eq_tok = self.prev_token; let (qself, path) = if self.eat_lt() { let lt_span = self.prev_token.span; let (qself, path) = self.parse_qpath(PathStyle::Expr).map_err(|mut err| { @@ -2067,7 +2067,7 @@ impl<'a> Parser<'a> { &mut self, mk_lit_char: impl FnOnce(Symbol, Span) -> L, ) -> PResult<'a, L> { - let token = self.token.clone(); + let token = self.token; let err = |self_: &Self| { let msg = format!("unexpected token: {}", super::token_descr(&token)); self_.dcx().struct_span_err(token.span, msg) @@ -2368,7 +2368,7 @@ impl<'a> Parser<'a> { fn parse_expr_closure(&mut self) -> PResult<'a, P> { let lo = self.token.span; - let before = self.prev_token.clone(); + let before = self.prev_token; let binder = if self.check_keyword(exp!(For)) { let lo = self.token.span; let (lifetime_defs, _) = self.parse_late_bound_lifetime_defs()?; @@ -2400,8 +2400,8 @@ impl<'a> Parser<'a> { FnRetTy::Default(_) => { let restrictions = self.restrictions - Restrictions::STMT_EXPR - Restrictions::ALLOW_LET; - let prev = self.prev_token.clone(); - let token = self.token.clone(); + let prev = self.prev_token; + let token = self.token; let attrs = self.parse_outer_attributes()?; match self.parse_expr_res(restrictions, attrs) { Ok((expr, _)) => expr, @@ -2648,7 +2648,7 @@ impl<'a> Parser<'a> { } } else { let attrs = self.parse_outer_attributes()?; // For recovery. - let maybe_fatarrow = self.token.clone(); + let maybe_fatarrow = self.token; let block = if self.check(exp!(OpenBrace)) { self.parse_block()? } else if let Some(block) = recover_block_from_condition(self) { @@ -3856,7 +3856,7 @@ impl<'a> Parser<'a> { return Err(this.dcx().create_err(errors::ExpectedStructField { span: this.look_ahead(1, |t| t.span), ident_span: this.token.span, - token: this.look_ahead(1, |t| t.clone()), + token: this.look_ahead(1, |t| *t), })); } let (ident, expr) = if is_shorthand { diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 83c0bceb20a4..73dc5c17a204 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1739,8 +1739,7 @@ impl<'a> Parser<'a> { self.expect_semi()?; body } else { - let err = - errors::UnexpectedTokenAfterStructName::new(self.token.span, self.token.clone()); + let err = errors::UnexpectedTokenAfterStructName::new(self.token.span, self.token); return Err(self.dcx().create_err(err)); }; @@ -2310,7 +2309,7 @@ impl<'a> Parser<'a> { || self.token.is_keyword(kw::Union)) && self.look_ahead(1, |t| t.is_ident()) { - let kw_token = self.token.clone(); + let kw_token = self.token; let kw_str = pprust::token_to_string(&kw_token); let item = self.parse_item(ForceCollect::No)?; let mut item = item.unwrap().span; diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index bb9393b8918b..d7525a0d716d 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -326,12 +326,12 @@ impl TokenCursor { // below can be removed. if let Some(tree) = self.curr.curr() { match tree { - &TokenTree::Token(ref token, spacing) => { + &TokenTree::Token(token, spacing) => { debug_assert!(!matches!( token.kind, token::OpenDelim(_) | token::CloseDelim(_) )); - let res = (token.clone(), spacing); + let res = (token, spacing); self.curr.bump(); return res; } @@ -1490,7 +1490,7 @@ impl<'a> Parser<'a> { _ => { let prev_spacing = self.token_spacing; self.bump(); - TokenTree::Token(self.prev_token.clone(), prev_spacing) + TokenTree::Token(self.prev_token, prev_spacing) } } } @@ -1676,7 +1676,7 @@ impl<'a> Parser<'a> { dbg_fmt.field("prev_token", &self.prev_token); let mut tokens = vec![]; for i in 0..lookahead { - let tok = self.look_ahead(i, |tok| tok.kind.clone()); + let tok = self.look_ahead(i, |tok| tok.kind); let is_eof = tok == TokenKind::Eof; tokens.push(tok); if is_eof { diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 576de7766849..b6e89cd7fa46 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -168,7 +168,7 @@ impl<'a> Parser<'a> { } else { Err(self.dcx().create_err(UnexpectedNonterminal::Ident { span: self.token.span, - token: self.token.clone(), + token: self.token, })) } } @@ -191,7 +191,7 @@ impl<'a> Parser<'a> { } else { Err(self.dcx().create_err(UnexpectedNonterminal::Lifetime { span: self.token.span, - token: self.token.clone(), + token: self.token, })) } } diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 9612f71b2af9..d5f469f9aa9e 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -363,7 +363,7 @@ impl<'a> Parser<'a> { self.dcx().emit_err(TrailingVertNotAllowed { span: self.token.span, start: lo, - token: self.token.clone(), + token: self.token, note_double_vert: matches!(self.token.kind, token::OrOr), }); self.bump(); @@ -1519,8 +1519,8 @@ impl<'a> Parser<'a> { etc = PatFieldsRest::Rest; let mut etc_sp = self.token.span; if first_etc_and_maybe_comma_span.is_none() { - if let Some(comma_tok) = self - .look_ahead(1, |t| if *t == token::Comma { Some(t.clone()) } else { None }) + if let Some(comma_tok) = + self.look_ahead(1, |&t| if t == token::Comma { Some(t) } else { None }) { let nw_span = self .psess diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 9c6830c36727..30fb96c6ea90 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -393,8 +393,8 @@ impl<'a> Parser<'a> { } else { // `(T, U) -> R` - let prev_token_before_parsing = self.prev_token.clone(); - let token_before_parsing = self.token.clone(); + let prev_token_before_parsing = self.prev_token; + let token_before_parsing = self.token; let mut snapshot = None; if self.may_recover() && prev_token_before_parsing == token::PathSep diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 953bc3030126..824e930aa88a 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -685,7 +685,7 @@ impl<'a> Parser<'a> { return Ok((AttrVec::new(), block)); } - let maybe_ident = self.prev_token.clone(); + let maybe_ident = self.prev_token; self.maybe_recover_unexpected_block_label(loop_header); if !self.eat(exp!(OpenBrace)) { return self.error_block_no_opening_brace(); diff --git a/compiler/rustc_parse/src/parser/tests.rs b/compiler/rustc_parse/src/parser/tests.rs index 49ae6cb9b726..2f958f4d4927 100644 --- a/compiler/rustc_parse/src/parser/tests.rs +++ b/compiler/rustc_parse/src/parser/tests.rs @@ -2554,7 +2554,7 @@ fn look(p: &Parser<'_>, dist: usize, kind: rustc_ast::token::TokenKind) { // Do the `assert_eq` outside the closure so that `track_caller` works. // (`#![feature(closure_track_caller)]` + `#[track_caller]` on the closure // doesn't give the line number in the test below if the assertion fails.) - let tok = p.look_ahead(dist, |tok| tok.clone()); + let tok = p.look_ahead(dist, |tok| *tok); assert_eq!(kind, tok.kind); } diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 93705da22c45..d0cff42a2091 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -547,7 +547,7 @@ impl<'a> Parser<'a> { // Recovery mutbl = Mutability::Mut; - let (dyn_tok, dyn_tok_sp) = (self.token.clone(), self.token_spacing); + let (dyn_tok, dyn_tok_sp) = (self.token, self.token_spacing); self.bump(); self.bump_with((dyn_tok, dyn_tok_sp)); } @@ -886,7 +886,7 @@ impl<'a> Parser<'a> { /// ``` fn parse_generic_bound(&mut self) -> PResult<'a, GenericBound> { let lo = self.token.span; - let leading_token = self.prev_token.clone(); + let leading_token = self.prev_token; let has_parens = self.eat(exp!(OpenParen)); let bound = if self.token.is_lifetime() { diff --git a/src/tools/rustfmt/src/macros.rs b/src/tools/rustfmt/src/macros.rs index ddf3d2ce96af..1e16aace3041 100644 --- a/src/tools/rustfmt/src/macros.rs +++ b/src/tools/rustfmt/src/macros.rs @@ -858,18 +858,18 @@ impl MacroArgParser { }; self.result.push(ParsedMacroArg { - kind: MacroArgKind::Repeat(delim, inner, another, self.last_tok.clone()), + kind: MacroArgKind::Repeat(delim, inner, another, self.last_tok), }); Some(()) } - fn update_buffer(&mut self, t: &Token) { + fn update_buffer(&mut self, t: Token) { if self.buf.is_empty() { - self.start_tok = t.clone(); + self.start_tok = t; } else { let needs_space = match next_space(&self.last_tok.kind) { - SpaceState::Ident => ident_like(t), - SpaceState::Punctuation => !ident_like(t), + SpaceState::Ident => ident_like(&t), + SpaceState::Punctuation => !ident_like(&t), SpaceState::Always => true, SpaceState::Never => false, }; @@ -878,7 +878,7 @@ impl MacroArgParser { } } - self.buf.push_str(&pprust::token_to_string(t)); + self.buf.push_str(&pprust::token_to_string(&t)); } fn need_space_prefix(&self) -> bool { @@ -937,7 +937,7 @@ impl MacroArgParser { ) if self.is_meta_var => { self.add_meta_variable(&mut iter)?; } - TokenTree::Token(ref t, _) => self.update_buffer(t), + &TokenTree::Token(t, _) => self.update_buffer(t), &TokenTree::Delimited(_dspan, _spacing, delimited, ref tts) => { if !self.buf.is_empty() { if next_space(&self.last_tok.kind) == SpaceState::Always { From 4c0cbaeb9e799362dd081ff8514f75e23ab8c2f5 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 4 Jul 2024 10:16:51 +1000 Subject: [PATCH 083/606] Remove `TokenStream::flattened` and `InvisibleOrigin::FlattenToken`. They are no longer needed. This does slightly worsen the error message for a single test, but that test contains code that is so badly broken that I'm not worried about it. --- compiler/rustc_ast/src/token.rs | 8 +--- compiler/rustc_ast/src/tokenstream.rs | 44 +------------------ compiler/rustc_ast_lowering/src/lib.rs | 2 +- compiler/rustc_attr_parsing/src/context.rs | 2 +- compiler/rustc_builtin_macros/src/cfg_eval.rs | 10 ++--- compiler/rustc_expand/src/config.rs | 6 --- tests/ui/macros/syntax-error-recovery.rs | 4 +- tests/ui/macros/syntax-error-recovery.stderr | 6 +-- 8 files changed, 12 insertions(+), 70 deletions(-) diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 9d56cc83ac8c..055481f5d878 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -30,10 +30,6 @@ pub enum InvisibleOrigin { // Converted from `proc_macro::Delimiter` in // `proc_macro::Delimiter::to_internal`, i.e. returned by a proc macro. ProcMacro, - - // Converted from `TokenKind::NtLifetime` in `TokenStream::flatten_token`. - // Treated similarly to `ProcMacro`. - FlattenToken, } impl PartialEq for InvisibleOrigin { @@ -130,9 +126,7 @@ impl Delimiter { match self { Delimiter::Parenthesis | Delimiter::Bracket | Delimiter::Brace => false, Delimiter::Invisible(InvisibleOrigin::MetaVar(_)) => false, - Delimiter::Invisible(InvisibleOrigin::FlattenToken | InvisibleOrigin::ProcMacro) => { - true - } + Delimiter::Invisible(InvisibleOrigin::ProcMacro) => true, } } diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index 8260842fb879..43d25d180750 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -25,7 +25,7 @@ use rustc_span::{DUMMY_SP, Span, SpanDecoder, SpanEncoder, Symbol, sym}; use crate::ast::AttrStyle; use crate::ast_traits::{HasAttrs, HasTokens}; -use crate::token::{self, Delimiter, InvisibleOrigin, Token, TokenKind}; +use crate::token::{self, Delimiter, Token, TokenKind}; use crate::{AttrVec, Attribute}; /// Part of a `TokenStream`. @@ -471,48 +471,6 @@ impl TokenStream { TokenStream::new(tts) } - fn flatten_token(token: &Token, spacing: Spacing) -> TokenTree { - match token.kind { - token::NtIdent(ident, is_raw) => { - TokenTree::Token(Token::new(token::Ident(ident.name, is_raw), ident.span), spacing) - } - token::NtLifetime(ident, is_raw) => TokenTree::Delimited( - DelimSpan::from_single(token.span), - DelimSpacing::new(Spacing::JointHidden, spacing), - Delimiter::Invisible(InvisibleOrigin::FlattenToken), - TokenStream::token_alone(token::Lifetime(ident.name, is_raw), ident.span), - ), - _ => TokenTree::Token(*token, spacing), - } - } - - fn flatten_token_tree(tree: &TokenTree) -> TokenTree { - match tree { - TokenTree::Token(token, spacing) => TokenStream::flatten_token(token, *spacing), - TokenTree::Delimited(span, spacing, delim, tts) => { - TokenTree::Delimited(*span, *spacing, *delim, tts.flattened()) - } - } - } - - #[must_use] - pub fn flattened(&self) -> TokenStream { - fn can_skip(stream: &TokenStream) -> bool { - stream.iter().all(|tree| match tree { - TokenTree::Token(token, _) => { - !matches!(token.kind, token::NtIdent(..) | token::NtLifetime(..)) - } - TokenTree::Delimited(.., inner) => can_skip(inner), - }) - } - - if can_skip(self) { - return self.clone(); - } - - self.iter().map(|tree| TokenStream::flatten_token_tree(tree)).collect() - } - // If `vec` is not empty, try to glue `tt` onto its last token. The return // value indicates if gluing took place. fn try_glue_to_last(vec: &mut Vec, tt: &TokenTree) -> bool { diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index d5d6dcd8d631..4fbd62864a1b 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -917,7 +917,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } fn lower_delim_args(&self, args: &DelimArgs) -> DelimArgs { - DelimArgs { dspan: args.dspan, delim: args.delim, tokens: args.tokens.flattened() } + DelimArgs { dspan: args.dspan, delim: args.delim, tokens: args.tokens.clone() } } /// Lower an associated item constraint. diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index a68d4578b40f..3bf03f84ce8f 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -320,7 +320,7 @@ impl<'sess> AttributeParser<'sess> { ast::AttrArgs::Delimited(args) => AttrArgs::Delimited(DelimArgs { dspan: args.dspan, delim: args.delim, - tokens: args.tokens.flattened(), + tokens: args.tokens.clone(), }), // This is an inert key-value attribute - it will never be visible to macros // after it gets lowered to HIR. Therefore, we can extract literals to handle diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs index ea0bbd0e31ad..da01e3e9607b 100644 --- a/compiler/rustc_builtin_macros/src/cfg_eval.rs +++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs @@ -92,11 +92,7 @@ impl CfgEval<'_> { // the location of `#[cfg]` and `#[cfg_attr]` in the token stream. The tokenization // process is lossless, so this process is invisible to proc-macros. - // 'Flatten' all nonterminals (i.e. `TokenKind::Nt{Ident,Lifetime}`) - // to `None`-delimited groups containing the corresponding tokens. This - // is normally delayed until the proc-macro server actually needs to - // provide tokens to a proc-macro. We do this earlier, so that we can - // handle cases like: + // Interesting cases: // // ```rust // #[cfg_eval] #[cfg] $item @@ -104,8 +100,8 @@ impl CfgEval<'_> { // // where `$item` is `#[cfg_attr] struct Foo {}`. We want to make // sure to evaluate *all* `#[cfg]` and `#[cfg_attr]` attributes - the simplest - // way to do this is to do a single parse of a stream without any nonterminals. - let orig_tokens = annotatable.to_tokens().flattened(); + // way to do this is to do a single parse of the token stream. + let orig_tokens = annotatable.to_tokens(); // Re-parse the tokens, setting the `capture_cfg` flag to save extra information // to the captured `AttrTokenStream` (specifically, we capture diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index 27924544de52..c70e259b2cd8 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -237,12 +237,6 @@ impl<'a> StripUnconfigured<'a> { inner = self.configure_tokens(&inner); Some(AttrTokenTree::Delimited(sp, spacing, delim, inner)) } - AttrTokenTree::Token( - Token { kind: TokenKind::NtIdent(..) | TokenKind::NtLifetime(..), .. }, - _, - ) => { - panic!("Nonterminal should have been flattened: {:?}", tree); - } AttrTokenTree::Token( Token { kind: TokenKind::OpenDelim(_) | TokenKind::CloseDelim(_), .. }, _, diff --git a/tests/ui/macros/syntax-error-recovery.rs b/tests/ui/macros/syntax-error-recovery.rs index 6cf9d54e8263..e1681ea32a2e 100644 --- a/tests/ui/macros/syntax-error-recovery.rs +++ b/tests/ui/macros/syntax-error-recovery.rs @@ -5,14 +5,14 @@ macro_rules! values { $( #[$attr] $token $($inner)? = $value, + //~^ ERROR expected one of `!` or `::`, found `` )* } }; } -//~^^^^^ ERROR expected one of `(`, `,`, `=`, `{`, or `}`, found `ty` metavariable +//~^^^^^^ ERROR expected one of `(`, `,`, `=`, `{`, or `}`, found `ty` metavariable //~| ERROR macro expansion ignores `ty` metavariable and any tokens following values!(STRING(1) as (String) => cfg(test),); -//~^ ERROR expected one of `!` or `::`, found `` fn main() {} diff --git a/tests/ui/macros/syntax-error-recovery.stderr b/tests/ui/macros/syntax-error-recovery.stderr index 61758fb9d7dc..a2059aa1aa80 100644 --- a/tests/ui/macros/syntax-error-recovery.stderr +++ b/tests/ui/macros/syntax-error-recovery.stderr @@ -22,10 +22,10 @@ LL | values!(STRING(1) as (String) => cfg(test),); = note: the usage of `values!` is likely invalid in item context error: expected one of `!` or `::`, found `` - --> $DIR/syntax-error-recovery.rs:15:9 + --> $DIR/syntax-error-recovery.rs:7:17 | -LL | values!(STRING(1) as (String) => cfg(test),); - | ^^^^^^ expected one of `!` or `::` +LL | $token $($inner)? = $value, + | ^^^^^^ expected one of `!` or `::` error: aborting due to 3 previous errors From 1830245a224c523f86ad3c62be76be3f336a9fb0 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 2 Apr 2025 16:25:27 +1100 Subject: [PATCH 084/606] Remove `recursion_limit` increases. These are no longer needed now that `Nonterminal` is gone. --- compiler/rustc_ast/src/lib.rs | 1 - compiler/rustc_ast_lowering/src/lib.rs | 1 - compiler/rustc_attr_parsing/src/lib.rs | 1 - compiler/rustc_borrowck/src/lib.rs | 1 - compiler/rustc_builtin_macros/src/lib.rs | 1 - compiler/rustc_codegen_ssa/src/lib.rs | 1 - compiler/rustc_const_eval/src/lib.rs | 1 - compiler/rustc_driver/src/lib.rs | 1 - compiler/rustc_driver_impl/src/lib.rs | 1 - compiler/rustc_hir/src/lib.rs | 1 - compiler/rustc_hir_analysis/src/lib.rs | 1 - compiler/rustc_hir_typeck/src/lib.rs | 1 - compiler/rustc_incremental/src/lib.rs | 1 - compiler/rustc_lint/src/lib.rs | 1 - compiler/rustc_metadata/src/lib.rs | 1 - compiler/rustc_middle/src/lib.rs | 1 - compiler/rustc_mir_build/src/lib.rs | 1 - compiler/rustc_mir_dataflow/src/lib.rs | 1 - compiler/rustc_mir_transform/src/lib.rs | 1 - compiler/rustc_monomorphize/src/lib.rs | 1 - compiler/rustc_parse/src/lib.rs | 1 - compiler/rustc_passes/src/lib.rs | 1 - compiler/rustc_privacy/src/lib.rs | 1 - compiler/rustc_query_impl/src/lib.rs | 1 - compiler/rustc_sanitizers/src/lib.rs | 1 - compiler/rustc_smir/src/lib.rs | 1 - compiler/rustc_symbol_mangling/src/lib.rs | 1 - compiler/rustc_transmute/src/lib.rs | 1 - compiler/rustc_ty_utils/src/lib.rs | 1 - 29 files changed, 29 deletions(-) diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs index da510e4967db..294c6c9ba7a5 100644 --- a/compiler/rustc_ast/src/lib.rs +++ b/compiler/rustc_ast/src/lib.rs @@ -6,7 +6,6 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141 #![doc( html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/", test(attr(deny(warnings))) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 4fbd62864a1b..17cac88aacbe 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -32,7 +32,6 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141 #![doc(rust_logo)] #![feature(assert_matches)] #![feature(box_patterns)] diff --git a/compiler/rustc_attr_parsing/src/lib.rs b/compiler/rustc_attr_parsing/src/lib.rs index a7465847e18b..249e71ef70dc 100644 --- a/compiler/rustc_attr_parsing/src/lib.rs +++ b/compiler/rustc_attr_parsing/src/lib.rs @@ -77,7 +77,6 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141 #![doc(rust_logo)] #![feature(let_chains)] #![feature(rustdoc_internals)] diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 84b7b8c6a2de..4a4a99aa154e 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -2,7 +2,6 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141 #![doc(rust_logo)] #![feature(assert_matches)] #![feature(box_patterns)] diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index 606e85577f7e..bcd40f980e64 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -5,7 +5,6 @@ #![allow(internal_features)] #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] -#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(assert_matches)] diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index d26d6edf3149..a49f82a2bca5 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -2,7 +2,6 @@ #![allow(internal_features)] #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] -#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(assert_matches)] diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index e03849c32f94..da52d60ae59f 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -1,7 +1,6 @@ // tidy-alphabetical-start #![allow(internal_features)] #![allow(rustc::diagnostic_outside_of_impl)] -#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141 #![doc(rust_logo)] #![feature(assert_matches)] #![feature(box_patterns)] diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 381309f83b2c..a03834c519d5 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -3,7 +3,6 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141 #![doc(rust_logo)] #![feature(rustdoc_internals)] // tidy-alphabetical-end diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 37755e7d61db..d3d435b01e99 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -7,7 +7,6 @@ // tidy-alphabetical-start #![allow(internal_features)] #![allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable -#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(decl_macro)] diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index 4a839d405718..84d369f1eddb 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -4,7 +4,6 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141 #![feature(associated_type_defaults)] #![feature(box_patterns)] #![feature(closure_track_caller)] diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index e7ecd727a852..e1ad8124aea7 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -59,7 +59,6 @@ This API is completely unstable and subject to change. #![allow(internal_features)] #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] -#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(assert_matches)] diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 4968998fd512..263fb84206e0 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -1,7 +1,6 @@ // tidy-alphabetical-start #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] -#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141 #![feature(array_windows)] #![feature(box_patterns)] #![feature(if_let_guard)] diff --git a/compiler/rustc_incremental/src/lib.rs b/compiler/rustc_incremental/src/lib.rs index dabfb6a90cad..299ee4876389 100644 --- a/compiler/rustc_incremental/src/lib.rs +++ b/compiler/rustc_incremental/src/lib.rs @@ -2,7 +2,6 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141 #![deny(missing_docs)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 25878c7ac814..7b05b4d26d32 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -21,7 +21,6 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(array_windows)] diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index 028d5c8b6099..3b44c44fcb94 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -1,6 +1,5 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(coroutines)] diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 1e6178144c92..8fe2cc7101ba 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -29,7 +29,6 @@ #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::potential_query_instability)] #![allow(rustc::untranslatable_diagnostic)] -#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(allocator_api)] diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs index a25697ba086d..8e96d46dac27 100644 --- a/compiler/rustc_mir_build/src/lib.rs +++ b/compiler/rustc_mir_build/src/lib.rs @@ -3,7 +3,6 @@ // tidy-alphabetical-start #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] -#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141 #![feature(assert_matches)] #![feature(box_patterns)] #![feature(if_let_guard)] diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index 82c57ef5678d..a0efc623b8e7 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -1,5 +1,4 @@ // tidy-alphabetical-start -#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141 #![feature(assert_matches)] #![feature(associated_type_defaults)] #![feature(box_patterns)] diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 205d388f4fb5..739cee5d7f4c 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -1,5 +1,4 @@ // tidy-alphabetical-start -#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141 #![feature(array_windows)] #![feature(assert_matches)] #![feature(box_patterns)] diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs index 5dbae50c499f..8f6914f3d724 100644 --- a/compiler/rustc_monomorphize/src/lib.rs +++ b/compiler/rustc_monomorphize/src/lib.rs @@ -1,5 +1,4 @@ // tidy-alphabetical-start -#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141 #![feature(array_windows)] #![feature(file_buffered)] #![feature(if_let_guard)] diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index 79939aab7fc2..2edc8c83017d 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -4,7 +4,6 @@ #![allow(internal_features)] #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] -#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141 #![feature(array_windows)] #![feature(assert_matches)] #![feature(box_patterns)] diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index 6f6115af96c8..93ff0f66d695 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -6,7 +6,6 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(let_chains)] diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 643b82f47530..c7bab828659a 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -1,6 +1,5 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(associated_type_defaults)] diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 30a9e718d236..3c329dd0a0e8 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -3,7 +3,6 @@ // tidy-alphabetical-start #![allow(internal_features)] #![allow(unused_parens)] -#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(min_specialization)] diff --git a/compiler/rustc_sanitizers/src/lib.rs b/compiler/rustc_sanitizers/src/lib.rs index c4a9cab24d07..e4792563e71e 100644 --- a/compiler/rustc_sanitizers/src/lib.rs +++ b/compiler/rustc_sanitizers/src/lib.rs @@ -4,7 +4,6 @@ //! compiler. // tidy-alphabetical-start -#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141 #![feature(let_chains)] // tidy-alphabetical-end diff --git a/compiler/rustc_smir/src/lib.rs b/compiler/rustc_smir/src/lib.rs index eaba14bbf30f..9f8888753061 100644 --- a/compiler/rustc_smir/src/lib.rs +++ b/compiler/rustc_smir/src/lib.rs @@ -9,7 +9,6 @@ // tidy-alphabetical-start #![allow(internal_features)] #![allow(rustc::usage_of_ty_tykind)] -#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141 #![doc( html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/", test(attr(allow(unused_variables), deny(warnings))) diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs index c9b15151a2cb..cc33974cc627 100644 --- a/compiler/rustc_symbol_mangling/src/lib.rs +++ b/compiler/rustc_symbol_mangling/src/lib.rs @@ -89,7 +89,6 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(let_chains)] diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs index 7d800e49ff45..00928137d297 100644 --- a/compiler/rustc_transmute/src/lib.rs +++ b/compiler/rustc_transmute/src/lib.rs @@ -1,5 +1,4 @@ // tidy-alphabetical-start -#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141 #![feature(never_type)] // tidy-alphabetical-end diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs index 143b7d538801..35cc6f398565 100644 --- a/compiler/rustc_ty_utils/src/lib.rs +++ b/compiler/rustc_ty_utils/src/lib.rs @@ -6,7 +6,6 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(assert_matches)] From 4a8d35709e301d983412b42b26dad6eb5c869951 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Wed, 2 Apr 2025 19:14:27 +0000 Subject: [PATCH 085/606] Revert "Disable `f16` on Aarch64 without `neon`" The LLVM issue [1] was resolved and the fix was synced to rust-lang/rust in [2]. This reverts commit c51b229140c885cac757a405a328a07e90d5bca9. [1]: https://github.com/llvm/llvm-project/issues/129394 [2]: https://github.com/rust-lang/rust/pull/138695 --- library/std/build.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/library/std/build.rs b/library/std/build.rs index d76d07a89f4e..40a56d4930d3 100644 --- a/library/std/build.rs +++ b/library/std/build.rs @@ -12,11 +12,6 @@ fn main() { .expect("CARGO_CFG_TARGET_POINTER_WIDTH was not set") .parse() .unwrap(); - let target_features: Vec<_> = env::var("CARGO_CFG_TARGET_FEATURE") - .unwrap_or_default() - .split(",") - .map(ToOwned::to_owned) - .collect(); let is_miri = env::var_os("CARGO_CFG_MIRI").is_some(); println!("cargo:rustc-check-cfg=cfg(netbsd10)"); @@ -108,8 +103,6 @@ fn main() { ("s390x", _) => false, // Unsupported ("arm64ec", _) => false, - // LLVM crash - ("aarch64", _) if !target_features.iter().any(|f| f == "neon") => false, // MinGW ABI bugs ("x86_64", "windows") if target_env == "gnu" && target_abi != "llvm" => false, // Infinite recursion From a3af09faa39d5a8d303a4cc2f80182e0f01baa7c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 2 Apr 2025 23:54:10 +0200 Subject: [PATCH 086/606] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index cf36b6fd0385..bc254efcd30c 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -4ac032f857b46037b55c1fc0fa702450aad37f43 +d5b4c2e4f19b6d7037371cdaecc3cc2c701c68df From 28d1844a259ce02e0d790d6d4e0a8de45b604dd5 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 3 Apr 2025 08:36:33 +0200 Subject: [PATCH 087/606] visit_freeze_sensitive: add comment --- src/tools/miri/src/helpers.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index 29ed94a2e4a2..b4098ca0750c 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -602,6 +602,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // We want to not actually read from memory for this visit. So, before // walking this value, we have to make sure it is not a // `Variants::Multiple`. + // FIXME: the current logic here is layout-dependent, so enums with + // multiple variants where all but 1 are uninhabited will be recursed into. + // Is that truly what we want? match v.layout.variants { Variants::Multiple { .. } => { // A multi-variant enum, or coroutine, or so. From fdefffecb2a1c2b89dfc2c5ad041c02144adda81 Mon Sep 17 00:00:00 2001 From: xtex Date: Sun, 30 Mar 2025 10:00:45 +0800 Subject: [PATCH 088/606] compiler: report error when trait object type param reference self Fixes #139082. Emits an error when `Self` is found in the projection bounds of a trait object. In type aliases, `Self` has no meaning, so `type A = &'static dyn B` where `trait B = Fn() -> Self` will expands to `type A = &'static Fn() -> Self` which is illegal, causing the region solver to bail out when hitting the uninferred Self. Bug: #139082 Signed-off-by: xtex --- compiler/rustc_hir_analysis/messages.ftl | 3 +++ compiler/rustc_hir_analysis/src/errors.rs | 8 ++++++++ .../src/hir_ty_lowering/dyn_compatibility.rs | 14 ++++++++++++++ .../trait-alias-self-projection.rs | 12 ++++++++++++ .../trait-alias-self-projection.stderr | 9 +++++++++ 5 files changed, 46 insertions(+) create mode 100644 tests/ui/dyn-compatibility/trait-alias-self-projection.rs create mode 100644 tests/ui/dyn-compatibility/trait-alias-self-projection.stderr diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 194f2cd04e46..2f7c3cb3c7d8 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -486,6 +486,9 @@ hir_analysis_self_in_impl_self = `Self` is not valid in the self type of an impl block .note = replace `Self` with a different type +hir_analysis_self_in_type_alias = `Self` is not allowed in type aliases + .label = `Self` is only available in impls, traits, and concrete type definitions + hir_analysis_self_ty_not_captured = `impl Trait` must mention the `Self` type of the trait in `use<...>` .label = `Self` type parameter is implicitly captured by this `impl Trait` .note = currently, all type parameters are required to be mentioned in the precise captures list diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index f2560f22874b..e6090a128b1c 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1707,3 +1707,11 @@ pub(crate) enum SupertraitItemShadowee { traits: DiagSymbolList, }, } + +#[derive(Diagnostic)] +#[diag(hir_analysis_self_in_type_alias, code = E0411)] +pub(crate) struct SelfInTypeAlias { + #[primary_span] + #[label] + pub span: Span, +} diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs index 27643e715e6b..28b55fff4ac9 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs @@ -16,6 +16,7 @@ use smallvec::{SmallVec, smallvec}; use tracing::{debug, instrument}; use super::HirTyLowerer; +use crate::errors::SelfInTypeAlias; use crate::hir_ty_lowering::{ GenericArgCountMismatch, GenericArgCountResult, PredicateFilter, RegionInferReason, }; @@ -113,6 +114,19 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // ``` let mut projection_bounds = FxIndexMap::default(); for (proj, proj_span) in elaborated_projection_bounds { + let proj = proj.map_bound(|mut b| { + if let Some(term_ty) = &b.term.as_type() { + let references_self = term_ty.walk().any(|arg| arg == dummy_self.into()); + if references_self { + // With trait alias and type alias combined, type resolver + // may not be able to catch all illegal `Self` usages (issue 139082) + let guar = tcx.dcx().emit_err(SelfInTypeAlias { span }); + b.term = replace_dummy_self_with_error(tcx, b.term, guar); + } + } + b + }); + let key = ( proj.skip_binder().projection_term.def_id, tcx.anonymize_bound_vars( diff --git a/tests/ui/dyn-compatibility/trait-alias-self-projection.rs b/tests/ui/dyn-compatibility/trait-alias-self-projection.rs new file mode 100644 index 000000000000..0badb738809e --- /dev/null +++ b/tests/ui/dyn-compatibility/trait-alias-self-projection.rs @@ -0,0 +1,12 @@ +#![feature(trait_alias)] +trait B = Fn() -> Self; +type D = &'static dyn B; +//~^ ERROR E0411 + +fn a() -> D { + unreachable!(); +} + +fn main() { + _ = a(); +} diff --git a/tests/ui/dyn-compatibility/trait-alias-self-projection.stderr b/tests/ui/dyn-compatibility/trait-alias-self-projection.stderr new file mode 100644 index 000000000000..dccee02e9cd1 --- /dev/null +++ b/tests/ui/dyn-compatibility/trait-alias-self-projection.stderr @@ -0,0 +1,9 @@ +error[E0411]: `Self` is not allowed in type aliases + --> $DIR/trait-alias-self-projection.rs:3:19 + | +LL | type D = &'static dyn B; + | ^^^^^ `Self` is only available in impls, traits, and concrete type definitions + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0411`. From ffb209710568fcb09d6971a509e6c64689da4982 Mon Sep 17 00:00:00 2001 From: xizheyin Date: Mon, 31 Mar 2025 15:07:51 +0800 Subject: [PATCH 089/606] std: clarify RefCell::get_mut more clearly Signed-off-by: xizheyin --- library/core/src/cell.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 1a320b316a41..420b08079379 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -1163,7 +1163,9 @@ impl RefCell { /// Since this method borrows `RefCell` mutably, it is statically guaranteed /// that no borrows to the underlying data exist. The dynamic checks inherent /// in [`borrow_mut`] and most other methods of `RefCell` are therefore - /// unnecessary. + /// unnecessary. Note that this method does not reset the borrowing state if borrows were previously leaked + /// (e.g., via [`forget()`] on a [`Ref`] or [`RefMut`]). For that purpose, + /// consider using the unstable [`undo_leak`] method. /// /// This method can only be called if `RefCell` can be mutably borrowed, /// which in general is only the case directly after the `RefCell` has @@ -1174,6 +1176,8 @@ impl RefCell { /// Use [`borrow_mut`] to get mutable access to the underlying data then. /// /// [`borrow_mut`]: RefCell::borrow_mut() + /// [`forget()`]: mem::forget + /// [`undo_leak`]: RefCell::undo_leak() /// /// # Examples /// From 0162f29436d7992ca5f3b642a282045afd922a26 Mon Sep 17 00:00:00 2001 From: xizheyin Date: Mon, 31 Mar 2025 15:11:23 +0800 Subject: [PATCH 090/606] std: clarify RwLock::get_mut more clearly Signed-off-by: xizheyin --- library/std/src/sync/poison/rwlock.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/library/std/src/sync/poison/rwlock.rs b/library/std/src/sync/poison/rwlock.rs index f9d9321f5f2d..a2abd4f692ec 100644 --- a/library/std/src/sync/poison/rwlock.rs +++ b/library/std/src/sync/poison/rwlock.rs @@ -608,7 +608,9 @@ impl RwLock { /// Returns a mutable reference to the underlying data. /// /// Since this call borrows the `RwLock` mutably, no actual locking needs to - /// take place -- the mutable borrow statically guarantees no locks exist. + /// take place -- the mutable borrow statically guarantees no new locks can be acquired + /// while this reference exists. Note that this method does not clear any previously abandoned locks + /// (e.g., via [`forget()`] on a [`RwLockReadGuard`] or [`RwLockWriteGuard`]). /// /// # Errors /// From 6966416a05572eb09131414a241c1ff7492d475f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 3 Apr 2025 15:38:08 +0200 Subject: [PATCH 091/606] Update to new rinja version (askama) --- Cargo.lock | 55 +++++++++++++++++++++- src/librustdoc/Cargo.toml | 2 +- src/librustdoc/{rinja.toml => askama.toml} | 0 src/librustdoc/html/layout.rs | 2 +- src/librustdoc/html/render/context.rs | 2 +- src/librustdoc/html/render/mod.rs | 2 +- src/librustdoc/html/render/print_item.rs | 10 ++-- src/librustdoc/html/render/sidebar.rs | 6 +-- src/librustdoc/html/render/type_layout.rs | 2 +- src/librustdoc/html/sources.rs | 2 +- src/librustdoc/html/templates/STYLE.md | 16 +++---- 11 files changed, 75 insertions(+), 24 deletions(-) rename src/librustdoc/{rinja.toml => askama.toml} (100%) diff --git a/Cargo.lock b/Cargo.lock index 96526f7e9e7d..697208e77629 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -186,6 +186,48 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +[[package]] +name = "askama" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a4e46abb203e00ef226442d452769233142bbfdd79c3941e84c8e61c4112543" +dependencies = [ + "askama_derive", + "itoa", + "percent-encoding", + "serde", + "serde_json", +] + +[[package]] +name = "askama_derive" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54398906821fd32c728135f7b351f0c7494ab95ae421d41b6f5a020e158f28a6" +dependencies = [ + "askama_parser", + "basic-toml", + "memchr", + "proc-macro2", + "quote", + "rustc-hash 2.1.1", + "serde", + "serde_derive", + "syn 2.0.100", +] + +[[package]] +name = "askama_parser" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf315ce6524c857bb129ff794935cf6d42c82a6cff60526fe2a63593de4d0d4f" +dependencies = [ + "memchr", + "serde", + "serde_derive", + "winnow 0.7.4", +] + [[package]] name = "autocfg" version = "1.4.0" @@ -4619,6 +4661,7 @@ name = "rustdoc" version = "0.0.0" dependencies = [ "arrayvec", + "askama", "base64", "expect-test", "indexmap", @@ -4627,7 +4670,6 @@ dependencies = [ "pulldown-cmark 0.9.6", "pulldown-cmark-escape", "regex", - "rinja", "rustdoc-json-types", "serde", "serde_json", @@ -5418,7 +5460,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "winnow", + "winnow 0.5.40", ] [[package]] @@ -6429,6 +6471,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "winnow" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e97b544156e9bebe1a0ffbc03484fc1ffe3100cbce3ffb17eac35f7cdd7ab36" +dependencies = [ + "memchr", +] + [[package]] name = "winsplit" version = "0.1.0" diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index 909b81a723b4..27ae0553c60d 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -9,7 +9,7 @@ path = "lib.rs" [dependencies] arrayvec = { version = "0.7", default-features = false } -rinja = { version = "0.3", default-features = false, features = ["config"] } +askama = { version = "0.13", default-features = false, features = ["alloc", "config", "derive"] } base64 = "0.21.7" itertools = "0.12" indexmap = "2" diff --git a/src/librustdoc/rinja.toml b/src/librustdoc/askama.toml similarity index 100% rename from src/librustdoc/rinja.toml rename to src/librustdoc/askama.toml diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index df70df062fe0..44b3be23914c 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -1,7 +1,7 @@ use std::fmt::{self, Display}; use std::path::PathBuf; -use rinja::Template; +use askama::Template; use rustc_data_structures::fx::FxIndexMap; use super::static_files::{STATIC_FILES, StaticFiles}; diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 5f69e79f3ab1..e2d1f58a37ec 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -5,7 +5,7 @@ use std::io; use std::path::{Path, PathBuf}; use std::sync::mpsc::{Receiver, channel}; -use rinja::Template; +use askama::Template; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; use rustc_hir::def_id::{DefIdMap, LOCAL_CRATE}; use rustc_middle::ty::TyCtxt; diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 2237e0f987bc..3512dff0865c 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -43,7 +43,7 @@ use std::iter::Peekable; use std::path::PathBuf; use std::{fs, str}; -use rinja::Template; +use askama::Template; use rustc_attr_parsing::{ ConstStability, DeprecatedSince, Deprecation, RustcVersion, StabilityLevel, StableSince, }; diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 3c5c2ce19767..aeda4736899d 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -2,7 +2,7 @@ use std::cmp::Ordering; use std::fmt::{self, Display, Write as _}; use std::iter; -use rinja::Template; +use askama::Template; use rustc_abi::VariantIdx; use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_hir as hir; @@ -37,7 +37,7 @@ use crate::html::markdown::{HeadingOffset, MarkdownSummaryLine}; use crate::html::render::{document_full, document_item_info}; use crate::html::url_parts_builder::UrlPartsBuilder; -/// Generates a Rinja template struct for rendering items with common methods. +/// Generates a Askama template struct for rendering items with common methods. /// /// Usage: /// ```ignore (illustrative) @@ -301,7 +301,7 @@ fn toggle_close(mut w: impl fmt::Write) { w.write_str("").unwrap(); } -trait ItemTemplate<'a, 'cx: 'a>: rinja::Template + Display { +trait ItemTemplate<'a, 'cx: 'a>: askama::Template + Display { fn item_and_cx(&self) -> (&'a clean::Item, &'a Context<'cx>); } @@ -1867,7 +1867,7 @@ fn item_proc_macro(cx: &Context<'_>, it: &clean::Item, m: &clean::ProcMacro) -> } } } - Ok(()) + Ok::<(), fmt::Error>(()) })?; write!(w, "{}", document(cx, it, None, HeadingOffset::H2)) }) @@ -1944,7 +1944,7 @@ fn item_constant( } } } - Ok(()) + Ok::<(), fmt::Error>(()) })?; write!(w, "{}", document(cx, it, None, HeadingOffset::H2)) diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs index 89ff61ecb03e..cd0c9775f5c9 100644 --- a/src/librustdoc/html/render/sidebar.rs +++ b/src/librustdoc/html/render/sidebar.rs @@ -1,7 +1,7 @@ use std::borrow::Cow; use std::cmp::Ordering; -use rinja::Template; +use askama::Template; use rustc_data_structures::fx::FxHashSet; use rustc_hir::def::CtorKind; use rustc_hir::def_id::{DefIdMap, DefIdSet}; @@ -123,10 +123,10 @@ impl<'a> Link<'a> { pub(crate) mod filters { use std::fmt::{self, Display}; - use rinja::filters::Safe; + use askama::filters::Safe; use crate::html::escape::EscapeBodyTextWithWbr; - pub(crate) fn wrapped(v: T) -> rinja::Result> + pub(crate) fn wrapped(v: T) -> askama::Result> where T: Display, { diff --git a/src/librustdoc/html/render/type_layout.rs b/src/librustdoc/html/render/type_layout.rs index a1ee5c8c548b..fb1f0271c2ad 100644 --- a/src/librustdoc/html/render/type_layout.rs +++ b/src/librustdoc/html/render/type_layout.rs @@ -1,6 +1,6 @@ use std::fmt; -use rinja::Template; +use askama::Template; use rustc_abi::{Primitive, TagEncoding, Variants}; use rustc_hir::def_id::DefId; use rustc_middle::span_bug; diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index cbbd4b01d83e..095795c711d9 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -3,7 +3,7 @@ use std::ffi::OsStr; use std::path::{Component, Path, PathBuf}; use std::{fmt, fs}; -use rinja::Template; +use askama::Template; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_hir::def_id::LOCAL_CRATE; use rustc_middle::ty::TyCtxt; diff --git a/src/librustdoc/html/templates/STYLE.md b/src/librustdoc/html/templates/STYLE.md index 32bacb11475c..12c2553cffdb 100644 --- a/src/librustdoc/html/templates/STYLE.md +++ b/src/librustdoc/html/templates/STYLE.md @@ -1,13 +1,13 @@ # Style for Templates -This directory has templates in the [Rinja templating language][rinjadoc], which is very +This directory has templates in the [Askama templating language][askamadoc], which is very similar to [Jinja2][jinjadoc]. [jinjadoc]: https://jinja.palletsprojects.com/en/3.1.x/templates/ -[rinjadoc]: https://docs.rs/rinja/latest/rinja/ +[askamadoc]: https://docs.rs/askama/latest/askama/ We want our rendered output to have as little unnecessary whitespace as -possible, so that pages load quickly. To achieve that we use Rinja's +possible, so that pages load quickly. To achieve that we use Askama's [whitespace control] features. By default, whitespace characters are removed around jinja tags (`{% %}` for example). At the end of most lines, we put an empty comment tag: `{# #}`. This causes all whitespace between the end of the @@ -18,7 +18,7 @@ remove following whitespace but not preceding. We also use the whitespace control characters in most instances of tags with control flow, for example `{% if foo %}`. -[whitespace control]: https://rinja.readthedocs.io/en/stable/configuration.html#whitespace-control +[whitespace control]: https://askama.readthedocs.io/en/stable/configuration.html#whitespace-control We want our templates to be readable, so we use indentation and newlines liberally. We indent by four spaces after opening an HTML tag _or_ a Jinja @@ -26,11 +26,11 @@ tag. In most cases an HTML tag should be followed by a newline, but if the tag has simple contents and fits with its close tag on a single line, the contents don't necessarily need a new line. -Rinja templates support quite sophisticated control flow. To keep our templates +Askama templates support quite sophisticated control flow. To keep our templates simple and understandable, we use only a subset: `if` and `for`. In particular -we avoid [assignments in the template logic][assignments] and [Rinja +we avoid [assignments in the template logic][assignments] and [Askama macros][macros]. This also may make things easier if we switch to a different Jinja-style template system in the future. -[assignments]: https://rinja.readthedocs.io/en/stable/template_syntax.html#assignments -[macros]: https://rinja.readthedocs.io/en/stable/template_syntax.html#macros +[assignments]: https://askama.readthedocs.io/en/stable/template_syntax.html#assignments +[macros]: https://askama.readthedocs.io/en/stable/template_syntax.html#macros From 1a89c2b08eb479b904aaa4523392666fe6eb35aa Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 3 Apr 2025 16:27:10 +0200 Subject: [PATCH 092/606] fix comment nit --- src/tools/miri/src/shims/unix/macos/foreign_items.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/tools/miri/src/shims/unix/macos/foreign_items.rs b/src/tools/miri/src/shims/unix/macos/foreign_items.rs index 918fd8dd52df..5046e9650822 100644 --- a/src/tools/miri/src/shims/unix/macos/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/macos/foreign_items.rs @@ -222,7 +222,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(res, dest)?; } - // Futex primitives + // Synchronization primitives "os_sync_wait_on_address" => { let [addr_op, value_op, size_op, flags_op] = this.check_shim(abi, Conv::C, link_name, args)?; @@ -273,7 +273,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { addr_op, size_op, flags_op, /* all */ true, dest, )?; } - "os_unfair_lock_lock" => { let [lock_op] = this.check_shim(abi, Conv::C, link_name, args)?; this.os_unfair_lock_lock(lock_op)?; From e7de860c332c9d4de1d718f8abb0c21ee0df7c9c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 3 Apr 2025 17:34:14 +0200 Subject: [PATCH 093/606] test-cargo-miri: permissive provenance should not be needed any more --- src/tools/miri/test-cargo-miri/run-test.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/tools/miri/test-cargo-miri/run-test.py b/src/tools/miri/test-cargo-miri/run-test.py index 5b77092979d3..8d55ec2b5313 100755 --- a/src/tools/miri/test-cargo-miri/run-test.py +++ b/src/tools/miri/test-cargo-miri/run-test.py @@ -147,16 +147,15 @@ def test_cargo_miri_test(): default_ref = "test.cross-target.stdout.ref" if is_foreign else "test.default.stdout.ref" filter_ref = "test.filter.cross-target.stdout.ref" if is_foreign else "test.filter.stdout.ref" - # macOS needs permissive provenance inside getrandom_1. test("`cargo miri test`", cargo_miri("test"), default_ref, "test.stderr-empty.ref", - env={'MIRIFLAGS': "-Zmiri-permissive-provenance -Zmiri-seed=4242"}, + env={'MIRIFLAGS': "-Zmiri-seed=4242"}, ) test("`cargo miri test` (no isolation, no doctests)", cargo_miri("test") + ["--bins", "--tests"], # no `--lib`, we disabled that in `Cargo.toml` "test.cross-target.stdout.ref", "test.stderr-empty.ref", - env={'MIRIFLAGS': "-Zmiri-permissive-provenance -Zmiri-disable-isolation"}, + env={'MIRIFLAGS': "-Zmiri-disable-isolation"}, ) test("`cargo miri test` (with filter)", cargo_miri("test") + ["--", "--format=pretty", "pl"], @@ -165,7 +164,6 @@ def test_cargo_miri_test(): test("`cargo miri test` (test target)", cargo_miri("test") + ["--test", "test", "--", "--format=pretty"], "test.test-target.stdout.ref", "test.stderr-empty.ref", - env={'MIRIFLAGS': "-Zmiri-permissive-provenance"}, ) test("`cargo miri test` (bin target)", cargo_miri("test") + ["--bin", "cargo-miri-test", "--", "--format=pretty"], @@ -183,13 +181,11 @@ def test_cargo_miri_test(): test("`cargo miri test` (custom target dir)", cargo_miri("test") + ["--target-dir=custom-test"], default_ref, "test.stderr-empty.ref", - env={'MIRIFLAGS': "-Zmiri-permissive-provenance"}, ) del os.environ["CARGO_TARGET_DIR"] # this overrides `build.target-dir` passed by `--config`, so unset it test("`cargo miri test` (config-cli)", cargo_miri("test") + ["--config=build.target-dir=\"config-cli\""], default_ref, "test.stderr-empty.ref", - env={'MIRIFLAGS': "-Zmiri-permissive-provenance"}, ) if ARGS.multi_target: test_cargo_miri_multi_target() @@ -199,7 +195,6 @@ def test_cargo_miri_multi_target(): test("`cargo miri test` (multiple targets)", cargo_miri("test", targets = ["aarch64-unknown-linux-gnu", "s390x-unknown-linux-gnu"]), "test.multiple_targets.stdout.ref", "test.stderr-empty.ref", - env={'MIRIFLAGS': "-Zmiri-permissive-provenance"}, ) args_parser = argparse.ArgumentParser(description='`cargo miri` testing') From 05d64b119b8e00b3305598bb12091035c653e24b Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Thu, 3 Apr 2025 11:02:45 -0600 Subject: [PATCH 094/606] Add another Miri-detected bug to README.md Miri detected this bug in Mockall: https://github.com/asomers/mockall/issues/647 [skip ci] --- src/tools/miri/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md index 201aa1f53869..8aa11e1f8210 100644 --- a/src/tools/miri/README.md +++ b/src/tools/miri/README.md @@ -565,6 +565,7 @@ Definite bugs found: * [Occasional memory leak in `std::mpsc` channels](https://github.com/rust-lang/rust/issues/121582) (original code in [crossbeam](https://github.com/crossbeam-rs/crossbeam/pull/1084)) * [Weak-memory-induced memory leak in Windows thread-local storage](https://github.com/rust-lang/rust/pull/124281) * [A bug in the new `RwLock::downgrade` implementation](https://rust-lang.zulipchat.com/#narrow/channel/269128-miri/topic/Miri.20error.20library.20test) (caught by Miri before it landed in the Rust repo) +* [Mockall reads unintialized memory when mocking `std::io::Read::read`, even if all expectations are satisfied](https://github.com/asomers/mockall/issues/647) (caught by Miri running Tokio's test suite) Violations of [Stacked Borrows] found that are likely bugs (but Stacked Borrows is currently just an experiment): From 984c51f6a1d93fa244829f488d2945e7fc06b880 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Tue, 18 Mar 2025 01:01:15 +0000 Subject: [PATCH 095/606] Stabilize `cfg_boolean_literals` --- .../rustc_attr_parsing/src/attributes/cfg.rs | 15 ------- compiler/rustc_feature/src/accepted.rs | 2 + compiler/rustc_feature/src/unstable.rs | 2 - .../language-features/cfg-boolean-literals.md | 22 ---------- .../crates/ide-db/src/generated/lints.rs | 29 ------------- tests/rustdoc-ui/cfg-boolean-literal.rs | 1 - tests/rustdoc-ui/doc-cfg-unstable.rs | 4 -- tests/rustdoc-ui/doc-cfg-unstable.stderr | 14 +----- tests/ui/cfg/true-false.rs | 1 - .../feature-gate-cfg-boolean-literals.rs | 10 ----- .../feature-gate-cfg-boolean-literals.stderr | 43 ------------------- tests/ui/lint/inert-attr-macro.rs | 1 - tests/ui/lint/inert-attr-macro.stderr | 14 +++--- tests/ui/proc-macro/cfg-attr-trace.rs | 1 - tests/ui/proc-macro/cfg-attr-trace.stdout | 30 ++++++------- 15 files changed, 26 insertions(+), 163 deletions(-) delete mode 100644 src/doc/unstable-book/src/language-features/cfg-boolean-literals.md delete mode 100644 tests/ui/feature-gates/feature-gate-cfg-boolean-literals.rs delete mode 100644 tests/ui/feature-gates/feature-gate-cfg-boolean-literals.stderr diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg.rs b/compiler/rustc_attr_parsing/src/attributes/cfg.rs index 0d6d521b40c6..48297b2ebd8c 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg.rs @@ -7,7 +7,6 @@ use rustc_session::config::ExpectedValues; use rustc_session::lint::BuiltinLintDiag; use rustc_session::lint::builtin::UNEXPECTED_CFGS; use rustc_session::parse::feature_err; -use rustc_span::symbol::kw; use rustc_span::{Span, Symbol, sym}; use crate::session_diagnostics::{self, UnsupportedLiteralReason}; @@ -89,20 +88,6 @@ pub fn eval_condition( let cfg = match cfg { MetaItemInner::MetaItem(meta_item) => meta_item, MetaItemInner::Lit(MetaItemLit { kind: LitKind::Bool(b), .. }) => { - if let Some(features) = features { - // we can't use `try_gate_cfg` as symbols don't differentiate between `r#true` - // and `true`, and we want to keep the former working without feature gate - gate_cfg( - &( - if *b { kw::True } else { kw::False }, - sym::cfg_boolean_literals, - |features: &Features| features.cfg_boolean_literals(), - ), - cfg.span(), - sess, - features, - ); - } return *b; } _ => { diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 88e6593572bc..a9ef7c3f9f18 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -95,6 +95,8 @@ declare_features! ( (accepted, c_unwind, "1.81.0", Some(74990)), /// Allows `#[cfg_attr(predicate, multiple, attributes, here)]`. (accepted, cfg_attr_multi, "1.33.0", Some(54881)), + /// Allows the use of `#[cfg()]`. + (accepted, cfg_boolean_literals, "CURRENT_RUSTC_VERSION", Some(131204)), /// Allows the use of `#[cfg(doctest)]`, set when rustdoc is collecting doctests. (accepted, cfg_doctest, "1.40.0", Some(62210)), /// Enables `#[cfg(panic = "...")]` config key. diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 87b88bb4223e..6ead07ac0ffb 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -391,8 +391,6 @@ declare_features! ( (unstable, async_trait_bounds, "1.85.0", Some(62290)), /// Allows using C-variadics. (unstable, c_variadic, "1.34.0", Some(44930)), - /// Allows the use of `#[cfg()]`. - (unstable, cfg_boolean_literals, "1.83.0", Some(131204)), /// Allows the use of `#[cfg(contract_checks)` to check if contract checks are enabled. (unstable, cfg_contract_checks, "1.86.0", Some(128044)), /// Allows the use of `#[cfg(overflow_checks)` to check if integer overflow behaviour. diff --git a/src/doc/unstable-book/src/language-features/cfg-boolean-literals.md b/src/doc/unstable-book/src/language-features/cfg-boolean-literals.md deleted file mode 100644 index ad795ff9d9b2..000000000000 --- a/src/doc/unstable-book/src/language-features/cfg-boolean-literals.md +++ /dev/null @@ -1,22 +0,0 @@ -# `cfg_boolean_literals` - -The tracking issue for this feature is: [#131204] - -[#131204]: https://github.com/rust-lang/rust/issues/131204 - ------------------------- - -The `cfg_boolean_literals` feature makes it possible to use the `true`/`false` -literal as cfg predicate. They always evaluate to true/false respectively. - -## Examples - -```rust -#![feature(cfg_boolean_literals)] - -#[cfg(true)] -const A: i32 = 5; - -#[cfg(all(false))] -const A: i32 = 58 * 89; -``` 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 0a7a7d1fb241..706d04484f6f 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 @@ -3789,35 +3789,6 @@ The tracking issue for this feature is: [#64797] [#64797]: https://github.com/rust-lang/rust/issues/64797 ------------------------ -"##, - default_severity: Severity::Allow, - warn_since: None, - deny_since: None, - }, - Lint { - label: "cfg_boolean_literals", - description: r##"# `cfg_boolean_literals` - -The tracking issue for this feature is: [#131204] - -[#131204]: https://github.com/rust-lang/rust/issues/131204 - ------------------------- - -The `cfg_boolean_literals` feature makes it possible to use the `true`/`false` -literal as cfg predicate. They always evaluate to true/false respectively. - -## Examples - -```rust -#![feature(cfg_boolean_literals)] - -#[cfg(true)] -const A: i32 = 5; - -#[cfg(all(false))] -const A: i32 = 58 * 89; -``` "##, default_severity: Severity::Allow, warn_since: None, diff --git a/tests/rustdoc-ui/cfg-boolean-literal.rs b/tests/rustdoc-ui/cfg-boolean-literal.rs index 4d4e599bfeef..74808d066c71 100644 --- a/tests/rustdoc-ui/cfg-boolean-literal.rs +++ b/tests/rustdoc-ui/cfg-boolean-literal.rs @@ -1,6 +1,5 @@ //@ check-pass -#![feature(cfg_boolean_literals)] #![feature(doc_cfg)] #[doc(cfg(false))] diff --git a/tests/rustdoc-ui/doc-cfg-unstable.rs b/tests/rustdoc-ui/doc-cfg-unstable.rs index 14c2e83ec854..b77c3654497d 100644 --- a/tests/rustdoc-ui/doc-cfg-unstable.rs +++ b/tests/rustdoc-ui/doc-cfg-unstable.rs @@ -1,10 +1,6 @@ // #138113: rustdoc didn't gate unstable predicates inside `doc(cfg(..))` #![feature(doc_cfg)] -// `cfg_boolean_literals` -#[doc(cfg(false))] //~ ERROR `cfg(false)` is experimental and subject to change -pub fn cfg_boolean_literals() {} - // `cfg_version` #[doc(cfg(sanitize = "thread"))] //~ ERROR `cfg(sanitize)` is experimental and subject to change pub fn cfg_sanitize() {} diff --git a/tests/rustdoc-ui/doc-cfg-unstable.stderr b/tests/rustdoc-ui/doc-cfg-unstable.stderr index 54de3b178edb..9651c5f1a0b0 100644 --- a/tests/rustdoc-ui/doc-cfg-unstable.stderr +++ b/tests/rustdoc-ui/doc-cfg-unstable.stderr @@ -1,15 +1,5 @@ -error[E0658]: `cfg(false)` is experimental and subject to change - --> $DIR/doc-cfg-unstable.rs:5:11 - | -LL | #[doc(cfg(false))] - | ^^^^^ - | - = note: see issue #131204 for more information - = help: add `#![feature(cfg_boolean_literals)]` 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]: `cfg(sanitize)` is experimental and subject to change - --> $DIR/doc-cfg-unstable.rs:9:11 + --> $DIR/doc-cfg-unstable.rs:5:11 | LL | #[doc(cfg(sanitize = "thread"))] | ^^^^^^^^^^^^^^^^^^^ @@ -18,6 +8,6 @@ LL | #[doc(cfg(sanitize = "thread"))] = help: add `#![feature(cfg_sanitize)]` 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 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/cfg/true-false.rs b/tests/ui/cfg/true-false.rs index 03d96fbafecb..0bd1cf427faf 100644 --- a/tests/ui/cfg/true-false.rs +++ b/tests/ui/cfg/true-false.rs @@ -1,7 +1,6 @@ //@ run-pass #![feature(link_cfg)] -#![feature(cfg_boolean_literals)] #[cfg(true)] fn foo() -> bool { diff --git a/tests/ui/feature-gates/feature-gate-cfg-boolean-literals.rs b/tests/ui/feature-gates/feature-gate-cfg-boolean-literals.rs deleted file mode 100644 index 6784b4450490..000000000000 --- a/tests/ui/feature-gates/feature-gate-cfg-boolean-literals.rs +++ /dev/null @@ -1,10 +0,0 @@ -#[cfg(true)] //~ ERROR `cfg(true)` is experimental -fn foo() {} - -#[cfg_attr(true, cfg(false))] //~ ERROR `cfg(true)` is experimental -//~^ ERROR `cfg(false)` is experimental -fn foo() {} - -fn main() { - cfg!(false); //~ ERROR `cfg(false)` is experimental -} diff --git a/tests/ui/feature-gates/feature-gate-cfg-boolean-literals.stderr b/tests/ui/feature-gates/feature-gate-cfg-boolean-literals.stderr deleted file mode 100644 index 64491464f1d4..000000000000 --- a/tests/ui/feature-gates/feature-gate-cfg-boolean-literals.stderr +++ /dev/null @@ -1,43 +0,0 @@ -error[E0658]: `cfg(true)` is experimental and subject to change - --> $DIR/feature-gate-cfg-boolean-literals.rs:1:7 - | -LL | #[cfg(true)] - | ^^^^ - | - = note: see issue #131204 for more information - = help: add `#![feature(cfg_boolean_literals)]` 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]: `cfg(true)` is experimental and subject to change - --> $DIR/feature-gate-cfg-boolean-literals.rs:4:12 - | -LL | #[cfg_attr(true, cfg(false))] - | ^^^^ - | - = note: see issue #131204 for more information - = help: add `#![feature(cfg_boolean_literals)]` 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]: `cfg(false)` is experimental and subject to change - --> $DIR/feature-gate-cfg-boolean-literals.rs:4:22 - | -LL | #[cfg_attr(true, cfg(false))] - | ^^^^^ - | - = note: see issue #131204 for more information - = help: add `#![feature(cfg_boolean_literals)]` 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]: `cfg(false)` is experimental and subject to change - --> $DIR/feature-gate-cfg-boolean-literals.rs:9:10 - | -LL | cfg!(false); - | ^^^^^ - | - = note: see issue #131204 for more information - = help: add `#![feature(cfg_boolean_literals)]` 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 4 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/lint/inert-attr-macro.rs b/tests/ui/lint/inert-attr-macro.rs index 5d4133d6c774..f2d50e30aecc 100644 --- a/tests/ui/lint/inert-attr-macro.rs +++ b/tests/ui/lint/inert-attr-macro.rs @@ -1,6 +1,5 @@ //@ check-pass -#![feature(cfg_boolean_literals)] #![warn(unused)] macro_rules! foo { diff --git a/tests/ui/lint/inert-attr-macro.stderr b/tests/ui/lint/inert-attr-macro.stderr index b85b0319e712..5ccb4ffe7929 100644 --- a/tests/ui/lint/inert-attr-macro.stderr +++ b/tests/ui/lint/inert-attr-macro.stderr @@ -1,41 +1,41 @@ warning: unused attribute `inline` - --> $DIR/inert-attr-macro.rs:11:5 + --> $DIR/inert-attr-macro.rs:10:5 | LL | #[inline] foo!(); | ^^^^^^^^^ | note: the built-in attribute `inline` will be ignored, since it's applied to the macro invocation `foo` - --> $DIR/inert-attr-macro.rs:11:15 + --> $DIR/inert-attr-macro.rs:10:15 | LL | #[inline] foo!(); | ^^^ note: the lint level is defined here - --> $DIR/inert-attr-macro.rs:4:9 + --> $DIR/inert-attr-macro.rs:3:9 | LL | #![warn(unused)] | ^^^^^^ = note: `#[warn(unused_attributes)]` implied by `#[warn(unused)]` warning: unused attribute `allow` - --> $DIR/inert-attr-macro.rs:15:5 + --> $DIR/inert-attr-macro.rs:14:5 | LL | #[allow(warnings)] #[inline] foo!(); | ^^^^^^^^^^^^^^^^^^ | note: the built-in attribute `allow` will be ignored, since it's applied to the macro invocation `foo` - --> $DIR/inert-attr-macro.rs:15:34 + --> $DIR/inert-attr-macro.rs:14:34 | LL | #[allow(warnings)] #[inline] foo!(); | ^^^ warning: unused attribute `inline` - --> $DIR/inert-attr-macro.rs:15:24 + --> $DIR/inert-attr-macro.rs:14:24 | LL | #[allow(warnings)] #[inline] foo!(); | ^^^^^^^^^ | note: the built-in attribute `inline` will be ignored, since it's applied to the macro invocation `foo` - --> $DIR/inert-attr-macro.rs:15:34 + --> $DIR/inert-attr-macro.rs:14:34 | LL | #[allow(warnings)] #[inline] foo!(); | ^^^ diff --git a/tests/ui/proc-macro/cfg-attr-trace.rs b/tests/ui/proc-macro/cfg-attr-trace.rs index 140dd10a7e04..412c65bed1d8 100644 --- a/tests/ui/proc-macro/cfg-attr-trace.rs +++ b/tests/ui/proc-macro/cfg-attr-trace.rs @@ -3,7 +3,6 @@ //@ check-pass //@ proc-macro: test-macros.rs -#![feature(cfg_boolean_literals)] #![feature(cfg_eval)] #[macro_use] diff --git a/tests/ui/proc-macro/cfg-attr-trace.stdout b/tests/ui/proc-macro/cfg-attr-trace.stdout index 52f9ff4e05c5..33bcfe5d69b7 100644 --- a/tests/ui/proc-macro/cfg-attr-trace.stdout +++ b/tests/ui/proc-macro/cfg-attr-trace.stdout @@ -4,75 +4,75 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Alone, - span: #0 bytes(305..306), + span: #0 bytes(271..272), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "test_macros", - span: #0 bytes(322..333), + span: #0 bytes(288..299), }, Punct { ch: ':', spacing: Joint, - span: #0 bytes(333..334), + span: #0 bytes(299..300), }, Punct { ch: ':', spacing: Alone, - span: #0 bytes(334..335), + span: #0 bytes(300..301), }, Ident { ident: "print_attr", - span: #0 bytes(335..345), + span: #0 bytes(301..311), }, ], - span: #0 bytes(306..347), + span: #0 bytes(272..313), }, Ident { ident: "struct", - span: #0 bytes(348..354), + span: #0 bytes(314..320), }, Ident { ident: "S", - span: #0 bytes(355..356), + span: #0 bytes(321..322), }, Punct { ch: ';', spacing: Alone, - span: #0 bytes(356..357), + span: #0 bytes(322..323), }, ] PRINT-ATTR INPUT (DISPLAY): struct S; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", - span: #0 bytes(348..354), + span: #0 bytes(314..320), }, Ident { ident: "S", - span: #0 bytes(355..356), + span: #0 bytes(321..322), }, Punct { ch: ';', spacing: Alone, - span: #0 bytes(356..357), + span: #0 bytes(322..323), }, ] PRINT-ATTR INPUT (DISPLAY): struct Z; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", - span: #0 bytes(411..417), + span: #0 bytes(377..383), }, Ident { ident: "Z", - span: #0 bytes(418..419), + span: #0 bytes(384..385), }, Punct { ch: ';', spacing: Alone, - span: #0 bytes(419..420), + span: #0 bytes(385..386), }, ] From d83f4153251ad3e85e975fa3e613378eba913c0b Mon Sep 17 00:00:00 2001 From: clubby789 Date: Tue, 18 Mar 2025 13:06:25 +0000 Subject: [PATCH 096/606] Add more tests for `cfg_boolean_literals` --- tests/ui/cfg/both-true-false.rs | 14 ++++++++++++++ tests/ui/cfg/both-true-false.stderr | 9 +++++++++ tests/ui/cfg/cmdline-false.rs | 9 +++++++++ tests/ui/cfg/cmdline-false.stderr | 9 +++++++++ 4 files changed, 41 insertions(+) create mode 100644 tests/ui/cfg/both-true-false.rs create mode 100644 tests/ui/cfg/both-true-false.stderr create mode 100644 tests/ui/cfg/cmdline-false.rs create mode 100644 tests/ui/cfg/cmdline-false.stderr diff --git a/tests/ui/cfg/both-true-false.rs b/tests/ui/cfg/both-true-false.rs new file mode 100644 index 000000000000..5fca8f654ad8 --- /dev/null +++ b/tests/ui/cfg/both-true-false.rs @@ -0,0 +1,14 @@ +/// Test that placing a `cfg(true)` and `cfg(false)` on the same item result in +//. it being disabled.` + +#[cfg(false)] +#[cfg(true)] +fn foo() {} + +#[cfg(true)] +#[cfg(false)] +fn foo() {} + +fn main() { + foo(); //~ ERROR cannot find function `foo` in this scope +} diff --git a/tests/ui/cfg/both-true-false.stderr b/tests/ui/cfg/both-true-false.stderr new file mode 100644 index 000000000000..1526cc2b707b --- /dev/null +++ b/tests/ui/cfg/both-true-false.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find function `foo` in this scope + --> $DIR/both-true-false.rs:13:5 + | +LL | foo(); + | ^^^ not found in this scope + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/cfg/cmdline-false.rs b/tests/ui/cfg/cmdline-false.rs new file mode 100644 index 000000000000..d4b7d3bbfdca --- /dev/null +++ b/tests/ui/cfg/cmdline-false.rs @@ -0,0 +1,9 @@ +/// Test that `--cfg false` doesn't cause `cfg(false)` to evaluate to `true` +//@ compile-flags: --cfg false + +#[cfg(false)] +fn foo() {} + +fn main() { + foo(); //~ ERROR cannot find function `foo` in this scope +} diff --git a/tests/ui/cfg/cmdline-false.stderr b/tests/ui/cfg/cmdline-false.stderr new file mode 100644 index 000000000000..5f57c754c403 --- /dev/null +++ b/tests/ui/cfg/cmdline-false.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find function `foo` in this scope + --> $DIR/cmdline-false.rs:8:5 + | +LL | foo(); + | ^^^ not found in this scope + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0425`. From 303c1b45c29f8bb186a9a95cb56643d1aef773fa Mon Sep 17 00:00:00 2001 From: clubby789 Date: Sat, 29 Mar 2025 17:24:03 +0000 Subject: [PATCH 097/606] Use `cfg(false)` in UI tests --- tests/pretty/ast-stmt-expr-attr.rs | 2 +- tests/pretty/enum-variant-vis.rs | 2 +- tests/pretty/if-attr.rs | 8 +- tests/pretty/nested-item-vis-defaultness.rs | 6 +- .../associated-types/associated-type-macro.rs | 2 +- .../ui/async-await/feature-async-for-loop.rs | 2 +- tests/ui/async-await/no-unsafe-async.rs | 4 +- tests/ui/attributes/z-crate-attr/cfg-false.rs | 4 +- tests/ui/auto-traits/pre-cfg.rs | 2 +- tests/ui/cfg/auxiliary/cfg_false_lib.rs | 4 +- .../auxiliary/cfg_false_lib_no_std_after.rs | 4 +- .../auxiliary/cfg_false_lib_no_std_before.rs | 4 +- tests/ui/cfg/auxiliary/cfged_out.rs | 4 +- tests/ui/cfg/cfg-false-feature.rs | 4 +- tests/ui/cfg/cfg-macros-notfoo.rs | 2 +- tests/ui/cfg/cfg-match-arm.rs | 2 +- tests/ui/cfg/cfg-stmt-recovery.rs | 2 +- tests/ui/cfg/cfg-stmt-recovery.stderr | 6 +- tests/ui/cfg/cfg_stmt_expr.rs | 30 ++-- tests/ui/cfg/conditional-compile.rs | 36 ++--- tests/ui/cfg/diagnostics-cross-crate.stderr | 4 +- tests/ui/cfg/diagnostics-reexport.rs | 10 +- tests/ui/cfg/diagnostics-reexport.stderr | 8 +- tests/ui/cfg/diagnostics-same-crate.rs | 4 +- tests/ui/cfg/diagnostics-same-crate.stderr | 8 +- tests/ui/check-cfg/allow-same-level.rs | 2 +- tests/ui/check-cfg/allow-same-level.stderr | 8 +- tests/ui/check-cfg/allow-top-level.rs | 2 +- tests/ui/check-cfg/allow-upper-level.rs | 2 +- .../cfg-generic-params.rs | 16 +- .../cfg-generic-params.stderr | 6 +- .../conditional-compilation/cfg-in-crate-1.rs | 2 +- .../cfg-in-crate-1.stderr | 2 +- .../cfg-non-opt-expr.rs | 6 +- .../cfg-non-opt-expr.stderr | 6 +- .../module_with_cfg.rs | 2 +- ...nst-extern-fns-dont-need-fn-specifier-2.rs | 2 +- ...const-extern-fns-dont-need-fn-specifier.rs | 2 +- .../explicit-paths-signature-pass.rs | 2 +- tests/ui/expr/if/attrs/bad-cfg.rs | 2 +- tests/ui/expr/if/attrs/bad-cfg.stderr | 2 +- tests/ui/expr/if/attrs/cfg-false-if-attr.rs | 14 +- tests/ui/expr/if/attrs/else-attrs.rs | 6 +- tests/ui/expr/if/attrs/gate-whole-expr.rs | 2 +- tests/ui/expr/if/attrs/let-chains-attr.rs | 2 +- .../feature-gates/feature-gate-coroutines.rs | 2 +- .../feature-gate-deref_patterns.rs | 2 +- .../feature-gates/feature-gate-gen_blocks.rs | 2 +- .../feature-gate-guard-patterns.rs | 2 +- .../ui/feature-gates/feature-gate-mut-ref.rs | 4 +- .../feature-gate-never_patterns.rs | 8 +- .../feature-gate-postfix_match.rs | 2 +- .../feature-gate-yeet_expr-in-cfg.rs | 4 +- .../soft-syntax-gates-with-errors.rs | 6 +- .../soft-syntax-gates-without-errors.rs | 6 +- .../stmt_expr_attrs_no_feature.rs | 24 +-- tests/ui/filter-block-view-items.rs | 2 +- ...nge-pats-inclusive-dotdotdot-bad-syntax.rs | 2 +- .../half-open-range-pats-inclusive-no-end.rs | 2 +- ...lf-open-range-pats-ref-ambiguous-interp.rs | 2 +- .../half-open-range-pats-syntactic-pass.rs | 2 +- tests/ui/inner-attrs-on-impl.rs | 4 +- tests/ui/issues/issue-11004.rs | 2 +- tests/ui/issues/issue-11085.rs | 8 +- tests/ui/issues/issue-16819.rs | 2 +- tests/ui/lexer/error-stage.rs | 2 +- .../link-attr-validation-late.rs | 2 +- .../link-attr-validation-late.stderr | 2 +- .../ui/lint/unused/unused-attr-macro-rules.rs | 2 +- tests/ui/macros/lint-trailing-macro-call.rs | 2 +- .../ui/macros/lint-trailing-macro-call.stderr | 4 +- tests/ui/macros/macro-attributes.rs | 2 +- tests/ui/macros/macro-inner-attributes.rs | 2 +- tests/ui/macros/macro-outer-attributes.rs | 2 +- tests/ui/macros/macro-outer-attributes.stderr | 2 +- tests/ui/macros/macro-with-attrs2.rs | 2 +- tests/ui/nested-cfg-attrs.rs | 2 +- .../ui/or-patterns/fn-param-wrap-parens.fixed | 2 +- tests/ui/or-patterns/fn-param-wrap-parens.rs | 2 +- .../or-patterns/or-patterns-syntactic-pass.rs | 2 +- .../ui/or-patterns/remove-leading-vert.fixed | 4 +- tests/ui/or-patterns/remove-leading-vert.rs | 4 +- .../assoc-const-underscore-syntactic-pass.rs | 2 +- .../assoc/assoc-static-syntactic-fail.rs | 6 +- .../attribute/attr-stmt-expr-attr-bad.rs | 90 +++++------ .../attribute/attr-stmt-expr-attr-bad.stderr | 150 +++++++++--------- .../multiple-tail-expr-behind-cfg.rs | 2 +- .../multiple-tail-expr-behind-cfg.stderr | 4 +- ...from-trailing-outer-attribute-in-body-2.rs | 2 +- ...-trailing-outer-attribute-in-body-2.stderr | 2 +- ...ints-before-generic-args-syntactic-pass.rs | 2 +- tests/ui/parser/default-on-wrong-item-kind.rs | 8 +- tests/ui/parser/extern-abi-syntactic.rs | 6 +- tests/ui/parser/extern-crate-async.rs | 4 +- .../parser/fn-body-optional-syntactic-pass.rs | 2 +- tests/ui/parser/fn-header-syntactic-pass.rs | 2 +- .../ui/parser/foreign-const-syntactic-fail.rs | 2 +- .../parser/foreign-static-syntactic-pass.rs | 2 +- tests/ui/parser/foreign-ty-syntactic-pass.rs | 2 +- tests/ui/parser/impl-item-const-pass.rs | 2 +- tests/ui/parser/impl-item-fn-no-body-pass.rs | 2 +- .../ui/parser/impl-item-type-no-body-pass.rs | 2 +- .../issue-65041-empty-vis-matcher-in-enum.rs | 2 +- .../issue-65041-empty-vis-matcher-in-trait.rs | 2 +- .../item-free-const-no-body-syntactic-pass.rs | 2 +- ...item-free-static-no-body-syntactic-pass.rs | 2 +- .../item-free-type-bounds-syntactic-pass.rs | 2 +- .../recover/recover-assoc-const-constraint.rs | 2 +- .../recover/recover-assoc-eq-missing-term.rs | 2 +- .../recover-assoc-lifetime-constraint.rs | 2 +- tests/ui/parser/self-param-syntactic-pass.rs | 10 +- .../stripped-nested-outline-mod-pass.rs | 2 +- .../trait-item-with-defaultness-pass.rs | 2 +- .../ui/parser/variadic-ffi-syntactic-pass.rs | 22 +-- ...d-type-ascription-syntactically-invalid.rs | 6 +- .../wild-before-at-syntactically-rejected.rs | 2 +- tests/ui/pattern/rest-pat-syntactic.rs | 2 +- tests/ui/proc-macro/attribute-after-derive.rs | 4 +- .../proc-macro/attribute-after-derive.stdout | 12 +- tests/ui/proc-macro/cfg-eval-fail.rs | 2 +- tests/ui/proc-macro/cfg-eval-fail.stderr | 2 +- tests/ui/proc-macro/cfg-eval-inner.rs | 2 +- tests/ui/proc-macro/cfg-eval.rs | 6 +- .../ui/proc-macro/derive-cfg-nested-tokens.rs | 2 +- .../derive-cfg-nested-tokens.stdout | 4 +- tests/ui/proc-macro/expand-to-derive.rs | 4 +- tests/ui/proc-macro/issue-75930-derive-cfg.rs | 26 +-- .../proc-macro/issue-75930-derive-cfg.stdout | 90 +++++------ tests/ui/proc-macro/nested-derive-cfg.rs | 4 +- .../rfc-2294-if-let-guard/feature-gate.rs | 2 +- tests/ui/rfcs/rfc-2294-if-let-guard/parens.rs | 2 +- .../disallowed-positions.rs | 8 +- .../rfc-2497-if-let-chains/feature-gate.rs | 2 +- .../feature-gate.stderr | 2 +- .../invalid-let-in-a-valid-let-context.rs | 10 +- .../attr-without-param.rs | 6 +- .../specialization/issue-63716-parse-async.rs | 2 +- tests/ui/suggestions/const-no-type.rs | 6 +- .../type-ascription-and-other-error.rs | 2 +- tests/ui/wasm/wasm-import-module.rs | 2 +- tests/ui/wasm/wasm-import-module.stderr | 2 +- 141 files changed, 470 insertions(+), 470 deletions(-) diff --git a/tests/pretty/ast-stmt-expr-attr.rs b/tests/pretty/ast-stmt-expr-attr.rs index fd7272a1b1fd..4ca60465b54c 100644 --- a/tests/pretty/ast-stmt-expr-attr.rs +++ b/tests/pretty/ast-stmt-expr-attr.rs @@ -2,7 +2,7 @@ fn main() {} -#[cfg(FALSE)] +#[cfg(false)] fn syntax() { let _ = #[attr] []; let _ = #[attr] [0]; diff --git a/tests/pretty/enum-variant-vis.rs b/tests/pretty/enum-variant-vis.rs index 3397e7dc8e28..5b9f7e037595 100644 --- a/tests/pretty/enum-variant-vis.rs +++ b/tests/pretty/enum-variant-vis.rs @@ -4,5 +4,5 @@ fn main() {} -#[cfg(FALSE)] +#[cfg(false)] enum Foo { pub V, } diff --git a/tests/pretty/if-attr.rs b/tests/pretty/if-attr.rs index 89d6130f6592..8b343a83a1c5 100644 --- a/tests/pretty/if-attr.rs +++ b/tests/pretty/if-attr.rs @@ -1,6 +1,6 @@ //@ pp-exact -#[cfg(FALSE)] +#[cfg(false)] fn simple_attr() { #[attr] @@ -10,21 +10,21 @@ fn simple_attr() { if true {} } -#[cfg(FALSE)] +#[cfg(false)] fn if_else_chain() { #[first_attr] if true {} else if false {} else {} } -#[cfg(FALSE)] +#[cfg(false)] fn if_let() { #[attr] if let Some(_) = Some(true) {} } -#[cfg(FALSE)] +#[cfg(false)] fn let_attr_if() { let _ = #[attr] if let _ = 0 {}; let _ = #[attr] if true {}; diff --git a/tests/pretty/nested-item-vis-defaultness.rs b/tests/pretty/nested-item-vis-defaultness.rs index 1e971fcf07a5..68f56a1be450 100644 --- a/tests/pretty/nested-item-vis-defaultness.rs +++ b/tests/pretty/nested-item-vis-defaultness.rs @@ -4,7 +4,7 @@ fn main() {} -#[cfg(FALSE)] +#[cfg(false)] extern "C" { static X: u8; type X; @@ -14,7 +14,7 @@ extern "C" { pub fn foo(); } -#[cfg(FALSE)] +#[cfg(false)] trait T { const X: u8; type X; @@ -30,7 +30,7 @@ trait T { pub default fn foo(); } -#[cfg(FALSE)] +#[cfg(false)] impl T for S { const X: u8; type X; diff --git a/tests/ui/associated-types/associated-type-macro.rs b/tests/ui/associated-types/associated-type-macro.rs index 22b5bca40103..8586dc172764 100644 --- a/tests/ui/associated-types/associated-type-macro.rs +++ b/tests/ui/associated-types/associated-type-macro.rs @@ -1,4 +1,4 @@ fn main() { - #[cfg(FALSE)] + #[cfg(false)] <() as module>::mac!(); //~ ERROR macros cannot use qualified paths } diff --git a/tests/ui/async-await/feature-async-for-loop.rs b/tests/ui/async-await/feature-async-for-loop.rs index 67817cbfa5f3..22d32907e0e7 100644 --- a/tests/ui/async-await/feature-async-for-loop.rs +++ b/tests/ui/async-await/feature-async-for-loop.rs @@ -11,7 +11,7 @@ fn f() { }; } -#[cfg(FALSE)] +#[cfg(false)] fn g() { let _ = async { for await _i in core::async_iter::from_iter(0..3) { diff --git a/tests/ui/async-await/no-unsafe-async.rs b/tests/ui/async-await/no-unsafe-async.rs index e58d878c3db0..cc7e89e16cb2 100644 --- a/tests/ui/async-await/no-unsafe-async.rs +++ b/tests/ui/async-await/no-unsafe-async.rs @@ -3,11 +3,11 @@ struct S; impl S { - #[cfg(FALSE)] + #[cfg(false)] unsafe async fn g() {} //~ ERROR expected one of `extern` or `fn`, found keyword `async` } -#[cfg(FALSE)] +#[cfg(false)] unsafe async fn f() {} //~ ERROR expected one of `extern` or `fn`, found keyword `async` fn main() {} diff --git a/tests/ui/attributes/z-crate-attr/cfg-false.rs b/tests/ui/attributes/z-crate-attr/cfg-false.rs index db37cfdd0863..5e5662c74385 100644 --- a/tests/ui/attributes/z-crate-attr/cfg-false.rs +++ b/tests/ui/attributes/z-crate-attr/cfg-false.rs @@ -1,5 +1,5 @@ -// Ensure that `-Z crate-attr=cfg(FALSE)` can comment out the whole crate -//@ compile-flags: --crate-type=lib -Zcrate-attr=cfg(FALSE) +// Ensure that `-Z crate-attr=cfg(false)` can comment out the whole crate +//@ compile-flags: --crate-type=lib -Zcrate-attr=cfg(false) //@ check-pass // NOTE: duplicate items are load-bearing diff --git a/tests/ui/auto-traits/pre-cfg.rs b/tests/ui/auto-traits/pre-cfg.rs index e806686f965c..4820a5353580 100644 --- a/tests/ui/auto-traits/pre-cfg.rs +++ b/tests/ui/auto-traits/pre-cfg.rs @@ -1,6 +1,6 @@ //@ check-pass -#[cfg(FALSE)] +#[cfg(false)] auto trait Foo {} //~^ WARN `auto` traits are unstable //~| WARN unstable syntax can change at any point in the future, causing a hard error! diff --git a/tests/ui/cfg/auxiliary/cfg_false_lib.rs b/tests/ui/cfg/auxiliary/cfg_false_lib.rs index 6c2dbb44d2a4..d1768e69b0d5 100644 --- a/tests/ui/cfg/auxiliary/cfg_false_lib.rs +++ b/tests/ui/cfg/auxiliary/cfg_false_lib.rs @@ -1,4 +1,4 @@ -// `#![no_std]` on a fully unconfigured crate is respected if it's placed before `cfg(FALSE)`. +// `#![no_std]` on a fully unconfigured crate is respected if it's placed before `cfg(false)`. // This crate has no such attribute, therefore this crate does link to libstd. -#![cfg(FALSE)] +#![cfg(false)] diff --git a/tests/ui/cfg/auxiliary/cfg_false_lib_no_std_after.rs b/tests/ui/cfg/auxiliary/cfg_false_lib_no_std_after.rs index 3cfa6c510d02..cd3170f3fb33 100644 --- a/tests/ui/cfg/auxiliary/cfg_false_lib_no_std_after.rs +++ b/tests/ui/cfg/auxiliary/cfg_false_lib_no_std_after.rs @@ -1,5 +1,5 @@ -// `#![no_std]` on a fully unconfigured crate is respected if it's placed before `cfg(FALSE)`. +// `#![no_std]` on a fully unconfigured crate is respected if it's placed before `cfg(false)`. // Therefore this crate does link to libstd. -#![cfg(FALSE)] +#![cfg(false)] #![no_std] diff --git a/tests/ui/cfg/auxiliary/cfg_false_lib_no_std_before.rs b/tests/ui/cfg/auxiliary/cfg_false_lib_no_std_before.rs index a5c14be4c29d..ce4e1690996b 100644 --- a/tests/ui/cfg/auxiliary/cfg_false_lib_no_std_before.rs +++ b/tests/ui/cfg/auxiliary/cfg_false_lib_no_std_before.rs @@ -1,8 +1,8 @@ -// `#![no_std]` on a fully unconfigured crate is respected if it's placed before `cfg(FALSE)`. +// `#![no_std]` on a fully unconfigured crate is respected if it's placed before `cfg(false)`. // Therefore this crate doesn't link to libstd. //@ no-prefer-dynamic #![no_std] #![crate_type = "lib"] -#![cfg(FALSE)] +#![cfg(false)] diff --git a/tests/ui/cfg/auxiliary/cfged_out.rs b/tests/ui/cfg/auxiliary/cfged_out.rs index f6a9089cf29d..564280b24f59 100644 --- a/tests/ui/cfg/auxiliary/cfged_out.rs +++ b/tests/ui/cfg/auxiliary/cfged_out.rs @@ -1,8 +1,8 @@ pub mod inner { - #[cfg(FALSE)] + #[cfg(false)] pub fn uwu() {} - #[cfg(FALSE)] + #[cfg(false)] pub mod doesnt_exist { pub fn hello() {} } diff --git a/tests/ui/cfg/cfg-false-feature.rs b/tests/ui/cfg/cfg-false-feature.rs index 716b18492c73..f66e4722440c 100644 --- a/tests/ui/cfg/cfg-false-feature.rs +++ b/tests/ui/cfg/cfg-false-feature.rs @@ -1,10 +1,10 @@ -// Features above `cfg(FALSE)` are in effect in a fully unconfigured crate (issue #104633). +// Features above `cfg(false)` are in effect in a fully unconfigured crate (issue #104633). //@ check-pass //@ compile-flags: --crate-type lib #![feature(decl_macro)] -#![cfg(FALSE)] +#![cfg(false)] #![feature(box_patterns)] macro mac() {} // OK diff --git a/tests/ui/cfg/cfg-macros-notfoo.rs b/tests/ui/cfg/cfg-macros-notfoo.rs index 9feb06be73e9..c25cf1c39bf5 100644 --- a/tests/ui/cfg/cfg-macros-notfoo.rs +++ b/tests/ui/cfg/cfg-macros-notfoo.rs @@ -3,7 +3,7 @@ // check that cfg correctly chooses between the macro impls (see also // cfg-macros-foo.rs) -#[cfg(FALSE)] +#[cfg(false)] #[macro_use] mod foo { macro_rules! bar { diff --git a/tests/ui/cfg/cfg-match-arm.rs b/tests/ui/cfg/cfg-match-arm.rs index f6cd52c475cf..cb5bf0ab0653 100644 --- a/tests/ui/cfg/cfg-match-arm.rs +++ b/tests/ui/cfg/cfg-match-arm.rs @@ -11,7 +11,7 @@ fn foo(f: Foo) { Foo::Bar => {}, #[cfg(not(FALSE))] Foo::Baz => {}, - #[cfg(FALSE)] + #[cfg(false)] Basdfwe => {} } } diff --git a/tests/ui/cfg/cfg-stmt-recovery.rs b/tests/ui/cfg/cfg-stmt-recovery.rs index 2e0839d2a153..f0f9a649165b 100644 --- a/tests/ui/cfg/cfg-stmt-recovery.rs +++ b/tests/ui/cfg/cfg-stmt-recovery.rs @@ -6,7 +6,7 @@ #[cfg_eval] fn main() { #[cfg_eval] - let _ = #[cfg(FALSE)] 0; + let _ = #[cfg(false)] 0; //~^ ERROR removing an expression is not supported in this position //~| ERROR expected expression, found `;` //~| ERROR removing an expression is not supported in this position diff --git a/tests/ui/cfg/cfg-stmt-recovery.stderr b/tests/ui/cfg/cfg-stmt-recovery.stderr index cb15e21fac69..e34da72afd93 100644 --- a/tests/ui/cfg/cfg-stmt-recovery.stderr +++ b/tests/ui/cfg/cfg-stmt-recovery.stderr @@ -1,19 +1,19 @@ error: removing an expression is not supported in this position --> $DIR/cfg-stmt-recovery.rs:9:13 | -LL | let _ = #[cfg(FALSE)] 0; +LL | let _ = #[cfg(false)] 0; | ^^^^^^^^^^^^^ error: expected expression, found `;` --> $DIR/cfg-stmt-recovery.rs:9:28 | -LL | let _ = #[cfg(FALSE)] 0; +LL | let _ = #[cfg(false)] 0; | ^ expected expression error: removing an expression is not supported in this position --> $DIR/cfg-stmt-recovery.rs:9:13 | -LL | let _ = #[cfg(FALSE)] 0; +LL | let _ = #[cfg(false)] 0; | ^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/tests/ui/cfg/cfg_stmt_expr.rs b/tests/ui/cfg/cfg_stmt_expr.rs index 9245f6d97576..361b159a354f 100644 --- a/tests/ui/cfg/cfg_stmt_expr.rs +++ b/tests/ui/cfg/cfg_stmt_expr.rs @@ -7,47 +7,47 @@ fn main() { let a = 413; - #[cfg(FALSE)] + #[cfg(false)] let a = (); assert_eq!(a, 413); let mut b = 612; - #[cfg(FALSE)] + #[cfg(false)] { b = 1111; } assert_eq!(b, 612); - #[cfg(FALSE)] + #[cfg(false)] undefined_fn(); - #[cfg(FALSE)] + #[cfg(false)] undefined_macro!(); - #[cfg(FALSE)] + #[cfg(false)] undefined_macro![]; - #[cfg(FALSE)] + #[cfg(false)] undefined_macro!{}; // pretty printer bug... - // #[cfg(FALSE)] + // #[cfg(false)] // undefined_macro!{} - let () = (#[cfg(FALSE)] 341,); // Should this also work on parens? - let t = (1, #[cfg(FALSE)] 3, 4); + let () = (#[cfg(false)] 341,); // Should this also work on parens? + let t = (1, #[cfg(false)] 3, 4); assert_eq!(t, (1, 4)); let f = |_: u32, _: u32| (); - f(2, 1, #[cfg(FALSE)] 6); + f(2, 1, #[cfg(false)] 6); - let _: u32 = a.clone(#[cfg(FALSE)] undefined); + let _: u32 = a.clone(#[cfg(false)] undefined); - let _: [(); 0] = [#[cfg(FALSE)] 126]; - let t = [#[cfg(FALSE)] 1, 2, 6]; + let _: [(); 0] = [#[cfg(false)] 126]; + let t = [#[cfg(false)] 1, 2, 6]; assert_eq!(t, [2, 6]); { let r; - #[cfg(FALSE)] + #[cfg(false)] (r = 5); #[cfg(not(FALSE))] (r = 10); @@ -75,7 +75,7 @@ fn main() { 612 }); - assert_eq!((#[cfg(FALSE)] 1, #[cfg(not(FALSE))] 2), (2,)); + assert_eq!((#[cfg(false)] 1, #[cfg(not(FALSE))] 2), (2,)); assert_eq!(n, 612); // check that lints work diff --git a/tests/ui/cfg/conditional-compile.rs b/tests/ui/cfg/conditional-compile.rs index dff280054d65..0739e877bfd1 100644 --- a/tests/ui/cfg/conditional-compile.rs +++ b/tests/ui/cfg/conditional-compile.rs @@ -6,16 +6,16 @@ // Crate use statements -#[cfg(FALSE)] +#[cfg(false)] use flippity; -#[cfg(FALSE)] +#[cfg(false)] static b: bool = false; static b: bool = true; mod rustrt { - #[cfg(FALSE)] + #[cfg(false)] extern "C" { // This symbol doesn't exist and would be a link error if this // module was codegened @@ -25,12 +25,12 @@ mod rustrt { extern "C" {} } -#[cfg(FALSE)] +#[cfg(false)] type t = isize; type t = bool; -#[cfg(FALSE)] +#[cfg(false)] enum tg { foo, } @@ -39,12 +39,12 @@ enum tg { bar, } -#[cfg(FALSE)] +#[cfg(false)] struct r { i: isize, } -#[cfg(FALSE)] +#[cfg(false)] fn r(i: isize) -> r { r { i: i } } @@ -57,7 +57,7 @@ fn r(i: isize) -> r { r { i: i } } -#[cfg(FALSE)] +#[cfg(false)] mod m { // This needs to parse but would fail in typeck. Since it's not in // the current config it should not be typechecked. @@ -69,7 +69,7 @@ mod m { mod m { // Submodules have slightly different code paths than the top-level // module, so let's make sure this jazz works here as well - #[cfg(FALSE)] + #[cfg(false)] pub fn f() {} pub fn f() {} @@ -77,7 +77,7 @@ mod m { // Since the FALSE configuration isn't defined main will just be // parsed, but nothing further will be done with it -#[cfg(FALSE)] +#[cfg(false)] pub fn main() { panic!() } @@ -93,14 +93,14 @@ pub fn main() { } fn test_in_fn_ctxt() { - #[cfg(FALSE)] + #[cfg(false)] fn f() { panic!() } fn f() {} f(); - #[cfg(FALSE)] + #[cfg(false)] static i: isize = 0; static i: isize = 1; assert_eq!(i, 1); @@ -109,7 +109,7 @@ fn test_in_fn_ctxt() { mod test_foreign_items { pub mod rustrt { extern "C" { - #[cfg(FALSE)] + #[cfg(false)] pub fn write() -> String; pub fn write() -> String; } @@ -117,7 +117,7 @@ mod test_foreign_items { } mod test_use_statements { - #[cfg(FALSE)] + #[cfg(false)] use flippity_foo; } @@ -127,24 +127,24 @@ mod test_methods { } impl Fooable for Foo { - #[cfg(FALSE)] + #[cfg(false)] fn what(&self) {} fn what(&self) {} - #[cfg(FALSE)] + #[cfg(false)] fn the(&self) {} fn the(&self) {} } trait Fooable { - #[cfg(FALSE)] + #[cfg(false)] fn what(&self); fn what(&self); - #[cfg(FALSE)] + #[cfg(false)] fn the(&self); fn the(&self); diff --git a/tests/ui/cfg/diagnostics-cross-crate.stderr b/tests/ui/cfg/diagnostics-cross-crate.stderr index 07ad4e3272d1..3e32a856e954 100644 --- a/tests/ui/cfg/diagnostics-cross-crate.stderr +++ b/tests/ui/cfg/diagnostics-cross-crate.stderr @@ -12,7 +12,7 @@ LL | pub mod doesnt_exist { note: the item is gated here --> $DIR/auxiliary/cfged_out.rs:5:5 | -LL | #[cfg(FALSE)] +LL | #[cfg(false)] | ^^^^^^^^^^^^^ error[E0425]: cannot find function `uwu` in crate `cfged_out` @@ -35,7 +35,7 @@ LL | pub fn uwu() {} note: the item is gated here --> $DIR/auxiliary/cfged_out.rs:2:5 | -LL | #[cfg(FALSE)] +LL | #[cfg(false)] | ^^^^^^^^^^^^^ error[E0425]: cannot find function `meow` in module `cfged_out::inner::right` diff --git a/tests/ui/cfg/diagnostics-reexport.rs b/tests/ui/cfg/diagnostics-reexport.rs index 9ae7d931fcb8..56fac5622382 100644 --- a/tests/ui/cfg/diagnostics-reexport.rs +++ b/tests/ui/cfg/diagnostics-reexport.rs @@ -1,10 +1,10 @@ pub mod inner { - #[cfg(FALSE)] + #[cfg(false)] mod gone { pub fn uwu() {} } - #[cfg(FALSE)] //~ NOTE the item is gated here + #[cfg(false)] //~ NOTE the item is gated here pub use super::uwu; //~^ NOTE found an item that was configured out } @@ -14,7 +14,7 @@ pub use a::x; //~| NOTE no `x` in `a` mod a { - #[cfg(FALSE)] //~ NOTE the item is gated here + #[cfg(false)] //~ NOTE the item is gated here pub fn x() {} //~^ NOTE found an item that was configured out } @@ -25,10 +25,10 @@ pub use b::{x, y}; //~| NOTE no `y` in `b` mod b { - #[cfg(FALSE)] //~ NOTE the item is gated here + #[cfg(false)] //~ NOTE the item is gated here pub fn x() {} //~^ NOTE found an item that was configured out - #[cfg(FALSE)] //~ NOTE the item is gated here + #[cfg(false)] //~ NOTE the item is gated here pub fn y() {} //~^ NOTE found an item that was configured out } diff --git a/tests/ui/cfg/diagnostics-reexport.stderr b/tests/ui/cfg/diagnostics-reexport.stderr index 737202fdf9ad..95dc4fac945e 100644 --- a/tests/ui/cfg/diagnostics-reexport.stderr +++ b/tests/ui/cfg/diagnostics-reexport.stderr @@ -12,7 +12,7 @@ LL | pub fn x() {} note: the item is gated here --> $DIR/diagnostics-reexport.rs:17:5 | -LL | #[cfg(FALSE)] +LL | #[cfg(false)] | ^^^^^^^^^^^^^ error[E0432]: unresolved imports `b::x`, `b::y` @@ -31,7 +31,7 @@ LL | pub fn x() {} note: the item is gated here --> $DIR/diagnostics-reexport.rs:28:5 | -LL | #[cfg(FALSE)] +LL | #[cfg(false)] | ^^^^^^^^^^^^^ note: found an item that was configured out --> $DIR/diagnostics-reexport.rs:32:12 @@ -41,7 +41,7 @@ LL | pub fn y() {} note: the item is gated here --> $DIR/diagnostics-reexport.rs:31:5 | -LL | #[cfg(FALSE)] +LL | #[cfg(false)] | ^^^^^^^^^^^^^ error[E0425]: cannot find function `uwu` in module `inner` @@ -58,7 +58,7 @@ LL | pub use super::uwu; note: the item is gated here --> $DIR/diagnostics-reexport.rs:7:5 | -LL | #[cfg(FALSE)] +LL | #[cfg(false)] | ^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/tests/ui/cfg/diagnostics-same-crate.rs b/tests/ui/cfg/diagnostics-same-crate.rs index d6f8dd21a922..9153f20b2964 100644 --- a/tests/ui/cfg/diagnostics-same-crate.rs +++ b/tests/ui/cfg/diagnostics-same-crate.rs @@ -1,11 +1,11 @@ #![allow(unexpected_cfgs)] // since we want to recognize them as unexpected pub mod inner { - #[cfg(FALSE)] //~ NOTE the item is gated here + #[cfg(false)] //~ NOTE the item is gated here pub fn uwu() {} //~^ NOTE found an item that was configured out - #[cfg(FALSE)] //~ NOTE the item is gated here + #[cfg(false)] //~ NOTE the item is gated here //~^ NOTE the item is gated here //~| NOTE the item is gated here pub mod doesnt_exist { diff --git a/tests/ui/cfg/diagnostics-same-crate.stderr b/tests/ui/cfg/diagnostics-same-crate.stderr index dd0d10c6567e..75a1bc39a013 100644 --- a/tests/ui/cfg/diagnostics-same-crate.stderr +++ b/tests/ui/cfg/diagnostics-same-crate.stderr @@ -12,7 +12,7 @@ LL | pub mod doesnt_exist { note: the item is gated here --> $DIR/diagnostics-same-crate.rs:8:5 | -LL | #[cfg(FALSE)] +LL | #[cfg(false)] | ^^^^^^^^^^^^^ error[E0432]: unresolved import `super::inner::doesnt_exist` @@ -29,7 +29,7 @@ LL | pub mod doesnt_exist { note: the item is gated here --> $DIR/diagnostics-same-crate.rs:8:5 | -LL | #[cfg(FALSE)] +LL | #[cfg(false)] | ^^^^^^^^^^^^^ error[E0433]: failed to resolve: could not find `doesnt_exist` in `inner` @@ -46,7 +46,7 @@ LL | pub mod doesnt_exist { note: the item is gated here --> $DIR/diagnostics-same-crate.rs:8:5 | -LL | #[cfg(FALSE)] +LL | #[cfg(false)] | ^^^^^^^^^^^^^ error[E0425]: cannot find function `uwu` in module `inner` @@ -63,7 +63,7 @@ LL | pub fn uwu() {} note: the item is gated here --> $DIR/diagnostics-same-crate.rs:4:5 | -LL | #[cfg(FALSE)] +LL | #[cfg(false)] | ^^^^^^^^^^^^^ error[E0425]: cannot find function `meow` in module `inner::right` diff --git a/tests/ui/check-cfg/allow-same-level.rs b/tests/ui/check-cfg/allow-same-level.rs index 8260b57bad4d..3f673cb88447 100644 --- a/tests/ui/check-cfg/allow-same-level.rs +++ b/tests/ui/check-cfg/allow-same-level.rs @@ -12,7 +12,7 @@ //@ compile-flags: --check-cfg=cfg() --cfg=unknown_but_active_cfg #[allow(unexpected_cfgs)] -#[cfg(FALSE)] +#[cfg(unknown_and_inactive_cfg)] //~^ WARNING unexpected `cfg` condition name fn bar() {} diff --git a/tests/ui/check-cfg/allow-same-level.stderr b/tests/ui/check-cfg/allow-same-level.stderr index a705cd4e5f01..cfff03048b53 100644 --- a/tests/ui/check-cfg/allow-same-level.stderr +++ b/tests/ui/check-cfg/allow-same-level.stderr @@ -1,10 +1,10 @@ -warning: unexpected `cfg` condition name: `FALSE` +warning: unexpected `cfg` condition name: `unknown_and_inactive_cfg` --> $DIR/allow-same-level.rs:15:7 | -LL | #[cfg(FALSE)] - | ^^^^^ +LL | #[cfg(unknown_and_inactive_cfg)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: to expect this configuration use `--check-cfg=cfg(FALSE)` + = help: to expect this configuration use `--check-cfg=cfg(unknown_and_inactive_cfg)` = note: see for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/allow-top-level.rs b/tests/ui/check-cfg/allow-top-level.rs index cf94ed5da428..7ccecd2360e8 100644 --- a/tests/ui/check-cfg/allow-top-level.rs +++ b/tests/ui/check-cfg/allow-top-level.rs @@ -6,7 +6,7 @@ #![allow(unexpected_cfgs)] -#[cfg(FALSE)] +#[cfg(false)] fn bar() {} fn foo() { diff --git a/tests/ui/check-cfg/allow-upper-level.rs b/tests/ui/check-cfg/allow-upper-level.rs index 2e6664c30d39..657a4768f952 100644 --- a/tests/ui/check-cfg/allow-upper-level.rs +++ b/tests/ui/check-cfg/allow-upper-level.rs @@ -6,7 +6,7 @@ #[allow(unexpected_cfgs)] mod aa { - #[cfg(FALSE)] + #[cfg(false)] fn bar() {} } diff --git a/tests/ui/conditional-compilation/cfg-generic-params.rs b/tests/ui/conditional-compilation/cfg-generic-params.rs index 4bb8f8ae94f6..6480a0f24794 100644 --- a/tests/ui/conditional-compilation/cfg-generic-params.rs +++ b/tests/ui/conditional-compilation/cfg-generic-params.rs @@ -1,18 +1,18 @@ //@ compile-flags:--cfg yes --check-cfg=cfg(yes,no) -fn f_lt<#[cfg(yes)] 'a: 'a, #[cfg(FALSE)] T>() {} -fn f_ty<#[cfg(FALSE)] 'a: 'a, #[cfg(yes)] T>() {} +fn f_lt<#[cfg(yes)] 'a: 'a, #[cfg(false)] T>() {} +fn f_ty<#[cfg(false)] 'a: 'a, #[cfg(yes)] T>() {} -type FnGood = for<#[cfg(yes)] 'a, #[cfg(FALSE)] T> fn(); // OK -type FnBad = for<#[cfg(FALSE)] 'a, #[cfg(yes)] T> fn(); +type FnGood = for<#[cfg(yes)] 'a, #[cfg(false)] T> fn(); // OK +type FnBad = for<#[cfg(false)] 'a, #[cfg(yes)] T> fn(); //~^ ERROR only lifetime parameters can be used in this context -type PolyGood = dyn for<#[cfg(yes)] 'a, #[cfg(FALSE)] T> Copy; // OK -type PolyBad = dyn for<#[cfg(FALSE)] 'a, #[cfg(yes)] T> Copy; +type PolyGood = dyn for<#[cfg(yes)] 'a, #[cfg(false)] T> Copy; // OK +type PolyBad = dyn for<#[cfg(false)] 'a, #[cfg(yes)] T> Copy; //~^ ERROR only lifetime parameters can be used in this context -struct WhereGood where for<#[cfg(yes)] 'a, #[cfg(FALSE)] T> u8: Copy; // OK -struct WhereBad where for<#[cfg(FALSE)] 'a, #[cfg(yes)] T> u8: Copy; +struct WhereGood where for<#[cfg(yes)] 'a, #[cfg(false)] T> u8: Copy; // OK +struct WhereBad where for<#[cfg(false)] 'a, #[cfg(yes)] T> u8: Copy; //~^ ERROR only lifetime parameters can be used in this context fn f_lt_no<#[cfg_attr(FALSE, unknown)] 'a>() {} // OK diff --git a/tests/ui/conditional-compilation/cfg-generic-params.stderr b/tests/ui/conditional-compilation/cfg-generic-params.stderr index 563616be36bc..bae75dd0deb0 100644 --- a/tests/ui/conditional-compilation/cfg-generic-params.stderr +++ b/tests/ui/conditional-compilation/cfg-generic-params.stderr @@ -31,7 +31,7 @@ LL | struct WhereYes where for<#[cfg_attr(yes, unknown)] 'a> u8: Copy; error[E0658]: only lifetime parameters can be used in this context --> $DIR/cfg-generic-params.rs:7:48 | -LL | type FnBad = for<#[cfg(FALSE)] 'a, #[cfg(yes)] T> fn(); +LL | type FnBad = for<#[cfg(false)] 'a, #[cfg(yes)] T> fn(); | ^ | = note: see issue #108185 for more information @@ -41,7 +41,7 @@ LL | type FnBad = for<#[cfg(FALSE)] 'a, #[cfg(yes)] T> fn(); error[E0658]: only lifetime parameters can be used in this context --> $DIR/cfg-generic-params.rs:11:54 | -LL | type PolyBad = dyn for<#[cfg(FALSE)] 'a, #[cfg(yes)] T> Copy; +LL | type PolyBad = dyn for<#[cfg(false)] 'a, #[cfg(yes)] T> Copy; | ^ | = note: see issue #108185 for more information @@ -51,7 +51,7 @@ LL | type PolyBad = dyn for<#[cfg(FALSE)] 'a, #[cfg(yes)] T> Copy; error[E0658]: only lifetime parameters can be used in this context --> $DIR/cfg-generic-params.rs:15:57 | -LL | struct WhereBad where for<#[cfg(FALSE)] 'a, #[cfg(yes)] T> u8: Copy; +LL | struct WhereBad where for<#[cfg(false)] 'a, #[cfg(yes)] T> u8: Copy; | ^ | = note: see issue #108185 for more information diff --git a/tests/ui/conditional-compilation/cfg-in-crate-1.rs b/tests/ui/conditional-compilation/cfg-in-crate-1.rs index a1faa2397a33..b9efa32babef 100644 --- a/tests/ui/conditional-compilation/cfg-in-crate-1.rs +++ b/tests/ui/conditional-compilation/cfg-in-crate-1.rs @@ -1 +1 @@ -#![cfg(FALSE)] //~ ERROR `main` function not found in crate `cfg_in_crate_1` +#![cfg(false)] //~ ERROR `main` function not found in crate `cfg_in_crate_1` diff --git a/tests/ui/conditional-compilation/cfg-in-crate-1.stderr b/tests/ui/conditional-compilation/cfg-in-crate-1.stderr index 126e10cf0402..352baf33091b 100644 --- a/tests/ui/conditional-compilation/cfg-in-crate-1.stderr +++ b/tests/ui/conditional-compilation/cfg-in-crate-1.stderr @@ -1,7 +1,7 @@ error[E0601]: `main` function not found in crate `cfg_in_crate_1` --> $DIR/cfg-in-crate-1.rs:1:15 | -LL | #![cfg(FALSE)] +LL | #![cfg(false)] | ^ consider adding a `main` function to `$DIR/cfg-in-crate-1.rs` error: aborting due to 1 previous error diff --git a/tests/ui/conditional-compilation/cfg-non-opt-expr.rs b/tests/ui/conditional-compilation/cfg-non-opt-expr.rs index ae85f38e645e..cae07ae0ced1 100644 --- a/tests/ui/conditional-compilation/cfg-non-opt-expr.rs +++ b/tests/ui/conditional-compilation/cfg-non-opt-expr.rs @@ -2,10 +2,10 @@ #![feature(custom_test_frameworks)] fn main() { - let _ = #[cfg(FALSE)] (); + let _ = #[cfg(false)] (); //~^ ERROR removing an expression is not supported in this position - let _ = 1 + 2 + #[cfg(FALSE)] 3; + let _ = 1 + 2 + #[cfg(false)] 3; //~^ ERROR removing an expression is not supported in this position - let _ = [1, 2, 3][#[cfg(FALSE)] 1]; + let _ = [1, 2, 3][#[cfg(false)] 1]; //~^ ERROR removing an expression is not supported in this position } diff --git a/tests/ui/conditional-compilation/cfg-non-opt-expr.stderr b/tests/ui/conditional-compilation/cfg-non-opt-expr.stderr index 06eaa59efdd7..bd1bfeb06c7a 100644 --- a/tests/ui/conditional-compilation/cfg-non-opt-expr.stderr +++ b/tests/ui/conditional-compilation/cfg-non-opt-expr.stderr @@ -1,19 +1,19 @@ error: removing an expression is not supported in this position --> $DIR/cfg-non-opt-expr.rs:5:13 | -LL | let _ = #[cfg(FALSE)] (); +LL | let _ = #[cfg(false)] (); | ^^^^^^^^^^^^^ error: removing an expression is not supported in this position --> $DIR/cfg-non-opt-expr.rs:7:21 | -LL | let _ = 1 + 2 + #[cfg(FALSE)] 3; +LL | let _ = 1 + 2 + #[cfg(false)] 3; | ^^^^^^^^^^^^^ error: removing an expression is not supported in this position --> $DIR/cfg-non-opt-expr.rs:9:23 | -LL | let _ = [1, 2, 3][#[cfg(FALSE)] 1]; +LL | let _ = [1, 2, 3][#[cfg(false)] 1]; | ^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/tests/ui/conditional-compilation/module_with_cfg.rs b/tests/ui/conditional-compilation/module_with_cfg.rs index 778379fa6ea7..29eb6d43aa79 100644 --- a/tests/ui/conditional-compilation/module_with_cfg.rs +++ b/tests/ui/conditional-compilation/module_with_cfg.rs @@ -1,3 +1,3 @@ //@ ignore-test (auxiliary, used by other tests) -#![cfg_attr(all(), cfg(FALSE))] +#![cfg_attr(all(), cfg(false))] diff --git a/tests/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier-2.rs b/tests/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier-2.rs index 7ced24808bf6..50728970be2c 100644 --- a/tests/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier-2.rs +++ b/tests/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier-2.rs @@ -1,6 +1,6 @@ fn main() {} -#[cfg(FALSE)] +#[cfg(false)] fn container() { const unsafe WhereIsFerris Now() {} //~^ ERROR expected one of `extern` or `fn` diff --git a/tests/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.rs b/tests/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.rs index 6f575d055a29..20e79ca200bb 100644 --- a/tests/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.rs +++ b/tests/ui/consts/const-extern-fn/issue-68062-const-extern-fns-dont-need-fn-specifier.rs @@ -1,6 +1,6 @@ fn main() {} -#[cfg(FALSE)] +#[cfg(false)] fn container() { const extern "Rust" PUT_ANYTHING_YOU_WANT_HERE bug() -> usize { 1 } //~^ ERROR expected `fn` diff --git a/tests/ui/delegation/explicit-paths-signature-pass.rs b/tests/ui/delegation/explicit-paths-signature-pass.rs index 8c16ad92393c..11bc8a70db0e 100644 --- a/tests/ui/delegation/explicit-paths-signature-pass.rs +++ b/tests/ui/delegation/explicit-paths-signature-pass.rs @@ -6,7 +6,7 @@ mod to_reuse { use crate::S; - pub fn foo<'a>(#[cfg(FALSE)] a: u8, _b: &'a S) -> u32 { + pub fn foo<'a>(#[cfg(false)] a: u8, _b: &'a S) -> u32 { 1 } } diff --git a/tests/ui/expr/if/attrs/bad-cfg.rs b/tests/ui/expr/if/attrs/bad-cfg.rs index 3f84929a00e4..6e7f4b007a92 100644 --- a/tests/ui/expr/if/attrs/bad-cfg.rs +++ b/tests/ui/expr/if/attrs/bad-cfg.rs @@ -1,5 +1,5 @@ #![feature(stmt_expr_attributes)] fn main() { - let _ = #[cfg(FALSE)] if true {}; //~ ERROR removing an expression + let _ = #[cfg(false)] if true {}; //~ ERROR removing an expression } diff --git a/tests/ui/expr/if/attrs/bad-cfg.stderr b/tests/ui/expr/if/attrs/bad-cfg.stderr index ca0eced267d6..d12f5eeaf5fa 100644 --- a/tests/ui/expr/if/attrs/bad-cfg.stderr +++ b/tests/ui/expr/if/attrs/bad-cfg.stderr @@ -1,7 +1,7 @@ error: removing an expression is not supported in this position --> $DIR/bad-cfg.rs:4:13 | -LL | let _ = #[cfg(FALSE)] if true {}; +LL | let _ = #[cfg(false)] if true {}; | ^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/expr/if/attrs/cfg-false-if-attr.rs b/tests/ui/expr/if/attrs/cfg-false-if-attr.rs index c139b347d998..e6c83b86cb77 100644 --- a/tests/ui/expr/if/attrs/cfg-false-if-attr.rs +++ b/tests/ui/expr/if/attrs/cfg-false-if-attr.rs @@ -1,12 +1,12 @@ //@ check-pass -#[cfg(FALSE)] +#[cfg(false)] fn simple_attr() { #[attr] if true {} #[allow_warnings] if true {} } -#[cfg(FALSE)] +#[cfg(false)] fn if_else_chain() { #[first_attr] if true { } else if false { @@ -14,20 +14,20 @@ fn if_else_chain() { } } -#[cfg(FALSE)] +#[cfg(false)] fn if_let() { #[attr] if let Some(_) = Some(true) {} } fn bar() { - #[cfg(FALSE)] + #[cfg(false)] if true { - let x: () = true; // Should not error due to the #[cfg(FALSE)] + let x: () = true; // Should not error due to the #[cfg(false)] } - #[cfg_attr(not(FALSE), cfg(FALSE))] + #[cfg_attr(not(FALSE), cfg(false))] if true { - let a: () = true; // Should not error due to the applied #[cfg(FALSE)] + let a: () = true; // Should not error due to the applied #[cfg(false)] } } diff --git a/tests/ui/expr/if/attrs/else-attrs.rs b/tests/ui/expr/if/attrs/else-attrs.rs index 85da7cf6bb8c..4010d9d6132b 100644 --- a/tests/ui/expr/if/attrs/else-attrs.rs +++ b/tests/ui/expr/if/attrs/else-attrs.rs @@ -1,11 +1,11 @@ -#[cfg(FALSE)] +#[cfg(false)] fn if_else_parse_error() { if true { } #[attr] else if false { //~ ERROR expected } } -#[cfg(FALSE)] +#[cfg(false)] fn else_attr_ifparse_error() { if true { } else #[attr] if false { //~ ERROR outer attributes are not allowed @@ -13,7 +13,7 @@ fn else_attr_ifparse_error() { } } -#[cfg(FALSE)] +#[cfg(false)] fn else_parse_error() { if true { } else if false { diff --git a/tests/ui/expr/if/attrs/gate-whole-expr.rs b/tests/ui/expr/if/attrs/gate-whole-expr.rs index bab01592c247..885909016b5e 100644 --- a/tests/ui/expr/if/attrs/gate-whole-expr.rs +++ b/tests/ui/expr/if/attrs/gate-whole-expr.rs @@ -3,7 +3,7 @@ fn main() { let x = 1; - #[cfg(FALSE)] + #[cfg(false)] if false { x = 2; } else if true { diff --git a/tests/ui/expr/if/attrs/let-chains-attr.rs b/tests/ui/expr/if/attrs/let-chains-attr.rs index b3dbd53e5798..2cf1b169f069 100644 --- a/tests/ui/expr/if/attrs/let-chains-attr.rs +++ b/tests/ui/expr/if/attrs/let-chains-attr.rs @@ -2,7 +2,7 @@ #![feature(let_chains)] -#[cfg(FALSE)] +#[cfg(false)] fn foo() { #[attr] if let Some(_) = Some(true) && let Ok(_) = Ok(1) { diff --git a/tests/ui/feature-gates/feature-gate-coroutines.rs b/tests/ui/feature-gates/feature-gate-coroutines.rs index f20dc56f1229..b37a61d9105f 100644 --- a/tests/ui/feature-gates/feature-gate-coroutines.rs +++ b/tests/ui/feature-gates/feature-gate-coroutines.rs @@ -12,7 +12,7 @@ fn main() { //~^^ ERROR `yield` can only be used } -#[cfg(FALSE)] +#[cfg(false)] fn foo() { // Ok in 2024 edition yield; //~ ERROR yield syntax is experimental diff --git a/tests/ui/feature-gates/feature-gate-deref_patterns.rs b/tests/ui/feature-gates/feature-gate-deref_patterns.rs index b43001f2d53f..53b4301f10c0 100644 --- a/tests/ui/feature-gates/feature-gate-deref_patterns.rs +++ b/tests/ui/feature-gates/feature-gate-deref_patterns.rs @@ -4,6 +4,6 @@ fn main() { println!("x: {}", x); // `box` syntax is allowed to be cfg-ed out for historical reasons (#65742). - #[cfg(FALSE)] + #[cfg(false)] let box _x = Box::new('c'); } diff --git a/tests/ui/feature-gates/feature-gate-gen_blocks.rs b/tests/ui/feature-gates/feature-gate-gen_blocks.rs index 01fd922b0e99..989daf471bcb 100644 --- a/tests/ui/feature-gates/feature-gate-gen_blocks.rs +++ b/tests/ui/feature-gates/feature-gate-gen_blocks.rs @@ -17,7 +17,7 @@ fn test_async_gen() { fn main() {} -#[cfg(FALSE)] +#[cfg(false)] fn foo() { gen {}; //[e2024]~^ ERROR: gen blocks are experimental diff --git a/tests/ui/feature-gates/feature-gate-guard-patterns.rs b/tests/ui/feature-gates/feature-gate-guard-patterns.rs index 52ed89e668b1..74fb5817081c 100644 --- a/tests/ui/feature-gates/feature-gate-guard-patterns.rs +++ b/tests/ui/feature-gates/feature-gate-guard-patterns.rs @@ -30,7 +30,7 @@ fn other_guards_dont() { while let (x if guard(x)) = 0 {} //~^ ERROR: guard patterns are experimental - #[cfg(FALSE)] + #[cfg(false)] while let (x if guard(x)) = 0 {} //~^ ERROR: guard patterns are experimental } diff --git a/tests/ui/feature-gates/feature-gate-mut-ref.rs b/tests/ui/feature-gates/feature-gate-mut-ref.rs index 806b25de66ff..752ae35d8a9a 100644 --- a/tests/ui/feature-gates/feature-gate-mut-ref.rs +++ b/tests/ui/feature-gates/feature-gate-mut-ref.rs @@ -6,8 +6,8 @@ fn main() { let mut ref mut z = 14; //~ ERROR [E0658] z = &mut 15; - #[cfg(FALSE)] + #[cfg(false)] let mut ref x = 10; //~ ERROR [E0658] - #[cfg(FALSE)] + #[cfg(false)] let mut ref mut y = 10; //~ ERROR [E0658] } diff --git a/tests/ui/feature-gates/feature-gate-never_patterns.rs b/tests/ui/feature-gates/feature-gate-never_patterns.rs index d23405ada2d4..2cb0b5a6679d 100644 --- a/tests/ui/feature-gates/feature-gate-never_patterns.rs +++ b/tests/ui/feature-gates/feature-gate-never_patterns.rs @@ -15,12 +15,12 @@ fn main() { //~^ ERROR `!` patterns are experimental } // Check that the gate operates even behind `cfg`. - #[cfg(FALSE)] + #[cfg(false)] match *ptr { ! //~^ ERROR `!` patterns are experimental } - #[cfg(FALSE)] + #[cfg(false)] match *ptr { ! => {} //~^ ERROR `!` patterns are experimental @@ -60,13 +60,13 @@ fn main() { // Check that the gate operates even behind `cfg`. match Some(0) { None => {} - #[cfg(FALSE)] + #[cfg(false)] Some(_) //~^ ERROR `match` arm with no body } match Some(0) { _ => {} - #[cfg(FALSE)] + #[cfg(false)] Some(_) if false //~^ ERROR `match` arm with no body } diff --git a/tests/ui/feature-gates/feature-gate-postfix_match.rs b/tests/ui/feature-gates/feature-gate-postfix_match.rs index dce7e81a9ae4..2226816e5ea7 100644 --- a/tests/ui/feature-gates/feature-gate-postfix_match.rs +++ b/tests/ui/feature-gates/feature-gate-postfix_match.rs @@ -9,7 +9,7 @@ fn main() { }; // Test that the gate works behind a cfg - #[cfg(FALSE)] + #[cfg(false)] val.match { //~ ERROR postfix match is experimental Some(42) => "the answer to life, the universe, and everything", _ => "might be the answer to something" diff --git a/tests/ui/feature-gates/feature-gate-yeet_expr-in-cfg.rs b/tests/ui/feature-gates/feature-gate-yeet_expr-in-cfg.rs index 33fda822baad..bacbbc57c2c9 100644 --- a/tests/ui/feature-gates/feature-gate-yeet_expr-in-cfg.rs +++ b/tests/ui/feature-gates/feature-gate-yeet_expr-in-cfg.rs @@ -1,7 +1,7 @@ //@ compile-flags: --edition 2021 pub fn demo() -> Option { - #[cfg(FALSE)] + #[cfg(false)] { do yeet //~ ERROR `do yeet` expression is experimental } @@ -9,7 +9,7 @@ pub fn demo() -> Option { Some(1) } -#[cfg(FALSE)] +#[cfg(false)] pub fn alternative() -> Result<(), String> { do yeet "hello"; //~ ERROR `do yeet` expression is experimental } diff --git a/tests/ui/feature-gates/soft-syntax-gates-with-errors.rs b/tests/ui/feature-gates/soft-syntax-gates-with-errors.rs index 2aa2ed34020c..87629a5bcce7 100644 --- a/tests/ui/feature-gates/soft-syntax-gates-with-errors.rs +++ b/tests/ui/feature-gates/soft-syntax-gates-with-errors.rs @@ -5,7 +5,7 @@ macro a() {} //~^ ERROR: `macro` is experimental -#[cfg(FALSE)] +#[cfg(false)] macro b() {} macro_rules! identity { @@ -17,13 +17,13 @@ identity! { //~^ ERROR: `macro` is experimental } -#[cfg(FALSE)] +#[cfg(false)] identity! { macro d() {} // No error } identity! { - #[cfg(FALSE)] + #[cfg(false)] macro e() {} } diff --git a/tests/ui/feature-gates/soft-syntax-gates-without-errors.rs b/tests/ui/feature-gates/soft-syntax-gates-without-errors.rs index 056c8fb04f45..72d0bf1ccd52 100644 --- a/tests/ui/feature-gates/soft-syntax-gates-without-errors.rs +++ b/tests/ui/feature-gates/soft-syntax-gates-without-errors.rs @@ -2,7 +2,7 @@ // This file is used to test the behavior of the early-pass syntax warnings. // If macro syntax is stabilized, replace with a different unstable syntax. -#[cfg(FALSE)] +#[cfg(false)] macro b() {} //~^ WARN: `macro` is experimental //~| WARN: unstable syntax @@ -11,13 +11,13 @@ macro_rules! identity { ($($x:tt)*) => ($($x)*); } -#[cfg(FALSE)] +#[cfg(false)] identity! { macro d() {} // No error } identity! { - #[cfg(FALSE)] + #[cfg(false)] macro e() {} //~^ WARN: `macro` is experimental //~| WARN: unstable syntax diff --git a/tests/ui/feature-gates/stmt_expr_attrs_no_feature.rs b/tests/ui/feature-gates/stmt_expr_attrs_no_feature.rs index a160a9bb082d..4523afa7c4bd 100644 --- a/tests/ui/feature-gates/stmt_expr_attrs_no_feature.rs +++ b/tests/ui/feature-gates/stmt_expr_attrs_no_feature.rs @@ -25,7 +25,7 @@ fn main() { // Check that cfg works right -#[cfg(FALSE)] +#[cfg(false)] fn c() { #[rustc_dummy] 5; @@ -37,7 +37,7 @@ fn j() { 5; } -#[cfg_attr(not(FALSE), cfg(FALSE))] +#[cfg_attr(not(FALSE), cfg(false))] fn d() { #[rustc_dummy] 8; @@ -57,7 +57,7 @@ macro_rules! item_mac { #[rustc_dummy] 42; - #[cfg(FALSE)] + #[cfg(false)] fn f() { #[rustc_dummy] 5; @@ -69,7 +69,7 @@ macro_rules! item_mac { 5; } - #[cfg_attr(not(FALSE), cfg(FALSE))] + #[cfg_attr(not(FALSE), cfg(false))] fn g() { #[rustc_dummy] 8; @@ -90,42 +90,42 @@ item_mac!(e); // check that the gate visitor works right: extern "C" { - #[cfg(FALSE)] + #[cfg(false)] fn x(a: [u8; #[rustc_dummy] 5]); fn y(a: [u8; #[rustc_dummy] 5]); //~ ERROR attributes on expressions are experimental } struct Foo; impl Foo { - #[cfg(FALSE)] + #[cfg(false)] const X: u8 = #[rustc_dummy] 5; const Y: u8 = #[rustc_dummy] 5; //~ ERROR attributes on expressions are experimental } trait Bar { - #[cfg(FALSE)] + #[cfg(false)] const X: [u8; #[rustc_dummy] 5]; const Y: [u8; #[rustc_dummy] 5]; //~ ERROR attributes on expressions are experimental } struct Joyce { - #[cfg(FALSE)] + #[cfg(false)] field: [u8; #[rustc_dummy] 5], field2: [u8; #[rustc_dummy] 5] //~ ERROR attributes on expressions are experimental } struct Walky( - #[cfg(FALSE)] [u8; #[rustc_dummy] 5], + #[cfg(false)] [u8; #[rustc_dummy] 5], [u8; #[rustc_dummy] 5] //~ ERROR attributes on expressions are experimental ); enum Mike { Happy( - #[cfg(FALSE)] [u8; #[rustc_dummy] 5], + #[cfg(false)] [u8; #[rustc_dummy] 5], [u8; #[rustc_dummy] 5] //~ ERROR attributes on expressions are experimental ), Angry { - #[cfg(FALSE)] + #[cfg(false)] field: [u8; #[rustc_dummy] 5], field2: [u8; #[rustc_dummy] 5] //~ ERROR attributes on expressions are experimental } @@ -133,7 +133,7 @@ enum Mike { fn pat() { match 5 { - #[cfg(FALSE)] + #[cfg(false)] 5 => #[rustc_dummy] (), 6 => #[rustc_dummy] (), //~ ERROR attributes on expressions are experimental _ => (), diff --git a/tests/ui/filter-block-view-items.rs b/tests/ui/filter-block-view-items.rs index 975ab19ddf25..cb599c272647 100644 --- a/tests/ui/filter-block-view-items.rs +++ b/tests/ui/filter-block-view-items.rs @@ -3,5 +3,5 @@ pub fn main() { // Make sure that this view item is filtered out because otherwise it would // trigger a compilation error - #[cfg(FALSE)] use bar as foo; + #[cfg(false)] use bar as foo; } diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs index 33506a5c444a..01f4340b14ad 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs @@ -9,7 +9,7 @@ fn main() {} -#[cfg(FALSE)] +#[cfg(false)] fn syntax() { match scrutinee { ...X => {} //~ ERROR range-to patterns with `...` are not allowed diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.rs index 2f1ec6589721..24eb99347329 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.rs +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.rs @@ -3,7 +3,7 @@ fn main() {} -#[cfg(FALSE)] +#[cfg(false)] fn foo() { if let 0... = 1 {} //~ ERROR inclusive range with no end if let 0..= = 1 {} //~ ERROR inclusive range with no end diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.rs index 2d63fe078561..6b33ead3f87d 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.rs +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.rs @@ -1,6 +1,6 @@ fn main() {} -#[cfg(FALSE)] +#[cfg(false)] fn syntax() { match &0 { &0.. | _ => {} diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-syntactic-pass.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-syntactic-pass.rs index 4e3fffbef2de..02699e76ad29 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-syntactic-pass.rs +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-syntactic-pass.rs @@ -4,7 +4,7 @@ fn main() {} -#[cfg(FALSE)] +#[cfg(false)] fn syntax() { match scrutinee { X.. | 0.. | 'a'.. | 0.0f32.. => {} diff --git a/tests/ui/inner-attrs-on-impl.rs b/tests/ui/inner-attrs-on-impl.rs index 75f406232e20..1dce1cdd261a 100644 --- a/tests/ui/inner-attrs-on-impl.rs +++ b/tests/ui/inner-attrs-on-impl.rs @@ -3,7 +3,7 @@ struct Foo; impl Foo { - #![cfg(FALSE)] + #![cfg(false)] fn method(&self) -> bool { false } } @@ -12,7 +12,7 @@ impl Foo { #![cfg(not(FALSE))] // check that we don't eat attributes too eagerly. - #[cfg(FALSE)] + #[cfg(false)] fn method(&self) -> bool { false } fn method(&self) -> bool { true } diff --git a/tests/ui/issues/issue-11004.rs b/tests/ui/issues/issue-11004.rs index 09d5476dbe60..7292843c86a9 100644 --- a/tests/ui/issues/issue-11004.rs +++ b/tests/ui/issues/issue-11004.rs @@ -9,7 +9,7 @@ unsafe fn access(n:*mut A) -> (i32, f64) { (x, y) } -#[cfg(FALSE)] +#[cfg(false)] unsafe fn access(n:*mut A) -> (i32, f64) { let x : i32 = (*n).x; let y : f64 = (*n).y; diff --git a/tests/ui/issues/issue-11085.rs b/tests/ui/issues/issue-11085.rs index d0703b063954..c3f13199b308 100644 --- a/tests/ui/issues/issue-11085.rs +++ b/tests/ui/issues/issue-11085.rs @@ -3,7 +3,7 @@ #![allow(dead_code)] struct Foo { - #[cfg(FALSE)] + #[cfg(false)] bar: baz, foo: isize, } @@ -15,18 +15,18 @@ struct Foo2 { enum Bar1 { Bar1_1, - #[cfg(FALSE)] + #[cfg(false)] Bar1_2(NotAType), } enum Bar2 { - #[cfg(FALSE)] + #[cfg(false)] Bar2_1(NotAType), } enum Bar3 { Bar3_1 { - #[cfg(FALSE)] + #[cfg(false)] foo: isize, bar: isize, } diff --git a/tests/ui/issues/issue-16819.rs b/tests/ui/issues/issue-16819.rs index e2b109091777..2805c82acfb2 100644 --- a/tests/ui/issues/issue-16819.rs +++ b/tests/ui/issues/issue-16819.rs @@ -3,7 +3,7 @@ // `#[cfg]` on struct field permits empty unusable struct struct S { - #[cfg(FALSE)] + #[cfg(false)] a: int, } diff --git a/tests/ui/lexer/error-stage.rs b/tests/ui/lexer/error-stage.rs index c8d88f745a1f..f0ccb886d0d2 100644 --- a/tests/ui/lexer/error-stage.rs +++ b/tests/ui/lexer/error-stage.rs @@ -59,7 +59,7 @@ const _: () = sink! { // The invalid literals used to cause errors, but this was changed by #102944. // Except for `0b010.0f32`, because it's a lexer error. -#[cfg(FALSE)] +#[cfg(false)] fn configured_out() { "string"any_suffix; // OK 10u123; // OK diff --git a/tests/ui/link-native-libs/link-attr-validation-late.rs b/tests/ui/link-native-libs/link-attr-validation-late.rs index 34f720dd2d3c..4eeb8ba4884f 100644 --- a/tests/ui/link-native-libs/link-attr-validation-late.rs +++ b/tests/ui/link-native-libs/link-attr-validation-late.rs @@ -9,7 +9,7 @@ extern "C" {} #[link(name = "foo", name = "bar")] //~ ERROR multiple `name` arguments #[link(name = "...", kind = "dylib", kind = "bar")] //~ ERROR multiple `kind` arguments #[link(name = "...", modifiers = "+verbatim", modifiers = "bar")] //~ ERROR multiple `modifiers` arguments -#[link(name = "...", cfg(FALSE), cfg(FALSE))] //~ ERROR multiple `cfg` arguments +#[link(name = "...", cfg(false), cfg(false))] //~ ERROR multiple `cfg` arguments #[link(wasm_import_module = "foo", wasm_import_module = "bar")] //~ ERROR multiple `wasm_import_module` arguments extern "C" {} diff --git a/tests/ui/link-native-libs/link-attr-validation-late.stderr b/tests/ui/link-native-libs/link-attr-validation-late.stderr index 1ad5fbaf7de8..f3989c09360f 100644 --- a/tests/ui/link-native-libs/link-attr-validation-late.stderr +++ b/tests/ui/link-native-libs/link-attr-validation-late.stderr @@ -31,7 +31,7 @@ LL | #[link(name = "...", modifiers = "+verbatim", modifiers = "bar")] error: multiple `cfg` arguments in a single `#[link]` attribute --> $DIR/link-attr-validation-late.rs:12:34 | -LL | #[link(name = "...", cfg(FALSE), cfg(FALSE))] +LL | #[link(name = "...", cfg(false), cfg(false))] | ^^^^^^^^^^ error: multiple `wasm_import_module` arguments in a single `#[link]` attribute diff --git a/tests/ui/lint/unused/unused-attr-macro-rules.rs b/tests/ui/lint/unused/unused-attr-macro-rules.rs index c0fc280ab1a7..7a8a1bb1ae52 100644 --- a/tests/ui/lint/unused/unused-attr-macro-rules.rs +++ b/tests/ui/lint/unused/unused-attr-macro-rules.rs @@ -17,7 +17,7 @@ macro_rules! foo2 { () => {}; } -#[cfg(FALSE)] +#[cfg(false)] macro_rules! foo { () => {}; } diff --git a/tests/ui/macros/lint-trailing-macro-call.rs b/tests/ui/macros/lint-trailing-macro-call.rs index 66dce057d0f5..78b861f1df17 100644 --- a/tests/ui/macros/lint-trailing-macro-call.rs +++ b/tests/ui/macros/lint-trailing-macro-call.rs @@ -6,7 +6,7 @@ macro_rules! expand_it { () => { - #[cfg(FALSE)] 25; //~ WARN trailing semicolon in macro + #[cfg(false)] 25; //~ WARN trailing semicolon in macro //~| WARN this was previously } } diff --git a/tests/ui/macros/lint-trailing-macro-call.stderr b/tests/ui/macros/lint-trailing-macro-call.stderr index 13cecc3a31d2..223b85e112ed 100644 --- a/tests/ui/macros/lint-trailing-macro-call.stderr +++ b/tests/ui/macros/lint-trailing-macro-call.stderr @@ -1,7 +1,7 @@ warning: trailing semicolon in macro used in expression position --> $DIR/lint-trailing-macro-call.rs:9:25 | -LL | #[cfg(FALSE)] 25; +LL | #[cfg(false)] 25; | ^ ... LL | expand_it!() @@ -20,7 +20,7 @@ Future incompatibility report: Future breakage diagnostic: warning: trailing semicolon in macro used in expression position --> $DIR/lint-trailing-macro-call.rs:9:25 | -LL | #[cfg(FALSE)] 25; +LL | #[cfg(false)] 25; | ^ ... LL | expand_it!() diff --git a/tests/ui/macros/macro-attributes.rs b/tests/ui/macros/macro-attributes.rs index 832907907669..976d2cbcccdb 100644 --- a/tests/ui/macros/macro-attributes.rs +++ b/tests/ui/macros/macro-attributes.rs @@ -9,7 +9,7 @@ macro_rules! compiles_fine { // check that the attributes are recognised by requiring this // to be removed to avoid a compile error - #[cfg(FALSE)] + #[cfg(false)] static MISTYPED: () = "foo"; } } diff --git a/tests/ui/macros/macro-inner-attributes.rs b/tests/ui/macros/macro-inner-attributes.rs index a1eb7cd15c4c..1a832ca9b0c4 100644 --- a/tests/ui/macros/macro-inner-attributes.rs +++ b/tests/ui/macros/macro-inner-attributes.rs @@ -5,7 +5,7 @@ macro_rules! test { ($nm:ident, $i:item) => (mod $nm { #![$a] $i }); } test!(a, - #[cfg(FALSE)], + #[cfg(false)], pub fn bar() { }); test!(b, diff --git a/tests/ui/macros/macro-outer-attributes.rs b/tests/ui/macros/macro-outer-attributes.rs index 8c79683f49a9..5b41cf9fd29d 100644 --- a/tests/ui/macros/macro-outer-attributes.rs +++ b/tests/ui/macros/macro-outer-attributes.rs @@ -5,7 +5,7 @@ macro_rules! test { ($nm:ident, $i:item) => (mod $nm { #[$a] $i }); } test!(a, - #[cfg(FALSE)], + #[cfg(false)], pub fn bar() { }); test!(b, diff --git a/tests/ui/macros/macro-outer-attributes.stderr b/tests/ui/macros/macro-outer-attributes.stderr index a8809f3fcff6..a894c90f4c32 100644 --- a/tests/ui/macros/macro-outer-attributes.stderr +++ b/tests/ui/macros/macro-outer-attributes.stderr @@ -16,7 +16,7 @@ LL | $i:item) => (mod $nm { #[$a] $i }); } | ^^^^^ LL | LL | / test!(a, -LL | | #[cfg(FALSE)], +LL | | #[cfg(false)], LL | | pub fn bar() { }); | |_______________________- in this macro invocation = note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/macros/macro-with-attrs2.rs b/tests/ui/macros/macro-with-attrs2.rs index 37188e45ad3b..7d0bf9114253 100644 --- a/tests/ui/macros/macro-with-attrs2.rs +++ b/tests/ui/macros/macro-with-attrs2.rs @@ -1,6 +1,6 @@ //@ run-pass -#[cfg(FALSE)] +#[cfg(false)] macro_rules! foo { () => (1) } #[cfg(not(FALSE))] diff --git a/tests/ui/nested-cfg-attrs.rs b/tests/ui/nested-cfg-attrs.rs index 0af28fc3d8ec..941807a84310 100644 --- a/tests/ui/nested-cfg-attrs.rs +++ b/tests/ui/nested-cfg-attrs.rs @@ -1,4 +1,4 @@ -#[cfg_attr(all(), cfg_attr(all(), cfg(FALSE)))] +#[cfg_attr(all(), cfg_attr(all(), cfg(false)))] fn f() {} fn main() { f() } //~ ERROR cannot find function `f` in this scope diff --git a/tests/ui/or-patterns/fn-param-wrap-parens.fixed b/tests/ui/or-patterns/fn-param-wrap-parens.fixed index 7b0bbd04d978..fbf60069c7d4 100644 --- a/tests/ui/or-patterns/fn-param-wrap-parens.fixed +++ b/tests/ui/or-patterns/fn-param-wrap-parens.fixed @@ -9,5 +9,5 @@ fn main() {} enum E { A, B } use E::*; -#[cfg(FALSE)] +#[cfg(false)] fn fun1((A | B): E) {} //~ ERROR top-level or-patterns are not allowed diff --git a/tests/ui/or-patterns/fn-param-wrap-parens.rs b/tests/ui/or-patterns/fn-param-wrap-parens.rs index dadbb8a906a7..d796f998e97c 100644 --- a/tests/ui/or-patterns/fn-param-wrap-parens.rs +++ b/tests/ui/or-patterns/fn-param-wrap-parens.rs @@ -9,5 +9,5 @@ fn main() {} enum E { A, B } use E::*; -#[cfg(FALSE)] +#[cfg(false)] fn fun1(A | B: E) {} //~ ERROR top-level or-patterns are not allowed diff --git a/tests/ui/or-patterns/or-patterns-syntactic-pass.rs b/tests/ui/or-patterns/or-patterns-syntactic-pass.rs index 6a8d0a5adb49..6fd5840e801a 100644 --- a/tests/ui/or-patterns/or-patterns-syntactic-pass.rs +++ b/tests/ui/or-patterns/or-patterns-syntactic-pass.rs @@ -18,7 +18,7 @@ accept_pat!([p | q]); // Non-macro tests: -#[cfg(FALSE)] +#[cfg(false)] fn or_patterns() { // Top level of `let`: let (| A | B); diff --git a/tests/ui/or-patterns/remove-leading-vert.fixed b/tests/ui/or-patterns/remove-leading-vert.fixed index 3ec815c84684..136ca5765b7e 100644 --- a/tests/ui/or-patterns/remove-leading-vert.fixed +++ b/tests/ui/or-patterns/remove-leading-vert.fixed @@ -6,7 +6,7 @@ fn main() {} -#[cfg(FALSE)] +#[cfg(false)] fn leading() { fn fun1( A: E) {} //~ ERROR top-level or-patterns are not allowed fn fun2( A: E) {} //~ ERROR unexpected `||` before function parameter @@ -21,7 +21,7 @@ fn leading() { let NS { f: | A }: NS; //~ ERROR unexpected token `||` in pattern } -#[cfg(FALSE)] +#[cfg(false)] fn trailing() { let ( A ): E; //~ ERROR a trailing `|` is not allowed in an or-pattern let (a ,): (E,); //~ ERROR a trailing `|` is not allowed in an or-pattern diff --git a/tests/ui/or-patterns/remove-leading-vert.rs b/tests/ui/or-patterns/remove-leading-vert.rs index 2aeeb0e979f6..d9e9c9fe4d2f 100644 --- a/tests/ui/or-patterns/remove-leading-vert.rs +++ b/tests/ui/or-patterns/remove-leading-vert.rs @@ -6,7 +6,7 @@ fn main() {} -#[cfg(FALSE)] +#[cfg(false)] fn leading() { fn fun1( | A: E) {} //~ ERROR top-level or-patterns are not allowed fn fun2( || A: E) {} //~ ERROR unexpected `||` before function parameter @@ -21,7 +21,7 @@ fn leading() { let NS { f: || A }: NS; //~ ERROR unexpected token `||` in pattern } -#[cfg(FALSE)] +#[cfg(false)] fn trailing() { let ( A | ): E; //~ ERROR a trailing `|` is not allowed in an or-pattern let (a |,): (E,); //~ ERROR a trailing `|` is not allowed in an or-pattern diff --git a/tests/ui/parser/assoc/assoc-const-underscore-syntactic-pass.rs b/tests/ui/parser/assoc/assoc-const-underscore-syntactic-pass.rs index 6c0453791916..63c567b2d033 100644 --- a/tests/ui/parser/assoc/assoc-const-underscore-syntactic-pass.rs +++ b/tests/ui/parser/assoc/assoc-const-underscore-syntactic-pass.rs @@ -4,7 +4,7 @@ fn main() {} -#[cfg(FALSE)] +#[cfg(false)] const _: () = { pub trait A { const _: () = (); diff --git a/tests/ui/parser/assoc/assoc-static-syntactic-fail.rs b/tests/ui/parser/assoc/assoc-static-syntactic-fail.rs index 492f2ea16ef5..e875d733bd62 100644 --- a/tests/ui/parser/assoc/assoc-static-syntactic-fail.rs +++ b/tests/ui/parser/assoc/assoc-static-syntactic-fail.rs @@ -2,7 +2,7 @@ fn main() {} -#[cfg(FALSE)] +#[cfg(false)] impl S { static IA: u8 = 0; //~ ERROR associated `static` items are not allowed static IB: u8; //~ ERROR associated `static` items are not allowed @@ -12,7 +12,7 @@ impl S { //~^ ERROR a static item cannot be `default` } -#[cfg(FALSE)] +#[cfg(false)] trait T { static TA: u8 = 0; //~ ERROR associated `static` items are not allowed static TB: u8; //~ ERROR associated `static` items are not allowed @@ -22,7 +22,7 @@ trait T { //~^ ERROR a static item cannot be `default` } -#[cfg(FALSE)] +#[cfg(false)] impl T for S { static TA: u8 = 0; //~ ERROR associated `static` items are not allowed static TB: u8; //~ ERROR associated `static` items are not allowed diff --git a/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.rs b/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.rs index 26761a1d2544..1380974538a5 100644 --- a/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.rs +++ b/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.rs @@ -1,108 +1,108 @@ fn main() {} -#[cfg(FALSE)] fn e() { let _ = [#[attr]]; } +#[cfg(false)] fn e() { let _ = [#[attr]]; } //~^ ERROR expected expression, found `]` -#[cfg(FALSE)] fn e() { let _ = foo#[attr](); } +#[cfg(false)] fn e() { let _ = foo#[attr](); } //~^ ERROR expected one of -#[cfg(FALSE)] fn e() { let _ = foo(#![attr]); } +#[cfg(false)] fn e() { let _ = foo(#![attr]); } //~^ ERROR an inner attribute is not permitted in this context //~| ERROR an inner attribute is not permitted in this context //~| ERROR expected expression, found `)` -#[cfg(FALSE)] fn e() { let _ = x.foo(#![attr]); } +#[cfg(false)] fn e() { let _ = x.foo(#![attr]); } //~^ ERROR an inner attribute is not permitted in this context //~| ERROR expected expression, found `)` -#[cfg(FALSE)] fn e() { let _ = 0 + #![attr] 0; } +#[cfg(false)] fn e() { let _ = 0 + #![attr] 0; } //~^ ERROR an inner attribute is not permitted in this context -#[cfg(FALSE)] fn e() { let _ = !#![attr] 0; } +#[cfg(false)] fn e() { let _ = !#![attr] 0; } //~^ ERROR an inner attribute is not permitted in this context -#[cfg(FALSE)] fn e() { let _ = -#![attr] 0; } +#[cfg(false)] fn e() { let _ = -#![attr] 0; } //~^ ERROR an inner attribute is not permitted in this context -#[cfg(FALSE)] fn e() { let _ = x #![attr] as Y; } +#[cfg(false)] fn e() { let _ = x #![attr] as Y; } //~^ ERROR expected one of -#[cfg(FALSE)] fn e() { let _ = || #![attr] foo; } +#[cfg(false)] fn e() { let _ = || #![attr] foo; } //~^ ERROR an inner attribute is not permitted in this context -#[cfg(FALSE)] fn e() { let _ = move || #![attr] foo; } +#[cfg(false)] fn e() { let _ = move || #![attr] foo; } //~^ ERROR an inner attribute is not permitted in this context -#[cfg(FALSE)] fn e() { let _ = || #![attr] {foo}; } +#[cfg(false)] fn e() { let _ = || #![attr] {foo}; } //~^ ERROR an inner attribute is not permitted in this context -#[cfg(FALSE)] fn e() { let _ = move || #![attr] {foo}; } +#[cfg(false)] fn e() { let _ = move || #![attr] {foo}; } //~^ ERROR an inner attribute is not permitted in this context -#[cfg(FALSE)] fn e() { let _ = #[attr] ..#[attr] 0; } +#[cfg(false)] fn e() { let _ = #[attr] ..#[attr] 0; } //~^ ERROR attributes are not allowed on range expressions starting with `..` -#[cfg(FALSE)] fn e() { let _ = #[attr] ..; } +#[cfg(false)] fn e() { let _ = #[attr] ..; } //~^ ERROR attributes are not allowed on range expressions starting with `..` -#[cfg(FALSE)] fn e() { let _ = #[attr] &#![attr] 0; } +#[cfg(false)] fn e() { let _ = #[attr] &#![attr] 0; } //~^ ERROR an inner attribute is not permitted in this context -#[cfg(FALSE)] fn e() { let _ = #[attr] &mut #![attr] 0; } +#[cfg(false)] fn e() { let _ = #[attr] &mut #![attr] 0; } //~^ ERROR an inner attribute is not permitted in this context -#[cfg(FALSE)] fn e() { let _ = if 0 #[attr] {}; } +#[cfg(false)] fn e() { let _ = if 0 #[attr] {}; } //~^ ERROR outer attributes are not allowed on `if` -#[cfg(FALSE)] fn e() { let _ = if 0 {#![attr]}; } +#[cfg(false)] fn e() { let _ = if 0 {#![attr]}; } //~^ ERROR an inner attribute is not permitted in this context -#[cfg(FALSE)] fn e() { let _ = if 0 {} #[attr] else {}; } +#[cfg(false)] fn e() { let _ = if 0 {} #[attr] else {}; } //~^ ERROR expected one of -#[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] {}; } +#[cfg(false)] fn e() { let _ = if 0 {} else #[attr] {}; } //~^ ERROR outer attributes are not allowed on `if` -#[cfg(FALSE)] fn e() { let _ = if 0 {} else {#![attr]}; } +#[cfg(false)] fn e() { let _ = if 0 {} else {#![attr]}; } //~^ ERROR an inner attribute is not permitted in this context -#[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; } +#[cfg(false)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; } //~^ ERROR outer attributes are not allowed on `if` -#[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; } +#[cfg(false)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; } //~^ ERROR outer attributes are not allowed on `if` -#[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 {#![attr]}; } +#[cfg(false)] fn e() { let _ = if 0 {} else if 0 {#![attr]}; } //~^ ERROR an inner attribute is not permitted in this context -#[cfg(FALSE)] fn e() { let _ = if let _ = 0 #[attr] {}; } +#[cfg(false)] fn e() { let _ = if let _ = 0 #[attr] {}; } //~^ ERROR outer attributes are not allowed on `if` -#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {#![attr]}; } +#[cfg(false)] fn e() { let _ = if let _ = 0 {#![attr]}; } //~^ ERROR an inner attribute is not permitted in this context -#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} #[attr] else {}; } +#[cfg(false)] fn e() { let _ = if let _ = 0 {} #[attr] else {}; } //~^ ERROR expected one of -#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] {}; } +#[cfg(false)] fn e() { let _ = if let _ = 0 {} else #[attr] {}; } //~^ ERROR outer attributes are not allowed on `if` -#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else {#![attr]}; } +#[cfg(false)] fn e() { let _ = if let _ = 0 {} else {#![attr]}; } //~^ ERROR an inner attribute is not permitted in this context -#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}; } +#[cfg(false)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}; } //~^ ERROR outer attributes are not allowed on `if` -#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {}; } +#[cfg(false)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {}; } //~^ ERROR outer attributes are not allowed on `if` -#[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {#![attr]}; } +#[cfg(false)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {#![attr]}; } //~^ ERROR an inner attribute is not permitted in this context -#[cfg(FALSE)] fn s() { #[attr] #![attr] let _ = 0; } +#[cfg(false)] fn s() { #[attr] #![attr] let _ = 0; } //~^ ERROR an inner attribute is not permitted following an outer attribute -#[cfg(FALSE)] fn s() { #[attr] #![attr] 0; } +#[cfg(false)] fn s() { #[attr] #![attr] 0; } //~^ ERROR an inner attribute is not permitted following an outer attribute -#[cfg(FALSE)] fn s() { #[attr] #![attr] foo!(); } +#[cfg(false)] fn s() { #[attr] #![attr] foo!(); } //~^ ERROR an inner attribute is not permitted following an outer attribute -#[cfg(FALSE)] fn s() { #[attr] #![attr] foo![]; } +#[cfg(false)] fn s() { #[attr] #![attr] foo![]; } //~^ ERROR an inner attribute is not permitted following an outer attribute -#[cfg(FALSE)] fn s() { #[attr] #![attr] foo!{}; } +#[cfg(false)] fn s() { #[attr] #![attr] foo!{}; } //~^ ERROR an inner attribute is not permitted following an outer attribute // FIXME: Allow attributes in pattern constexprs? // note: requires parens in patterns to allow disambiguation -#[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } } +#[cfg(false)] fn e() { match 0 { 0..=#[attr] 10 => () } } //~^ ERROR inclusive range with no end //~| ERROR expected one of `=>`, `if`, or `|`, found `#` -#[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } } +#[cfg(false)] fn e() { match 0 { 0..=#[attr] -10 => () } } //~^ ERROR inclusive range with no end //~| ERROR expected one of `=>`, `if`, or `|`, found `#` -#[cfg(FALSE)] fn e() { match 0 { 0..=-#[attr] 10 => () } } +#[cfg(false)] fn e() { match 0 { 0..=-#[attr] 10 => () } } //~^ ERROR unexpected token: `#` -#[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } } +#[cfg(false)] fn e() { match 0 { 0..=#[attr] FOO => () } } //~^ ERROR inclusive range with no end //~| ERROR expected one of `=>`, `if`, or `|`, found `#` -#[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); } +#[cfg(false)] fn e() { let _ = x.#![attr]foo(); } //~^ ERROR unexpected token: `#` //~| ERROR expected one of `.` -#[cfg(FALSE)] fn e() { let _ = x.#[attr]foo(); } +#[cfg(false)] fn e() { let _ = x.#[attr]foo(); } //~^ ERROR unexpected token: `#` //~| ERROR expected one of `.` // make sure we don't catch this bug again... -#[cfg(FALSE)] fn e() { { fn foo() { #[attr]; } } } +#[cfg(false)] fn e() { { fn foo() { #[attr]; } } } //~^ ERROR expected statement after outer attribute -#[cfg(FALSE)] fn e() { { fn foo() { #[attr] } } } +#[cfg(false)] fn e() { { fn foo() { #[attr] } } } //~^ ERROR expected statement after outer attribute diff --git a/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr b/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr index bd860841b806..5d94a8dcbdb8 100644 --- a/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr +++ b/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr @@ -1,19 +1,19 @@ error: expected expression, found `]` --> $DIR/attr-stmt-expr-attr-bad.rs:3:40 | -LL | #[cfg(FALSE)] fn e() { let _ = [#[attr]]; } +LL | #[cfg(false)] fn e() { let _ = [#[attr]]; } | ^ expected expression error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `#` --> $DIR/attr-stmt-expr-attr-bad.rs:5:35 | -LL | #[cfg(FALSE)] fn e() { let _ = foo#[attr](); } +LL | #[cfg(false)] fn e() { let _ = foo#[attr](); } | ^ expected one of 8 possible tokens error: an inner attribute is not permitted in this context --> $DIR/attr-stmt-expr-attr-bad.rs:7:36 | -LL | #[cfg(FALSE)] fn e() { let _ = foo(#![attr]); } +LL | #[cfg(false)] fn e() { let _ = foo(#![attr]); } | ^^^^^^^^ | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files @@ -22,7 +22,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = foo(#![attr]); } error: an inner attribute is not permitted in this context --> $DIR/attr-stmt-expr-attr-bad.rs:7:36 | -LL | #[cfg(FALSE)] fn e() { let _ = foo(#![attr]); } +LL | #[cfg(false)] fn e() { let _ = foo(#![attr]); } | ^^^^^^^^ | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files @@ -32,13 +32,13 @@ LL | #[cfg(FALSE)] fn e() { let _ = foo(#![attr]); } error: expected expression, found `)` --> $DIR/attr-stmt-expr-attr-bad.rs:7:44 | -LL | #[cfg(FALSE)] fn e() { let _ = foo(#![attr]); } +LL | #[cfg(false)] fn e() { let _ = foo(#![attr]); } | ^ expected expression error: an inner attribute is not permitted in this context --> $DIR/attr-stmt-expr-attr-bad.rs:11:38 | -LL | #[cfg(FALSE)] fn e() { let _ = x.foo(#![attr]); } +LL | #[cfg(false)] fn e() { let _ = x.foo(#![attr]); } | ^^^^^^^^ | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files @@ -47,13 +47,13 @@ LL | #[cfg(FALSE)] fn e() { let _ = x.foo(#![attr]); } error: expected expression, found `)` --> $DIR/attr-stmt-expr-attr-bad.rs:11:46 | -LL | #[cfg(FALSE)] fn e() { let _ = x.foo(#![attr]); } +LL | #[cfg(false)] fn e() { let _ = x.foo(#![attr]); } | ^ expected expression error: an inner attribute is not permitted in this context --> $DIR/attr-stmt-expr-attr-bad.rs:14:36 | -LL | #[cfg(FALSE)] fn e() { let _ = 0 + #![attr] 0; } +LL | #[cfg(false)] fn e() { let _ = 0 + #![attr] 0; } | ^^^^^^^^ | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files @@ -62,7 +62,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = 0 + #![attr] 0; } error: an inner attribute is not permitted in this context --> $DIR/attr-stmt-expr-attr-bad.rs:16:33 | -LL | #[cfg(FALSE)] fn e() { let _ = !#![attr] 0; } +LL | #[cfg(false)] fn e() { let _ = !#![attr] 0; } | ^^^^^^^^ | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files @@ -71,7 +71,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = !#![attr] 0; } error: an inner attribute is not permitted in this context --> $DIR/attr-stmt-expr-attr-bad.rs:18:33 | -LL | #[cfg(FALSE)] fn e() { let _ = -#![attr] 0; } +LL | #[cfg(false)] fn e() { let _ = -#![attr] 0; } | ^^^^^^^^ | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files @@ -80,13 +80,13 @@ LL | #[cfg(FALSE)] fn e() { let _ = -#![attr] 0; } error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `#` --> $DIR/attr-stmt-expr-attr-bad.rs:20:34 | -LL | #[cfg(FALSE)] fn e() { let _ = x #![attr] as Y; } +LL | #[cfg(false)] fn e() { let _ = x #![attr] as Y; } | ^ expected one of 8 possible tokens error: an inner attribute is not permitted in this context --> $DIR/attr-stmt-expr-attr-bad.rs:22:35 | -LL | #[cfg(FALSE)] fn e() { let _ = || #![attr] foo; } +LL | #[cfg(false)] fn e() { let _ = || #![attr] foo; } | ^^^^^^^^ | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files @@ -95,7 +95,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = || #![attr] foo; } error: an inner attribute is not permitted in this context --> $DIR/attr-stmt-expr-attr-bad.rs:24:40 | -LL | #[cfg(FALSE)] fn e() { let _ = move || #![attr] foo; } +LL | #[cfg(false)] fn e() { let _ = move || #![attr] foo; } | ^^^^^^^^ | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files @@ -104,7 +104,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = move || #![attr] foo; } error: an inner attribute is not permitted in this context --> $DIR/attr-stmt-expr-attr-bad.rs:26:35 | -LL | #[cfg(FALSE)] fn e() { let _ = || #![attr] {foo}; } +LL | #[cfg(false)] fn e() { let _ = || #![attr] {foo}; } | ^^^^^^^^ | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files @@ -113,7 +113,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = || #![attr] {foo}; } error: an inner attribute is not permitted in this context --> $DIR/attr-stmt-expr-attr-bad.rs:28:40 | -LL | #[cfg(FALSE)] fn e() { let _ = move || #![attr] {foo}; } +LL | #[cfg(false)] fn e() { let _ = move || #![attr] {foo}; } | ^^^^^^^^ | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files @@ -122,19 +122,19 @@ LL | #[cfg(FALSE)] fn e() { let _ = move || #![attr] {foo}; } error: attributes are not allowed on range expressions starting with `..` --> $DIR/attr-stmt-expr-attr-bad.rs:30:40 | -LL | #[cfg(FALSE)] fn e() { let _ = #[attr] ..#[attr] 0; } +LL | #[cfg(false)] fn e() { let _ = #[attr] ..#[attr] 0; } | ^^ error: attributes are not allowed on range expressions starting with `..` --> $DIR/attr-stmt-expr-attr-bad.rs:32:40 | -LL | #[cfg(FALSE)] fn e() { let _ = #[attr] ..; } +LL | #[cfg(false)] fn e() { let _ = #[attr] ..; } | ^^ error: an inner attribute is not permitted in this context --> $DIR/attr-stmt-expr-attr-bad.rs:34:41 | -LL | #[cfg(FALSE)] fn e() { let _ = #[attr] &#![attr] 0; } +LL | #[cfg(false)] fn e() { let _ = #[attr] &#![attr] 0; } | ^^^^^^^^ | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files @@ -143,7 +143,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = #[attr] &#![attr] 0; } error: an inner attribute is not permitted in this context --> $DIR/attr-stmt-expr-attr-bad.rs:36:45 | -LL | #[cfg(FALSE)] fn e() { let _ = #[attr] &mut #![attr] 0; } +LL | #[cfg(false)] fn e() { let _ = #[attr] &mut #![attr] 0; } | ^^^^^^^^ | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files @@ -152,21 +152,21 @@ LL | #[cfg(FALSE)] fn e() { let _ = #[attr] &mut #![attr] 0; } error: outer attributes are not allowed on `if` and `else` branches --> $DIR/attr-stmt-expr-attr-bad.rs:38:37 | -LL | #[cfg(FALSE)] fn e() { let _ = if 0 #[attr] {}; } +LL | #[cfg(false)] fn e() { let _ = if 0 #[attr] {}; } | -- ^^^^^^^ -- the attributes are attached to this branch | | | the branch belongs to this `if` | help: remove the attributes | -LL - #[cfg(FALSE)] fn e() { let _ = if 0 #[attr] {}; } -LL + #[cfg(FALSE)] fn e() { let _ = if 0 {}; } +LL - #[cfg(false)] fn e() { let _ = if 0 #[attr] {}; } +LL + #[cfg(false)] fn e() { let _ = if 0 {}; } | error: an inner attribute is not permitted in this context --> $DIR/attr-stmt-expr-attr-bad.rs:40:38 | -LL | #[cfg(FALSE)] fn e() { let _ = if 0 {#![attr]}; } +LL | #[cfg(false)] fn e() { let _ = if 0 {#![attr]}; } | ^^^^^^^^ | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files @@ -175,27 +175,27 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 {#![attr]}; } error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#` --> $DIR/attr-stmt-expr-attr-bad.rs:42:40 | -LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} #[attr] else {}; } +LL | #[cfg(false)] fn e() { let _ = if 0 {} #[attr] else {}; } | ^ expected one of `.`, `;`, `?`, `else`, or an operator error: outer attributes are not allowed on `if` and `else` branches --> $DIR/attr-stmt-expr-attr-bad.rs:44:45 | -LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] {}; } +LL | #[cfg(false)] fn e() { let _ = if 0 {} else #[attr] {}; } | ---- ^^^^^^^ -- the attributes are attached to this branch | | | the branch belongs to this `else` | help: remove the attributes | -LL - #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] {}; } -LL + #[cfg(FALSE)] fn e() { let _ = if 0 {} else {}; } +LL - #[cfg(false)] fn e() { let _ = if 0 {} else #[attr] {}; } +LL + #[cfg(false)] fn e() { let _ = if 0 {} else {}; } | error: an inner attribute is not permitted in this context --> $DIR/attr-stmt-expr-attr-bad.rs:46:46 | -LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else {#![attr]}; } +LL | #[cfg(false)] fn e() { let _ = if 0 {} else {#![attr]}; } | ^^^^^^^^ | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files @@ -204,35 +204,35 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else {#![attr]}; } error: outer attributes are not allowed on `if` and `else` branches --> $DIR/attr-stmt-expr-attr-bad.rs:48:45 | -LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; } +LL | #[cfg(false)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; } | ---- ^^^^^^^ ------- the attributes are attached to this branch | | | the branch belongs to this `else` | help: remove the attributes | -LL - #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; } -LL + #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 {}; } +LL - #[cfg(false)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; } +LL + #[cfg(false)] fn e() { let _ = if 0 {} else if 0 {}; } | error: outer attributes are not allowed on `if` and `else` branches --> $DIR/attr-stmt-expr-attr-bad.rs:50:50 | -LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; } +LL | #[cfg(false)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; } | -- ^^^^^^^ -- the attributes are attached to this branch | | | the branch belongs to this `if` | help: remove the attributes | -LL - #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; } -LL + #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 {}; } +LL - #[cfg(false)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; } +LL + #[cfg(false)] fn e() { let _ = if 0 {} else if 0 {}; } | error: an inner attribute is not permitted in this context --> $DIR/attr-stmt-expr-attr-bad.rs:52:51 | -LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 {#![attr]}; } +LL | #[cfg(false)] fn e() { let _ = if 0 {} else if 0 {#![attr]}; } | ^^^^^^^^ | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files @@ -241,21 +241,21 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 {#![attr]}; } error: outer attributes are not allowed on `if` and `else` branches --> $DIR/attr-stmt-expr-attr-bad.rs:54:45 | -LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 #[attr] {}; } +LL | #[cfg(false)] fn e() { let _ = if let _ = 0 #[attr] {}; } | -- ^^^^^^^ -- the attributes are attached to this branch | | | the branch belongs to this `if` | help: remove the attributes | -LL - #[cfg(FALSE)] fn e() { let _ = if let _ = 0 #[attr] {}; } -LL + #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {}; } +LL - #[cfg(false)] fn e() { let _ = if let _ = 0 #[attr] {}; } +LL + #[cfg(false)] fn e() { let _ = if let _ = 0 {}; } | error: an inner attribute is not permitted in this context --> $DIR/attr-stmt-expr-attr-bad.rs:56:46 | -LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {#![attr]}; } +LL | #[cfg(false)] fn e() { let _ = if let _ = 0 {#![attr]}; } | ^^^^^^^^ | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files @@ -264,27 +264,27 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {#![attr]}; } error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#` --> $DIR/attr-stmt-expr-attr-bad.rs:58:48 | -LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} #[attr] else {}; } +LL | #[cfg(false)] fn e() { let _ = if let _ = 0 {} #[attr] else {}; } | ^ expected one of `.`, `;`, `?`, `else`, or an operator error: outer attributes are not allowed on `if` and `else` branches --> $DIR/attr-stmt-expr-attr-bad.rs:60:53 | -LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] {}; } +LL | #[cfg(false)] fn e() { let _ = if let _ = 0 {} else #[attr] {}; } | ---- ^^^^^^^ -- the attributes are attached to this branch | | | the branch belongs to this `else` | help: remove the attributes | -LL - #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] {}; } -LL + #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else {}; } +LL - #[cfg(false)] fn e() { let _ = if let _ = 0 {} else #[attr] {}; } +LL + #[cfg(false)] fn e() { let _ = if let _ = 0 {} else {}; } | error: an inner attribute is not permitted in this context --> $DIR/attr-stmt-expr-attr-bad.rs:62:54 | -LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else {#![attr]}; } +LL | #[cfg(false)] fn e() { let _ = if let _ = 0 {} else {#![attr]}; } | ^^^^^^^^ | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files @@ -293,35 +293,35 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else {#![attr]}; } error: outer attributes are not allowed on `if` and `else` branches --> $DIR/attr-stmt-expr-attr-bad.rs:64:53 | -LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}; } +LL | #[cfg(false)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}; } | ---- ^^^^^^^ --------------- the attributes are attached to this branch | | | the branch belongs to this `else` | help: remove the attributes | -LL - #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}; } -LL + #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {}; } +LL - #[cfg(false)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}; } +LL + #[cfg(false)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {}; } | error: outer attributes are not allowed on `if` and `else` branches --> $DIR/attr-stmt-expr-attr-bad.rs:66:66 | -LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {}; } +LL | #[cfg(false)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {}; } | -- ^^^^^^^ -- the attributes are attached to this branch | | | the branch belongs to this `if` | help: remove the attributes | -LL - #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {}; } -LL + #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {}; } +LL - #[cfg(false)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {}; } +LL + #[cfg(false)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {}; } | error: an inner attribute is not permitted in this context --> $DIR/attr-stmt-expr-attr-bad.rs:68:67 | -LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {#![attr]}; } +LL | #[cfg(false)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {#![attr]}; } | ^^^^^^^^ | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files @@ -330,7 +330,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {#![attr]} error: an inner attribute is not permitted following an outer attribute --> $DIR/attr-stmt-expr-attr-bad.rs:71:32 | -LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] let _ = 0; } +LL | #[cfg(false)] fn s() { #[attr] #![attr] let _ = 0; } | ------- ^^^^^^^^ not permitted following an outer attribute | | | previous outer attribute @@ -341,7 +341,7 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] let _ = 0; } error: an inner attribute is not permitted following an outer attribute --> $DIR/attr-stmt-expr-attr-bad.rs:73:32 | -LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] 0; } +LL | #[cfg(false)] fn s() { #[attr] #![attr] 0; } | ------- ^^^^^^^^ not permitted following an outer attribute | | | previous outer attribute @@ -352,7 +352,7 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] 0; } error: an inner attribute is not permitted following an outer attribute --> $DIR/attr-stmt-expr-attr-bad.rs:75:32 | -LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!(); } +LL | #[cfg(false)] fn s() { #[attr] #![attr] foo!(); } | ------- ^^^^^^^^ ------- the inner attribute doesn't annotate this item macro invocation | | | | | not permitted following an outer attribute @@ -363,7 +363,7 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!(); } error: an inner attribute is not permitted following an outer attribute --> $DIR/attr-stmt-expr-attr-bad.rs:77:32 | -LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo![]; } +LL | #[cfg(false)] fn s() { #[attr] #![attr] foo![]; } | ------- ^^^^^^^^ ------- the inner attribute doesn't annotate this item macro invocation | | | | | not permitted following an outer attribute @@ -374,7 +374,7 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo![]; } error: an inner attribute is not permitted following an outer attribute --> $DIR/attr-stmt-expr-attr-bad.rs:79:32 | -LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!{}; } +LL | #[cfg(false)] fn s() { #[attr] #![attr] foo!{}; } | ------- ^^^^^^^^ ------ the inner attribute doesn't annotate this item macro invocation | | | | | not permitted following an outer attribute @@ -385,100 +385,100 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!{}; } error[E0586]: inclusive range with no end --> $DIR/attr-stmt-expr-attr-bad.rs:85:35 | -LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } } +LL | #[cfg(false)] fn e() { match 0 { 0..=#[attr] 10 => () } } | ^^^ | = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) help: use `..` instead | -LL - #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } } -LL + #[cfg(FALSE)] fn e() { match 0 { 0..#[attr] 10 => () } } +LL - #[cfg(false)] fn e() { match 0 { 0..=#[attr] 10 => () } } +LL + #[cfg(false)] fn e() { match 0 { 0..#[attr] 10 => () } } | error: expected one of `=>`, `if`, or `|`, found `#` --> $DIR/attr-stmt-expr-attr-bad.rs:85:38 | -LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } } +LL | #[cfg(false)] fn e() { match 0 { 0..=#[attr] 10 => () } } | ^ expected one of `=>`, `if`, or `|` error[E0586]: inclusive range with no end --> $DIR/attr-stmt-expr-attr-bad.rs:88:35 | -LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } } +LL | #[cfg(false)] fn e() { match 0 { 0..=#[attr] -10 => () } } | ^^^ | = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) help: use `..` instead | -LL - #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } } -LL + #[cfg(FALSE)] fn e() { match 0 { 0..#[attr] -10 => () } } +LL - #[cfg(false)] fn e() { match 0 { 0..=#[attr] -10 => () } } +LL + #[cfg(false)] fn e() { match 0 { 0..#[attr] -10 => () } } | error: expected one of `=>`, `if`, or `|`, found `#` --> $DIR/attr-stmt-expr-attr-bad.rs:88:38 | -LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } } +LL | #[cfg(false)] fn e() { match 0 { 0..=#[attr] -10 => () } } | ^ expected one of `=>`, `if`, or `|` error: unexpected token: `#` --> $DIR/attr-stmt-expr-attr-bad.rs:91:39 | -LL | #[cfg(FALSE)] fn e() { match 0 { 0..=-#[attr] 10 => () } } +LL | #[cfg(false)] fn e() { match 0 { 0..=-#[attr] 10 => () } } | ^ error[E0586]: inclusive range with no end --> $DIR/attr-stmt-expr-attr-bad.rs:93:35 | -LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } } +LL | #[cfg(false)] fn e() { match 0 { 0..=#[attr] FOO => () } } | ^^^ | = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) help: use `..` instead | -LL - #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } } -LL + #[cfg(FALSE)] fn e() { match 0 { 0..#[attr] FOO => () } } +LL - #[cfg(false)] fn e() { match 0 { 0..=#[attr] FOO => () } } +LL + #[cfg(false)] fn e() { match 0 { 0..#[attr] FOO => () } } | error: expected one of `=>`, `if`, or `|`, found `#` --> $DIR/attr-stmt-expr-attr-bad.rs:93:38 | -LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } } +LL | #[cfg(false)] fn e() { match 0 { 0..=#[attr] FOO => () } } | ^ expected one of `=>`, `if`, or `|` error: unexpected token: `#` --> $DIR/attr-stmt-expr-attr-bad.rs:97:34 | -LL | #[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); } +LL | #[cfg(false)] fn e() { let _ = x.#![attr]foo(); } | ^ error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#` --> $DIR/attr-stmt-expr-attr-bad.rs:97:34 | -LL | #[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); } +LL | #[cfg(false)] fn e() { let _ = x.#![attr]foo(); } | ^ expected one of `.`, `;`, `?`, `else`, or an operator error: unexpected token: `#` --> $DIR/attr-stmt-expr-attr-bad.rs:100:34 | -LL | #[cfg(FALSE)] fn e() { let _ = x.#[attr]foo(); } +LL | #[cfg(false)] fn e() { let _ = x.#[attr]foo(); } | ^ error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#` --> $DIR/attr-stmt-expr-attr-bad.rs:100:34 | -LL | #[cfg(FALSE)] fn e() { let _ = x.#[attr]foo(); } +LL | #[cfg(false)] fn e() { let _ = x.#[attr]foo(); } | ^ expected one of `.`, `;`, `?`, `else`, or an operator error: expected statement after outer attribute --> $DIR/attr-stmt-expr-attr-bad.rs:105:37 | -LL | #[cfg(FALSE)] fn e() { { fn foo() { #[attr]; } } } +LL | #[cfg(false)] fn e() { { fn foo() { #[attr]; } } } | ^^^^^^^ error: expected statement after outer attribute --> $DIR/attr-stmt-expr-attr-bad.rs:107:37 | -LL | #[cfg(FALSE)] fn e() { { fn foo() { #[attr] } } } +LL | #[cfg(false)] fn e() { { fn foo() { #[attr] } } } | ^^^^^^^ error: aborting due to 53 previous errors diff --git a/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.rs b/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.rs index 33671df94928..371f19d48726 100644 --- a/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.rs +++ b/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.rs @@ -1,7 +1,7 @@ #![feature(stmt_expr_attributes)] fn foo() -> String { - #[cfg(FALSE)] + #[cfg(false)] [1, 2, 3].iter().map(|c| c.to_string()).collect::() //~ ERROR expected `;`, found `#` #[cfg(not(FALSE))] String::new() diff --git a/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.stderr b/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.stderr index 6266718162f8..3a97a14b3c30 100644 --- a/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.stderr +++ b/tests/ui/parser/attribute/multiple-tail-expr-behind-cfg.stderr @@ -1,7 +1,7 @@ error: expected `;`, found `#` --> $DIR/multiple-tail-expr-behind-cfg.rs:5:64 | -LL | #[cfg(FALSE)] +LL | #[cfg(false)] | ------------- only `;` terminated statements or tail expressions are allowed after this attribute LL | [1, 2, 3].iter().map(|c| c.to_string()).collect::() | ^ expected `;` here @@ -18,7 +18,7 @@ LL | { [1, 2, 3].iter().map(|c| c.to_string()).collect::() } | + + help: it seems like you are trying to provide different expressions depending on `cfg`, consider using `if cfg!(..)` | -LL ~ if cfg!(FALSE) { +LL ~ if cfg!(false) { LL ~ [1, 2, 3].iter().map(|c| c.to_string()).collect::() LL ~ } else if cfg!(not(FALSE)) { LL ~ String::new() diff --git a/tests/ui/parser/attribute/properly-recover-from-trailing-outer-attribute-in-body-2.rs b/tests/ui/parser/attribute/properly-recover-from-trailing-outer-attribute-in-body-2.rs index e2a62922bcc5..1cd3f13d7b67 100644 --- a/tests/ui/parser/attribute/properly-recover-from-trailing-outer-attribute-in-body-2.rs +++ b/tests/ui/parser/attribute/properly-recover-from-trailing-outer-attribute-in-body-2.rs @@ -5,7 +5,7 @@ macro_rules! the_macro { #[cfg()] $foo //~ ERROR expected `;`, found `#` - #[cfg(FALSE)] + #[cfg(false)] $bar }; } diff --git a/tests/ui/parser/attribute/properly-recover-from-trailing-outer-attribute-in-body-2.stderr b/tests/ui/parser/attribute/properly-recover-from-trailing-outer-attribute-in-body-2.stderr index fa4409f73fa5..41e7b5ab759d 100644 --- a/tests/ui/parser/attribute/properly-recover-from-trailing-outer-attribute-in-body-2.stderr +++ b/tests/ui/parser/attribute/properly-recover-from-trailing-outer-attribute-in-body-2.stderr @@ -6,7 +6,7 @@ LL | #[cfg()] LL | $foo | ^ expected `;` here LL | -LL | #[cfg(FALSE)] +LL | #[cfg(false)] | - unexpected token ... LL | the_macro!( (); (); ); diff --git a/tests/ui/parser/constraints-before-generic-args-syntactic-pass.rs b/tests/ui/parser/constraints-before-generic-args-syntactic-pass.rs index ed3ffed2f802..acc58a47fbcf 100644 --- a/tests/ui/parser/constraints-before-generic-args-syntactic-pass.rs +++ b/tests/ui/parser/constraints-before-generic-args-syntactic-pass.rs @@ -1,6 +1,6 @@ //@ check-pass -#[cfg(FALSE)] +#[cfg(false)] fn syntax() { foo::(); foo::(); diff --git a/tests/ui/parser/default-on-wrong-item-kind.rs b/tests/ui/parser/default-on-wrong-item-kind.rs index 98a95cfa35a9..da990a4b4212 100644 --- a/tests/ui/parser/default-on-wrong-item-kind.rs +++ b/tests/ui/parser/default-on-wrong-item-kind.rs @@ -4,7 +4,7 @@ fn main() {} -#[cfg(FALSE)] +#[cfg(false)] mod free_items { default extern crate foo; //~ ERROR an extern crate cannot be `default` default use foo; //~ ERROR a `use` import cannot be `default` @@ -28,7 +28,7 @@ mod free_items { default macro_rules! foo {} //~ ERROR a macro definition cannot be `default` } -#[cfg(FALSE)] +#[cfg(false)] extern "C" { default extern crate foo; //~ ERROR an extern crate cannot be `default` //~^ ERROR extern crate is not supported in `extern` blocks @@ -65,7 +65,7 @@ extern "C" { //~^ ERROR macro definition is not supported in `extern` blocks } -#[cfg(FALSE)] +#[cfg(false)] impl S { default extern crate foo; //~ ERROR an extern crate cannot be `default` //~^ ERROR extern crate is not supported in `trait`s or `impl`s @@ -102,7 +102,7 @@ impl S { //~^ ERROR macro definition is not supported in `trait`s or `impl`s } -#[cfg(FALSE)] +#[cfg(false)] trait T { default extern crate foo; //~ ERROR an extern crate cannot be `default` //~^ ERROR extern crate is not supported in `trait`s or `impl`s diff --git a/tests/ui/parser/extern-abi-syntactic.rs b/tests/ui/parser/extern-abi-syntactic.rs index d3e2ba0e2d3f..28565a3f4bef 100644 --- a/tests/ui/parser/extern-abi-syntactic.rs +++ b/tests/ui/parser/extern-abi-syntactic.rs @@ -5,13 +5,13 @@ fn main() {} -#[cfg(FALSE)] +#[cfg(false)] extern "some_abi_that_we_are_sure_does_not_exist_semantically" fn foo() {} -#[cfg(FALSE)] +#[cfg(false)] extern "some_abi_that_we_are_sure_does_not_exist_semantically" { fn foo(); } -#[cfg(FALSE)] +#[cfg(false)] type T = extern "some_abi_that_we_are_sure_does_not_exist_semantically" fn(); diff --git a/tests/ui/parser/extern-crate-async.rs b/tests/ui/parser/extern-crate-async.rs index 7c7769075b65..529e0f1ab5cb 100644 --- a/tests/ui/parser/extern-crate-async.rs +++ b/tests/ui/parser/extern-crate-async.rs @@ -5,8 +5,8 @@ fn main() {} -#[cfg(FALSE)] +#[cfg(false)] extern crate async; -#[cfg(FALSE)] +#[cfg(false)] extern crate async as something_else; diff --git a/tests/ui/parser/fn-body-optional-syntactic-pass.rs b/tests/ui/parser/fn-body-optional-syntactic-pass.rs index 140471dfc774..762247e63e99 100644 --- a/tests/ui/parser/fn-body-optional-syntactic-pass.rs +++ b/tests/ui/parser/fn-body-optional-syntactic-pass.rs @@ -4,7 +4,7 @@ fn main() {} -#[cfg(FALSE)] +#[cfg(false)] fn syntax() { fn f(); fn f() {} diff --git a/tests/ui/parser/fn-header-syntactic-pass.rs b/tests/ui/parser/fn-header-syntactic-pass.rs index 065ded31b073..1e15886e5645 100644 --- a/tests/ui/parser/fn-header-syntactic-pass.rs +++ b/tests/ui/parser/fn-header-syntactic-pass.rs @@ -5,7 +5,7 @@ fn main() {} -#[cfg(FALSE)] +#[cfg(false)] fn syntax() { async fn f(); unsafe fn f(); diff --git a/tests/ui/parser/foreign-const-syntactic-fail.rs b/tests/ui/parser/foreign-const-syntactic-fail.rs index a6e77f846638..fc3cd0b3430d 100644 --- a/tests/ui/parser/foreign-const-syntactic-fail.rs +++ b/tests/ui/parser/foreign-const-syntactic-fail.rs @@ -2,7 +2,7 @@ fn main() {} -#[cfg(FALSE)] +#[cfg(false)] extern "C" { const A: isize; //~ ERROR extern items cannot be `const` const B: isize = 42; //~ ERROR extern items cannot be `const` diff --git a/tests/ui/parser/foreign-static-syntactic-pass.rs b/tests/ui/parser/foreign-static-syntactic-pass.rs index a76b9bab4911..d7c21c672ab6 100644 --- a/tests/ui/parser/foreign-static-syntactic-pass.rs +++ b/tests/ui/parser/foreign-static-syntactic-pass.rs @@ -4,7 +4,7 @@ fn main() {} -#[cfg(FALSE)] +#[cfg(false)] extern "C" { static X: u8; static mut Y: u8; diff --git a/tests/ui/parser/foreign-ty-syntactic-pass.rs b/tests/ui/parser/foreign-ty-syntactic-pass.rs index 50bb68cd83be..337276852010 100644 --- a/tests/ui/parser/foreign-ty-syntactic-pass.rs +++ b/tests/ui/parser/foreign-ty-syntactic-pass.rs @@ -2,7 +2,7 @@ fn main() {} -#[cfg(FALSE)] +#[cfg(false)] extern "C" { type A: Ord; type A<'a> where 'a: 'static; diff --git a/tests/ui/parser/impl-item-const-pass.rs b/tests/ui/parser/impl-item-const-pass.rs index 8ebdf633b5b9..6ca4cd9cd930 100644 --- a/tests/ui/parser/impl-item-const-pass.rs +++ b/tests/ui/parser/impl-item-const-pass.rs @@ -2,7 +2,7 @@ fn main() {} -#[cfg(FALSE)] +#[cfg(false)] impl X { const Y: u8; } diff --git a/tests/ui/parser/impl-item-fn-no-body-pass.rs b/tests/ui/parser/impl-item-fn-no-body-pass.rs index 5a593fe1d124..b8269fc42708 100644 --- a/tests/ui/parser/impl-item-fn-no-body-pass.rs +++ b/tests/ui/parser/impl-item-fn-no-body-pass.rs @@ -2,7 +2,7 @@ fn main() {} -#[cfg(FALSE)] +#[cfg(false)] impl X { fn f(); } diff --git a/tests/ui/parser/impl-item-type-no-body-pass.rs b/tests/ui/parser/impl-item-type-no-body-pass.rs index 039825bcc538..979b5f765960 100644 --- a/tests/ui/parser/impl-item-type-no-body-pass.rs +++ b/tests/ui/parser/impl-item-type-no-body-pass.rs @@ -2,7 +2,7 @@ fn main() {} -#[cfg(FALSE)] +#[cfg(false)] impl X { type Y; type Z: Ord; diff --git a/tests/ui/parser/issues/issue-65041-empty-vis-matcher-in-enum.rs b/tests/ui/parser/issues/issue-65041-empty-vis-matcher-in-enum.rs index 4fa803bb318e..13bb9351bb69 100644 --- a/tests/ui/parser/issues/issue-65041-empty-vis-matcher-in-enum.rs +++ b/tests/ui/parser/issues/issue-65041-empty-vis-matcher-in-enum.rs @@ -20,7 +20,7 @@ macro_rules! mac_variant { mac_variant!(MARKER); // We also accept visibilities on variants syntactically but not semantically. -#[cfg(FALSE)] +#[cfg(false)] enum E { pub U, pub(crate) T(u8), diff --git a/tests/ui/parser/issues/issue-65041-empty-vis-matcher-in-trait.rs b/tests/ui/parser/issues/issue-65041-empty-vis-matcher-in-trait.rs index cd474db63b71..55e69cd14d6b 100644 --- a/tests/ui/parser/issues/issue-65041-empty-vis-matcher-in-trait.rs +++ b/tests/ui/parser/issues/issue-65041-empty-vis-matcher-in-trait.rs @@ -20,7 +20,7 @@ trait Alpha { } // We also accept visibilities on items in traits syntactically but not semantically. -#[cfg(FALSE)] +#[cfg(false)] trait Foo { pub fn bar(); pub(crate) type baz; diff --git a/tests/ui/parser/item-free-const-no-body-syntactic-pass.rs b/tests/ui/parser/item-free-const-no-body-syntactic-pass.rs index 4edbee54de67..0b9229860bf8 100644 --- a/tests/ui/parser/item-free-const-no-body-syntactic-pass.rs +++ b/tests/ui/parser/item-free-const-no-body-syntactic-pass.rs @@ -4,5 +4,5 @@ fn main() {} -#[cfg(FALSE)] +#[cfg(false)] const X: u8; diff --git a/tests/ui/parser/item-free-static-no-body-syntactic-pass.rs b/tests/ui/parser/item-free-static-no-body-syntactic-pass.rs index df5192645e11..8dae4338ee7e 100644 --- a/tests/ui/parser/item-free-static-no-body-syntactic-pass.rs +++ b/tests/ui/parser/item-free-static-no-body-syntactic-pass.rs @@ -4,5 +4,5 @@ fn main() {} -#[cfg(FALSE)] +#[cfg(false)] static X: u8; diff --git a/tests/ui/parser/item-free-type-bounds-syntactic-pass.rs b/tests/ui/parser/item-free-type-bounds-syntactic-pass.rs index 80de3cfc668d..8603dc3eaf86 100644 --- a/tests/ui/parser/item-free-type-bounds-syntactic-pass.rs +++ b/tests/ui/parser/item-free-type-bounds-syntactic-pass.rs @@ -2,7 +2,7 @@ fn main() {} -#[cfg(FALSE)] +#[cfg(false)] fn syntax() { type A: Ord; type B: Ord = u8; diff --git a/tests/ui/parser/recover/recover-assoc-const-constraint.rs b/tests/ui/parser/recover/recover-assoc-const-constraint.rs index 1453e6cb5cd7..d938b4ccaca7 100644 --- a/tests/ui/parser/recover/recover-assoc-const-constraint.rs +++ b/tests/ui/parser/recover/recover-assoc-const-constraint.rs @@ -1,4 +1,4 @@ -#[cfg(FALSE)] +#[cfg(false)] fn syntax() { bar::(); //~^ ERROR associated const equality is incomplete diff --git a/tests/ui/parser/recover/recover-assoc-eq-missing-term.rs b/tests/ui/parser/recover/recover-assoc-eq-missing-term.rs index 4b42c44dc64e..73b4e22cab6f 100644 --- a/tests/ui/parser/recover/recover-assoc-eq-missing-term.rs +++ b/tests/ui/parser/recover/recover-assoc-eq-missing-term.rs @@ -1,4 +1,4 @@ -#[cfg(FALSE)] +#[cfg(false)] fn syntax() { bar::(); //~ ERROR missing type to the right of `=` } diff --git a/tests/ui/parser/recover/recover-assoc-lifetime-constraint.rs b/tests/ui/parser/recover/recover-assoc-lifetime-constraint.rs index cb65f80b0890..30bac49e63a5 100644 --- a/tests/ui/parser/recover/recover-assoc-lifetime-constraint.rs +++ b/tests/ui/parser/recover/recover-assoc-lifetime-constraint.rs @@ -1,4 +1,4 @@ -#[cfg(FALSE)] +#[cfg(false)] fn syntax() { bar::(); //~ ERROR lifetimes are not permitted in this context } diff --git a/tests/ui/parser/self-param-syntactic-pass.rs b/tests/ui/parser/self-param-syntactic-pass.rs index c7fdc5297164..331e652f9c57 100644 --- a/tests/ui/parser/self-param-syntactic-pass.rs +++ b/tests/ui/parser/self-param-syntactic-pass.rs @@ -5,7 +5,7 @@ fn main() {} -#[cfg(FALSE)] +#[cfg(false)] fn free() { fn f(self) {} fn f(mut self) {} @@ -17,7 +17,7 @@ fn free() { fn f(mut self: u8) {} } -#[cfg(FALSE)] +#[cfg(false)] extern "C" { fn f(self); fn f(mut self); @@ -29,7 +29,7 @@ extern "C" { fn f(mut self: u8); } -#[cfg(FALSE)] +#[cfg(false)] trait X { fn f(self) {} fn f(mut self) {} @@ -41,7 +41,7 @@ trait X { fn f(mut self: u8) {} } -#[cfg(FALSE)] +#[cfg(false)] impl X for Y { fn f(self) {} fn f(mut self) {} @@ -53,7 +53,7 @@ impl X for Y { fn f(mut self: u8) {} } -#[cfg(FALSE)] +#[cfg(false)] impl X for Y { type X = fn(self); type X = fn(mut self); diff --git a/tests/ui/parser/stripped-nested-outline-mod-pass.rs b/tests/ui/parser/stripped-nested-outline-mod-pass.rs index 8909d8ae0eb6..166a60f257a3 100644 --- a/tests/ui/parser/stripped-nested-outline-mod-pass.rs +++ b/tests/ui/parser/stripped-nested-outline-mod-pass.rs @@ -5,7 +5,7 @@ fn main() {} -#[cfg(FALSE)] +#[cfg(false)] mod foo { mod bar { mod baz; // This was an error before. diff --git a/tests/ui/parser/trait-item-with-defaultness-pass.rs b/tests/ui/parser/trait-item-with-defaultness-pass.rs index c636342f6ca4..164d0b13b539 100644 --- a/tests/ui/parser/trait-item-with-defaultness-pass.rs +++ b/tests/ui/parser/trait-item-with-defaultness-pass.rs @@ -2,7 +2,7 @@ fn main() {} -#[cfg(FALSE)] +#[cfg(false)] trait X { default const A: u8; default const B: u8 = 0; diff --git a/tests/ui/parser/variadic-ffi-syntactic-pass.rs b/tests/ui/parser/variadic-ffi-syntactic-pass.rs index da81f1362160..ebe0b6c2dd25 100644 --- a/tests/ui/parser/variadic-ffi-syntactic-pass.rs +++ b/tests/ui/parser/variadic-ffi-syntactic-pass.rs @@ -2,31 +2,31 @@ fn main() {} -#[cfg(FALSE)] +#[cfg(false)] fn f1_1(x: isize, ...) {} -#[cfg(FALSE)] +#[cfg(false)] fn f1_2(...) {} -#[cfg(FALSE)] +#[cfg(false)] extern "C" fn f2_1(x: isize, ...) {} -#[cfg(FALSE)] +#[cfg(false)] extern "C" fn f2_2(...) {} -#[cfg(FALSE)] +#[cfg(false)] extern "C" fn f2_3(..., x: isize) {} -#[cfg(FALSE)] +#[cfg(false)] extern fn f3_1(x: isize, ...) {} -#[cfg(FALSE)] +#[cfg(false)] extern fn f3_2(...) {} -#[cfg(FALSE)] +#[cfg(false)] extern fn f3_3(..., x: isize) {} -#[cfg(FALSE)] +#[cfg(false)] extern { fn e_f1(...); fn e_f2(..., x: isize); @@ -34,7 +34,7 @@ extern { struct X; -#[cfg(FALSE)] +#[cfg(false)] impl X { fn i_f1(x: isize, ...) {} fn i_f2(...) {} @@ -42,7 +42,7 @@ impl X { fn i_f4(..., x: isize, ...) {} } -#[cfg(FALSE)] +#[cfg(false)] trait T { fn t_f1(x: isize, ...) {} fn t_f2(x: isize, ...); diff --git a/tests/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.rs b/tests/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.rs index 01a978d55574..9582d2729a89 100644 --- a/tests/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.rs +++ b/tests/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.rs @@ -13,19 +13,19 @@ fn _ok() { fn _f(_a @ _b: u8) {} // OK. } -#[cfg(FALSE)] +#[cfg(false)] fn case_1() { let a: u8 @ b = 0; //~^ ERROR expected one of `!` } -#[cfg(FALSE)] +#[cfg(false)] fn case_2() { let a @ (b: u8); //~^ ERROR expected one of `)` } -#[cfg(FALSE)] +#[cfg(false)] fn case_3() { let a: T1 @ Outer(b: T2); //~^ ERROR expected one of `!` diff --git a/tests/ui/pattern/bindings-after-at/wild-before-at-syntactically-rejected.rs b/tests/ui/pattern/bindings-after-at/wild-before-at-syntactically-rejected.rs index 50ac0ef27834..c3994d35c421 100644 --- a/tests/ui/pattern/bindings-after-at/wild-before-at-syntactically-rejected.rs +++ b/tests/ui/pattern/bindings-after-at/wild-before-at-syntactically-rejected.rs @@ -3,7 +3,7 @@ fn main() {} -#[cfg(FALSE)] +#[cfg(false)] fn wild_before_at_is_bad_syntax() { let _ @ a = 0; //~^ ERROR pattern on wrong side of `@` diff --git a/tests/ui/pattern/rest-pat-syntactic.rs b/tests/ui/pattern/rest-pat-syntactic.rs index 1de29e69b054..59c687bb5a8d 100644 --- a/tests/ui/pattern/rest-pat-syntactic.rs +++ b/tests/ui/pattern/rest-pat-syntactic.rs @@ -11,7 +11,7 @@ macro_rules! accept_pat { accept_pat!(..); -#[cfg(FALSE)] +#[cfg(false)] fn rest_patterns() { // Top level: fn foo(..: u8) {} diff --git a/tests/ui/proc-macro/attribute-after-derive.rs b/tests/ui/proc-macro/attribute-after-derive.rs index f2e2eb12a195..382ef1f6ddfd 100644 --- a/tests/ui/proc-macro/attribute-after-derive.rs +++ b/tests/ui/proc-macro/attribute-after-derive.rs @@ -14,14 +14,14 @@ extern crate test_macros; #[print_attr] #[derive(Print)] struct AttributeDerive { - #[cfg(FALSE)] + #[cfg(false)] field: u8, } #[derive(Print)] #[print_attr] struct DeriveAttribute { - #[cfg(FALSE)] + #[cfg(false)] field: u8, } diff --git a/tests/ui/proc-macro/attribute-after-derive.stdout b/tests/ui/proc-macro/attribute-after-derive.stdout index 6d9531df8caf..bc0fc6dc1af1 100644 --- a/tests/ui/proc-macro/attribute-after-derive.stdout +++ b/tests/ui/proc-macro/attribute-after-derive.stdout @@ -1,5 +1,5 @@ -PRINT-ATTR INPUT (DISPLAY): #[derive(Print)] struct AttributeDerive { #[cfg(FALSE)] field: u8, } -PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): #[derive(Print)] struct AttributeDerive { #[cfg(FALSE)] field : u8, } +PRINT-ATTR INPUT (DISPLAY): #[derive(Print)] struct AttributeDerive { #[cfg(false)] field: u8, } +PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): #[derive(Print)] struct AttributeDerive { #[cfg(false)] field : u8, } PRINT-ATTR INPUT (DEBUG): TokenStream [ Punct { ch: '#', @@ -53,7 +53,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ delimiter: Parenthesis, stream: TokenStream [ Ident { - ident: "FALSE", + ident: "false", span: $DIR/attribute-after-derive.rs:17:11: 17:16 (#0), }, ], @@ -131,8 +131,8 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ span: $DIR/attribute-after-derive.rs:23:24: 26:2 (#0), }, ] -PRINT-ATTR INPUT (DISPLAY): struct DeriveAttribute { #[cfg(FALSE)] field: u8, } -PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): struct DeriveAttribute { #[cfg(FALSE)] field : u8, } +PRINT-ATTR INPUT (DISPLAY): struct DeriveAttribute { #[cfg(false)] field: u8, } +PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): struct DeriveAttribute { #[cfg(false)] field : u8, } PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", @@ -161,7 +161,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ delimiter: Parenthesis, stream: TokenStream [ Ident { - ident: "FALSE", + ident: "false", span: $DIR/attribute-after-derive.rs:24:11: 24:16 (#0), }, ], diff --git a/tests/ui/proc-macro/cfg-eval-fail.rs b/tests/ui/proc-macro/cfg-eval-fail.rs index a259aa2e6ec0..a94dcd283781 100644 --- a/tests/ui/proc-macro/cfg-eval-fail.rs +++ b/tests/ui/proc-macro/cfg-eval-fail.rs @@ -2,6 +2,6 @@ #![feature(stmt_expr_attributes)] fn main() { - let _ = #[cfg_eval] #[cfg(FALSE)] 0; + let _ = #[cfg_eval] #[cfg(false)] 0; //~^ ERROR removing an expression is not supported in this position } diff --git a/tests/ui/proc-macro/cfg-eval-fail.stderr b/tests/ui/proc-macro/cfg-eval-fail.stderr index 945ad46bf33c..7f21e4646b1c 100644 --- a/tests/ui/proc-macro/cfg-eval-fail.stderr +++ b/tests/ui/proc-macro/cfg-eval-fail.stderr @@ -1,7 +1,7 @@ error: removing an expression is not supported in this position --> $DIR/cfg-eval-fail.rs:5:25 | -LL | let _ = #[cfg_eval] #[cfg(FALSE)] 0; +LL | let _ = #[cfg_eval] #[cfg(false)] 0; | ^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/proc-macro/cfg-eval-inner.rs b/tests/ui/proc-macro/cfg-eval-inner.rs index 7493f3ea5236..dc4efd6ba15f 100644 --- a/tests/ui/proc-macro/cfg-eval-inner.rs +++ b/tests/ui/proc-macro/cfg-eval-inner.rs @@ -32,7 +32,7 @@ impl Foo<[u8; { #![cfg_attr(not(FALSE), rustc_dummy(evaluated_attr))] fn bar() { - #[cfg(FALSE)] let a = 1; + #[cfg(false)] let a = 1; } } diff --git a/tests/ui/proc-macro/cfg-eval.rs b/tests/ui/proc-macro/cfg-eval.rs index 1d9b4f23ea5c..ddf370805960 100644 --- a/tests/ui/proc-macro/cfg-eval.rs +++ b/tests/ui/proc-macro/cfg-eval.rs @@ -15,7 +15,7 @@ extern crate test_macros; #[cfg_eval] #[print_attr] struct S1 { - #[cfg(FALSE)] + #[cfg(false)] field_false: u8, #[cfg(all(/*true*/))] #[cfg_attr(FALSE, unknown_attr)] @@ -24,7 +24,7 @@ struct S1 { } #[cfg_eval] -#[cfg(FALSE)] +#[cfg(false)] struct S2 {} fn main() { @@ -33,5 +33,5 @@ fn main() { // expression. `#[cfg]` is not supported inside parenthesized expressions, so this will // produce an error when attribute collection runs. let _ = #[cfg_eval] #[print_attr] #[cfg_attr(not(FALSE), rustc_dummy)] - (#[cfg(FALSE)] 0, #[cfg(all(/*true*/))] 1,); + (#[cfg(false)] 0, #[cfg(all(/*true*/))] 1,); } diff --git a/tests/ui/proc-macro/derive-cfg-nested-tokens.rs b/tests/ui/proc-macro/derive-cfg-nested-tokens.rs index 7d4e8d8373d6..ec6aba0d1ea3 100644 --- a/tests/ui/proc-macro/derive-cfg-nested-tokens.rs +++ b/tests/ui/proc-macro/derive-cfg-nested-tokens.rs @@ -15,7 +15,7 @@ struct S { // - on eagerly configured `S` (from `impl Copy`), only 11 should be printed // - on non-configured `S` (from `struct S`), both 10 and 11 should be printed field: [u8; #[print_attr] { - #[cfg(FALSE)] { 10 } + #[cfg(false)] { 10 } #[cfg(not(FALSE))] { 11 } }], } diff --git a/tests/ui/proc-macro/derive-cfg-nested-tokens.stdout b/tests/ui/proc-macro/derive-cfg-nested-tokens.stdout index 05bf21ee8f9b..9dbddc95902d 100644 --- a/tests/ui/proc-macro/derive-cfg-nested-tokens.stdout +++ b/tests/ui/proc-macro/derive-cfg-nested-tokens.stdout @@ -54,7 +54,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ span: #0 bytes(452..523), }, ] -PRINT-ATTR INPUT (DISPLAY): { #[cfg(FALSE)] { 10 } #[cfg(not(FALSE))] { 11 } } +PRINT-ATTR INPUT (DISPLAY): { #[cfg(false)] { 10 } #[cfg(not(FALSE))] { 11 } } PRINT-ATTR INPUT (DEBUG): TokenStream [ Group { delimiter: Brace, @@ -75,7 +75,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ delimiter: Parenthesis, stream: TokenStream [ Ident { - ident: "FALSE", + ident: "false", span: #0 bytes(468..473), }, ], diff --git a/tests/ui/proc-macro/expand-to-derive.rs b/tests/ui/proc-macro/expand-to-derive.rs index 0e38e471980b..05c8e3262431 100644 --- a/tests/ui/proc-macro/expand-to-derive.rs +++ b/tests/ui/proc-macro/expand-to-derive.rs @@ -14,7 +14,7 @@ macro_rules! expand_to_derive { ($item:item) => { #[derive(Print)] struct Foo { - #[cfg(FALSE)] removed: bool, + #[cfg(false)] removed: bool, field: [bool; { $item 0 @@ -26,7 +26,7 @@ macro_rules! expand_to_derive { expand_to_derive! { #[cfg_attr(not(FALSE), rustc_dummy)] struct Inner { - #[cfg(FALSE)] removed_inner_field: bool, + #[cfg(false)] removed_inner_field: bool, other_inner_field: u8, } } diff --git a/tests/ui/proc-macro/issue-75930-derive-cfg.rs b/tests/ui/proc-macro/issue-75930-derive-cfg.rs index 376a8ea42783..f0851b31e9cb 100644 --- a/tests/ui/proc-macro/issue-75930-derive-cfg.rs +++ b/tests/ui/proc-macro/issue-75930-derive-cfg.rs @@ -31,7 +31,7 @@ extern crate test_macros; // // It is because of this code from below: // ``` -// struct Foo<#[cfg(FALSE)] A, B> +// struct Foo<#[cfg(false)] A, B> // ``` // When the token stream is formed during parsing, `<` is followed immediately // by `#`, which is punctuation, so it is marked `Joint`. But before being @@ -51,22 +51,22 @@ extern crate test_macros; #[print_attr] #[derive(Print)] #[print_helper(b)] -struct Foo<#[cfg(FALSE)] A, B> { - #[cfg(FALSE)] first: String, +struct Foo<#[cfg(false)] A, B> { + #[cfg(false)] first: String, #[cfg_attr(FALSE, deny(warnings))] second: bool, third: [u8; { - #[cfg(FALSE)] struct Bar; + #[cfg(false)] struct Bar; #[cfg(not(FALSE))] struct Inner; - #[cfg(FALSE)] let a = 25; + #[cfg(false)] let a = 25; match true { - #[cfg(FALSE)] true => {}, + #[cfg(false)] true => {}, #[cfg_attr(not(FALSE), allow(warnings))] false => {}, _ => {} }; #[print_helper(should_be_removed)] fn removed_fn() { - #![cfg(FALSE)] + #![cfg(false)] } #[print_helper(c)] #[cfg(not(FALSE))] fn kept_fn() { @@ -76,22 +76,22 @@ struct Foo<#[cfg(FALSE)] A, B> { enum TupleEnum { Foo( - #[cfg(FALSE)] u8, - #[cfg(FALSE)] bool, + #[cfg(false)] u8, + #[cfg(false)] bool, #[cfg(not(FALSE))] i32, - #[cfg(FALSE)] String, u8 + #[cfg(false)] String, u8 ) } struct TupleStruct( - #[cfg(FALSE)] String, + #[cfg(false)] String, #[cfg(not(FALSE))] i32, - #[cfg(FALSE)] bool, + #[cfg(false)] bool, u8 ); fn plain_removed_fn() { - #![cfg_attr(not(FALSE), cfg(FALSE))] + #![cfg_attr(not(FALSE), cfg(false))] } 0 diff --git a/tests/ui/proc-macro/issue-75930-derive-cfg.stdout b/tests/ui/proc-macro/issue-75930-derive-cfg.stdout index 4dcf2b717d8a..549621fdca31 100644 --- a/tests/ui/proc-macro/issue-75930-derive-cfg.stdout +++ b/tests/ui/proc-macro/issue-75930-derive-cfg.stdout @@ -1,73 +1,73 @@ PRINT-ATTR INPUT (DISPLAY): #[print_helper(a)] #[allow(dead_code)] #[derive(Print)] #[print_helper(b)] -struct Foo<#[cfg(FALSE)] A, B> +struct Foo<#[cfg(false)] A, B> { - #[cfg(FALSE)] first: String, #[cfg_attr(FALSE, deny(warnings))] second: + #[cfg(false)] first: String, #[cfg_attr(FALSE, deny(warnings))] second: bool, third: [u8; { - #[cfg(FALSE)] struct Bar; #[cfg(not(FALSE))] struct Inner; - #[cfg(FALSE)] let a = 25; match true + #[cfg(false)] struct Bar; #[cfg(not(FALSE))] struct Inner; + #[cfg(false)] let a = 25; match true { - #[cfg(FALSE)] true => {}, #[cfg_attr(not(FALSE), allow(warnings))] + #[cfg(false)] true => {}, #[cfg_attr(not(FALSE), allow(warnings))] false => {}, _ => {} }; #[print_helper(should_be_removed)] fn removed_fn() - { #![cfg(FALSE)] } #[print_helper(c)] #[cfg(not(FALSE))] fn kept_fn() + { #![cfg(false)] } #[print_helper(c)] #[cfg(not(FALSE))] fn kept_fn() { #![cfg(not(FALSE))] let my_val = true; } enum TupleEnum { - Foo(#[cfg(FALSE)] u8, #[cfg(FALSE)] bool, #[cfg(not(FALSE))] i32, - #[cfg(FALSE)] String, u8) + Foo(#[cfg(false)] u8, #[cfg(false)] bool, #[cfg(not(FALSE))] i32, + #[cfg(false)] String, u8) } struct - TupleStruct(#[cfg(FALSE)] String, #[cfg(not(FALSE))] i32, - #[cfg(FALSE)] bool, u8); fn plain_removed_fn() - { #![cfg_attr(not(FALSE), cfg(FALSE))] } 0 + TupleStruct(#[cfg(false)] String, #[cfg(not(FALSE))] i32, + #[cfg(false)] bool, u8); fn plain_removed_fn() + { #![cfg_attr(not(FALSE), cfg(false))] } 0 }], #[print_helper(d)] fourth: B } PRINT-ATTR RE-COLLECTED (DISPLAY): #[print_helper(a)] #[allow(dead_code)] #[derive(Print)] #[print_helper(b)] -struct Foo <#[cfg(FALSE)] A, B > +struct Foo <#[cfg(false)] A, B > { - #[cfg(FALSE)] first: String, #[cfg_attr(FALSE, deny(warnings))] second: + #[cfg(false)] first: String, #[cfg_attr(FALSE, deny(warnings))] second: bool, third: [u8; { - #[cfg(FALSE)] struct Bar; #[cfg(not(FALSE))] struct Inner; - #[cfg(FALSE)] let a = 25; match true + #[cfg(false)] struct Bar; #[cfg(not(FALSE))] struct Inner; + #[cfg(false)] let a = 25; match true { - #[cfg(FALSE)] true => {}, #[cfg_attr(not(FALSE), allow(warnings))] + #[cfg(false)] true => {}, #[cfg_attr(not(FALSE), allow(warnings))] false => {}, _ => {} }; #[print_helper(should_be_removed)] fn removed_fn() - { #![cfg(FALSE)] } #[print_helper(c)] #[cfg(not(FALSE))] fn kept_fn() + { #![cfg(false)] } #[print_helper(c)] #[cfg(not(FALSE))] fn kept_fn() { #![cfg(not(FALSE))] let my_val = true; } enum TupleEnum { - Foo(#[cfg(FALSE)] u8, #[cfg(FALSE)] bool, #[cfg(not(FALSE))] i32, - #[cfg(FALSE)] String, u8) + Foo(#[cfg(false)] u8, #[cfg(false)] bool, #[cfg(not(FALSE))] i32, + #[cfg(false)] String, u8) } struct - TupleStruct(#[cfg(FALSE)] String, #[cfg(not(FALSE))] i32, - #[cfg(FALSE)] bool, u8); fn plain_removed_fn() - { #![cfg_attr(not(FALSE), cfg(FALSE))] } 0 + TupleStruct(#[cfg(false)] String, #[cfg(not(FALSE))] i32, + #[cfg(false)] bool, u8); fn plain_removed_fn() + { #![cfg_attr(not(FALSE), cfg(false))] } 0 }], #[print_helper(d)] fourth: B } PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): #[print_helper(a)] #[allow(dead_code)] #[derive(Print)] #[print_helper(b)] -struct Foo <#[cfg(FALSE)] A, B > +struct Foo <#[cfg(false)] A, B > { - #[cfg(FALSE)] first : String, #[cfg_attr(FALSE, deny(warnings))] second : + #[cfg(false)] first : String, #[cfg_attr(FALSE, deny(warnings))] second : bool, third : [u8; { - #[cfg(FALSE)] struct Bar; #[cfg(not(FALSE))] struct Inner; - #[cfg(FALSE)] let a = 25; match true + #[cfg(false)] struct Bar; #[cfg(not(FALSE))] struct Inner; + #[cfg(false)] let a = 25; match true { - #[cfg(FALSE)] true => {}, #[cfg_attr(not(FALSE), allow(warnings))] + #[cfg(false)] true => {}, #[cfg_attr(not(FALSE), allow(warnings))] false => {}, _ => {} }; #[print_helper(should_be_removed)] fn removed_fn() - { #! [cfg(FALSE)] } #[print_helper(c)] #[cfg(not(FALSE))] fn kept_fn() + { #! [cfg(false)] } #[print_helper(c)] #[cfg(not(FALSE))] fn kept_fn() { #! [cfg(not(FALSE))] let my_val = true; } enum TupleEnum { - Foo(#[cfg(FALSE)] u8, #[cfg(FALSE)] bool, #[cfg(not(FALSE))] i32, - #[cfg(FALSE)] String, u8) + Foo(#[cfg(false)] u8, #[cfg(false)] bool, #[cfg(not(FALSE))] i32, + #[cfg(false)] String, u8) } struct - TupleStruct(#[cfg(FALSE)] String, #[cfg(not(FALSE))] i32, - #[cfg(FALSE)] bool, u8); fn plain_removed_fn() - { #! [cfg_attr(not(FALSE), cfg(FALSE))] } 0 + TupleStruct(#[cfg(false)] String, #[cfg(not(FALSE))] i32, + #[cfg(false)] bool, u8); fn plain_removed_fn() + { #! [cfg_attr(not(FALSE), cfg(false))] } 0 }], #[print_helper(d)] fourth : B } PRINT-ATTR INPUT (DEBUG): TokenStream [ @@ -200,7 +200,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ delimiter: Parenthesis, stream: TokenStream [ Ident { - ident: "FALSE", + ident: "false", span: $DIR/issue-75930-derive-cfg.rs:54:18: 54:23 (#0), }, ], @@ -246,7 +246,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ delimiter: Parenthesis, stream: TokenStream [ Ident { - ident: "FALSE", + ident: "false", span: $DIR/issue-75930-derive-cfg.rs:55:11: 55:16 (#0), }, ], @@ -375,7 +375,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ delimiter: Parenthesis, stream: TokenStream [ Ident { - ident: "FALSE", + ident: "false", span: $DIR/issue-75930-derive-cfg.rs:58:15: 58:20 (#0), }, ], @@ -461,7 +461,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ delimiter: Parenthesis, stream: TokenStream [ Ident { - ident: "FALSE", + ident: "false", span: $DIR/issue-75930-derive-cfg.rs:60:15: 60:20 (#0), }, ], @@ -521,7 +521,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ delimiter: Parenthesis, stream: TokenStream [ Ident { - ident: "FALSE", + ident: "false", span: $DIR/issue-75930-derive-cfg.rs:62:19: 62:24 (#0), }, ], @@ -721,7 +721,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ delimiter: Parenthesis, stream: TokenStream [ Ident { - ident: "FALSE", + ident: "false", span: $DIR/issue-75930-derive-cfg.rs:69:20: 69:25 (#0), }, ], @@ -908,7 +908,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ delimiter: Parenthesis, stream: TokenStream [ Ident { - ident: "FALSE", + ident: "false", span: $DIR/issue-75930-derive-cfg.rs:79:23: 79:28 (#0), }, ], @@ -942,7 +942,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ delimiter: Parenthesis, stream: TokenStream [ Ident { - ident: "FALSE", + ident: "false", span: $DIR/issue-75930-derive-cfg.rs:80:23: 80:28 (#0), }, ], @@ -1020,7 +1020,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ delimiter: Parenthesis, stream: TokenStream [ Ident { - ident: "FALSE", + ident: "false", span: $DIR/issue-75930-derive-cfg.rs:82:23: 82:28 (#0), }, ], @@ -1075,7 +1075,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ delimiter: Parenthesis, stream: TokenStream [ Ident { - ident: "FALSE", + ident: "false", span: $DIR/issue-75930-derive-cfg.rs:87:19: 87:24 (#0), }, ], @@ -1153,7 +1153,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ delimiter: Parenthesis, stream: TokenStream [ Ident { - ident: "FALSE", + ident: "false", span: $DIR/issue-75930-derive-cfg.rs:89:19: 89:24 (#0), }, ], @@ -1246,7 +1246,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ delimiter: Parenthesis, stream: TokenStream [ Ident { - ident: "FALSE", + ident: "false", span: $DIR/issue-75930-derive-cfg.rs:94:41: 94:46 (#0), }, ], diff --git a/tests/ui/proc-macro/nested-derive-cfg.rs b/tests/ui/proc-macro/nested-derive-cfg.rs index bd8f231ac2c2..b3dcfb7c3966 100644 --- a/tests/ui/proc-macro/nested-derive-cfg.rs +++ b/tests/ui/proc-macro/nested-derive-cfg.rs @@ -10,10 +10,10 @@ extern crate test_macros; #[derive(Print)] struct Foo { - #[cfg(FALSE)] removed: bool, + #[cfg(false)] removed: bool, my_array: [bool; { struct Inner { - #[cfg(FALSE)] removed_inner_field: u8, + #[cfg(false)] removed_inner_field: u8, non_removed_inner_field: usize } 0 diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs index 110c03d0e549..983fe87451f2 100644 --- a/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs @@ -64,7 +64,7 @@ fn _macros() { //~^ ERROR expected expression, found `let` statement //~| ERROR expected expression, found `let` statement match () { - #[cfg(FALSE)] + #[cfg(false)] () if let 0 = 1 => {} //~^ ERROR `if let` guards are experimental _ => {} diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/parens.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/parens.rs index f12824db9c00..0e71a9d24c97 100644 --- a/tests/ui/rfcs/rfc-2294-if-let-guard/parens.rs +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/parens.rs @@ -3,7 +3,7 @@ #![feature(if_let_guard)] #![feature(let_chains)] -#[cfg(FALSE)] +#[cfg(false)] fn un_cfged() { match () { () if let 0 = 1 => {} diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs index 99f99c2be72d..0b0abe6ec175 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs @@ -340,12 +340,12 @@ fn outside_if_and_while_expr() { //~| ERROR expected expression, found `let` statement { - #[cfg(FALSE)] + #[cfg(false)] let x = true && let y = 1; //~^ ERROR expected expression, found `let` statement } - #[cfg(FALSE)] + #[cfg(false)] { [1, 2, 3][let _ = ()] //~^ ERROR expected expression, found `let` statement @@ -436,11 +436,11 @@ fn with_parenthesis() { //[no_feature]~^ ERROR `let` expressions in this position are unstable } - #[cfg(FALSE)] + #[cfg(false)] let x = (true && let y = 1); //~^ ERROR expected expression, found `let` statement - #[cfg(FALSE)] + #[cfg(false)] { ([1, 2, 3][let _ = ()]) //~^ ERROR expected expression, found `let` statement diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.rs index 2087fc42cf10..dad02b7f1063 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.rs +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.rs @@ -51,7 +51,7 @@ fn _macros() { while $e {} } } - #[cfg(FALSE)] (let 0 = 1); + #[cfg(false)] (let 0 = 1); //~^ ERROR expected expression, found `let` statement use_expr!(let 0 = 1); //~^ ERROR no rules expected keyword `let` diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.stderr index 7c874ae78a8a..b9dac472dca1 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.stderr +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/feature-gate.stderr @@ -1,7 +1,7 @@ error: expected expression, found `let` statement --> $DIR/feature-gate.rs:54:20 | -LL | #[cfg(FALSE)] (let 0 = 1); +LL | #[cfg(false)] (let 0 = 1); | ^^^ | = note: only supported directly in conditions of `if` and `while` expressions diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.rs index dce1c19ff339..ae525aed4148 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.rs +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/invalid-let-in-a-valid-let-context.rs @@ -3,12 +3,12 @@ fn main() { let _opt = Some(1i32); - #[cfg(FALSE)] + #[cfg(false)] { let _ = &&let Some(x) = Some(42); //~^ ERROR expected expression, found `let` statement } - #[cfg(FALSE)] + #[cfg(false)] { if let Some(elem) = _opt && [1, 2, 3][let _ = &&let Some(x) = Some(42)] = 1 { //~^ ERROR expected expression, found `let` statement @@ -18,7 +18,7 @@ fn main() { } } - #[cfg(FALSE)] + #[cfg(false)] { if let Some(elem) = _opt && { [1, 2, 3][let _ = ()]; @@ -28,7 +28,7 @@ fn main() { } } - #[cfg(FALSE)] + #[cfg(false)] { if let Some(elem) = _opt && [1, 2, 3][let _ = ()] = 1 { //~^ ERROR expected expression, found `let` statement @@ -36,7 +36,7 @@ fn main() { true } } - #[cfg(FALSE)] + #[cfg(false)] { if let a = 1 && { let x = let y = 1; diff --git a/tests/ui/rfcs/rfc-2565-param-attrs/attr-without-param.rs b/tests/ui/rfcs/rfc-2565-param-attrs/attr-without-param.rs index eeb2191bab46..c0f17570673c 100644 --- a/tests/ui/rfcs/rfc-2565-param-attrs/attr-without-param.rs +++ b/tests/ui/rfcs/rfc-2565-param-attrs/attr-without-param.rs @@ -1,14 +1,14 @@ -#[cfg(FALSE)] +#[cfg(false)] impl S { fn f(#[attr]) {} //~ ERROR expected parameter name, found `)` } -#[cfg(FALSE)] +#[cfg(false)] impl T for S { fn f(#[attr]) {} //~ ERROR expected parameter name, found `)` } -#[cfg(FALSE)] +#[cfg(false)] trait T { fn f(#[attr]); //~ ERROR expected argument name, found `)` } diff --git a/tests/ui/specialization/issue-63716-parse-async.rs b/tests/ui/specialization/issue-63716-parse-async.rs index 3314b4e20f90..00c0b291a1ad 100644 --- a/tests/ui/specialization/issue-63716-parse-async.rs +++ b/tests/ui/specialization/issue-63716-parse-async.rs @@ -8,7 +8,7 @@ fn main() {} -#[cfg(FALSE)] +#[cfg(false)] impl Foo for Bar { default async fn baz() {} } diff --git a/tests/ui/suggestions/const-no-type.rs b/tests/ui/suggestions/const-no-type.rs index c6fdcdadbeaf..b72ace95213c 100644 --- a/tests/ui/suggestions/const-no-type.rs +++ b/tests/ui/suggestions/const-no-type.rs @@ -10,19 +10,19 @@ fn main() {} // These will not reach typeck: -#[cfg(FALSE)] +#[cfg(false)] const C2 = 42; //~^ ERROR missing type for `const` item //~| HELP provide a type for the item //~| SUGGESTION : -#[cfg(FALSE)] +#[cfg(false)] static S2 = "abc"; //~^ ERROR missing type for `static` item //~| HELP provide a type for the item //~| SUGGESTION : -#[cfg(FALSE)] +#[cfg(false)] static mut SM2 = "abc"; //~^ ERROR missing type for `static mut` item //~| HELP provide a type for the item diff --git a/tests/ui/suggestions/type-ascription-and-other-error.rs b/tests/ui/suggestions/type-ascription-and-other-error.rs index 99ab2f3c858b..da985b53aef6 100644 --- a/tests/ui/suggestions/type-ascription-and-other-error.rs +++ b/tests/ui/suggestions/type-ascription-and-other-error.rs @@ -1,6 +1,6 @@ fn main() { not rust; //~ ERROR let _ = 0: i32; // (error hidden by existing error) - #[cfg(FALSE)] + #[cfg(false)] let _ = 0: i32; // (warning hidden by existing error) } diff --git a/tests/ui/wasm/wasm-import-module.rs b/tests/ui/wasm/wasm-import-module.rs index bff08847d37d..2b3bca9a411b 100644 --- a/tests/ui/wasm/wasm-import-module.rs +++ b/tests/ui/wasm/wasm-import-module.rs @@ -15,7 +15,7 @@ extern "C" {} #[link(wasm_import_module = "foo", kind = "dylib")] //~ ERROR: `wasm_import_module` is incompatible with other arguments extern "C" {} -#[link(wasm_import_module = "foo", cfg(FALSE))] //~ ERROR: `wasm_import_module` is incompatible with other arguments +#[link(wasm_import_module = "foo", cfg(false))] //~ ERROR: `wasm_import_module` is incompatible with other arguments extern "C" {} fn main() {} diff --git a/tests/ui/wasm/wasm-import-module.stderr b/tests/ui/wasm/wasm-import-module.stderr index e792c33e91a9..84f437941a79 100644 --- a/tests/ui/wasm/wasm-import-module.stderr +++ b/tests/ui/wasm/wasm-import-module.stderr @@ -31,7 +31,7 @@ LL | #[link(wasm_import_module = "foo", kind = "dylib")] error: `wasm_import_module` is incompatible with other arguments in `#[link]` attributes --> $DIR/wasm-import-module.rs:18:8 | -LL | #[link(wasm_import_module = "foo", cfg(FALSE))] +LL | #[link(wasm_import_module = "foo", cfg(false))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 6 previous errors From 3123df8ef0cc32318d96b90620396d8b22d2ffb3 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Thu, 27 Mar 2025 18:29:58 +0100 Subject: [PATCH 098/606] Implement `super let`. --- compiler/rustc_ast/src/ast.rs | 3 +- compiler/rustc_ast/src/mut_visit.rs | 3 +- compiler/rustc_ast/src/visit.rs | 2 +- compiler/rustc_ast_lowering/src/block.rs | 3 +- compiler/rustc_ast_lowering/src/lib.rs | 1 + compiler/rustc_ast_pretty/src/pprust/state.rs | 3 + compiler/rustc_expand/src/build.rs | 2 + compiler/rustc_hir/src/hir.rs | 4 +- .../rustc_hir_analysis/src/check/region.rs | 91 +++++++++++++++---- compiler/rustc_hir_pretty/src/lib.rs | 10 +- .../rustc_hir_typeck/src/gather_locals.rs | 2 +- compiler/rustc_parse/src/parser/stmt.rs | 14 +-- tests/ui/stats/input-stats.stderr | 36 ++++---- 13 files changed, 126 insertions(+), 48 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 97e6879c33e9..78cc663a8e37 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1169,6 +1169,7 @@ pub enum MacStmtStyle { #[derive(Clone, Encodable, Decodable, Debug)] pub struct Local { pub id: NodeId, + pub super_: Option, pub pat: P, pub ty: Option>, pub kind: LocalKind, @@ -3926,7 +3927,7 @@ mod size_asserts { static_assert_size!(Item, 144); static_assert_size!(ItemKind, 80); static_assert_size!(LitKind, 24); - static_assert_size!(Local, 80); + static_assert_size!(Local, 96); static_assert_size!(MetaItemLit, 40); static_assert_size!(Param, 40); static_assert_size!(Pat, 72); diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index f7d13acdfc40..58af024dc163 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -704,7 +704,8 @@ fn walk_parenthesized_parameter_data(vis: &mut T, args: &mut Pare } fn walk_local(vis: &mut T, local: &mut P) { - let Local { id, pat, ty, kind, span, colon_sp, attrs, tokens } = local.deref_mut(); + let Local { id, super_, pat, ty, kind, span, colon_sp, attrs, tokens } = local.deref_mut(); + visit_opt(super_, |sp| vis.visit_span(sp)); vis.visit_id(id); visit_attrs(vis, attrs); vis.visit_pat(pat); diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 1ef92ff8898e..37e32671b294 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -323,7 +323,7 @@ pub fn walk_crate<'a, V: Visitor<'a>>(visitor: &mut V, krate: &'a Crate) -> V::R } pub fn walk_local<'a, V: Visitor<'a>>(visitor: &mut V, local: &'a Local) -> V::Result { - let Local { id: _, pat, ty, kind, span: _, colon_sp: _, attrs, tokens: _ } = local; + let Local { id: _, super_: _, pat, ty, kind, span: _, colon_sp: _, attrs, tokens: _ } = local; walk_list!(visitor, visit_attribute, attrs); try_visit!(visitor.visit_pat(pat)); visit_opt!(visitor, visit_ty, ty); diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs index 1d9ca6bb9c8c..c3222b79e55c 100644 --- a/compiler/rustc_ast_lowering/src/block.rs +++ b/compiler/rustc_ast_lowering/src/block.rs @@ -95,6 +95,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_local(&mut self, l: &Local) -> &'hir hir::LetStmt<'hir> { // Let statements are allowed to have impl trait in bindings. + let super_ = l.super_; let ty = l.ty.as_ref().map(|t| { self.lower_ty(t, self.impl_trait_in_bindings_ctxt(ImplTraitPosition::Variable)) }); @@ -109,7 +110,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let span = self.lower_span(l.span); let source = hir::LocalSource::Normal; self.lower_attrs(hir_id, &l.attrs, l.span); - self.arena.alloc(hir::LetStmt { hir_id, ty, pat, init, els, span, source }) + self.arena.alloc(hir::LetStmt { hir_id, super_, ty, pat, init, els, span, source }) } fn lower_block_check_mode(&mut self, b: &BlockCheckMode) -> hir::BlockCheckMode { diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index d5d6dcd8d631..0dd8bd79604e 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2223,6 +2223,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.attrs.insert(hir_id.local_id, a); } let local = hir::LetStmt { + super_: None, hir_id, init, pat, diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 3dbfc191f8f5..e2dc334f7efc 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1336,6 +1336,9 @@ impl<'a> State<'a> { self.print_outer_attributes(&loc.attrs); self.space_if_not_bol(); self.ibox(INDENT_UNIT); + if loc.super_.is_some() { + self.word_nbsp("let"); + } self.word_nbsp("let"); self.ibox(INDENT_UNIT); diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index f68172c1f67c..6d616cf84bbd 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -230,6 +230,7 @@ impl<'a> ExtCtxt<'a> { self.pat_ident(sp, ident) }; let local = P(ast::Local { + super_: None, pat, ty, id: ast::DUMMY_NODE_ID, @@ -245,6 +246,7 @@ impl<'a> ExtCtxt<'a> { /// Generates `let _: Type;`, which is usually used for type assertions. pub fn stmt_let_type_only(&self, span: Span, ty: P) -> ast::Stmt { let local = P(ast::Local { + super_: None, pat: self.pat_wild(span), ty: Some(ty), id: ast::DUMMY_NODE_ID, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 1a6c15b66a45..14b7c31285ef 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1817,6 +1817,8 @@ pub enum StmtKind<'hir> { /// Represents a `let` statement (i.e., `let : = ;`). #[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct LetStmt<'hir> { + /// Span of `super` in `super let`. + pub super_: Option, pub pat: &'hir Pat<'hir>, /// Type annotation, if any (otherwise the type will be inferred). pub ty: Option<&'hir Ty<'hir>>, @@ -4850,7 +4852,7 @@ mod size_asserts { static_assert_size!(ImplItemKind<'_>, 40); static_assert_size!(Item<'_>, 88); static_assert_size!(ItemKind<'_>, 64); - static_assert_size!(LetStmt<'_>, 64); + static_assert_size!(LetStmt<'_>, 72); static_assert_size!(Param<'_>, 32); static_assert_size!(Pat<'_>, 72); static_assert_size!(Path<'_>, 40); diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index cf66ab708bb9..15d121758918 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -8,6 +8,7 @@ use std::mem; +use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{self, Visitor}; @@ -44,6 +45,8 @@ struct ScopeResolutionVisitor<'tcx> { scope_tree: ScopeTree, cx: Context, + + extended_super_lets: FxHashMap>, } /// Records the lifetime of a local variable as `cx.var_parent` @@ -214,18 +217,29 @@ fn resolve_stmt<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, stmt: &'tcx hi let stmt_id = stmt.hir_id.local_id; debug!("resolve_stmt(stmt.id={:?})", stmt_id); - // Every statement will clean up the temporaries created during - // execution of that statement. Therefore each statement has an - // associated destruction scope that represents the scope of the - // statement plus its destructors, and thus the scope for which - // regions referenced by the destructors need to survive. + if let hir::StmtKind::Let(LetStmt { super_: Some(_), .. }) = stmt.kind { + // `super let` statement does not start a new scope, such that + // + // { super let x = identity(&temp()); &x }.method(); + // + // behaves exactly as + // + // (&identity(&temp()).method(); + intravisit::walk_stmt(visitor, stmt); + } else { + // Every statement will clean up the temporaries created during + // execution of that statement. Therefore each statement has an + // associated destruction scope that represents the scope of the + // statement plus its destructors, and thus the scope for which + // regions referenced by the destructors need to survive. - let prev_parent = visitor.cx.parent; - visitor.enter_node_scope_with_dtor(stmt_id, true); + let prev_parent = visitor.cx.parent; + visitor.enter_node_scope_with_dtor(stmt_id, true); - intravisit::walk_stmt(visitor, stmt); + intravisit::walk_stmt(visitor, stmt); - visitor.cx.parent = prev_parent; + visitor.cx.parent = prev_parent; + } } fn resolve_expr<'tcx>( @@ -485,10 +499,9 @@ fn resolve_local<'tcx>( visitor: &mut ScopeResolutionVisitor<'tcx>, pat: Option<&'tcx hir::Pat<'tcx>>, init: Option<&'tcx hir::Expr<'tcx>>, + super_let: bool, ) { - debug!("resolve_local(pat={:?}, init={:?})", pat, init); - - let blk_scope = visitor.cx.var_parent; + debug!("resolve_local(pat={:?}, init={:?}, super_let={:?})", pat, init, super_let); // As an exception to the normal rules governing temporary // lifetimes, initializers in a let have a temporary lifetime @@ -546,14 +559,50 @@ fn resolve_local<'tcx>( // A, but the inner rvalues `a()` and `b()` have an extended lifetime // due to rule C. + if super_let { + if let Some(scope) = visitor.extended_super_lets.remove(&pat.unwrap().hir_id.local_id) { + // This expression was lifetime-extended by a parent let binding. E.g. + // + // let a = { + // super let b = temp(); + // &b + // }; + // + // (Which needs to behave exactly as: let a = &temp();) + // + // Processing of `let a` will have already decided to extend the lifetime of this + // `super let` to its own var_scope. We use that scope. + visitor.cx.var_parent = scope; + } else { + // This `super let` is not subject to lifetime extension from a parent let binding. E.g. + // + // identity({ super let x = temp(); &x }).method(); + // + // (Which needs to behave exactly as: identity(&temp()).method();) + // + // Iterate up to the enclosing destruction scope to find the same scope that will also + // be used for the result of the block itself. + while let Some(s) = visitor.cx.var_parent { + let parent = visitor.scope_tree.parent_map.get(&s).cloned(); + if let Some(Scope { data: ScopeData::Destruction, .. }) = parent { + break; + } + visitor.cx.var_parent = parent; + } + } + } + if let Some(expr) = init { - record_rvalue_scope_if_borrow_expr(visitor, expr, blk_scope); + record_rvalue_scope_if_borrow_expr(visitor, expr, visitor.cx.var_parent); if let Some(pat) = pat { if is_binding_pat(pat) { visitor.scope_tree.record_rvalue_candidate( expr.hir_id, - RvalueCandidate { target: expr.hir_id.local_id, lifetime: blk_scope }, + RvalueCandidate { + target: expr.hir_id.local_id, + lifetime: visitor.cx.var_parent, + }, ); } } @@ -565,6 +614,7 @@ fn resolve_local<'tcx>( if let Some(expr) = init { visitor.visit_expr(expr); } + if let Some(pat) = pat { visitor.visit_pat(pat); } @@ -642,6 +692,7 @@ fn resolve_local<'tcx>( /// | [ ..., E&, ... ] /// | ( ..., E&, ... ) /// | {...; E&} + /// | { super let ... = E&; ... } /// | if _ { ...; E& } else { ...; E& } /// | match _ { ..., _ => E&, ... } /// | box E& @@ -678,6 +729,13 @@ fn resolve_local<'tcx>( if let Some(subexpr) = block.expr { record_rvalue_scope_if_borrow_expr(visitor, subexpr, blk_id); } + for stmt in block.stmts { + if let hir::StmtKind::Let(local) = stmt.kind + && let Some(_) = local.super_ + { + visitor.extended_super_lets.insert(local.pat.hir_id.local_id, blk_id); + } + } } hir::ExprKind::If(_, then_block, else_block) => { record_rvalue_scope_if_borrow_expr(visitor, then_block, blk_id); @@ -803,7 +861,7 @@ impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> { local_id: body.value.hir_id.local_id, data: ScopeData::Destruction, }); - resolve_local(this, None, Some(body.value)); + resolve_local(this, None, Some(body.value), false); } }) } @@ -821,7 +879,7 @@ impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> { resolve_expr(self, ex, false); } fn visit_local(&mut self, l: &'tcx LetStmt<'tcx>) { - resolve_local(self, Some(l.pat), l.init) + resolve_local(self, Some(l.pat), l.init, l.super_.is_some()); } fn visit_inline_const(&mut self, c: &'tcx hir::ConstBlock) { let body = self.tcx.hir_body(c.body); @@ -850,6 +908,7 @@ pub(crate) fn region_scope_tree(tcx: TyCtxt<'_>, def_id: DefId) -> &ScopeTree { cx: Context { parent: None, var_parent: None }, pessimistic_yield: false, fixup_scopes: vec![], + extended_super_lets: Default::default(), }; visitor.scope_tree.root_body = Some(body.value.hir_id); diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 8c0c17f7a7d6..5a3849e7afdc 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -960,12 +960,16 @@ impl<'a> State<'a> { fn print_local( &mut self, + super_: bool, init: Option<&hir::Expr<'_>>, els: Option<&hir::Block<'_>>, decl: impl Fn(&mut Self), ) { self.space_if_not_bol(); self.ibox(INDENT_UNIT); + if super_ { + self.word_nbsp("super"); + } self.word_nbsp("let"); self.ibox(INDENT_UNIT); @@ -995,7 +999,9 @@ impl<'a> State<'a> { self.maybe_print_comment(st.span.lo()); match st.kind { hir::StmtKind::Let(loc) => { - self.print_local(loc.init, loc.els, |this| this.print_local_decl(loc)); + self.print_local(loc.super_.is_some(), loc.init, loc.els, |this| { + this.print_local_decl(loc) + }); } hir::StmtKind::Item(item) => self.ann.nested(self, Nested::Item(item)), hir::StmtKind::Expr(expr) => { @@ -1488,7 +1494,7 @@ impl<'a> State<'a> { // Print `let _t = $init;`: let temp = Ident::from_str("_t"); - self.print_local(Some(init), None, |this| this.print_ident(temp)); + self.print_local(false, Some(init), None, |this| this.print_ident(temp)); self.word(";"); // Print `_t`: diff --git a/compiler/rustc_hir_typeck/src/gather_locals.rs b/compiler/rustc_hir_typeck/src/gather_locals.rs index 48fd5f1f9824..5d87e800096f 100644 --- a/compiler/rustc_hir_typeck/src/gather_locals.rs +++ b/compiler/rustc_hir_typeck/src/gather_locals.rs @@ -43,7 +43,7 @@ pub(super) struct Declaration<'a> { impl<'a> From<&'a hir::LetStmt<'a>> for Declaration<'a> { fn from(local: &'a hir::LetStmt<'a>) -> Self { - let hir::LetStmt { hir_id, pat, ty, span, init, els, source: _ } = *local; + let hir::LetStmt { hir_id, super_: _, pat, ty, span, init, els, source: _ } = *local; Declaration { hir_id, pat, ty, span, init, origin: DeclOrigin::LocalDecl { els } } } } diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 2cd09aa8959c..e00fd40ecee7 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -75,10 +75,11 @@ impl<'a> Parser<'a> { let stmt = if self.token.is_keyword(kw::Super) && self.is_keyword_ahead(1, &[kw::Let]) { self.collect_tokens(None, attrs, force_collect, |this, attrs| { + let super_span = this.token.span; this.expect_keyword(exp!(Super))?; - this.psess.gated_spans.gate(sym::super_let, this.prev_token.span); this.expect_keyword(exp!(Let))?; - let local = this.parse_local(attrs)?; // FIXME(mara): implement super let + this.psess.gated_spans.gate(sym::super_let, super_span); + let local = this.parse_local(Some(super_span), attrs)?; let trailing = Trailing::from(capture_semi && this.token == token::Semi); Ok(( this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Let(local)), @@ -89,7 +90,7 @@ impl<'a> Parser<'a> { } else if self.token.is_keyword(kw::Let) { self.collect_tokens(None, attrs, force_collect, |this, attrs| { this.expect_keyword(exp!(Let))?; - let local = this.parse_local(attrs)?; + let local = this.parse_local(None, attrs)?; let trailing = Trailing::from(capture_semi && this.token == token::Semi); Ok(( this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Let(local)), @@ -294,7 +295,7 @@ impl<'a> Parser<'a> { force_collect: ForceCollect, ) -> PResult<'a, Stmt> { let stmt = self.collect_tokens(None, attrs, force_collect, |this, attrs| { - let local = this.parse_local(attrs)?; + let local = this.parse_local(None, attrs)?; // FIXME - maybe capture semicolon in recovery? Ok(( this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Let(local)), @@ -308,8 +309,8 @@ impl<'a> Parser<'a> { } /// Parses a local variable declaration. - fn parse_local(&mut self, attrs: AttrVec) -> PResult<'a, P> { - let lo = self.prev_token.span; + fn parse_local(&mut self, super_: Option, attrs: AttrVec) -> PResult<'a, P> { + let lo = super_.unwrap_or(self.prev_token.span); if self.token.is_keyword(kw::Const) && self.look_ahead(1, |t| t.is_ident()) { self.dcx().emit_err(errors::ConstLetMutuallyExclusive { span: lo.to(self.token.span) }); @@ -411,6 +412,7 @@ impl<'a> Parser<'a> { }; let hi = if self.token == token::Semi { self.token.span } else { self.prev_token.span }; Ok(P(ast::Local { + super_, ty, pat, kind, diff --git a/tests/ui/stats/input-stats.stderr b/tests/ui/stats/input-stats.stderr index 24e389486478..b369af62f876 100644 --- a/tests/ui/stats/input-stats.stderr +++ b/tests/ui/stats/input-stats.stderr @@ -5,25 +5,25 @@ ast-stats-1 Crate 40 ( 0.6%) 1 40 ast-stats-1 GenericArgs 40 ( 0.6%) 1 40 ast-stats-1 - AngleBracketed 40 ( 0.6%) 1 ast-stats-1 ExprField 48 ( 0.7%) 1 48 -ast-stats-1 Attribute 64 ( 1.0%) 2 32 +ast-stats-1 Attribute 64 ( 0.9%) 2 32 ast-stats-1 - DocComment 32 ( 0.5%) 1 ast-stats-1 - Normal 32 ( 0.5%) 1 ast-stats-1 WherePredicate 72 ( 1.1%) 1 72 ast-stats-1 - BoundPredicate 72 ( 1.1%) 1 ast-stats-1 ForeignItem 80 ( 1.2%) 1 80 ast-stats-1 - Fn 80 ( 1.2%) 1 -ast-stats-1 Local 80 ( 1.2%) 1 80 ast-stats-1 Arm 96 ( 1.4%) 2 48 +ast-stats-1 Local 96 ( 1.4%) 1 96 ast-stats-1 FnDecl 120 ( 1.8%) 5 24 ast-stats-1 Param 160 ( 2.4%) 4 40 ast-stats-1 Stmt 160 ( 2.4%) 5 32 ast-stats-1 - Let 32 ( 0.5%) 1 ast-stats-1 - MacCall 32 ( 0.5%) 1 ast-stats-1 - Expr 96 ( 1.4%) 3 -ast-stats-1 Block 192 ( 2.9%) 6 32 +ast-stats-1 Block 192 ( 2.8%) 6 32 ast-stats-1 FieldDef 208 ( 3.1%) 2 104 ast-stats-1 Variant 208 ( 3.1%) 2 104 -ast-stats-1 AssocItem 320 ( 4.8%) 4 80 +ast-stats-1 AssocItem 320 ( 4.7%) 4 80 ast-stats-1 - Fn 160 ( 2.4%) 2 ast-stats-1 - Type 160 ( 2.4%) 2 ast-stats-1 GenericBound 352 ( 5.2%) 4 88 @@ -33,7 +33,7 @@ ast-stats-1 Pat 504 ( 7.5%) 7 72 ast-stats-1 - Struct 72 ( 1.1%) 1 ast-stats-1 - Wild 72 ( 1.1%) 1 ast-stats-1 - Ident 360 ( 5.3%) 5 -ast-stats-1 Expr 576 ( 8.6%) 8 72 +ast-stats-1 Expr 576 ( 8.5%) 8 72 ast-stats-1 - Match 72 ( 1.1%) 1 ast-stats-1 - Path 72 ( 1.1%) 1 ast-stats-1 - Struct 72 ( 1.1%) 1 @@ -41,8 +41,8 @@ ast-stats-1 - Lit 144 ( 2.1%) 2 ast-stats-1 - Block 216 ( 3.2%) 3 ast-stats-1 PathSegment 744 (11.0%) 31 24 ast-stats-1 Ty 896 (13.3%) 14 64 -ast-stats-1 - Ptr 64 ( 1.0%) 1 -ast-stats-1 - Ref 64 ( 1.0%) 1 +ast-stats-1 - Ptr 64 ( 0.9%) 1 +ast-stats-1 - Ref 64 ( 0.9%) 1 ast-stats-1 - ImplicitSelf 128 ( 1.9%) 2 ast-stats-1 - Path 640 ( 9.5%) 10 ast-stats-1 Item 1_296 (19.2%) 9 144 @@ -53,7 +53,7 @@ ast-stats-1 - Trait 144 ( 2.1%) 1 ast-stats-1 - Fn 288 ( 4.3%) 2 ast-stats-1 - Use 432 ( 6.4%) 3 ast-stats-1 ---------------------------------------------------------------- -ast-stats-1 Total 6_736 116 +ast-stats-1 Total 6_752 116 ast-stats-1 ast-stats-2 POST EXPANSION AST STATS ast-stats-2 Name Accumulated Size Count Item Size @@ -66,8 +66,8 @@ ast-stats-2 WherePredicate 72 ( 1.0%) 1 72 ast-stats-2 - BoundPredicate 72 ( 1.0%) 1 ast-stats-2 ForeignItem 80 ( 1.1%) 1 80 ast-stats-2 - Fn 80 ( 1.1%) 1 -ast-stats-2 Local 80 ( 1.1%) 1 80 ast-stats-2 Arm 96 ( 1.3%) 2 48 +ast-stats-2 Local 96 ( 1.3%) 1 96 ast-stats-2 FnDecl 120 ( 1.6%) 5 24 ast-stats-2 InlineAsm 120 ( 1.6%) 1 120 ast-stats-2 Attribute 128 ( 1.7%) 4 32 @@ -84,14 +84,14 @@ ast-stats-2 Variant 208 ( 2.8%) 2 104 ast-stats-2 AssocItem 320 ( 4.3%) 4 80 ast-stats-2 - Fn 160 ( 2.2%) 2 ast-stats-2 - Type 160 ( 2.2%) 2 -ast-stats-2 GenericBound 352 ( 4.8%) 4 88 -ast-stats-2 - Trait 352 ( 4.8%) 4 +ast-stats-2 GenericBound 352 ( 4.7%) 4 88 +ast-stats-2 - Trait 352 ( 4.7%) 4 ast-stats-2 GenericParam 480 ( 6.5%) 5 96 ast-stats-2 Pat 504 ( 6.8%) 7 72 ast-stats-2 - Struct 72 ( 1.0%) 1 ast-stats-2 - Wild 72 ( 1.0%) 1 ast-stats-2 - Ident 360 ( 4.9%) 5 -ast-stats-2 Expr 648 ( 8.8%) 9 72 +ast-stats-2 Expr 648 ( 8.7%) 9 72 ast-stats-2 - InlineAsm 72 ( 1.0%) 1 ast-stats-2 - Match 72 ( 1.0%) 1 ast-stats-2 - Path 72 ( 1.0%) 1 @@ -113,7 +113,7 @@ ast-stats-2 - Trait 144 ( 1.9%) 1 ast-stats-2 - Fn 288 ( 3.9%) 2 ast-stats-2 - Use 576 ( 7.8%) 4 ast-stats-2 ---------------------------------------------------------------- -ast-stats-2 Total 7_400 127 +ast-stats-2 Total 7_416 127 ast-stats-2 hir-stats HIR STATS hir-stats Name Accumulated Size Count Item Size @@ -126,11 +126,11 @@ hir-stats TraitItemRef 56 ( 0.6%) 2 28 hir-stats GenericArg 64 ( 0.7%) 4 16 hir-stats - Type 16 ( 0.2%) 1 hir-stats - Lifetime 48 ( 0.5%) 3 -hir-stats Local 64 ( 0.7%) 1 64 hir-stats Param 64 ( 0.7%) 2 32 hir-stats Body 72 ( 0.8%) 3 24 hir-stats ImplItemRef 72 ( 0.8%) 2 36 hir-stats InlineAsm 72 ( 0.8%) 1 72 +hir-stats Local 72 ( 0.8%) 1 72 hir-stats WherePredicate 72 ( 0.8%) 3 24 hir-stats - BoundPredicate 72 ( 0.8%) 3 hir-stats Arm 80 ( 0.9%) 2 40 @@ -143,8 +143,8 @@ hir-stats Attribute 128 ( 1.4%) 4 32 hir-stats FieldDef 128 ( 1.4%) 2 64 hir-stats GenericArgs 144 ( 1.6%) 3 48 hir-stats Variant 144 ( 1.6%) 2 72 -hir-stats GenericBound 256 ( 2.9%) 4 64 -hir-stats - Trait 256 ( 2.9%) 4 +hir-stats GenericBound 256 ( 2.8%) 4 64 +hir-stats - Trait 256 ( 2.8%) 4 hir-stats Block 288 ( 3.2%) 6 48 hir-stats Pat 360 ( 4.0%) 5 72 hir-stats - Struct 72 ( 0.8%) 1 @@ -156,7 +156,7 @@ hir-stats Ty 720 ( 8.0%) 15 48 hir-stats - Ptr 48 ( 0.5%) 1 hir-stats - Ref 48 ( 0.5%) 1 hir-stats - Path 624 ( 6.9%) 13 -hir-stats Expr 768 ( 8.6%) 12 64 +hir-stats Expr 768 ( 8.5%) 12 64 hir-stats - InlineAsm 64 ( 0.7%) 1 hir-stats - Match 64 ( 0.7%) 1 hir-stats - Path 64 ( 0.7%) 1 @@ -174,5 +174,5 @@ hir-stats - Use 352 ( 3.9%) 4 hir-stats Path 1_240 (13.8%) 31 40 hir-stats PathSegment 1_920 (21.4%) 40 48 hir-stats ---------------------------------------------------------------- -hir-stats Total 8_980 180 +hir-stats Total 8_988 180 hir-stats From f02e2786397f9954ad019ba2af7f574c1e17c904 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 2 Apr 2025 23:48:13 +0200 Subject: [PATCH 099/606] Fix typo in pretty printing super let. Co-authored-by: lcnr --- compiler/rustc_ast_pretty/src/pprust/state.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index e2dc334f7efc..5e0bfc210e4b 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1337,7 +1337,7 @@ impl<'a> State<'a> { self.space_if_not_bol(); self.ibox(INDENT_UNIT); if loc.super_.is_some() { - self.word_nbsp("let"); + self.word_nbsp("super"); } self.word_nbsp("let"); From 3e6cc7689d467fce677faed22672b592363b0f5f Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 2 Apr 2025 23:55:41 +0200 Subject: [PATCH 100/606] Boolean hate. --- .../rustc_hir_analysis/src/check/region.rs | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index 15d121758918..fedca3302f9b 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -495,13 +495,19 @@ fn resolve_expr<'tcx>( visitor.cx = prev_cx; } +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +enum LetKind { + Regular, + Super, +} + fn resolve_local<'tcx>( visitor: &mut ScopeResolutionVisitor<'tcx>, pat: Option<&'tcx hir::Pat<'tcx>>, init: Option<&'tcx hir::Expr<'tcx>>, - super_let: bool, + let_kind: LetKind, ) { - debug!("resolve_local(pat={:?}, init={:?}, super_let={:?})", pat, init, super_let); + debug!("resolve_local(pat={:?}, init={:?}, let_kind={:?})", pat, init, let_kind); // As an exception to the normal rules governing temporary // lifetimes, initializers in a let have a temporary lifetime @@ -559,7 +565,7 @@ fn resolve_local<'tcx>( // A, but the inner rvalues `a()` and `b()` have an extended lifetime // due to rule C. - if super_let { + if let_kind == LetKind::Super { if let Some(scope) = visitor.extended_super_lets.remove(&pat.unwrap().hir_id.local_id) { // This expression was lifetime-extended by a parent let binding. E.g. // @@ -861,7 +867,7 @@ impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> { local_id: body.value.hir_id.local_id, data: ScopeData::Destruction, }); - resolve_local(this, None, Some(body.value), false); + resolve_local(this, None, Some(body.value), LetKind::Regular); } }) } @@ -879,7 +885,11 @@ impl<'tcx> Visitor<'tcx> for ScopeResolutionVisitor<'tcx> { resolve_expr(self, ex, false); } fn visit_local(&mut self, l: &'tcx LetStmt<'tcx>) { - resolve_local(self, Some(l.pat), l.init, l.super_.is_some()); + let let_kind = match l.super_ { + Some(_) => LetKind::Super, + None => LetKind::Regular, + }; + resolve_local(self, Some(l.pat), l.init, let_kind); } fn visit_inline_const(&mut self, c: &'tcx hir::ConstBlock) { let body = self.tcx.hir_body(c.body); From b9babad9277fbf0b6209a3075e01f7b2dd043bf4 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Fri, 4 Apr 2025 09:38:04 +0200 Subject: [PATCH 101/606] Add feature gate test for cfg'd out super let. --- tests/ui/feature-gates/feature-gate-super-let.rs | 7 +++++++ tests/ui/feature-gates/feature-gate-super-let.stderr | 12 +++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/tests/ui/feature-gates/feature-gate-super-let.rs b/tests/ui/feature-gates/feature-gate-super-let.rs index cfe92a42669d..7be080039133 100644 --- a/tests/ui/feature-gates/feature-gate-super-let.rs +++ b/tests/ui/feature-gates/feature-gate-super-let.rs @@ -2,3 +2,10 @@ fn main() { super let a = 1; //~^ ERROR `super let` is experimental } + +// Check that it also isn't accepted in cfg'd out code. +#[cfg(any())] +fn a() { + super let a = 1; + //~^ ERROR `super let` is experimental +} diff --git a/tests/ui/feature-gates/feature-gate-super-let.stderr b/tests/ui/feature-gates/feature-gate-super-let.stderr index a64e1b374f9c..4d088594f6df 100644 --- a/tests/ui/feature-gates/feature-gate-super-let.stderr +++ b/tests/ui/feature-gates/feature-gate-super-let.stderr @@ -8,6 +8,16 @@ LL | super let a = 1; = help: add `#![feature(super_let)]` 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 +error[E0658]: `super let` is experimental + --> $DIR/feature-gate-super-let.rs:9:5 + | +LL | super let a = 1; + | ^^^^^ + | + = note: see issue #139076 for more information + = help: add `#![feature(super_let)]` 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 2 previous errors For more information about this error, try `rustc --explain E0658`. From 6c3417dd15cb560a860ddea063193c68b5b47b87 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Fri, 4 Apr 2025 11:16:32 +0200 Subject: [PATCH 102/606] fixup! Implement `super let`. --- compiler/rustc_feature/src/unstable.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 710e129b609f..7647f8e4b236 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -630,7 +630,7 @@ declare_features! ( /// Allows string patterns to dereference values to match them. (unstable, string_deref_patterns, "1.67.0", Some(87121)), /// Allows `super let` statements. - (incomplete, super_let, "CURRENT_RUSTC_VERSION", Some(139076)), + (unstable, super_let, "CURRENT_RUSTC_VERSION", Some(139076)), /// Allows subtrait items to shadow supertrait items. (unstable, supertrait_item_shadowing, "1.86.0", Some(89151)), /// Allows using `#[thread_local]` on `static` items. From 109edab245e72c876467938d46bd0ad65aaeee0b Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Thu, 3 Apr 2025 13:04:41 +0000 Subject: [PATCH 103/606] Allow GVN to produce places and not just locals. --- compiler/rustc_mir_transform/src/gvn.rs | 66 +++++++++++-------- .../const_prop/address_of_pair.fn0.GVN.diff | 6 +- ...ng_operand.test.GVN.32bit.panic-abort.diff | 8 +-- ...g_operand.test.GVN.32bit.panic-unwind.diff | 8 +-- ...ng_operand.test.GVN.64bit.panic-abort.diff | 8 +-- ...g_operand.test.GVN.64bit.panic-unwind.diff | 8 +-- ...ust_change_both_sides.GVN.panic-abort.diff | 3 +- ...st_change_both_sides.GVN.panic-unwind.diff | 3 +- tests/mir-opt/gvn.rs | 2 +- ...ompare_constant_index.GVN.panic-abort.diff | 58 ++++++++++++++++ ...mpare_constant_index.GVN.panic-unwind.diff | 58 ++++++++++++++++ tests/mir-opt/gvn_copy_constant_projection.rs | 18 +++++ ...y.run2-{closure#0}.Inline.panic-abort.diff | 4 +- ....run2-{closure#0}.Inline.panic-unwind.diff | 4 +- .../derived_ord.demo_le.PreCodegen.after.mir | 3 + ...e_ord.demo_ge_partial.PreCodegen.after.mir | 2 + ...ple_ord.demo_le_total.PreCodegen.after.mir | 2 + 17 files changed, 203 insertions(+), 58 deletions(-) create mode 100644 tests/mir-opt/gvn_copy_constant_projection.compare_constant_index.GVN.panic-abort.diff create mode 100644 tests/mir-opt/gvn_copy_constant_projection.compare_constant_index.GVN.panic-unwind.diff create mode 100644 tests/mir-opt/gvn_copy_constant_projection.rs diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 68bc0ffce6b5..a0fb20d18449 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -980,27 +980,15 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { } } - let tcx = self.tcx; - let mut projection = SmallVec::<[PlaceElem<'tcx>; 1]>::new(); - loop { - if let Some(local) = self.try_as_local(copy_from_local_value, location) { - projection.reverse(); - let place = Place { local, projection: tcx.mk_place_elems(projection.as_slice()) }; - if rvalue.ty(self.local_decls, tcx) == place.ty(self.local_decls, tcx).ty { - self.reused_locals.insert(local); - *rvalue = Rvalue::Use(Operand::Copy(place)); - return Some(copy_from_value); - } - return None; - } else if let Value::Projection(pointer, proj) = *self.get(copy_from_local_value) - && let Some(proj) = self.try_as_place_elem(proj, location) - { - projection.push(proj); - copy_from_local_value = pointer; - } else { - return None; + if let Some(place) = self.try_as_place(copy_from_local_value, location) { + if rvalue.ty(self.local_decls, self.tcx) == place.ty(self.local_decls, self.tcx).ty { + self.reused_locals.insert(place.local); + *rvalue = Rvalue::Use(Operand::Copy(place)); + return Some(copy_from_local_value); } } + + None } fn simplify_aggregate( @@ -1672,14 +1660,14 @@ fn op_to_prop_const<'tcx>( } impl<'tcx> VnState<'_, 'tcx> { - /// If either [`Self::try_as_constant`] as [`Self::try_as_local`] succeeds, + /// If either [`Self::try_as_constant`] as [`Self::try_as_place`] succeeds, /// returns that result as an [`Operand`]. fn try_as_operand(&mut self, index: VnIndex, location: Location) -> Option> { if let Some(const_) = self.try_as_constant(index) { Some(Operand::Constant(Box::new(const_))) - } else if let Some(local) = self.try_as_local(index, location) { - self.reused_locals.insert(local); - Some(Operand::Copy(local.into())) + } else if let Some(place) = self.try_as_place(index, location) { + self.reused_locals.insert(place.local); + Some(Operand::Copy(place)) } else { None } @@ -1712,6 +1700,29 @@ impl<'tcx> VnState<'_, 'tcx> { Some(ConstOperand { span: DUMMY_SP, user_ty: None, const_ }) } + /// Construct a place which holds the same value as `index` and for which all locals strictly + /// dominate `loc`. If you used this place, add its base local to `reused_locals` to remove + /// storage statements. + #[instrument(level = "trace", skip(self), ret)] + fn try_as_place(&mut self, mut index: VnIndex, loc: Location) -> Option> { + let mut projection = SmallVec::<[PlaceElem<'tcx>; 1]>::new(); + loop { + if let Some(local) = self.try_as_local(index, loc) { + projection.reverse(); + let place = + Place { local, projection: self.tcx.mk_place_elems(projection.as_slice()) }; + return Some(place); + } else if let Value::Projection(pointer, proj) = *self.get(index) + && let Some(proj) = self.try_as_place_elem(proj, loc) + { + projection.push(proj); + index = pointer; + } else { + return None; + } + } + } + /// If there is a local which is assigned `index`, and its assignment strictly dominates `loc`, /// return it. If you used this local, add it to `reused_locals` to remove storage statements. fn try_as_local(&mut self, index: VnIndex, loc: Location) -> Option { @@ -1762,11 +1773,12 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> { if let Some(value) = value { if let Some(const_) = self.try_as_constant(value) { *rvalue = Rvalue::Use(Operand::Constant(Box::new(const_))); - } else if let Some(local) = self.try_as_local(value, location) - && *rvalue != Rvalue::Use(Operand::Move(local.into())) + } else if let Some(place) = self.try_as_place(value, location) + && *rvalue != Rvalue::Use(Operand::Move(place)) + && *rvalue != Rvalue::Use(Operand::Copy(place)) { - *rvalue = Rvalue::Use(Operand::Copy(local.into())); - self.reused_locals.insert(local); + *rvalue = Rvalue::Use(Operand::Copy(place)); + self.reused_locals.insert(place.local); } } } diff --git a/tests/mir-opt/const_prop/address_of_pair.fn0.GVN.diff b/tests/mir-opt/const_prop/address_of_pair.fn0.GVN.diff index e33185f17bcf..c23afae829f4 100644 --- a/tests/mir-opt/const_prop/address_of_pair.fn0.GVN.diff +++ b/tests/mir-opt/const_prop/address_of_pair.fn0.GVN.diff @@ -31,15 +31,13 @@ (*_3) = const true; _4 = const (); StorageDead(_4); -- StorageLive(_5); -+ nop; + StorageLive(_5); StorageLive(_6); _6 = copy (_2.1: bool); _5 = Not(move _6); StorageDead(_6); _0 = copy _5; -- StorageDead(_5); -+ nop; + StorageDead(_5); StorageDead(_3); StorageDead(_2); return; diff --git a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff index 37dd14e6c896..35eb4fbd106a 100644 --- a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff @@ -69,8 +69,7 @@ bb0: { StorageLive(_1); -- StorageLive(_2); -+ nop; + StorageLive(_2); StorageLive(_3); StorageLive(_11); StorageLive(_12); @@ -119,8 +118,7 @@ StorageDead(_11); _2 = &_3; _1 = copy _2; -- StorageDead(_2); -+ nop; + StorageDead(_2); StorageLive(_4); - _9 = deref_copy _3; + _9 = copy _3; @@ -141,7 +139,7 @@ StorageLive(_8); _8 = copy _5; - _7 = copy _8 as *mut () (PtrToPtr); -+ _7 = copy _5 as *mut () (PtrToPtr); ++ _7 = copy ((_9.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *mut () (Transmute); StorageDead(_8); StorageDead(_7); - StorageDead(_5); diff --git a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-unwind.diff b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-unwind.diff index 6bac68059431..b2085afb7137 100644 --- a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-unwind.diff @@ -35,8 +35,7 @@ bb0: { StorageLive(_1); -- StorageLive(_2); -+ nop; + StorageLive(_2); StorageLive(_3); _3 = Box::<()>::new(const ()) -> [return: bb1, unwind continue]; } @@ -44,8 +43,7 @@ bb1: { _2 = &_3; _1 = copy _2; -- StorageDead(_2); -+ nop; + StorageDead(_2); StorageLive(_4); - _9 = deref_copy _3; + _9 = copy _3; @@ -66,7 +64,7 @@ StorageLive(_8); _8 = copy _5; - _7 = copy _8 as *mut () (PtrToPtr); -+ _7 = copy _5 as *mut () (PtrToPtr); ++ _7 = copy ((_9.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *mut () (Transmute); StorageDead(_8); StorageDead(_7); - StorageDead(_5); diff --git a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff index 1cf0f6de011e..4427a5fcc7de 100644 --- a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff @@ -69,8 +69,7 @@ bb0: { StorageLive(_1); -- StorageLive(_2); -+ nop; + StorageLive(_2); StorageLive(_3); StorageLive(_11); StorageLive(_12); @@ -119,8 +118,7 @@ StorageDead(_11); _2 = &_3; _1 = copy _2; -- StorageDead(_2); -+ nop; + StorageDead(_2); StorageLive(_4); - _9 = deref_copy _3; + _9 = copy _3; @@ -141,7 +139,7 @@ StorageLive(_8); _8 = copy _5; - _7 = copy _8 as *mut () (PtrToPtr); -+ _7 = copy _5 as *mut () (PtrToPtr); ++ _7 = copy ((_9.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *mut () (Transmute); StorageDead(_8); StorageDead(_7); - StorageDead(_5); diff --git a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-unwind.diff b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-unwind.diff index 6bac68059431..b2085afb7137 100644 --- a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-unwind.diff @@ -35,8 +35,7 @@ bb0: { StorageLive(_1); -- StorageLive(_2); -+ nop; + StorageLive(_2); StorageLive(_3); _3 = Box::<()>::new(const ()) -> [return: bb1, unwind continue]; } @@ -44,8 +43,7 @@ bb1: { _2 = &_3; _1 = copy _2; -- StorageDead(_2); -+ nop; + StorageDead(_2); StorageLive(_4); - _9 = deref_copy _3; + _9 = copy _3; @@ -66,7 +64,7 @@ StorageLive(_8); _8 = copy _5; - _7 = copy _8 as *mut () (PtrToPtr); -+ _7 = copy _5 as *mut () (PtrToPtr); ++ _7 = copy ((_9.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *mut () (Transmute); StorageDead(_8); StorageDead(_7); - StorageDead(_5); diff --git a/tests/mir-opt/gvn.remove_casts_must_change_both_sides.GVN.panic-abort.diff b/tests/mir-opt/gvn.remove_casts_must_change_both_sides.GVN.panic-abort.diff index 98cb34810bc0..545a1e350b8f 100644 --- a/tests/mir-opt/gvn.remove_casts_must_change_both_sides.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.remove_casts_must_change_both_sides.GVN.panic-abort.diff @@ -9,7 +9,8 @@ bb0: { _3 = copy (*_1) as *const u8 (PtrToPtr); _4 = copy _2 as *const u8 (PtrToPtr); - _0 = Eq(copy _3, copy _4); +- _0 = Eq(copy _3, copy _4); ++ _0 = Eq(copy (*_1), copy _2); return; } } diff --git a/tests/mir-opt/gvn.remove_casts_must_change_both_sides.GVN.panic-unwind.diff b/tests/mir-opt/gvn.remove_casts_must_change_both_sides.GVN.panic-unwind.diff index 98cb34810bc0..545a1e350b8f 100644 --- a/tests/mir-opt/gvn.remove_casts_must_change_both_sides.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.remove_casts_must_change_both_sides.GVN.panic-unwind.diff @@ -9,7 +9,8 @@ bb0: { _3 = copy (*_1) as *const u8 (PtrToPtr); _4 = copy _2 as *const u8 (PtrToPtr); - _0 = Eq(copy _3, copy _4); +- _0 = Eq(copy _3, copy _4); ++ _0 = Eq(copy (*_1), copy _2); return; } } diff --git a/tests/mir-opt/gvn.rs b/tests/mir-opt/gvn.rs index 6ef320c90de1..fa263091a81d 100644 --- a/tests/mir-opt/gvn.rs +++ b/tests/mir-opt/gvn.rs @@ -1048,7 +1048,7 @@ fn remove_casts_must_change_both_sides(mut_a: &*mut u8, mut_b: *mut u8) -> bool let a = *mut_a as *const u8; // CHECK: [[B:_.+]] = copy _2 as *const u8 (PtrToPtr); let b = mut_b as *const u8; - // CHECK: _0 = Eq(copy [[A]], copy [[B]]); + // CHECK: _0 = Eq(copy (*_1), copy _2); RET = a == b; Return() } diff --git a/tests/mir-opt/gvn_copy_constant_projection.compare_constant_index.GVN.panic-abort.diff b/tests/mir-opt/gvn_copy_constant_projection.compare_constant_index.GVN.panic-abort.diff new file mode 100644 index 000000000000..e2e55304921b --- /dev/null +++ b/tests/mir-opt/gvn_copy_constant_projection.compare_constant_index.GVN.panic-abort.diff @@ -0,0 +1,58 @@ +- // MIR for `compare_constant_index` before GVN ++ // MIR for `compare_constant_index` after GVN + + fn compare_constant_index(_1: [i32; 1], _2: [i32; 1]) -> std::cmp::Ordering { + debug x => _1; + debug y => _2; + let mut _0: std::cmp::Ordering; + let _3: &i32; + let _4: usize; + let mut _5: bool; + let _6: &i32; + let _7: usize; + let mut _8: bool; + scope 1 (inlined std::cmp::impls::::cmp) { + let mut _9: i32; + let mut _10: i32; + } + + bb0: { +- StorageLive(_4); ++ nop; + _4 = const 0_usize; +- _5 = Lt(copy _4, const 1_usize); +- assert(move _5, "index out of bounds: the length is {} but the index is {}", const 1_usize, copy _4) -> [success: bb1, unwind unreachable]; ++ _5 = const true; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 1_usize, const 0_usize) -> [success: bb1, unwind unreachable]; + } + + bb1: { +- _3 = &_1[_4]; ++ _3 = &_1[0 of 1]; + StorageLive(_7); + _7 = const 0_usize; +- _8 = Lt(copy _7, const 1_usize); +- assert(move _8, "index out of bounds: the length is {} but the index is {}", const 1_usize, copy _7) -> [success: bb2, unwind unreachable]; ++ _8 = const true; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 1_usize, const 0_usize) -> [success: bb2, unwind unreachable]; + } + + bb2: { +- _6 = &_2[_7]; ++ _6 = &_2[0 of 1]; + StorageLive(_9); +- _9 = copy (*_3); ++ _9 = copy _1[0 of 1]; + StorageLive(_10); +- _10 = copy (*_6); ++ _10 = copy _2[0 of 1]; + _0 = Cmp(move _9, move _10); + StorageDead(_10); + StorageDead(_9); + StorageDead(_7); +- StorageDead(_4); ++ nop; + return; + } + } + diff --git a/tests/mir-opt/gvn_copy_constant_projection.compare_constant_index.GVN.panic-unwind.diff b/tests/mir-opt/gvn_copy_constant_projection.compare_constant_index.GVN.panic-unwind.diff new file mode 100644 index 000000000000..60611146a0ee --- /dev/null +++ b/tests/mir-opt/gvn_copy_constant_projection.compare_constant_index.GVN.panic-unwind.diff @@ -0,0 +1,58 @@ +- // MIR for `compare_constant_index` before GVN ++ // MIR for `compare_constant_index` after GVN + + fn compare_constant_index(_1: [i32; 1], _2: [i32; 1]) -> std::cmp::Ordering { + debug x => _1; + debug y => _2; + let mut _0: std::cmp::Ordering; + let _3: &i32; + let _4: usize; + let mut _5: bool; + let _6: &i32; + let _7: usize; + let mut _8: bool; + scope 1 (inlined std::cmp::impls::::cmp) { + let mut _9: i32; + let mut _10: i32; + } + + bb0: { +- StorageLive(_4); ++ nop; + _4 = const 0_usize; +- _5 = Lt(copy _4, const 1_usize); +- assert(move _5, "index out of bounds: the length is {} but the index is {}", const 1_usize, copy _4) -> [success: bb1, unwind continue]; ++ _5 = const true; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 1_usize, const 0_usize) -> [success: bb1, unwind continue]; + } + + bb1: { +- _3 = &_1[_4]; ++ _3 = &_1[0 of 1]; + StorageLive(_7); + _7 = const 0_usize; +- _8 = Lt(copy _7, const 1_usize); +- assert(move _8, "index out of bounds: the length is {} but the index is {}", const 1_usize, copy _7) -> [success: bb2, unwind continue]; ++ _8 = const true; ++ assert(const true, "index out of bounds: the length is {} but the index is {}", const 1_usize, const 0_usize) -> [success: bb2, unwind continue]; + } + + bb2: { +- _6 = &_2[_7]; ++ _6 = &_2[0 of 1]; + StorageLive(_9); +- _9 = copy (*_3); ++ _9 = copy _1[0 of 1]; + StorageLive(_10); +- _10 = copy (*_6); ++ _10 = copy _2[0 of 1]; + _0 = Cmp(move _9, move _10); + StorageDead(_10); + StorageDead(_9); + StorageDead(_7); +- StorageDead(_4); ++ nop; + return; + } + } + diff --git a/tests/mir-opt/gvn_copy_constant_projection.rs b/tests/mir-opt/gvn_copy_constant_projection.rs new file mode 100644 index 000000000000..a08ae0ac7c97 --- /dev/null +++ b/tests/mir-opt/gvn_copy_constant_projection.rs @@ -0,0 +1,18 @@ +// EMIT_MIR_FOR_EACH_PANIC_STRATEGY + +use std::cmp::Ordering; +fn compare_constant_index(x: [i32; 1], y: [i32; 1]) -> Ordering { + // CHECK-LABEL: fn compare_constant_index( + // CHECK-NOT: (*{{_.*}}); + // CHECK: [[lhs:_.*]] = copy _1[0 of 1]; + // CHECK-NOT: (*{{_.*}}); + // CHECK: [[rhs:_.*]] = copy _2[0 of 1]; + // CHECK: _0 = Cmp(move [[lhs]], move [[rhs]]); + Ord::cmp(&x[0], &y[0]) +} + +fn main() { + compare_constant_index([1], [2]); +} + +// EMIT_MIR gvn_copy_constant_projection.compare_constant_index.GVN.diff diff --git a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff index eb97af1e2845..e49d7cea28e5 100644 --- a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff +++ b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff @@ -229,7 +229,6 @@ + StorageDead(_24); + StorageLive(_45); + StorageLive(_46); -+ StorageLive(_49); + StorageLive(_51); + StorageLive(_42); + StorageLive(_43); @@ -243,9 +242,11 @@ + _47 = Pin::<&mut std::future::Ready<()>> { __pointer: copy _45 }; + StorageDead(_47); + _44 = &mut ((*_45).0: std::option::Option<()>); ++ StorageLive(_49); + _49 = Option::<()>::None; + _43 = copy ((*_45).0: std::option::Option<()>); + ((*_45).0: std::option::Option<()>) = copy _49; ++ StorageDead(_49); + StorageDead(_44); + StorageLive(_50); + _50 = discriminant(_43); @@ -322,7 +323,6 @@ + _18 = Poll::<()>::Ready(move _42); + StorageDead(_42); + StorageDead(_51); -+ StorageDead(_49); + StorageDead(_46); + StorageDead(_45); + StorageDead(_22); diff --git a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff index eb757e091145..e7aed556f2d7 100644 --- a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff @@ -246,7 +246,6 @@ + StorageDead(_24); + StorageLive(_47); + StorageLive(_48); -+ StorageLive(_51); + StorageLive(_53); + StorageLive(_44); + StorageLive(_45); @@ -260,9 +259,11 @@ + _49 = Pin::<&mut std::future::Ready<()>> { __pointer: copy _47 }; + StorageDead(_49); + _46 = &mut ((*_47).0: std::option::Option<()>); ++ StorageLive(_51); + _51 = Option::<()>::None; + _45 = copy ((*_47).0: std::option::Option<()>); + ((*_47).0: std::option::Option<()>) = copy _51; ++ StorageDead(_51); + StorageDead(_46); + StorageLive(_52); + _52 = discriminant(_45); @@ -363,7 +364,6 @@ + _18 = Poll::<()>::Ready(move _44); + StorageDead(_44); + StorageDead(_53); -+ StorageDead(_51); + StorageDead(_48); + StorageDead(_47); + StorageDead(_22); diff --git a/tests/mir-opt/pre-codegen/derived_ord.demo_le.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/derived_ord.demo_le.PreCodegen.after.mir index 49314a64c3fc..8746cb089916 100644 --- a/tests/mir-opt/pre-codegen/derived_ord.demo_le.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/derived_ord.demo_le.PreCodegen.after.mir @@ -40,6 +40,7 @@ fn demo_le(_1: &MultiField, _2: &MultiField) -> bool { StorageLive(_12); StorageLive(_11); StorageLive(_5); + StorageLive(_6); StorageLive(_7); StorageLive(_3); _3 = copy ((*_1).0: char); @@ -65,6 +66,7 @@ fn demo_le(_1: &MultiField, _2: &MultiField) -> bool { _11 = Option::::Some(move _10); StorageDead(_10); StorageDead(_7); + StorageDead(_6); StorageDead(_5); goto -> bb3; } @@ -72,6 +74,7 @@ fn demo_le(_1: &MultiField, _2: &MultiField) -> bool { bb2: { _11 = copy _6; StorageDead(_7); + StorageDead(_6); StorageDead(_5); goto -> bb3; } diff --git a/tests/mir-opt/pre-codegen/tuple_ord.demo_ge_partial.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/tuple_ord.demo_ge_partial.PreCodegen.after.mir index dd2eebc8f4a1..c4d0e318b58d 100644 --- a/tests/mir-opt/pre-codegen/tuple_ord.demo_ge_partial.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/tuple_ord.demo_ge_partial.PreCodegen.after.mir @@ -44,8 +44,10 @@ fn demo_ge_partial(_1: &(f32, f32), _2: &(f32, f32)) -> bool { StorageDead(_5); StorageDead(_4); StorageDead(_3); + StorageLive(_8); _8 = copy ((_7 as Break).0: bool); _0 = copy _8; + StorageDead(_8); goto -> bb3; } diff --git a/tests/mir-opt/pre-codegen/tuple_ord.demo_le_total.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/tuple_ord.demo_le_total.PreCodegen.after.mir index ea1d164cefaf..44df8b279935 100644 --- a/tests/mir-opt/pre-codegen/tuple_ord.demo_le_total.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/tuple_ord.demo_le_total.PreCodegen.after.mir @@ -44,8 +44,10 @@ fn demo_le_total(_1: &(u16, i16), _2: &(u16, i16)) -> bool { StorageDead(_5); StorageDead(_4); StorageDead(_3); + StorageLive(_8); _8 = copy ((_7 as Break).0: bool); _0 = copy _8; + StorageDead(_8); goto -> bb3; } From d9caf840e1b82d24238b516d714f3933a96ff04a Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Fri, 4 Apr 2025 10:27:50 +0000 Subject: [PATCH 104/606] Only introduce stable projections. --- compiler/rustc_mir_transform/src/gvn.rs | 16 ++++++++++++---- ...s_must_change_both_sides.GVN.panic-abort.diff | 3 +-- ..._must_change_both_sides.GVN.panic-unwind.diff | 3 +-- tests/mir-opt/gvn.rs | 2 +- 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index a0fb20d18449..8b8d1efbbd2e 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -980,7 +980,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { } } - if let Some(place) = self.try_as_place(copy_from_local_value, location) { + // Allow introducing places with non-constant offsets, as those are still better than + // reconstructing an aggregate. + if let Some(place) = self.try_as_place(copy_from_local_value, location, true) { if rvalue.ty(self.local_decls, self.tcx) == place.ty(self.local_decls, self.tcx).ty { self.reused_locals.insert(place.local); *rvalue = Rvalue::Use(Operand::Copy(place)); @@ -1665,7 +1667,7 @@ impl<'tcx> VnState<'_, 'tcx> { fn try_as_operand(&mut self, index: VnIndex, location: Location) -> Option> { if let Some(const_) = self.try_as_constant(index) { Some(Operand::Constant(Box::new(const_))) - } else if let Some(place) = self.try_as_place(index, location) { + } else if let Some(place) = self.try_as_place(index, location, false) { self.reused_locals.insert(place.local); Some(Operand::Copy(place)) } else { @@ -1704,7 +1706,12 @@ impl<'tcx> VnState<'_, 'tcx> { /// dominate `loc`. If you used this place, add its base local to `reused_locals` to remove /// storage statements. #[instrument(level = "trace", skip(self), ret)] - fn try_as_place(&mut self, mut index: VnIndex, loc: Location) -> Option> { + fn try_as_place( + &mut self, + mut index: VnIndex, + loc: Location, + allow_complex_projection: bool, + ) -> Option> { let mut projection = SmallVec::<[PlaceElem<'tcx>; 1]>::new(); loop { if let Some(local) = self.try_as_local(index, loc) { @@ -1713,6 +1720,7 @@ impl<'tcx> VnState<'_, 'tcx> { Place { local, projection: self.tcx.mk_place_elems(projection.as_slice()) }; return Some(place); } else if let Value::Projection(pointer, proj) = *self.get(index) + && (allow_complex_projection || proj.is_stable_offset()) && let Some(proj) = self.try_as_place_elem(proj, loc) { projection.push(proj); @@ -1773,7 +1781,7 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> { if let Some(value) = value { if let Some(const_) = self.try_as_constant(value) { *rvalue = Rvalue::Use(Operand::Constant(Box::new(const_))); - } else if let Some(place) = self.try_as_place(value, location) + } else if let Some(place) = self.try_as_place(value, location, false) && *rvalue != Rvalue::Use(Operand::Move(place)) && *rvalue != Rvalue::Use(Operand::Copy(place)) { diff --git a/tests/mir-opt/gvn.remove_casts_must_change_both_sides.GVN.panic-abort.diff b/tests/mir-opt/gvn.remove_casts_must_change_both_sides.GVN.panic-abort.diff index 545a1e350b8f..98cb34810bc0 100644 --- a/tests/mir-opt/gvn.remove_casts_must_change_both_sides.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.remove_casts_must_change_both_sides.GVN.panic-abort.diff @@ -9,8 +9,7 @@ bb0: { _3 = copy (*_1) as *const u8 (PtrToPtr); _4 = copy _2 as *const u8 (PtrToPtr); -- _0 = Eq(copy _3, copy _4); -+ _0 = Eq(copy (*_1), copy _2); + _0 = Eq(copy _3, copy _4); return; } } diff --git a/tests/mir-opt/gvn.remove_casts_must_change_both_sides.GVN.panic-unwind.diff b/tests/mir-opt/gvn.remove_casts_must_change_both_sides.GVN.panic-unwind.diff index 545a1e350b8f..98cb34810bc0 100644 --- a/tests/mir-opt/gvn.remove_casts_must_change_both_sides.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.remove_casts_must_change_both_sides.GVN.panic-unwind.diff @@ -9,8 +9,7 @@ bb0: { _3 = copy (*_1) as *const u8 (PtrToPtr); _4 = copy _2 as *const u8 (PtrToPtr); -- _0 = Eq(copy _3, copy _4); -+ _0 = Eq(copy (*_1), copy _2); + _0 = Eq(copy _3, copy _4); return; } } diff --git a/tests/mir-opt/gvn.rs b/tests/mir-opt/gvn.rs index fa263091a81d..6ef320c90de1 100644 --- a/tests/mir-opt/gvn.rs +++ b/tests/mir-opt/gvn.rs @@ -1048,7 +1048,7 @@ fn remove_casts_must_change_both_sides(mut_a: &*mut u8, mut_b: *mut u8) -> bool let a = *mut_a as *const u8; // CHECK: [[B:_.+]] = copy _2 as *const u8 (PtrToPtr); let b = mut_b as *const u8; - // CHECK: _0 = Eq(copy (*_1), copy _2); + // CHECK: _0 = Eq(copy [[A]], copy [[B]]); RET = a == b; Return() } From d0591827ddc8268b0f248dcb02c2e20a737229aa Mon Sep 17 00:00:00 2001 From: morine0122 Date: Sat, 22 Mar 2025 21:57:45 +0900 Subject: [PATCH 105/606] Make the compiler suggest actual paths instead of visible paths if the visible paths are through any doc hidden path. --- compiler/rustc_hir_typeck/src/method/suggest.rs | 9 +++++++-- compiler/rustc_middle/src/ty/print/pretty.rs | 7 +++++++ ...ggest-trait-reexported-as-not-doc-visible-a.rs | 5 +++++ ...ggest-trait-reexported-as-not-doc-visible-b.rs | 14 ++++++++++++++ ...suggest-trait-reexported-as-not-doc-visible.rs | 11 +++++++++++ ...est-trait-reexported-as-not-doc-visible.stderr | 15 +++++++++++++++ 6 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 tests/ui/typeck/auxiliary/suggest-trait-reexported-as-not-doc-visible-a.rs create mode 100644 tests/ui/typeck/auxiliary/suggest-trait-reexported-as-not-doc-visible-b.rs create mode 100644 tests/ui/typeck/suggest-trait-reexported-as-not-doc-visible.rs create mode 100644 tests/ui/typeck/suggest-trait-reexported-as-not-doc-visible.stderr diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 246b23f11b68..8be4d55542d0 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -25,6 +25,7 @@ use rustc_middle::bug; use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams, simplify_type}; use rustc_middle::ty::print::{ PrintTraitRefExt as _, with_crate_prefix, with_forced_trimmed_paths, + with_no_visible_paths_if_doc_hidden, }; use rustc_middle::ty::{self, GenericArgKind, IsSuggestable, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::def_id::DefIdSet; @@ -3328,7 +3329,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let path_strings = candidates.iter().map(|trait_did| { format!( "{prefix}{}{postfix}\n", - with_crate_prefix!(self.tcx.def_path_str(*trait_did)), + with_no_visible_paths_if_doc_hidden!(with_crate_prefix!( + self.tcx.def_path_str(*trait_did) + )), ) }); @@ -3336,7 +3339,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let parent_did = parent_map.get(trait_did).unwrap(); format!( "{prefix}{}::*{postfix} // trait {}\n", - with_crate_prefix!(self.tcx.def_path_str(*parent_did)), + with_no_visible_paths_if_doc_hidden!(with_crate_prefix!( + self.tcx.def_path_str(*parent_did) + )), self.tcx.item_name(*trait_did), ) }); diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 3281cb4135a0..c914f7cc8821 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -63,6 +63,7 @@ thread_local! { static FORCE_TRIMMED_PATH: Cell = const { Cell::new(false) }; static REDUCED_QUERIES: Cell = const { Cell::new(false) }; static NO_VISIBLE_PATH: Cell = const { Cell::new(false) }; + static NO_VISIBLE_PATH_IF_DOC_HIDDEN: Cell = const { Cell::new(false) }; static RTN_MODE: Cell = const { Cell::new(RtnMode::ForDiagnostic) }; } @@ -134,6 +135,8 @@ define_helper!( /// Prevent selection of visible paths. `Display` impl of DefId will prefer /// visible (public) reexports of types as paths. fn with_no_visible_paths(NoVisibleGuard, NO_VISIBLE_PATH); + /// Prevent selection of visible paths if the paths are through a doc hidden path. + fn with_no_visible_paths_if_doc_hidden(NoVisibleIfDocHiddenGuard, NO_VISIBLE_PATH_IF_DOC_HIDDEN); ); #[must_use] @@ -569,6 +572,10 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { return Ok(false); }; + if self.tcx().is_doc_hidden(visible_parent) && with_no_visible_paths_if_doc_hidden() { + return Ok(false); + } + let actual_parent = self.tcx().opt_parent(def_id); debug!( "try_print_visible_def_path: visible_parent={:?} actual_parent={:?}", diff --git a/tests/ui/typeck/auxiliary/suggest-trait-reexported-as-not-doc-visible-a.rs b/tests/ui/typeck/auxiliary/suggest-trait-reexported-as-not-doc-visible-a.rs new file mode 100644 index 000000000000..87d83663626b --- /dev/null +++ b/tests/ui/typeck/auxiliary/suggest-trait-reexported-as-not-doc-visible-a.rs @@ -0,0 +1,5 @@ +//@ edition: 2021 + +pub trait Foo { + fn foo(); +} diff --git a/tests/ui/typeck/auxiliary/suggest-trait-reexported-as-not-doc-visible-b.rs b/tests/ui/typeck/auxiliary/suggest-trait-reexported-as-not-doc-visible-b.rs new file mode 100644 index 000000000000..9e90e0f0b356 --- /dev/null +++ b/tests/ui/typeck/auxiliary/suggest-trait-reexported-as-not-doc-visible-b.rs @@ -0,0 +1,14 @@ +// ignore-tidy-linelength +//@ edition: 2021 +//@ aux-crate:suggest_trait_reexported_as_not_doc_visible_a=suggest-trait-reexported-as-not-doc-visible-a.rs + +pub struct Bar; + +impl __DocHidden::Foo for Bar { + fn foo() {} +} + +#[doc(hidden)] +pub mod __DocHidden { + pub use suggest_trait_reexported_as_not_doc_visible_a::Foo; +} diff --git a/tests/ui/typeck/suggest-trait-reexported-as-not-doc-visible.rs b/tests/ui/typeck/suggest-trait-reexported-as-not-doc-visible.rs new file mode 100644 index 000000000000..3cb775e85ac6 --- /dev/null +++ b/tests/ui/typeck/suggest-trait-reexported-as-not-doc-visible.rs @@ -0,0 +1,11 @@ +// ignore-tidy-linelength +//@ edition: 2021 +//@ aux-crate:suggest_trait_reexported_as_not_doc_visible_a=suggest-trait-reexported-as-not-doc-visible-a.rs +//@ aux-crate:suggest_trait_reexported_as_not_doc_visible_b=suggest-trait-reexported-as-not-doc-visible-b.rs + +use suggest_trait_reexported_as_not_doc_visible_b::Bar; + +fn main() { + Bar::foo(); + //~^ ERROR: no function or associated item named `foo` found for struct `Bar` in the current scope [E0599] +} diff --git a/tests/ui/typeck/suggest-trait-reexported-as-not-doc-visible.stderr b/tests/ui/typeck/suggest-trait-reexported-as-not-doc-visible.stderr new file mode 100644 index 000000000000..9128ee684446 --- /dev/null +++ b/tests/ui/typeck/suggest-trait-reexported-as-not-doc-visible.stderr @@ -0,0 +1,15 @@ +error[E0599]: no function or associated item named `foo` found for struct `Bar` in the current scope + --> $DIR/suggest-trait-reexported-as-not-doc-visible.rs:9:10 + | +LL | Bar::foo(); + | ^^^ function or associated item not found in `Bar` + | + = help: items from traits can only be used if the trait is in scope +help: trait `Foo` which provides `foo` is implemented but not in scope; perhaps you want to import it + | +LL + use suggest_trait_reexported_as_not_doc_visible_a::Foo; + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0599`. From bd779df31338a3d6443151f79da43c5d88c03e10 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 4 Apr 2025 13:51:47 +0200 Subject: [PATCH 106/606] semver-bump some dependencies --- src/tools/miri/Cargo.lock | 65 ++++++--- src/tools/miri/Cargo.toml | 6 +- src/tools/miri/cargo-miri/Cargo.lock | 118 ++++------------- src/tools/miri/cargo-miri/Cargo.toml | 4 +- src/tools/miri/miri-script/Cargo.lock | 139 +++++--------------- src/tools/miri/miri-script/Cargo.toml | 6 +- src/tools/miri/test_dependencies/Cargo.lock | 23 +++- src/tools/miri/test_dependencies/Cargo.toml | 2 +- 8 files changed, 133 insertions(+), 230 deletions(-) diff --git a/src/tools/miri/Cargo.lock b/src/tools/miri/Cargo.lock index b8100d0e7ad9..28c15c15d06f 100644 --- a/src/tools/miri/Cargo.lock +++ b/src/tools/miri/Cargo.lock @@ -132,7 +132,7 @@ dependencies = [ "semver", "serde", "serde_json", - "thiserror", + "thiserror 1.0.63", ] [[package]] @@ -282,23 +282,23 @@ dependencies = [ [[package]] name = "directories" -version = "5.0.1" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35" +checksum = "16f5094c54661b38d03bd7e50df373292118db60b585c08a411c6d840017fe7d" dependencies = [ "dirs-sys", ] [[package]] name = "dirs-sys" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -496,9 +496,9 @@ checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "measureme" -version = "11.0.1" +version = "12.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfa4a40f09af7aa6faef38285402a78847d0d72bf8827006cd2a332e1e6e4a8d" +checksum = "570a507d8948a66a97f42cbbaf8a6bb9516a51017d4ee949502ad7a10a864395" dependencies = [ "log", "memmap2", @@ -553,7 +553,7 @@ dependencies = [ "tempfile", "tikv-jemalloc-sys", "ui_test", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -719,9 +719,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" dependencies = [ "unicode-ident", ] @@ -792,13 +792,13 @@ dependencies = [ [[package]] name = "redox_users" -version = "0.4.5" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" +checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" dependencies = [ "getrandom 0.2.15", "libredox", - "thiserror", + "thiserror 2.0.12", ] [[package]] @@ -859,7 +859,7 @@ checksum = "70f5b7fc8060f4f8373f9381a630304b42e1183535d9beb1d3f596b236c9106a" dependencies = [ "serde", "serde_json", - "thiserror", + "thiserror 1.0.63", "tracing", ] @@ -968,9 +968,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.72" +version = "2.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" +checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" dependencies = [ "proc-macro2", "quote", @@ -996,7 +996,16 @@ version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.63", +] + +[[package]] +name = "thiserror" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +dependencies = [ + "thiserror-impl 2.0.12", ] [[package]] @@ -1010,6 +1019,17 @@ dependencies = [ "syn", ] +[[package]] +name = "thiserror-impl" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "thread_local" version = "1.1.8" @@ -1160,6 +1180,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-targets" version = "0.48.5" diff --git a/src/tools/miri/Cargo.toml b/src/tools/miri/Cargo.toml index 5d8c9a866445..5bb07648f75c 100644 --- a/src/tools/miri/Cargo.toml +++ b/src/tools/miri/Cargo.toml @@ -22,10 +22,10 @@ getrandom = { version = "0.3", features = ["std"] } rand = "0.9" smallvec = { version = "1.7", features = ["drain_filter"] } aes = { version = "0.8.3", features = ["hazmat"] } -measureme = "11" +measureme = "12" chrono = { version = "0.4.38", default-features = false } chrono-tz = "0.10" -directories = "5" +directories = "6" # Copied from `compiler/rustc/Cargo.toml`. # But only for some targets, it fails for others. Rustc configures this in its CI, but we can't @@ -40,7 +40,7 @@ libffi = "3.2.0" libloading = "0.8" [target.'cfg(target_family = "windows")'.dependencies] -windows-sys = { version = "0.52", features = [ +windows-sys = { version = "0.59", features = [ "Win32_Foundation", "Win32_System_IO", "Win32_Storage_FileSystem", diff --git a/src/tools/miri/cargo-miri/Cargo.lock b/src/tools/miri/cargo-miri/Cargo.lock index b8e08d39a861..c75610d2a686 100644 --- a/src/tools/miri/cargo-miri/Cargo.lock +++ b/src/tools/miri/cargo-miri/Cargo.lock @@ -47,9 +47,9 @@ dependencies = [ [[package]] name = "cargo_metadata" -version = "0.18.1" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" +checksum = "dd5eb614ed4c27c5d706420e4320fbe3216ab31fa1c33cd8246ac36dae4479ba" dependencies = [ "camino", "cargo-platform", @@ -67,23 +67,23 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "directories" -version = "5.0.1" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35" +checksum = "16f5094c54661b38d03bd7e50df373292118db60b585c08a411c6d840017fe7d" dependencies = [ "dirs-sys", ] [[package]] name = "dirs-sys" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -161,9 +161,9 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" dependencies = [ "unicode-ident", ] @@ -179,9 +179,9 @@ dependencies = [ [[package]] name = "redox_users" -version = "0.4.5" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" +checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" dependencies = [ "getrandom", "libredox", @@ -286,9 +286,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.72" +version = "2.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" +checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" dependencies = [ "proc-macro2", "quote", @@ -310,18 +310,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.63" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.63" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", @@ -359,22 +359,13 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - [[package]] name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.6", + "windows-targets", ] [[package]] @@ -383,22 +374,7 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", + "windows-targets", ] [[package]] @@ -407,46 +383,28 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -459,48 +417,24 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" diff --git a/src/tools/miri/cargo-miri/Cargo.toml b/src/tools/miri/cargo-miri/Cargo.toml index de0988d6d1cd..ed142b0e2114 100644 --- a/src/tools/miri/cargo-miri/Cargo.toml +++ b/src/tools/miri/cargo-miri/Cargo.toml @@ -14,10 +14,10 @@ test = false # we have no unit tests doctest = false # and no doc tests [dependencies] -directories = "5" +directories = "6" rustc_version = "0.4" serde_json = "1.0.40" -cargo_metadata = "0.18.0" +cargo_metadata = "0.19" rustc-build-sysroot = "0.5.4" # Enable some feature flags that dev-dependencies need but dependencies diff --git a/src/tools/miri/miri-script/Cargo.lock b/src/tools/miri/miri-script/Cargo.lock index 25c6f817575e..7411c874453a 100644 --- a/src/tools/miri/miri-script/Cargo.lock +++ b/src/tools/miri/miri-script/Cargo.lock @@ -117,23 +117,23 @@ checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "directories" -version = "5.0.1" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35" +checksum = "16f5094c54661b38d03bd7e50df373292118db60b585c08a411c6d840017fe7d" dependencies = [ "dirs-sys", ] [[package]] name = "dirs-sys" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -148,6 +148,12 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" +[[package]] +name = "env_home" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f84e12ccf0a7ddc17a6c41c93326024c42920d7ee630d04950e6926645c0fe" + [[package]] name = "errno" version = "0.3.9" @@ -181,15 +187,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "home" -version = "0.5.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" -dependencies = [ - "windows-sys 0.52.0", -] - [[package]] name = "is_terminal_polyfill" version = "1.70.1" @@ -198,9 +195,9 @@ checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "itertools" -version = "0.11.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" dependencies = [ "either", ] @@ -280,9 +277,9 @@ checksum = "a6e819bbd49d5939f682638fa54826bf1650abddcd65d000923de8ad63cc7d15" [[package]] name = "proc-macro2" -version = "1.0.78" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" dependencies = [ "unicode-ident", ] @@ -298,9 +295,9 @@ dependencies = [ [[package]] name = "redox_users" -version = "0.4.6" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" dependencies = [ "getrandom", "libredox", @@ -396,9 +393,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "2.0.50" +version = "2.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74f1bdc9872430ce9b75da68329d1c1746faf50ffac5f19e02b71e37ff881ffb" +checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" dependencies = [ "proc-macro2", "quote", @@ -420,18 +417,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.57" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.57" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", @@ -468,12 +465,12 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "which" -version = "6.0.3" +version = "7.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ee928febd44d98f2f459a4a79bd4d928591333a494a10a868418ac1b39cf1f" +checksum = "2774c861e1f072b3aadc02f8ba886c26ad6321567ecc294c935434cad06f1283" dependencies = [ "either", - "home", + "env_home", "rustix", "winsafe", ] @@ -487,22 +484,13 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - [[package]] name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.6", + "windows-targets", ] [[package]] @@ -511,22 +499,7 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", + "windows-targets", ] [[package]] @@ -535,46 +508,28 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -587,48 +542,24 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" diff --git a/src/tools/miri/miri-script/Cargo.toml b/src/tools/miri/miri-script/Cargo.toml index 5879b2717e5d..a04898de6aba 100644 --- a/src/tools/miri/miri-script/Cargo.toml +++ b/src/tools/miri/miri-script/Cargo.toml @@ -13,16 +13,16 @@ edition = "2021" # This is needed to make this package build on stable when the parent package uses unstable cargo features. [dependencies] -which = "6.0" +which = "7" walkdir = "2.3" -itertools = "0.11" +itertools = "0.14" path_macro = "1.0" shell-words = "1.1" anyhow = "1.0" xshell = "0.2.6" rustc_version = "0.4" dunce = "1.0.4" -directories = "5" +directories = "6" serde = "1" serde_json = "1" serde_derive = "1" diff --git a/src/tools/miri/test_dependencies/Cargo.lock b/src/tools/miri/test_dependencies/Cargo.lock index af92f9d0dec4..c11fe24e737f 100644 --- a/src/tools/miri/test_dependencies/Cargo.lock +++ b/src/tools/miri/test_dependencies/Cargo.lock @@ -72,7 +72,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -180,7 +180,7 @@ dependencies = [ "hermit-abi", "libc", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -196,7 +196,7 @@ dependencies = [ "page_size", "tempfile", "tokio", - "windows-sys", + "windows-sys 0.59.0", ] [[package]] @@ -274,7 +274,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -299,7 +299,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -323,7 +323,7 @@ dependencies = [ "fastrand", "once_cell", "rustix", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -340,7 +340,7 @@ dependencies = [ "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -466,6 +466,15 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + [[package]] name = "windows-targets" version = "0.52.6" diff --git a/src/tools/miri/test_dependencies/Cargo.toml b/src/tools/miri/test_dependencies/Cargo.toml index 78dddaf11dff..7e16592ca7a8 100644 --- a/src/tools/miri/test_dependencies/Cargo.toml +++ b/src/tools/miri/test_dependencies/Cargo.toml @@ -25,6 +25,6 @@ page_size = "0.6" tokio = { version = "1.24", features = ["macros", "rt-multi-thread", "time", "net", "fs", "sync", "signal", "io-util"] } [target.'cfg(windows)'.dependencies] -windows-sys = { version = "0.52", features = [ "Win32_Foundation", "Win32_System_Threading" ] } +windows-sys = { version = "0.59", features = [ "Win32_Foundation", "Win32_System_Threading" ] } [workspace] From eb00d966a0bb3124e4ac75993177d999e4c1116d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 4 Apr 2025 14:08:42 +0200 Subject: [PATCH 107/606] cargo update --- src/tools/miri/Cargo.lock | 521 ++++++++++---------- src/tools/miri/cargo-miri/Cargo.lock | 145 +++--- src/tools/miri/miri-script/Cargo.lock | 195 +++++--- src/tools/miri/test_dependencies/Cargo.lock | 188 ++++--- 4 files changed, 550 insertions(+), 499 deletions(-) diff --git a/src/tools/miri/Cargo.lock b/src/tools/miri/Cargo.lock index 28c15c15d06f..bb228962ecc9 100644 --- a/src/tools/miri/Cargo.lock +++ b/src/tools/miri/Cargo.lock @@ -39,31 +39,31 @@ dependencies = [ [[package]] name = "annotate-snippets" -version = "0.11.4" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24e35ed54e5ea7997c14ed4c70ba043478db1112e98263b3b035907aa197d991" +checksum = "710e8eae58854cdc1790fcb56cca04d712a17be849eeb81da2a724bf4bae2bc4" dependencies = [ "anstyle", - "unicode-width", + "unicode-width 0.2.0", ] [[package]] name = "anstyle" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anyhow" -version = "1.0.86" +version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "backtrace" @@ -82,15 +82,15 @@ dependencies = [ [[package]] name = "bitflags" -version = "2.6.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" [[package]] name = "bstr" -version = "1.10.0" +version = "1.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c" +checksum = "531a9155a481e2ee699d4f98f43c0ca4ff8ee1bfd55c31e9e98fb29d2b176fe0" dependencies = [ "memchr", "regex-automata", @@ -98,25 +98,25 @@ dependencies = [ ] [[package]] -name = "byteorder" -version = "1.5.0" +name = "bumpalo" +version = "3.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" [[package]] name = "camino" -version = "1.1.7" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0ec6b951b160caa93cc0c7b209e5a3bff7aae9062213451ac99493cd844c239" +checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" dependencies = [ "serde", ] [[package]] name = "cargo-platform" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" +checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" dependencies = [ "serde", ] @@ -132,14 +132,14 @@ dependencies = [ "semver", "serde", "serde_json", - "thiserror 1.0.63", + "thiserror 1.0.69", ] [[package]] name = "cc" -version = "1.1.22" +version = "1.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9540e661f81799159abee814118cc139a2004b3a3aa3ea37724a1b66530b90e0" +checksum = "1fcb57c740ae1daf453ae85f16e37396f672b039e00d9d866e07ddb24e328e3a" dependencies = [ "shlex", ] @@ -152,18 +152,18 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.38" +version = "0.4.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c" dependencies = [ "num-traits", ] [[package]] name = "chrono-tz" -version = "0.10.0" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd6dd8046d00723a59a2f8c5f295c515b9bb9a331ee4f8f3d4dd49e428acd3b6" +checksum = "efdce149c370f133a071ca8ef6ea340b7b88748ab0810097a9e2976eaa34b4f3" dependencies = [ "chrono", "chrono-tz-build", @@ -172,9 +172,9 @@ dependencies = [ [[package]] name = "chrono-tz-build" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94fea34d77a245229e7746bd2beb786cd2a896f306ff491fb8cecb3074b10a7" +checksum = "8f10f8c9340e31fc120ff885fcdb54a0b48e474bbd77cab557f0c30a3e569402" dependencies = [ "parse-zoneinfo", "phf_codegen", @@ -219,12 +219,12 @@ dependencies = [ [[package]] name = "colored" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8" +checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c" dependencies = [ "lazy_static", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -235,40 +235,40 @@ checksum = "55b672471b4e9f9e95499ea597ff64941a309b2cdbffcc46f2cc5e2d971fd335" [[package]] name = "console" -version = "0.15.8" +version = "0.15.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" +checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8" dependencies = [ "encode_unicode", - "lazy_static", "libc", - "unicode-width", - "windows-sys 0.52.0", + "once_cell", + "unicode-width 0.2.0", + "windows-sys", ] [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" dependencies = [ "libc", ] [[package]] name = "crossbeam-channel" -version = "0.5.13" +version = "0.5.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" +checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.20" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crypto-common" @@ -298,23 +298,23 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.59.0", + "windows-sys", ] [[package]] name = "encode_unicode" -version = "0.3.6" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" [[package]] name = "errno" -version = "0.3.9" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys", ] [[package]] @@ -329,9 +329,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.1.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "generic-array" @@ -356,14 +356,14 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" +checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" dependencies = [ "cfg-if", "libc", - "wasi 0.13.3+wasi-0.2.2", - "windows-targets 0.52.6", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", ] [[package]] @@ -380,40 +380,41 @@ checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" [[package]] name = "indicatif" -version = "0.17.8" +version = "0.17.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "763a5a8f45087d6bcea4222e7b72c291a054edf80e4ef6efd2a4979878c7bea3" +checksum = "183b3088984b400f4cfac3620d5e076c84da5364016b4f49473de574b2586235" dependencies = [ "console", - "instant", "number_prefix", "portable-atomic", - "unicode-width", + "unicode-width 0.2.0", + "web-time", ] [[package]] name = "inout" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" dependencies = [ "generic-array", ] [[package]] -name = "instant" -version = "0.1.13" +name = "itoa" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" -dependencies = [ - "cfg-if", -] +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] -name = "itoa" -version = "1.0.11" +name = "js-sys" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +dependencies = [ + "once_cell", + "wasm-bindgen", +] [[package]] name = "lazy_static" @@ -429,9 +430,9 @@ checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760" [[package]] name = "libc" -version = "0.2.155" +version = "0.2.171" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" [[package]] name = "libffi" @@ -454,12 +455,12 @@ dependencies = [ [[package]] name = "libloading" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" +checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" dependencies = [ "cfg-if", - "windows-targets 0.52.6", + "windows-targets", ] [[package]] @@ -474,9 +475,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.14" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +checksum = "fe7db12097d22ec582439daf8618b8fdd1a7bef6270e9af3b1ebcd30893cf413" [[package]] name = "lock_api" @@ -490,9 +491,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.22" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" [[package]] name = "measureme" @@ -541,7 +542,7 @@ dependencies = [ "chrono-tz", "colored", "directories", - "getrandom 0.3.1", + "getrandom 0.3.2", "libc", "libffi", "libloading", @@ -553,7 +554,7 @@ dependencies = [ "tempfile", "tikv-jemalloc-sys", "ui_test", - "windows-sys 0.59.0", + "windows-sys", ] [[package]] @@ -582,9 +583,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.19.0" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "option-ext" @@ -604,7 +605,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2ad9b889f1b12e0b9ee24db044b5129150d5eada288edc800f789928dc8c0e3" dependencies = [ - "unicode-width", + "unicode-width 0.1.14", ] [[package]] @@ -627,7 +628,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-targets 0.52.6", + "windows-targets", ] [[package]] @@ -650,18 +651,18 @@ dependencies = [ [[package]] name = "phf" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" dependencies = [ "phf_shared", ] [[package]] name = "phf_codegen" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a" +checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" dependencies = [ "phf_generator", "phf_shared", @@ -669,9 +670,9 @@ dependencies = [ [[package]] name = "phf_generator" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ "phf_shared", "rand 0.8.5", @@ -679,32 +680,32 @@ dependencies = [ [[package]] name = "phf_shared" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" dependencies = [ "siphasher", ] [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "portable-atomic" -version = "1.7.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da544ee218f0d287a911e9c99a39a8c9bc8fcad3cb8db5959940044ecfc67265" +checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" [[package]] name = "ppv-lite86" -version = "0.2.20" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ - "zerocopy 0.7.35", + "zerocopy", ] [[package]] @@ -728,13 +729,19 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.36" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" + [[package]] name = "rand" version = "0.8.5" @@ -751,8 +758,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" dependencies = [ "rand_chacha", - "rand_core 0.9.0", - "zerocopy 0.8.14", + "rand_core 0.9.3", + "zerocopy", ] [[package]] @@ -762,7 +769,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core 0.9.0", + "rand_core 0.9.3", ] [[package]] @@ -773,19 +780,18 @@ checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" [[package]] name = "rand_core" -version = "0.9.0" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b08f3c9802962f7e1b25113931d94f43ed9725bebc59db9d0c3e9a23b67e15ff" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ - "getrandom 0.3.1", - "zerocopy 0.8.14", + "getrandom 0.3.2", ] [[package]] name = "redox_syscall" -version = "0.5.3" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" +checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1" dependencies = [ "bitflags", ] @@ -803,9 +809,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.6" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", @@ -815,9 +821,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -826,9 +832,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "rustc-demangle" @@ -844,43 +850,43 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] [[package]] name = "rustfix" -version = "0.8.5" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70f5b7fc8060f4f8373f9381a630304b42e1183535d9beb1d3f596b236c9106a" +checksum = "82fa69b198d894d84e23afde8e9ab2af4400b2cba20d6bf2b428a8b01c222c5a" dependencies = [ "serde", "serde_json", - "thiserror 1.0.63", + "thiserror 1.0.69", "tracing", ] [[package]] name = "rustix" -version = "0.38.34" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +checksum = "d97817398dd4bb2e6da002002db259209759911da105da92bec29ccb12cf58bf" dependencies = [ "bitflags", "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys", ] [[package]] name = "ryu" -version = "1.0.18" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "scopeguard" @@ -890,27 +896,27 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "semver" -version = "1.0.23" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.204" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.204" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", @@ -919,9 +925,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.122" +version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784b6203951c57ff748476b126ccb5e8e2959a5c19e5c617ab1956be3dbc68da" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" dependencies = [ "itoa", "memchr", @@ -946,15 +952,15 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "siphasher" -version = "0.3.11" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" [[package]] name = "smallvec" -version = "1.13.2" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" [[package]] name = "spanned" @@ -979,24 +985,24 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.11.0" +version = "3.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fcd239983515c23a32fb82099f97d0b11b8c72f654ed659363a95c3dad7a53" +checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf" dependencies = [ - "cfg-if", "fastrand", + "getrandom 0.3.2", "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys", ] [[package]] name = "thiserror" -version = "1.0.63" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl 1.0.63", + "thiserror-impl 1.0.69", ] [[package]] @@ -1010,9 +1016,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "1.0.63" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", @@ -1052,9 +1058,9 @@ dependencies = [ [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "pin-project-lite", "tracing-core", @@ -1062,9 +1068,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", "valuable", @@ -1072,9 +1078,9 @@ dependencies = [ [[package]] name = "tracing-error" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e" +checksum = "8b1581020d7a273442f5b45074a6a57d5757ad0a47dac0e9f0bd57b81936f3db" dependencies = [ "tracing", "tracing-subscriber", @@ -1082,9 +1088,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" dependencies = [ "sharded-slab", "thread_local", @@ -1093,15 +1099,15 @@ dependencies = [ [[package]] name = "typenum" -version = "1.17.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" [[package]] name = "ui_test" -version = "0.29.1" +version = "0.29.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14bf63f2931a28a04af0bd24c5f850223d29f3a40afae49ed6ce442a65eb8652" +checksum = "1211b1111c752c73b33073d2958072be08825fd97c9ab4d83444da361a06634b" dependencies = [ "annotate-snippets", "anyhow", @@ -1125,21 +1131,27 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] name = "unicode-width" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "unicode-width" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" [[package]] name = "valuable" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" [[package]] name = "version_check" @@ -1155,29 +1167,78 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasi" -version = "0.13.3+wasi-0.2.2" +version = "0.14.2+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" dependencies = [ "wit-bindgen-rt", ] [[package]] -name = "windows-sys" -version = "0.48.0" +name = "wasm-bindgen" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ - "windows-targets 0.48.5", + "cfg-if", + "once_cell", + "wasm-bindgen-macro", ] [[package]] -name = "windows-sys" -version = "0.52.0" +name = "wasm-bindgen-backend" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ - "windows-targets 0.52.6", + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", ] [[package]] @@ -1186,22 +1247,7 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", + "windows-targets", ] [[package]] @@ -1210,46 +1256,28 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -1262,48 +1290,24 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -1312,48 +1316,27 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "wit-bindgen-rt" -version = "0.33.0" +version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" dependencies = [ "bitflags", ] [[package]] name = "zerocopy" -version = "0.7.35" +version = "0.8.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879" dependencies = [ - "byteorder", - "zerocopy-derive 0.7.35", -] - -[[package]] -name = "zerocopy" -version = "0.8.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a367f292d93d4eab890745e75a778da40909cab4d6ff8173693812f79c4a2468" -dependencies = [ - "zerocopy-derive 0.8.14", + "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.35" +version = "0.8.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3931cb58c62c13adec22e38686b559c86a30565e16ad6e8510a337cedc611e1" +checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" dependencies = [ "proc-macro2", "quote", diff --git a/src/tools/miri/cargo-miri/Cargo.lock b/src/tools/miri/cargo-miri/Cargo.lock index c75610d2a686..bd4ca2860f35 100644 --- a/src/tools/miri/cargo-miri/Cargo.lock +++ b/src/tools/miri/cargo-miri/Cargo.lock @@ -4,21 +4,21 @@ version = 4 [[package]] name = "anyhow" -version = "1.0.86" +version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" [[package]] name = "bitflags" -version = "2.6.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" [[package]] name = "camino" -version = "1.1.7" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0ec6b951b160caa93cc0c7b209e5a3bff7aae9062213451ac99493cd844c239" +checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" dependencies = [ "serde", ] @@ -38,9 +38,9 @@ dependencies = [ [[package]] name = "cargo-platform" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" +checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" dependencies = [ "serde", ] @@ -83,24 +83,24 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.59.0", + "windows-sys", ] [[package]] name = "errno" -version = "0.3.9" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys", ] [[package]] name = "fastrand" -version = "2.1.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "getrandom" @@ -110,20 +110,32 @@ checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", ] [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "libc" -version = "0.2.155" +version = "0.2.171" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" [[package]] name = "libredox" @@ -137,9 +149,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.14" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +checksum = "fe7db12097d22ec582439daf8618b8fdd1a7bef6270e9af3b1ebcd30893cf413" [[package]] name = "memchr" @@ -149,9 +161,9 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "once_cell" -version = "1.19.0" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "option-ext" @@ -170,20 +182,26 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.36" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" + [[package]] name = "redox_users" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" dependencies = [ - "getrandom", + "getrandom 0.2.15", "libredox", "thiserror", ] @@ -202,37 +220,37 @@ dependencies = [ [[package]] name = "rustc_tools_util" -version = "0.4.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3316159ab19e19d1065ecc49278e87f767a9dae9fae80348d2b4d4fa4ae02d4d" +checksum = "a3b75158011a63889ba12084cf1224baad7bcad50f6ee7c842f772b74aa148ed" [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] [[package]] name = "rustix" -version = "0.38.34" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +checksum = "d97817398dd4bb2e6da002002db259209759911da105da92bec29ccb12cf58bf" dependencies = [ "bitflags", "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys", ] [[package]] name = "ryu" -version = "1.0.18" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "same-file" @@ -245,27 +263,27 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.23" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.204" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.204" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", @@ -274,9 +292,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.122" +version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784b6203951c57ff748476b126ccb5e8e2959a5c19e5c617ab1956be3dbc68da" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" dependencies = [ "itoa", "memchr", @@ -297,15 +315,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.11.0" +version = "3.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fcd239983515c23a32fb82099f97d0b11b8c72f654ed659363a95c3dad7a53" +checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf" dependencies = [ - "cfg-if", "fastrand", + "getrandom 0.3.2", "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys", ] [[package]] @@ -330,9 +348,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] name = "walkdir" @@ -350,22 +368,22 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + [[package]] name = "winapi-util" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets", + "windows-sys", ] [[package]] @@ -440,3 +458,12 @@ name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags", +] diff --git a/src/tools/miri/miri-script/Cargo.lock b/src/tools/miri/miri-script/Cargo.lock index 7411c874453a..3494a241ec50 100644 --- a/src/tools/miri/miri-script/Cargo.lock +++ b/src/tools/miri/miri-script/Cargo.lock @@ -38,30 +38,31 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ - "windows-sys 0.59.0", + "windows-sys", ] [[package]] name = "anstyle-wincon" -version = "3.0.6" +version = "3.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" +checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" dependencies = [ "anstyle", - "windows-sys 0.59.0", + "once_cell", + "windows-sys", ] [[package]] name = "anyhow" -version = "1.0.80" +version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" +checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" [[package]] name = "bitflags" -version = "2.4.2" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" [[package]] name = "cfg-if" @@ -71,9 +72,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.5.23" +version = "4.5.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" +checksum = "d8aa86934b44c19c50f87cc2790e19f54f7a67aedb64101c2e1a2e5ecfb73944" dependencies = [ "clap_builder", "clap_derive", @@ -81,9 +82,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.23" +version = "4.5.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" +checksum = "2414dbb2dd0695280da6ea9261e327479e9d37b0630f6b53ba2a11c60c679fd9" dependencies = [ "anstream", "anstyle", @@ -93,9 +94,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.18" +version = "4.5.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" dependencies = [ "heck", "proc-macro2", @@ -133,20 +134,20 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.59.0", + "windows-sys", ] [[package]] name = "dunce" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" [[package]] name = "either" -version = "1.10.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "env_home" @@ -156,29 +157,41 @@ checksum = "c7f84e12ccf0a7ddc17a6c41c93326024c42920d7ee630d04950e6926645c0fe" [[package]] name = "errno" -version = "0.3.9" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys", ] [[package]] name = "fastrand" -version = "2.1.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "getrandom" -version = "0.2.12" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", ] [[package]] @@ -204,15 +217,15 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "libc" -version = "0.2.159" +version = "0.2.171" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" +checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" [[package]] name = "libredox" @@ -226,9 +239,15 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "linux-raw-sys" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe7db12097d22ec582439daf8618b8fdd1a7bef6270e9af3b1ebcd30893cf413" [[package]] name = "memchr" @@ -259,9 +278,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.20.2" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "option-ext" @@ -286,51 +305,70 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.35" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" + [[package]] name = "redox_users" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" dependencies = [ - "getrandom", + "getrandom 0.2.15", "libredox", "thiserror", ] [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] [[package]] name = "rustix" -version = "0.38.37" +version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ "bitflags", "errno", "libc", - "linux-raw-sys", - "windows-sys 0.52.0", + "linux-raw-sys 0.4.15", + "windows-sys", +] + +[[package]] +name = "rustix" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d97817398dd4bb2e6da002002db259209759911da105da92bec29ccb12cf58bf" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys 0.9.3", + "windows-sys", ] [[package]] name = "ryu" -version = "1.0.18" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "same-file" @@ -343,24 +381,24 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.22" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" [[package]] name = "serde" -version = "1.0.210" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.210" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", @@ -369,9 +407,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.128" +version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" dependencies = [ "itoa", "memchr", @@ -404,15 +442,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.13.0" +version = "3.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" +checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf" dependencies = [ - "cfg-if", "fastrand", + "getrandom 0.3.2", "once_cell", - "rustix", - "windows-sys 0.59.0", + "rustix 1.0.5", + "windows-sys", ] [[package]] @@ -437,9 +475,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] name = "utf8parse" @@ -449,9 +487,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "walkdir" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", @@ -463,6 +501,15 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + [[package]] name = "which" version = "7.0.2" @@ -471,7 +518,7 @@ checksum = "2774c861e1f072b3aadc02f8ba886c26ad6321567ecc294c935434cad06f1283" dependencies = [ "either", "env_home", - "rustix", + "rustix 0.38.44", "winsafe", ] @@ -481,16 +528,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets", + "windows-sys", ] [[package]] @@ -572,6 +610,15 @@ version = "0.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags", +] + [[package]] name = "xshell" version = "0.2.7" diff --git a/src/tools/miri/test_dependencies/Cargo.lock b/src/tools/miri/test_dependencies/Cargo.lock index c11fe24e737f..d02d2dffbdb8 100644 --- a/src/tools/miri/test_dependencies/Cargo.lock +++ b/src/tools/miri/test_dependencies/Cargo.lock @@ -4,60 +4,51 @@ version = 4 [[package]] name = "addr2line" -version = "0.22.0" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "backtrace" -version = "0.3.73" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", + "windows-targets", ] [[package]] name = "bitflags" -version = "2.6.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" [[package]] name = "bumpalo" -version = "3.16.0" +version = "3.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" [[package]] name = "bytes" -version = "1.7.1" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" - -[[package]] -name = "cc" -version = "1.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9540e661f81799159abee814118cc139a2004b3a3aa3ea37724a1b66530b90e0" -dependencies = [ - "shlex", -] +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "cfg-if" @@ -67,19 +58,19 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "errno" -version = "0.3.9" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "fastrand" -version = "2.1.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "getrandom" @@ -107,21 +98,21 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" +checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" dependencies = [ "cfg-if", "libc", - "wasi 0.13.3+wasi-0.2.2", - "windows-targets", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", ] [[package]] name = "gimli" -version = "0.29.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "hermit-abi" @@ -131,30 +122,31 @@ checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "js-sys" -version = "0.3.69" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ + "once_cell", "wasm-bindgen", ] [[package]] name = "libc" -version = "0.2.161" +version = "0.2.171" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" +checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" [[package]] name = "linux-raw-sys" -version = "0.4.14" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +checksum = "fe7db12097d22ec582439daf8618b8fdd1a7bef6270e9af3b1ebcd30893cf413" [[package]] name = "log" -version = "0.4.22" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" [[package]] name = "memchr" @@ -164,20 +156,19 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "miniz_oxide" -version = "0.7.4" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +checksum = "ff70ce3e48ae43fa075863cef62e8b43b71a4f2382229920e0df362592919430" dependencies = [ - "adler", + "adler2", ] [[package]] name = "mio" -version = "1.0.1" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ - "hermit-abi", "libc", "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.52.0", @@ -190,7 +181,7 @@ dependencies = [ "cfg-if", "getrandom 0.1.16", "getrandom 0.2.15", - "getrandom 0.3.1", + "getrandom 0.3.2", "libc", "num_cpus", "page_size", @@ -211,18 +202,18 @@ dependencies = [ [[package]] name = "object" -version = "0.36.2" +version = "0.36.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.19.0" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "page_size" @@ -236,28 +227,34 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.36" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" + [[package]] name = "rustc-demangle" version = "0.1.24" @@ -266,23 +263,17 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustix" -version = "0.38.34" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +checksum = "d97817398dd4bb2e6da002002db259209759911da105da92bec29ccb12cf58bf" dependencies = [ "bitflags", "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - [[package]] name = "signal-hook-registry" version = "1.4.2" @@ -294,9 +285,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.7" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef" dependencies = [ "libc", "windows-sys 0.52.0", @@ -304,9 +295,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.72" +version = "2.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" +checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" dependencies = [ "proc-macro2", "quote", @@ -315,22 +306,22 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.11.0" +version = "3.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fcd239983515c23a32fb82099f97d0b11b8c72f654ed659363a95c3dad7a53" +checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf" dependencies = [ - "cfg-if", "fastrand", + "getrandom 0.3.2", "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "tokio" -version = "1.39.2" +version = "1.44.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1" +checksum = "f382da615b842244d4b8738c82ed1275e6c5dd90c459a30941cd07080b06c91a" dependencies = [ "backtrace", "bytes", @@ -345,9 +336,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", @@ -356,9 +347,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] name = "wasi" @@ -374,32 +365,32 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasi" -version = "0.13.3+wasi-0.2.2" +version = "0.14.2+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" dependencies = [ "wit-bindgen-rt", ] [[package]] name = "wasm-bindgen" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ "bumpalo", "log", - "once_cell", "proc-macro2", "quote", "syn", @@ -408,9 +399,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -418,9 +409,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", @@ -431,9 +422,12 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] [[package]] name = "winapi" @@ -541,9 +535,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "wit-bindgen-rt" -version = "0.33.0" +version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" dependencies = [ "bitflags", ] From 35087787a69a967542bac8701c7a949953eea206 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 4 Apr 2025 13:49:14 +0200 Subject: [PATCH 108/606] bump parts of test-cargo-miri to edition 2024 --- src/tools/miri/test-cargo-miri/Cargo.lock | 18 ++++++------- src/tools/miri/test-cargo-miri/Cargo.toml | 2 +- src/tools/miri/test-cargo-miri/run-test.py | 27 ++++++++++--------- src/tools/miri/test-cargo-miri/src/lib.rs | 3 ++- src/tools/miri/test-cargo-miri/src/main.rs | 4 +-- .../miri/test-cargo-miri/subcrate/Cargo.toml | 4 +-- .../miri/test-cargo-miri/subcrate/src/lib.rs | 22 +++++---------- .../{test.stderr-empty.ref => test.empty.ref} | 0 ...c-macro.ref => test.proc-macro.stderr.ref} | 1 + .../test.stderr-proc-macro-doctest.ref | 1 - .../test-cargo-miri/test.stdout-empty.ref | 0 .../test.subcrate.cross-target.stdout.ref | 11 ++++++++ .../test-cargo-miri/test.subcrate.stdout.ref | 10 +++++++ 13 files changed, 59 insertions(+), 44 deletions(-) rename src/tools/miri/test-cargo-miri/{test.stderr-empty.ref => test.empty.ref} (100%) rename src/tools/miri/test-cargo-miri/{test.stderr-proc-macro.ref => test.proc-macro.stderr.ref} (50%) delete mode 100644 src/tools/miri/test-cargo-miri/test.stderr-proc-macro-doctest.ref delete mode 100644 src/tools/miri/test-cargo-miri/test.stdout-empty.ref create mode 100644 src/tools/miri/test-cargo-miri/test.subcrate.cross-target.stdout.ref diff --git a/src/tools/miri/test-cargo-miri/Cargo.lock b/src/tools/miri/test-cargo-miri/Cargo.lock index 8f618e7ffb38..32119426184d 100644 --- a/src/tools/miri/test-cargo-miri/Cargo.lock +++ b/src/tools/miri/test-cargo-miri/Cargo.lock @@ -1,12 +1,12 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "autocfg" -version = "1.2.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "byteorder" @@ -96,15 +96,15 @@ version = "0.1.0" [[package]] name = "once_cell" -version = "1.19.0" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "proc-macro2" -version = "1.0.79" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" dependencies = [ "unicode-ident", ] @@ -129,6 +129,6 @@ version = "0.1.0" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" diff --git a/src/tools/miri/test-cargo-miri/Cargo.toml b/src/tools/miri/test-cargo-miri/Cargo.toml index 574f1d05a6fa..f5092a4748f3 100644 --- a/src/tools/miri/test-cargo-miri/Cargo.toml +++ b/src/tools/miri/test-cargo-miri/Cargo.toml @@ -6,7 +6,7 @@ exclude = ["no-std-smoke"] # it wants to be panic="abort" name = "cargo-miri-test" version = "0.1.0" authors = ["Miri Team"] -edition = "2018" +edition = "2024" [dependencies] byteorder = "1.0" diff --git a/src/tools/miri/test-cargo-miri/run-test.py b/src/tools/miri/test-cargo-miri/run-test.py index 8d55ec2b5313..a9d09ac7a9d6 100755 --- a/src/tools/miri/test-cargo-miri/run-test.py +++ b/src/tools/miri/test-cargo-miri/run-test.py @@ -136,7 +136,7 @@ def test_cargo_miri_run(): cargo_miri("run") + ["--target-dir=custom-run", "--", "--target-dir=target/custom-run"], "run.args.stdout.ref", "run.custom-target-dir.stderr.ref", ) - test("`cargo miri run --package=test-local-crate-detection` (test local crate detection)", + test("`cargo miri run` (test local crate detection)", cargo_miri("run") + ["--package=test-local-crate-detection"], "run.local_crate.stdout.ref", "run.local_crate.stderr.ref", ) @@ -149,43 +149,44 @@ def test_cargo_miri_test(): test("`cargo miri test`", cargo_miri("test"), - default_ref, "test.stderr-empty.ref", + default_ref, "test.empty.ref", env={'MIRIFLAGS': "-Zmiri-seed=4242"}, ) test("`cargo miri test` (no isolation, no doctests)", cargo_miri("test") + ["--bins", "--tests"], # no `--lib`, we disabled that in `Cargo.toml` - "test.cross-target.stdout.ref", "test.stderr-empty.ref", + "test.cross-target.stdout.ref", "test.empty.ref", env={'MIRIFLAGS': "-Zmiri-disable-isolation"}, ) test("`cargo miri test` (with filter)", cargo_miri("test") + ["--", "--format=pretty", "pl"], - filter_ref, "test.stderr-empty.ref", + filter_ref, "test.empty.ref", ) test("`cargo miri test` (test target)", cargo_miri("test") + ["--test", "test", "--", "--format=pretty"], - "test.test-target.stdout.ref", "test.stderr-empty.ref", + "test.test-target.stdout.ref", "test.empty.ref", ) test("`cargo miri test` (bin target)", cargo_miri("test") + ["--bin", "cargo-miri-test", "--", "--format=pretty"], - "test.bin-target.stdout.ref", "test.stderr-empty.ref", + "test.bin-target.stdout.ref", "test.empty.ref", ) test("`cargo miri t` (subcrate, no isolation)", cargo_miri("t") + ["-p", "subcrate"], - "test.subcrate.stdout.ref", "test.stderr-proc-macro.ref", + "test.subcrate.cross-target.stdout.ref" if is_foreign else "test.subcrate.stdout.ref", + "test.empty.ref", env={'MIRIFLAGS': "-Zmiri-disable-isolation"}, ) - test("`cargo miri test` (subcrate, doctests)", - cargo_miri("test") + ["-p", "subcrate", "--doc"], - "test.stdout-empty.ref", "test.stderr-proc-macro-doctest.ref", + test("`cargo miri test` (proc-macro crate)", + cargo_miri("test") + ["-p", "proc_macro_crate"], + "test.empty.ref", "test.proc-macro.stderr.ref", ) test("`cargo miri test` (custom target dir)", cargo_miri("test") + ["--target-dir=custom-test"], - default_ref, "test.stderr-empty.ref", + default_ref, "test.empty.ref", ) del os.environ["CARGO_TARGET_DIR"] # this overrides `build.target-dir` passed by `--config`, so unset it test("`cargo miri test` (config-cli)", cargo_miri("test") + ["--config=build.target-dir=\"config-cli\""], - default_ref, "test.stderr-empty.ref", + default_ref, "test.empty.ref", ) if ARGS.multi_target: test_cargo_miri_multi_target() @@ -194,7 +195,7 @@ def test_cargo_miri_test(): def test_cargo_miri_multi_target(): test("`cargo miri test` (multiple targets)", cargo_miri("test", targets = ["aarch64-unknown-linux-gnu", "s390x-unknown-linux-gnu"]), - "test.multiple_targets.stdout.ref", "test.stderr-empty.ref", + "test.multiple_targets.stdout.ref", "test.empty.ref", ) args_parser = argparse.ArgumentParser(description='`cargo miri` testing') diff --git a/src/tools/miri/test-cargo-miri/src/lib.rs b/src/tools/miri/test-cargo-miri/src/lib.rs index 003341d0974c..3b63f8afc902 100644 --- a/src/tools/miri/test-cargo-miri/src/lib.rs +++ b/src/tools/miri/test-cargo-miri/src/lib.rs @@ -26,7 +26,8 @@ /// /// let _val = Fail::::C; /// ``` -#[no_mangle] +// This is imported in `main.rs`. +#[unsafe(no_mangle)] pub fn make_true() -> bool { proc_macro_crate::use_the_dependency!(); issue_1567::use_the_dependency(); diff --git a/src/tools/miri/test-cargo-miri/src/main.rs b/src/tools/miri/test-cargo-miri/src/main.rs index efe95bf3abab..00a239a9161a 100644 --- a/src/tools/miri/test-cargo-miri/src/main.rs +++ b/src/tools/miri/test-cargo-miri/src/main.rs @@ -30,7 +30,7 @@ fn main() { let mut out = Vec::with_capacity(1024); unsafe { - extern "Rust" { + unsafe extern "Rust" { fn miri_host_to_target_path( path: *const c_char, out: *mut c_char, @@ -81,7 +81,7 @@ mod test { // Test calling exported symbols in (transitive) dependencies. // Repeat calls to make sure the `Instance` cache is not broken. for _ in 0..3 { - extern "Rust" { + unsafe extern "Rust" { fn exported_symbol() -> i32; fn assoc_fn_as_exported_symbol() -> i32; fn make_true() -> bool; diff --git a/src/tools/miri/test-cargo-miri/subcrate/Cargo.toml b/src/tools/miri/test-cargo-miri/subcrate/Cargo.toml index 06b1ce1cba4b..f2f6360f2d21 100644 --- a/src/tools/miri/test-cargo-miri/subcrate/Cargo.toml +++ b/src/tools/miri/test-cargo-miri/subcrate/Cargo.toml @@ -2,11 +2,11 @@ name = "subcrate" version = "0.1.0" authors = ["Miri Team"] +# This is deliberately *not* on the 2024 edition to ensure doctests keep working +# on old editions. edition = "2018" [lib] -proc-macro = true -doctest = false [[bin]] name = "subcrate" diff --git a/src/tools/miri/test-cargo-miri/subcrate/src/lib.rs b/src/tools/miri/test-cargo-miri/subcrate/src/lib.rs index 98c22fef0766..b9278c54dbed 100644 --- a/src/tools/miri/test-cargo-miri/subcrate/src/lib.rs +++ b/src/tools/miri/test-cargo-miri/subcrate/src/lib.rs @@ -1,16 +1,8 @@ -// This is a proc-macro crate. - -extern crate proc_macro; // make sure proc_macro is in the sysroot - -#[cfg(doctest)] -compile_error!("rustdoc should not touch me"); - -#[cfg(miri)] -compile_error!("Miri should not touch me"); - -use proc_macro::TokenStream; - -#[proc_macro] -pub fn make_answer(_item: TokenStream) -> TokenStream { - "fn answer() -> u32 { 42 }".parse().unwrap() +/// Doc-test test +/// +/// ```rust +/// assert!(subcrate::make_true()); +/// ``` +pub fn make_true() -> bool { + true } diff --git a/src/tools/miri/test-cargo-miri/test.stderr-empty.ref b/src/tools/miri/test-cargo-miri/test.empty.ref similarity index 100% rename from src/tools/miri/test-cargo-miri/test.stderr-empty.ref rename to src/tools/miri/test-cargo-miri/test.empty.ref diff --git a/src/tools/miri/test-cargo-miri/test.stderr-proc-macro.ref b/src/tools/miri/test-cargo-miri/test.proc-macro.stderr.ref similarity index 50% rename from src/tools/miri/test-cargo-miri/test.stderr-proc-macro.ref rename to src/tools/miri/test-cargo-miri/test.proc-macro.stderr.ref index 4983250917b5..b95474208b27 100644 --- a/src/tools/miri/test-cargo-miri/test.stderr-proc-macro.ref +++ b/src/tools/miri/test-cargo-miri/test.proc-macro.stderr.ref @@ -1 +1,2 @@ Running unit tests of `proc-macro` crates is not currently supported by Miri. +Running doctests of `proc-macro` crates is not currently supported by Miri. diff --git a/src/tools/miri/test-cargo-miri/test.stderr-proc-macro-doctest.ref b/src/tools/miri/test-cargo-miri/test.stderr-proc-macro-doctest.ref deleted file mode 100644 index ca5e3a2392db..000000000000 --- a/src/tools/miri/test-cargo-miri/test.stderr-proc-macro-doctest.ref +++ /dev/null @@ -1 +0,0 @@ -Running doctests of `proc-macro` crates is not currently supported by Miri. diff --git a/src/tools/miri/test-cargo-miri/test.stdout-empty.ref b/src/tools/miri/test-cargo-miri/test.stdout-empty.ref deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/src/tools/miri/test-cargo-miri/test.subcrate.cross-target.stdout.ref b/src/tools/miri/test-cargo-miri/test.subcrate.cross-target.stdout.ref new file mode 100644 index 000000000000..436e6e4fbbbc --- /dev/null +++ b/src/tools/miri/test-cargo-miri/test.subcrate.cross-target.stdout.ref @@ -0,0 +1,11 @@ + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + +subcrate testing diff --git a/src/tools/miri/test-cargo-miri/test.subcrate.stdout.ref b/src/tools/miri/test-cargo-miri/test.subcrate.stdout.ref index e50838ebc838..c7c7bc8351b2 100644 --- a/src/tools/miri/test-cargo-miri/test.subcrate.stdout.ref +++ b/src/tools/miri/test-cargo-miri/test.subcrate.stdout.ref @@ -1,6 +1,16 @@ +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + + running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME subcrate testing + +running 1 test +. +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + From a503ecbfcbaed5c7fcb686b1b011f29bbab3e01a Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Fri, 4 Apr 2025 06:31:55 -0600 Subject: [PATCH 109/606] Update README.md verb -> participle Co-authored-by: Ralf Jung --- src/tools/miri/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md index 8aa11e1f8210..e8ea988558ce 100644 --- a/src/tools/miri/README.md +++ b/src/tools/miri/README.md @@ -565,7 +565,7 @@ Definite bugs found: * [Occasional memory leak in `std::mpsc` channels](https://github.com/rust-lang/rust/issues/121582) (original code in [crossbeam](https://github.com/crossbeam-rs/crossbeam/pull/1084)) * [Weak-memory-induced memory leak in Windows thread-local storage](https://github.com/rust-lang/rust/pull/124281) * [A bug in the new `RwLock::downgrade` implementation](https://rust-lang.zulipchat.com/#narrow/channel/269128-miri/topic/Miri.20error.20library.20test) (caught by Miri before it landed in the Rust repo) -* [Mockall reads unintialized memory when mocking `std::io::Read::read`, even if all expectations are satisfied](https://github.com/asomers/mockall/issues/647) (caught by Miri running Tokio's test suite) +* [Mockall reading unintialized memory when mocking `std::io::Read::read`, even if all expectations are satisfied](https://github.com/asomers/mockall/issues/647) (caught by Miri running Tokio's test suite) Violations of [Stacked Borrows] found that are likely bugs (but Stacked Borrows is currently just an experiment): From 0522ed059db967db26143387747b46c11528f49b Mon Sep 17 00:00:00 2001 From: Bryanskiy Date: Fri, 4 Apr 2025 15:32:00 +0300 Subject: [PATCH 110/606] Default auto traits: fix perf --- .../src/collect/predicates_of.rs | 30 +--------- .../src/hir_ty_lowering/bounds.rs | 56 ++++++++++++++++--- 2 files changed, 51 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 776b23bea8e1..320225a7a663 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -172,33 +172,9 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen }; if let Node::TraitItem(item) = node { - let parent = tcx.local_parent(item.hir_id().owner.def_id); - let Node::Item(parent_trait) = tcx.hir_node_by_def_id(parent) else { - unreachable!(); - }; - - let (trait_generics, trait_bounds) = match parent_trait.kind { - hir::ItemKind::Trait(_, _, _, generics, supertraits, _) => (generics, supertraits), - hir::ItemKind::TraitAlias(_, generics, supertraits) => (generics, supertraits), - _ => unreachable!(), - }; - - // Implicitly add `Self: DefaultAutoTrait` clauses on trait associated items if - // they are not added as super trait bounds to the trait itself. See comment on - // `requires_default_supertraits` for more details. - if !icx.lowerer().requires_default_supertraits(trait_bounds, trait_generics) { - let mut bounds = Vec::new(); - let self_ty_where_predicates = (parent, item.generics.predicates); - icx.lowerer().add_default_traits_with_filter( - &mut bounds, - tcx.types.self_param, - &[], - Some(self_ty_where_predicates), - item.span, - |tr| tr != hir::LangItem::Sized, - ); - predicates.extend(bounds); - } + let mut bounds = Vec::new(); + icx.lowerer().add_default_trait_item_bounds(item, &mut bounds); + predicates.extend(bounds); } let generics = tcx.generics_of(def_id); diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index c3bb860538ee..55087d1f400f 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -43,12 +43,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } /// Checks whether `Self: DefaultAutoTrait` bounds should be added on trait super bounds - /// or associative items. + /// or associated items. /// /// To keep backward compatibility with existing code, `experimental_default_bounds` bounds /// should be added everywhere, including super bounds. However this causes a huge performance /// costs. For optimization purposes instead of adding default supertraits, bounds - /// are added to the associative items: + /// are added to the associated items: /// /// ```ignore(illustrative) /// // Default bounds are generated in the following way: @@ -81,7 +81,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// /// Therefore, `experimental_default_bounds` are still being added to supertraits if /// the `SelfTyParam` or `AssocItemConstraint` were found in a trait header. - pub(crate) fn requires_default_supertraits( + fn requires_default_supertraits( &self, hir_bounds: &'tcx [hir::GenericBound<'tcx>], hir_generics: &'tcx hir::Generics<'tcx>, @@ -120,6 +120,43 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { found } + /// Implicitly add `Self: DefaultAutoTrait` clauses on trait associated items if + /// they are not added as super trait bounds to the trait itself. See + /// `requires_default_supertraits` for more information. + pub(crate) fn add_default_trait_item_bounds( + &self, + trait_item: &hir::TraitItem<'tcx>, + bounds: &mut Vec<(ty::Clause<'tcx>, Span)>, + ) { + let tcx = self.tcx(); + if !tcx.sess.opts.unstable_opts.experimental_default_bounds { + return; + } + + let parent = tcx.local_parent(trait_item.hir_id().owner.def_id); + let hir::Node::Item(parent_trait) = tcx.hir_node_by_def_id(parent) else { + unreachable!(); + }; + + let (trait_generics, trait_bounds) = match parent_trait.kind { + hir::ItemKind::Trait(_, _, _, generics, supertraits, _) => (generics, supertraits), + hir::ItemKind::TraitAlias(_, generics, supertraits) => (generics, supertraits), + _ => unreachable!(), + }; + + if !self.requires_default_supertraits(trait_bounds, trait_generics) { + let self_ty_where_predicates = (parent, trait_item.generics.predicates); + self.add_default_traits_with_filter( + bounds, + tcx.types.self_param, + &[], + Some(self_ty_where_predicates), + trait_item.span, + |tr| tr != hir::LangItem::Sized, + ); + } + } + /// Lazily sets `experimental_default_bounds` to true on trait super bounds. /// See `requires_default_supertraits` for more information. pub(crate) fn add_default_super_traits( @@ -130,6 +167,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { hir_generics: &'tcx hir::Generics<'tcx>, span: Span, ) { + if !self.tcx().sess.opts.unstable_opts.experimental_default_bounds { + return; + } + assert!(matches!(self.tcx().def_kind(trait_def_id), DefKind::Trait | DefKind::TraitAlias)); if self.requires_default_supertraits(hir_bounds, hir_generics) { let self_ty_where_predicates = (trait_def_id, hir_generics.predicates); @@ -263,11 +304,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { seen_unbound = true; } let emit_relax_err = || { - let unbound_traits = - match self.tcx().sess.opts.unstable_opts.experimental_default_bounds { - true => "`?Sized` and `experimental_default_bounds`", - false => "`?Sized`", - }; + let unbound_traits = match tcx.sess.opts.unstable_opts.experimental_default_bounds { + true => "`?Sized` and `experimental_default_bounds`", + false => "`?Sized`", + }; // There was a `?Trait` bound, but it was neither `?Sized` nor `experimental_default_bounds`. tcx.dcx().span_err( unbound.span, From 280a1d8edb8322280bb9b10fab41c7bfb43d67b2 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 3 Dec 2024 00:12:24 +0000 Subject: [PATCH 111/606] Do not visit whole crate to compute `lints_that_dont_need_to_run`. --- compiler/rustc_lint/src/levels.rs | 117 ++++-------------- compiler/rustc_middle/src/query/mod.rs | 2 +- .../unsafe/proc-unsafe-attributes.rs | 2 + .../unsafe/proc-unsafe-attributes.stderr | 18 ++- .../deduplicate-diagnostics.duplicate.stderr | 10 +- tests/ui/deduplicate-diagnostics.rs | 1 + tests/ui/tool-attributes/tool_lints.rs | 1 + tests/ui/tool-attributes/tool_lints.stderr | 11 +- .../tool-attributes/unknown-lint-tool-name.rs | 1 + .../unknown-lint-tool-name.stderr | 11 +- 10 files changed, 79 insertions(+), 95 deletions(-) diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index f1fe07cfcfaa..d0b1e7bf2553 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -1,10 +1,11 @@ use rustc_ast::attr::AttributeExt; use rustc_ast_pretty::pprust; -use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; +use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; +use rustc_data_structures::unord::UnordSet; use rustc_errors::{Diag, LintDiagnostic, MultiSpan}; use rustc_feature::{Features, GateIssue}; +use rustc_hir::HirId; use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{CRATE_HIR_ID, HirId}; use rustc_index::IndexVec; use rustc_middle::bug; use rustc_middle::hir::nested_filter; @@ -115,12 +116,11 @@ impl LintLevelSets { } } -fn lints_that_dont_need_to_run(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet { +fn lints_that_dont_need_to_run(tcx: TyCtxt<'_>, (): ()) -> UnordSet { let store = unerased_lint_store(&tcx.sess); + let root_map = tcx.shallow_lint_levels_on(hir::CRATE_OWNER_ID); - let map = tcx.shallow_lint_levels_on(rustc_hir::CRATE_OWNER_ID); - - let dont_need_to_run: FxIndexSet = store + let mut dont_need_to_run: FxHashSet = store .get_lints() .into_iter() .filter(|lint| { @@ -129,24 +129,31 @@ fn lints_that_dont_need_to_run(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet { lint.future_incompatible.is_some_and(|fut| fut.reason.has_future_breakage()); !has_future_breakage && !lint.eval_always }) - .filter_map(|lint| { - let lint_level = map.lint_level_id_at_node(tcx, LintId::of(lint), CRATE_HIR_ID); - if matches!(lint_level.level, Level::Allow) - || (matches!(lint_level.src, LintLevelSource::Default)) - && lint.default_level(tcx.sess.edition()) == Level::Allow - { - Some(LintId::of(lint)) - } else { - None - } + .filter(|lint| { + let lint_level = + root_map.lint_level_id_at_node(tcx, LintId::of(lint), hir::CRATE_HIR_ID); + // Only include lints that are allowed at crate root or by default. + matches!(lint_level.level, Level::Allow) + || (matches!(lint_level.src, LintLevelSource::Default) + && lint.default_level(tcx.sess.edition()) == Level::Allow) }) + .map(|lint| LintId::of(*lint)) .collect(); - let mut visitor = LintLevelMaximum { tcx, dont_need_to_run }; - visitor.process_opts(); - tcx.hir_walk_attributes(&mut visitor); + for owner in tcx.hir_crate_items(()).owners() { + let map = tcx.shallow_lint_levels_on(owner); - visitor.dont_need_to_run + // All lints that appear with a non-allow level must be run. + for (_, specs) in map.specs.iter() { + for (lint, level_and_source) in specs.iter() { + if !matches!(level_and_source.level, Level::Allow) { + dont_need_to_run.remove(lint); + } + } + } + } + + dont_need_to_run.into() } #[instrument(level = "trace", skip(tcx), ret)] @@ -340,76 +347,6 @@ impl<'tcx> Visitor<'tcx> for LintLevelsBuilder<'_, LintLevelQueryMap<'tcx>> { } } -/// Visitor with the only function of visiting every item-like in a crate and -/// computing the highest level that every lint gets put to. -/// -/// E.g., if a crate has a global #![allow(lint)] attribute, but a single item -/// uses #[warn(lint)], this visitor will set that lint level as `Warn` -struct LintLevelMaximum<'tcx> { - tcx: TyCtxt<'tcx>, - /// The actual list of detected lints. - dont_need_to_run: FxIndexSet, -} - -impl<'tcx> LintLevelMaximum<'tcx> { - fn process_opts(&mut self) { - let store = unerased_lint_store(self.tcx.sess); - for (lint_group, level) in &self.tcx.sess.opts.lint_opts { - if *level != Level::Allow { - let Ok(lints) = store.find_lints(lint_group) else { - return; - }; - for lint in lints { - self.dont_need_to_run.swap_remove(&lint); - } - } - } - } -} - -impl<'tcx> Visitor<'tcx> for LintLevelMaximum<'tcx> { - type NestedFilter = nested_filter::All; - - fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt { - self.tcx - } - - /// FIXME(blyxyas): In a future revision, we should also graph #![allow]s, - /// but that is handled with more care - fn visit_attribute(&mut self, attribute: &'tcx hir::Attribute) { - if matches!( - Level::from_attr(attribute), - Some((Level::Warn | Level::Deny | Level::Forbid | Level::Expect | Level::ForceWarn, _)) - ) { - let store = unerased_lint_store(self.tcx.sess); - // Lint attributes are always a metalist inside a - // metalist (even with just one lint). - let Some(meta_item_list) = attribute.meta_item_list() else { return }; - - for meta_list in meta_item_list { - // Convert Path to String - let Some(meta_item) = meta_list.meta_item() else { return }; - let ident: &str = &meta_item - .path - .segments - .iter() - .map(|segment| segment.ident.as_str()) - .collect::>() - .join("::"); - let Ok(lints) = store.find_lints( - // Lint attributes can only have literals - ident, - ) else { - return; - }; - for lint in lints { - self.dont_need_to_run.swap_remove(&lint); - } - } - } - } -} - pub struct LintLevelsBuilder<'s, P> { sess: &'s Session, features: &'s Features, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 698859c663b1..b9a113b976e4 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -476,7 +476,7 @@ rustc_queries! { desc { "computing `#[expect]`ed lints in this crate" } } - query lints_that_dont_need_to_run(_: ()) -> &'tcx FxIndexSet { + query lints_that_dont_need_to_run(_: ()) -> &'tcx UnordSet { arena_cache desc { "Computing all lints that are explicitly enabled or with a default level greater than Allow" } } diff --git a/tests/ui/attributes/unsafe/proc-unsafe-attributes.rs b/tests/ui/attributes/unsafe/proc-unsafe-attributes.rs index eaf8706369a5..2f17d9620b41 100644 --- a/tests/ui/attributes/unsafe/proc-unsafe-attributes.rs +++ b/tests/ui/attributes/unsafe/proc-unsafe-attributes.rs @@ -30,6 +30,8 @@ pub fn e() {} //~| ERROR: expected identifier, found keyword `unsafe` //~| ERROR: malformed lint attribute input //~| ERROR: malformed lint attribute input +//~| ERROR: malformed lint attribute input +//~| ERROR: malformed lint attribute input pub fn f() {} fn main() {} diff --git a/tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr b/tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr index 9c5751c82e4c..25b83a26e170 100644 --- a/tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr +++ b/tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr @@ -114,6 +114,22 @@ LL | #[unsafe(allow(unsafe(dead_code)))] | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 15 previous errors +error[E0452]: malformed lint attribute input + --> $DIR/proc-unsafe-attributes.rs:26:16 + | +LL | #[unsafe(allow(unsafe(dead_code)))] + | ^^^^^^^^^^^^^^^^^ bad attribute argument + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0452]: malformed lint attribute input + --> $DIR/proc-unsafe-attributes.rs:26:16 + | +LL | #[unsafe(allow(unsafe(dead_code)))] + | ^^^^^^^^^^^^^^^^^ bad attribute argument + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 17 previous errors For more information about this error, try `rustc --explain E0452`. diff --git a/tests/ui/deduplicate-diagnostics.duplicate.stderr b/tests/ui/deduplicate-diagnostics.duplicate.stderr index 0544b993278d..48e2ba7b86aa 100644 --- a/tests/ui/deduplicate-diagnostics.duplicate.stderr +++ b/tests/ui/deduplicate-diagnostics.duplicate.stderr @@ -26,6 +26,14 @@ LL | #[deny("literal")] | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 4 previous errors +error[E0452]: malformed lint attribute input + --> $DIR/deduplicate-diagnostics.rs:8:8 + | +LL | #[deny("literal")] + | ^^^^^^^^^ bad attribute argument + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0452`. diff --git a/tests/ui/deduplicate-diagnostics.rs b/tests/ui/deduplicate-diagnostics.rs index 54bd5dd5098c..299c1f5f4610 100644 --- a/tests/ui/deduplicate-diagnostics.rs +++ b/tests/ui/deduplicate-diagnostics.rs @@ -7,4 +7,5 @@ struct S; #[deny("literal")] //~ ERROR malformed lint attribute input //[duplicate]~| ERROR malformed lint attribute input + //[duplicate]~| ERROR malformed lint attribute input fn main() {} diff --git a/tests/ui/tool-attributes/tool_lints.rs b/tests/ui/tool-attributes/tool_lints.rs index ef27532f6de1..9e4aa7a939ac 100644 --- a/tests/ui/tool-attributes/tool_lints.rs +++ b/tests/ui/tool-attributes/tool_lints.rs @@ -1,4 +1,5 @@ #[warn(foo::bar)] //~^ ERROR unknown tool name `foo` found in scoped lint: `foo::bar` //~| ERROR unknown tool name `foo` found in scoped lint: `foo::bar` +//~| ERROR unknown tool name `foo` found in scoped lint: `foo::bar` fn main() {} diff --git a/tests/ui/tool-attributes/tool_lints.stderr b/tests/ui/tool-attributes/tool_lints.stderr index f1d825caba15..eee0a9784ece 100644 --- a/tests/ui/tool-attributes/tool_lints.stderr +++ b/tests/ui/tool-attributes/tool_lints.stderr @@ -15,6 +15,15 @@ LL | #[warn(foo::bar)] = help: add `#![register_tool(foo)]` to the crate root = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 2 previous errors +error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar` + --> $DIR/tool_lints.rs:1:8 + | +LL | #[warn(foo::bar)] + | ^^^ + | + = help: add `#![register_tool(foo)]` to the crate root + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0710`. diff --git a/tests/ui/tool-attributes/unknown-lint-tool-name.rs b/tests/ui/tool-attributes/unknown-lint-tool-name.rs index 59fc56d820ee..84ab7c1944ab 100644 --- a/tests/ui/tool-attributes/unknown-lint-tool-name.rs +++ b/tests/ui/tool-attributes/unknown-lint-tool-name.rs @@ -4,4 +4,5 @@ #[allow(foo::bar)] //~ ERROR unknown tool name `foo` found in scoped lint: `foo::bar` //~| ERROR unknown tool name `foo` found in scoped lint: `foo::bar` + //~| ERROR unknown tool name `foo` found in scoped lint: `foo::bar` fn main() {} diff --git a/tests/ui/tool-attributes/unknown-lint-tool-name.stderr b/tests/ui/tool-attributes/unknown-lint-tool-name.stderr index 5d99777a14ae..91baf8827375 100644 --- a/tests/ui/tool-attributes/unknown-lint-tool-name.stderr +++ b/tests/ui/tool-attributes/unknown-lint-tool-name.stderr @@ -41,6 +41,15 @@ LL | #![deny(foo::bar)] = help: add `#![register_tool(foo)]` to the crate root = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 5 previous errors +error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar` + --> $DIR/unknown-lint-tool-name.rs:5:9 + | +LL | #[allow(foo::bar)] + | ^^^ + | + = help: add `#![register_tool(foo)]` to the crate root + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0710`. From e2c8ae96f6814ac80cdf3952a881da51867b73c8 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 4 Apr 2025 15:28:14 +0200 Subject: [PATCH 112/606] fix windows_join_multiple --- .../pass-dep/concurrency/windows_join_multiple.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/tools/miri/tests/pass-dep/concurrency/windows_join_multiple.rs b/src/tools/miri/tests/pass-dep/concurrency/windows_join_multiple.rs index ce829eee2270..2796541a3d72 100644 --- a/src/tools/miri/tests/pass-dep/concurrency/windows_join_multiple.rs +++ b/src/tools/miri/tests/pass-dep/concurrency/windows_join_multiple.rs @@ -9,6 +9,10 @@ use std::thread; use windows_sys::Win32::Foundation::{HANDLE, WAIT_OBJECT_0}; use windows_sys::Win32::System::Threading::{INFINITE, WaitForSingleObject}; +#[derive(Copy, Clone)] +struct UnsafeSendWrapper(T); +unsafe impl Send for UnsafeSendWrapper {} + fn main() { static FLAG: AtomicBool = AtomicBool::new(false); @@ -17,10 +21,12 @@ fn main() { thread::yield_now(); } }) - .into_raw_handle() as HANDLE; + .into_raw_handle(); + let blocker = UnsafeSendWrapper(blocker as HANDLE); let waiter = move || unsafe { - assert_eq!(WaitForSingleObject(blocker, INFINITE), WAIT_OBJECT_0); + let blocker = blocker; // circumvent per-field capturing + assert_eq!(WaitForSingleObject(blocker.0, INFINITE), WAIT_OBJECT_0); }; let waiter1 = thread::spawn(waiter); From ccbef74fc5a6bf5adfdd79fd15601fe91aa22c66 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Fri, 4 Apr 2025 11:16:37 +0200 Subject: [PATCH 113/606] Add tests for super let. --- tests/ui/super-let.borrowck.stderr | 174 ++++++++++++++++++ tests/ui/super-let.rs | 286 +++++++++++++++++++++++++++++ 2 files changed, 460 insertions(+) create mode 100644 tests/ui/super-let.borrowck.stderr create mode 100644 tests/ui/super-let.rs diff --git a/tests/ui/super-let.borrowck.stderr b/tests/ui/super-let.borrowck.stderr new file mode 100644 index 000000000000..01ef29d87588 --- /dev/null +++ b/tests/ui/super-let.borrowck.stderr @@ -0,0 +1,174 @@ +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/super-let.rs:30:28 + | +LL | super let b = DropMe(&mut x); + | ------ `x` is borrowed here +... +LL | #[cfg(borrowck)] { x = true; } + | ^^^^^^^^ `x` is assigned to here but it was already borrowed +... +LL | } + | - borrow might be used here, when `b` is dropped and runs the `Drop` code for type `DropMe` + +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/super-let.rs:46:28 + | +LL | super let b = &DropMe(&mut x); + | -------------- + | | | + | | `x` is borrowed here + | a temporary with access to the borrow is created here ... +... +LL | #[cfg(borrowck)] { x = true; } + | ^^^^^^^^ `x` is assigned to here but it was already borrowed +... +LL | } + | - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `DropMe` + +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/super-let.rs:64:32 + | +LL | super let b = identity(&DropMe(&mut x)); + | -------------- + | | | + | | `x` is borrowed here + | a temporary with access to the borrow is created here ... +LL | #[cfg(borrowck)] { x = true; } + | ^^^^^^^^ `x` is assigned to here but it was already borrowed +... +LL | }; + | - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `DropMe` + +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/super-let.rs:87:36 + | +LL | super let b = identity(&DropMe(&mut x)); + | -------------- + | | | + | | `x` is borrowed here + | a temporary with access to the borrow is created here ... +... +LL | #[cfg(borrowck)] { x = true; } + | ^^^^^^^^ `x` is assigned to here but it was already borrowed +... +LL | )); + | - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `DropMe` + +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/super-let.rs:107:28 + | +LL | super let b = DropMe(&mut x); + | ------ `x` is borrowed here +... +LL | #[cfg(borrowck)] { x = true; } + | ^^^^^^^^ `x` is assigned to here but it was already borrowed +... +LL | } + | - borrow might be used here, when `b` is dropped and runs the `Drop` code for type `DropMe` + +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/super-let.rs:125:28 + | +LL | super let b = DropMe(&mut x); + | ------ `x` is borrowed here +... +LL | #[cfg(borrowck)] { x = true; } + | ^^^^^^^^ `x` is assigned to here but it was already borrowed +... +LL | } + | - borrow might be used here, when `b` is dropped and runs the `Drop` code for type `DropMe` + +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/super-let.rs:143:28 + | +LL | super let b = DropMe(&mut x); + | ------ `x` is borrowed here +... +LL | #[cfg(borrowck)] { x = true; } + | ^^^^^^^^ `x` is assigned to here but it was already borrowed +... +LL | } + | - borrow might be used here, when `b` is dropped and runs the `Drop` code for type `DropMe` + +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/super-let.rs:159:28 + | +LL | b = DropMe(&mut x); + | ------ `x` is borrowed here +... +LL | #[cfg(borrowck)] { x = true; } + | ^^^^^^^^ `x` is assigned to here but it was already borrowed +LL | drop(a); + | - borrow later used here + +error[E0716]: temporary value dropped while borrowed + --> $DIR/super-let.rs:172:33 + | +LL | #[cfg(borrowck)] { a = &String::from("asdf"); }; + | ^^^^^^^^^^^^^^^^^^^^- temporary value is freed at the end of this statement + | | + | creates a temporary value which is freed while still in use +... +LL | let _ = a; + | - borrow later used here + | + = note: consider using a `let` binding to create a longer lived value + +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/super-let.rs:206:28 + | +LL | super let d = &DropMe(&mut x); + | -------------- + | | | + | | `x` is borrowed here + | a temporary with access to the borrow is created here ... +... +LL | #[cfg(borrowck)] { x = true; } + | ^^^^^^^^ `x` is assigned to here but it was already borrowed +... +LL | } + | - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `DropMe` + +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/super-let.rs:227:32 + | +LL | super let d = identity(&DropMe(&mut x)); + | -------------- + | | | + | | `x` is borrowed here + | a temporary with access to the borrow is created here ... +... +LL | #[cfg(borrowck)] { x = true; } + | ^^^^^^^^ `x` is assigned to here but it was already borrowed +... +LL | }; + | - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `DropMe` + +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/super-let.rs:246:28 + | +LL | super let b = DropMe(&mut x); + | ------ `x` is borrowed here +... +LL | #[cfg(borrowck)] { x = true; } + | ^^^^^^^^ `x` is assigned to here but it was already borrowed +... +LL | } + | - borrow might be used here, when `b` is dropped and runs the `Drop` code for type `DropMe` + +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/super-let.rs:263:28 + | +LL | let dropme = Some(DropMe(&mut x)); + | ------ `x` is borrowed here +... +LL | #[cfg(borrowck)] { x = true; } + | ^^^^^^^^ `x` is assigned to here but it was already borrowed +... +LL | } + | - borrow might be used here, when `x` is dropped and runs the `Drop` code for type `DropMe` + +error: aborting due to 13 previous errors + +Some errors have detailed explanations: E0506, E0716. +For more information about an error, try `rustc --explain E0506`. diff --git a/tests/ui/super-let.rs b/tests/ui/super-let.rs new file mode 100644 index 000000000000..380470f792fe --- /dev/null +++ b/tests/ui/super-let.rs @@ -0,0 +1,286 @@ +// Check in two ways: +// - borrowck: Check with borrow checking errors when things are alive and dead. +// - runtime: Check with a mutable bool if things are dropped on time. +// +//@ revisions: runtime borrowck +//@ [runtime] run-pass +//@ [borrowck] check-fail + +#![allow(dropping_references)] +#![feature(super_let, stmt_expr_attributes)] + +use std::convert::identity; + +struct DropMe<'a>(&'a mut bool); + +impl Drop for DropMe<'_> { + fn drop(&mut self) { + *self.0 = true; + } +} + +// Check that a super let variable lives as long as the result of a block. +fn extended_variable() { + let mut x = false; + { + let a = { + super let b = DropMe(&mut x); + &b + }; + #[cfg(borrowck)] { x = true; } //[borrowck]~ ERROR borrowed + drop(a); + // DropMe is still alive here... + } + // ... but not here. + assert_eq!(x, true) // ok +} + +// Check that the init expression of a super let is subject to (temporary) lifetime extension. +fn extended_temporary() { + let mut x = false; + { + let a = { + super let b = &DropMe(&mut x); + b + }; + #[cfg(borrowck)] { x = true; } //[borrowck]~ ERROR borrowed + drop(a); + // DropMe is still alive here... + } + // ... but not here. + assert_eq!(x, true); // ok +} + +// Check that even non-extended temporaries live until the end of the block, +// but (unlike extended temporaries) not beyond that. +// +// This is necessary for things like select(pin!(identity(&temp()))) to work. +fn non_extended() { + let mut x = false; + { + let _a = { + // Use identity() to supress temporary lifetime extension. + super let b = identity(&DropMe(&mut x)); + #[cfg(borrowck)] { x = true; } //[borrowck]~ ERROR borrowed + b + // DropMe is still alive here... + }; + // ... but not here. + assert_eq!(x, true); // ok + } +} + +// Check that even non-extended temporaries live until the end of the block, +// but (unlike extended temporaries) not beyond that. +// +// This is necessary for things like select(pin!(identity(&temp()))) to work. +fn non_extended_in_expression() { + let mut x = false; + { + identity(( + { + // Use identity() to supress temporary lifetime extension. + super let b = identity(&DropMe(&mut x)); + b + }, + { + #[cfg(borrowck)] { x = true; } //[borrowck]~ ERROR borrowed + // DropMe is still alive here... + } + )); + // ... but not here. + assert_eq!(x, true); // ok + } +} + +// Check `super let` in a match arm. +fn match_arm() { + let mut x = false; + { + let a = match Some(123) { + Some(_) => { + super let b = DropMe(&mut x); + &b + } + None => unreachable!(), + }; + #[cfg(borrowck)] { x = true; } //[borrowck]~ ERROR borrowed + drop(a); + // DropMe is still alive here... + } + // ... but not here. + assert_eq!(x, true); // ok +} + +// Check `super let` in an if body. +fn if_body() { + let mut x = false; + { + let a = if true { + super let b = DropMe(&mut x); + &b + } else { + unreachable!() + }; + #[cfg(borrowck)] { x = true; } //[borrowck]~ ERROR borrowed + drop(a); + // DropMe is still alive here... + } + // ... but not here. + assert_eq!(x, true); // ok +} + +// Check `super let` in an else body. +fn else_body() { + let mut x = false; + { + let a = if false { + unreachable!() + } else { + super let b = DropMe(&mut x); + &b + }; + #[cfg(borrowck)] { x = true; } //[borrowck]~ ERROR borrowed + drop(a); + // DropMe is still alive here... + } + // ... but not here. + assert_eq!(x, true); // ok +} + +fn without_initializer() { + let mut x = false; + { + let a = { + super let b; + b = DropMe(&mut x); + b + }; + #[cfg(borrowck)] { x = true; } //[borrowck]~ ERROR borrowed + drop(a); + // DropMe is still alive here... + } + // ... but not here. + assert_eq!(x, true); +} + +// Assignment isn't special, even when assigning to a `super let` variable. +fn assignment() { + let mut x = false; + { + super let a; + #[cfg(borrowck)] { a = &String::from("asdf"); }; //[borrowck]~ ERROR dropped while borrowed + #[cfg(runtime)] { a = drop(&DropMe(&mut x)); } // Temporary dropped at the `;` as usual. + assert_eq!(x, true); + let _ = a; + } +} + +// `super let mut` should work just fine. +fn mutable() { + let mut x = false; + { + let a = { + super let mut b = None; + &mut b + }; + *a = Some(DropMe(&mut x)); + } + assert_eq!(x, true); +} + +// Temporary lifetime extension should recurse through `super let`s. +fn multiple_levels() { + let mut x = false; + { + let a = { + super let b = { + super let c = { + super let d = &DropMe(&mut x); + d + }; + c + }; + b + }; + #[cfg(borrowck)] { x = true; } //[borrowck]~ ERROR borrowed + drop(a); + // DropMe is still alive here... + } + // ... but not here. + assert_eq!(x, true); +} + +// Non-extended temporaries should be dropped at the +// end of the first parent statement that isn't `super`. +fn multiple_levels_but_no_extension() { + let mut x = false; + { + let _a = { + super let b = { + super let c = { + super let d = identity(&DropMe(&mut x)); + d + }; + c + }; + #[cfg(borrowck)] { x = true; } //[borrowck]~ ERROR borrowed + b + // DropMe is still alive here... + }; + // ... but not here. + assert_eq!(x, true); + } +} + +// Check for potential weird interactions with `let else`. +fn super_let_and_let_else() { + let mut x = false; + { + let a = 'a: { + let Some(_) = Some(123) else { unreachable!() }; + super let b = DropMe(&mut x); + let None = Some(123) else { break 'a &b }; + unreachable!() + }; + #[cfg(borrowck)] { x = true; } //[borrowck]~ ERROR borrowed + // DropMe is still alive here... + drop(a); + } + // ... but not here. + assert_eq!(x, true); +} + +// Check if `super let .. else ..;` works. +fn super_let_else() { + let mut x = false; + { + let a = { + let dropme = Some(DropMe(&mut x)); + super let Some(x) = dropme else { unreachable!() }; + &x + }; + #[cfg(borrowck)] { x = true; } //[borrowck]~ ERROR borrowed + // DropMe is still alive here... + drop(a); + } + // ... but not here. + assert_eq!(x, true); +} + +fn main() { + extended_variable(); + extended_temporary(); + non_extended(); + non_extended_in_expression(); + match_arm(); + if_body(); + else_body(); + without_initializer(); + assignment(); + mutable(); + multiple_levels(); + multiple_levels_but_no_extension(); + super_let_and_let_else(); + super_let_else(); +} From f86832285b55bd35b0e2c0f4264b5690001d941e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 4 Apr 2025 18:05:11 +0200 Subject: [PATCH 114/606] Solaris does not have flock --- src/tools/miri/src/shims/unix/foreign_items.rs | 2 ++ src/tools/miri/tests/pass-dep/libc/libc-fs-flock.rs | 1 + 2 files changed, 3 insertions(+) diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index 1770b99c0a22..5e6259c35744 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -231,6 +231,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(result, dest)?; } "flock" => { + // Currently this function does not exist on all Unixes, e.g. on Solaris. + this.check_target_os(&["linux", "freebsd", "macos", "illumos"], link_name)?; let [fd, op] = this.check_shim(abi, Conv::C, link_name, args)?; let fd = this.read_scalar(fd)?.to_i32()?; let op = this.read_scalar(op)?.to_i32()?; diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs-flock.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs-flock.rs index 99d6d2b38f8d..116cde4b425c 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-fs-flock.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-fs-flock.rs @@ -1,4 +1,5 @@ //@ignore-target: windows # File handling is not implemented yet +//@ignore-target: solaris # Does not have flock //@compile-flags: -Zmiri-disable-isolation use std::fs::File; From 8b12153e3557318900675a0ab3fe1581ecf9d9e2 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Fri, 4 Apr 2025 16:41:40 +0000 Subject: [PATCH 115/606] Update windows-bindgen to 0.61.0 --- Cargo.lock | 6 +- .../std/src/sys/fs/windows/remove_dir_all.rs | 2 +- library/std/src/sys/pal/windows/c.rs | 4 +- .../std/src/sys/pal/windows/c/bindings.txt | 4 +- .../std/src/sys/pal/windows/c/windows_sys.rs | 303 ++++++++++++++++-- src/tools/generate-windows-sys/Cargo.toml | 2 +- 6 files changed, 290 insertions(+), 31 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 96526f7e9e7d..2ba12ea8030e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6066,11 +6066,13 @@ dependencies = [ [[package]] name = "windows-bindgen" -version = "0.59.0" +version = "0.61.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b7fb600834d7e868f6e5bb748a86101427330fafbf9485c331b9d5f562d54a5" +checksum = "ac1c59c20569610dd9ed784d5f003fb493ec57b4cf39d974eb03a84bb7156c90" dependencies = [ "rayon", + "serde", + "serde_json", ] [[package]] diff --git a/library/std/src/sys/fs/windows/remove_dir_all.rs b/library/std/src/sys/fs/windows/remove_dir_all.rs index f51eced84164..b213c49bcb00 100644 --- a/library/std/src/sys/fs/windows/remove_dir_all.rs +++ b/library/std/src/sys/fs/windows/remove_dir_all.rs @@ -95,7 +95,7 @@ fn open_link_no_reparse( ObjectName: &mut path_str, RootDirectory: parent.as_raw_handle(), Attributes: ATTRIBUTES.load(Ordering::Relaxed), - ..c::OBJECT_ATTRIBUTES::default() + ..c::OBJECT_ATTRIBUTES::with_length() }; let share = c::FILE_SHARE_DELETE | c::FILE_SHARE_READ | c::FILE_SHARE_WRITE; let options = c::FILE_OPEN_REPARSE_POINT | options; diff --git a/library/std/src/sys/pal/windows/c.rs b/library/std/src/sys/pal/windows/c.rs index 004cbee52f62..ac1c5e9932e1 100644 --- a/library/std/src/sys/pal/windows/c.rs +++ b/library/std/src/sys/pal/windows/c.rs @@ -44,8 +44,8 @@ impl UNICODE_STRING { } } -impl Default for OBJECT_ATTRIBUTES { - fn default() -> Self { +impl OBJECT_ATTRIBUTES { + pub fn with_length() -> Self { Self { Length: size_of::() as _, RootDirectory: ptr::null_mut(), diff --git a/library/std/src/sys/pal/windows/c/bindings.txt b/library/std/src/sys/pal/windows/c/bindings.txt index e2c216332796..d5fbb453c6f9 100644 --- a/library/std/src/sys/pal/windows/c/bindings.txt +++ b/library/std/src/sys/pal/windows/c/bindings.txt @@ -1,7 +1,8 @@ --out windows_sys.rs --flat --sys ---no-core +--no-deps +--link windows_targets --filter !INVALID_HANDLE_VALUE ABOVE_NORMAL_PRIORITY_CLASS @@ -19,7 +20,6 @@ ALL_PROCESSOR_GROUPS ARM64_NT_NEON128 BELOW_NORMAL_PRIORITY_CLASS bind -BOOL BY_HANDLE_FILE_INFORMATION CALLBACK_CHUNK_FINISHED CALLBACK_STREAM_SWITCH diff --git a/library/std/src/sys/pal/windows/c/windows_sys.rs b/library/std/src/sys/pal/windows/c/windows_sys.rs index 1d0e89f5d0f0..eb2914b86447 100644 --- a/library/std/src/sys/pal/windows/c/windows_sys.rs +++ b/library/std/src/sys/pal/windows/c/windows_sys.rs @@ -1,4 +1,4 @@ -// Bindings generated by `windows-bindgen` 0.59.0 +// Bindings generated by `windows-bindgen` 0.61.0 #![allow(non_snake_case, non_upper_case_globals, non_camel_case_types, dead_code, clippy::all)] @@ -141,7 +141,7 @@ windows_targets::link!("ws2_32.dll" "system" fn setsockopt(s : SOCKET, level : i windows_targets::link!("ws2_32.dll" "system" fn shutdown(s : SOCKET, how : WINSOCK_SHUTDOWN_HOW) -> i32); pub const ABOVE_NORMAL_PRIORITY_CLASS: PROCESS_CREATION_FLAGS = 32768u32; #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct ACL { pub AclRevision: u8, pub Sbz1: u8, @@ -162,6 +162,11 @@ pub struct ADDRINFOA { pub ai_addr: *mut SOCKADDR, pub ai_next: *mut ADDRINFOA, } +impl Default for ADDRINFOA { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} pub const AF_INET: ADDRESS_FAMILY = 2u16; pub const AF_INET6: ADDRESS_FAMILY = 23u16; pub const AF_UNIX: u16 = 1u16; @@ -176,8 +181,13 @@ pub union ARM64_NT_NEON128 { pub H: [u16; 8], pub B: [u8; 16], } +impl Default for ARM64_NT_NEON128 { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct ARM64_NT_NEON128_0 { pub Low: u64, pub High: i64, @@ -185,7 +195,7 @@ pub struct ARM64_NT_NEON128_0 { pub const BELOW_NORMAL_PRIORITY_CLASS: PROCESS_CREATION_FLAGS = 16384u32; pub type BOOL = i32; #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct BY_HANDLE_FILE_INFORMATION { pub dwFileAttributes: u32, pub ftCreationTime: FILETIME, @@ -206,9 +216,14 @@ pub type COMPARESTRING_RESULT = i32; pub struct CONDITION_VARIABLE { pub Ptr: *mut core::ffi::c_void, } +impl Default for CONDITION_VARIABLE { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} pub type CONSOLE_MODE = u32; #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct CONSOLE_READCONSOLE_CONTROL { pub nLength: u32, pub nInitialChars: u32, @@ -245,6 +260,12 @@ pub struct CONTEXT { pub SegSs: u32, pub ExtendedRegisters: [u8; 512], } +#[cfg(target_arch = "x86")] +impl Default for CONTEXT { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] #[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))] #[derive(Clone, Copy)] @@ -296,6 +317,12 @@ pub struct CONTEXT { pub LastExceptionToRip: u64, pub LastExceptionFromRip: u64, } +#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))] +impl Default for CONTEXT { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] #[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))] #[derive(Clone, Copy)] @@ -303,6 +330,12 @@ pub union CONTEXT_0 { pub FltSave: XSAVE_FORMAT, pub Anonymous: CONTEXT_0_0, } +#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))] +impl Default for CONTEXT_0 { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] #[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))] #[derive(Clone, Copy)] @@ -326,6 +359,12 @@ pub struct CONTEXT_0_0 { pub Xmm14: M128A, pub Xmm15: M128A, } +#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))] +impl Default for CONTEXT_0_0 { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] #[cfg(target_arch = "aarch64")] #[derive(Clone, Copy)] @@ -343,6 +382,12 @@ pub struct CONTEXT { pub Wcr: [u32; 2], pub Wvr: [u64; 2], } +#[cfg(target_arch = "aarch64")] +impl Default for CONTEXT { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] #[cfg(target_arch = "aarch64")] #[derive(Clone, Copy)] @@ -350,9 +395,15 @@ pub union CONTEXT_0 { pub Anonymous: CONTEXT_0_0, pub X: [u64; 31], } +#[cfg(target_arch = "aarch64")] +impl Default for CONTEXT_0 { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] #[cfg(target_arch = "aarch64")] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct CONTEXT_0_0 { pub X0: u64, pub X1: u64, @@ -2305,6 +2356,11 @@ pub struct EXCEPTION_POINTERS { pub ExceptionRecord: *mut EXCEPTION_RECORD, pub ContextRecord: *mut CONTEXT, } +impl Default for EXCEPTION_POINTERS { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] #[derive(Clone, Copy)] pub struct EXCEPTION_RECORD { @@ -2315,6 +2371,11 @@ pub struct EXCEPTION_RECORD { pub NumberParameters: u32, pub ExceptionInformation: [usize; 15], } +impl Default for EXCEPTION_RECORD { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} pub const EXCEPTION_STACK_OVERFLOW: NTSTATUS = 0xC00000FD_u32 as _; pub const EXTENDED_STARTUPINFO_PRESENT: PROCESS_CREATION_FLAGS = 524288u32; pub const E_NOTIMPL: HRESULT = 0x80004001_u32 as _; @@ -2333,8 +2394,13 @@ pub struct FD_SET { pub fd_count: u32, pub fd_array: [SOCKET; 64], } +impl Default for FD_SET { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct FILETIME { pub dwLowDateTime: u32, pub dwHighDateTime: u32, @@ -2343,7 +2409,7 @@ pub type FILE_ACCESS_RIGHTS = u32; pub const FILE_ADD_FILE: FILE_ACCESS_RIGHTS = 2u32; pub const FILE_ADD_SUBDIRECTORY: FILE_ACCESS_RIGHTS = 4u32; #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct FILE_ALLOCATION_INFO { pub AllocationSize: i64, } @@ -2369,7 +2435,7 @@ pub const FILE_ATTRIBUTE_REPARSE_POINT: FILE_FLAGS_AND_ATTRIBUTES = 1024u32; pub const FILE_ATTRIBUTE_SPARSE_FILE: FILE_FLAGS_AND_ATTRIBUTES = 512u32; pub const FILE_ATTRIBUTE_SYSTEM: FILE_FLAGS_AND_ATTRIBUTES = 4u32; #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct FILE_ATTRIBUTE_TAG_INFO { pub FileAttributes: u32, pub ReparseTag: u32, @@ -2378,7 +2444,7 @@ pub const FILE_ATTRIBUTE_TEMPORARY: FILE_FLAGS_AND_ATTRIBUTES = 256u32; pub const FILE_ATTRIBUTE_UNPINNED: FILE_FLAGS_AND_ATTRIBUTES = 1048576u32; pub const FILE_ATTRIBUTE_VIRTUAL: FILE_FLAGS_AND_ATTRIBUTES = 65536u32; #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct FILE_BASIC_INFO { pub CreationTime: i64, pub LastAccessTime: i64, @@ -2405,19 +2471,19 @@ pub const FILE_DISPOSITION_FLAG_IGNORE_READONLY_ATTRIBUTE: FILE_DISPOSITION_INFO pub const FILE_DISPOSITION_FLAG_ON_CLOSE: FILE_DISPOSITION_INFO_EX_FLAGS = 8u32; pub const FILE_DISPOSITION_FLAG_POSIX_SEMANTICS: FILE_DISPOSITION_INFO_EX_FLAGS = 2u32; #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct FILE_DISPOSITION_INFO { pub DeleteFile: bool, } #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct FILE_DISPOSITION_INFO_EX { pub Flags: FILE_DISPOSITION_INFO_EX_FLAGS, } pub type FILE_DISPOSITION_INFO_EX_FLAGS = u32; pub const FILE_END: SET_FILE_POINTER_MOVE_METHOD = 2u32; #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct FILE_END_OF_FILE_INFO { pub EndOfFile: i64, } @@ -2457,9 +2523,14 @@ pub struct FILE_ID_BOTH_DIR_INFO { pub FileId: i64, pub FileName: [u16; 1], } +impl Default for FILE_ID_BOTH_DIR_INFO { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} pub type FILE_INFO_BY_HANDLE_CLASS = i32; #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct FILE_IO_PRIORITY_HINT_INFO { pub PriorityHint: PRIORITY_HINT, } @@ -2494,12 +2565,22 @@ pub struct FILE_RENAME_INFO { pub FileNameLength: u32, pub FileName: [u16; 1], } +impl Default for FILE_RENAME_INFO { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] #[derive(Clone, Copy)] pub union FILE_RENAME_INFO_0 { pub ReplaceIfExists: bool, pub Flags: u32, } +impl Default for FILE_RENAME_INFO_0 { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} pub const FILE_RESERVE_OPFILTER: NTCREATEFILE_CREATE_OPTIONS = 1048576u32; pub const FILE_SEQUENTIAL_ONLY: NTCREATEFILE_CREATE_OPTIONS = 4u32; pub const FILE_SESSION_AWARE: NTCREATEFILE_CREATE_OPTIONS = 262144u32; @@ -2509,7 +2590,7 @@ pub const FILE_SHARE_NONE: FILE_SHARE_MODE = 0u32; pub const FILE_SHARE_READ: FILE_SHARE_MODE = 1u32; pub const FILE_SHARE_WRITE: FILE_SHARE_MODE = 2u32; #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct FILE_STANDARD_INFO { pub AllocationSize: i64, pub EndOfFile: i64, @@ -2549,6 +2630,12 @@ pub struct FLOATING_SAVE_AREA { pub RegisterArea: [u8; 80], pub Spare0: u32, } +#[cfg(target_arch = "x86")] +impl Default for FLOATING_SAVE_AREA { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] #[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))] #[derive(Clone, Copy)] @@ -2563,6 +2650,12 @@ pub struct FLOATING_SAVE_AREA { pub RegisterArea: [u8; 80], pub Cr0NpxState: u32, } +#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))] +impl Default for FLOATING_SAVE_AREA { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} pub const FORMAT_MESSAGE_ALLOCATE_BUFFER: FORMAT_MESSAGE_OPTIONS = 256u32; pub const FORMAT_MESSAGE_ARGUMENT_ARRAY: FORMAT_MESSAGE_OPTIONS = 8192u32; pub const FORMAT_MESSAGE_FROM_HMODULE: FORMAT_MESSAGE_OPTIONS = 2048u32; @@ -2639,12 +2732,22 @@ pub const IDLE_PRIORITY_CLASS: PROCESS_CREATION_FLAGS = 64u32; pub struct IN6_ADDR { pub u: IN6_ADDR_0, } +impl Default for IN6_ADDR { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] #[derive(Clone, Copy)] pub union IN6_ADDR_0 { pub Byte: [u8; 16], pub Word: [u16; 8], } +impl Default for IN6_ADDR_0 { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} pub const INFINITE: u32 = 4294967295u32; pub const INHERIT_CALLER_PRIORITY: PROCESS_CREATION_FLAGS = 131072u32; pub const INHERIT_PARENT_AFFINITY: PROCESS_CREATION_FLAGS = 65536u32; @@ -2653,6 +2756,11 @@ pub const INHERIT_PARENT_AFFINITY: PROCESS_CREATION_FLAGS = 65536u32; pub union INIT_ONCE { pub Ptr: *mut core::ffi::c_void, } +impl Default for INIT_ONCE { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} pub const INIT_ONCE_INIT_FAILED: u32 = 4u32; pub const INVALID_FILE_ATTRIBUTES: u32 = 4294967295u32; pub const INVALID_SOCKET: SOCKET = -1i32 as _; @@ -2661,6 +2769,11 @@ pub const INVALID_SOCKET: SOCKET = -1i32 as _; pub struct IN_ADDR { pub S_un: IN_ADDR_0, } +impl Default for IN_ADDR { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] #[derive(Clone, Copy)] pub union IN_ADDR_0 { @@ -2668,8 +2781,13 @@ pub union IN_ADDR_0 { pub S_un_w: IN_ADDR_0_1, pub S_addr: u32, } +impl Default for IN_ADDR_0 { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct IN_ADDR_0_0 { pub s_b1: u8, pub s_b2: u8, @@ -2677,7 +2795,7 @@ pub struct IN_ADDR_0_0 { pub s_b4: u8, } #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct IN_ADDR_0_1 { pub s_w1: u16, pub s_w2: u16, @@ -2690,12 +2808,22 @@ pub struct IO_STATUS_BLOCK { pub Anonymous: IO_STATUS_BLOCK_0, pub Information: usize, } +impl Default for IO_STATUS_BLOCK { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] #[derive(Clone, Copy)] pub union IO_STATUS_BLOCK_0 { pub Status: NTSTATUS, pub Pointer: *mut core::ffi::c_void, } +impl Default for IO_STATUS_BLOCK_0 { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} pub type IPPROTO = i32; pub const IPPROTO_AH: IPPROTO = 51i32; pub const IPPROTO_CBT: IPPROTO = 7i32; @@ -2742,6 +2870,11 @@ pub struct IPV6_MREQ { pub ipv6mr_multiaddr: IN6_ADDR, pub ipv6mr_interface: u32, } +impl Default for IPV6_MREQ { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} pub const IPV6_MULTICAST_LOOP: i32 = 11i32; pub const IPV6_V6ONLY: i32 = 27i32; pub const IP_ADD_MEMBERSHIP: i32 = 12i32; @@ -2752,11 +2885,16 @@ pub struct IP_MREQ { pub imr_multiaddr: IN_ADDR, pub imr_interface: IN_ADDR, } +impl Default for IP_MREQ { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} pub const IP_MULTICAST_LOOP: i32 = 11i32; pub const IP_MULTICAST_TTL: i32 = 10i32; pub const IP_TTL: i32 = 4i32; #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct LINGER { pub l_onoff: u16, pub l_linger: u16, @@ -2797,7 +2935,7 @@ pub type LPWSAOVERLAPPED_COMPLETION_ROUTINE = Option< ), >; #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct M128A { pub Low: u64, pub High: i64, @@ -2838,6 +2976,11 @@ pub struct OBJECT_ATTRIBUTES { pub SecurityDescriptor: *const SECURITY_DESCRIPTOR, pub SecurityQualityOfService: *const SECURITY_QUALITY_OF_SERVICE, } +impl Default for OBJECT_ATTRIBUTES { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} pub type OBJECT_ATTRIBUTE_FLAGS = u32; pub const OBJ_DONT_REPARSE: OBJECT_ATTRIBUTE_FLAGS = 4096u32; pub const OPEN_ALWAYS: FILE_CREATION_DISPOSITION = 4u32; @@ -2850,14 +2993,24 @@ pub struct OVERLAPPED { pub Anonymous: OVERLAPPED_0, pub hEvent: HANDLE, } +impl Default for OVERLAPPED { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] #[derive(Clone, Copy)] pub union OVERLAPPED_0 { pub Anonymous: OVERLAPPED_0_0, pub Pointer: *mut core::ffi::c_void, } +impl Default for OVERLAPPED_0 { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct OVERLAPPED_0_0 { pub Offset: u32, pub OffsetHigh: u32, @@ -2895,6 +3048,11 @@ pub struct PROCESS_INFORMATION { pub dwProcessId: u32, pub dwThreadId: u32, } +impl Default for PROCESS_INFORMATION { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} pub const PROCESS_MODE_BACKGROUND_BEGIN: PROCESS_CREATION_FLAGS = 1048576u32; pub const PROCESS_MODE_BACKGROUND_END: PROCESS_CREATION_FLAGS = 2097152u32; pub const PROFILE_KERNEL: PROCESS_CREATION_FLAGS = 536870912u32; @@ -2926,6 +3084,11 @@ pub struct SECURITY_ATTRIBUTES { pub lpSecurityDescriptor: *mut core::ffi::c_void, pub bInheritHandle: BOOL, } +impl Default for SECURITY_ATTRIBUTES { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} pub const SECURITY_CONTEXT_TRACKING: FILE_FLAGS_AND_ATTRIBUTES = 262144u32; pub const SECURITY_DELEGATION: FILE_FLAGS_AND_ATTRIBUTES = 196608u32; #[repr(C)] @@ -2939,13 +3102,18 @@ pub struct SECURITY_DESCRIPTOR { pub Sacl: *mut ACL, pub Dacl: *mut ACL, } +impl Default for SECURITY_DESCRIPTOR { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} pub type SECURITY_DESCRIPTOR_CONTROL = u16; pub const SECURITY_EFFECTIVE_ONLY: FILE_FLAGS_AND_ATTRIBUTES = 524288u32; pub const SECURITY_IDENTIFICATION: FILE_FLAGS_AND_ATTRIBUTES = 65536u32; pub const SECURITY_IMPERSONATION: FILE_FLAGS_AND_ATTRIBUTES = 131072u32; pub type SECURITY_IMPERSONATION_LEVEL = i32; #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct SECURITY_QUALITY_OF_SERVICE { pub Length: u32, pub ImpersonationLevel: SECURITY_IMPERSONATION_LEVEL, @@ -2962,6 +3130,11 @@ pub struct SOCKADDR { pub sa_family: ADDRESS_FAMILY, pub sa_data: [i8; 14], } +impl Default for SOCKADDR { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] #[derive(Clone, Copy)] pub struct SOCKADDR_STORAGE { @@ -2970,12 +3143,22 @@ pub struct SOCKADDR_STORAGE { pub __ss_align: i64, pub __ss_pad2: [i8; 112], } +impl Default for SOCKADDR_STORAGE { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] #[derive(Clone, Copy)] pub struct SOCKADDR_UN { pub sun_family: ADDRESS_FAMILY, pub sun_path: [i8; 108], } +impl Default for SOCKADDR_UN { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} pub type SOCKET = usize; pub const SOCKET_ERROR: i32 = -1i32; pub const SOCK_DGRAM: WINSOCK_SOCKET_TYPE = 2i32; @@ -2995,6 +3178,11 @@ pub const SPECIFIC_RIGHTS_ALL: FILE_ACCESS_RIGHTS = 65535u32; pub struct SRWLOCK { pub Ptr: *mut core::ffi::c_void, } +impl Default for SRWLOCK { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} pub const STACK_SIZE_PARAM_IS_A_RESERVATION: THREAD_CREATION_FLAGS = 65536u32; pub const STANDARD_RIGHTS_ALL: FILE_ACCESS_RIGHTS = 2031616u32; pub const STANDARD_RIGHTS_EXECUTE: FILE_ACCESS_RIGHTS = 131072u32; @@ -3021,6 +3209,11 @@ pub struct STARTUPINFOEXW { pub StartupInfo: STARTUPINFOW, pub lpAttributeList: LPPROC_THREAD_ATTRIBUTE_LIST, } +impl Default for STARTUPINFOEXW { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] #[derive(Clone, Copy)] pub struct STARTUPINFOW { @@ -3043,6 +3236,11 @@ pub struct STARTUPINFOW { pub hStdOutput: HANDLE, pub hStdError: HANDLE, } +impl Default for STARTUPINFOW { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} pub type STARTUPINFOW_FLAGS = u32; pub const STATUS_DELETE_PENDING: NTSTATUS = 0xC0000056_u32 as _; pub const STATUS_DIRECTORY_NOT_EMPTY: NTSTATUS = 0xC0000101_u32 as _; @@ -3078,14 +3276,24 @@ pub struct SYSTEM_INFO { pub wProcessorLevel: u16, pub wProcessorRevision: u16, } +impl Default for SYSTEM_INFO { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] #[derive(Clone, Copy)] pub union SYSTEM_INFO_0 { pub dwOemId: u32, pub Anonymous: SYSTEM_INFO_0_0, } +impl Default for SYSTEM_INFO_0 { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct SYSTEM_INFO_0_0 { pub wProcessorArchitecture: PROCESSOR_ARCHITECTURE, pub wReserved: u16, @@ -3097,7 +3305,7 @@ pub type THREAD_CREATION_FLAGS = u32; pub const TIMER_ALL_ACCESS: SYNCHRONIZATION_ACCESS_RIGHTS = 2031619u32; pub const TIMER_MODIFY_STATE: SYNCHRONIZATION_ACCESS_RIGHTS = 2u32; #[repr(C)] -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct TIMEVAL { pub tv_sec: i32, pub tv_usec: i32, @@ -3134,6 +3342,11 @@ pub struct UNICODE_STRING { pub MaximumLength: u16, pub Buffer: PWSTR, } +impl Default for UNICODE_STRING { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} pub const VOLUME_NAME_DOS: GETFINALPATHNAMEBYHANDLE_FLAGS = 0u32; pub const VOLUME_NAME_GUID: GETFINALPATHNAMEBYHANDLE_FLAGS = 1u32; pub const VOLUME_NAME_NONE: GETFINALPATHNAMEBYHANDLE_FLAGS = 4u32; @@ -3160,6 +3373,11 @@ pub struct WIN32_FIND_DATAW { pub cFileName: [u16; 260], pub cAlternateFileName: [u16; 14], } +impl Default for WIN32_FIND_DATAW { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} pub type WINSOCK_SHUTDOWN_HOW = i32; pub type WINSOCK_SOCKET_TYPE = i32; pub const WRITE_DAC: FILE_ACCESS_RIGHTS = 262144u32; @@ -3171,6 +3389,11 @@ pub struct WSABUF { pub len: u32, pub buf: PSTR, } +impl Default for WSABUF { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] #[cfg(target_arch = "x86")] #[derive(Clone, Copy)] @@ -3183,6 +3406,12 @@ pub struct WSADATA { pub iMaxUdpDg: u16, pub lpVendorInfo: PSTR, } +#[cfg(target_arch = "x86")] +impl Default for WSADATA { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] #[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))] #[derive(Clone, Copy)] @@ -3195,6 +3424,12 @@ pub struct WSADATA { pub szDescription: [i8; 257], pub szSystemStatus: [i8; 129], } +#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))] +impl Default for WSADATA { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} pub const WSAEACCES: WSA_ERROR = 10013i32; pub const WSAEADDRINUSE: WSA_ERROR = 10048i32; pub const WSAEADDRNOTAVAIL: WSA_ERROR = 10049i32; @@ -3255,6 +3490,11 @@ pub struct WSAPROTOCOLCHAIN { pub ChainLen: i32, pub ChainEntries: [u32; 7], } +impl Default for WSAPROTOCOLCHAIN { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] #[derive(Clone, Copy)] pub struct WSAPROTOCOL_INFOW { @@ -3279,6 +3519,11 @@ pub struct WSAPROTOCOL_INFOW { pub dwProviderReserved: u32, pub szProtocol: [u16; 256], } +impl Default for WSAPROTOCOL_INFOW { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} pub const WSASERVICE_NOT_FOUND: WSA_ERROR = 10108i32; pub const WSASYSCALLFAILURE: WSA_ERROR = 10107i32; pub const WSASYSNOTREADY: WSA_ERROR = 10091i32; @@ -3348,6 +3593,12 @@ pub struct XSAVE_FORMAT { pub XmmRegisters: [M128A; 8], pub Reserved4: [u8; 224], } +#[cfg(target_arch = "x86")] +impl Default for XSAVE_FORMAT { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[repr(C)] #[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))] #[derive(Clone, Copy)] @@ -3369,6 +3620,12 @@ pub struct XSAVE_FORMAT { pub XmmRegisters: [M128A; 16], pub Reserved4: [u8; 96], } +#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))] +impl Default for XSAVE_FORMAT { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } +} #[cfg(target_arch = "arm")] #[repr(C)] diff --git a/src/tools/generate-windows-sys/Cargo.toml b/src/tools/generate-windows-sys/Cargo.toml index f5c0e56bb3c2..152cd504abd1 100644 --- a/src/tools/generate-windows-sys/Cargo.toml +++ b/src/tools/generate-windows-sys/Cargo.toml @@ -4,4 +4,4 @@ version = "0.1.0" edition = "2021" [dependencies.windows-bindgen] -version = "0.59.0" +version = "0.61.0" From f343b9d1fded2e9c33a1202b3c767bb2deb7eb4d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 4 Apr 2025 02:16:12 +0000 Subject: [PATCH 116/606] Don't construct preds w escaping bound vars in diagnostic_hir_wf_check --- .../rustc_hir_analysis/src/hir_wf_check.rs | 11 +++- .../diagnostic-hir-wf-check.rs | 18 +++++ .../diagnostic-hir-wf-check.stderr | 65 +++++++++++++++++++ 3 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 tests/ui/traits/non_lifetime_binders/diagnostic-hir-wf-check.rs create mode 100644 tests/ui/traits/non_lifetime_binders/diagnostic-hir-wf-check.stderr diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs index c01b81563dcf..64c1a78bd1c8 100644 --- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs @@ -4,7 +4,7 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::{ObligationCause, WellFormedLoc}; use rustc_middle::bug; use rustc_middle::query::Providers; -use rustc_middle::ty::{self, TyCtxt, TypingMode, fold_regions}; +use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt, TypingMode, fold_regions}; use rustc_span::def_id::LocalDefId; use rustc_trait_selection::traits::{self, ObligationCtxt}; use tracing::debug; @@ -77,6 +77,15 @@ fn diagnostic_hir_wf_check<'tcx>( let tcx_ty = fold_regions(self.tcx, tcx_ty, |r, _| { if r.is_bound() { self.tcx.lifetimes.re_erased } else { r } }); + + // We may be checking the WFness of a type in an opaque with a non-lifetime bound. + // Perhaps we could rebind all the escaping bound vars, but they're coming from + // arbitrary debruijn indices and aren't particularly important anyways, since they + // are only coming from `feature(non_lifetime_binders)` anyways. + if tcx_ty.has_escaping_bound_vars() { + return; + } + let cause = traits::ObligationCause::new( ty.span, self.def_id, diff --git a/tests/ui/traits/non_lifetime_binders/diagnostic-hir-wf-check.rs b/tests/ui/traits/non_lifetime_binders/diagnostic-hir-wf-check.rs new file mode 100644 index 000000000000..74c23a59bee9 --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/diagnostic-hir-wf-check.rs @@ -0,0 +1,18 @@ +// Make sure not to construct predicates with escaping bound vars in `diagnostic_hir_wf_check`. +// Regression test for . + +#![feature(non_lifetime_binders)] +//~^ WARN the feature `non_lifetime_binders` is incomplete + +trait A {} +impl A for () {} + +trait B {} +struct W(T); + +fn b() -> (W<()>, impl for A) { (W(()), ()) } +//~^ ERROR the trait bound `(): B` is not satisfied +//~| ERROR the trait bound `(): B` is not satisfied +//~| ERROR the trait bound `(): B` is not satisfied + +fn main() {} diff --git a/tests/ui/traits/non_lifetime_binders/diagnostic-hir-wf-check.stderr b/tests/ui/traits/non_lifetime_binders/diagnostic-hir-wf-check.stderr new file mode 100644 index 000000000000..df99f4a67abb --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/diagnostic-hir-wf-check.stderr @@ -0,0 +1,65 @@ +warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/diagnostic-hir-wf-check.rs:4:12 + | +LL | #![feature(non_lifetime_binders)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #108185 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0277]: the trait bound `(): B` is not satisfied + --> $DIR/diagnostic-hir-wf-check.rs:13:12 + | +LL | fn b() -> (W<()>, impl for A) { (W(()), ()) } + | ^^^^^ the trait `B` is not implemented for `()` + | +help: this trait has no implementations, consider adding one + --> $DIR/diagnostic-hir-wf-check.rs:10:1 + | +LL | trait B {} + | ^^^^^^^ +note: required by a bound in `W` + --> $DIR/diagnostic-hir-wf-check.rs:11:13 + | +LL | struct W(T); + | ^ required by this bound in `W` + +error[E0277]: the trait bound `(): B` is not satisfied + --> $DIR/diagnostic-hir-wf-check.rs:13:42 + | +LL | fn b() -> (W<()>, impl for A) { (W(()), ()) } + | - ^^ the trait `B` is not implemented for `()` + | | + | required by a bound introduced by this call + | +help: this trait has no implementations, consider adding one + --> $DIR/diagnostic-hir-wf-check.rs:10:1 + | +LL | trait B {} + | ^^^^^^^ +note: required by a bound in `W` + --> $DIR/diagnostic-hir-wf-check.rs:11:13 + | +LL | struct W(T); + | ^ required by this bound in `W` + +error[E0277]: the trait bound `(): B` is not satisfied + --> $DIR/diagnostic-hir-wf-check.rs:13:40 + | +LL | fn b() -> (W<()>, impl for A) { (W(()), ()) } + | ^^^^^ the trait `B` is not implemented for `()` + | +help: this trait has no implementations, consider adding one + --> $DIR/diagnostic-hir-wf-check.rs:10:1 + | +LL | trait B {} + | ^^^^^^^ +note: required by a bound in `W` + --> $DIR/diagnostic-hir-wf-check.rs:11:13 + | +LL | struct W(T); + | ^ required by this bound in `W` + +error: aborting due to 3 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. From 6dfbe7c986d55a5a48f625d37d4576092e5638eb Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 4 Apr 2025 21:36:03 +0000 Subject: [PATCH 117/606] Detect and provide suggestion for `&raw EXPR` --- compiler/rustc_ast/src/ast.rs | 11 ++ .../rustc_parse/src/parser/diagnostics.rs | 21 ++++ compiler/rustc_parse/src/parser/expr.rs | 12 ++ compiler/rustc_parse/src/parser/stmt.rs | 6 +- tests/ui/parser/recover/raw-no-const-mut.rs | 31 +++++ .../ui/parser/recover/raw-no-const-mut.stderr | 109 ++++++++++++++++++ 6 files changed, 189 insertions(+), 1 deletion(-) create mode 100644 tests/ui/parser/recover/raw-no-const-mut.rs create mode 100644 tests/ui/parser/recover/raw-no-const-mut.stderr diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 33c20602dfd2..77b181974823 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -120,6 +120,17 @@ impl Path { Path { segments: thin_vec![PathSegment::from_ident(ident)], span: ident.span, tokens: None } } + pub fn is_ident(&self, name: Symbol) -> bool { + if let [segment] = self.segments.as_ref() + && segment.args.is_none() + && segment.ident.name == name + { + true + } else { + false + } + } + pub fn is_global(&self) -> bool { self.segments.first().is_some_and(|segment| segment.ident.name == kw::PathRoot) } diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index ef044fe9d638..2f026a77a0fb 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -609,6 +609,8 @@ impl<'a> Parser<'a> { // FIXME: translation requires list formatting (for `expect`) let mut err = self.dcx().struct_span_err(self.token.span, msg_exp); + self.label_expected_raw_ref(&mut err); + // Look for usages of '=>' where '>=' was probably intended if self.token == token::FatArrow && expected.iter().any(|tok| matches!(tok, TokenType::Operator | TokenType::Le)) @@ -750,6 +752,25 @@ impl<'a> Parser<'a> { Err(err) } + /// Adds a label when `&raw EXPR` was written instead of `&raw const EXPR`/`&raw mut EXPR`. + /// + /// Given that not all parser diagnostics flow through `expected_one_of_not_found`, this + /// label may need added to other diagnostics emission paths as needed. + pub(super) fn label_expected_raw_ref(&mut self, err: &mut Diag<'_>) { + if self.prev_token.is_keyword(kw::Raw) + && self.expected_token_types.contains(TokenType::KwMut) + && self.expected_token_types.contains(TokenType::KwConst) + && self.token.can_begin_expr() + { + err.span_suggestions( + self.prev_token.span.shrink_to_hi(), + "`&raw` must be followed by `const` or `mut` to be a raw reference expression", + [" const".to_string(), " mut".to_string()], + Applicability::MaybeIncorrect, + ); + } + } + /// Checks if the current token or the previous token are misspelled keywords /// and adds a helpful suggestion. fn check_for_misspelled_kw(&self, err: &mut Diag<'_>, expected: &[TokenType]) { diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index e1e6b93abf35..8ae660cb780f 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -829,6 +829,18 @@ impl<'a> Parser<'a> { if let Some(lt) = lifetime { self.error_remove_borrow_lifetime(span, lt.ident.span.until(expr.span)); } + + // Add expected tokens if we parsed `&raw` as an expression. + // This will make sure we see "expected `const`, `mut`", and + // guides recovery in case we write `&raw expr`. + if borrow_kind == ast::BorrowKind::Ref + && mutbl == ast::Mutability::Not + && matches!(&expr.kind, ExprKind::Path(None, p) if p.is_ident(kw::Raw)) + { + self.expected_token_types.insert(TokenType::KwMut); + self.expected_token_types.insert(TokenType::KwConst); + } + Ok((span, ExprKind::AddrOf(borrow_kind, mutbl, expr))) } diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 2cd09aa8959c..040de133c927 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -516,7 +516,11 @@ impl<'a> Parser<'a> { let prev = self.prev_token.span; let sp = self.token.span; let mut e = self.dcx().struct_span_err(sp, msg); - let do_not_suggest_help = self.token.is_keyword(kw::In) || self.token == token::Colon; + self.label_expected_raw_ref(&mut e); + + let do_not_suggest_help = self.token.is_keyword(kw::In) + || self.token == token::Colon + || self.prev_token.is_keyword(kw::Raw); // Check to see if the user has written something like // diff --git a/tests/ui/parser/recover/raw-no-const-mut.rs b/tests/ui/parser/recover/raw-no-const-mut.rs new file mode 100644 index 000000000000..d0ae69cc3084 --- /dev/null +++ b/tests/ui/parser/recover/raw-no-const-mut.rs @@ -0,0 +1,31 @@ +fn a() { + let x = &raw 1; + //~^ ERROR expected one of +} + +fn b() { + [&raw const 1, &raw 2] + //~^ ERROR expected one of + //~| ERROR cannot find value `raw` in this scope + //~| ERROR cannot take address of a temporary +} + +fn c() { + if x == &raw z {} + //~^ ERROR expected `{` +} + +fn d() { + f(&raw 2); + //~^ ERROR expected one of + //~| ERROR cannot find value `raw` in this scope + //~| ERROR cannot find function `f` in this scope +} + +fn e() { + let x; + x = &raw 1; + //~^ ERROR expected one of +} + +fn main() {} diff --git a/tests/ui/parser/recover/raw-no-const-mut.stderr b/tests/ui/parser/recover/raw-no-const-mut.stderr new file mode 100644 index 000000000000..65032c807953 --- /dev/null +++ b/tests/ui/parser/recover/raw-no-const-mut.stderr @@ -0,0 +1,109 @@ +error: expected one of `!`, `.`, `::`, `;`, `?`, `const`, `else`, `mut`, `{`, or an operator, found `1` + --> $DIR/raw-no-const-mut.rs:2:18 + | +LL | let x = &raw 1; + | ^ expected one of 10 possible tokens + | +help: `&raw` must be followed by `const` or `mut` to be a raw reference expression + | +LL | let x = &raw const 1; + | +++++ +LL | let x = &raw mut 1; + | +++ + +error: expected one of `!`, `,`, `.`, `::`, `?`, `]`, `const`, `mut`, `{`, or an operator, found `2` + --> $DIR/raw-no-const-mut.rs:7:25 + | +LL | [&raw const 1, &raw 2] + | ^ expected one of 10 possible tokens + | +help: `&raw` must be followed by `const` or `mut` to be a raw reference expression + | +LL | [&raw const 1, &raw const 2] + | +++++ +LL | [&raw const 1, &raw mut 2] + | +++ +help: missing `,` + | +LL | [&raw const 1, &raw, 2] + | + + +error: expected `{`, found `z` + --> $DIR/raw-no-const-mut.rs:14:18 + | +LL | if x == &raw z {} + | ^ expected `{` + | +note: the `if` expression is missing a block after this condition + --> $DIR/raw-no-const-mut.rs:14:8 + | +LL | if x == &raw z {} + | ^^^^^^^^^ +help: `&raw` must be followed by `const` or `mut` to be a raw reference expression + | +LL | if x == &raw const z {} + | +++++ +LL | if x == &raw mut z {} + | +++ + +error: expected one of `!`, `)`, `,`, `.`, `::`, `?`, `const`, `mut`, `{`, or an operator, found `2` + --> $DIR/raw-no-const-mut.rs:19:12 + | +LL | f(&raw 2); + | ^ expected one of 10 possible tokens + | +help: `&raw` must be followed by `const` or `mut` to be a raw reference expression + | +LL | f(&raw const 2); + | +++++ +LL | f(&raw mut 2); + | +++ +help: missing `,` + | +LL | f(&raw, 2); + | + + +error: expected one of `!`, `.`, `::`, `;`, `?`, `const`, `mut`, `{`, `}`, or an operator, found `1` + --> $DIR/raw-no-const-mut.rs:27:14 + | +LL | x = &raw 1; + | ^ expected one of 10 possible tokens + | +help: `&raw` must be followed by `const` or `mut` to be a raw reference expression + | +LL | x = &raw const 1; + | +++++ +LL | x = &raw mut 1; + | +++ + +error[E0425]: cannot find value `raw` in this scope + --> $DIR/raw-no-const-mut.rs:7:21 + | +LL | [&raw const 1, &raw 2] + | ^^^ not found in this scope + +error[E0425]: cannot find value `raw` in this scope + --> $DIR/raw-no-const-mut.rs:19:8 + | +LL | f(&raw 2); + | ^^^ not found in this scope + +error[E0745]: cannot take address of a temporary + --> $DIR/raw-no-const-mut.rs:7:17 + | +LL | [&raw const 1, &raw 2] + | ^ temporary value + +error[E0425]: cannot find function `f` in this scope + --> $DIR/raw-no-const-mut.rs:19:5 + | +LL | fn a() { + | ------ similarly named function `a` defined here +... +LL | f(&raw 2); + | ^ help: a function with a similar name exists: `a` + +error: aborting due to 9 previous errors + +Some errors have detailed explanations: E0425, E0745. +For more information about an error, try `rustc --explain E0425`. From 41fcdab3b5549ed93c87409bcf0b526a39d8b31c Mon Sep 17 00:00:00 2001 From: clubby789 Date: Thu, 3 Apr 2025 13:28:10 +0000 Subject: [PATCH 118/606] Switch `time` to `jiff` for time formatting in ICE dumps --- Cargo.lock | 54 +--------------------- compiler/rustc_driver_impl/Cargo.toml | 2 +- compiler/rustc_driver_impl/src/lib.rs | 13 ++---- src/bootstrap/src/utils/proc_macro_deps.rs | 2 - src/tools/tidy/src/deps.rs | 9 ++-- 5 files changed, 8 insertions(+), 72 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 96526f7e9e7d..3c96e195191c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -890,15 +890,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "deranged" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" -dependencies = [ - "powerfmt", -] - [[package]] name = "derive-where" version = "1.2.7" @@ -2385,12 +2376,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-conv" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" - [[package]] name = "num-integer" version = "0.1.46" @@ -2768,12 +2753,6 @@ dependencies = [ "portable-atomic", ] -[[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - [[package]] name = "ppv-lite86" version = "0.2.21" @@ -3572,6 +3551,7 @@ name = "rustc_driver_impl" version = "0.0.0" dependencies = [ "ctrlc", + "jiff", "libc", "rustc_abi", "rustc_ast", @@ -3618,7 +3598,6 @@ dependencies = [ "rustc_ty_utils", "serde_json", "shlex", - "time", "tracing", "windows 0.59.0", ] @@ -5311,37 +5290,6 @@ dependencies = [ "libc", ] -[[package]] -name = "time" -version = "0.3.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" -dependencies = [ - "deranged", - "itoa", - "num-conv", - "powerfmt", - "serde", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" - -[[package]] -name = "time-macros" -version = "0.2.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" -dependencies = [ - "num-conv", - "time-core", -] - [[package]] name = "tinystr" version = "0.7.6" diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index de643355f5f4..c823d11126e2 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -4,6 +4,7 @@ version = "0.0.0" edition = "2024" [dependencies] +jiff = { version = "0.2.5", default-features = false, features = ["std"] } # tidy-alphabetical-start rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } @@ -50,7 +51,6 @@ rustc_trait_selection = { path = "../rustc_trait_selection" } rustc_ty_utils = { path = "../rustc_ty_utils" } serde_json = "1.0.59" shlex = "1.0" -time = { version = "0.3.36", default-features = false, features = ["alloc", "formatting", "macros"] } tracing = { version = "0.1.35" } # tidy-alphabetical-end diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index f1dc4bb795e5..75478d9fdea3 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -30,7 +30,7 @@ use std::path::{Path, PathBuf}; use std::process::{self, Command, Stdio}; use std::sync::OnceLock; use std::sync::atomic::{AtomicBool, Ordering}; -use std::time::{Instant, SystemTime}; +use std::time::Instant; use std::{env, str}; use rustc_ast as ast; @@ -66,8 +66,6 @@ use rustc_session::{EarlyDiagCtxt, Session, config, filesearch}; use rustc_span::FileName; use rustc_target::json::ToJson; use rustc_target::spec::{Target, TargetTuple}; -use time::OffsetDateTime; -use time::macros::format_description; use tracing::trace; #[allow(unused_macros)] @@ -1304,13 +1302,8 @@ fn ice_path_with_config(config: Option<&UnstableOptions>) -> &'static Option Date: Fri, 4 Apr 2025 20:16:28 +0300 Subject: [PATCH 119/606] create new option `build.compiletest-use-stage0-libtest` Signed-off-by: onur-ozkan --- bootstrap.example.toml | 5 ++++- src/bootstrap/src/core/config/config.rs | 6 ++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/bootstrap.example.toml b/bootstrap.example.toml index 2a98821f2252..0927f648635c 100644 --- a/bootstrap.example.toml +++ b/bootstrap.example.toml @@ -28,7 +28,7 @@ # - A new option # - A change in the default values # -# If the change-id does not match the version currently in use, x.py will +# If the change-id does not match the version currently in use, x.py will # display the changes made to the bootstrap. # To suppress these warnings, you can set change-id = "ignore". #change-id = @@ -442,6 +442,9 @@ # What custom diff tool to use for displaying compiletest tests. #compiletest-diff-tool = +# Whether to use the precompiled stage0 libtest with compiletest. +#compiletest-use-stage0-libtest = true + # Indicates whether ccache is used when building certain artifacts (e.g. LLVM). # Set to `true` to use the first `ccache` in PATH, or set an absolute path to use # a specific version. diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 1712be7f947f..d83731e0f089 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -417,6 +417,9 @@ pub struct Config { /// Command for visual diff display, e.g. `diff-tool --color=always`. pub compiletest_diff_tool: Option, + /// Whether to use the precompiled stage0 libtest with compiletest. + pub compiletest_use_stage0_libtest: bool, + pub is_running_on_ci: bool, } @@ -983,6 +986,7 @@ define_config! { optimized_compiler_builtins: Option = "optimized-compiler-builtins", jobs: Option = "jobs", compiletest_diff_tool: Option = "compiletest-diff-tool", + compiletest_use_stage0_libtest: Option = "compiletest-use-stage0-libtest", ccache: Option = "ccache", exclude: Option> = "exclude", } @@ -1682,6 +1686,7 @@ impl Config { optimized_compiler_builtins, jobs, compiletest_diff_tool, + compiletest_use_stage0_libtest, mut ccache, exclude, } = toml.build.unwrap_or_default(); @@ -2415,6 +2420,7 @@ impl Config { config.optimized_compiler_builtins = optimized_compiler_builtins.unwrap_or(config.channel != "dev"); config.compiletest_diff_tool = compiletest_diff_tool; + config.compiletest_use_stage0_libtest = compiletest_use_stage0_libtest.unwrap_or(true); let download_rustc = config.download_rustc_commit.is_some(); config.explicit_stage_from_cli = flags.stage.is_some(); From 17fad21702c8d20dd7c84dd8e6122dc777059d76 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Fri, 4 Apr 2025 20:40:57 +0300 Subject: [PATCH 120/606] utilize `compiletest_use_stage0_libtest` option Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/tool.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index cd57e06ae04a..b58d279359e3 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -425,11 +425,14 @@ macro_rules! bootstrap_tool { } )* + let is_unstable = false $(|| $unstable)*; + let compiletest_wants_stage0 = $tool_name == "compiletest" && builder.config.compiletest_use_stage0_libtest; + builder.ensure(ToolBuild { compiler: self.compiler, target: self.target, tool: $tool_name, - mode: if false $(|| $unstable)* { + mode: if is_unstable && !compiletest_wants_stage0 { // use in-tree libraries for unstable features Mode::ToolStd } else { From afe3834bced04aad06233f138cc4293b9e503215 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Fri, 4 Apr 2025 20:58:58 +0300 Subject: [PATCH 121/606] add change-entry Signed-off-by: onur-ozkan --- src/bootstrap/src/utils/change_tracker.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index 244391739f38..48b6f77e8a58 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -391,4 +391,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ severity: ChangeSeverity::Info, summary: "You can now use `change-id = \"ignore\"` to suppress `change-id ` warnings in the console.", }, + ChangeInfo { + change_id: 139386, + severity: ChangeSeverity::Info, + summary: "Added a new option `build.compiletest-use-stage0-libtest` to force `compiletest` to use the stage 0 libtest.", + }, ]; From 1c568bbe6fa17dd3e6fd659aa311145ab4f573d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sat, 5 Apr 2025 13:14:27 +0200 Subject: [PATCH 122/606] Reuse the index from promoted nodes when coloring executed tasks --- .../rustc_query_system/src/dep_graph/graph.rs | 83 +++++++++++-------- .../src/dep_graph/serialized.rs | 41 ++++++++- 2 files changed, 88 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 9f34417973ed..56fd3a660d0c 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -141,7 +141,7 @@ impl DepGraph { let colors = DepNodeColorMap::new(prev_graph_node_count); // Instantiate a node with zero dependencies only once for anonymous queries. - let _green_node_index = current.alloc_node( + let _green_node_index = current.alloc_new_node( DepNode { kind: D::DEP_KIND_ANON_ZERO_DEPS, hash: current.anon_id_seed.into() }, EdgesVec::new(), Fingerprint::ZERO, @@ -149,7 +149,7 @@ impl DepGraph { assert_eq!(_green_node_index, DepNodeIndex::SINGLETON_ZERO_DEPS_ANON_NODE); // Instantiate a dependy-less red node only once for anonymous queries. - let red_node_index = current.alloc_node( + let red_node_index = current.alloc_new_node( DepNode { kind: D::DEP_KIND_RED, hash: Fingerprint::ZERO.into() }, EdgesVec::new(), Fingerprint::ZERO, @@ -438,7 +438,7 @@ impl DepGraphData { // memory impact of this `anon_node_to_index` map remains tolerable, and helps // us avoid useless growth of the graph with almost-equivalent nodes. self.current.anon_node_to_index.get_or_insert_with(target_dep_node, || { - self.current.alloc_node(target_dep_node, task_deps, Fingerprint::ZERO) + self.current.alloc_new_node(target_dep_node, task_deps, Fingerprint::ZERO) }) } }; @@ -680,8 +680,8 @@ impl DepGraphData { qcx: Qcx, diagnostic: &DiagInner, ) -> DepNodeIndex { - // Use `send` so we get an unique index, even though the dep node is not. - let dep_node_index = self.current.encoder.send( + // Use `send_new` so we get an unique index, even though the dep node is not. + let dep_node_index = self.current.encoder.send_new( DepNode { kind: D::DEP_KIND_SIDE_EFFECT, hash: PackedFingerprint::from(Fingerprint::ZERO), @@ -713,20 +713,22 @@ impl DepGraphData { } } - // Manually recreate the node as `promote_node_and_deps_to_current` expects all - // green dependencies. - let dep_node_index = self.current.encoder.send( + // Use `send_and_color` as `promote_node_and_deps_to_current` expects all + // green dependencies. `send_and_color` will also prevent multiple nodes + // being encoded for concurrent calls. + let dep_node_index = self.current.encoder.send_and_color( + prev_index, + &self.colors, DepNode { kind: D::DEP_KIND_SIDE_EFFECT, hash: PackedFingerprint::from(Fingerprint::ZERO), }, Fingerprint::ZERO, std::iter::once(DepNodeIndex::FOREVER_RED_NODE).collect(), + true, ); + // This will just overwrite the same value for concurrent calls. qcx.store_side_effect(dep_node_index, side_effect); - - // Mark the node as green. - self.colors.insert(prev_index, DepNodeColor::Green(dep_node_index)); }) } @@ -736,38 +738,43 @@ impl DepGraphData { edges: EdgesVec, fingerprint: Option, ) -> DepNodeIndex { - let dep_node_index = - self.current.alloc_node(key, edges, fingerprint.unwrap_or(Fingerprint::ZERO)); - if let Some(prev_index) = self.previous.node_to_index_opt(&key) { // Determine the color and index of the new `DepNode`. - let color = if let Some(fingerprint) = fingerprint { + let is_green = if let Some(fingerprint) = fingerprint { if fingerprint == self.previous.fingerprint_by_index(prev_index) { // This is a green node: it existed in the previous compilation, // its query was re-executed, and it has the same result as before. - DepNodeColor::Green(dep_node_index) + true } else { // This is a red node: it existed in the previous compilation, its query // was re-executed, but it has a different result from before. - DepNodeColor::Red + false } } else { // This is a red node, effectively: it existed in the previous compilation // session, its query was re-executed, but it doesn't compute a result hash // (i.e. it represents a `no_hash` query), so we have no way of determining // whether or not the result was the same as before. - DepNodeColor::Red + false }; - debug_assert!( - self.colors.get(prev_index).is_none(), - "DepGraph::with_task() - Duplicate DepNodeColor insertion for {key:?}", + let fingerprint = fingerprint.unwrap_or(Fingerprint::ZERO); + + let dep_node_index = self.current.encoder.send_and_color( + prev_index, + &self.colors, + key, + fingerprint, + edges, + is_green, ); - self.colors.insert(prev_index, color); - } + self.current.record_node(dep_node_index, key, fingerprint); - dep_node_index + dep_node_index + } else { + self.current.alloc_new_node(key, edges, fingerprint.unwrap_or(Fingerprint::ZERO)) + } } fn promote_node_and_deps_to_current(&self, prev_index: SerializedDepNodeIndex) -> DepNodeIndex { @@ -1246,19 +1253,15 @@ impl CurrentDepGraph { assert_eq!(previous, fingerprint, "Unstable fingerprints for {:?}", key); } - /// Writes the node to the current dep-graph and allocates a `DepNodeIndex` for it. - /// Assumes that this is a node that has no equivalent in the previous dep-graph. #[inline(always)] - fn alloc_node( + fn record_node( &self, + dep_node_index: DepNodeIndex, key: DepNode, - edges: EdgesVec, - current_fingerprint: Fingerprint, - ) -> DepNodeIndex { - let dep_node_index = self.encoder.send(key, current_fingerprint, edges); - + _current_fingerprint: Fingerprint, + ) { #[cfg(debug_assertions)] - self.record_edge(dep_node_index, key, current_fingerprint); + self.record_edge(dep_node_index, key, _current_fingerprint); if let Some(ref nodes_in_current_session) = self.nodes_in_current_session { outline(|| { @@ -1267,6 +1270,20 @@ impl CurrentDepGraph { } }); } + } + + /// Writes the node to the current dep-graph and allocates a `DepNodeIndex` for it. + /// Assumes that this is a node that has no equivalent in the previous dep-graph. + #[inline(always)] + fn alloc_new_node( + &self, + key: DepNode, + edges: EdgesVec, + current_fingerprint: Fingerprint, + ) -> DepNodeIndex { + let dep_node_index = self.encoder.send_new(key, current_fingerprint, edges); + + self.record_node(dep_node_index, key, current_fingerprint); dep_node_index } diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs index 7750d6d1fef4..7556a2456aae 100644 --- a/compiler/rustc_query_system/src/dep_graph/serialized.rs +++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs @@ -707,7 +707,8 @@ impl GraphEncoder { } } - pub(crate) fn send( + /// Encodes a node that does not exists in the previous graph. + pub(crate) fn send_new( &self, node: DepNode, fingerprint: Fingerprint, @@ -718,6 +719,40 @@ impl GraphEncoder { self.status.lock().as_mut().unwrap().encode_node(&node, &self.record_graph) } + /// Encodes a node that exists in the previous graph, but was re-executed. + /// + /// This will also ensure the dep node is colored either red or green. + pub(crate) fn send_and_color( + &self, + prev_index: SerializedDepNodeIndex, + colors: &DepNodeColorMap, + node: DepNode, + fingerprint: Fingerprint, + edges: EdgesVec, + is_green: bool, + ) -> DepNodeIndex { + let _prof_timer = self.profiler.generic_activity("incr_comp_encode_dep_graph"); + let node = NodeInfo { node, fingerprint, edges }; + + let mut status = self.status.lock(); + let status = status.as_mut().unwrap(); + + // Check colors inside the lock to avoid racing when `send_promoted` is called concurrently + // on the same index. + match colors.get(prev_index) { + None => { + let dep_node_index = status.encode_node(&node, &self.record_graph); + colors.insert( + prev_index, + if is_green { DepNodeColor::Green(dep_node_index) } else { DepNodeColor::Red }, + ); + dep_node_index + } + Some(DepNodeColor::Green(dep_node_index)) => dep_node_index, + Some(DepNodeColor::Red) => panic!(), + } + } + /// Encodes a node that was promoted from the previous graph. It reads the information directly from /// the previous dep graph and expects all edges to already have a new dep node index assigned. /// @@ -733,8 +768,8 @@ impl GraphEncoder { let mut status = self.status.lock(); let status = status.as_mut().unwrap(); - // Check colors inside the lock to avoid racing when `send_promoted` is called concurrently - // on the same index. + // Check colors inside the lock to avoid racing when `send_promoted` or `send_and_color` + // is called concurrently on the same index. match colors.get(prev_index) { None => { let dep_node_index = From 0acac2cbe306b8db9bc0a7c45f529f1dfa6680c8 Mon Sep 17 00:00:00 2001 From: Thalia Archibald Date: Wed, 26 Mar 2025 00:38:28 -0700 Subject: [PATCH 123/606] std: Fix build for NuttX targets Fix std build for all NuttX targets. It is the single largest set of failures on . Although, ESP-IDF also requires these same gates, there are other issues for those targets. This can verified be running `x check library/std --target=` for all NuttX targets. --- library/std/src/sys/fd/unix.rs | 2 ++ library/std/src/sys/net/connection/socket/unix.rs | 1 + 2 files changed, 3 insertions(+) diff --git a/library/std/src/sys/fd/unix.rs b/library/std/src/sys/fd/unix.rs index 2042ea2c73d0..13fefb4031d0 100644 --- a/library/std/src/sys/fd/unix.rs +++ b/library/std/src/sys/fd/unix.rs @@ -71,9 +71,11 @@ const fn max_iov() -> usize { target_os = "android", target_os = "dragonfly", target_os = "emscripten", + target_os = "espidf", target_os = "freebsd", target_os = "linux", target_os = "netbsd", + target_os = "nuttx", target_os = "nto", target_os = "openbsd", target_os = "horizon", diff --git a/library/std/src/sys/net/connection/socket/unix.rs b/library/std/src/sys/net/connection/socket/unix.rs index bbe1e038dccf..b35d5d2aa841 100644 --- a/library/std/src/sys/net/connection/socket/unix.rs +++ b/library/std/src/sys/net/connection/socket/unix.rs @@ -1,5 +1,6 @@ use libc::{MSG_PEEK, c_int, c_void, size_t, sockaddr, socklen_t}; +#[cfg(not(any(target_os = "espidf", target_os = "nuttx")))] use crate::ffi::CStr; use crate::io::{self, BorrowedBuf, BorrowedCursor, IoSlice, IoSliceMut}; use crate::net::{Shutdown, SocketAddr}; From 45afefa7c025f3847439822b053edf76ae62e561 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 5 Apr 2025 19:33:47 +0000 Subject: [PATCH 124/606] Fix trait upcasting to dyn type with no principal when there are projections --- .../src/traits/select/confirmation.rs | 38 ++++++++++++------- .../dyn-drop-principal-with-projections.rs | 13 +++++++ 2 files changed, 37 insertions(+), 14 deletions(-) create mode 100644 tests/ui/traits/dyn-drop-principal-with-projections.rs diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 2cb7d2d89313..9d5eb551fe6f 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -1090,26 +1090,36 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { { // See `assemble_candidates_for_unsizing` for more info. // We already checked the compatibility of auto traits within `assemble_candidates_for_unsizing`. - let iter = data_a - .principal() - .filter(|_| { - // optionally drop the principal, if we're unsizing to no principal - data_b.principal().is_some() - }) - .map(|b| b.map_bound(ty::ExistentialPredicate::Trait)) - .into_iter() - .chain( + let existential_predicates = if data_b.principal().is_some() { + tcx.mk_poly_existential_predicates_from_iter( data_a - .projection_bounds() - .map(|b| b.map_bound(ty::ExistentialPredicate::Projection)), + .principal() + .map(|b| b.map_bound(ty::ExistentialPredicate::Trait)) + .into_iter() + .chain( + data_a + .projection_bounds() + .map(|b| b.map_bound(ty::ExistentialPredicate::Projection)), + ) + .chain( + data_b + .auto_traits() + .map(ty::ExistentialPredicate::AutoTrait) + .map(ty::Binder::dummy), + ), ) - .chain( + } else { + // If we're unsizing to a dyn type that has no principal, then drop + // the principal and projections from the type. We use the auto traits + // from the RHS type since as we noted that we've checked for auto + // trait compatibility during unsizing. + tcx.mk_poly_existential_predicates_from_iter( data_b .auto_traits() .map(ty::ExistentialPredicate::AutoTrait) .map(ty::Binder::dummy), - ); - let existential_predicates = tcx.mk_poly_existential_predicates_from_iter(iter); + ) + }; let source_trait = Ty::new_dynamic(tcx, existential_predicates, r_b, dyn_a); // Require that the traits involved in this upcast are **equal**; diff --git a/tests/ui/traits/dyn-drop-principal-with-projections.rs b/tests/ui/traits/dyn-drop-principal-with-projections.rs new file mode 100644 index 000000000000..912061847c69 --- /dev/null +++ b/tests/ui/traits/dyn-drop-principal-with-projections.rs @@ -0,0 +1,13 @@ +//@ check-pass + +trait Tr { + type Assoc; +} + +impl Tr for () { + type Assoc = (); +} + +fn main() { + let x = &() as &(dyn Tr + Send) as &dyn Send; +} From b8c4c163f0e2e3438eb474c6b0ae5fa545061aa9 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 5 Apr 2025 20:37:56 +0000 Subject: [PATCH 125/606] Suppress missing field error when autoderef bottoms out in infer --- compiler/rustc_hir_typeck/src/expr.rs | 9 +++++++-- tests/ui/typeck/issue-65611.rs | 1 - tests/ui/typeck/issue-65611.stderr | 11 ++--------- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 45ab8e03db57..64465b609ade 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -2915,8 +2915,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } // We failed to check the expression, report an error. - // Emits an error if we deref an infer variable, like calling `.field` on a base type of &_. - self.structurally_resolve_type(autoderef.span(), autoderef.final_ty(false)); + // Emits an error if we deref an infer variable, like calling `.field` on a base type + // of `&_`. We can also use this to suppress unnecessary "missing field" errors that + // will follow ambiguity errors. + let final_ty = self.structurally_resolve_type(autoderef.span(), autoderef.final_ty(false)); + if let ty::Error(_) = final_ty.kind() { + return final_ty; + } if let Some((adjustments, did)) = private_candidate { // (#90483) apply adjustments to avoid ExprUseVisitor from diff --git a/tests/ui/typeck/issue-65611.rs b/tests/ui/typeck/issue-65611.rs index 7645311496d8..0dae75927a86 100644 --- a/tests/ui/typeck/issue-65611.rs +++ b/tests/ui/typeck/issue-65611.rs @@ -58,6 +58,5 @@ fn main() { let mut buffer = ArrayVec::new(); let x = buffer.last().unwrap().0.clone(); //~^ ERROR type annotations needed - //~| ERROR no field `0` on type `&_` buffer.reverse(); } diff --git a/tests/ui/typeck/issue-65611.stderr b/tests/ui/typeck/issue-65611.stderr index 2278450a6d8e..52f0f0cffff9 100644 --- a/tests/ui/typeck/issue-65611.stderr +++ b/tests/ui/typeck/issue-65611.stderr @@ -4,13 +4,6 @@ error[E0282]: type annotations needed LL | let x = buffer.last().unwrap().0.clone(); | ^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T` -error[E0609]: no field `0` on type `&_` - --> $DIR/issue-65611.rs:59:36 - | -LL | let x = buffer.last().unwrap().0.clone(); - | ^ unknown field +error: aborting due to 1 previous error -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0282, E0609. -For more information about an error, try `rustc --explain E0282`. +For more information about this error, try `rustc --explain E0282`. From a6b7a26c3d3b389183b39f203b77edbac55f8a86 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 4 Apr 2025 12:19:51 +0200 Subject: [PATCH 126/606] Update rinja version in `generate-copyright` --- Cargo.lock | 4 +--- src/librustdoc/html/render/print_item.rs | 4 ++-- src/tools/generate-copyright/Cargo.toml | 2 +- src/tools/generate-copyright/src/main.rs | 4 ++-- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 697208e77629..88ad352f0410 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1387,8 +1387,8 @@ name = "generate-copyright" version = "0.1.0" dependencies = [ "anyhow", + "askama", "cargo_metadata 0.18.1", - "rinja", "serde", "serde_json", "thiserror 1.0.69", @@ -3111,9 +3111,7 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dc4940d00595430b3d7d5a01f6222b5e5b51395d1120bdb28d854bb8abb17a5" dependencies = [ - "humansize", "itoa", - "percent-encoding", "rinja_derive", ] diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index aeda4736899d..96847f13f655 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -37,7 +37,7 @@ use crate::html::markdown::{HeadingOffset, MarkdownSummaryLine}; use crate::html::render::{document_full, document_item_info}; use crate::html::url_parts_builder::UrlPartsBuilder; -/// Generates a Askama template struct for rendering items with common methods. +/// Generates an Askama template struct for rendering items with common methods. /// /// Usage: /// ```ignore (illustrative) @@ -1867,7 +1867,7 @@ fn item_proc_macro(cx: &Context<'_>, it: &clean::Item, m: &clean::ProcMacro) -> } } } - Ok::<(), fmt::Error>(()) + fmt::Result::Ok(()) })?; write!(w, "{}", document(cx, it, None, HeadingOffset::H2)) }) diff --git a/src/tools/generate-copyright/Cargo.toml b/src/tools/generate-copyright/Cargo.toml index 404101abd41b..ab76d0fc01e7 100644 --- a/src/tools/generate-copyright/Cargo.toml +++ b/src/tools/generate-copyright/Cargo.toml @@ -8,8 +8,8 @@ description = "Produces a manifest of all the copyrighted materials in the Rust [dependencies] anyhow = "1.0.65" +askama = "0.13.0" cargo_metadata = "0.18.1" -rinja = "0.3.0" serde = { version = "1.0.147", features = ["derive"] } serde_json = "1.0.85" thiserror = "1" diff --git a/src/tools/generate-copyright/src/main.rs b/src/tools/generate-copyright/src/main.rs index 79e90d88f444..d6ed7261b7c8 100644 --- a/src/tools/generate-copyright/src/main.rs +++ b/src/tools/generate-copyright/src/main.rs @@ -2,7 +2,7 @@ use std::collections::BTreeMap; use std::path::{Path, PathBuf}; use anyhow::Error; -use rinja::Template; +use askama::Template; mod cargo_metadata; @@ -117,7 +117,7 @@ struct Metadata { } /// Describes one node in our metadata tree -#[derive(serde::Deserialize, rinja::Template, Clone, Debug, PartialEq, Eq)] +#[derive(serde::Deserialize, Template, Clone, Debug, PartialEq, Eq)] #[serde(rename_all = "kebab-case", tag = "type")] #[template(path = "Node.html")] pub(crate) enum Node { From e30cb329d81cc83a082f6919943361b8d9710509 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 5 Apr 2025 17:46:47 -0700 Subject: [PATCH 127/606] Polymorphize `array::IntoIter`'s iterator impl --- library/core/src/array/iter.rs | 231 +++++++----------- library/core/src/array/iter/iter_inner.rs | 281 ++++++++++++++++++++++ library/core/src/ops/index_range.rs | 55 +++++ tests/codegen/issues/issue-101082.rs | 25 +- 4 files changed, 447 insertions(+), 145 deletions(-) create mode 100644 library/core/src/array/iter/iter_inner.rs diff --git a/library/core/src/array/iter.rs b/library/core/src/array/iter.rs index 1edade41597f..90f76d6d4c7b 100644 --- a/library/core/src/array/iter.rs +++ b/library/core/src/array/iter.rs @@ -1,38 +1,35 @@ //! Defines the `IntoIter` owned iterator for arrays. use crate::intrinsics::transmute_unchecked; -use crate::iter::{self, FusedIterator, TrustedLen, TrustedRandomAccessNoCoerce}; +use crate::iter::{FusedIterator, TrustedLen, TrustedRandomAccessNoCoerce}; use crate::mem::MaybeUninit; use crate::num::NonZero; -use crate::ops::{IndexRange, Range}; +use crate::ops::{IndexRange, Range, Try}; use crate::{fmt, ptr}; +mod iter_inner; + +type InnerSized = iter_inner::PolymorphicIter<[MaybeUninit; N]>; +type InnerUnsized = iter_inner::PolymorphicIter<[MaybeUninit]>; + /// A by-value [array] iterator. #[stable(feature = "array_value_iter", since = "1.51.0")] #[rustc_insignificant_dtor] #[rustc_diagnostic_item = "ArrayIntoIter"] +#[derive(Clone)] pub struct IntoIter { - /// This is the array we are iterating over. - /// - /// Elements with index `i` where `alive.start <= i < alive.end` have not - /// been yielded yet and are valid array entries. Elements with indices `i - /// < alive.start` or `i >= alive.end` have been yielded already and must - /// not be accessed anymore! Those dead elements might even be in a - /// completely uninitialized state! - /// - /// So the invariants are: - /// - `data[alive]` is alive (i.e. contains valid elements) - /// - `data[..alive.start]` and `data[alive.end..]` are dead (i.e. the - /// elements were already read and must not be touched anymore!) - data: [MaybeUninit; N], + inner: InnerSized, +} - /// The elements in `data` that have not been yielded yet. - /// - /// Invariants: - /// - `alive.end <= N` - /// - /// (And the `IndexRange` type requires `alive.start <= alive.end`.) - alive: IndexRange, +impl IntoIter { + #[inline] + fn unsize(&self) -> &InnerUnsized { + &self.inner + } + #[inline] + fn unsize_mut(&mut self) -> &mut InnerUnsized { + &mut self.inner + } } // Note: the `#[rustc_skip_during_method_dispatch(array)]` on `trait IntoIterator` @@ -53,6 +50,7 @@ impl IntoIterator for [T; N] { /// 2021 edition -- see the [array] Editions section for more information. /// /// [array]: prim@array + #[inline] fn into_iter(self) -> Self::IntoIter { // SAFETY: The transmute here is actually safe. The docs of `MaybeUninit` // promise: @@ -68,7 +66,10 @@ impl IntoIterator for [T; N] { // FIXME: If normal `transmute` ever gets smart enough to allow this // directly, use it instead of `transmute_unchecked`. let data: [MaybeUninit; N] = unsafe { transmute_unchecked(self) }; - IntoIter { data, alive: IndexRange::zero_to(N) } + // SAFETY: The original array was entirely initialized and the the alive + // range we're passing here represents that fact. + let inner = unsafe { InnerSized::new_unchecked(IndexRange::zero_to(N), data) }; + IntoIter { inner } } } @@ -136,13 +137,16 @@ impl IntoIter { /// assert_eq!(r.collect::>(), vec![10, 11, 12, 13, 14, 15]); /// ``` #[unstable(feature = "array_into_iter_constructors", issue = "91583")] + #[inline] pub const unsafe fn new_unchecked( buffer: [MaybeUninit; N], initialized: Range, ) -> Self { // SAFETY: one of our safety conditions is that the range is canonical. let alive = unsafe { IndexRange::new_unchecked(initialized.start, initialized.end) }; - Self { data: buffer, alive } + // SAFETY: one of our safety condition is that these items are initialized. + let inner = unsafe { InnerSized::new_unchecked(alive, buffer) }; + IntoIter { inner } } /// Creates an iterator over `T` which returns no elements. @@ -198,172 +202,134 @@ impl IntoIter { /// assert_eq!(get_bytes(false).collect::>(), vec![]); /// ``` #[unstable(feature = "array_into_iter_constructors", issue = "91583")] + #[inline] pub const fn empty() -> Self { - let buffer = [const { MaybeUninit::uninit() }; N]; - let initialized = 0..0; - - // SAFETY: We're telling it that none of the elements are initialized, - // which is trivially true. And ∀N: usize, 0 <= N. - unsafe { Self::new_unchecked(buffer, initialized) } + let inner = InnerSized::empty(); + IntoIter { inner } } /// Returns an immutable slice of all elements that have not been yielded /// yet. #[stable(feature = "array_value_iter", since = "1.51.0")] + #[inline] pub fn as_slice(&self) -> &[T] { - // SAFETY: We know that all elements within `alive` are properly initialized. - unsafe { - let slice = self.data.get_unchecked(self.alive.clone()); - slice.assume_init_ref() - } + self.unsize().as_slice() } /// Returns a mutable slice of all elements that have not been yielded yet. #[stable(feature = "array_value_iter", since = "1.51.0")] + #[inline] pub fn as_mut_slice(&mut self) -> &mut [T] { - // SAFETY: We know that all elements within `alive` are properly initialized. - unsafe { - let slice = self.data.get_unchecked_mut(self.alive.clone()); - slice.assume_init_mut() - } + self.unsize_mut().as_mut_slice() } } #[stable(feature = "array_value_iter_impls", since = "1.40.0")] impl Iterator for IntoIter { type Item = T; - fn next(&mut self) -> Option { - // Get the next index from the front. - // - // Increasing `alive.start` by 1 maintains the invariant regarding - // `alive`. However, due to this change, for a short time, the alive - // zone is not `data[alive]` anymore, but `data[idx..alive.end]`. - self.alive.next().map(|idx| { - // Read the element from the array. - // SAFETY: `idx` is an index into the former "alive" region of the - // array. Reading this element means that `data[idx]` is regarded as - // dead now (i.e. do not touch). As `idx` was the start of the - // alive-zone, the alive zone is now `data[alive]` again, restoring - // all invariants. - unsafe { self.data.get_unchecked(idx).assume_init_read() } - }) - } - fn size_hint(&self) -> (usize, Option) { - let len = self.len(); - (len, Some(len)) + #[inline] + fn next(&mut self) -> Option { + self.unsize_mut().next() } #[inline] - fn fold(mut self, init: Acc, mut fold: Fold) -> Acc + fn size_hint(&self) -> (usize, Option) { + self.unsize().size_hint() + } + + #[inline] + fn fold(mut self, init: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { - let data = &mut self.data; - iter::ByRefSized(&mut self.alive).fold(init, |acc, idx| { - // SAFETY: idx is obtained by folding over the `alive` range, which implies the - // value is currently considered alive but as the range is being consumed each value - // we read here will only be read once and then considered dead. - fold(acc, unsafe { data.get_unchecked(idx).assume_init_read() }) - }) + self.unsize_mut().fold(init, fold) } + #[inline] + fn try_fold(&mut self, init: B, f: F) -> R + where + Self: Sized, + F: FnMut(B, Self::Item) -> R, + R: Try, + { + self.unsize_mut().try_fold(init, f) + } + + #[inline] fn count(self) -> usize { self.len() } + #[inline] fn last(mut self) -> Option { self.next_back() } + #[inline] fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { - // This also moves the start, which marks them as conceptually "dropped", - // so if anything goes bad then our drop impl won't double-free them. - let range_to_drop = self.alive.take_prefix(n); - let remaining = n - range_to_drop.len(); - - // SAFETY: These elements are currently initialized, so it's fine to drop them. - unsafe { - let slice = self.data.get_unchecked_mut(range_to_drop); - slice.assume_init_drop(); - } - - NonZero::new(remaining).map_or(Ok(()), Err) + self.unsize_mut().advance_by(n) } #[inline] unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item { // SAFETY: The caller must provide an idx that is in bound of the remainder. - unsafe { self.data.as_ptr().add(self.alive.start()).add(idx).cast::().read() } + let elem_ref = unsafe { self.as_mut_slice().get_unchecked_mut(idx) }; + // SAFETY: We only implement `TrustedRandomAccessNoCoerce` for types + // which are actually `Copy`, so cannot have multiple-drop issues. + unsafe { ptr::read(elem_ref) } } } #[stable(feature = "array_value_iter_impls", since = "1.40.0")] impl DoubleEndedIterator for IntoIter { + #[inline] fn next_back(&mut self) -> Option { - // Get the next index from the back. - // - // Decreasing `alive.end` by 1 maintains the invariant regarding - // `alive`. However, due to this change, for a short time, the alive - // zone is not `data[alive]` anymore, but `data[alive.start..=idx]`. - self.alive.next_back().map(|idx| { - // Read the element from the array. - // SAFETY: `idx` is an index into the former "alive" region of the - // array. Reading this element means that `data[idx]` is regarded as - // dead now (i.e. do not touch). As `idx` was the end of the - // alive-zone, the alive zone is now `data[alive]` again, restoring - // all invariants. - unsafe { self.data.get_unchecked(idx).assume_init_read() } - }) + self.unsize_mut().next_back() } #[inline] - fn rfold(mut self, init: Acc, mut rfold: Fold) -> Acc + fn rfold(mut self, init: Acc, rfold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { - let data = &mut self.data; - iter::ByRefSized(&mut self.alive).rfold(init, |acc, idx| { - // SAFETY: idx is obtained by folding over the `alive` range, which implies the - // value is currently considered alive but as the range is being consumed each value - // we read here will only be read once and then considered dead. - rfold(acc, unsafe { data.get_unchecked(idx).assume_init_read() }) - }) + self.unsize_mut().rfold(init, rfold) } + #[inline] + fn try_rfold(&mut self, init: B, f: F) -> R + where + Self: Sized, + F: FnMut(B, Self::Item) -> R, + R: Try, + { + self.unsize_mut().try_rfold(init, f) + } + + #[inline] fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { - // This also moves the end, which marks them as conceptually "dropped", - // so if anything goes bad then our drop impl won't double-free them. - let range_to_drop = self.alive.take_suffix(n); - let remaining = n - range_to_drop.len(); - - // SAFETY: These elements are currently initialized, so it's fine to drop them. - unsafe { - let slice = self.data.get_unchecked_mut(range_to_drop); - slice.assume_init_drop(); - } - - NonZero::new(remaining).map_or(Ok(()), Err) + self.unsize_mut().advance_back_by(n) } } #[stable(feature = "array_value_iter_impls", since = "1.40.0")] impl Drop for IntoIter { + #[inline] fn drop(&mut self) { - // SAFETY: This is safe: `as_mut_slice` returns exactly the sub-slice - // of elements that have not been moved out yet and that remain - // to be dropped. - unsafe { ptr::drop_in_place(self.as_mut_slice()) } + // `inner` now handles this, but it'd technically be a breaking change + // to remove this `impl`, even though it's useless. } } #[stable(feature = "array_value_iter_impls", since = "1.40.0")] impl ExactSizeIterator for IntoIter { + #[inline] fn len(&self) -> usize { - self.alive.len() + self.inner.len() } + #[inline] fn is_empty(&self) -> bool { - self.alive.is_empty() + self.inner.len() == 0 } } @@ -396,32 +362,9 @@ where const MAY_HAVE_SIDE_EFFECT: bool = false; } -#[stable(feature = "array_value_iter_impls", since = "1.40.0")] -impl Clone for IntoIter { - fn clone(&self) -> Self { - // Note, we don't really need to match the exact same alive range, so - // we can just clone into offset 0 regardless of where `self` is. - let mut new = - Self { data: [const { MaybeUninit::uninit() }; N], alive: IndexRange::zero_to(0) }; - - // Clone all alive elements. - for (src, dst) in iter::zip(self.as_slice(), &mut new.data) { - // Write a clone into the new array, then update its alive range. - // If cloning panics, we'll correctly drop the previous items. - dst.write(src.clone()); - // This addition cannot overflow as we're iterating a slice - new.alive = IndexRange::zero_to(new.alive.end() + 1); - } - - new - } -} - #[stable(feature = "array_value_iter_impls", since = "1.40.0")] impl fmt::Debug for IntoIter { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // Only print the elements that were not yielded yet: we cannot - // access the yielded elements anymore. - f.debug_tuple("IntoIter").field(&self.as_slice()).finish() + self.unsize().fmt(f) } } diff --git a/library/core/src/array/iter/iter_inner.rs b/library/core/src/array/iter/iter_inner.rs new file mode 100644 index 000000000000..f43d9e7ddd63 --- /dev/null +++ b/library/core/src/array/iter/iter_inner.rs @@ -0,0 +1,281 @@ +//! Defines the `IntoIter` owned iterator for arrays. + +use crate::mem::MaybeUninit; +use crate::num::NonZero; +use crate::ops::{IndexRange, NeverShortCircuit, Try}; +use crate::{fmt, iter}; + +#[allow(private_bounds)] +trait PartialDrop { + /// # Safety + /// `self[alive]` are all initialized before the call, + /// then are never used (without reinitializing them) after it. + unsafe fn partial_drop(&mut self, alive: IndexRange); +} +impl PartialDrop for [MaybeUninit] { + unsafe fn partial_drop(&mut self, alive: IndexRange) { + // SAFETY: We know that all elements within `alive` are properly initialized. + unsafe { self.get_unchecked_mut(alive).assume_init_drop() } + } +} +impl PartialDrop for [MaybeUninit; N] { + unsafe fn partial_drop(&mut self, alive: IndexRange) { + let slice: &mut [MaybeUninit] = self; + // SAFETY: Initialized elements in the array are also initialized in the slice. + unsafe { slice.partial_drop(alive) } + } +} + +/// The internals of a by-value array iterator. +/// +/// The real `array::IntoIter` stores a `PolymorphicIter<[MaybeUninit, N]>` +/// which it unsizes to `PolymorphicIter<[MaybeUninit]>` to iterate. +#[allow(private_bounds)] +pub(super) struct PolymorphicIter +where + TAIL: PartialDrop, +{ + /// The elements in `data` that have not been yielded yet. + /// + /// Invariants: + /// - `alive.end <= N` + /// + /// (And the `IndexRange` type requires `alive.start <= alive.end`.) + alive: IndexRange, + + /// This is the array we are iterating over. + /// + /// Elements with index `i` where `alive.start <= i < alive.end` have not + /// been yielded yet and are valid array entries. Elements with indices `i + /// < alive.start` or `i >= alive.end` have been yielded already and must + /// not be accessed anymore! Those dead elements might even be in a + /// completely uninitialized state! + /// + /// So the invariants are: + /// - `data[alive]` is alive (i.e. contains valid elements) + /// - `data[..alive.start]` and `data[alive.end..]` are dead (i.e. the + /// elements were already read and must not be touched anymore!) + data: TAIL, +} + +#[allow(private_bounds)] +impl PolymorphicIter +where + TAIL: PartialDrop, +{ + #[inline] + pub(super) const fn len(&self) -> usize { + self.alive.len() + } +} + +#[allow(private_bounds)] +impl Drop for PolymorphicIter +where + TAIL: PartialDrop, +{ + #[inline] + fn drop(&mut self) { + // SAFETY: by our type invariant `self.alive` is exactly the initialized + // items, and this is drop so nothing can use the items afterwards. + unsafe { self.data.partial_drop(self.alive.clone()) } + } +} + +impl PolymorphicIter<[MaybeUninit; N]> { + #[inline] + pub(super) const fn empty() -> Self { + Self { alive: IndexRange::zero_to(0), data: [const { MaybeUninit::uninit() }; N] } + } + + /// # Safety + /// `data[alive]` are all initialized. + #[inline] + pub(super) const unsafe fn new_unchecked(alive: IndexRange, data: [MaybeUninit; N]) -> Self { + Self { alive, data } + } +} + +impl Clone for PolymorphicIter<[MaybeUninit; N]> { + #[inline] + fn clone(&self) -> Self { + // Note, we don't really need to match the exact same alive range, so + // we can just clone into offset 0 regardless of where `self` is. + let mut new = Self::empty(); + + fn clone_into_new( + source: &PolymorphicIter<[MaybeUninit]>, + target: &mut PolymorphicIter<[MaybeUninit]>, + ) { + // Clone all alive elements. + for (src, dst) in iter::zip(source.as_slice(), &mut target.data) { + // Write a clone into the new array, then update its alive range. + // If cloning panics, we'll correctly drop the previous items. + dst.write(src.clone()); + // This addition cannot overflow as we're iterating a slice, + // the length of which always fits in usize. + target.alive = IndexRange::zero_to(target.alive.end() + 1); + } + } + + clone_into_new(self, &mut new); + new + } +} + +impl PolymorphicIter<[MaybeUninit]> { + #[inline] + pub(super) fn as_slice(&self) -> &[T] { + // SAFETY: We know that all elements within `alive` are properly initialized. + unsafe { + let slice = self.data.get_unchecked(self.alive.clone()); + slice.assume_init_ref() + } + } + + #[inline] + pub(super) fn as_mut_slice(&mut self) -> &mut [T] { + // SAFETY: We know that all elements within `alive` are properly initialized. + unsafe { + let slice = self.data.get_unchecked_mut(self.alive.clone()); + slice.assume_init_mut() + } + } +} + +impl fmt::Debug for PolymorphicIter<[MaybeUninit]> { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // Only print the elements that were not yielded yet: we cannot + // access the yielded elements anymore. + f.debug_tuple("IntoIter").field(&self.as_slice()).finish() + } +} + +/// Iterator-equivalent methods. +/// +/// We don't implement the actual iterator traits because we want to implement +/// things like `try_fold` that require `Self: Sized` (which we're not). +impl PolymorphicIter<[MaybeUninit]> { + #[inline] + pub(super) fn next(&mut self) -> Option { + // Get the next index from the front. + // + // Increasing `alive.start` by 1 maintains the invariant regarding + // `alive`. However, due to this change, for a short time, the alive + // zone is not `data[alive]` anymore, but `data[idx..alive.end]`. + self.alive.next().map(|idx| { + // Read the element from the array. + // SAFETY: `idx` is an index into the former "alive" region of the + // array. Reading this element means that `data[idx]` is regarded as + // dead now (i.e. do not touch). As `idx` was the start of the + // alive-zone, the alive zone is now `data[alive]` again, restoring + // all invariants. + unsafe { self.data.get_unchecked(idx).assume_init_read() } + }) + } + + #[inline] + pub(super) fn size_hint(&self) -> (usize, Option) { + let len = self.len(); + (len, Some(len)) + } + + #[inline] + pub(super) fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { + // This also moves the start, which marks them as conceptually "dropped", + // so if anything goes bad then our drop impl won't double-free them. + let range_to_drop = self.alive.take_prefix(n); + let remaining = n - range_to_drop.len(); + + // SAFETY: These elements are currently initialized, so it's fine to drop them. + unsafe { + let slice = self.data.get_unchecked_mut(range_to_drop); + slice.assume_init_drop(); + } + + NonZero::new(remaining).map_or(Ok(()), Err) + } + + #[inline] + pub(super) fn fold(&mut self, init: B, f: impl FnMut(B, T) -> B) -> B { + self.try_fold(init, NeverShortCircuit::wrap_mut_2(f)).0 + } + + #[inline] + pub(super) fn try_fold(&mut self, init: B, mut f: F) -> R + where + F: FnMut(B, T) -> R, + R: Try, + { + // `alive` is an `IndexRange`, not an arbitrary iterator, so we can + // trust that its `try_rfold` isn't going to do something weird like + // call the fold-er multiple times for the same index. + let data = &mut self.data; + self.alive.try_fold(init, move |accum, idx| { + // SAFETY: `idx` has been removed from the alive range, so we're not + // going to drop it (even if `f` panics) and thus its ok to give + // out ownership of that item to `f` to handle. + let elem = unsafe { data.get_unchecked(idx).assume_init_read() }; + f(accum, elem) + }) + } + + #[inline] + pub(super) fn next_back(&mut self) -> Option { + // Get the next index from the back. + // + // Decreasing `alive.end` by 1 maintains the invariant regarding + // `alive`. However, due to this change, for a short time, the alive + // zone is not `data[alive]` anymore, but `data[alive.start..=idx]`. + self.alive.next_back().map(|idx| { + // Read the element from the array. + // SAFETY: `idx` is an index into the former "alive" region of the + // array. Reading this element means that `data[idx]` is regarded as + // dead now (i.e. do not touch). As `idx` was the end of the + // alive-zone, the alive zone is now `data[alive]` again, restoring + // all invariants. + unsafe { self.data.get_unchecked(idx).assume_init_read() } + }) + } + + #[inline] + pub(super) fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { + // This also moves the end, which marks them as conceptually "dropped", + // so if anything goes bad then our drop impl won't double-free them. + let range_to_drop = self.alive.take_suffix(n); + let remaining = n - range_to_drop.len(); + + // SAFETY: These elements are currently initialized, so it's fine to drop them. + unsafe { + let slice = self.data.get_unchecked_mut(range_to_drop); + slice.assume_init_drop(); + } + + NonZero::new(remaining).map_or(Ok(()), Err) + } + + #[inline] + pub(super) fn rfold(&mut self, init: B, f: impl FnMut(B, T) -> B) -> B { + self.try_rfold(init, NeverShortCircuit::wrap_mut_2(f)).0 + } + + #[inline] + pub(super) fn try_rfold(&mut self, init: B, mut f: F) -> R + where + F: FnMut(B, T) -> R, + R: Try, + { + // `alive` is an `IndexRange`, not an arbitrary iterator, so we can + // trust that its `try_rfold` isn't going to do something weird like + // call the fold-er multiple times for the same index. + let data = &mut self.data; + self.alive.try_rfold(init, move |accum, idx| { + // SAFETY: `idx` has been removed from the alive range, so we're not + // going to drop it (even if `f` panics) and thus its ok to give + // out ownership of that item to `f` to handle. + let elem = unsafe { data.get_unchecked(idx).assume_init_read() }; + f(accum, elem) + }) + } +} diff --git a/library/core/src/ops/index_range.rs b/library/core/src/ops/index_range.rs index b82184b15b2f..c645c996eb70 100644 --- a/library/core/src/ops/index_range.rs +++ b/library/core/src/ops/index_range.rs @@ -1,5 +1,6 @@ use crate::iter::{FusedIterator, TrustedLen}; use crate::num::NonZero; +use crate::ops::{NeverShortCircuit, Try}; use crate::ub_checks; /// Like a `Range`, but with a safety invariant that `start <= end`. @@ -112,6 +113,12 @@ impl IndexRange { self.end = mid; suffix } + + #[inline] + fn assume_range(&self) { + // SAFETY: This is the type invariant + unsafe { crate::hint::assert_unchecked(self.start <= self.end) } + } } impl Iterator for IndexRange { @@ -138,6 +145,30 @@ impl Iterator for IndexRange { let taken = self.take_prefix(n); NonZero::new(n - taken.len()).map_or(Ok(()), Err) } + + #[inline] + fn fold B>(mut self, init: B, f: F) -> B { + self.try_fold(init, NeverShortCircuit::wrap_mut_2(f)).0 + } + + #[inline] + fn try_fold(&mut self, mut accum: B, mut f: F) -> R + where + Self: Sized, + F: FnMut(B, Self::Item) -> R, + R: Try, + { + // `Range` needs to check `start < end`, but thanks to our type invariant + // we can loop on the stricter `start != end`. + + self.assume_range(); + while self.start != self.end { + // SAFETY: We just checked that the range is non-empty + let i = unsafe { self.next_unchecked() }; + accum = f(accum, i)?; + } + try { accum } + } } impl DoubleEndedIterator for IndexRange { @@ -156,6 +187,30 @@ impl DoubleEndedIterator for IndexRange { let taken = self.take_suffix(n); NonZero::new(n - taken.len()).map_or(Ok(()), Err) } + + #[inline] + fn rfold B>(mut self, init: B, f: F) -> B { + self.try_rfold(init, NeverShortCircuit::wrap_mut_2(f)).0 + } + + #[inline] + fn try_rfold(&mut self, mut accum: B, mut f: F) -> R + where + Self: Sized, + F: FnMut(B, Self::Item) -> R, + R: Try, + { + // `Range` needs to check `start < end`, but thanks to our type invariant + // we can loop on the stricter `start != end`. + + self.assume_range(); + while self.start != self.end { + // SAFETY: We just checked that the range is non-empty + let i = unsafe { self.next_back_unchecked() }; + accum = f(accum, i)?; + } + try { accum } + } } impl ExactSizeIterator for IndexRange { diff --git a/tests/codegen/issues/issue-101082.rs b/tests/codegen/issues/issue-101082.rs index 7fb850ca2532..89295da5bd10 100644 --- a/tests/codegen/issues/issue-101082.rs +++ b/tests/codegen/issues/issue-101082.rs @@ -11,7 +11,18 @@ #[no_mangle] pub fn test() -> usize { // CHECK-LABEL: @test( - // CHECK: ret {{i64|i32}} 165 + // host: ret {{i64|i32}} 165 + + // FIXME: Now that this autovectorizes via a masked load, it doesn't actually + // const-fold for certain widths. The `test_eight` case below shows that, yes, + // what we're emitting *can* be const-folded, except that the way LLVM does it + // for certain widths doesn't today. We should be able to put this back to + // the same check after + // x86-64-v3: + // x86-64-v3: llvm.masked.load + // x86-64-v3: %[[R:.+]] = {{.+}}llvm.vector.reduce.add.v4i64 + // x86-64-v3: ret i64 %[[R]] + let values = [23, 16, 54, 3, 60, 9]; let mut acc = 0; for item in values { @@ -19,3 +30,15 @@ pub fn test() -> usize { } acc } + +#[no_mangle] +pub fn test_eight() -> usize { + // CHECK-LABEL: @test_eight( + // CHECK: ret {{i64|i32}} 220 + let values = [23, 16, 54, 3, 60, 9, 13, 42]; + let mut acc = 0; + for item in values { + acc += item; + } + acc +} From d37bd4d7de29dc932eec2f7688e04892f628d018 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 3 Apr 2025 15:54:33 +0200 Subject: [PATCH 128/606] Update proc-macro deps list --- src/bootstrap/src/utils/proc_macro_deps.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/bootstrap/src/utils/proc_macro_deps.rs b/src/bootstrap/src/utils/proc_macro_deps.rs index dbfd6f47dc67..aa564b4a0451 100644 --- a/src/bootstrap/src/utils/proc_macro_deps.rs +++ b/src/bootstrap/src/utils/proc_macro_deps.rs @@ -5,6 +5,7 @@ pub static CRATES: &[&str] = &[ // tidy-alphabetical-start "annotate-snippets", "anstyle", + "askama_parser", "basic-toml", "block-buffer", "bumpalo", @@ -64,6 +65,7 @@ pub static CRATES: &[&str] = &[ "wasm-bindgen-backend", "wasm-bindgen-macro-support", "wasm-bindgen-shared", + "winnow", "yoke", "zerofrom", "zerovec", From 3aac9a37a5ff306eccb63872a7d6f4ef6f90a577 Mon Sep 17 00:00:00 2001 From: beetrees Date: Sun, 6 Apr 2025 02:31:52 +0100 Subject: [PATCH 129/606] Remove LLVM 18 inline ASM span fallback --- compiler/rustc_codegen_llvm/src/back/write.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index bf6138142b64..76d431a49756 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -439,12 +439,9 @@ fn report_inline_asm( let span = if cookie == 0 || matches!(cgcx.lto, Lto::Fat | Lto::Thin) { SpanData::default() } else { - let lo = BytePos::from_u32(cookie as u32); - let hi = BytePos::from_u32((cookie >> 32) as u32); SpanData { - lo, - // LLVM version < 19 silently truncates the cookie to 32 bits in some situations. - hi: if hi.to_u32() != 0 { hi } else { lo }, + lo: BytePos::from_u32(cookie as u32), + hi: BytePos::from_u32((cookie >> 32) as u32), ctxt: SyntaxContext::root(), parent: None, } From 1f06a6a25238e3f13c78a7ec2ac25af07d44a710 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Fri, 28 Mar 2025 20:50:28 -0700 Subject: [PATCH 130/606] Tell LLVM about impossible niche tags --- compiler/rustc_codegen_ssa/src/mir/operand.rs | 28 ++ tests/codegen/enum/enum-match.rs | 393 +++++++++++++++++- tests/codegen/enum/enum-two-variants-match.rs | 63 ++- 3 files changed, 465 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index 7e355b6406ae..fca0695f296f 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -9,6 +9,7 @@ use rustc_middle::mir::{self, ConstValue}; use rustc_middle::ty::Ty; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::{bug, span_bug}; +use rustc_session::config::OptLevel; use tracing::{debug, instrument}; use super::place::{PlaceRef, PlaceValue}; @@ -496,6 +497,18 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { _ => (tag_imm, bx.cx().immediate_backend_type(tag_op.layout)), }; + // Layout ensures that we only get here for cases where the discriminant + // value and the variant index match, since that's all `Niche` can encode. + // But for emphasis and debugging, let's double-check one anyway. + debug_assert_eq!( + self.layout + .ty + .discriminant_for_variant(bx.tcx(), untagged_variant) + .unwrap() + .val, + u128::from(untagged_variant.as_u32()), + ); + let relative_max = niche_variants.end().as_u32() - niche_variants.start().as_u32(); // We have a subrange `niche_start..=niche_end` inside `range`. @@ -537,6 +550,21 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { relative_discr, bx.cx().const_uint(tag_llty, relative_max as u64), ); + + // Thanks to parameter attributes and load metadata, LLVM already knows + // the general valid range of the tag. It's possible, though, for there + // to be an impossible value *in the middle*, which those ranges don't + // communicate, so it's worth an `assume` to let the optimizer know. + if niche_variants.contains(&untagged_variant) + && bx.cx().sess().opts.optimize != OptLevel::No + { + let impossible = + u64::from(untagged_variant.as_u32() - niche_variants.start().as_u32()); + let impossible = bx.cx().const_uint(tag_llty, impossible); + let ne = bx.icmp(IntPredicate::IntNE, relative_discr, impossible); + bx.assume(ne); + } + (is_niche, cast_tag, niche_variants.start().as_u32() as u128) }; diff --git a/tests/codegen/enum/enum-match.rs b/tests/codegen/enum/enum-match.rs index a24b98050d23..bea0d5f33b0a 100644 --- a/tests/codegen/enum/enum-match.rs +++ b/tests/codegen/enum/enum-match.rs @@ -1,7 +1,8 @@ //@ compile-flags: -Copt-level=1 -//@ only-x86_64 +//@ only-64bit #![crate_type = "lib"] +#![feature(core_intrinsics)] // Check each of the 3 cases for `codegen_get_discr`. @@ -11,11 +12,12 @@ pub enum Enum0 { B, } -// CHECK: define noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @match0{{.*}} +// CHECK-LABEL: define noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @match0(i8{{.+}}%0) // CHECK-NEXT: start: -// CHECK-NEXT: %1 = icmp eq i8 %0, 2 -// CHECK-NEXT: %2 = and i8 %0, 1 -// CHECK-NEXT: %{{.+}} = select i1 %1, i8 13, i8 %2 +// CHECK-NEXT: %[[IS_B:.+]] = icmp eq i8 %0, 2 +// CHECK-NEXT: %[[TRUNC:.+]] = and i8 %0, 1 +// CHECK-NEXT: %[[R:.+]] = select i1 %[[IS_B]], i8 13, i8 %[[TRUNC]] +// CHECK-NEXT: ret i8 %[[R]] #[no_mangle] pub fn match0(e: Enum0) -> u8 { use Enum0::*; @@ -32,13 +34,14 @@ pub enum Enum1 { C, } -// CHECK: define noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @match1{{.*}} +// CHECK-LABEL: define noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @match1(i8{{.+}}%0) // CHECK-NEXT: start: -// CHECK-NEXT: %1 = add{{( nsw)?}} i8 %0, -2 -// CHECK-NEXT: %2 = zext i8 %1 to i64 -// CHECK-NEXT: %3 = icmp ult i8 %1, 2 -// CHECK-NEXT: %4 = add nuw nsw i64 %2, 1 -// CHECK-NEXT: %_2 = select i1 %3, i64 %4, i64 0 +// CHECK-NEXT: %[[REL_VAR:.+]] = add{{( nsw)?}} i8 %0, -2 +// CHECK-NEXT: %[[REL_VAR_WIDE:.+]] = zext i8 %[[REL_VAR]] to i64 +// CHECK-NEXT: %[[IS_NICHE:.+]] = icmp ult i8 %[[REL_VAR]], 2 +// CHECK-NEXT: %[[NICHE_DISCR:.+]] = add nuw nsw i64 %[[REL_VAR_WIDE]], 1 +// CHECK-NEXT: %[[DISCR:.+]] = select i1 %[[IS_NICHE]], i64 %[[NICHE_DISCR]], i64 0 +// CHECK-NEXT: switch i64 %[[DISCR]] #[no_mangle] pub fn match1(e: Enum1) -> u8 { use Enum1::*; @@ -92,14 +95,14 @@ pub enum Enum2 { E, } -// CHECK: define noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @match2{{.*}} +// CHECK-LABEL: define noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @match2(i8{{.+}}%0) // CHECK-NEXT: start: -// CHECK-NEXT: %1 = add i8 %0, 2 -// CHECK-NEXT: %2 = zext i8 %1 to i64 -// CHECK-NEXT: %3 = icmp ult i8 %1, 4 -// CHECK-NEXT: %4 = add nuw nsw i64 %2, 1 -// CHECK-NEXT: %_2 = select i1 %3, i64 %4, i64 0 -// CHECK-NEXT: switch i64 %_2, label {{.*}} [ +// CHECK-NEXT: %[[REL_VAR:.+]] = add i8 %0, 2 +// CHECK-NEXT: %[[REL_VAR_WIDE:.+]] = zext i8 %[[REL_VAR]] to i64 +// CHECK-NEXT: %[[IS_NICHE:.+]] = icmp ult i8 %[[REL_VAR]], 4 +// CHECK-NEXT: %[[NICHE_DISCR:.+]] = add nuw nsw i64 %[[REL_VAR_WIDE]], 1 +// CHECK-NEXT: %[[DISCR:.+]] = select i1 %[[IS_NICHE]], i64 %[[NICHE_DISCR]], i64 0 +// CHECK-NEXT: switch i64 %[[DISCR]] #[no_mangle] pub fn match2(e: Enum2) -> u8 { use Enum2::*; @@ -111,3 +114,357 @@ pub fn match2(e: Enum2) -> u8 { E => 250, } } + +// And make sure it works even if the niched scalar is a pointer. +// (For example, that we don't try to `sub` on pointers.) + +// CHECK-LABEL: define noundef{{( range\(i16 -?[0-9]+, -?[0-9]+\))?}} i16 @match3(ptr{{.+}}%0) +// CHECK-NEXT: start: +// CHECK-NEXT: %[[IS_NULL:.+]] = icmp eq ptr %0, null +// CHECK-NEXT: br i1 %[[IS_NULL]] +#[no_mangle] +pub fn match3(e: Option<&u8>) -> i16 { + match e { + Some(r) => *r as _, + None => -1, + } +} + +// If the untagged variant is in the middle, there's an impossible value that's +// not reflected in the `range` parameter attribute, so we assume it away. + +#[derive(PartialEq)] +pub enum MiddleNiche { + A, + B, + C(bool), + D, + E, +} + +// CHECK-LABEL: define noundef{{( range\(i8 -?[0-9]+, -?[0-9]+\))?}} i8 @match4(i8{{.+}}%0) +// CHECK-NEXT: start: +// CHECK-NEXT: %[[REL_VAR:.+]] = add nsw i8 %0, -2 +// CHECK-NEXT: %[[IS_NICHE:.+]] = icmp ult i8 %[[REL_VAR]], 5 +// CHECK-NEXT: %[[NOT_IMPOSSIBLE:.+]] = icmp ne i8 %[[REL_VAR]], 2 +// CHECK-NEXT: call void @llvm.assume(i1 %[[NOT_IMPOSSIBLE]]) +// CHECK-NEXT: %[[DISCR:.+]] = select i1 %[[IS_NICHE]], i8 %[[REL_VAR]], i8 2 +// CHECK-NEXT: switch i8 %[[DISCR]] +#[no_mangle] +pub fn match4(e: MiddleNiche) -> u8 { + use MiddleNiche::*; + match e { + A => 13, + B => 100, + C(b) => b as u8, + D => 200, + E => 250, + } +} + +// CHECK-LABEL: define{{.+}}i1 @match4_is_c(i8{{.+}}%e) +// CHECK-NEXT: start +// CHECK-NEXT: %[[REL_VAR:.+]] = add nsw i8 %e, -2 +// CHECK-NEXT: %[[NOT_NICHE:.+]] = icmp ugt i8 %[[REL_VAR]], 4 +// CHECK-NEXT: %[[NOT_IMPOSSIBLE:.+]] = icmp ne i8 %[[REL_VAR]], 2 +// CHECK-NEXT: call void @llvm.assume(i1 %[[NOT_IMPOSSIBLE]]) +// CHECK-NEXT: ret i1 %[[NOT_NICHE]] +#[no_mangle] +pub fn match4_is_c(e: MiddleNiche) -> bool { + // Before #139098, this couldn't optimize out the `select` because it looked + // like it was possible for a `2` to be produced on both sides. + + std::intrinsics::discriminant_value(&e) == 2 +} + +// You have to do something pretty obnoxious to get a variant index that doesn't +// fit in the tag size, but it's possible + +pub enum Never {} + +pub enum HugeVariantIndex { + V000(Never), + V001(Never), + V002(Never), + V003(Never), + V004(Never), + V005(Never), + V006(Never), + V007(Never), + V008(Never), + V009(Never), + V010(Never), + V011(Never), + V012(Never), + V013(Never), + V014(Never), + V015(Never), + V016(Never), + V017(Never), + V018(Never), + V019(Never), + V020(Never), + V021(Never), + V022(Never), + V023(Never), + V024(Never), + V025(Never), + V026(Never), + V027(Never), + V028(Never), + V029(Never), + V030(Never), + V031(Never), + V032(Never), + V033(Never), + V034(Never), + V035(Never), + V036(Never), + V037(Never), + V038(Never), + V039(Never), + V040(Never), + V041(Never), + V042(Never), + V043(Never), + V044(Never), + V045(Never), + V046(Never), + V047(Never), + V048(Never), + V049(Never), + V050(Never), + V051(Never), + V052(Never), + V053(Never), + V054(Never), + V055(Never), + V056(Never), + V057(Never), + V058(Never), + V059(Never), + V060(Never), + V061(Never), + V062(Never), + V063(Never), + V064(Never), + V065(Never), + V066(Never), + V067(Never), + V068(Never), + V069(Never), + V070(Never), + V071(Never), + V072(Never), + V073(Never), + V074(Never), + V075(Never), + V076(Never), + V077(Never), + V078(Never), + V079(Never), + V080(Never), + V081(Never), + V082(Never), + V083(Never), + V084(Never), + V085(Never), + V086(Never), + V087(Never), + V088(Never), + V089(Never), + V090(Never), + V091(Never), + V092(Never), + V093(Never), + V094(Never), + V095(Never), + V096(Never), + V097(Never), + V098(Never), + V099(Never), + V100(Never), + V101(Never), + V102(Never), + V103(Never), + V104(Never), + V105(Never), + V106(Never), + V107(Never), + V108(Never), + V109(Never), + V110(Never), + V111(Never), + V112(Never), + V113(Never), + V114(Never), + V115(Never), + V116(Never), + V117(Never), + V118(Never), + V119(Never), + V120(Never), + V121(Never), + V122(Never), + V123(Never), + V124(Never), + V125(Never), + V126(Never), + V127(Never), + V128(Never), + V129(Never), + V130(Never), + V131(Never), + V132(Never), + V133(Never), + V134(Never), + V135(Never), + V136(Never), + V137(Never), + V138(Never), + V139(Never), + V140(Never), + V141(Never), + V142(Never), + V143(Never), + V144(Never), + V145(Never), + V146(Never), + V147(Never), + V148(Never), + V149(Never), + V150(Never), + V151(Never), + V152(Never), + V153(Never), + V154(Never), + V155(Never), + V156(Never), + V157(Never), + V158(Never), + V159(Never), + V160(Never), + V161(Never), + V162(Never), + V163(Never), + V164(Never), + V165(Never), + V166(Never), + V167(Never), + V168(Never), + V169(Never), + V170(Never), + V171(Never), + V172(Never), + V173(Never), + V174(Never), + V175(Never), + V176(Never), + V177(Never), + V178(Never), + V179(Never), + V180(Never), + V181(Never), + V182(Never), + V183(Never), + V184(Never), + V185(Never), + V186(Never), + V187(Never), + V188(Never), + V189(Never), + V190(Never), + V191(Never), + V192(Never), + V193(Never), + V194(Never), + V195(Never), + V196(Never), + V197(Never), + V198(Never), + V199(Never), + V200(Never), + V201(Never), + V202(Never), + V203(Never), + V204(Never), + V205(Never), + V206(Never), + V207(Never), + V208(Never), + V209(Never), + V210(Never), + V211(Never), + V212(Never), + V213(Never), + V214(Never), + V215(Never), + V216(Never), + V217(Never), + V218(Never), + V219(Never), + V220(Never), + V221(Never), + V222(Never), + V223(Never), + V224(Never), + V225(Never), + V226(Never), + V227(Never), + V228(Never), + V229(Never), + V230(Never), + V231(Never), + V232(Never), + V233(Never), + V234(Never), + V235(Never), + V236(Never), + V237(Never), + V238(Never), + V239(Never), + V240(Never), + V241(Never), + V242(Never), + V243(Never), + V244(Never), + V245(Never), + V246(Never), + V247(Never), + V248(Never), + V249(Never), + V250(Never), + V251(Never), + V252(Never), + V253(Never), + V254(Never), + V255(Never), + V256(Never), + + Possible257, + Bool258(bool), + Possible259, +} + +// CHECK-LABEL: define noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @match5(i8{{.+}}%0) +// CHECK-NEXT: start: +// CHECK-NEXT: %[[REL_VAR:.+]] = add nsw i8 %0, -2 +// CHECK-NEXT: %[[REL_VAR_WIDE:.+]] = zext i8 %[[REL_VAR]] to i64 +// CHECK-NEXT: %[[IS_NICHE:.+]] = icmp ult i8 %[[REL_VAR]], 3 +// CHECK-NEXT: %[[NOT_IMPOSSIBLE:.+]] = icmp ne i8 %[[REL_VAR]], 1 +// CHECK-NEXT: call void @llvm.assume(i1 %[[NOT_IMPOSSIBLE]]) +// CHECK-NEXT: %[[NICHE_DISCR:.+]] = add nuw nsw i64 %[[REL_VAR_WIDE]], 257 +// CHECK-NEXT: %[[DISCR:.+]] = select i1 %[[IS_NICHE]], i64 %[[NICHE_DISCR]], i64 258 +// CHECK-NEXT: switch i64 %[[DISCR]], +// CHECK-NEXT: i64 257, +// CHECK-NEXT: i64 258, +// CHECK-NEXT: i64 259, +#[no_mangle] +pub fn match5(e: HugeVariantIndex) -> u8 { + use HugeVariantIndex::*; + match e { + Possible257 => 13, + Bool258(b) => b as u8, + Possible259 => 100, + } +} diff --git a/tests/codegen/enum/enum-two-variants-match.rs b/tests/codegen/enum/enum-two-variants-match.rs index 21ae1f96bca7..5b6c0e2f8ad1 100644 --- a/tests/codegen/enum/enum-two-variants-match.rs +++ b/tests/codegen/enum/enum-two-variants-match.rs @@ -1,5 +1,5 @@ //@ compile-flags: -Copt-level=3 -C no-prepopulate-passes -//@ only-x86_64 (because these discriminants are isize) +//@ only-64bit (because these discriminants are isize) #![crate_type = "lib"] @@ -51,3 +51,64 @@ pub fn result_match(x: Result) -> u16 { Ok(_) => 42, } } + +// CHECK-LABEL: @option_bool_match( +#[no_mangle] +pub fn option_bool_match(x: Option) -> char { + // CHECK: %[[RAW:.+]] = load i8, ptr %x + // CHECK: %[[IS_NONE:.+]] = icmp eq i8 %[[RAW]], 2 + // CHECK: %[[OPT_DISCR:.+]] = select i1 %[[IS_NONE]], i64 0, i64 1 + // CHECK: %[[OPT_DISCR_T:.+]] = trunc nuw i64 %[[OPT_DISCR]] to i1 + // CHECK: br i1 %[[OPT_DISCR_T]], label %[[BB_SOME:.+]], label %[[BB_NONE:.+]] + + // CHECK: [[BB_SOME]]: + // CHECK: %[[FIELD:.+]] = load i8, ptr %x + // CHECK: %[[FIELD_T:.+]] = trunc nuw i8 %[[FIELD]] to i1 + // CHECK: br i1 %[[FIELD_T]] + match x { + None => 'n', + Some(false) => 'f', + Some(true) => 't', + } +} + +use std::cmp::Ordering::{self, *}; +// CHECK-LABEL: @option_ordering_match( +#[no_mangle] +pub fn option_ordering_match(x: Option) -> char { + // CHECK: %[[RAW:.+]] = load i8, ptr %x + // CHECK: %[[IS_NONE:.+]] = icmp eq i8 %[[RAW]], 2 + // CHECK: %[[OPT_DISCR:.+]] = select i1 %[[IS_NONE]], i64 0, i64 1 + // CHECK: %[[OPT_DISCR_T:.+]] = trunc nuw i64 %[[OPT_DISCR]] to i1 + // CHECK: br i1 %[[OPT_DISCR_T]], label %[[BB_SOME:.+]], label %[[BB_NONE:.+]] + + // CHECK: [[BB_SOME]]: + // CHECK: %[[FIELD:.+]] = load i8, ptr %x + // CHECK: switch i8 %[[FIELD]], label %[[UNREACHABLE:.+]] [ + // CHECK-NEXT: i8 -1, label + // CHECK-NEXT: i8 0, label + // CHECK-NEXT: i8 1, label + // CHECK-NEXT: ] + + // CHECK: [[UNREACHABLE]]: + // CHECK-NEXT: unreachable + match x { + None => '?', + Some(Less) => '<', + Some(Equal) => '=', + Some(Greater) => '>', + } +} + +// CHECK-LABEL: @option_nonzero_match( +#[no_mangle] +pub fn option_nonzero_match(x: Option>) -> u16 { + // CHECK: %[[IS_NONE:.+]] = icmp eq i16 %x, 0 + // CHECK: %[[OPT_DISCR:.+]] = select i1 %[[IS_NONE]], i64 0, i64 1 + // CHECK: %[[OPT_DISCR_T:.+]] = trunc nuw i64 %[[OPT_DISCR]] to i1 + // CHECK: br i1 %[[OPT_DISCR_T]], label %[[BB_SOME:.+]], label %[[BB_NONE:.+]] + match x { + None => 123, + Some(_) => 987, + } +} From 51e67e21cf2ca50a431d392a03dcc66377a365cd Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 29 Mar 2025 12:45:20 -0700 Subject: [PATCH 131/606] LLVM18 compatibility fixes in the tests --- tests/codegen/enum/enum-match.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/codegen/enum/enum-match.rs b/tests/codegen/enum/enum-match.rs index bea0d5f33b0a..6e185cf89329 100644 --- a/tests/codegen/enum/enum-match.rs +++ b/tests/codegen/enum/enum-match.rs @@ -6,6 +6,9 @@ // Check each of the 3 cases for `codegen_get_discr`. +// FIXME: once our min-bar LLVM has `range` attributes, update the various +// tests here to no longer have the `range`s and `nsw`s as optional. + // Case 0: One tagged variant. pub enum Enum0 { A(bool), @@ -144,7 +147,7 @@ pub enum MiddleNiche { // CHECK-LABEL: define noundef{{( range\(i8 -?[0-9]+, -?[0-9]+\))?}} i8 @match4(i8{{.+}}%0) // CHECK-NEXT: start: -// CHECK-NEXT: %[[REL_VAR:.+]] = add nsw i8 %0, -2 +// CHECK-NEXT: %[[REL_VAR:.+]] = add{{( nsw)?}} i8 %0, -2 // CHECK-NEXT: %[[IS_NICHE:.+]] = icmp ult i8 %[[REL_VAR]], 5 // CHECK-NEXT: %[[NOT_IMPOSSIBLE:.+]] = icmp ne i8 %[[REL_VAR]], 2 // CHECK-NEXT: call void @llvm.assume(i1 %[[NOT_IMPOSSIBLE]]) @@ -164,7 +167,7 @@ pub fn match4(e: MiddleNiche) -> u8 { // CHECK-LABEL: define{{.+}}i1 @match4_is_c(i8{{.+}}%e) // CHECK-NEXT: start -// CHECK-NEXT: %[[REL_VAR:.+]] = add nsw i8 %e, -2 +// CHECK-NEXT: %[[REL_VAR:.+]] = add{{( nsw)?}} i8 %e, -2 // CHECK-NEXT: %[[NOT_NICHE:.+]] = icmp ugt i8 %[[REL_VAR]], 4 // CHECK-NEXT: %[[NOT_IMPOSSIBLE:.+]] = icmp ne i8 %[[REL_VAR]], 2 // CHECK-NEXT: call void @llvm.assume(i1 %[[NOT_IMPOSSIBLE]]) @@ -448,7 +451,7 @@ pub enum HugeVariantIndex { // CHECK-LABEL: define noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @match5(i8{{.+}}%0) // CHECK-NEXT: start: -// CHECK-NEXT: %[[REL_VAR:.+]] = add nsw i8 %0, -2 +// CHECK-NEXT: %[[REL_VAR:.+]] = add{{( nsw)?}} i8 %0, -2 // CHECK-NEXT: %[[REL_VAR_WIDE:.+]] = zext i8 %[[REL_VAR]] to i64 // CHECK-NEXT: %[[IS_NICHE:.+]] = icmp ult i8 %[[REL_VAR]], 3 // CHECK-NEXT: %[[NOT_IMPOSSIBLE:.+]] = icmp ne i8 %[[REL_VAR]], 1 From 75135aaf19f22637b60b0e29255f0000029bdbf9 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 21 Mar 2025 15:07:05 +1100 Subject: [PATCH 132/606] coverage: Extract module `mapgen::unused` for handling unused functions --- .../src/coverageinfo/mapgen.rs | 129 +----------------- .../src/coverageinfo/mapgen/unused.rs | 128 +++++++++++++++++ 2 files changed, 132 insertions(+), 125 deletions(-) create mode 100644 compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/unused.rs diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index 9a2473d6cf23..23e068fafacf 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -5,15 +5,11 @@ use rustc_abi::Align; use rustc_codegen_ssa::traits::{ BaseTypeCodegenMethods, ConstCodegenMethods, StaticCodegenMethods, }; -use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; -use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_data_structures::fx::FxIndexMap; use rustc_index::IndexVec; -use rustc_middle::mir; -use rustc_middle::mir::mono::MonoItemPartitions; -use rustc_middle::ty::{self, TyCtxt}; +use rustc_middle::ty::TyCtxt; use rustc_session::RemapFileNameExt; use rustc_session::config::RemapPathScopeComponents; -use rustc_span::def_id::DefIdSet; use rustc_span::{SourceFile, StableSourceFileId}; use tracing::debug; @@ -24,6 +20,7 @@ use crate::llvm; mod covfun; mod spans; +mod unused; /// Generates and exports the coverage map, which is embedded in special /// linker sections in the final binary. @@ -76,7 +73,7 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) { // In a single designated CGU, also prepare covfun records for functions // in this crate that were instrumented for coverage, but are unused. if cx.codegen_unit.is_code_coverage_dead_code_cgu() { - let mut unused_instances = gather_unused_function_instances(cx); + let mut unused_instances = unused::gather_unused_function_instances(cx); // Sort the unused instances by symbol name, for the same reason as the used ones. unused_instances.sort_by_cached_key(|&instance| tcx.symbol_name(instance).name); covfun_records.extend(unused_instances.into_iter().filter_map(|instance| { @@ -249,121 +246,3 @@ fn generate_covmap_record<'ll>(cx: &CodegenCx<'ll, '_>, version: u32, filenames_ cx.add_used_global(covmap_global); } - -/// Each CGU will normally only emit coverage metadata for the functions that it actually generates. -/// But since we don't want unused functions to disappear from coverage reports, we also scan for -/// functions that were instrumented but are not participating in codegen. -/// -/// These unused functions don't need to be codegenned, but we do need to add them to the function -/// coverage map (in a single designated CGU) so that we still emit coverage mappings for them. -/// We also end up adding their symbol names to a special global array that LLVM will include in -/// its embedded coverage data. -fn gather_unused_function_instances<'tcx>(cx: &CodegenCx<'_, 'tcx>) -> Vec> { - assert!(cx.codegen_unit.is_code_coverage_dead_code_cgu()); - - let tcx = cx.tcx; - let usage = prepare_usage_sets(tcx); - - let is_unused_fn = |def_id: LocalDefId| -> bool { - // Usage sets expect `DefId`, so convert from `LocalDefId`. - let d: DefId = LocalDefId::to_def_id(def_id); - // To be potentially eligible for "unused function" mappings, a definition must: - // - Be eligible for coverage instrumentation - // - Not participate directly in codegen (or have lost all its coverage statements) - // - Not have any coverage statements inlined into codegenned functions - tcx.is_eligible_for_coverage(def_id) - && (!usage.all_mono_items.contains(&d) || usage.missing_own_coverage.contains(&d)) - && !usage.used_via_inlining.contains(&d) - }; - - // FIXME(#79651): Consider trying to filter out dummy instantiations of - // unused generic functions from library crates, because they can produce - // "unused instantiation" in coverage reports even when they are actually - // used by some downstream crate in the same binary. - - tcx.mir_keys(()) - .iter() - .copied() - .filter(|&def_id| is_unused_fn(def_id)) - .map(|def_id| make_dummy_instance(tcx, def_id)) - .collect::>() -} - -struct UsageSets<'tcx> { - all_mono_items: &'tcx DefIdSet, - used_via_inlining: FxHashSet, - missing_own_coverage: FxHashSet, -} - -/// Prepare sets of definitions that are relevant to deciding whether something -/// is an "unused function" for coverage purposes. -fn prepare_usage_sets<'tcx>(tcx: TyCtxt<'tcx>) -> UsageSets<'tcx> { - let MonoItemPartitions { all_mono_items, codegen_units, .. } = - tcx.collect_and_partition_mono_items(()); - - // Obtain a MIR body for each function participating in codegen, via an - // arbitrary instance. - let mut def_ids_seen = FxHashSet::default(); - let def_and_mir_for_all_mono_fns = codegen_units - .iter() - .flat_map(|cgu| cgu.items().keys()) - .filter_map(|item| match item { - mir::mono::MonoItem::Fn(instance) => Some(instance), - mir::mono::MonoItem::Static(_) | mir::mono::MonoItem::GlobalAsm(_) => None, - }) - // We only need one arbitrary instance per definition. - .filter(move |instance| def_ids_seen.insert(instance.def_id())) - .map(|instance| { - // We don't care about the instance, just its underlying MIR. - let body = tcx.instance_mir(instance.def); - (instance.def_id(), body) - }); - - // Functions whose coverage statements were found inlined into other functions. - let mut used_via_inlining = FxHashSet::default(); - // Functions that were instrumented, but had all of their coverage statements - // removed by later MIR transforms (e.g. UnreachablePropagation). - let mut missing_own_coverage = FxHashSet::default(); - - for (def_id, body) in def_and_mir_for_all_mono_fns { - let mut saw_own_coverage = false; - - // Inspect every coverage statement in the function's MIR. - for stmt in body - .basic_blocks - .iter() - .flat_map(|block| &block.statements) - .filter(|stmt| matches!(stmt.kind, mir::StatementKind::Coverage(_))) - { - if let Some(inlined) = stmt.source_info.scope.inlined_instance(&body.source_scopes) { - // This coverage statement was inlined from another function. - used_via_inlining.insert(inlined.def_id()); - } else { - // Non-inlined coverage statements belong to the enclosing function. - saw_own_coverage = true; - } - } - - if !saw_own_coverage && body.function_coverage_info.is_some() { - missing_own_coverage.insert(def_id); - } - } - - UsageSets { all_mono_items, used_via_inlining, missing_own_coverage } -} - -fn make_dummy_instance<'tcx>(tcx: TyCtxt<'tcx>, local_def_id: LocalDefId) -> ty::Instance<'tcx> { - let def_id = local_def_id.to_def_id(); - - // Make a dummy instance that fills in all generics with placeholders. - ty::Instance::new( - def_id, - ty::GenericArgs::for_item(tcx, def_id, |param, _| { - if let ty::GenericParamDefKind::Lifetime = param.kind { - tcx.lifetimes.re_erased.into() - } else { - tcx.mk_param_from_def(param) - } - }), - ) -} diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/unused.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/unused.rs new file mode 100644 index 000000000000..e7c9075bc15d --- /dev/null +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/unused.rs @@ -0,0 +1,128 @@ +use rustc_data_structures::fx::FxHashSet; +use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_middle::mir; +use rustc_middle::mir::mono::MonoItemPartitions; +use rustc_middle::ty::{self, TyCtxt}; +use rustc_span::def_id::DefIdSet; + +use crate::common::CodegenCx; + +/// Each CGU will normally only emit coverage metadata for the functions that it actually generates. +/// But since we don't want unused functions to disappear from coverage reports, we also scan for +/// functions that were instrumented but are not participating in codegen. +/// +/// These unused functions don't need to be codegenned, but we do need to add them to the function +/// coverage map (in a single designated CGU) so that we still emit coverage mappings for them. +/// We also end up adding their symbol names to a special global array that LLVM will include in +/// its embedded coverage data. +pub(crate) fn gather_unused_function_instances<'tcx>( + cx: &CodegenCx<'_, 'tcx>, +) -> Vec> { + assert!(cx.codegen_unit.is_code_coverage_dead_code_cgu()); + + let tcx = cx.tcx; + let usage = prepare_usage_sets(tcx); + + let is_unused_fn = |def_id: LocalDefId| -> bool { + // Usage sets expect `DefId`, so convert from `LocalDefId`. + let d: DefId = LocalDefId::to_def_id(def_id); + // To be potentially eligible for "unused function" mappings, a definition must: + // - Be eligible for coverage instrumentation + // - Not participate directly in codegen (or have lost all its coverage statements) + // - Not have any coverage statements inlined into codegenned functions + tcx.is_eligible_for_coverage(def_id) + && (!usage.all_mono_items.contains(&d) || usage.missing_own_coverage.contains(&d)) + && !usage.used_via_inlining.contains(&d) + }; + + // FIXME(#79651): Consider trying to filter out dummy instantiations of + // unused generic functions from library crates, because they can produce + // "unused instantiation" in coverage reports even when they are actually + // used by some downstream crate in the same binary. + + tcx.mir_keys(()) + .iter() + .copied() + .filter(|&def_id| is_unused_fn(def_id)) + .map(|def_id| make_dummy_instance(tcx, def_id)) + .collect::>() +} + +struct UsageSets<'tcx> { + all_mono_items: &'tcx DefIdSet, + used_via_inlining: FxHashSet, + missing_own_coverage: FxHashSet, +} + +/// Prepare sets of definitions that are relevant to deciding whether something +/// is an "unused function" for coverage purposes. +fn prepare_usage_sets<'tcx>(tcx: TyCtxt<'tcx>) -> UsageSets<'tcx> { + let MonoItemPartitions { all_mono_items, codegen_units, .. } = + tcx.collect_and_partition_mono_items(()); + + // Obtain a MIR body for each function participating in codegen, via an + // arbitrary instance. + let mut def_ids_seen = FxHashSet::default(); + let def_and_mir_for_all_mono_fns = codegen_units + .iter() + .flat_map(|cgu| cgu.items().keys()) + .filter_map(|item| match item { + mir::mono::MonoItem::Fn(instance) => Some(instance), + mir::mono::MonoItem::Static(_) | mir::mono::MonoItem::GlobalAsm(_) => None, + }) + // We only need one arbitrary instance per definition. + .filter(move |instance| def_ids_seen.insert(instance.def_id())) + .map(|instance| { + // We don't care about the instance, just its underlying MIR. + let body = tcx.instance_mir(instance.def); + (instance.def_id(), body) + }); + + // Functions whose coverage statements were found inlined into other functions. + let mut used_via_inlining = FxHashSet::default(); + // Functions that were instrumented, but had all of their coverage statements + // removed by later MIR transforms (e.g. UnreachablePropagation). + let mut missing_own_coverage = FxHashSet::default(); + + for (def_id, body) in def_and_mir_for_all_mono_fns { + let mut saw_own_coverage = false; + + // Inspect every coverage statement in the function's MIR. + for stmt in body + .basic_blocks + .iter() + .flat_map(|block| &block.statements) + .filter(|stmt| matches!(stmt.kind, mir::StatementKind::Coverage(_))) + { + if let Some(inlined) = stmt.source_info.scope.inlined_instance(&body.source_scopes) { + // This coverage statement was inlined from another function. + used_via_inlining.insert(inlined.def_id()); + } else { + // Non-inlined coverage statements belong to the enclosing function. + saw_own_coverage = true; + } + } + + if !saw_own_coverage && body.function_coverage_info.is_some() { + missing_own_coverage.insert(def_id); + } + } + + UsageSets { all_mono_items, used_via_inlining, missing_own_coverage } +} + +fn make_dummy_instance<'tcx>(tcx: TyCtxt<'tcx>, local_def_id: LocalDefId) -> ty::Instance<'tcx> { + let def_id = local_def_id.to_def_id(); + + // Make a dummy instance that fills in all generics with placeholders. + ty::Instance::new( + def_id, + ty::GenericArgs::for_item(tcx, def_id, |param, _| { + if let ty::GenericParamDefKind::Lifetime = param.kind { + tcx.lifetimes.re_erased.into() + } else { + tcx.mk_param_from_def(param) + } + }), + ) +} From b3c40cf374422ac8f6cbb14fa6747b2fae5762db Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 21 Mar 2025 15:14:22 +1100 Subject: [PATCH 133/606] coverage: Deal with unused functions and their names in one place --- .../src/coverageinfo/mapgen.rs | 34 ++----------- .../src/coverageinfo/mapgen/covfun.rs | 8 ---- .../src/coverageinfo/mapgen/unused.rs | 48 ++++++++++++++++++- 3 files changed, 51 insertions(+), 39 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index 23e068fafacf..5e62ce285dd8 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -73,12 +73,11 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) { // In a single designated CGU, also prepare covfun records for functions // in this crate that were instrumented for coverage, but are unused. if cx.codegen_unit.is_code_coverage_dead_code_cgu() { - let mut unused_instances = unused::gather_unused_function_instances(cx); - // Sort the unused instances by symbol name, for the same reason as the used ones. - unused_instances.sort_by_cached_key(|&instance| tcx.symbol_name(instance).name); - covfun_records.extend(unused_instances.into_iter().filter_map(|instance| { - prepare_covfun_record(tcx, &mut global_file_table, instance, false) - })); + unused::prepare_covfun_records_for_unused_functions( + cx, + &mut global_file_table, + &mut covfun_records, + ); } // If there are no covfun records for this CGU, don't generate a covmap record. @@ -97,33 +96,10 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) { // contain multiple covmap records from different compilation units. let filenames_hash = llvm_cov::hash_bytes(&filenames_buffer); - let mut unused_function_names = vec![]; - for covfun in &covfun_records { - unused_function_names.extend(covfun.mangled_function_name_if_unused()); - covfun::generate_covfun_record(cx, filenames_hash, covfun) } - // For unused functions, we need to take their mangled names and store them - // in a specially-named global array. LLVM's `InstrProfiling` pass will - // detect this global and include those names in its `__llvm_prf_names` - // section. (See `llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp`.) - if !unused_function_names.is_empty() { - assert!(cx.codegen_unit.is_code_coverage_dead_code_cgu()); - - let name_globals = unused_function_names - .into_iter() - .map(|mangled_function_name| cx.const_str(mangled_function_name).0) - .collect::>(); - let initializer = cx.const_array(cx.type_ptr(), &name_globals); - - let array = llvm::add_global(cx.llmod, cx.val_ty(initializer), c"__llvm_coverage_names"); - llvm::set_global_constant(array, true); - llvm::set_linkage(array, llvm::Linkage::InternalLinkage); - llvm::set_initializer(array, initializer); - } - // Generate the coverage map header, which contains the filenames used by // this CGU's coverage mappings, and store it in a well-known global. // (This is skipped if we returned early due to having no covfun records.) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs index 048e1988c327..93419c2caad2 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs @@ -37,14 +37,6 @@ pub(crate) struct CovfunRecord<'tcx> { regions: ffi::Regions, } -impl<'tcx> CovfunRecord<'tcx> { - /// FIXME(Zalathar): Make this the responsibility of the code that determines - /// which functions are unused. - pub(crate) fn mangled_function_name_if_unused(&self) -> Option<&'tcx str> { - (!self.is_used).then_some(self.mangled_function_name) - } -} - pub(crate) fn prepare_covfun_record<'tcx>( tcx: TyCtxt<'tcx>, global_file_table: &mut GlobalFileTable, diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/unused.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/unused.rs index e7c9075bc15d..ab030f5b6152 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/unused.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/unused.rs @@ -1,3 +1,4 @@ +use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, ConstCodegenMethods}; use rustc_data_structures::fx::FxHashSet; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::mir; @@ -6,6 +7,9 @@ use rustc_middle::ty::{self, TyCtxt}; use rustc_span::def_id::DefIdSet; use crate::common::CodegenCx; +use crate::coverageinfo::mapgen::GlobalFileTable; +use crate::coverageinfo::mapgen::covfun::{CovfunRecord, prepare_covfun_record}; +use crate::llvm; /// Each CGU will normally only emit coverage metadata for the functions that it actually generates. /// But since we don't want unused functions to disappear from coverage reports, we also scan for @@ -15,9 +19,48 @@ use crate::common::CodegenCx; /// coverage map (in a single designated CGU) so that we still emit coverage mappings for them. /// We also end up adding their symbol names to a special global array that LLVM will include in /// its embedded coverage data. -pub(crate) fn gather_unused_function_instances<'tcx>( +pub(crate) fn prepare_covfun_records_for_unused_functions<'tcx>( cx: &CodegenCx<'_, 'tcx>, -) -> Vec> { + global_file_table: &mut GlobalFileTable, + covfun_records: &mut Vec>, +) { + assert!(cx.codegen_unit.is_code_coverage_dead_code_cgu()); + + let mut unused_instances = gather_unused_function_instances(cx); + // Sort the unused instances by symbol name, so that their order isn't hash-sensitive. + unused_instances.sort_by_key(|instance| instance.symbol_name); + + // Try to create a covfun record for each unused function. + let mut name_globals = Vec::with_capacity(unused_instances.len()); + covfun_records.extend(unused_instances.into_iter().filter_map(|unused| try { + let record = prepare_covfun_record(cx.tcx, global_file_table, unused.instance, false)?; + // If successful, also store its symbol name in a global constant. + name_globals.push(cx.const_str(unused.symbol_name.name).0); + record + })); + + // Store the names of unused functions in a specially-named global array. + // LLVM's `InstrProfilling` pass will detect this array, and include the + // referenced names in its `__llvm_prf_names` section. + // (See `llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp`.) + if !name_globals.is_empty() { + let initializer = cx.const_array(cx.type_ptr(), &name_globals); + + let array = llvm::add_global(cx.llmod, cx.val_ty(initializer), c"__llvm_coverage_names"); + llvm::set_global_constant(array, true); + llvm::set_linkage(array, llvm::Linkage::InternalLinkage); + llvm::set_initializer(array, initializer); + } +} + +/// Holds a dummy function instance along with its symbol name, to avoid having +/// to repeatedly query for the name. +struct UnusedInstance<'tcx> { + instance: ty::Instance<'tcx>, + symbol_name: ty::SymbolName<'tcx>, +} + +fn gather_unused_function_instances<'tcx>(cx: &CodegenCx<'_, 'tcx>) -> Vec> { assert!(cx.codegen_unit.is_code_coverage_dead_code_cgu()); let tcx = cx.tcx; @@ -45,6 +88,7 @@ pub(crate) fn gather_unused_function_instances<'tcx>( .copied() .filter(|&def_id| is_unused_fn(def_id)) .map(|def_id| make_dummy_instance(tcx, def_id)) + .map(|instance| UnusedInstance { instance, symbol_name: tcx.symbol_name(instance) }) .collect::>() } From f21d18063ca8beb847121e367140395348399082 Mon Sep 17 00:00:00 2001 From: izarma Date: Sun, 6 Apr 2025 15:09:59 +0530 Subject: [PATCH 134/606] doc changes --- library/core/src/iter/adapters/enumerate.rs | 2 +- library/core/src/iter/traits/iterator.rs | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/library/core/src/iter/adapters/enumerate.rs b/library/core/src/iter/adapters/enumerate.rs index f9c388e8564d..bd093e279c38 100644 --- a/library/core/src/iter/adapters/enumerate.rs +++ b/library/core/src/iter/adapters/enumerate.rs @@ -36,7 +36,7 @@ where /// /// The method does no guarding against overflows, so enumerating more than /// `usize::MAX` elements either produces the wrong result or panics. If - /// debug assertions are enabled, a panic is guaranteed. + /// overflow checks are enabled, a panic is guaranteed. /// /// # Panics /// diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 3bbb52fdbcb5..d9534a445980 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -199,7 +199,7 @@ pub trait Iterator { /// /// The method does no guarding against overflows, so counting elements of /// an iterator with more than [`usize::MAX`] elements either produces the - /// wrong result or panics. If debug assertions are enabled, a panic is + /// wrong result or panics. If overflow checks are enabled, a panic is /// guaranteed. /// /// # Panics @@ -931,7 +931,7 @@ pub trait Iterator { /// /// The method does no guarding against overflows, so enumerating more than /// [`usize::MAX`] elements either produces the wrong result or panics. If - /// debug assertions are enabled, a panic is guaranteed. + /// overflow checks are enabled, a panic is guaranteed. /// /// # Panics /// @@ -2964,7 +2964,7 @@ pub trait Iterator { /// /// The method does no guarding against overflows, so if there are more /// than [`usize::MAX`] non-matching elements, it either produces the wrong - /// result or panics. If debug assertions are enabled, a panic is + /// result or panics. If overflow checks are enabled, a panic is /// guaranteed. /// /// # Panics @@ -3516,7 +3516,7 @@ pub trait Iterator { /// # Panics /// /// When calling `sum()` and a primitive integer type is being returned, this - /// method will panic if the computation overflows and debug assertions are + /// method will panic if the computation overflows and overflow checks are /// enabled. /// /// # Examples @@ -3550,7 +3550,7 @@ pub trait Iterator { /// # Panics /// /// When calling `product()` and a primitive integer type is being returned, - /// method will panic if the computation overflows and debug assertions are + /// method will panic if the computation overflows and overflow checks are /// enabled. /// /// # Examples From de57c0515d39a285541039205e7f9d6b06430031 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sat, 29 Mar 2025 13:38:48 +0100 Subject: [PATCH 135/606] Let `const_to_pat` handle the `ExpandedConstant` wrapping --- .../src/thir/pattern/const_to_pat.rs | 10 +++++++++- .../rustc_mir_build/src/thir/pattern/mod.rs | 17 +++-------------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 372453688d24..0fca9775530c 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -5,6 +5,7 @@ use rustc_apfloat::Float; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Diag; use rustc_hir as hir; +use rustc_hir::def::DefKind; use rustc_index::Idx; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::Obligation; @@ -182,7 +183,14 @@ impl<'tcx> ConstToPat<'tcx> { } } - inlined_const_as_pat + // Wrap the pattern in a marker node to indicate that it is the result of lowering a + // constant. This is used for diagnostics, and for unsafety checking of inline const blocks. + let kind = PatKind::ExpandedConstant { + subpattern: inlined_const_as_pat, + def_id: uv.def, + is_inline: matches!(self.tcx.def_kind(uv.def), DefKind::InlineConst), + }; + Box::new(Pat { kind, ty, span: self.span }) } fn field_pats( diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index d20e051548bf..fbb3a0995e28 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -567,15 +567,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { // Lower the named constant to a THIR pattern. let args = self.typeck_results.node_args(id); let c = ty::Const::new_unevaluated(self.tcx, ty::UnevaluatedConst { def: def_id, args }); - let subpattern = self.const_to_pat(c, ty, id, span); - - // Wrap the pattern in a marker node to indicate that it is the result - // of lowering a named constant. This marker is used for improved - // diagnostics in some situations, but has no effect at runtime. - let mut pattern = { - let kind = PatKind::ExpandedConstant { subpattern, def_id, is_inline: false }; - Box::new(Pat { span, ty, kind }) - }; + let mut pattern = self.const_to_pat(c, ty, id, span); // If this is an associated constant with an explicit user-written // type, add an ascription node (e.g. ` as MyTrait>::CONST`). @@ -619,11 +611,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { debug_assert!(!args.has_free_regions()); let ct = ty::UnevaluatedConst { def: def_id.to_def_id(), args }; - let subpattern = self.const_to_pat(ty::Const::new_unevaluated(self.tcx, ct), ty, id, span); - - // Wrap the pattern in a marker node to indicate that it is the result - // of lowering an inline const block. - PatKind::ExpandedConstant { subpattern, def_id: def_id.to_def_id(), is_inline: true } + let c = ty::Const::new_unevaluated(self.tcx, ct); + self.const_to_pat(c, ty, id, span).kind } /// Lowers the kinds of "expression" that can appear in a HIR pattern: From 090d76497f67f915f977c1176d50acaa2c962aeb Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sat, 29 Mar 2025 13:55:05 +0100 Subject: [PATCH 136/606] Remove the `is_inline` field from `PatKind::ExpandedConstant` --- compiler/rustc_middle/src/thir.rs | 22 +++++--------- .../src/builder/custom/parse/instruction.rs | 2 +- .../src/builder/matches/match_pair.rs | 11 ++++--- .../rustc_mir_build/src/check_unsafety.rs | 4 +-- .../src/thir/pattern/check_match.rs | 5 ++-- .../src/thir/pattern/const_to_pat.rs | 7 +---- .../rustc_mir_build/src/thir/pattern/mod.rs | 29 +++++++------------ compiler/rustc_mir_build/src/thir/print.rs | 3 +- 8 files changed, 32 insertions(+), 51 deletions(-) diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 8d373cb3b309..bc49c197ef81 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -812,23 +812,17 @@ pub enum PatKind<'tcx> { }, /// Pattern obtained by converting a constant (inline or named) to its pattern - /// representation using `const_to_pat`. + /// representation using `const_to_pat`. This is used for unsafety checking. ExpandedConstant { - /// [DefId] of the constant, we need this so that we have a - /// reference that can be used by unsafety checking to visit nested - /// unevaluated constants and for diagnostics. If the `DefId` doesn't - /// correspond to a local crate, it points at the `const` item. + /// [DefId] of the constant item. def_id: DefId, - /// If `false`, then `def_id` points at a `const` item, otherwise it - /// corresponds to a local inline const. - is_inline: bool, - /// If the inline constant is used in a range pattern, this subpattern - /// represents the range (if both ends are inline constants, there will - /// be multiple InlineConstant wrappers). + /// The pattern that the constant lowered to. /// - /// Otherwise, the actual pattern that the constant lowered to. As with - /// other constants, inline constants are matched structurally where - /// possible. + /// HACK: we need to keep the `DefId` of inline constants around for unsafety checking; + /// therefore when a range pattern contains inline constants, we re-wrap the range pattern + /// with the `ExpandedConstant` nodes that correspond to the range endpoints. Hence + /// `subpattern` may actually be a range pattern, and `def_id` be the constant for one of + /// its endpoints. subpattern: Box>, }, diff --git a/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs index 19669021eefb..5918498f2392 100644 --- a/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs +++ b/compiler/rustc_mir_build/src/builder/custom/parse/instruction.rs @@ -145,7 +145,7 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> { let arm = &self.thir[*arm]; let value = match arm.pattern.kind { PatKind::Constant { value } => value, - PatKind::ExpandedConstant { ref subpattern, def_id: _, is_inline: false } + PatKind::ExpandedConstant { ref subpattern, def_id: _ } if let PatKind::Constant { value } = subpattern.kind => { value diff --git a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs index 29d400a957b4..c84664bd68e3 100644 --- a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs +++ b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs @@ -1,5 +1,6 @@ use std::sync::Arc; +use rustc_hir::def::DefKind; use rustc_middle::mir::*; use rustc_middle::thir::*; use rustc_middle::ty::{self, Ty, TypeVisitableExt}; @@ -201,15 +202,13 @@ impl<'tcx> MatchPairTree<'tcx> { None } - PatKind::ExpandedConstant { subpattern: ref pattern, def_id: _, is_inline: false } => { - MatchPairTree::for_pattern(place_builder, pattern, cx, &mut subpairs, extra_data); - None - } - PatKind::ExpandedConstant { subpattern: ref pattern, def_id, is_inline: true } => { + PatKind::ExpandedConstant { subpattern: ref pattern, def_id } => { MatchPairTree::for_pattern(place_builder, pattern, cx, &mut subpairs, extra_data); // Apply a type ascription for the inline constant to the value at `match_pair.place` - if let Some(source) = place { + if let Some(source) = place + && matches!(cx.tcx.def_kind(def_id), DefKind::InlineConst) + { let span = pattern.span; let parent_id = cx.tcx.typeck_root_def_id(cx.def_id.to_def_id()); let args = ty::InlineConstArgs::new( diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 6fb9974fc8e2..b52d0d1e3004 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -403,9 +403,9 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { visit::walk_pat(self, pat); self.inside_adt = old_inside_adt; } - PatKind::ExpandedConstant { def_id, is_inline, .. } => { + PatKind::ExpandedConstant { def_id, .. } => { if let Some(def) = def_id.as_local() - && *is_inline + && matches!(self.tcx.def_kind(def_id), DefKind::InlineConst) { self.visit_inner_body(def); } diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 9f5e2c06b229..78583a402fe9 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -676,7 +676,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { unpeeled_pat = subpattern; } - if let PatKind::ExpandedConstant { def_id, is_inline: false, .. } = unpeeled_pat.kind + if let PatKind::ExpandedConstant { def_id, .. } = unpeeled_pat.kind && let DefKind::Const = self.tcx.def_kind(def_id) && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(pat.span) // We filter out paths with multiple path::segments. @@ -1296,7 +1296,8 @@ fn report_non_exhaustive_match<'p, 'tcx>( for &arm in arms { let arm = &thir.arms[arm]; - if let PatKind::ExpandedConstant { def_id, is_inline: false, .. } = arm.pattern.kind + if let PatKind::ExpandedConstant { def_id, .. } = arm.pattern.kind + && !matches!(cx.tcx.def_kind(def_id), DefKind::InlineConst) && let Ok(snippet) = cx.tcx.sess.source_map().span_to_snippet(arm.pattern.span) // We filter out paths with multiple path::segments. && snippet.chars().all(|c| c.is_alphanumeric() || c == '_') diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 0fca9775530c..a40001bf7455 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -5,7 +5,6 @@ use rustc_apfloat::Float; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Diag; use rustc_hir as hir; -use rustc_hir::def::DefKind; use rustc_index::Idx; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::Obligation; @@ -185,11 +184,7 @@ impl<'tcx> ConstToPat<'tcx> { // Wrap the pattern in a marker node to indicate that it is the result of lowering a // constant. This is used for diagnostics, and for unsafety checking of inline const blocks. - let kind = PatKind::ExpandedConstant { - subpattern: inlined_const_as_pat, - def_id: uv.def, - is_inline: matches!(self.tcx.def_kind(uv.def), DefKind::InlineConst), - }; + let kind = PatKind::ExpandedConstant { subpattern: inlined_const_as_pat, def_id: uv.def }; Box::new(Pat { kind, ty, span: self.span }) } diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index fbb3a0995e28..e7850962785e 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -20,7 +20,7 @@ use rustc_middle::thir::{ use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::{bug, span_bug}; -use rustc_span::def_id::LocalDefId; +use rustc_span::def_id::DefId; use rustc_span::{ErrorGuaranteed, Span}; use tracing::{debug, instrument}; @@ -124,7 +124,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { expr: Option<&'tcx hir::PatExpr<'tcx>>, // Out-parameters collecting extra data to be reapplied by the caller ascriptions: &mut Vec>, - inline_consts: &mut Vec, + expanded_consts: &mut Vec, ) -> Result>, ErrorGuaranteed> { let Some(expr) = expr else { return Ok(None) }; @@ -139,10 +139,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { ascriptions.push(ascription); kind = subpattern.kind; } - PatKind::ExpandedConstant { is_inline, def_id, subpattern } => { - if is_inline { - inline_consts.extend(def_id.as_local()); - } + PatKind::ExpandedConstant { def_id, subpattern } => { + expanded_consts.push(def_id); kind = subpattern.kind; } _ => break, @@ -221,10 +219,10 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { // Collect extra data while lowering the endpoints, to be reapplied later. let mut ascriptions = vec![]; - let mut inline_consts = vec![]; + let mut expanded_consts = vec![]; let mut lower_endpoint = - |expr| self.lower_pattern_range_endpoint(expr, &mut ascriptions, &mut inline_consts); + |expr| self.lower_pattern_range_endpoint(expr, &mut ascriptions, &mut expanded_consts); let lo = lower_endpoint(lo_expr)?.unwrap_or(PatRangeBoundary::NegInfinity); let hi = lower_endpoint(hi_expr)?.unwrap_or(PatRangeBoundary::PosInfinity); @@ -269,17 +267,12 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { // `Foo::<'a>::A..=Foo::B`), we need to put the ascriptions for the associated // constants somewhere. Have them on the range pattern. for ascription in ascriptions { - kind = PatKind::AscribeUserType { - ascription, - subpattern: Box::new(Pat { span, ty, kind }), - }; + let subpattern = Box::new(Pat { span, ty, kind }); + kind = PatKind::AscribeUserType { ascription, subpattern }; } - for def in inline_consts { - kind = PatKind::ExpandedConstant { - def_id: def.to_def_id(), - is_inline: true, - subpattern: Box::new(Pat { span, ty, kind }), - }; + for def_id in expanded_consts { + let subpattern = Box::new(Pat { span, ty, kind }); + kind = PatKind::ExpandedConstant { def_id, subpattern }; } Ok(kind) } diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs index 16cef0ec3acb..aa8d2e5897ea 100644 --- a/compiler/rustc_mir_build/src/thir/print.rs +++ b/compiler/rustc_mir_build/src/thir/print.rs @@ -740,10 +740,9 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> { print_indented!(self, format!("value: {:?}", value), depth_lvl + 2); print_indented!(self, "}", depth_lvl + 1); } - PatKind::ExpandedConstant { def_id, is_inline, subpattern } => { + PatKind::ExpandedConstant { def_id, subpattern } => { print_indented!(self, "ExpandedConstant {", depth_lvl + 1); print_indented!(self, format!("def_id: {def_id:?}"), depth_lvl + 2); - print_indented!(self, format!("is_inline: {is_inline:?}"), depth_lvl + 2); print_indented!(self, "subpattern:", depth_lvl + 2); self.print_pat(subpattern, depth_lvl + 2); print_indented!(self, "}", depth_lvl + 1); From 50e10b37c040af7b33b034eec4f7de9b9323b4a2 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sat, 29 Mar 2025 12:32:07 +0100 Subject: [PATCH 137/606] Tweak `lower_pat_expr` --- .../rustc_mir_build/src/thir/pattern/mod.rs | 68 +++++++++---------- 1 file changed, 33 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index e7850962785e..153a3b8a7298 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -617,43 +617,41 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { expr: &'tcx hir::PatExpr<'tcx>, pat_ty: Option>, ) -> PatKind<'tcx> { - let (lit, neg) = match &expr.kind { - hir::PatExprKind::Path(qpath) => { - return self.lower_path(qpath, expr.hir_id, expr.span).kind; - } + match &expr.kind { + hir::PatExprKind::Path(qpath) => self.lower_path(qpath, expr.hir_id, expr.span).kind, hir::PatExprKind::ConstBlock(anon_const) => { - return self.lower_inline_const(anon_const, expr.hir_id, expr.span); + self.lower_inline_const(anon_const, expr.hir_id, expr.span) } - hir::PatExprKind::Lit { lit, negated } => (lit, *negated), - }; - - // We handle byte string literal patterns by using the pattern's type instead of the - // literal's type in `const_to_pat`: if the literal `b"..."` matches on a slice reference, - // the pattern's type will be `&[u8]` whereas the literal's type is `&[u8; 3]`; using the - // pattern's type means we'll properly translate it to a slice reference pattern. This works - // because slices and arrays have the same valtree representation. - // HACK: As an exception, use the literal's type if `pat_ty` is `String`; this can happen if - // `string_deref_patterns` is enabled. There's a special case for that when lowering to MIR. - // FIXME(deref_patterns): This hack won't be necessary once `string_deref_patterns` is - // superseded by a more general implementation of deref patterns. - let ct_ty = match pat_ty { - Some(pat_ty) - if let ty::Adt(def, _) = *pat_ty.kind() - && self.tcx.is_lang_item(def.did(), LangItem::String) => - { - if !self.tcx.features().string_deref_patterns() { - span_bug!( - expr.span, - "matching on `String` went through without enabling string_deref_patterns" - ); - } - self.typeck_results.node_type(expr.hir_id) + hir::PatExprKind::Lit { lit, negated } => { + // We handle byte string literal patterns by using the pattern's type instead of the + // literal's type in `const_to_pat`: if the literal `b"..."` matches on a slice reference, + // the pattern's type will be `&[u8]` whereas the literal's type is `&[u8; 3]`; using the + // pattern's type means we'll properly translate it to a slice reference pattern. This works + // because slices and arrays have the same valtree representation. + // HACK: As an exception, use the literal's type if `pat_ty` is `String`; this can happen if + // `string_deref_patterns` is enabled. There's a special case for that when lowering to MIR. + // FIXME(deref_patterns): This hack won't be necessary once `string_deref_patterns` is + // superseded by a more general implementation of deref patterns. + let ct_ty = match pat_ty { + Some(pat_ty) + if let ty::Adt(def, _) = *pat_ty.kind() + && self.tcx.is_lang_item(def.did(), LangItem::String) => + { + if !self.tcx.features().string_deref_patterns() { + span_bug!( + expr.span, + "matching on `String` went through without enabling string_deref_patterns" + ); + } + self.typeck_results.node_type(expr.hir_id) + } + Some(pat_ty) => pat_ty, + None => self.typeck_results.node_type(expr.hir_id), + }; + let lit_input = LitToConstInput { lit: &lit.node, ty: ct_ty, neg: *negated }; + let constant = self.tcx.at(expr.span).lit_to_const(lit_input); + self.const_to_pat(constant, ct_ty, expr.hir_id, lit.span).kind } - Some(pat_ty) => pat_ty, - None => self.typeck_results.node_type(expr.hir_id), - }; - let lit_input = LitToConstInput { lit: &lit.node, ty: ct_ty, neg }; - let constant = self.tcx.at(expr.span).lit_to_const(lit_input); - self.const_to_pat(constant, ct_ty, expr.hir_id, lit.span).kind + } } } From 961c7463d8df79bef545af0c07a534aabfd258c2 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sat, 29 Mar 2025 15:13:14 +0100 Subject: [PATCH 138/606] Add the inline const type annotation in pattern lowering --- .../src/builder/matches/match_pair.rs | 30 +--------------- .../rustc_mir_build/src/thir/pattern/mod.rs | 36 +++++++++++++++++-- 2 files changed, 35 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs index c84664bd68e3..fcfacf1e1f86 100644 --- a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs +++ b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs @@ -1,6 +1,5 @@ use std::sync::Arc; -use rustc_hir::def::DefKind; use rustc_middle::mir::*; use rustc_middle::thir::*; use rustc_middle::ty::{self, Ty, TypeVisitableExt}; @@ -202,35 +201,8 @@ impl<'tcx> MatchPairTree<'tcx> { None } - PatKind::ExpandedConstant { subpattern: ref pattern, def_id } => { + PatKind::ExpandedConstant { subpattern: ref pattern, .. } => { MatchPairTree::for_pattern(place_builder, pattern, cx, &mut subpairs, extra_data); - - // Apply a type ascription for the inline constant to the value at `match_pair.place` - if let Some(source) = place - && matches!(cx.tcx.def_kind(def_id), DefKind::InlineConst) - { - let span = pattern.span; - let parent_id = cx.tcx.typeck_root_def_id(cx.def_id.to_def_id()); - let args = ty::InlineConstArgs::new( - cx.tcx, - ty::InlineConstArgsParts { - parent_args: ty::GenericArgs::identity_for_item(cx.tcx, parent_id), - ty: cx.infcx.next_ty_var(span), - }, - ) - .args; - let user_ty = cx.infcx.canonicalize_user_type_annotation(ty::UserType::new( - ty::UserTypeKind::TypeOf(def_id, ty::UserArgs { args, user_self_ty: None }), - )); - let annotation = ty::CanonicalUserTypeAnnotation { - inferred_ty: pattern.ty, - span, - user_ty: Box::new(user_ty), - }; - let variance = ty::Contravariant; - extra_data.ascriptions.push(super::Ascription { annotation, source, variance }); - } - None } diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 153a3b8a7298..7da0c872dfe9 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -13,12 +13,15 @@ use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::pat_util::EnumerateAndAdjustIterator; use rustc_hir::{self as hir, LangItem, RangeEnd}; use rustc_index::Idx; +use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::mir::interpret::LitToConstInput; use rustc_middle::thir::{ Ascription, FieldPat, LocalVarId, Pat, PatKind, PatRange, PatRangeBoundary, }; use rustc_middle::ty::layout::IntegerExt; -use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{ + self, CanonicalUserTypeAnnotation, Ty, TyCtxt, TypeVisitableExt, TypingMode, +}; use rustc_middle::{bug, span_bug}; use rustc_span::def_id::DefId; use rustc_span::{ErrorGuaranteed, Span}; @@ -605,7 +608,36 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { let ct = ty::UnevaluatedConst { def: def_id.to_def_id(), args }; let c = ty::Const::new_unevaluated(self.tcx, ct); - self.const_to_pat(c, ty, id, span).kind + let pattern = self.const_to_pat(c, ty, id, span); + + // Apply a type ascription for the inline constant. + // FIXME: reusing the `args` above causes an ICE + let annotation = { + let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); + let args = ty::InlineConstArgs::new( + tcx, + ty::InlineConstArgsParts { + parent_args: ty::GenericArgs::identity_for_item(tcx, typeck_root_def_id), + ty: infcx.next_ty_var(span), + }, + ) + .args; + infcx.canonicalize_user_type_annotation(ty::UserType::new(ty::UserTypeKind::TypeOf( + def_id.to_def_id(), + ty::UserArgs { args, user_self_ty: None }, + ))) + }; + let annotation = + CanonicalUserTypeAnnotation { user_ty: Box::new(annotation), span, inferred_ty: ty }; + PatKind::AscribeUserType { + subpattern: pattern, + ascription: Ascription { + annotation, + // Note that we use `Contravariant` here. See the `variance` field documentation + // for details. + variance: ty::Contravariant, + }, + } } /// Lowers the kinds of "expression" that can appear in a HIR pattern: From d912c0352516bc8196437bbf00566a1df985b621 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sat, 29 Mar 2025 15:23:37 +0100 Subject: [PATCH 139/606] Reuse `parent_args` --- compiler/rustc_mir_build/src/thir/pattern/mod.rs | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 7da0c872dfe9..7ceeebbb70df 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -19,9 +19,7 @@ use rustc_middle::thir::{ Ascription, FieldPat, LocalVarId, Pat, PatKind, PatRange, PatRangeBoundary, }; use rustc_middle::ty::layout::IntegerExt; -use rustc_middle::ty::{ - self, CanonicalUserTypeAnnotation, Ty, TyCtxt, TypeVisitableExt, TypingMode, -}; +use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt, TypingMode}; use rustc_middle::{bug, span_bug}; use rustc_span::def_id::DefId; use rustc_span::{ErrorGuaranteed, Span}; @@ -600,26 +598,19 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { let ty = tcx.typeck(def_id).node_type(block.hir_id); let typeck_root_def_id = tcx.typeck_root_def_id(def_id.to_def_id()); - let parent_args = - tcx.erase_regions(ty::GenericArgs::identity_for_item(tcx, typeck_root_def_id)); + let parent_args = ty::GenericArgs::identity_for_item(tcx, typeck_root_def_id); let args = ty::InlineConstArgs::new(tcx, ty::InlineConstArgsParts { parent_args, ty }).args; - debug_assert!(!args.has_free_regions()); - let ct = ty::UnevaluatedConst { def: def_id.to_def_id(), args }; let c = ty::Const::new_unevaluated(self.tcx, ct); let pattern = self.const_to_pat(c, ty, id, span); // Apply a type ascription for the inline constant. - // FIXME: reusing the `args` above causes an ICE let annotation = { let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); let args = ty::InlineConstArgs::new( tcx, - ty::InlineConstArgsParts { - parent_args: ty::GenericArgs::identity_for_item(tcx, typeck_root_def_id), - ty: infcx.next_ty_var(span), - }, + ty::InlineConstArgsParts { parent_args, ty: infcx.next_ty_var(span) }, ) .args; infcx.canonicalize_user_type_annotation(ty::UserType::new(ty::UserTypeKind::TypeOf( From cd4453fdbadec9d9a3b0b40a069c63e01ad52ebf Mon Sep 17 00:00:00 2001 From: jackh726 Date: Sat, 5 Apr 2025 18:21:22 +0000 Subject: [PATCH 140/606] Explicitly depend on ena in rustc_type_ir and make the UnifyKey and UnifyValue imports non-nightly --- Cargo.lock | 1 + compiler/rustc_type_ir/Cargo.toml | 1 + compiler/rustc_type_ir/src/data_structures/mod.rs | 1 + compiler/rustc_type_ir/src/ty_kind.rs | 8 +------- 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 96526f7e9e7d..ce8efe631ce6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4581,6 +4581,7 @@ version = "0.0.0" dependencies = [ "bitflags", "derive-where", + "ena", "indexmap", "rustc-hash 1.1.0", "rustc_ast_ir", diff --git a/compiler/rustc_type_ir/Cargo.toml b/compiler/rustc_type_ir/Cargo.toml index 4adf71579266..83d3d78298e6 100644 --- a/compiler/rustc_type_ir/Cargo.toml +++ b/compiler/rustc_type_ir/Cargo.toml @@ -7,6 +7,7 @@ edition = "2024" # tidy-alphabetical-start bitflags = "2.4.1" derive-where = "1.2.7" +ena = "0.14.3" indexmap = "2.0.0" rustc-hash = "1.1.0" rustc_ast_ir = { path = "../rustc_ast_ir", default-features = false } diff --git a/compiler/rustc_type_ir/src/data_structures/mod.rs b/compiler/rustc_type_ir/src/data_structures/mod.rs index 30c67d10d0e8..a72669cbd189 100644 --- a/compiler/rustc_type_ir/src/data_structures/mod.rs +++ b/compiler/rustc_type_ir/src/data_structures/mod.rs @@ -1,5 +1,6 @@ use std::hash::BuildHasherDefault; +pub use ena::unify::{NoError, UnifyKey, UnifyValue}; use rustc_hash::FxHasher; pub use rustc_hash::{FxHashMap as HashMap, FxHashSet as HashSet}; diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index d35b22d517c5..753a72a051ad 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -6,9 +6,8 @@ use rustc_ast_ir::Mutability; #[cfg(feature = "nightly")] use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; #[cfg(feature = "nightly")] -use rustc_data_structures::unify::{NoError, UnifyKey, UnifyValue}; -#[cfg(feature = "nightly")] use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext}; +use rustc_type_ir::data_structures::{NoError, UnifyKey, UnifyValue}; use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; use self::TyKind::*; @@ -796,7 +795,6 @@ pub enum InferTy { /// Raw `TyVid` are used as the unification key for `sub_relations`; /// they carry no values. -#[cfg(feature = "nightly")] impl UnifyKey for TyVid { type Value = (); #[inline] @@ -812,7 +810,6 @@ impl UnifyKey for TyVid { } } -#[cfg(feature = "nightly")] impl UnifyValue for IntVarValue { type Error = NoError; @@ -832,7 +829,6 @@ impl UnifyValue for IntVarValue { } } -#[cfg(feature = "nightly")] impl UnifyKey for IntVid { type Value = IntVarValue; #[inline] // make this function eligible for inlining - it is quite hot. @@ -848,7 +844,6 @@ impl UnifyKey for IntVid { } } -#[cfg(feature = "nightly")] impl UnifyValue for FloatVarValue { type Error = NoError; @@ -866,7 +861,6 @@ impl UnifyValue for FloatVarValue { } } -#[cfg(feature = "nightly")] impl UnifyKey for FloatVid { type Value = FloatVarValue; #[inline] From 92e6f08fadaca753f8de948ad4b9094deeb99c25 Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Sun, 1 Dec 2024 19:27:32 -0800 Subject: [PATCH 141/606] Refactor `Handle` slightly - consistent handling, invalid handles are always an abort - Helper for reading handles that does the checking and machine stop - Use real handle types more places - Adds `File` and `Invalid` types of handle. File support will be added next --- .../miri/src/shims/windows/foreign_items.rs | 66 +++++++------------ src/tools/miri/src/shims/windows/handle.rs | 55 ++++++++++++++-- src/tools/miri/src/shims/windows/thread.rs | 8 +-- 3 files changed, 78 insertions(+), 51 deletions(-) diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs index fae6170a9e72..dda302092751 100644 --- a/src/tools/miri/src/shims/windows/foreign_items.rs +++ b/src/tools/miri/src/shims/windows/foreign_items.rs @@ -9,14 +9,9 @@ use rustc_target::callconv::{Conv, FnAbi}; use self::shims::windows::handle::{Handle, PseudoHandle}; use crate::shims::os_str::bytes_to_os_str; -use crate::shims::windows::handle::HandleError; use crate::shims::windows::*; use crate::*; -// The NTSTATUS STATUS_INVALID_HANDLE (0xC0000008) encoded as a HRESULT by setting the N bit. -// (https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/0642cb2f-2075-4469-918c-4441e69c548a) -const STATUS_INVALID_HANDLE: u32 = 0xD0000008; - pub fn is_dyn_sym(name: &str) -> bool { // std does dynamic detection for these symbols matches!( @@ -498,52 +493,37 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "SetThreadDescription" => { let [handle, name] = this.check_shim(abi, sys_conv, link_name, args)?; - let handle = this.read_scalar(handle)?; + let handle = this.read_handle(handle)?; let name = this.read_wide_str(this.read_pointer(name)?)?; - let thread = match Handle::try_from_scalar(handle, this)? { - Ok(Handle::Thread(thread)) => Ok(thread), - Ok(Handle::Pseudo(PseudoHandle::CurrentThread)) => Ok(this.active_thread()), - Ok(_) | Err(HandleError::InvalidHandle) => - this.invalid_handle("SetThreadDescription")?, - Err(HandleError::ThreadNotFound(e)) => Err(e), + let thread = match handle { + Handle::Thread(thread) => thread, + Handle::Pseudo(PseudoHandle::CurrentThread) => this.active_thread(), + _ => this.invalid_handle("SetThreadDescription")?, }; - let res = match thread { - Ok(thread) => { - // FIXME: use non-lossy conversion - this.set_thread_name(thread, String::from_utf16_lossy(&name).into_bytes()); - Scalar::from_u32(0) - } - Err(_) => Scalar::from_u32(STATUS_INVALID_HANDLE), - }; - - this.write_scalar(res, dest)?; + // FIXME: use non-lossy conversion + this.set_thread_name(thread, String::from_utf16_lossy(&name).into_bytes()); + this.write_scalar(Scalar::from_u32(0), dest)?; } "GetThreadDescription" => { let [handle, name_ptr] = this.check_shim(abi, sys_conv, link_name, args)?; - let handle = this.read_scalar(handle)?; + let handle = this.read_handle(handle)?; let name_ptr = this.deref_pointer_as(name_ptr, this.machine.layouts.mut_raw_ptr)?; // the pointer where we should store the ptr to the name - let thread = match Handle::try_from_scalar(handle, this)? { - Ok(Handle::Thread(thread)) => Ok(thread), - Ok(Handle::Pseudo(PseudoHandle::CurrentThread)) => Ok(this.active_thread()), - Ok(_) | Err(HandleError::InvalidHandle) => - this.invalid_handle("GetThreadDescription")?, - Err(HandleError::ThreadNotFound(e)) => Err(e), - }; - let (name, res) = match thread { - Ok(thread) => { - // Looks like the default thread name is empty. - let name = this.get_thread_name(thread).unwrap_or(b"").to_owned(); - let name = this.alloc_os_str_as_wide_str( - bytes_to_os_str(&name)?, - MiriMemoryKind::WinLocal.into(), - )?; - (Scalar::from_maybe_pointer(name, this), Scalar::from_u32(0)) - } - Err(_) => (Scalar::null_ptr(this), Scalar::from_u32(STATUS_INVALID_HANDLE)), + let thread = match handle { + Handle::Thread(thread) => thread, + Handle::Pseudo(PseudoHandle::CurrentThread) => this.active_thread(), + _ => this.invalid_handle("GetThreadDescription")?, }; + // Looks like the default thread name is empty. + let name = this.get_thread_name(thread).unwrap_or(b"").to_owned(); + let name = this.alloc_os_str_as_wide_str( + bytes_to_os_str(&name)?, + MiriMemoryKind::WinLocal.into(), + )?; + let name = Scalar::from_maybe_pointer(name, this); + let res = Scalar::from_u32(0); this.write_scalar(name, &name_ptr)?; this.write_scalar(res, dest)?; @@ -638,11 +618,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let [handle, filename, size] = this.check_shim(abi, sys_conv, link_name, args)?; this.check_no_isolation("`GetModuleFileNameW`")?; - let handle = this.read_target_usize(handle)?; + let handle = this.read_handle(handle)?; let filename = this.read_pointer(filename)?; let size = this.read_scalar(size)?.to_u32()?; - if handle != 0 { + if handle != Handle::Null { throw_unsup_format!("`GetModuleFileNameW` only supports the NULL handle"); } diff --git a/src/tools/miri/src/shims/windows/handle.rs b/src/tools/miri/src/shims/windows/handle.rs index c4eb11fbd3f9..cac67c888f86 100644 --- a/src/tools/miri/src/shims/windows/handle.rs +++ b/src/tools/miri/src/shims/windows/handle.rs @@ -1,4 +1,5 @@ use std::mem::variant_count; +use std::panic::Location; use rustc_abi::HasDataLayout; @@ -16,6 +17,8 @@ pub enum Handle { Null, Pseudo(PseudoHandle), Thread(ThreadId), + File(i32), + Invalid, } impl PseudoHandle { @@ -47,12 +50,16 @@ impl Handle { const NULL_DISCRIMINANT: u32 = 0; const PSEUDO_DISCRIMINANT: u32 = 1; const THREAD_DISCRIMINANT: u32 = 2; + const FILE_DISCRIMINANT: u32 = 3; + const INVALID_DISCRIMINANT: u32 = 7; fn discriminant(self) -> u32 { match self { Self::Null => Self::NULL_DISCRIMINANT, Self::Pseudo(_) => Self::PSEUDO_DISCRIMINANT, Self::Thread(_) => Self::THREAD_DISCRIMINANT, + Self::File(_) => Self::FILE_DISCRIMINANT, + Self::Invalid => Self::INVALID_DISCRIMINANT, } } @@ -61,11 +68,16 @@ impl Handle { Self::Null => 0, Self::Pseudo(pseudo_handle) => pseudo_handle.value(), Self::Thread(thread) => thread.to_u32(), + #[expect(clippy::cast_sign_loss)] + Self::File(fd) => fd as u32, + Self::Invalid => 0x1FFFFFFF, } } fn packed_disc_size() -> u32 { // ceil(log2(x)) is how many bits it takes to store x numbers + // We ensure that INVALID_HANDLE_VALUE (0xFFFFFFFF) decodes to Handle::Invalid + // see https://devblogs.microsoft.com/oldnewthing/20230914-00/?p=108766 let variant_count = variant_count::(); // however, std's ilog2 is floor(log2(x)) @@ -93,7 +105,7 @@ impl Handle { assert!(discriminant < 2u32.pow(disc_size)); // make sure the data fits into `data_size` bits - assert!(data < 2u32.pow(data_size)); + assert!(data <= 2u32.pow(data_size)); // packs the data into the lower `data_size` bits // and packs the discriminant right above the data @@ -105,6 +117,9 @@ impl Handle { Self::NULL_DISCRIMINANT if data == 0 => Some(Self::Null), Self::PSEUDO_DISCRIMINANT => Some(Self::Pseudo(PseudoHandle::from_value(data)?)), Self::THREAD_DISCRIMINANT => Some(Self::Thread(ThreadId::new_unchecked(data))), + #[expect(clippy::cast_possible_wrap)] + Self::FILE_DISCRIMINANT => Some(Self::File(data as i32)), + Self::INVALID_DISCRIMINANT => Some(Self::Invalid), _ => None, } } @@ -171,6 +186,26 @@ impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} #[allow(non_snake_case)] pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { + #[track_caller] + fn read_handle(&self, handle: &OpTy<'tcx>) -> InterpResult<'tcx, Handle> { + let this = self.eval_context_ref(); + let handle = this.read_scalar(handle)?; + match Handle::try_from_scalar(handle, this)? { + Ok(handle) => interp_ok(handle), + Err(HandleError::InvalidHandle) => + throw_machine_stop!(TerminationInfo::Abort(format!( + "invalid handle {} at {}", + handle.to_target_isize(this)?, + Location::caller(), + ))), + Err(HandleError::ThreadNotFound(_)) => + throw_machine_stop!(TerminationInfo::Abort(format!( + "invalid thread ID: {}", + Location::caller() + ))), + } + } + fn invalid_handle(&mut self, function_name: &str) -> InterpResult<'tcx, !> { throw_machine_stop!(TerminationInfo::Abort(format!( "invalid handle passed to `{function_name}`" @@ -180,12 +215,24 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn CloseHandle(&mut self, handle_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - let handle = this.read_scalar(handle_op)?; - let ret = match Handle::try_from_scalar(handle, this)? { - Ok(Handle::Thread(thread)) => { + let handle = this.read_handle(handle_op)?; + let ret = match handle { + Handle::Thread(thread) => { this.detach_thread(thread, /*allow_terminated_joined*/ true)?; this.eval_windows("c", "TRUE") } + Handle::File(fd) => + if let Some(file) = this.machine.fds.get(fd) { + let err = file.close(this.machine.communicate(), this)?; + if let Err(e) = err { + this.set_last_error(e)?; + this.eval_windows("c", "FALSE") + } else { + this.eval_windows("c", "TRUE") + } + } else { + this.invalid_handle("CloseHandle")? + }, _ => this.invalid_handle("CloseHandle")?, }; diff --git a/src/tools/miri/src/shims/windows/thread.rs b/src/tools/miri/src/shims/windows/thread.rs index 5db554044227..8289eea34127 100644 --- a/src/tools/miri/src/shims/windows/thread.rs +++ b/src/tools/miri/src/shims/windows/thread.rs @@ -62,14 +62,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - let handle = this.read_scalar(handle_op)?; + let handle = this.read_handle(handle_op)?; let timeout = this.read_scalar(timeout_op)?.to_u32()?; - let thread = match Handle::try_from_scalar(handle, this)? { - Ok(Handle::Thread(thread)) => thread, + let thread = match handle { + Handle::Thread(thread) => thread, // Unlike on posix, the outcome of joining the current thread is not documented. // On current Windows, it just deadlocks. - Ok(Handle::Pseudo(PseudoHandle::CurrentThread)) => this.active_thread(), + Handle::Pseudo(PseudoHandle::CurrentThread) => this.active_thread(), _ => this.invalid_handle("WaitForSingleObject")?, }; From 13bf79cd879023ae4434ed4c6b287159bef32b48 Mon Sep 17 00:00:00 2001 From: HaeNoe Date: Sun, 9 Mar 2025 22:55:07 +0100 Subject: [PATCH 142/606] fix usage of `autodiff` macro with inner functions - fix errors caused by the move of `ast::Item::ident` (see #138740) - move the logic of getting `sig`, `vis`, and `ident` from two seperate `match` statements into one (less repetition especially with the nested `match`) --- compiler/rustc_builtin_macros/src/autodiff.rs | 108 ++++++++++++------ 1 file changed, 76 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs index 7f99f75b2b9d..287f0fdc516b 100644 --- a/compiler/rustc_builtin_macros/src/autodiff.rs +++ b/compiler/rustc_builtin_macros/src/autodiff.rs @@ -199,27 +199,46 @@ mod llvm_enzyme { return vec![item]; } let dcx = ecx.sess.dcx(); - // first get the annotable item: - let (primal, sig, is_impl): (Ident, FnSig, bool) = match &item { + + // first get information about the annotable item: + let (sig, vis, primal) = match &item { Annotatable::Item(iitem) => { - let (ident, sig) = match &iitem.kind { - ItemKind::Fn(box ast::Fn { ident, sig, .. }) => (ident, sig), + let (sig, ident) = match &iitem.kind { + ItemKind::Fn(box ast::Fn { sig, ident, .. }) => (sig, ident), _ => { dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() }); return vec![item]; } }; - (*ident, sig.clone(), false) + (sig.clone(), iitem.vis.clone(), ident.clone()) } Annotatable::AssocItem(assoc_item, Impl { of_trait: false }) => { - let (ident, sig) = match &assoc_item.kind { - ast::AssocItemKind::Fn(box ast::Fn { ident, sig, .. }) => (ident, sig), + let (sig, ident) = match &assoc_item.kind { + ast::AssocItemKind::Fn(box ast::Fn { sig, ident, .. }) => (sig, ident), _ => { dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() }); return vec![item]; } }; - (*ident, sig.clone(), true) + (sig.clone(), assoc_item.vis.clone(), ident.clone()) + } + Annotatable::Stmt(stmt) => { + let (sig, vis, ident) = match &stmt.kind { + ast::StmtKind::Item(iitem) => match &iitem.kind { + ast::ItemKind::Fn(box ast::Fn { sig, ident, .. }) => { + (sig.clone(), iitem.vis.clone(), ident.clone()) + } + _ => { + dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() }); + return vec![item]; + } + }, + _ => { + dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() }); + return vec![item]; + } + }; + (sig, vis, ident) } _ => { dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() }); @@ -238,15 +257,6 @@ mod llvm_enzyme { let has_ret = has_ret(&sig.decl.output); let sig_span = ecx.with_call_site_ctxt(sig.span); - let vis = match &item { - Annotatable::Item(iitem) => iitem.vis.clone(), - Annotatable::AssocItem(assoc_item, _) => assoc_item.vis.clone(), - _ => { - dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() }); - return vec![item]; - } - }; - // create TokenStream from vec elemtents: // meta_item doesn't have a .tokens field let mut ts: Vec = vec![]; @@ -379,6 +389,22 @@ mod llvm_enzyme { } Annotatable::AssocItem(assoc_item.clone(), i) } + Annotatable::Stmt(ref mut stmt) => { + match stmt.kind { + ast::StmtKind::Item(ref mut iitem) => { + if !iitem.attrs.iter().any(|a| same_attribute(&a.kind, &attr.kind)) { + iitem.attrs.push(attr); + } + if !iitem.attrs.iter().any(|a| same_attribute(&a.kind, &inline_never.kind)) + { + iitem.attrs.push(inline_never.clone()); + } + } + _ => unreachable!("stmt kind checked previously"), + }; + + Annotatable::Stmt(stmt.clone()) + } _ => { unreachable!("annotatable kind checked previously") } @@ -389,22 +415,40 @@ mod llvm_enzyme { delim: rustc_ast::token::Delimiter::Parenthesis, tokens: ts, }); + let d_attr = outer_normal_attr(&rustc_ad_attr, new_id, span); - let d_annotatable = if is_impl { - let assoc_item: AssocItemKind = ast::AssocItemKind::Fn(asdf); - let d_fn = P(ast::AssocItem { - attrs: thin_vec![d_attr, inline_never], - id: ast::DUMMY_NODE_ID, - span, - vis, - kind: assoc_item, - tokens: None, - }); - Annotatable::AssocItem(d_fn, Impl { of_trait: false }) - } else { - let mut d_fn = ecx.item(span, thin_vec![d_attr, inline_never], ItemKind::Fn(asdf)); - d_fn.vis = vis; - Annotatable::Item(d_fn) + let d_annotatable = match &item { + Annotatable::AssocItem(_, _) => { + let assoc_item: AssocItemKind = ast::AssocItemKind::Fn(asdf); + let d_fn = P(ast::AssocItem { + attrs: thin_vec![d_attr, inline_never], + id: ast::DUMMY_NODE_ID, + span, + vis, + kind: assoc_item, + tokens: None, + }); + Annotatable::AssocItem(d_fn, Impl { of_trait: false }) + } + Annotatable::Item(_) => { + let mut d_fn = ecx.item(span, thin_vec![d_attr, inline_never], ItemKind::Fn(asdf)); + d_fn.vis = vis; + + Annotatable::Item(d_fn) + } + Annotatable::Stmt(_) => { + let mut d_fn = ecx.item(span, thin_vec![d_attr, inline_never], ItemKind::Fn(asdf)); + d_fn.vis = vis; + + Annotatable::Stmt(P(ast::Stmt { + id: ast::DUMMY_NODE_ID, + kind: ast::StmtKind::Item(d_fn), + span, + })) + } + _ => { + unreachable!("item kind checked previously") + } }; return vec![orig_annotatable, d_annotatable]; From 72091edcc46601b0fc10c8d71349449d86718d5e Mon Sep 17 00:00:00 2001 From: HaeNoe Date: Sat, 22 Mar 2025 00:26:11 +0100 Subject: [PATCH 143/606] feat: add test to validate autodiff macro expansion --- tests/pretty/autodiff_forward.pp | 15 +++++++++++++++ tests/pretty/autodiff_forward.rs | 8 ++++++++ 2 files changed, 23 insertions(+) diff --git a/tests/pretty/autodiff_forward.pp b/tests/pretty/autodiff_forward.pp index 4b2fb6166ff7..a62ced56dc41 100644 --- a/tests/pretty/autodiff_forward.pp +++ b/tests/pretty/autodiff_forward.pp @@ -29,6 +29,8 @@ pub fn f1(x: &[f64], y: f64) -> f64 { // Make sure, that we add the None for the default return. + // We want to make sure that we can use the macro for functions defined inside of functions + ::core::panicking::panic("not implemented") } #[rustc_autodiff(Forward, 1, Dual, Const, Dual)] @@ -158,4 +160,17 @@ fn f8_1(x: &f32, bx_0: &f32) -> f32 { ::core::hint::black_box((bx_0,)); ::core::hint::black_box(::default()) } +pub fn f9() { + #[rustc_autodiff] + #[inline(never)] + fn inner(x: f32) -> f32 { x * x } + #[rustc_autodiff(Forward, 1, Dual, DualOnly)] + #[inline(never)] + fn d_inner(x: f32, bx_0: f32) -> f32 { + unsafe { asm!("NOP", options(pure, nomem)); }; + ::core::hint::black_box(inner(x)); + ::core::hint::black_box((bx_0,)); + ::core::hint::black_box(::default()) + } +} fn main() {} diff --git a/tests/pretty/autodiff_forward.rs b/tests/pretty/autodiff_forward.rs index a765738c2a81..e61d1ec36172 100644 --- a/tests/pretty/autodiff_forward.rs +++ b/tests/pretty/autodiff_forward.rs @@ -54,4 +54,12 @@ fn f8(x: &f32) -> f32 { unimplemented!() } +// We want to make sure that we can use the macro for functions defined inside of functions +pub fn f9() { + #[autodiff(d_inner, Forward, Dual, DualOnly)] + fn inner(x: f32) -> f32 { + x * x + } +} + fn main() {} From 5eb535c568de730a36bbf96f0ec1163942301b15 Mon Sep 17 00:00:00 2001 From: Skgland <3877590+Skgland@users.noreply.github.com> Date: Sun, 6 Apr 2025 21:32:58 +0200 Subject: [PATCH 144/606] remove compiler support for `extern "rust-intrinsic"` blocks --- compiler/rustc_abi/src/extern_abi.rs | 4 +- compiler/rustc_ast_lowering/src/stability.rs | 4 - .../rustc_hir_analysis/src/check/check.rs | 108 ++++++++---------- .../rustc_hir_analysis/src/check/intrinsic.rs | 2 +- compiler/rustc_hir_analysis/src/check/mod.rs | 9 -- compiler/rustc_hir_analysis/src/collect.rs | 8 +- compiler/rustc_hir_typeck/src/check.rs | 4 +- compiler/rustc_hir_typeck/src/coercion.rs | 5 - compiler/rustc_metadata/src/native_libs.rs | 2 +- compiler/rustc_middle/src/ty/instance.rs | 2 +- compiler/rustc_middle/src/ty/layout.rs | 4 +- compiler/rustc_middle/src/ty/util.rs | 7 +- compiler/rustc_passes/src/check_attr.rs | 2 +- .../rustc_smir/src/rustc_internal/internal.rs | 1 - .../rustc_smir/src/rustc_smir/convert/ty.rs | 1 - compiler/rustc_smir/src/stable_mir/ty.rs | 1 - .../rustc_target/src/callconv/loongarch.rs | 10 +- compiler/rustc_target/src/callconv/mod.rs | 13 +-- compiler/rustc_target/src/callconv/riscv.rs | 10 +- compiler/rustc_target/src/callconv/x86.rs | 11 +- compiler/rustc_target/src/spec/mod.rs | 11 +- compiler/rustc_ty_utils/src/abi.rs | 4 +- src/librustdoc/clean/types.rs | 3 - 23 files changed, 79 insertions(+), 147 deletions(-) diff --git a/compiler/rustc_abi/src/extern_abi.rs b/compiler/rustc_abi/src/extern_abi.rs index 4d70afd4e0bc..55f4845d2167 100644 --- a/compiler/rustc_abi/src/extern_abi.rs +++ b/compiler/rustc_abi/src/extern_abi.rs @@ -60,7 +60,6 @@ pub enum ExternAbi { System { unwind: bool, }, - RustIntrinsic, RustCall, /// *Not* a stable ABI, just directly use the Rust types to describe the ABI for LLVM. Even /// normally ABI-compatible Rust types can become ABI-incompatible with this ABI! @@ -128,7 +127,6 @@ abi_impls! { RiscvInterruptS =><= "riscv-interrupt-s", RustCall =><= "rust-call", RustCold =><= "rust-cold", - RustIntrinsic =><= "rust-intrinsic", Stdcall { unwind: false } =><= "stdcall", Stdcall { unwind: true } =><= "stdcall-unwind", System { unwind: false } =><= "system", @@ -199,7 +197,7 @@ impl ExternAbi { /// - are subject to change between compiler versions pub fn is_rustic_abi(self) -> bool { use ExternAbi::*; - matches!(self, Rust | RustCall | RustIntrinsic | RustCold) + matches!(self, Rust | RustCall | RustCold) } pub fn supports_varargs(self) -> bool { diff --git a/compiler/rustc_ast_lowering/src/stability.rs b/compiler/rustc_ast_lowering/src/stability.rs index a2004bbb39f0..eb052ba1c6d7 100644 --- a/compiler/rustc_ast_lowering/src/stability.rs +++ b/compiler/rustc_ast_lowering/src/stability.rs @@ -79,10 +79,6 @@ pub fn extern_abi_stability(abi: ExternAbi) -> Result<(), UnstableAbi> { | ExternAbi::SysV64 { .. } | ExternAbi::System { .. } | ExternAbi::EfiApi => Ok(()), - // implementation details - ExternAbi::RustIntrinsic => { - Err(UnstableAbi { abi, feature: sym::intrinsics, explain: GateReason::ImplDetail }) - } ExternAbi::Unadjusted => { Err(UnstableAbi { abi, feature: sym::abi_unadjusted, explain: GateReason::ImplDetail }) } diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index a07986567630..e3ed20e1b318 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -741,10 +741,6 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) { for &assoc_item in assoc_items.in_definition_order() { match assoc_item.kind { - ty::AssocKind::Fn => { - let abi = tcx.fn_sig(assoc_item.def_id).skip_binder().abi(); - forbid_intrinsic_abi(tcx, assoc_item.ident(tcx).span, abi); - } ty::AssocKind::Type if assoc_item.defaultness(tcx).has_value() => { let trait_args = GenericArgs::identity_for_item(tcx, def_id); let _: Result<_, rustc_errors::ErrorGuaranteed> = check_type_bounds( @@ -788,65 +784,59 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) { }; check_abi(tcx, it.span, abi); - match abi { - ExternAbi::RustIntrinsic => { - for item in items { - intrinsic::check_intrinsic_type( - tcx, - item.id.owner_id.def_id, - item.span, - item.ident.name, - abi, - ); - } + for item in items { + let def_id = item.id.owner_id.def_id; + + if tcx.has_attr(def_id, sym::rustc_intrinsic) { + intrinsic::check_intrinsic_type( + tcx, + item.id.owner_id.def_id, + item.span, + item.ident.name, + abi, + ); } - _ => { - for item in items { - let def_id = item.id.owner_id.def_id; - let generics = tcx.generics_of(def_id); - let own_counts = generics.own_counts(); - if generics.own_params.len() - own_counts.lifetimes != 0 { - let (kinds, kinds_pl, egs) = match (own_counts.types, own_counts.consts) - { - (_, 0) => ("type", "types", Some("u32")), - // We don't specify an example value, because we can't generate - // a valid value for any type. - (0, _) => ("const", "consts", None), - _ => ("type or const", "types or consts", None), - }; - struct_span_code_err!( - tcx.dcx(), - item.span, - E0044, - "foreign items may not have {kinds} parameters", - ) - .with_span_label(item.span, format!("can't have {kinds} parameters")) - .with_help( - // FIXME: once we start storing spans for type arguments, turn this - // into a suggestion. - format!( - "replace the {} parameters with concrete {}{}", - kinds, - kinds_pl, - egs.map(|egs| format!(" like `{egs}`")).unwrap_or_default(), - ), - ) - .emit(); - } + let generics = tcx.generics_of(def_id); + let own_counts = generics.own_counts(); + if generics.own_params.len() - own_counts.lifetimes != 0 { + let (kinds, kinds_pl, egs) = match (own_counts.types, own_counts.consts) { + (_, 0) => ("type", "types", Some("u32")), + // We don't specify an example value, because we can't generate + // a valid value for any type. + (0, _) => ("const", "consts", None), + _ => ("type or const", "types or consts", None), + }; + struct_span_code_err!( + tcx.dcx(), + item.span, + E0044, + "foreign items may not have {kinds} parameters", + ) + .with_span_label(item.span, format!("can't have {kinds} parameters")) + .with_help( + // FIXME: once we start storing spans for type arguments, turn this + // into a suggestion. + format!( + "replace the {} parameters with concrete {}{}", + kinds, + kinds_pl, + egs.map(|egs| format!(" like `{egs}`")).unwrap_or_default(), + ), + ) + .emit(); + } - let item = tcx.hir_foreign_item(item.id); - match &item.kind { - hir::ForeignItemKind::Fn(sig, _, _) => { - require_c_abi_if_c_variadic(tcx, sig.decl, abi, item.span); - } - hir::ForeignItemKind::Static(..) => { - check_static_inhabited(tcx, def_id); - check_static_linkage(tcx, def_id); - } - _ => {} - } + let item = tcx.hir_foreign_item(item.id); + match &item.kind { + hir::ForeignItemKind::Fn(sig, _, _) => { + require_c_abi_if_c_variadic(tcx, sig.decl, abi, item.span); } + hir::ForeignItemKind::Static(..) => { + check_static_inhabited(tcx, def_id); + check_static_linkage(tcx, def_id); + } + _ => {} } } } diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 42d785c8dd0f..0bf9e127989f 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -1,4 +1,4 @@ -//! Type-checking for the rust-intrinsic intrinsics that the compiler exposes. +//! Type-checking for the `#[rustc_intrinsic]` intrinsics that the compiler exposes. use rustc_abi::ExternAbi; use rustc_errors::codes::*; diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 7c5d7b33a34d..30921b6f055d 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -137,15 +137,6 @@ fn get_owner_return_paths( }) } -/// Forbid defining intrinsics in Rust code, -/// as they must always be defined by the compiler. -// FIXME: Move this to a more appropriate place. -pub fn forbid_intrinsic_abi(tcx: TyCtxt<'_>, sp: Span, abi: ExternAbi) { - if let ExternAbi::RustIntrinsic = abi { - tcx.dcx().span_err(sp, "intrinsic must be in `extern \"rust-intrinsic\" { ... }` block"); - } -} - pub(super) fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDefId) { // Only restricted on wasm target for now if !tcx.sess.target.is_like_wasm { diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 625f51dd29ea..e9cd22435d95 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -42,7 +42,6 @@ use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::ObligationCtxt; use tracing::{debug, instrument}; -use crate::check::intrinsic::intrinsic_operation_unsafety; use crate::errors; use crate::hir_ty_lowering::errors::assoc_kind_str; use crate::hir_ty_lowering::{FeedConstTy, HirTyLowerer, RegionInferReason}; @@ -1704,18 +1703,13 @@ fn compute_sig_of_foreign_fn_decl<'tcx>( abi: ExternAbi, safety: hir::Safety, ) -> ty::PolyFnSig<'tcx> { - let safety = if abi == ExternAbi::RustIntrinsic { - intrinsic_operation_unsafety(tcx, def_id) - } else { - safety - }; let hir_id = tcx.local_def_id_to_hir_id(def_id); let fty = ItemCtxt::new(tcx, def_id).lowerer().lower_fn_ty(hir_id, safety, abi, decl, None, None); // Feature gate SIMD types in FFI, since I am not sure that the // ABIs are handled at all correctly. -huonw - if abi != ExternAbi::RustIntrinsic && !tcx.features().simd_ffi() { + if !tcx.features().simd_ffi() { let check = |hir_ty: &hir::Ty<'_>, ty: Ty<'_>| { if ty.is_simd() { let snip = tcx diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index dabae7b1d094..2189fdf0f343 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -5,7 +5,7 @@ use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; -use rustc_hir_analysis::check::{check_function_signature, forbid_intrinsic_abi}; +use rustc_hir_analysis::check::check_function_signature; use rustc_infer::infer::RegionVariableOrigin; use rustc_infer::traits::WellFormedLoc; use rustc_middle::ty::{self, Binder, Ty, TyCtxt}; @@ -50,8 +50,6 @@ pub(super) fn check_fn<'a, 'tcx>( let span = body.value.span; - forbid_intrinsic_abi(tcx, span, fn_sig.abi); - GatherLocalsVisitor::new(fcx).visit_body(body); // C-variadic fns also have a `VaList` input that's not listed in `fn_sig` diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index f42ca3af2b35..f1571cf4c831 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -37,7 +37,6 @@ use std::ops::Deref; -use rustc_abi::ExternAbi; use rustc_attr_parsing::InlineAttr; use rustc_errors::codes::*; use rustc_errors::{Applicability, Diag, struct_span_code_err}; @@ -1240,10 +1239,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } }; if let (Some(a_sig), Some(b_sig)) = (a_sig, b_sig) { - // Intrinsics are not coercible to function pointers. - if a_sig.abi() == ExternAbi::RustIntrinsic || b_sig.abi() == ExternAbi::RustIntrinsic { - return Err(TypeError::IntrinsicCast); - } // The signature must match. let (a_sig, b_sig) = self.normalize(new.span, (a_sig, b_sig)); let sig = self diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 130a425e9c74..cfb0de8475c8 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -207,7 +207,7 @@ impl<'tcx> Collector<'tcx> { let sess = self.tcx.sess; - if matches!(abi, ExternAbi::Rust | ExternAbi::RustIntrinsic) { + if matches!(abi, ExternAbi::Rust) { return; } diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 55ebd15248c6..07f2a602f2bf 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -71,7 +71,7 @@ pub enum InstanceKind<'tcx> { /// - coroutines Item(DefId), - /// An intrinsic `fn` item (with `"rust-intrinsic"` ABI). + /// An intrinsic `fn` item (with`#[rustc_instrinsic]`). /// /// Alongside `Virtual`, this is the only `InstanceKind` that does not have its own callable MIR. /// Instead, codegen and const eval "magically" evaluate calls to intrinsics purely in the diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index ebb6a8c08a54..7ebfebea44e5 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -1265,9 +1265,7 @@ pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option, abi: ExternAbi) | CCmseNonSecureCall | CCmseNonSecureEntry | Unadjusted => false, - Rust | RustCall | RustCold | RustIntrinsic => { - tcx.sess.panic_strategy() == PanicStrategy::Unwind - } + Rust | RustCall | RustCold => tcx.sess.panic_strategy() == PanicStrategy::Unwind, } } diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index e4863896fc8b..857b462b9eb1 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -2,7 +2,7 @@ use std::{fmt, iter}; -use rustc_abi::{ExternAbi, Float, Integer, IntegerType, Size}; +use rustc_abi::{Float, Integer, IntegerType, Size}; use rustc_apfloat::Float as _; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; @@ -1719,10 +1719,7 @@ pub fn is_doc_notable_trait(tcx: TyCtxt<'_>, def_id: DefId) -> bool { /// the compiler to make some assumptions about its shape; if the user doesn't use a feature gate, they may /// cause an ICE that we otherwise may want to prevent. pub fn intrinsic_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option { - if tcx.features().intrinsics() - && (matches!(tcx.fn_sig(def_id).skip_binder().abi(), ExternAbi::RustIntrinsic) - || tcx.has_attr(def_id, sym::rustc_intrinsic)) - { + if tcx.features().intrinsics() && tcx.has_attr(def_id, sym::rustc_intrinsic) { let must_be_overridden = match tcx.hir_node_by_def_id(def_id) { hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn { has_body, .. }, .. }) => { !has_body diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 669349f3380a..9161b23428a0 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1598,7 +1598,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { if target == Target::ForeignMod && let hir::Node::Item(item) = self.tcx.hir_node(hir_id) && let Item { kind: ItemKind::ForeignMod { abi, .. }, .. } = item - && !matches!(abi, ExternAbi::Rust | ExternAbi::RustIntrinsic) + && !matches!(abi, ExternAbi::Rust) { return; } diff --git a/compiler/rustc_smir/src/rustc_internal/internal.rs b/compiler/rustc_smir/src/rustc_internal/internal.rs index 36b68cc13982..6e13b87c41d7 100644 --- a/compiler/rustc_smir/src/rustc_internal/internal.rs +++ b/compiler/rustc_smir/src/rustc_internal/internal.rs @@ -491,7 +491,6 @@ impl RustcInternal for Abi { Abi::CCmseNonSecureCall => rustc_abi::ExternAbi::CCmseNonSecureCall, Abi::CCmseNonSecureEntry => rustc_abi::ExternAbi::CCmseNonSecureEntry, Abi::System { unwind } => rustc_abi::ExternAbi::System { unwind }, - Abi::RustIntrinsic => rustc_abi::ExternAbi::RustIntrinsic, Abi::RustCall => rustc_abi::ExternAbi::RustCall, Abi::Unadjusted => rustc_abi::ExternAbi::Unadjusted, Abi::RustCold => rustc_abi::ExternAbi::RustCold, diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index 1ba25aa0e971..28fc68d5e491 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -871,7 +871,6 @@ impl<'tcx> Stable<'tcx> for rustc_abi::ExternAbi { ExternAbi::CCmseNonSecureCall => Abi::CCmseNonSecureCall, ExternAbi::CCmseNonSecureEntry => Abi::CCmseNonSecureEntry, ExternAbi::System { unwind } => Abi::System { unwind }, - ExternAbi::RustIntrinsic => Abi::RustIntrinsic, ExternAbi::RustCall => Abi::RustCall, ExternAbi::Unadjusted => Abi::Unadjusted, ExternAbi::RustCold => Abi::RustCold, diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs index 1efa2fe13c56..3fcbbb0e138b 100644 --- a/compiler/rustc_smir/src/stable_mir/ty.rs +++ b/compiler/rustc_smir/src/stable_mir/ty.rs @@ -1093,7 +1093,6 @@ pub enum Abi { CCmseNonSecureCall, CCmseNonSecureEntry, System { unwind: bool }, - RustIntrinsic, RustCall, Unadjusted, RustCold, diff --git a/compiler/rustc_target/src/callconv/loongarch.rs b/compiler/rustc_target/src/callconv/loongarch.rs index 209d7483e612..c779720f97b9 100644 --- a/compiler/rustc_target/src/callconv/loongarch.rs +++ b/compiler/rustc_target/src/callconv/loongarch.rs @@ -1,6 +1,6 @@ use rustc_abi::{ - BackendRepr, ExternAbi, FieldsShape, HasDataLayout, Primitive, Reg, RegKind, Size, - TyAbiInterface, TyAndLayout, Variants, + BackendRepr, FieldsShape, HasDataLayout, Primitive, Reg, RegKind, Size, TyAbiInterface, + TyAndLayout, Variants, }; use crate::callconv::{ArgAbi, ArgExtension, CastTarget, FnAbi, PassMode, Uniform}; @@ -364,15 +364,11 @@ where } } -pub(crate) fn compute_rust_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, abi: ExternAbi) +pub(crate) fn compute_rust_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout + HasTargetSpec, { - if abi == ExternAbi::RustIntrinsic { - return; - } - let grlen = cx.data_layout().pointer_size.bits(); for arg in fn_abi.args.iter_mut() { diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs index 55e39d093e23..7ecc46cc69db 100644 --- a/compiler/rustc_target/src/callconv/mod.rs +++ b/compiler/rustc_target/src/callconv/mod.rs @@ -717,16 +717,16 @@ impl<'a, Ty> FnAbi<'a, Ty> { } } - pub fn adjust_for_rust_abi(&mut self, cx: &C, abi: ExternAbi) + pub fn adjust_for_rust_abi(&mut self, cx: &C) where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout + HasTargetSpec, { let spec = cx.target_spec(); match &*spec.arch { - "x86" => x86::compute_rust_abi_info(cx, self, abi), - "riscv32" | "riscv64" => riscv::compute_rust_abi_info(cx, self, abi), - "loongarch64" => loongarch::compute_rust_abi_info(cx, self, abi), + "x86" => x86::compute_rust_abi_info(cx, self), + "riscv32" | "riscv64" => riscv::compute_rust_abi_info(cx, self), + "loongarch64" => loongarch::compute_rust_abi_info(cx, self), "aarch64" => aarch64::compute_rust_abi_info(cx, self), _ => {} }; @@ -850,10 +850,7 @@ impl<'a, Ty> FnAbi<'a, Ty> { // // Note that the intrinsic ABI is exempt here as those are not // real functions anyway, and the backend expects very specific types. - if abi != ExternAbi::RustIntrinsic - && spec.simd_types_indirect - && !can_pass_simd_directly(arg) - { + if spec.simd_types_indirect && !can_pass_simd_directly(arg) { arg.make_indirect(); } } diff --git a/compiler/rustc_target/src/callconv/riscv.rs b/compiler/rustc_target/src/callconv/riscv.rs index 7368e225efa7..cd1d3cd1eee0 100644 --- a/compiler/rustc_target/src/callconv/riscv.rs +++ b/compiler/rustc_target/src/callconv/riscv.rs @@ -5,8 +5,8 @@ // https://github.com/llvm/llvm-project/blob/8e780252a7284be45cf1ba224cabd884847e8e92/clang/lib/CodeGen/TargetInfo.cpp#L9311-L9773 use rustc_abi::{ - BackendRepr, ExternAbi, FieldsShape, HasDataLayout, Primitive, Reg, RegKind, Size, - TyAbiInterface, TyAndLayout, Variants, + BackendRepr, FieldsShape, HasDataLayout, Primitive, Reg, RegKind, Size, TyAbiInterface, + TyAndLayout, Variants, }; use crate::callconv::{ArgAbi, ArgExtension, CastTarget, FnAbi, PassMode, Uniform}; @@ -370,15 +370,11 @@ where } } -pub(crate) fn compute_rust_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, abi: ExternAbi) +pub(crate) fn compute_rust_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout + HasTargetSpec, { - if abi == ExternAbi::RustIntrinsic { - return; - } - let xlen = cx.data_layout().pointer_size.bits(); for arg in fn_abi.args.iter_mut() { diff --git a/compiler/rustc_target/src/callconv/x86.rs b/compiler/rustc_target/src/callconv/x86.rs index ba3c14062112..8328f818f9b8 100644 --- a/compiler/rustc_target/src/callconv/x86.rs +++ b/compiler/rustc_target/src/callconv/x86.rs @@ -1,6 +1,6 @@ use rustc_abi::{ - AddressSpace, Align, BackendRepr, ExternAbi, HasDataLayout, Primitive, Reg, RegKind, - TyAbiInterface, TyAndLayout, + AddressSpace, Align, BackendRepr, HasDataLayout, Primitive, Reg, RegKind, TyAbiInterface, + TyAndLayout, }; use crate::callconv::{ArgAttribute, FnAbi, PassMode}; @@ -193,7 +193,7 @@ pub(crate) fn fill_inregs<'a, Ty, C>( } } -pub(crate) fn compute_rust_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, abi: ExternAbi) +pub(crate) fn compute_rust_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout + HasTargetSpec, @@ -201,10 +201,7 @@ where // Avoid returning floats in x87 registers on x86 as loading and storing from x87 // registers will quiet signalling NaNs. Also avoid using SSE registers since they // are not always available (depending on target features). - if !fn_abi.ret.is_ignore() - // Intrinsics themselves are not "real" functions, so theres no need to change their ABIs. - && abi != ExternAbi::RustIntrinsic - { + if !fn_abi.ret.is_ignore() { let has_float = match fn_abi.ret.layout.backend_repr { BackendRepr::Scalar(s) => matches!(s.primitive(), Primitive::Float(_)), BackendRepr::ScalarPair(s1, s2) => { diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 79f73ef28b36..64171fcc7ab3 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -2962,14 +2962,9 @@ impl Target { pub fn is_abi_supported(&self, abi: ExternAbi) -> bool { use ExternAbi::*; match abi { - Rust - | C { .. } - | System { .. } - | RustIntrinsic - | RustCall - | Unadjusted - | Cdecl { .. } - | RustCold => true, + Rust | C { .. } | System { .. } | RustCall | Unadjusted | Cdecl { .. } | RustCold => { + true + } EfiApi => { ["arm", "aarch64", "riscv32", "riscv64", "x86", "x86_64"].contains(&&self.arch[..]) } diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 48d5a4a0fcb0..3d4ab33240af 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -244,7 +244,7 @@ fn fn_sig_for_fn_abi<'tcx>( fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: ExternAbi, c_variadic: bool) -> Conv { use rustc_abi::ExternAbi::*; match tcx.sess.target.adjust_abi(abi, c_variadic) { - RustIntrinsic | Rust | RustCall => Conv::Rust, + Rust | RustCall => Conv::Rust, // This is intentionally not using `Conv::Cold`, as that has to preserve // even SIMD registers, which is generally not a good trade-off. @@ -660,7 +660,7 @@ fn fn_abi_adjust_for_abi<'tcx>( let tcx = cx.tcx(); if abi.is_rustic_abi() { - fn_abi.adjust_for_rust_abi(cx, abi); + fn_abi.adjust_for_rust_abi(cx); // Look up the deduced parameter attributes for this function, if we have its def ID and // we're optimizing in non-incremental mode. We'll tag its parameters with those attributes diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index d3ddb77c0b33..06e75fe1764e 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -11,7 +11,6 @@ use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId}; use rustc_hir::lang_items::LangItem; use rustc_hir::{BodyId, Mutability}; -use rustc_hir_analysis::check::intrinsic::intrinsic_operation_unsafety; use rustc_index::IndexVec; use rustc_metadata::rendered_const; use rustc_middle::span_bug; @@ -687,8 +686,6 @@ impl Item { hir::FnHeader { safety: if tcx.codegen_fn_attrs(def_id).safe_target_features { hir::HeaderSafety::SafeTargetFeatures - } else if abi == ExternAbi::RustIntrinsic { - intrinsic_operation_unsafety(tcx, def_id.expect_local()).into() } else { safety.into() }, From 63e825e52a1961f1270bed5075c52f2c9921ef08 Mon Sep 17 00:00:00 2001 From: HaeNoe Date: Tue, 1 Apr 2025 07:25:04 +0200 Subject: [PATCH 145/606] feat: apply autodiff macro twice to inner function Verify that the expanded `inline` and `rustc_autodiff` macros are not duplicated. --- tests/pretty/autodiff_forward.pp | 10 +++++++++- tests/pretty/autodiff_forward.rs | 3 ++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/tests/pretty/autodiff_forward.pp b/tests/pretty/autodiff_forward.pp index a62ced56dc41..713b8f541ae0 100644 --- a/tests/pretty/autodiff_forward.pp +++ b/tests/pretty/autodiff_forward.pp @@ -164,9 +164,17 @@ pub fn f9() { #[rustc_autodiff] #[inline(never)] fn inner(x: f32) -> f32 { x * x } + #[rustc_autodiff(Forward, 1, Dual, Dual)] + #[inline(never)] + fn d_inner_2(x: f32, bx_0: f32) -> (f32, f32) { + unsafe { asm!("NOP", options(pure, nomem)); }; + ::core::hint::black_box(inner(x)); + ::core::hint::black_box((bx_0,)); + ::core::hint::black_box(<(f32, f32)>::default()) + } #[rustc_autodiff(Forward, 1, Dual, DualOnly)] #[inline(never)] - fn d_inner(x: f32, bx_0: f32) -> f32 { + fn d_inner_1(x: f32, bx_0: f32) -> f32 { unsafe { asm!("NOP", options(pure, nomem)); }; ::core::hint::black_box(inner(x)); ::core::hint::black_box((bx_0,)); diff --git a/tests/pretty/autodiff_forward.rs b/tests/pretty/autodiff_forward.rs index e61d1ec36172..5a0660a08e52 100644 --- a/tests/pretty/autodiff_forward.rs +++ b/tests/pretty/autodiff_forward.rs @@ -56,7 +56,8 @@ fn f8(x: &f32) -> f32 { // We want to make sure that we can use the macro for functions defined inside of functions pub fn f9() { - #[autodiff(d_inner, Forward, Dual, DualOnly)] + #[autodiff(d_inner_1, Forward, Dual, DualOnly)] + #[autodiff(d_inner_2, Forward, Dual, Dual)] fn inner(x: f32) -> f32 { x * x } From 51b51b51d7931da85280382a81c4dd80c73ca754 Mon Sep 17 00:00:00 2001 From: Skgland <3877590+Skgland@users.noreply.github.com> Date: Sun, 6 Apr 2025 21:34:00 +0200 Subject: [PATCH 146/606] remove rust-analyser support for `extern "rust-intrinsic"` blocks --- .../rust-analyzer/crates/hir-ty/src/lib.rs | 3 --- .../crates/hir-ty/src/mir/eval/shim.rs | 14 +--------- .../rust-analyzer/crates/hir-ty/src/utils.rs | 26 +++++-------------- .../src/completions/extern_abi.rs | 1 - .../crates/intern/src/symbol/symbols.rs | 1 - 5 files changed, 7 insertions(+), 38 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs index cc02b71f05c1..e4c50f2ebdb4 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs @@ -400,7 +400,6 @@ pub enum FnAbi { Rust, RustCall, RustCold, - RustIntrinsic, Stdcall, StdcallUnwind, System, @@ -457,7 +456,6 @@ impl FnAbi { s if *s == sym::riscv_dash_interrupt_dash_s => FnAbi::RiscvInterruptS, s if *s == sym::rust_dash_call => FnAbi::RustCall, s if *s == sym::rust_dash_cold => FnAbi::RustCold, - s if *s == sym::rust_dash_intrinsic => FnAbi::RustIntrinsic, s if *s == sym::Rust => FnAbi::Rust, s if *s == sym::stdcall_dash_unwind => FnAbi::StdcallUnwind, s if *s == sym::stdcall => FnAbi::Stdcall, @@ -500,7 +498,6 @@ impl FnAbi { FnAbi::Rust => "Rust", FnAbi::RustCall => "rust-call", FnAbi::RustCold => "rust-cold", - FnAbi::RustIntrinsic => "rust-intrinsic", FnAbi::Stdcall => "stdcall", FnAbi::StdcallUnwind => "stdcall-unwind", FnAbi::System => "system", diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs index f61ecabb7e41..06ac5b1ffad9 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs @@ -59,19 +59,7 @@ impl Evaluator<'_> { let function_data = self.db.function_data(def); let attrs = self.db.attrs(def.into()); - let is_intrinsic = attrs.by_key(&sym::rustc_intrinsic).exists() - // Keep this around for a bit until extern "rustc-intrinsic" abis are no longer used - || (match &function_data.abi { - Some(abi) => *abi == sym::rust_dash_intrinsic, - None => match def.lookup(self.db.upcast()).container { - hir_def::ItemContainerId::ExternBlockId(block) => { - let id = block.lookup(self.db.upcast()).id; - id.item_tree(self.db.upcast())[id.value].abi.as_ref() - == Some(&sym::rust_dash_intrinsic) - } - _ => false, - }, - }); + let is_intrinsic = attrs.by_key(&sym::rustc_intrinsic).exists(); if is_intrinsic { return self.exec_intrinsic( diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs index 89d89fe2230a..0cfd36d9166b 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs @@ -18,7 +18,6 @@ use hir_def::{ TypeOrConstParamId, }; use hir_expand::name::Name; -use intern::sym; use rustc_abi::TargetDataLayout; use rustc_hash::FxHashSet; use smallvec::{smallvec, SmallVec}; @@ -303,26 +302,13 @@ pub fn is_fn_unsafe_to_call( let loc = func.lookup(db.upcast()); match loc.container { - hir_def::ItemContainerId::ExternBlockId(block) => { - let id = block.lookup(db.upcast()).id; - let is_intrinsic_block = - id.item_tree(db.upcast())[id.value].abi.as_ref() == Some(&sym::rust_dash_intrinsic); - if is_intrinsic_block { - // legacy intrinsics - // extern "rust-intrinsic" intrinsics are unsafe unless they have the rustc_safe_intrinsic attribute - if db.attrs(func.into()).by_key(&sym::rustc_safe_intrinsic).exists() { - Unsafety::Safe - } else { - Unsafety::Unsafe - } + hir_def::ItemContainerId::ExternBlockId(_block) => { + // Function in an `extern` block are always unsafe to call, except when + // it is marked as `safe`. + if data.is_safe() { + Unsafety::Safe } else { - // Function in an `extern` block are always unsafe to call, except when - // it is marked as `safe`. - if data.is_safe() { - Unsafety::Safe - } else { - Unsafety::Unsafe - } + Unsafety::Unsafe } } _ => Unsafety::Safe, diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs index 7c2cc2a6c1d8..a3554114f4c3 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs @@ -36,7 +36,6 @@ const SUPPORTED_CALLING_CONVENTIONS: &[&str] = &[ "wasm", "system", "system-unwind", - "rust-intrinsic", "rust-call", "unadjusted", ]; diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs index 6b77c72cee89..d4f334289f03 100644 --- a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs +++ b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs @@ -125,7 +125,6 @@ define_symbols! { riscv_dash_interrupt_dash_s = "riscv-interrupt-s", rust_dash_call = "rust-call", rust_dash_cold = "rust-cold", - rust_dash_intrinsic = "rust-intrinsic", stdcall_dash_unwind = "stdcall-unwind", system_dash_unwind = "system-unwind", sysv64_dash_unwind = "sysv64-unwind", From 6dfb29624cf2fd1b6d2f31e6321bcef5e4a4a84e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bennet=20Ble=C3=9Fmann?= Date: Sun, 6 Apr 2025 15:10:23 +0200 Subject: [PATCH 147/606] update docs - src\doc\nomicon\src\ffi.md should also have its ABI list updated --- .../src/intrinsics/mod.rs | 3 +- compiler/rustc_feature/src/unstable.rs | 2 +- library/core/src/intrinsics/mod.rs | 1 + .../src/language-features/intrinsics.md | 30 ++----------------- .../crates/ide/src/hover/tests.rs | 28 ++--------------- 5 files changed, 7 insertions(+), 57 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index 75f3a3c19724..d3f47ad72633 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -1,5 +1,4 @@ -//! Codegen of intrinsics. This includes `extern "rust-intrinsic"`, -//! functions marked with the `#[rustc_intrinsic]` attribute +//! Codegen of intrinsics. This includes functions marked with the `#[rustc_intrinsic]` attribute //! and LLVM intrinsics that have symbol names starting with `llvm.`. macro_rules! intrinsic_args { diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 710e129b609f..77d8965602cc 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -211,7 +211,7 @@ declare_features! ( (internal, custom_mir, "1.65.0", None), /// Outputs useful `assert!` messages (unstable, generic_assert, "1.63.0", None), - /// Allows using the `rust-intrinsic`'s "ABI". + /// Allows using the #[rustc_intrinsic] attribute. (internal, intrinsics, "1.0.0", None), /// Allows using `#[lang = ".."]` attribute for linking items to special compiler logic. (internal, lang_items, "1.0.0", None), diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index afd6192d7c47..7fa57df9928c 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -8,6 +8,7 @@ //! Note: any changes to the constness of intrinsics should be discussed with the language team. //! This includes changes in the stability of the constness. //! +//! //FIXME(#132735) "old" style intrinsics support has been removed //! In order to make an intrinsic usable at compile-time, it needs to be declared in the "new" //! style, i.e. as a `#[rustc_intrinsic]` function, not inside an `extern` block. Then copy the //! implementation from to diff --git a/src/doc/unstable-book/src/language-features/intrinsics.md b/src/doc/unstable-book/src/language-features/intrinsics.md index 975b400447eb..a0e38f340f58 100644 --- a/src/doc/unstable-book/src/language-features/intrinsics.md +++ b/src/doc/unstable-book/src/language-features/intrinsics.md @@ -52,9 +52,8 @@ with any regular function. Various intrinsics have native MIR operations that they correspond to. Instead of requiring backends to implement both the intrinsic and the MIR operation, the `lower_intrinsics` pass will convert the calls to the MIR operation. Backends do not need to know about these intrinsics -at all. These intrinsics only make sense without a body, and can either be declared as a "rust-intrinsic" -or as a `#[rustc_intrinsic]`. The body is never used, as calls to the intrinsic do not exist -anymore after MIR analyses. +at all. These intrinsics only make sense without a body, and can be declared as a `#[rustc_intrinsic]`. +The body is never used, as calls to the intrinsic do not exist anymore after MIR analyses. ## Intrinsics without fallback logic @@ -70,28 +69,3 @@ These are written without a body: #[rustc_intrinsic] pub fn abort() -> !; ``` - -### Legacy extern ABI based intrinsics - -*This style is deprecated, always prefer the above form.* - -These are imported as if they were FFI functions, with the special -`rust-intrinsic` ABI. For example, if one was in a freestanding -context, but wished to be able to `transmute` between types, and -perform efficient pointer arithmetic, one would import those functions -via a declaration like - -```rust -#![feature(intrinsics)] -#![allow(internal_features)] -# fn main() {} - -extern "rust-intrinsic" { - fn transmute(x: T) -> U; - - fn arith_offset(dst: *const T, offset: isize) -> *const T; -} -``` - -As with any other FFI functions, these are by default always `unsafe` to call. -You can add `#[rustc_safe_intrinsic]` to the intrinsic to make it safe to call. diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs index 6b470d921f7a..5dfd826d7f96 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs @@ -6945,9 +6945,8 @@ fn hover_feature() { Various intrinsics have native MIR operations that they correspond to. Instead of requiring backends to implement both the intrinsic and the MIR operation, the `lower_intrinsics` pass will convert the calls to the MIR operation. Backends do not need to know about these intrinsics - at all. These intrinsics only make sense without a body, and can either be declared as a "rust-intrinsic" - or as a `#[rustc_intrinsic]`. The body is never used, as calls to the intrinsic do not exist - anymore after MIR analyses. + at all. These intrinsics only make sense without a body, and can be as a `#[rustc_intrinsic]`. + The body is never used, as calls to the intrinsic do not exist anymore after MIR analyses. ## Intrinsics without fallback logic @@ -6960,29 +6959,6 @@ fn hover_feature() { `#[rustc_intrinsic_must_be_overridden]` to the function to ensure that backends don't invoke the body. - ### Legacy extern ABI based intrinsics - - These are imported as if they were FFI functions, with the special - `rust-intrinsic` ABI. For example, if one was in a freestanding - context, but wished to be able to `transmute` between types, and - perform efficient pointer arithmetic, one would import those functions - via a declaration like - - ```rust - #![feature(intrinsics)] - #![allow(internal_features)] - # fn main() {} - - extern "rust-intrinsic" { - fn transmute(x: T) -> U; - - fn arith_offset(dst: *const T, offset: isize) -> *const T; - } - ``` - - As with any other FFI functions, these are by default always `unsafe` to call. - You can add `#[rustc_safe_intrinsic]` to the intrinsic to make it safe to call. - "#]], ) } From 7dd57f085cab4cc671b01d6dd27977c76d04de28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bennet=20Ble=C3=9Fmann?= Date: Sun, 6 Apr 2025 15:12:24 +0200 Subject: [PATCH 148/606] update/bless tests --- .../src/error_codes/E0622.md | 10 +- tests/assembly/simd-bitmask.rs | 5 +- tests/assembly/simd-intrinsic-gather.rs | 5 +- tests/assembly/simd-intrinsic-mask-load.rs | 5 +- tests/assembly/simd-intrinsic-mask-reduce.rs | 8 +- tests/assembly/simd-intrinsic-mask-store.rs | 5 +- tests/assembly/simd-intrinsic-scatter.rs | 5 +- tests/assembly/simd-intrinsic-select.rs | 5 +- tests/codegen/avr/avr-func-addrspace.rs | 5 +- .../codegen/emscripten-catch-unwind-js-eh.rs | 13 +- .../emscripten-catch-unwind-wasm-eh.rs | 14 +- tests/codegen/intrinsic-no-unnamed-attr.rs | 6 +- tests/codegen/intrinsics/nontemporal.rs | 5 +- tests/mir-opt/lower_intrinsics.rs | 9 +- .../atomic-lock-free/atomic_lock_free.rs | 5 +- .../avr-rjmp-offset/avr-rjmp-offsets.rs | 7 +- ...abi-typo-unstable.feature_disabled.stderr} | 8 +- .../abi-typo-unstable.feature_enabled.stderr | 16 + tests/ui/abi/abi-typo-unstable.rs | 11 +- ...sociated-types-in-ambiguous-context.stderr | 36 +- ...ice-mutability-error-slicing-121807.stderr | 12 +- .../trait-impl-argument-difference-ice.stderr | 12 +- tests/ui/delegation/ice-issue-124347.rs | 1 - tests/ui/delegation/ice-issue-124347.stderr | 12 +- ...-fn-inputs-and-outputs-issue-125139.stderr | 320 +++++++++--------- tests/ui/error-codes/E0092.rs | 9 +- tests/ui/error-codes/E0092.stderr | 6 +- tests/ui/error-codes/E0093.rs | 11 +- tests/ui/error-codes/E0093.stderr | 6 +- tests/ui/error-codes/E0622.rs | 14 +- tests/ui/error-codes/E0622.stderr | 6 +- tests/ui/extern/extern-with-type-bounds.rs | 21 -- .../ui/extern/extern-with-type-bounds.stderr | 9 - tests/ui/feature-gates/feature-gate-abi.rs | 21 -- .../ui/feature-gates/feature-gate-abi.stderr | 172 +--------- .../feature-gates/feature-gate-intrinsics.rs | 9 +- .../feature-gate-intrinsics.stderr | 36 +- .../feature-gated-feature-in-macro-arg.rs | 6 +- .../feature-gated-feature-in-macro-arg.stderr | 10 +- tests/ui/intrinsics/always-extern.rs | 17 - tests/ui/intrinsics/always-extern.stderr | 34 -- .../ui/intrinsics/auxiliary/cci_intrinsic.rs | 9 +- .../incorrect-read_via_copy-defn.rs | 7 +- .../incorrect-read_via_copy-defn.stderr | 21 +- tests/ui/intrinsics/incorrect-transmute.rs | 7 +- .../ui/intrinsics/incorrect-transmute.stderr | 21 +- tests/ui/intrinsics/intrinsic-atomics.rs | 64 ++-- .../intrinsics/invalid-ABI-rust-intrinsic.rs | 19 ++ .../invalid-ABI-rust-intrinsic.stderr | 35 ++ tests/ui/intrinsics/issue-28575.rs | 1 + tests/ui/intrinsics/issue-28575.stderr | 15 +- .../ui/intrinsics/safe-intrinsic-mismatch.rs | 11 +- .../intrinsics/safe-intrinsic-mismatch.stderr | 21 +- tests/ui/lint/internal_features.rs | 5 +- tests/ui/print-calling-conventions.stdout | 1 - ...it-should-use-self-2021-without-dyn.stderr | 56 +-- tests/ui/suggestions/issue-116434-2015.stderr | 26 +- .../typeck_type_placeholder_item.stderr | 24 +- ...ir-wf-check-anon-const-issue-122199.stderr | 12 +- 59 files changed, 545 insertions(+), 737 deletions(-) rename tests/ui/abi/{abi-typo-unstable.stderr => abi-typo-unstable.feature_disabled.stderr} (55%) create mode 100644 tests/ui/abi/abi-typo-unstable.feature_enabled.stderr delete mode 100644 tests/ui/extern/extern-with-type-bounds.rs delete mode 100644 tests/ui/extern/extern-with-type-bounds.stderr delete mode 100644 tests/ui/intrinsics/always-extern.rs delete mode 100644 tests/ui/intrinsics/always-extern.stderr create mode 100644 tests/ui/intrinsics/invalid-ABI-rust-intrinsic.rs create mode 100644 tests/ui/intrinsics/invalid-ABI-rust-intrinsic.stderr diff --git a/compiler/rustc_error_codes/src/error_codes/E0622.md b/compiler/rustc_error_codes/src/error_codes/E0622.md index 4cb605b636d2..e6ff949d3e9f 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0622.md +++ b/compiler/rustc_error_codes/src/error_codes/E0622.md @@ -6,8 +6,9 @@ Erroneous code example: #![feature(intrinsics)] #![allow(internal_features)] -extern "rust-intrinsic" { - pub static atomic_singlethreadfence_seqcst: fn(); +extern "C" { + #[rustc_intrinsic] + pub static atomic_singlethreadfence_seqcst: unsafe fn(); // error: intrinsic must be a function } @@ -22,9 +23,8 @@ error, just declare a function. Example: #![feature(intrinsics)] #![allow(internal_features)] -extern "rust-intrinsic" { - pub fn atomic_singlethreadfence_seqcst(); // ok! -} +#[rustc_intrinsic] +pub unsafe fn atomic_singlethreadfence_seqcst(); // ok! fn main() { unsafe { atomic_singlethreadfence_seqcst(); } } ``` diff --git a/tests/assembly/simd-bitmask.rs b/tests/assembly/simd-bitmask.rs index a632791153b2..e41224610870 100644 --- a/tests/assembly/simd-bitmask.rs +++ b/tests/assembly/simd-bitmask.rs @@ -35,9 +35,8 @@ pub struct m64x2([i64; 2]); #[repr(simd)] pub struct m64x4([i64; 4]); -extern "rust-intrinsic" { - fn simd_bitmask(mask: V) -> B; -} +#[rustc_intrinsic] +unsafe fn simd_bitmask(mask: V) -> B; // CHECK-LABEL: bitmask_m8x16 #[no_mangle] diff --git a/tests/assembly/simd-intrinsic-gather.rs b/tests/assembly/simd-intrinsic-gather.rs index 8c17a58046d8..bcab0ba1cc09 100644 --- a/tests/assembly/simd-intrinsic-gather.rs +++ b/tests/assembly/simd-intrinsic-gather.rs @@ -22,9 +22,8 @@ pub struct m64x4([i64; 4]); #[repr(simd)] pub struct pf64x4([*const f64; 4]); -extern "rust-intrinsic" { - fn simd_gather(values: V, mask: M, pointer: P) -> V; -} +#[rustc_intrinsic] +unsafe fn simd_gather(values: V, mask: M, pointer: P) -> V; // CHECK-LABEL: gather_f64x4 #[no_mangle] diff --git a/tests/assembly/simd-intrinsic-mask-load.rs b/tests/assembly/simd-intrinsic-mask-load.rs index a0d0514c0141..d3f3453a780a 100644 --- a/tests/assembly/simd-intrinsic-mask-load.rs +++ b/tests/assembly/simd-intrinsic-mask-load.rs @@ -34,9 +34,8 @@ pub struct f64x4([f64; 4]); #[repr(simd)] pub struct m64x4([i64; 4]); -extern "rust-intrinsic" { - fn simd_masked_load(mask: M, pointer: P, values: T) -> T; -} +#[rustc_intrinsic] +unsafe fn simd_masked_load(mask: M, pointer: P, values: T) -> T; // CHECK-LABEL: load_i8x16 #[no_mangle] diff --git a/tests/assembly/simd-intrinsic-mask-reduce.rs b/tests/assembly/simd-intrinsic-mask-reduce.rs index 959c4ddefdb0..8b15ed0a254c 100644 --- a/tests/assembly/simd-intrinsic-mask-reduce.rs +++ b/tests/assembly/simd-intrinsic-mask-reduce.rs @@ -20,10 +20,10 @@ use minicore::*; #[repr(simd)] pub struct mask8x16([i8; 16]); -extern "rust-intrinsic" { - fn simd_reduce_all(x: T) -> bool; - fn simd_reduce_any(x: T) -> bool; -} +#[rustc_intrinsic] +unsafe fn simd_reduce_all(x: T) -> bool; +#[rustc_intrinsic] +unsafe fn simd_reduce_any(x: T) -> bool; // CHECK-LABEL: mask_reduce_all: #[no_mangle] diff --git a/tests/assembly/simd-intrinsic-mask-store.rs b/tests/assembly/simd-intrinsic-mask-store.rs index 4be9194943c7..001762e5060d 100644 --- a/tests/assembly/simd-intrinsic-mask-store.rs +++ b/tests/assembly/simd-intrinsic-mask-store.rs @@ -34,9 +34,8 @@ pub struct f64x4([f64; 4]); #[repr(simd)] pub struct m64x4([i64; 4]); -extern "rust-intrinsic" { - fn simd_masked_store(mask: M, pointer: P, values: T); -} +#[rustc_intrinsic] +unsafe fn simd_masked_store(mask: M, pointer: P, values: T); // CHECK-LABEL: store_i8x16 #[no_mangle] diff --git a/tests/assembly/simd-intrinsic-scatter.rs b/tests/assembly/simd-intrinsic-scatter.rs index 715de04af4d7..d77dfad3546d 100644 --- a/tests/assembly/simd-intrinsic-scatter.rs +++ b/tests/assembly/simd-intrinsic-scatter.rs @@ -22,9 +22,8 @@ pub struct m64x4([i64; 4]); #[repr(simd)] pub struct pf64x4([*mut f64; 4]); -extern "rust-intrinsic" { - fn simd_scatter(values: V, pointer: P, mask: M); -} +#[rustc_intrinsic] +unsafe fn simd_scatter(values: V, pointer: P, mask: M); // CHECK-LABEL: scatter_f64x4 #[no_mangle] diff --git a/tests/assembly/simd-intrinsic-select.rs b/tests/assembly/simd-intrinsic-select.rs index 7f1e42662bfb..4f8d6b825b61 100644 --- a/tests/assembly/simd-intrinsic-select.rs +++ b/tests/assembly/simd-intrinsic-select.rs @@ -48,9 +48,8 @@ pub struct f64x8([f64; 8]); #[repr(simd)] pub struct m64x8([i64; 8]); -extern "rust-intrinsic" { - fn simd_select(mask: M, a: V, b: V) -> V; -} +#[rustc_intrinsic] +unsafe fn simd_select(mask: M, a: V, b: V) -> V; // CHECK-LABEL: select_i8x16 #[no_mangle] diff --git a/tests/codegen/avr/avr-func-addrspace.rs b/tests/codegen/avr/avr-func-addrspace.rs index 2ae2f40d7b34..e0192f8b45ab 100644 --- a/tests/codegen/avr/avr-func-addrspace.rs +++ b/tests/codegen/avr/avr-func-addrspace.rs @@ -17,9 +17,8 @@ extern crate minicore; use minicore::*; -extern "rust-intrinsic" { - pub fn transmute(src: Src) -> Dst; -} +#[rustc_intrinsic] +pub unsafe fn transmute(src: Src) -> Dst; pub static mut STORAGE_FOO: fn(&usize, &mut u32) -> Result<(), ()> = arbitrary_black_box; pub static mut STORAGE_BAR: u32 = 12; diff --git a/tests/codegen/emscripten-catch-unwind-js-eh.rs b/tests/codegen/emscripten-catch-unwind-js-eh.rs index 018ad5454fc2..3ab4b5c9c631 100644 --- a/tests/codegen/emscripten-catch-unwind-js-eh.rs +++ b/tests/codegen/emscripten-catch-unwind-js-eh.rs @@ -23,13 +23,12 @@ 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; -} +#[rustc_intrinsic] +unsafe 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] diff --git a/tests/codegen/emscripten-catch-unwind-wasm-eh.rs b/tests/codegen/emscripten-catch-unwind-wasm-eh.rs index 0fc9ae96720e..d0571e4df081 100644 --- a/tests/codegen/emscripten-catch-unwind-wasm-eh.rs +++ b/tests/codegen/emscripten-catch-unwind-wasm-eh.rs @@ -21,14 +21,12 @@ impl Copy for *mut T {} 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; -} +#[rustc_intrinsic] +unsafe 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] diff --git a/tests/codegen/intrinsic-no-unnamed-attr.rs b/tests/codegen/intrinsic-no-unnamed-attr.rs index fce0de80d7b6..35eb025ab6bb 100644 --- a/tests/codegen/intrinsic-no-unnamed-attr.rs +++ b/tests/codegen/intrinsic-no-unnamed-attr.rs @@ -2,9 +2,9 @@ #![feature(intrinsics)] -extern "rust-intrinsic" { - fn sqrtf32(x: f32) -> f32; -} +#[rustc_intrinsic] +unsafe fn sqrtf32(x: f32) -> f32; + // CHECK: @llvm.sqrt.f32(float) #{{[0-9]*}} fn main() { diff --git a/tests/codegen/intrinsics/nontemporal.rs b/tests/codegen/intrinsics/nontemporal.rs index 1d4fae83c29d..a151d4bd2974 100644 --- a/tests/codegen/intrinsics/nontemporal.rs +++ b/tests/codegen/intrinsics/nontemporal.rs @@ -18,9 +18,8 @@ extern crate minicore; use minicore::*; -extern "rust-intrinsic" { - pub fn nontemporal_store(ptr: *mut T, val: T); -} +#[rustc_intrinsic] +pub unsafe fn nontemporal_store(ptr: *mut T, val: T); #[no_mangle] pub fn a(a: &mut u32, b: u32) { diff --git a/tests/mir-opt/lower_intrinsics.rs b/tests/mir-opt/lower_intrinsics.rs index 4859d9354619..5afddc5ff730 100644 --- a/tests/mir-opt/lower_intrinsics.rs +++ b/tests/mir-opt/lower_intrinsics.rs @@ -153,11 +153,10 @@ pub fn discriminant(t: T) { core::intrinsics::discriminant_value(&E::B); } -extern "rust-intrinsic" { - // Cannot use `std::intrinsics::copy_nonoverlapping` as that is a wrapper function - #[rustc_nounwind] - fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize); -} +// Cannot use `std::intrinsics::copy_nonoverlapping` as that is a wrapper function +#[rustc_nounwind] +#[rustc_intrinsic] +unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize); // EMIT_MIR lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.diff pub fn f_copy_nonoverlapping() { diff --git a/tests/run-make/atomic-lock-free/atomic_lock_free.rs b/tests/run-make/atomic-lock-free/atomic_lock_free.rs index 1f1116b9bfd1..b49c5044f31d 100644 --- a/tests/run-make/atomic-lock-free/atomic_lock_free.rs +++ b/tests/run-make/atomic-lock-free/atomic_lock_free.rs @@ -2,9 +2,8 @@ #![crate_type = "rlib"] #![no_core] -extern "rust-intrinsic" { - fn atomic_xadd_seqcst(dst: *mut T, src: T) -> T; -} +#[rustc_intrinsic] +unsafe fn atomic_xadd_seqcst(dst: *mut T, src: T) -> T; #[lang = "sized"] trait Sized {} diff --git a/tests/run-make/avr-rjmp-offset/avr-rjmp-offsets.rs b/tests/run-make/avr-rjmp-offset/avr-rjmp-offsets.rs index 2f97fc1ed95a..c91cd695ceea 100644 --- a/tests/run-make/avr-rjmp-offset/avr-rjmp-offsets.rs +++ b/tests/run-make/avr-rjmp-offset/avr-rjmp-offsets.rs @@ -37,10 +37,9 @@ mod minicore { #[inline] #[rustc_diagnostic_item = "ptr_write_volatile"] pub unsafe fn write_volatile(dst: *mut T, src: T) { - extern "rust-intrinsic" { - #[rustc_nounwind] - pub fn volatile_store(dst: *mut T, val: T); - } + #[rustc_intrinsic] + pub unsafe fn volatile_store(dst: *mut T, val: T); + unsafe { volatile_store(dst, src) }; } } diff --git a/tests/ui/abi/abi-typo-unstable.stderr b/tests/ui/abi/abi-typo-unstable.feature_disabled.stderr similarity index 55% rename from tests/ui/abi/abi-typo-unstable.stderr rename to tests/ui/abi/abi-typo-unstable.feature_disabled.stderr index 9ba67ad7dbe4..1934b483c47a 100644 --- a/tests/ui/abi/abi-typo-unstable.stderr +++ b/tests/ui/abi/abi-typo-unstable.feature_disabled.stderr @@ -1,8 +1,8 @@ -error[E0703]: invalid ABI: found `rust-intrinsec` - --> $DIR/abi-typo-unstable.rs:2:8 +error[E0703]: invalid ABI: found `rust-cull` + --> $DIR/abi-typo-unstable.rs:5:8 | -LL | extern "rust-intrinsec" fn rust_intrinsic() {} - | ^^^^^^^^^^^^^^^^ invalid ABI +LL | extern "rust-cull" fn rust_call(_: ()) {} + | ^^^^^^^^^^^ invalid ABI | = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions diff --git a/tests/ui/abi/abi-typo-unstable.feature_enabled.stderr b/tests/ui/abi/abi-typo-unstable.feature_enabled.stderr new file mode 100644 index 000000000000..868b9509830b --- /dev/null +++ b/tests/ui/abi/abi-typo-unstable.feature_enabled.stderr @@ -0,0 +1,16 @@ +error[E0703]: invalid ABI: found `rust-cull` + --> $DIR/abi-typo-unstable.rs:5:8 + | +LL | extern "rust-cull" fn rust_call(_: ()) {} + | ^^^^^^^^^^^ invalid ABI + | + = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions +help: there's a similarly named valid ABI `rust-call` + | +LL - extern "rust-cull" fn rust_call(_: ()) {} +LL + extern "rust-call" fn rust_call(_: ()) {} + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0703`. diff --git a/tests/ui/abi/abi-typo-unstable.rs b/tests/ui/abi/abi-typo-unstable.rs index 94991a5eb17e..75366217fa26 100644 --- a/tests/ui/abi/abi-typo-unstable.rs +++ b/tests/ui/abi/abi-typo-unstable.rs @@ -1,6 +1,11 @@ -// rust-intrinsic is unstable and not enabled, so it should not be suggested as a fix -extern "rust-intrinsec" fn rust_intrinsic() {} //~ ERROR invalid ABI +//@ revisions: feature_disabled feature_enabled +#![cfg_attr(feature_enabled, feature(unboxed_closures))] + +// rust-call is unstable and not enabled, so it should not be suggested as a fix +extern "rust-cull" fn rust_call(_: ()) {} +//~^ ERROR invalid ABI +//[feature_enabled]~| HELP there's a similarly named valid ABI fn main() { - rust_intrinsic(); + rust_call(()); } diff --git a/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr b/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr index d7d2161e7ad9..1be8db5ddf44 100644 --- a/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr +++ b/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr @@ -10,24 +10,6 @@ LL - fn get(x: T, y: U) -> Get::Value {} LL + fn get(x: T, y: U) -> ::Value {} | -error[E0223]: ambiguous associated type - --> $DIR/associated-types-in-ambiguous-context.rs:13:23 - | -LL | fn grab(&self) -> Grab::Value; - | ^^^^^^^^^^^ help: use fully-qualified syntax: `::Value` - -error[E0223]: ambiguous associated type - --> $DIR/associated-types-in-ambiguous-context.rs:16:22 - | -LL | fn get(&self) -> Get::Value; - | ^^^^^^^^^^ - | -help: if there were a type named `Example` that implemented `Get`, you could use the fully-qualified path - | -LL - fn get(&self) -> Get::Value; -LL + fn get(&self) -> ::Value; - | - error[E0223]: ambiguous associated type --> $DIR/associated-types-in-ambiguous-context.rs:22:17 | @@ -56,6 +38,24 @@ LL + type X = as Deref>::Target; | and N other candidates +error[E0223]: ambiguous associated type + --> $DIR/associated-types-in-ambiguous-context.rs:13:23 + | +LL | fn grab(&self) -> Grab::Value; + | ^^^^^^^^^^^ help: use fully-qualified syntax: `::Value` + +error[E0223]: ambiguous associated type + --> $DIR/associated-types-in-ambiguous-context.rs:16:22 + | +LL | fn get(&self) -> Get::Value; + | ^^^^^^^^^^ + | +help: if there were a type named `Example` that implemented `Get`, you could use the fully-qualified path + | +LL - fn get(&self) -> Get::Value; +LL + fn get(&self) -> ::Value; + | + error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0223`. diff --git a/tests/ui/borrowck/ice-mutability-error-slicing-121807.stderr b/tests/ui/borrowck/ice-mutability-error-slicing-121807.stderr index 3a6b8008fceb..02d5231f7134 100644 --- a/tests/ui/borrowck/ice-mutability-error-slicing-121807.stderr +++ b/tests/ui/borrowck/ice-mutability-error-slicing-121807.stderr @@ -23,12 +23,6 @@ LL | extern "C" fn read_dword(Self::Assoc<'_>) -> u16; = note: for more information, see issue #41686 = note: `#[warn(anonymous_parameters)]` on by default -error[E0220]: associated type `Assoc` not found for `Self` - --> $DIR/ice-mutability-error-slicing-121807.rs:7:36 - | -LL | extern "C" fn read_dword(Self::Assoc<'_>) -> u16; - | ^^^^^ associated type `Assoc` not found - error[E0185]: method `read_dword` has a `&self` declaration in the impl, but not in the trait --> $DIR/ice-mutability-error-slicing-121807.rs:17:5 | @@ -47,6 +41,12 @@ LL | extern "C" fn read_word(&mut self) -> u8; LL | impl MemoryUnit for ROM { | ^^^^^^^^^^^^^^^^^^^^^^^ missing `read_word` in implementation +error[E0220]: associated type `Assoc` not found for `Self` + --> $DIR/ice-mutability-error-slicing-121807.rs:7:36 + | +LL | extern "C" fn read_dword(Self::Assoc<'_>) -> u16; + | ^^^^^ associated type `Assoc` not found + error: aborting due to 4 previous errors; 1 warning emitted Some errors have detailed explanations: E0046, E0185, E0220, E0261. diff --git a/tests/ui/borrowck/trait-impl-argument-difference-ice.stderr b/tests/ui/borrowck/trait-impl-argument-difference-ice.stderr index 190ddeaa8f28..a656bb67bcba 100644 --- a/tests/ui/borrowck/trait-impl-argument-difference-ice.stderr +++ b/tests/ui/borrowck/trait-impl-argument-difference-ice.stderr @@ -8,12 +8,6 @@ LL | extern "C" fn read_dword(Self::Assoc<'_>) -> u16; = note: for more information, see issue #41686 = note: `#[warn(anonymous_parameters)]` on by default -error[E0220]: associated type `Assoc` not found for `Self` - --> $DIR/trait-impl-argument-difference-ice.rs:4:36 - | -LL | extern "C" fn read_dword(Self::Assoc<'_>) -> u16; - | ^^^^^ associated type `Assoc` not found - error[E0185]: method `read_dword` has a `&self` declaration in the impl, but not in the trait --> $DIR/trait-impl-argument-difference-ice.rs:14:5 | @@ -32,6 +26,12 @@ LL | extern "C" fn read_word(&mut self) -> u8; LL | impl MemoryUnit for ROM { | ^^^^^^^^^^^^^^^^^^^^^^^ missing `read_word` in implementation +error[E0220]: associated type `Assoc` not found for `Self` + --> $DIR/trait-impl-argument-difference-ice.rs:4:36 + | +LL | extern "C" fn read_dword(Self::Assoc<'_>) -> u16; + | ^^^^^ associated type `Assoc` not found + error[E0596]: cannot borrow `*self` as mutable, as it is behind a `&` reference --> $DIR/trait-impl-argument-difference-ice.rs:16:19 | diff --git a/tests/ui/delegation/ice-issue-124347.rs b/tests/ui/delegation/ice-issue-124347.rs index b2b3c61a722b..3e0a5b36ddcf 100644 --- a/tests/ui/delegation/ice-issue-124347.rs +++ b/tests/ui/delegation/ice-issue-124347.rs @@ -4,7 +4,6 @@ // FIXME(fn_delegation): `recursive delegation` error should be emitted here trait Trait { reuse Trait::foo { &self.0 } - //~^ ERROR recursive delegation is not supported yet } reuse foo; diff --git a/tests/ui/delegation/ice-issue-124347.stderr b/tests/ui/delegation/ice-issue-124347.stderr index 74c4b5cd949a..2955c0442034 100644 --- a/tests/ui/delegation/ice-issue-124347.stderr +++ b/tests/ui/delegation/ice-issue-124347.stderr @@ -1,23 +1,17 @@ -error: recursive delegation is not supported yet - --> $DIR/ice-issue-124347.rs:6:18 - | -LL | reuse Trait::foo { &self.0 } - | ^^^ callee defined here - error[E0391]: cycle detected when computing generics of `foo` - --> $DIR/ice-issue-124347.rs:10:7 + --> $DIR/ice-issue-124347.rs:9:7 | LL | reuse foo; | ^^^ | = note: ...which immediately requires computing generics of `foo` again note: cycle used when checking that `foo` is well-formed - --> $DIR/ice-issue-124347.rs:10:7 + --> $DIR/ice-issue-124347.rs:9:7 | LL | reuse foo; | ^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.stderr b/tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.stderr index 832e7ef4dc38..2cf244185e69 100644 --- a/tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.stderr +++ b/tests/ui/dyn-compatibility/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.stderr @@ -187,166 +187,6 @@ help: consider using the `'static` lifetime, but this is uncommon unless you're LL | fn parrot() -> &'static mut Trait { | +++++++ -error[E0782]: expected a type, found a trait - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:52:16 - | -LL | fn foo(_: &Trait); - | ^^^^^ - | -help: use a new generic type parameter, constrained by `Trait` - | -LL - fn foo(_: &Trait); -LL + fn foo(_: &T); - | -help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference - | -LL | fn foo(_: &impl Trait); - | ++++ -help: alternatively, use a trait object to accept any type that implements `Trait`, accessing its methods at runtime using dynamic dispatch - | -LL | fn foo(_: &dyn Trait); - | +++ - -error[E0782]: expected a type, found a trait - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:55:19 - | -LL | fn bar(_: &'a Trait); - | ^^^^^ - | -help: use a new generic type parameter, constrained by `Trait` - | -LL - fn bar(_: &'a Trait); -LL + fn bar(_: &'a T); - | -help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference - | -LL | fn bar(_: &'a impl Trait); - | ++++ -help: alternatively, use a trait object to accept any type that implements `Trait`, accessing its methods at runtime using dynamic dispatch - | -LL | fn bar(_: &'a dyn Trait); - | +++ - -error[E0782]: expected a type, found a trait - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:59:22 - | -LL | fn alice<'a>(_: &Trait); - | ^^^^^ - | -help: use a new generic type parameter, constrained by `Trait` - | -LL - fn alice<'a>(_: &Trait); -LL + fn alice<'a, T: Trait>(_: &T); - | -help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference - | -LL | fn alice<'a>(_: &impl Trait); - | ++++ -help: alternatively, use a trait object to accept any type that implements `Trait`, accessing its methods at runtime using dynamic dispatch - | -LL | fn alice<'a>(_: &dyn Trait); - | +++ - -error[E0782]: expected a type, found a trait - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:62:23 - | -LL | fn bob<'a>(_: &'a Trait); - | ^^^^^ - | -help: use a new generic type parameter, constrained by `Trait` - | -LL - fn bob<'a>(_: &'a Trait); -LL + fn bob<'a, T: Trait>(_: &'a T); - | -help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference - | -LL | fn bob<'a>(_: &'a impl Trait); - | ++++ -help: alternatively, use a trait object to accept any type that implements `Trait`, accessing its methods at runtime using dynamic dispatch - | -LL | fn bob<'a>(_: &'a dyn Trait); - | +++ - -error[E0782]: expected a type, found a trait - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:65:18 - | -LL | fn cat() -> &Trait; - | ^^^^^ - | -help: use `impl Trait` to return an opaque type, as long as you return a single underlying type - | -LL | fn cat() -> &impl Trait; - | ++++ -help: alternatively, you can return an owned trait object - | -LL - fn cat() -> &Trait; -LL + fn cat() -> Box; - | - -error[E0782]: expected a type, found a trait - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:69:22 - | -LL | fn dog<'a>() -> &Trait { - | ^^^^^ - | -help: use `impl Trait` to return an opaque type, as long as you return a single underlying type - | -LL | fn dog<'a>() -> &impl Trait { - | ++++ -help: alternatively, you can return an owned trait object - | -LL - fn dog<'a>() -> &Trait { -LL + fn dog<'a>() -> Box { - | - -error[E0782]: expected a type, found a trait - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:75:24 - | -LL | fn kitten() -> &'a Trait { - | ^^^^^ - | -help: use `impl Trait` to return an opaque type, as long as you return a single underlying type - | -LL | fn kitten() -> &'a impl Trait { - | ++++ -help: alternatively, you can return an owned trait object - | -LL - fn kitten() -> &'a Trait { -LL + fn kitten() -> Box { - | - -error[E0782]: expected a type, found a trait - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:81:27 - | -LL | fn puppy<'a>() -> &'a Trait { - | ^^^^^ - | -help: use `impl Trait` to return an opaque type, as long as you return a single underlying type - | -LL | fn puppy<'a>() -> &'a impl Trait { - | ++++ -help: alternatively, you can return an owned trait object - | -LL - fn puppy<'a>() -> &'a Trait { -LL + fn puppy<'a>() -> Box { - | - -error[E0782]: expected a type, found a trait - --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:86:25 - | -LL | fn parrot() -> &mut Trait { - | ^^^^^ - | -help: use `impl Trait` to return an opaque type, as long as you return a single underlying type - | -LL | fn parrot() -> &mut impl Trait { - | ++++ -help: alternatively, you can return an owned trait object - | -LL - fn parrot() -> &mut Trait { -LL + fn parrot() -> Box { - | - error[E0782]: expected a type, found a trait --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:93:12 | @@ -667,6 +507,166 @@ LL - fn parrot() -> &mut Trait { LL + fn parrot() -> Box { | +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:52:16 + | +LL | fn foo(_: &Trait); + | ^^^^^ + | +help: use a new generic type parameter, constrained by `Trait` + | +LL - fn foo(_: &Trait); +LL + fn foo(_: &T); + | +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn foo(_: &impl Trait); + | ++++ +help: alternatively, use a trait object to accept any type that implements `Trait`, accessing its methods at runtime using dynamic dispatch + | +LL | fn foo(_: &dyn Trait); + | +++ + +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:55:19 + | +LL | fn bar(_: &'a Trait); + | ^^^^^ + | +help: use a new generic type parameter, constrained by `Trait` + | +LL - fn bar(_: &'a Trait); +LL + fn bar(_: &'a T); + | +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn bar(_: &'a impl Trait); + | ++++ +help: alternatively, use a trait object to accept any type that implements `Trait`, accessing its methods at runtime using dynamic dispatch + | +LL | fn bar(_: &'a dyn Trait); + | +++ + +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:59:22 + | +LL | fn alice<'a>(_: &Trait); + | ^^^^^ + | +help: use a new generic type parameter, constrained by `Trait` + | +LL - fn alice<'a>(_: &Trait); +LL + fn alice<'a, T: Trait>(_: &T); + | +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn alice<'a>(_: &impl Trait); + | ++++ +help: alternatively, use a trait object to accept any type that implements `Trait`, accessing its methods at runtime using dynamic dispatch + | +LL | fn alice<'a>(_: &dyn Trait); + | +++ + +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:62:23 + | +LL | fn bob<'a>(_: &'a Trait); + | ^^^^^ + | +help: use a new generic type parameter, constrained by `Trait` + | +LL - fn bob<'a>(_: &'a Trait); +LL + fn bob<'a, T: Trait>(_: &'a T); + | +help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference + | +LL | fn bob<'a>(_: &'a impl Trait); + | ++++ +help: alternatively, use a trait object to accept any type that implements `Trait`, accessing its methods at runtime using dynamic dispatch + | +LL | fn bob<'a>(_: &'a dyn Trait); + | +++ + +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:65:18 + | +LL | fn cat() -> &Trait; + | ^^^^^ + | +help: use `impl Trait` to return an opaque type, as long as you return a single underlying type + | +LL | fn cat() -> &impl Trait; + | ++++ +help: alternatively, you can return an owned trait object + | +LL - fn cat() -> &Trait; +LL + fn cat() -> Box; + | + +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:69:22 + | +LL | fn dog<'a>() -> &Trait { + | ^^^^^ + | +help: use `impl Trait` to return an opaque type, as long as you return a single underlying type + | +LL | fn dog<'a>() -> &impl Trait { + | ++++ +help: alternatively, you can return an owned trait object + | +LL - fn dog<'a>() -> &Trait { +LL + fn dog<'a>() -> Box { + | + +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:75:24 + | +LL | fn kitten() -> &'a Trait { + | ^^^^^ + | +help: use `impl Trait` to return an opaque type, as long as you return a single underlying type + | +LL | fn kitten() -> &'a impl Trait { + | ++++ +help: alternatively, you can return an owned trait object + | +LL - fn kitten() -> &'a Trait { +LL + fn kitten() -> Box { + | + +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:81:27 + | +LL | fn puppy<'a>() -> &'a Trait { + | ^^^^^ + | +help: use `impl Trait` to return an opaque type, as long as you return a single underlying type + | +LL | fn puppy<'a>() -> &'a impl Trait { + | ++++ +help: alternatively, you can return an owned trait object + | +LL - fn puppy<'a>() -> &'a Trait { +LL + fn puppy<'a>() -> Box { + | + +error[E0782]: expected a type, found a trait + --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:86:25 + | +LL | fn parrot() -> &mut Trait { + | ^^^^^ + | +help: use `impl Trait` to return an opaque type, as long as you return a single underlying type + | +LL | fn parrot() -> &mut impl Trait { + | ++++ +help: alternatively, you can return an owned trait object + | +LL - fn parrot() -> &mut Trait { +LL + fn parrot() -> Box { + | + error: aborting due to 42 previous errors Some errors have detailed explanations: E0106, E0261, E0782. diff --git a/tests/ui/error-codes/E0092.rs b/tests/ui/error-codes/E0092.rs index ddaace98bd4a..19a7c65a48ed 100644 --- a/tests/ui/error-codes/E0092.rs +++ b/tests/ui/error-codes/E0092.rs @@ -1,7 +1,6 @@ #![feature(intrinsics)] -extern "rust-intrinsic" { - fn atomic_foo(); //~ ERROR E0092 -} -fn main() { -} +#[rustc_intrinsic] +unsafe fn atomic_foo(); //~ ERROR E0092 + +fn main() {} diff --git a/tests/ui/error-codes/E0092.stderr b/tests/ui/error-codes/E0092.stderr index 4ff2e6f077d2..003c989fd596 100644 --- a/tests/ui/error-codes/E0092.stderr +++ b/tests/ui/error-codes/E0092.stderr @@ -1,8 +1,8 @@ error[E0092]: unrecognized atomic operation function: `foo` - --> $DIR/E0092.rs:3:5 + --> $DIR/E0092.rs:4:11 | -LL | fn atomic_foo(); - | ^^^^^^^^^^^^^^^^ unrecognized atomic operation +LL | unsafe fn atomic_foo(); + | ^^^^^^^^^^ unrecognized atomic operation error: aborting due to 1 previous error diff --git a/tests/ui/error-codes/E0093.rs b/tests/ui/error-codes/E0093.rs index a2f0b1ae4437..24df7a9a32b9 100644 --- a/tests/ui/error-codes/E0093.rs +++ b/tests/ui/error-codes/E0093.rs @@ -1,8 +1,7 @@ #![feature(intrinsics)] -extern "rust-intrinsic" { - fn foo(); - //~^ ERROR E0093 -} -fn main() { -} +#[rustc_intrinsic] +unsafe fn foo(); +//~^ ERROR E0093 + +fn main() {} diff --git a/tests/ui/error-codes/E0093.stderr b/tests/ui/error-codes/E0093.stderr index 51c367b343ab..d81bf53976ae 100644 --- a/tests/ui/error-codes/E0093.stderr +++ b/tests/ui/error-codes/E0093.stderr @@ -1,8 +1,8 @@ error[E0093]: unrecognized intrinsic function: `foo` - --> $DIR/E0093.rs:3:5 + --> $DIR/E0093.rs:4:11 | -LL | fn foo(); - | ^^^^^^^^^ unrecognized intrinsic +LL | unsafe fn foo(); + | ^^^ unrecognized intrinsic | = help: if you're adding an intrinsic, be sure to update `check_intrinsic_type` diff --git a/tests/ui/error-codes/E0622.rs b/tests/ui/error-codes/E0622.rs index 08c6d1712960..0c2a4f226d80 100644 --- a/tests/ui/error-codes/E0622.rs +++ b/tests/ui/error-codes/E0622.rs @@ -1,6 +1,14 @@ #![feature(intrinsics)] -extern "rust-intrinsic" { - pub static atomic_singlethreadfence_seqcst : unsafe extern "rust-intrinsic" fn(); + +extern "C" { + + #[rustc_intrinsic] + pub static atomic_singlethreadfence_seqcst: unsafe extern "C" fn(); //~^ ERROR intrinsic must be a function [E0622] } -fn main() { unsafe { atomic_singlethreadfence_seqcst(); } } + +fn main() { + unsafe { + atomic_singlethreadfence_seqcst(); + } +} diff --git a/tests/ui/error-codes/E0622.stderr b/tests/ui/error-codes/E0622.stderr index 739ec984fc60..c0aea542af04 100644 --- a/tests/ui/error-codes/E0622.stderr +++ b/tests/ui/error-codes/E0622.stderr @@ -1,8 +1,8 @@ error[E0622]: intrinsic must be a function - --> $DIR/E0622.rs:3:5 + --> $DIR/E0622.rs:6:5 | -LL | pub static atomic_singlethreadfence_seqcst : unsafe extern "rust-intrinsic" fn(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected a function +LL | pub static atomic_singlethreadfence_seqcst: unsafe extern "C" fn(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected a function error: aborting due to 1 previous error diff --git a/tests/ui/extern/extern-with-type-bounds.rs b/tests/ui/extern/extern-with-type-bounds.rs deleted file mode 100644 index 3fbddfc99a6f..000000000000 --- a/tests/ui/extern/extern-with-type-bounds.rs +++ /dev/null @@ -1,21 +0,0 @@ -#![feature(intrinsics, rustc_attrs)] - -// Intrinsics are the only (?) extern blocks supporting generics. -// Once intrinsics have to be declared via `#[rustc_intrinsic]`, -// the entire support for generics in extern fn can probably be removed. - -extern "rust-intrinsic" { - // Silent bounds made explicit to make sure they are actually - // resolved. - fn transmute(val: T) -> U; - - // Bounds aren't checked right now, so this should work - // even though it's incorrect. - fn size_of_val(x: *const T) -> usize; - - // Unresolved bounds should still error. - fn align_of() -> usize; - //~^ ERROR cannot find trait `NoSuchTrait` in this scope -} - -fn main() {} diff --git a/tests/ui/extern/extern-with-type-bounds.stderr b/tests/ui/extern/extern-with-type-bounds.stderr deleted file mode 100644 index 893947e831fd..000000000000 --- a/tests/ui/extern/extern-with-type-bounds.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0405]: cannot find trait `NoSuchTrait` in this scope - --> $DIR/extern-with-type-bounds.rs:17:20 - | -LL | fn align_of() -> usize; - | ^^^^^^^^^^^ not found in this scope - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0405`. diff --git a/tests/ui/feature-gates/feature-gate-abi.rs b/tests/ui/feature-gates/feature-gate-abi.rs index 2af623734ee8..bafd3643788e 100644 --- a/tests/ui/feature-gates/feature-gate-abi.rs +++ b/tests/ui/feature-gates/feature-gate-abi.rs @@ -8,19 +8,10 @@ extern crate minicore; use minicore::*; -// Functions -extern "rust-intrinsic" fn f1() {} //~ ERROR extern "rust-intrinsic" ABI is an implementation detail - //~^ ERROR intrinsic must be in -extern "rust-intrinsic" fn f2() {} //~ ERROR extern "rust-intrinsic" ABI is an implementation detail - //~^ ERROR intrinsic must be in extern "rust-call" fn f4(_: ()) {} //~ ERROR extern "rust-call" ABI is experimental and subject to change // Methods in trait definition trait Tr { - extern "rust-intrinsic" fn m1(); //~ ERROR extern "rust-intrinsic" ABI is an implementation detail - //~^ ERROR intrinsic must be in - extern "rust-intrinsic" fn m2(); //~ ERROR extern "rust-intrinsic" ABI is an implementation detail - //~^ ERROR intrinsic must be in extern "rust-call" fn m4(_: ()); //~ ERROR extern "rust-call" ABI is experimental and subject to change extern "rust-call" fn dm4(_: ()) {} //~ ERROR extern "rust-call" ABI is experimental and subject to change @@ -30,28 +21,16 @@ struct S; // Methods in trait impl impl Tr for S { - extern "rust-intrinsic" fn m1() {} //~ ERROR extern "rust-intrinsic" ABI is an implementation detail - //~^ ERROR intrinsic must be in - extern "rust-intrinsic" fn m2() {} //~ ERROR extern "rust-intrinsic" ABI is an implementation detail - //~^ ERROR intrinsic must be in extern "rust-call" fn m4(_: ()) {} //~ ERROR extern "rust-call" ABI is experimental and subject to change } // Methods in inherent impl impl S { - extern "rust-intrinsic" fn im1() {} //~ ERROR extern "rust-intrinsic" ABI is an implementation detail - //~^ ERROR intrinsic must be in - extern "rust-intrinsic" fn im2() {} //~ ERROR extern "rust-intrinsic" ABI is an implementation detail - //~^ ERROR intrinsic must be in extern "rust-call" fn im4(_: ()) {} //~ ERROR extern "rust-call" ABI is experimental and subject to change } // Function pointer types -type A1 = extern "rust-intrinsic" fn(); //~ ERROR extern "rust-intrinsic" ABI is an implementation detail -type A2 = extern "rust-intrinsic" fn(); //~ ERROR extern "rust-intrinsic" ABI is an implementation detail type A4 = extern "rust-call" fn(_: ()); //~ ERROR extern "rust-call" ABI is experimental and subject to change // Foreign modules -extern "rust-intrinsic" {} //~ ERROR extern "rust-intrinsic" ABI is an implementation detail -extern "rust-intrinsic" {} //~ ERROR extern "rust-intrinsic" ABI is an implementation detail extern "rust-call" {} //~ ERROR extern "rust-call" ABI is experimental and subject to change diff --git a/tests/ui/feature-gates/feature-gate-abi.stderr b/tests/ui/feature-gates/feature-gate-abi.stderr index a974c0099cbd..7897a60b34f4 100644 --- a/tests/ui/feature-gates/feature-gate-abi.stderr +++ b/tests/ui/feature-gates/feature-gate-abi.stderr @@ -1,23 +1,5 @@ -error[E0658]: the extern "rust-intrinsic" ABI is an implementation detail and perma-unstable - --> $DIR/feature-gate-abi.rs:12:8 - | -LL | extern "rust-intrinsic" fn f1() {} - | ^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(intrinsics)]` 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 extern "rust-intrinsic" ABI is an implementation detail and perma-unstable - --> $DIR/feature-gate-abi.rs:14:8 - | -LL | extern "rust-intrinsic" fn f2() {} - | ^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(intrinsics)]` 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 extern "rust-call" ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:16:8 + --> $DIR/feature-gate-abi.rs:11:8 | LL | extern "rust-call" fn f4(_: ()) {} | ^^^^^^^^^^^ @@ -26,26 +8,8 @@ LL | extern "rust-call" fn f4(_: ()) {} = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: the extern "rust-intrinsic" ABI is an implementation detail and perma-unstable - --> $DIR/feature-gate-abi.rs:20:12 - | -LL | extern "rust-intrinsic" fn m1(); - | ^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(intrinsics)]` 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 extern "rust-intrinsic" ABI is an implementation detail and perma-unstable - --> $DIR/feature-gate-abi.rs:22:12 - | -LL | extern "rust-intrinsic" fn m2(); - | ^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(intrinsics)]` 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 extern "rust-call" ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:24:12 + --> $DIR/feature-gate-abi.rs:15:12 | LL | extern "rust-call" fn m4(_: ()); | ^^^^^^^^^^^ @@ -55,7 +19,7 @@ LL | extern "rust-call" fn m4(_: ()); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the extern "rust-call" ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:26:12 + --> $DIR/feature-gate-abi.rs:17:12 | LL | extern "rust-call" fn dm4(_: ()) {} | ^^^^^^^^^^^ @@ -64,26 +28,8 @@ LL | extern "rust-call" fn dm4(_: ()) {} = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: the extern "rust-intrinsic" ABI is an implementation detail and perma-unstable - --> $DIR/feature-gate-abi.rs:33:12 - | -LL | extern "rust-intrinsic" fn m1() {} - | ^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(intrinsics)]` 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 extern "rust-intrinsic" ABI is an implementation detail and perma-unstable - --> $DIR/feature-gate-abi.rs:35:12 - | -LL | extern "rust-intrinsic" fn m2() {} - | ^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(intrinsics)]` 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 extern "rust-call" ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:37:12 + --> $DIR/feature-gate-abi.rs:24:12 | LL | extern "rust-call" fn m4(_: ()) {} | ^^^^^^^^^^^ @@ -92,26 +38,8 @@ LL | extern "rust-call" fn m4(_: ()) {} = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: the extern "rust-intrinsic" ABI is an implementation detail and perma-unstable - --> $DIR/feature-gate-abi.rs:42:12 - | -LL | extern "rust-intrinsic" fn im1() {} - | ^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(intrinsics)]` 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 extern "rust-intrinsic" ABI is an implementation detail and perma-unstable - --> $DIR/feature-gate-abi.rs:44:12 - | -LL | extern "rust-intrinsic" fn im2() {} - | ^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(intrinsics)]` 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 extern "rust-call" ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:46:12 + --> $DIR/feature-gate-abi.rs:29:12 | LL | extern "rust-call" fn im4(_: ()) {} | ^^^^^^^^^^^ @@ -120,26 +48,8 @@ LL | extern "rust-call" fn im4(_: ()) {} = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: the extern "rust-intrinsic" ABI is an implementation detail and perma-unstable - --> $DIR/feature-gate-abi.rs:50:18 - | -LL | type A1 = extern "rust-intrinsic" fn(); - | ^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(intrinsics)]` 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 extern "rust-intrinsic" ABI is an implementation detail and perma-unstable - --> $DIR/feature-gate-abi.rs:51:18 - | -LL | type A2 = extern "rust-intrinsic" fn(); - | ^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(intrinsics)]` 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 extern "rust-call" ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:52:18 + --> $DIR/feature-gate-abi.rs:33:18 | LL | type A4 = extern "rust-call" fn(_: ()); | ^^^^^^^^^^^ @@ -148,26 +58,8 @@ LL | type A4 = extern "rust-call" fn(_: ()); = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: the extern "rust-intrinsic" ABI is an implementation detail and perma-unstable - --> $DIR/feature-gate-abi.rs:55:8 - | -LL | extern "rust-intrinsic" {} - | ^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(intrinsics)]` 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 extern "rust-intrinsic" ABI is an implementation detail and perma-unstable - --> $DIR/feature-gate-abi.rs:56:8 - | -LL | extern "rust-intrinsic" {} - | ^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(intrinsics)]` 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 extern "rust-call" ABI is experimental and subject to change - --> $DIR/feature-gate-abi.rs:57:8 + --> $DIR/feature-gate-abi.rs:36:8 | LL | extern "rust-call" {} | ^^^^^^^^^^^ @@ -176,54 +68,6 @@ LL | extern "rust-call" {} = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:20:32 - | -LL | extern "rust-intrinsic" fn m1(); - | ^^ - -error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:22:32 - | -LL | extern "rust-intrinsic" fn m2(); - | ^^ - -error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:12:33 - | -LL | extern "rust-intrinsic" fn f1() {} - | ^^ - -error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:14:33 - | -LL | extern "rust-intrinsic" fn f2() {} - | ^^ - -error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:33:37 - | -LL | extern "rust-intrinsic" fn m1() {} - | ^^ - -error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:35:37 - | -LL | extern "rust-intrinsic" fn m2() {} - | ^^ - -error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:42:38 - | -LL | extern "rust-intrinsic" fn im1() {} - | ^^ - -error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-abi.rs:44:38 - | -LL | extern "rust-intrinsic" fn im2() {} - | ^^ - -error: aborting due to 27 previous errors +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-intrinsics.rs b/tests/ui/feature-gates/feature-gate-intrinsics.rs index 65806a0223e7..b7ebba672728 100644 --- a/tests/ui/feature-gates/feature-gate-intrinsics.rs +++ b/tests/ui/feature-gates/feature-gate-intrinsics.rs @@ -1,8 +1,5 @@ -extern "rust-intrinsic" { //~ ERROR "rust-intrinsic" ABI is an implementation detail - fn bar(); //~ ERROR unrecognized intrinsic function: `bar` -} - -extern "rust-intrinsic" fn baz() {} //~ ERROR "rust-intrinsic" ABI is an implementation detail -//~^ ERROR intrinsic must be in +#[rustc_intrinsic] +//~^ ERROR the `#[rustc_intrinsic]` attribute is used to declare intrinsics as function items +fn bar(); fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-intrinsics.stderr b/tests/ui/feature-gates/feature-gate-intrinsics.stderr index 97246f05258f..a7a725883a92 100644 --- a/tests/ui/feature-gates/feature-gate-intrinsics.stderr +++ b/tests/ui/feature-gates/feature-gate-intrinsics.stderr @@ -1,36 +1,12 @@ -error[E0658]: the extern "rust-intrinsic" ABI is an implementation detail and perma-unstable - --> $DIR/feature-gate-intrinsics.rs:1:8 +error[E0658]: the `#[rustc_intrinsic]` attribute is used to declare intrinsics as function items + --> $DIR/feature-gate-intrinsics.rs:1:1 | -LL | extern "rust-intrinsic" { - | ^^^^^^^^^^^^^^^^ +LL | #[rustc_intrinsic] + | ^^^^^^^^^^^^^^^^^^ | = help: add `#![feature(intrinsics)]` 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 extern "rust-intrinsic" ABI is an implementation detail and perma-unstable - --> $DIR/feature-gate-intrinsics.rs:5:8 - | -LL | extern "rust-intrinsic" fn baz() {} - | ^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(intrinsics)]` 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 -error[E0093]: unrecognized intrinsic function: `bar` - --> $DIR/feature-gate-intrinsics.rs:2:5 - | -LL | fn bar(); - | ^^^^^^^^^ unrecognized intrinsic - | - = help: if you're adding an intrinsic, be sure to update `check_intrinsic_type` - -error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/feature-gate-intrinsics.rs:5:34 - | -LL | extern "rust-intrinsic" fn baz() {} - | ^^ - -error: aborting due to 4 previous errors - -Some errors have detailed explanations: E0093, E0658. -For more information about an error, try `rustc --explain E0093`. +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.rs b/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.rs index 2328798d74c3..44c0f1130f05 100644 --- a/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.rs +++ b/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.rs @@ -5,9 +5,9 @@ fn main() { let a = &[1, 2, 3]; println!("{}", { - extern "rust-intrinsic" { //~ ERROR "rust-intrinsic" ABI is an implementation detail - fn atomic_fence(); - } + #[rustc_intrinsic] //~ ERROR the `#[rustc_intrinsic]` attribute is used to declare intrinsics as function items + unsafe fn atomic_fence(); + atomic_fence(); //~ ERROR: is unsafe 42 }); diff --git a/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.stderr b/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.stderr index 86f88fdff5fc..aaaaeece67a8 100644 --- a/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.stderr +++ b/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.stderr @@ -1,13 +1,13 @@ -error[E0658]: the extern "rust-intrinsic" ABI is an implementation detail and perma-unstable - --> $DIR/feature-gated-feature-in-macro-arg.rs:8:16 +error[E0658]: the `#[rustc_intrinsic]` attribute is used to declare intrinsics as function items + --> $DIR/feature-gated-feature-in-macro-arg.rs:8:9 | -LL | extern "rust-intrinsic" { - | ^^^^^^^^^^^^^^^^ +LL | #[rustc_intrinsic] + | ^^^^^^^^^^^^^^^^^^ | = help: add `#![feature(intrinsics)]` 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[E0133]: call to unsafe function `main::atomic_fence` is unsafe and requires unsafe function or block +error[E0133]: call to unsafe function `atomic_fence` is unsafe and requires unsafe function or block --> $DIR/feature-gated-feature-in-macro-arg.rs:11:9 | LL | atomic_fence(); diff --git a/tests/ui/intrinsics/always-extern.rs b/tests/ui/intrinsics/always-extern.rs deleted file mode 100644 index 0afd8353455f..000000000000 --- a/tests/ui/intrinsics/always-extern.rs +++ /dev/null @@ -1,17 +0,0 @@ -#![feature(intrinsics)] - -trait Foo { - extern "rust-intrinsic" fn foo(&self); //~ ERROR intrinsic must -} - -impl Foo for () { - extern "rust-intrinsic" fn foo(&self) { //~ ERROR intrinsic must - } -} - -extern "rust-intrinsic" fn hello() {//~ ERROR intrinsic must - //~^ ERROR unrecognized intrinsic function: `hello` -} - -fn main() { -} diff --git a/tests/ui/intrinsics/always-extern.stderr b/tests/ui/intrinsics/always-extern.stderr deleted file mode 100644 index 44b889c6faac..000000000000 --- a/tests/ui/intrinsics/always-extern.stderr +++ /dev/null @@ -1,34 +0,0 @@ -error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/always-extern.rs:4:32 - | -LL | extern "rust-intrinsic" fn foo(&self); - | ^^^ - -error[E0093]: unrecognized intrinsic function: `hello` - --> $DIR/always-extern.rs:12:28 - | -LL | extern "rust-intrinsic" fn hello() { - | ^^^^^ unrecognized intrinsic - | - = help: if you're adding an intrinsic, be sure to update `check_intrinsic_type` - -error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/always-extern.rs:8:43 - | -LL | extern "rust-intrinsic" fn foo(&self) { - | ___________________________________________^ -LL | | } - | |_____^ - -error: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/always-extern.rs:12:36 - | -LL | extern "rust-intrinsic" fn hello() { - | ____________________________________^ -LL | | -LL | | } - | |_^ - -error: aborting due to 4 previous errors - -For more information about this error, try `rustc --explain E0093`. diff --git a/tests/ui/intrinsics/auxiliary/cci_intrinsic.rs b/tests/ui/intrinsics/auxiliary/cci_intrinsic.rs index f3b9d569ce3b..1014ac6f5609 100644 --- a/tests/ui/intrinsics/auxiliary/cci_intrinsic.rs +++ b/tests/ui/intrinsics/auxiliary/cci_intrinsic.rs @@ -1,14 +1,11 @@ #![feature(intrinsics)] pub mod rusti { - extern "rust-intrinsic" { - pub fn atomic_xchg_seqcst(dst: *mut T, src: T) -> T; - } + #[rustc_intrinsic] + pub unsafe fn atomic_xchg_seqcst(dst: *mut T, src: T) -> T; } #[inline(always)] pub fn atomic_xchg_seqcst(dst: *mut isize, src: isize) -> isize { - unsafe { - rusti::atomic_xchg_seqcst(dst, src) - } + unsafe { rusti::atomic_xchg_seqcst(dst, src) } } diff --git a/tests/ui/intrinsics/incorrect-read_via_copy-defn.rs b/tests/ui/intrinsics/incorrect-read_via_copy-defn.rs index 5520430e140b..e9f9270de87f 100644 --- a/tests/ui/intrinsics/incorrect-read_via_copy-defn.rs +++ b/tests/ui/intrinsics/incorrect-read_via_copy-defn.rs @@ -1,7 +1,8 @@ fn main() { read_via_copy(); + //~^ ERROR call to unsafe function `read_via_copy` is unsafe and requires unsafe function or block } -extern "rust-intrinsic" fn read_via_copy() {} -//~^ ERROR "rust-intrinsic" ABI is an implementation detail -//~| ERROR intrinsic must be in `extern "rust-intrinsic" { ... }` block +#[rustc_intrinsic] +//~^ ERROR the `#[rustc_intrinsic]` attribute is used to declare intrinsics as function items +unsafe fn read_via_copy() {} diff --git a/tests/ui/intrinsics/incorrect-read_via_copy-defn.stderr b/tests/ui/intrinsics/incorrect-read_via_copy-defn.stderr index c6682693f740..6711c77a11eb 100644 --- a/tests/ui/intrinsics/incorrect-read_via_copy-defn.stderr +++ b/tests/ui/intrinsics/incorrect-read_via_copy-defn.stderr @@ -1,18 +1,21 @@ -error[E0658]: the extern "rust-intrinsic" ABI is an implementation detail and perma-unstable - --> $DIR/incorrect-read_via_copy-defn.rs:5:8 +error[E0658]: the `#[rustc_intrinsic]` attribute is used to declare intrinsics as function items + --> $DIR/incorrect-read_via_copy-defn.rs:6:1 | -LL | extern "rust-intrinsic" fn read_via_copy() {} - | ^^^^^^^^^^^^^^^^ +LL | #[rustc_intrinsic] + | ^^^^^^^^^^^^^^^^^^ | = help: add `#![feature(intrinsics)]` 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: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/incorrect-read_via_copy-defn.rs:5:44 +error[E0133]: call to unsafe function `read_via_copy` is unsafe and requires unsafe function or block + --> $DIR/incorrect-read_via_copy-defn.rs:2:5 | -LL | extern "rust-intrinsic" fn read_via_copy() {} - | ^^ +LL | read_via_copy(); + | ^^^^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0133, E0658. +For more information about an error, try `rustc --explain E0133`. diff --git a/tests/ui/intrinsics/incorrect-transmute.rs b/tests/ui/intrinsics/incorrect-transmute.rs index 15d1ab939ed0..25fbc7a92ee7 100644 --- a/tests/ui/intrinsics/incorrect-transmute.rs +++ b/tests/ui/intrinsics/incorrect-transmute.rs @@ -1,7 +1,8 @@ fn main() { transmute(); // does not ICE + //~^ ERROR call to unsafe function `transmute` is unsafe and requires unsafe function or block } -extern "rust-intrinsic" fn transmute() {} -//~^ ERROR "rust-intrinsic" ABI is an implementation detail -//~| ERROR intrinsic must be in `extern "rust-intrinsic" { ... }` block +#[rustc_intrinsic] +//~^ ERROR the `#[rustc_intrinsic]` attribute is used to declare intrinsics as function items +unsafe fn transmute() {} diff --git a/tests/ui/intrinsics/incorrect-transmute.stderr b/tests/ui/intrinsics/incorrect-transmute.stderr index 99dfb9847ff2..6145a11c4ae0 100644 --- a/tests/ui/intrinsics/incorrect-transmute.stderr +++ b/tests/ui/intrinsics/incorrect-transmute.stderr @@ -1,18 +1,21 @@ -error[E0658]: the extern "rust-intrinsic" ABI is an implementation detail and perma-unstable - --> $DIR/incorrect-transmute.rs:5:8 +error[E0658]: the `#[rustc_intrinsic]` attribute is used to declare intrinsics as function items + --> $DIR/incorrect-transmute.rs:6:1 | -LL | extern "rust-intrinsic" fn transmute() {} - | ^^^^^^^^^^^^^^^^ +LL | #[rustc_intrinsic] + | ^^^^^^^^^^^^^^^^^^ | = help: add `#![feature(intrinsics)]` 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: intrinsic must be in `extern "rust-intrinsic" { ... }` block - --> $DIR/incorrect-transmute.rs:5:40 +error[E0133]: call to unsafe function `transmute` is unsafe and requires unsafe function or block + --> $DIR/incorrect-transmute.rs:2:5 | -LL | extern "rust-intrinsic" fn transmute() {} - | ^^ +LL | transmute(); // does not ICE + | ^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0133, E0658. +For more information about an error, try `rustc --explain E0133`. diff --git a/tests/ui/intrinsics/intrinsic-atomics.rs b/tests/ui/intrinsics/intrinsic-atomics.rs index 4ad267e3ddb3..6bc3f8d884db 100644 --- a/tests/ui/intrinsics/intrinsic-atomics.rs +++ b/tests/ui/intrinsics/intrinsic-atomics.rs @@ -2,33 +2,51 @@ #![feature(intrinsics)] mod rusti { - extern "rust-intrinsic" { - pub fn atomic_cxchg_seqcst_seqcst(dst: *mut T, old: T, src: T) -> (T, bool); - pub fn atomic_cxchg_acquire_acquire(dst: *mut T, old: T, src: T) -> (T, bool); - pub fn atomic_cxchg_release_relaxed(dst: *mut T, old: T, src: T) -> (T, bool); - pub fn atomic_cxchgweak_seqcst_seqcst(dst: *mut T, old: T, src: T) -> (T, bool); - pub fn atomic_cxchgweak_acquire_acquire(dst: *mut T, old: T, src: T) -> (T, bool); - pub fn atomic_cxchgweak_release_relaxed(dst: *mut T, old: T, src: T) -> (T, bool); + #[rustc_intrinsic] + pub unsafe fn atomic_cxchg_seqcst_seqcst(dst: *mut T, old: T, src: T) -> (T, bool); + #[rustc_intrinsic] + pub unsafe fn atomic_cxchg_acquire_acquire(dst: *mut T, old: T, src: T) -> (T, bool); + #[rustc_intrinsic] + pub unsafe fn atomic_cxchg_release_relaxed(dst: *mut T, old: T, src: T) -> (T, bool); - pub fn atomic_load_seqcst(src: *const T) -> T; - pub fn atomic_load_acquire(src: *const T) -> T; + #[rustc_intrinsic] + pub unsafe fn atomic_cxchgweak_seqcst_seqcst(dst: *mut T, old: T, src: T) -> (T, bool); + #[rustc_intrinsic] + pub unsafe fn atomic_cxchgweak_acquire_acquire(dst: *mut T, old: T, src: T) -> (T, bool); + #[rustc_intrinsic] + pub unsafe fn atomic_cxchgweak_release_relaxed(dst: *mut T, old: T, src: T) -> (T, bool); - pub fn atomic_store_seqcst(dst: *mut T, val: T); - pub fn atomic_store_release(dst: *mut T, val: T); + #[rustc_intrinsic] + pub unsafe fn atomic_load_seqcst(src: *const T) -> T; + #[rustc_intrinsic] + pub unsafe fn atomic_load_acquire(src: *const T) -> T; - pub fn atomic_xchg_seqcst(dst: *mut T, src: T) -> T; - pub fn atomic_xchg_acquire(dst: *mut T, src: T) -> T; - pub fn atomic_xchg_release(dst: *mut T, src: T) -> T; + #[rustc_intrinsic] + pub unsafe fn atomic_store_seqcst(dst: *mut T, val: T); + #[rustc_intrinsic] + pub unsafe fn atomic_store_release(dst: *mut T, val: T); - pub fn atomic_xadd_seqcst(dst: *mut T, src: T) -> T; - pub fn atomic_xadd_acquire(dst: *mut T, src: T) -> T; - pub fn atomic_xadd_release(dst: *mut T, src: T) -> T; + #[rustc_intrinsic] + pub unsafe fn atomic_xchg_seqcst(dst: *mut T, src: T) -> T; + #[rustc_intrinsic] + pub unsafe fn atomic_xchg_acquire(dst: *mut T, src: T) -> T; + #[rustc_intrinsic] + pub unsafe fn atomic_xchg_release(dst: *mut T, src: T) -> T; - pub fn atomic_xsub_seqcst(dst: *mut T, src: T) -> T; - pub fn atomic_xsub_acquire(dst: *mut T, src: T) -> T; - pub fn atomic_xsub_release(dst: *mut T, src: T) -> T; - } + #[rustc_intrinsic] + pub unsafe fn atomic_xadd_seqcst(dst: *mut T, src: T) -> T; + #[rustc_intrinsic] + pub unsafe fn atomic_xadd_acquire(dst: *mut T, src: T) -> T; + #[rustc_intrinsic] + pub unsafe fn atomic_xadd_release(dst: *mut T, src: T) -> T; + + #[rustc_intrinsic] + pub unsafe fn atomic_xsub_seqcst(dst: *mut T, src: T) -> T; + #[rustc_intrinsic] + pub unsafe fn atomic_xsub_acquire(dst: *mut T, src: T) -> T; + #[rustc_intrinsic] + pub unsafe fn atomic_xsub_release(dst: *mut T, src: T) -> T; } pub fn main() { @@ -39,9 +57,9 @@ pub fn main() { *x = 5; assert_eq!(rusti::atomic_load_acquire(&*x), 5); - rusti::atomic_store_seqcst(&mut *x,3); + rusti::atomic_store_seqcst(&mut *x, 3); assert_eq!(*x, 3); - rusti::atomic_store_release(&mut *x,1); + rusti::atomic_store_release(&mut *x, 1); assert_eq!(*x, 1); assert_eq!(rusti::atomic_cxchg_seqcst_seqcst(&mut *x, 1, 2), (1, true)); diff --git a/tests/ui/intrinsics/invalid-ABI-rust-intrinsic.rs b/tests/ui/intrinsics/invalid-ABI-rust-intrinsic.rs new file mode 100644 index 000000000000..4b777deb8b50 --- /dev/null +++ b/tests/ui/intrinsics/invalid-ABI-rust-intrinsic.rs @@ -0,0 +1,19 @@ +#![feature(intrinsics)] + +trait Foo { + extern "rust-intrinsic" fn foo(&self); //~ ERROR invalid ABI +} + +impl Foo for () { + extern "rust-intrinsic" fn foo(&self) { //~ ERROR invalid ABI + } +} + +extern "rust-intrinsic" fn hello() { //~ ERROR invalid ABI +} + +extern "rust-intrinsic" { + //~^ ERROR invalid ABI +} + +fn main() {} diff --git a/tests/ui/intrinsics/invalid-ABI-rust-intrinsic.stderr b/tests/ui/intrinsics/invalid-ABI-rust-intrinsic.stderr new file mode 100644 index 000000000000..fc8bf62915b1 --- /dev/null +++ b/tests/ui/intrinsics/invalid-ABI-rust-intrinsic.stderr @@ -0,0 +1,35 @@ +error[E0703]: invalid ABI: found `rust-intrinsic` + --> $DIR/invalid-ABI-rust-intrinsic.rs:4:12 + | +LL | extern "rust-intrinsic" fn foo(&self); + | ^^^^^^^^^^^^^^^^ invalid ABI + | + = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions + +error[E0703]: invalid ABI: found `rust-intrinsic` + --> $DIR/invalid-ABI-rust-intrinsic.rs:8:12 + | +LL | extern "rust-intrinsic" fn foo(&self) { + | ^^^^^^^^^^^^^^^^ invalid ABI + | + = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions + +error[E0703]: invalid ABI: found `rust-intrinsic` + --> $DIR/invalid-ABI-rust-intrinsic.rs:12:8 + | +LL | extern "rust-intrinsic" fn hello() { + | ^^^^^^^^^^^^^^^^ invalid ABI + | + = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions + +error[E0703]: invalid ABI: found `rust-intrinsic` + --> $DIR/invalid-ABI-rust-intrinsic.rs:15:8 + | +LL | extern "rust-intrinsic" { + | ^^^^^^^^^^^^^^^^ invalid ABI + | + = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0703`. diff --git a/tests/ui/intrinsics/issue-28575.rs b/tests/ui/intrinsics/issue-28575.rs index 141136d25b21..841bc45138a1 100644 --- a/tests/ui/intrinsics/issue-28575.rs +++ b/tests/ui/intrinsics/issue-28575.rs @@ -2,6 +2,7 @@ extern "C" { pub static FOO: extern "rust-intrinsic" fn(); + //~^ ERROR invalid ABI } fn main() { diff --git a/tests/ui/intrinsics/issue-28575.stderr b/tests/ui/intrinsics/issue-28575.stderr index 8a7816f231f7..09c52aa4c998 100644 --- a/tests/ui/intrinsics/issue-28575.stderr +++ b/tests/ui/intrinsics/issue-28575.stderr @@ -1,11 +1,20 @@ +error[E0703]: invalid ABI: found `rust-intrinsic` + --> $DIR/issue-28575.rs:4:28 + | +LL | pub static FOO: extern "rust-intrinsic" fn(); + | ^^^^^^^^^^^^^^^^ invalid ABI + | + = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions + error[E0133]: use of extern static is unsafe and requires unsafe function or block - --> $DIR/issue-28575.rs:8:5 + --> $DIR/issue-28575.rs:9:5 | LL | FOO() | ^^^ use of extern static | = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior -error: aborting due to 1 previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0133`. +Some errors have detailed explanations: E0133, E0703. +For more information about an error, try `rustc --explain E0133`. diff --git a/tests/ui/intrinsics/safe-intrinsic-mismatch.rs b/tests/ui/intrinsics/safe-intrinsic-mismatch.rs index 915a23b59053..4c301f9dbb09 100644 --- a/tests/ui/intrinsics/safe-intrinsic-mismatch.rs +++ b/tests/ui/intrinsics/safe-intrinsic-mismatch.rs @@ -1,13 +1,14 @@ #![feature(intrinsics)] #![feature(rustc_attrs)] -extern "rust-intrinsic" { - fn size_of() -> usize; //~ ERROR intrinsic safety mismatch - //~^ ERROR intrinsic safety mismatch -} +#[rustc_intrinsic] +unsafe fn size_of() -> usize; +//~^ ERROR intrinsic safety mismatch +//~| ERROR intrinsic has wrong type #[rustc_intrinsic] -const fn assume(_b: bool) {} //~ ERROR intrinsic safety mismatch +const fn assume(_b: bool) {} +//~^ ERROR intrinsic safety mismatch //~| ERROR intrinsic has wrong type #[rustc_intrinsic] diff --git a/tests/ui/intrinsics/safe-intrinsic-mismatch.stderr b/tests/ui/intrinsics/safe-intrinsic-mismatch.stderr index aa4f294232d2..04f6daeced2a 100644 --- a/tests/ui/intrinsics/safe-intrinsic-mismatch.stderr +++ b/tests/ui/intrinsics/safe-intrinsic-mismatch.stderr @@ -1,16 +1,17 @@ error: intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `size_of` - --> $DIR/safe-intrinsic-mismatch.rs:5:5 + --> $DIR/safe-intrinsic-mismatch.rs:5:1 | -LL | fn size_of() -> usize; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | unsafe fn size_of() -> usize; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `size_of` - --> $DIR/safe-intrinsic-mismatch.rs:5:5 +error[E0308]: intrinsic has wrong type + --> $DIR/safe-intrinsic-mismatch.rs:5:18 | -LL | fn size_of() -> usize; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | unsafe fn size_of() -> usize; + | ^^^ expected safe fn, found unsafe fn | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + = note: expected signature `fn() -> _` + found signature `unsafe fn() -> _` error: intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `assume` --> $DIR/safe-intrinsic-mismatch.rs:10:1 @@ -28,13 +29,13 @@ LL | const fn assume(_b: bool) {} found signature `fn(_)` error: intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `const_deallocate` - --> $DIR/safe-intrinsic-mismatch.rs:14:1 + --> $DIR/safe-intrinsic-mismatch.rs:15:1 | LL | const fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0308]: intrinsic has wrong type - --> $DIR/safe-intrinsic-mismatch.rs:14:26 + --> $DIR/safe-intrinsic-mismatch.rs:15:26 | LL | const fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {} | ^ expected unsafe fn, found safe fn diff --git a/tests/ui/lint/internal_features.rs b/tests/ui/lint/internal_features.rs index 32ce9540cb36..6456078a5c2f 100644 --- a/tests/ui/lint/internal_features.rs +++ b/tests/ui/lint/internal_features.rs @@ -4,8 +4,7 @@ //~^ ERROR: internal //~| ERROR: internal -extern "rust-intrinsic" { - fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize); -} +#[rustc_intrinsic] +unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize); fn main() {} diff --git a/tests/ui/print-calling-conventions.stdout b/tests/ui/print-calling-conventions.stdout index 539b2d5dee40..feee8cc3aa9c 100644 --- a/tests/ui/print-calling-conventions.stdout +++ b/tests/ui/print-calling-conventions.stdout @@ -19,7 +19,6 @@ riscv-interrupt-m riscv-interrupt-s rust-call rust-cold -rust-intrinsic stdcall stdcall-unwind system diff --git a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.stderr b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.stderr index 7b0fd9799919..e189012d15c9 100644 --- a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.stderr +++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.stderr @@ -26,6 +26,20 @@ help: `A` is dyn-incompatible, use `impl A` to return an opaque type, as long as LL | fn f(a: A) -> impl A; | ++++ +error: associated item referring to unboxed trait object for its own trait + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:4:13 + | +LL | trait A: Sized { + | - in this trait +LL | fn f(a: A) -> A; + | ^ ^ + | +help: you might have meant to use `Self` to refer to the implementing type + | +LL - fn f(a: A) -> A; +LL + fn f(a: Self) -> Self; + | + error[E0782]: expected a type, found a trait --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:10:13 | @@ -54,6 +68,20 @@ help: `B` is dyn-incompatible, use `impl B` to return an opaque type, as long as LL | fn f(b: B) -> impl B; | ++++ +error: associated item referring to unboxed trait object for its own trait + --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:10:13 + | +LL | trait B { + | - in this trait +LL | fn f(b: B) -> B; + | ^ ^ + | +help: you might have meant to use `Self` to refer to the implementing type + | +LL - fn f(b: B) -> B; +LL + fn f(b: Self) -> Self; + | + error[E0782]: expected a type, found a trait --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:16:20 | @@ -82,34 +110,6 @@ help: `C` is dyn-incompatible, use `impl C` to return an opaque type, as long as LL | fn f(&self, c: C) -> impl C; | ++++ -error: associated item referring to unboxed trait object for its own trait - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:4:13 - | -LL | trait A: Sized { - | - in this trait -LL | fn f(a: A) -> A; - | ^ ^ - | -help: you might have meant to use `Self` to refer to the implementing type - | -LL - fn f(a: A) -> A; -LL + fn f(a: Self) -> Self; - | - -error: associated item referring to unboxed trait object for its own trait - --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:10:13 - | -LL | trait B { - | - in this trait -LL | fn f(b: B) -> B; - | ^ ^ - | -help: you might have meant to use `Self` to refer to the implementing type - | -LL - fn f(b: B) -> B; -LL + fn f(b: Self) -> Self; - | - error: associated item referring to unboxed trait object for its own trait --> $DIR/dyn-incompatible-trait-should-use-self-2021-without-dyn.rs:16:20 | diff --git a/tests/ui/suggestions/issue-116434-2015.stderr b/tests/ui/suggestions/issue-116434-2015.stderr index e7b8cd2f101d..07a254432a28 100644 --- a/tests/ui/suggestions/issue-116434-2015.stderr +++ b/tests/ui/suggestions/issue-116434-2015.stderr @@ -12,19 +12,6 @@ help: if this is a dyn-compatible trait, use `dyn` LL | fn foo() -> dyn Clone; | +++ -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/issue-116434-2015.rs:18:20 - | -LL | fn handle() -> DbHandle; - | ^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see -help: if this is a dyn-compatible trait, use `dyn` - | -LL | fn handle() -> dyn DbHandle; - | +++ - warning: trait objects without an explicit `dyn` are deprecated --> $DIR/issue-116434-2015.rs:3:17 | @@ -53,6 +40,19 @@ help: there is an associated type with the same name LL | fn foo() -> Self::Clone; | ++++++ +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/issue-116434-2015.rs:18:20 + | +LL | fn handle() -> DbHandle; + | ^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +help: if this is a dyn-compatible trait, use `dyn` + | +LL | fn handle() -> dyn DbHandle; + | +++ + warning: trait objects without an explicit `dyn` are deprecated --> $DIR/issue-116434-2015.rs:18:20 | diff --git a/tests/ui/typeck/typeck_type_placeholder_item.stderr b/tests/ui/typeck/typeck_type_placeholder_item.stderr index 2a4a5a62ab4c..7184244f5dc9 100644 --- a/tests/ui/typeck/typeck_type_placeholder_item.stderr +++ b/tests/ui/typeck/typeck_type_placeholder_item.stderr @@ -439,6 +439,18 @@ LL | fn fn_test13(x: _) -> (i32, _) { (x, x) } | | not allowed in type signatures | help: replace with the correct return type: `(i32, i32)` +error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs + --> $DIR/typeck_type_placeholder_item.rs:154:21 + | +LL | struct BadStruct<_>(_); + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL - struct BadStruct<_>(_); +LL + struct BadStruct(T); + | + error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:140:31 | @@ -515,18 +527,6 @@ LL - fn assoc_fn_test3() -> _; LL + fn assoc_fn_test3() -> T; | -error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs - --> $DIR/typeck_type_placeholder_item.rs:154:21 - | -LL | struct BadStruct<_>(_); - | ^ not allowed in type signatures - | -help: use type parameters instead - | -LL - struct BadStruct<_>(_); -LL + struct BadStruct(T); - | - error[E0121]: the placeholder `_` is not allowed within types on item signatures for implementations --> $DIR/typeck_type_placeholder_item.rs:159:15 | diff --git a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.stderr b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.stderr index 3b4de0753af0..59eef0c63278 100644 --- a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.stderr +++ b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.stderr @@ -53,6 +53,12 @@ LL | trait Trait { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = 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: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:6:12 + | +LL | fn fnc(&self) -> Trait { + | ^^^^^^^^^^^^^^^^^^^^ + warning: trait objects without an explicit `dyn` are deprecated --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:6:44 | @@ -66,12 +72,6 @@ help: if this is a dyn-compatible trait, use `dyn` LL | fn fnc(&self) -> dyn Trait { | +++ -error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:6:12 - | -LL | fn fnc(&self) -> Trait { - | ^^^^^^^^^^^^^^^^^^^^ - warning: trait objects without an explicit `dyn` are deprecated --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:6:21 | From bf69443a9f0fa9b44aaec36c1c470ad22a325c2a Mon Sep 17 00:00:00 2001 From: HaeNoe Date: Thu, 3 Apr 2025 22:47:30 +0200 Subject: [PATCH 149/606] refactor: simplify function-info gathering --- compiler/rustc_builtin_macros/src/autodiff.rs | 67 +++++++------------ 1 file changed, 26 insertions(+), 41 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs index 287f0fdc516b..351413dea493 100644 --- a/compiler/rustc_builtin_macros/src/autodiff.rs +++ b/compiler/rustc_builtin_macros/src/autodiff.rs @@ -17,7 +17,7 @@ mod llvm_enzyme { use rustc_ast::visit::AssocCtxt::*; use rustc_ast::{ self as ast, AssocItemKind, BindingMode, ExprKind, FnRetTy, FnSig, Generics, ItemKind, - MetaItemInner, PatKind, QSelf, TyKind, + MetaItemInner, PatKind, QSelf, TyKind, Visibility, }; use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_span::{Ident, Span, Symbol, kw, sym}; @@ -72,6 +72,16 @@ mod llvm_enzyme { } } + // Get information about the function the macro is applied to + fn extract_item_info(iitem: &P) -> Option<(Visibility, FnSig, Ident)> { + match &iitem.kind { + ItemKind::Fn(box ast::Fn { sig, ident, .. }) => { + Some((iitem.vis.clone(), sig.clone(), ident.clone())) + } + _ => None, + } + } + pub(crate) fn from_ast( ecx: &mut ExtCtxt<'_>, meta_item: &ThinVec, @@ -201,49 +211,24 @@ mod llvm_enzyme { let dcx = ecx.sess.dcx(); // first get information about the annotable item: - let (sig, vis, primal) = match &item { - Annotatable::Item(iitem) => { - let (sig, ident) = match &iitem.kind { - ItemKind::Fn(box ast::Fn { sig, ident, .. }) => (sig, ident), - _ => { - dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() }); - return vec![item]; - } - }; - (sig.clone(), iitem.vis.clone(), ident.clone()) - } + let Some((vis, sig, primal)) = (match &item { + Annotatable::Item(iitem) => extract_item_info(iitem), + Annotatable::Stmt(stmt) => match &stmt.kind { + ast::StmtKind::Item(iitem) => extract_item_info(iitem), + _ => None, + }, Annotatable::AssocItem(assoc_item, Impl { of_trait: false }) => { - let (sig, ident) = match &assoc_item.kind { - ast::AssocItemKind::Fn(box ast::Fn { sig, ident, .. }) => (sig, ident), - _ => { - dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() }); - return vec![item]; + match &assoc_item.kind { + ast::AssocItemKind::Fn(box ast::Fn { sig, ident, .. }) => { + Some((assoc_item.vis.clone(), sig.clone(), ident.clone())) } - }; - (sig.clone(), assoc_item.vis.clone(), ident.clone()) - } - Annotatable::Stmt(stmt) => { - let (sig, vis, ident) = match &stmt.kind { - ast::StmtKind::Item(iitem) => match &iitem.kind { - ast::ItemKind::Fn(box ast::Fn { sig, ident, .. }) => { - (sig.clone(), iitem.vis.clone(), ident.clone()) - } - _ => { - dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() }); - return vec![item]; - } - }, - _ => { - dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() }); - return vec![item]; - } - }; - (sig, vis, ident) - } - _ => { - dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() }); - return vec![item]; + _ => None, + } } + _ => None, + }) else { + dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() }); + return vec![item]; }; let meta_item_vec: ThinVec = match meta_item.kind { From c8649a31a8eea7c4ed33d68d3fc3b71a2cffd119 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 6 Apr 2025 21:55:06 +0000 Subject: [PATCH 150/606] Stop calling source_span query in significant drop order code --- .../src/ty/significant_drop_order.rs | 22 +-- .../drop/drop-order-comparisons.e2021.stderr | 176 +++++------------- ...nt-if-let-rescope-gated.edition2021.stderr | 8 +- .../lint-if-let-rescope-with-macro.stderr | 8 +- tests/ui/drop/lint-if-let-rescope.stderr | 64 ++----- .../ui/drop/lint-tail-expr-drop-order.stderr | 84 +++------ ...expr_drop_order-on-coroutine-unwind.stderr | 18 +- 7 files changed, 100 insertions(+), 280 deletions(-) diff --git a/compiler/rustc_middle/src/ty/significant_drop_order.rs b/compiler/rustc_middle/src/ty/significant_drop_order.rs index 4881d611c128..ce4208f2c445 100644 --- a/compiler/rustc_middle/src/ty/significant_drop_order.rs +++ b/compiler/rustc_middle/src/ty/significant_drop_order.rs @@ -143,25 +143,11 @@ pub fn ty_dtor_span<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option { | ty::UnsafeBinder(_) => None, ty::Adt(adt_def, _) => { - let did = adt_def.did(); - let try_local_did_span = |did: DefId| { - if let Some(local) = did.as_local() { - tcx.source_span(local) - } else { - tcx.def_span(did) - } - }; - let dtor = if let Some(dtor) = tcx.adt_destructor(did) { - dtor.did - } else if let Some(dtor) = tcx.adt_async_destructor(did) { - return Some(tcx.source_span(dtor.impl_did)); + if let Some(dtor) = tcx.adt_destructor(adt_def.did()) { + Some(tcx.def_span(tcx.parent(dtor.did))) } else { - return Some(try_local_did_span(did)); - }; - let def_key = tcx.def_key(dtor); - let Some(parent_index) = def_key.parent else { return Some(try_local_did_span(dtor)) }; - let parent_did = DefId { index: parent_index, krate: dtor.krate }; - Some(try_local_did_span(parent_did)) + Some(tcx.def_span(adt_def.did())) + } } ty::Coroutine(did, _) | ty::CoroutineWitness(did, _) diff --git a/tests/ui/drop/drop-order-comparisons.e2021.stderr b/tests/ui/drop/drop-order-comparisons.e2021.stderr index 601b0a38412f..0717a8c1b9b9 100644 --- a/tests/ui/drop/drop-order-comparisons.e2021.stderr +++ b/tests/ui/drop/drop-order-comparisons.e2021.stderr @@ -31,39 +31,23 @@ LL | | }, e.mark(3), e.ok(4)); note: `#3` invokes this custom destructor --> $DIR/drop-order-comparisons.rs:571:1 | -LL | / impl<'b> Drop for LogDrop<'b> { -LL | | fn drop(&mut self) { -LL | | self.0.mark(self.1); -LL | | } -LL | | } - | |_^ +LL | impl<'b> Drop for LogDrop<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: `#1` invokes this custom destructor --> $DIR/drop-order-comparisons.rs:571:1 | -LL | / impl<'b> Drop for LogDrop<'b> { -LL | | fn drop(&mut self) { -LL | | self.0.mark(self.1); -LL | | } -LL | | } - | |_^ +LL | impl<'b> Drop for LogDrop<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: `_v` invokes this custom destructor --> $DIR/drop-order-comparisons.rs:571:1 | -LL | / impl<'b> Drop for LogDrop<'b> { -LL | | fn drop(&mut self) { -LL | | self.0.mark(self.1); -LL | | } -LL | | } - | |_^ +LL | impl<'b> Drop for LogDrop<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: `#2` invokes this custom destructor --> $DIR/drop-order-comparisons.rs:571:1 | -LL | / impl<'b> Drop for LogDrop<'b> { -LL | | fn drop(&mut self) { -LL | | self.0.mark(self.1); -LL | | } -LL | | } - | |_^ +LL | impl<'b> Drop for LogDrop<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages note: the lint level is defined here --> $DIR/drop-order-comparisons.rs:28:25 @@ -95,21 +79,13 @@ LL | | }, e.mark(1), e.ok(4)); note: `#2` invokes this custom destructor --> $DIR/drop-order-comparisons.rs:571:1 | -LL | / impl<'b> Drop for LogDrop<'b> { -LL | | fn drop(&mut self) { -LL | | self.0.mark(self.1); -LL | | } -LL | | } - | |_^ +LL | impl<'b> Drop for LogDrop<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: `#1` invokes this custom destructor --> $DIR/drop-order-comparisons.rs:571:1 | -LL | / impl<'b> Drop for LogDrop<'b> { -LL | | fn drop(&mut self) { -LL | | self.0.mark(self.1); -LL | | } -LL | | } - | |_^ +LL | impl<'b> Drop for LogDrop<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages warning: relative drop order changing in Rust 2024 @@ -135,21 +111,13 @@ LL | | }, e.mark(1), e.ok(4)); note: `#2` invokes this custom destructor --> $DIR/drop-order-comparisons.rs:571:1 | -LL | / impl<'b> Drop for LogDrop<'b> { -LL | | fn drop(&mut self) { -LL | | self.0.mark(self.1); -LL | | } -LL | | } - | |_^ +LL | impl<'b> Drop for LogDrop<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: `#1` invokes this custom destructor --> $DIR/drop-order-comparisons.rs:571:1 | -LL | / impl<'b> Drop for LogDrop<'b> { -LL | | fn drop(&mut self) { -LL | | self.0.mark(self.1); -LL | | } -LL | | } - | |_^ +LL | impl<'b> Drop for LogDrop<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages warning: relative drop order changing in Rust 2024 @@ -175,21 +143,13 @@ LL | | }, e.mark(2), e.ok(3)); note: `#2` invokes this custom destructor --> $DIR/drop-order-comparisons.rs:571:1 | -LL | / impl<'b> Drop for LogDrop<'b> { -LL | | fn drop(&mut self) { -LL | | self.0.mark(self.1); -LL | | } -LL | | } - | |_^ +LL | impl<'b> Drop for LogDrop<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: `#1` invokes this custom destructor --> $DIR/drop-order-comparisons.rs:571:1 | -LL | / impl<'b> Drop for LogDrop<'b> { -LL | | fn drop(&mut self) { -LL | | self.0.mark(self.1); -LL | | } -LL | | } - | |_^ +LL | impl<'b> Drop for LogDrop<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages warning: relative drop order changing in Rust 2024 @@ -215,21 +175,13 @@ LL | | }, e.mark(2), e.ok(3)); note: `#2` invokes this custom destructor --> $DIR/drop-order-comparisons.rs:571:1 | -LL | / impl<'b> Drop for LogDrop<'b> { -LL | | fn drop(&mut self) { -LL | | self.0.mark(self.1); -LL | | } -LL | | } - | |_^ +LL | impl<'b> Drop for LogDrop<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: `#1` invokes this custom destructor --> $DIR/drop-order-comparisons.rs:571:1 | -LL | / impl<'b> Drop for LogDrop<'b> { -LL | | fn drop(&mut self) { -LL | | self.0.mark(self.1); -LL | | } -LL | | } - | |_^ +LL | impl<'b> Drop for LogDrop<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages warning: `if let` assigns a shorter lifetime since Edition 2024 @@ -245,12 +197,8 @@ LL | _ = (if let Ok(_) = e.ok(4).as_ref() { note: value invokes this custom destructor --> $DIR/drop-order-comparisons.rs:571:1 | -LL | / impl<'b> Drop for LogDrop<'b> { -LL | | fn drop(&mut self) { -LL | | self.0.mark(self.1); -LL | | } -LL | | } - | |_^ +LL | impl<'b> Drop for LogDrop<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 --> $DIR/drop-order-comparisons.rs:127:5 | @@ -279,12 +227,8 @@ LL | _ = (if let Ok(_) = e.err(4).as_ref() {} else { note: value invokes this custom destructor --> $DIR/drop-order-comparisons.rs:571:1 | -LL | / impl<'b> Drop for LogDrop<'b> { -LL | | fn drop(&mut self) { -LL | | self.0.mark(self.1); -LL | | } -LL | | } - | |_^ +LL | impl<'b> Drop for LogDrop<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 --> $DIR/drop-order-comparisons.rs:145:44 | @@ -312,12 +256,8 @@ LL | if let Ok(_) = e.err(4).as_ref() {} else { note: value invokes this custom destructor --> $DIR/drop-order-comparisons.rs:571:1 | -LL | / impl<'b> Drop for LogDrop<'b> { -LL | | fn drop(&mut self) { -LL | | self.0.mark(self.1); -LL | | } -LL | | } - | |_^ +LL | impl<'b> Drop for LogDrop<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 --> $DIR/drop-order-comparisons.rs:247:43 | @@ -345,12 +285,8 @@ LL | if let true = e.err(9).is_ok() {} else { note: value invokes this custom destructor --> $DIR/drop-order-comparisons.rs:571:1 | -LL | / impl<'b> Drop for LogDrop<'b> { -LL | | fn drop(&mut self) { -LL | | self.0.mark(self.1); -LL | | } -LL | | } - | |_^ +LL | impl<'b> Drop for LogDrop<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 --> $DIR/drop-order-comparisons.rs:352:41 | @@ -378,12 +314,8 @@ LL | if let Ok(_v) = e.err(8) {} else { note: value invokes this custom destructor --> $DIR/drop-order-comparisons.rs:571:1 | -LL | / impl<'b> Drop for LogDrop<'b> { -LL | | fn drop(&mut self) { -LL | | self.0.mark(self.1); -LL | | } -LL | | } - | |_^ +LL | impl<'b> Drop for LogDrop<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 --> $DIR/drop-order-comparisons.rs:355:35 | @@ -411,12 +343,8 @@ LL | if let Ok(_) = e.err(7) {} else { note: value invokes this custom destructor --> $DIR/drop-order-comparisons.rs:571:1 | -LL | / impl<'b> Drop for LogDrop<'b> { -LL | | fn drop(&mut self) { -LL | | self.0.mark(self.1); -LL | | } -LL | | } - | |_^ +LL | impl<'b> Drop for LogDrop<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 --> $DIR/drop-order-comparisons.rs:358:34 | @@ -444,12 +372,8 @@ LL | if let Ok(_) = e.err(6).as_ref() {} else { note: value invokes this custom destructor --> $DIR/drop-order-comparisons.rs:571:1 | -LL | / impl<'b> Drop for LogDrop<'b> { -LL | | fn drop(&mut self) { -LL | | self.0.mark(self.1); -LL | | } -LL | | } - | |_^ +LL | impl<'b> Drop for LogDrop<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 --> $DIR/drop-order-comparisons.rs:361:43 | @@ -477,12 +401,8 @@ LL | if let Ok(_v) = e.err(5) {} else { note: value invokes this custom destructor --> $DIR/drop-order-comparisons.rs:571:1 | -LL | / impl<'b> Drop for LogDrop<'b> { -LL | | fn drop(&mut self) { -LL | | self.0.mark(self.1); -LL | | } -LL | | } - | |_^ +LL | impl<'b> Drop for LogDrop<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 --> $DIR/drop-order-comparisons.rs:365:35 | @@ -510,12 +430,8 @@ LL | if let Ok(_) = e.err(4) {} else { note: value invokes this custom destructor --> $DIR/drop-order-comparisons.rs:571:1 | -LL | / impl<'b> Drop for LogDrop<'b> { -LL | | fn drop(&mut self) { -LL | | self.0.mark(self.1); -LL | | } -LL | | } - | |_^ +LL | impl<'b> Drop for LogDrop<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 --> $DIR/drop-order-comparisons.rs:368:34 | @@ -543,12 +459,8 @@ LL | if let Ok(_) = e.err(4).as_ref() {} else { note: value invokes this custom destructor --> $DIR/drop-order-comparisons.rs:571:1 | -LL | / impl<'b> Drop for LogDrop<'b> { -LL | | fn drop(&mut self) { -LL | | self.0.mark(self.1); -LL | | } -LL | | } - | |_^ +LL | impl<'b> Drop for LogDrop<'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 --> $DIR/drop-order-comparisons.rs:404:43 | diff --git a/tests/ui/drop/lint-if-let-rescope-gated.edition2021.stderr b/tests/ui/drop/lint-if-let-rescope-gated.edition2021.stderr index 070ba1c6a4cf..0d6974d516b6 100644 --- a/tests/ui/drop/lint-if-let-rescope-gated.edition2021.stderr +++ b/tests/ui/drop/lint-if-let-rescope-gated.edition2021.stderr @@ -11,12 +11,8 @@ LL | if let Some(_value) = Droppy.get() { note: value invokes this custom destructor --> $DIR/lint-if-let-rescope-gated.rs:14:1 | -LL | / impl Drop for Droppy { -LL | | fn drop(&mut self) { -LL | | println!("dropped"); -LL | | } -LL | | } - | |_^ +LL | impl Drop for Droppy { + | ^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 --> $DIR/lint-if-let-rescope-gated.rs:30:5 | diff --git a/tests/ui/drop/lint-if-let-rescope-with-macro.stderr b/tests/ui/drop/lint-if-let-rescope-with-macro.stderr index f1ca0ba57de4..a0afb8eddb53 100644 --- a/tests/ui/drop/lint-if-let-rescope-with-macro.stderr +++ b/tests/ui/drop/lint-if-let-rescope-with-macro.stderr @@ -18,12 +18,8 @@ LL | | }; note: value invokes this custom destructor --> $DIR/lint-if-let-rescope-with-macro.rs:22:1 | -LL | / impl Drop for Droppy { -LL | | fn drop(&mut self) { -LL | | println!("dropped"); -LL | | } -LL | | } - | |_^ +LL | impl Drop for Droppy { + | ^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 --> $DIR/lint-if-let-rescope-with-macro.rs:12:38 | diff --git a/tests/ui/drop/lint-if-let-rescope.stderr b/tests/ui/drop/lint-if-let-rescope.stderr index e95ec8fcea7f..ca2416efcb1a 100644 --- a/tests/ui/drop/lint-if-let-rescope.stderr +++ b/tests/ui/drop/lint-if-let-rescope.stderr @@ -11,12 +11,8 @@ LL | if let Some(_value) = droppy().get() { note: value invokes this custom destructor --> $DIR/lint-if-let-rescope.rs:11:1 | -LL | / impl Drop for Droppy { -LL | | fn drop(&mut self) { -LL | | println!("dropped"); -LL | | } -LL | | } - | |_^ +LL | impl Drop for Droppy { + | ^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 --> $DIR/lint-if-let-rescope.rs:32:5 | @@ -55,21 +51,13 @@ LL | } else if let Some(_value) = droppy().get() { note: value invokes this custom destructor --> $DIR/lint-if-let-rescope.rs:11:1 | -LL | / impl Drop for Droppy { -LL | | fn drop(&mut self) { -LL | | println!("dropped"); -LL | | } -LL | | } - | |_^ +LL | impl Drop for Droppy { + | ^^^^^^^^^^^^^^^^^^^^ note: value invokes this custom destructor --> $DIR/lint-if-let-rescope.rs:11:1 | -LL | / impl Drop for Droppy { -LL | | fn drop(&mut self) { -LL | | println!("dropped"); -LL | | } -LL | | } - | |_^ +LL | impl Drop for Droppy { + | ^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 --> $DIR/lint-if-let-rescope.rs:42:5 | @@ -105,12 +93,8 @@ LL | } else if let Some(_value) = droppy().get() { note: value invokes this custom destructor --> $DIR/lint-if-let-rescope.rs:11:1 | -LL | / impl Drop for Droppy { -LL | | fn drop(&mut self) { -LL | | println!("dropped"); -LL | | } -LL | | } - | |_^ +LL | impl Drop for Droppy { + | ^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 --> $DIR/lint-if-let-rescope.rs:54:5 | @@ -140,12 +124,8 @@ LL | if let Some(1) = { if let Some(_value) = Droppy.get() { Some(1) } else note: value invokes this custom destructor --> $DIR/lint-if-let-rescope.rs:11:1 | -LL | / impl Drop for Droppy { -LL | | fn drop(&mut self) { -LL | | println!("dropped"); -LL | | } -LL | | } - | |_^ +LL | impl Drop for Droppy { + | ^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 --> $DIR/lint-if-let-rescope.rs:58:69 | @@ -170,12 +150,8 @@ LL | if (if let Some(_value) = droppy().get() { true } else { false }) { note: value invokes this custom destructor --> $DIR/lint-if-let-rescope.rs:11:1 | -LL | / impl Drop for Droppy { -LL | | fn drop(&mut self) { -LL | | println!("dropped"); -LL | | } -LL | | } - | |_^ +LL | impl Drop for Droppy { + | ^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 --> $DIR/lint-if-let-rescope.rs:72:53 | @@ -200,12 +176,8 @@ LL | } else if (((if let Some(_value) = droppy().get() { true } else { false note: value invokes this custom destructor --> $DIR/lint-if-let-rescope.rs:11:1 | -LL | / impl Drop for Droppy { -LL | | fn drop(&mut self) { -LL | | println!("dropped"); -LL | | } -LL | | } - | |_^ +LL | impl Drop for Droppy { + | ^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 --> $DIR/lint-if-let-rescope.rs:78:62 | @@ -230,12 +202,8 @@ LL | while (if let Some(_value) = droppy().get() { false } else { true }) { note: value invokes this custom destructor --> $DIR/lint-if-let-rescope.rs:11:1 | -LL | / impl Drop for Droppy { -LL | | fn drop(&mut self) { -LL | | println!("dropped"); -LL | | } -LL | | } - | |_^ +LL | impl Drop for Droppy { + | ^^^^^^^^^^^^^^^^^^^^ help: the value is now dropped here in Edition 2024 --> $DIR/lint-if-let-rescope.rs:90:57 | diff --git a/tests/ui/drop/lint-tail-expr-drop-order.stderr b/tests/ui/drop/lint-tail-expr-drop-order.stderr index 6ff9b7c12681..e124e9874d0b 100644 --- a/tests/ui/drop/lint-tail-expr-drop-order.stderr +++ b/tests/ui/drop/lint-tail-expr-drop-order.stderr @@ -21,17 +21,13 @@ LL | } note: `#1` invokes this custom destructor --> $DIR/lint-tail-expr-drop-order.rs:10:1 | -LL | / impl Drop for LoudDropper { -... | -LL | | } - | |_^ +LL | impl Drop for LoudDropper { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: `x` invokes this custom destructor --> $DIR/lint-tail-expr-drop-order.rs:10:1 | -LL | / impl Drop for LoudDropper { -... | -LL | | } - | |_^ +LL | impl Drop for LoudDropper { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages note: the lint level is defined here --> $DIR/lint-tail-expr-drop-order.rs:6:9 @@ -62,17 +58,13 @@ LL | } note: `#1` invokes this custom destructor --> $DIR/lint-tail-expr-drop-order.rs:10:1 | -LL | / impl Drop for LoudDropper { -... | -LL | | } - | |_^ +LL | impl Drop for LoudDropper { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: `x` invokes this custom destructor --> $DIR/lint-tail-expr-drop-order.rs:10:1 | -LL | / impl Drop for LoudDropper { -... | -LL | | } - | |_^ +LL | impl Drop for LoudDropper { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages error: relative drop order changing in Rust 2024 @@ -98,17 +90,13 @@ LL | } note: `#1` invokes this custom destructor --> $DIR/lint-tail-expr-drop-order.rs:10:1 | -LL | / impl Drop for LoudDropper { -... | -LL | | } - | |_^ +LL | impl Drop for LoudDropper { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: `x` invokes this custom destructor --> $DIR/lint-tail-expr-drop-order.rs:10:1 | -LL | / impl Drop for LoudDropper { -... | -LL | | } - | |_^ +LL | impl Drop for LoudDropper { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages error: relative drop order changing in Rust 2024 @@ -134,10 +122,8 @@ LL | } note: `#1` invokes this custom destructor --> $DIR/lint-tail-expr-drop-order.rs:10:1 | -LL | / impl Drop for LoudDropper { -... | -LL | | } - | |_^ +LL | impl Drop for LoudDropper { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages error: relative drop order changing in Rust 2024 @@ -185,17 +171,13 @@ LL | } note: `#1` invokes this custom destructor --> $DIR/lint-tail-expr-drop-order.rs:10:1 | -LL | / impl Drop for LoudDropper { -... | -LL | | } - | |_^ +LL | impl Drop for LoudDropper { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: `x` invokes this custom destructor --> $DIR/lint-tail-expr-drop-order.rs:10:1 | -LL | / impl Drop for LoudDropper { -... | -LL | | } - | |_^ +LL | impl Drop for LoudDropper { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages error: relative drop order changing in Rust 2024 @@ -221,23 +203,13 @@ LL | } note: `#1` invokes this custom destructor --> $DIR/lint-tail-expr-drop-order.rs:193:5 | -LL | / impl Drop for LoudDropper3 { -LL | | -LL | | fn drop(&mut self) { -LL | | println!("loud drop"); -LL | | } -LL | | } - | |_____^ +LL | impl Drop for LoudDropper3 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ note: `x` invokes this custom destructor --> $DIR/lint-tail-expr-drop-order.rs:205:5 | -LL | / impl Drop for LoudDropper2 { -LL | | -LL | | fn drop(&mut self) { -LL | | println!("loud drop"); -LL | | } -LL | | } - | |_____^ +LL | impl Drop for LoudDropper2 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages error: relative drop order changing in Rust 2024 @@ -263,17 +235,13 @@ LL | )); note: `#1` invokes this custom destructor --> $DIR/lint-tail-expr-drop-order.rs:10:1 | -LL | / impl Drop for LoudDropper { -... | -LL | | } - | |_^ +LL | impl Drop for LoudDropper { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: `_x` invokes this custom destructor --> $DIR/lint-tail-expr-drop-order.rs:10:1 | -LL | / impl Drop for LoudDropper { -... | -LL | | } - | |_^ +LL | impl Drop for LoudDropper { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages error: aborting due to 8 previous errors diff --git a/tests/ui/drop/tail_expr_drop_order-on-coroutine-unwind.stderr b/tests/ui/drop/tail_expr_drop_order-on-coroutine-unwind.stderr index b0f971dd5cec..7bf452e2496c 100644 --- a/tests/ui/drop/tail_expr_drop_order-on-coroutine-unwind.stderr +++ b/tests/ui/drop/tail_expr_drop_order-on-coroutine-unwind.stderr @@ -27,24 +27,18 @@ LL | } note: `#2` invokes this custom destructor --> $DIR/tail_expr_drop_order-on-coroutine-unwind.rs:9:1 | -LL | / impl std::ops::Drop for Drop { -LL | | fn drop(&mut self) {} -LL | | } - | |_^ +LL | impl std::ops::Drop for Drop { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: `#1` invokes this custom destructor --> $DIR/tail_expr_drop_order-on-coroutine-unwind.rs:9:1 | -LL | / impl std::ops::Drop for Drop { -LL | | fn drop(&mut self) {} -LL | | } - | |_^ +LL | impl std::ops::Drop for Drop { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: `e` invokes this custom destructor --> $DIR/tail_expr_drop_order-on-coroutine-unwind.rs:9:1 | -LL | / impl std::ops::Drop for Drop { -LL | | fn drop(&mut self) {} -LL | | } - | |_^ +LL | impl std::ops::Drop for Drop { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages note: the lint level is defined here --> $DIR/tail_expr_drop_order-on-coroutine-unwind.rs:6:9 From ee07e3f83f5c2e87c1ce19f2472bc7c622ecebcf Mon Sep 17 00:00:00 2001 From: Caleb Cartwright Date: Sun, 6 Apr 2025 14:45:48 -0500 Subject: [PATCH 151/606] doc(style): add let-chain rules --- src/doc/style-guide/src/expressions.md | 78 ++++++++++++++++++++++++-- 1 file changed, 72 insertions(+), 6 deletions(-) diff --git a/src/doc/style-guide/src/expressions.md b/src/doc/style-guide/src/expressions.md index 12037b5992ec..031e59d86e1d 100644 --- a/src/doc/style-guide/src/expressions.md +++ b/src/doc/style-guide/src/expressions.md @@ -521,8 +521,11 @@ self.pre_comment.as_ref().map_or( ## Control flow expressions -This section covers `if`, `if let`, `loop`, `while`, `while let`, and `for` -expressions. +This section covers `for` and `loop` expressions, as well as `if` and `while` +expressions with their sub-expression variants. This includes those with a +single `let` sub-expression (i.e. `if let` and `while let`) +as well as "let-chains": those with one or more `let` sub-expressions and +one or more bool-type conditions (i.e. `if a && let Some(b) = c`). Put the keyword, any initial clauses, and the opening brace of the block all on a single line, if they fit. Apply the usual rules for [block @@ -548,10 +551,11 @@ if let ... { } ``` -If the control line needs to be broken, prefer to break before the `=` in `* -let` expressions and before `in` in a `for` expression; block-indent the -following line. If the control line is broken for any reason, put the opening -brace on its own line, not indented. Examples: +If the control line needs to be broken, then prefer breaking after the `=` for any +`let` sub-expression in an `if` or `while` expression that does not fit, +and before `in` in a `for` expression; the following line should be block indented. +If the control line is broken for any reason, then the opening brace should be on its +own line and not indented. Examples: ```rust while let Some(foo) @@ -572,6 +576,68 @@ if a_long_expression { ... } + +if let Some(a) = b + && another_long_expression + && a_third_long_expression +{ + // ... +} + +if let Some(relatively_long_thing) + = a_long_expression + && another_long_expression + && a_third_long_expression +{ + // ... +} + +if some_expr + && another_long_expression + && let Some(relatively_long_thing) = + a_long_long_long_long_long_long_really_reallllllllllyyyyyyy_long_expression + && a_third_long_expression +{ + // ... +} +``` + +A let-chain control line is allowed to be formatted on a single line provided +it only consists of two clauses, with the first, left-hand side operand being a literal or an +`ident` (which can optionally be preceded by any number of unary prefix operators), +and the second, right-hand side operand being a single-line `let` clause. Otherwise, +the control line must be broken and formatted according to the above rules. For example: + +```rust +if a && let Some(b) = foo() { + // ... +} + +if true && let Some(b) = foo() { + // ... +} + +let operator = if !from_hir_call && let Some(p) = parent { + // ... +}; + +if let Some(b) = foo() + && a +{ + // .. +} + +if foo() + && let Some(b) = bar +{ + // ... +} + +if gen_pos != GenericArgPosition::Type + && let Some(b) = gen_args.bindings.first() +{ + // .. +} ``` Where the initial clause spans multiple lines and ends with one or more closing From d111aa87f1588d2ac0c282baa1b7d70e87231d52 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 7 Apr 2025 05:03:35 +0000 Subject: [PATCH 152/606] Trivial tweaks to stop tracking source span directly --- .../rustc_borrowck/src/region_infer/mod.rs | 32 +++++++++++-------- compiler/rustc_hir_typeck/src/closure.rs | 2 +- compiler/rustc_hir_typeck/src/lib.rs | 2 +- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index a80d74d9e370..5756a5e7c7c5 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -22,7 +22,7 @@ use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, UniverseIndex, use rustc_mir_dataflow::points::DenseLocationMap; use rustc_span::hygiene::DesugaringKind; use rustc_span::{DUMMY_SP, Span}; -use tracing::{debug, instrument, trace}; +use tracing::{Level, debug, enabled, instrument, trace}; use crate::BorrowckInferCtxt; use crate::constraints::graph::{self, NormalConstraintGraph, RegionGraph}; @@ -327,11 +327,13 @@ fn sccs_info<'tcx>(infcx: &BorrowckInferCtxt<'tcx>, sccs: &ConstraintSccs) { let mut var_to_origin_sorted = var_to_origin.clone().into_iter().collect::>(); var_to_origin_sorted.sort_by_key(|vto| vto.0); - let mut reg_vars_to_origins_str = "region variables to origins:\n".to_string(); - for (reg_var, origin) in var_to_origin_sorted.into_iter() { - reg_vars_to_origins_str.push_str(&format!("{reg_var:?}: {origin:?}\n")); + if enabled!(Level::DEBUG) { + let mut reg_vars_to_origins_str = "region variables to origins:\n".to_string(); + for (reg_var, origin) in var_to_origin_sorted.into_iter() { + reg_vars_to_origins_str.push_str(&format!("{reg_var:?}: {origin:?}\n")); + } + debug!("{}", reg_vars_to_origins_str); } - debug!("{}", reg_vars_to_origins_str); let num_components = sccs.num_sccs(); let mut components = vec![FxIndexSet::default(); num_components]; @@ -342,16 +344,18 @@ fn sccs_info<'tcx>(infcx: &BorrowckInferCtxt<'tcx>, sccs: &ConstraintSccs) { components[scc_idx.as_usize()].insert((reg_var, *origin)); } - let mut components_str = "strongly connected components:".to_string(); - for (scc_idx, reg_vars_origins) in components.iter().enumerate() { - let regions_info = reg_vars_origins.clone().into_iter().collect::>(); - components_str.push_str(&format!( - "{:?}: {:?},\n)", - ConstraintSccIndex::from_usize(scc_idx), - regions_info, - )) + if enabled!(Level::DEBUG) { + let mut components_str = "strongly connected components:".to_string(); + for (scc_idx, reg_vars_origins) in components.iter().enumerate() { + let regions_info = reg_vars_origins.clone().into_iter().collect::>(); + components_str.push_str(&format!( + "{:?}: {:?},\n)", + ConstraintSccIndex::from_usize(scc_idx), + regions_info, + )) + } + debug!("{}", components_str); } - debug!("{}", components_str); // calculate the best representative for each component let components_representatives = components diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 467ca26e7eab..b8968b58769a 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -970,7 +970,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.typeck_results.borrow_mut().user_provided_sigs.insert(expr_def_id, c_result); // Normalize only after registering in `user_provided_sigs`. - self.normalize(self.tcx.hir_span(hir_id), result) + self.normalize(self.tcx.def_span(expr_def_id), result) } /// Invoked when we are translating the coroutine that results diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 46389668de7c..1d86ff14471a 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -117,7 +117,7 @@ fn typeck_with_inspect<'tcx>( let id = tcx.local_def_id_to_hir_id(def_id); let node = tcx.hir_node(id); - let span = tcx.hir_span(id); + let span = tcx.def_span(def_id); // Figure out what primary body this item has. let body_id = node.body_id().unwrap_or_else(|| { From c51c448fae5123b0dfb56fcd7c69251f85f2a73b Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 7 Apr 2025 05:07:02 +0000 Subject: [PATCH 153/606] More trivial tweaks --- compiler/rustc_hir_analysis/src/check/region.rs | 11 ++++------- compiler/rustc_hir_typeck/src/demand.rs | 5 +---- compiler/rustc_passes/src/liveness.rs | 2 +- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index cf66ab708bb9..6b504c0d6725 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -446,14 +446,11 @@ fn resolve_expr<'tcx>( // Mark this expr's scope and all parent scopes as containing `yield`. let mut scope = Scope { local_id: expr.hir_id.local_id, data: ScopeData::Node }; loop { - let span = match expr.kind { - hir::ExprKind::Yield(expr, hir::YieldSource::Await { .. }) => { - expr.span.shrink_to_hi().to(expr.span) - } - _ => expr.span, + let data = YieldData { + span: expr.span, + expr_and_pat_count: visitor.expr_and_pat_count, + source: *source, }; - let data = - YieldData { span, expr_and_pat_count: visitor.expr_and_pat_count, source: *source }; match visitor.scope_tree.yield_in_scope.get_mut(&scope) { Some(yields) => yields.push(data), None => { diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index b845e2190ef0..fec459954107 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -865,10 +865,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // `&'name Ty` -> `&'name mut Ty` or `&Ty` -> `&mut Ty` vec![( ty_ref.1.ty.span.shrink_to_lo(), - format!( - "{}mut ", - if ty_ref.0.ident.span.lo() == ty_ref.0.ident.span.hi() { "" } else { " " }, - ), + format!("{}mut ", if ty_ref.0.ident.span.is_empty() { "" } else { " " },), )] }; sugg.extend([ diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index ed70d9ee91f5..d79e9263f613 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -1655,7 +1655,7 @@ impl<'tcx> Liveness<'_, 'tcx> { // `&'name Ty` -> `&'name mut Ty` or `&Ty` -> `&mut Ty` Some(mut_ty.ty.span.shrink_to_lo()) }; - let pre = if lt.ident.span.lo() == lt.ident.span.hi() { "" } else { " " }; + let pre = if lt.ident.span.is_empty() { "" } else { " " }; Some(errors::UnusedAssignSuggestion { ty_span, pre, From fa06e723adb8ad4a4cc995b2fccfccc7caf80bff Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Mon, 7 Apr 2025 05:17:09 +0000 Subject: [PATCH 154/606] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index bc254efcd30c..a6f295108797 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -d5b4c2e4f19b6d7037371cdaecc3cc2c701c68df +25a615bf829b9f6d6f22da537e3851043f92e5f2 From 253da2f22b8d67e764b72c15d2541c1ca2bc9b3d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 7 Apr 2025 05:37:25 +0000 Subject: [PATCH 155/606] Don't call Span.with_parent on the good path in has_stashed_diagnostic --- compiler/rustc_errors/src/lib.rs | 70 ++++++++++++++++++++------------ 1 file changed, 44 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index f5f7618285e1..75bb0e8e7b43 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -589,7 +589,8 @@ struct DiagCtxtInner { /// add more information). All stashed diagnostics must be emitted with /// `emit_stashed_diagnostics` by the time the `DiagCtxtInner` is dropped, /// otherwise an assertion failure will occur. - stashed_diagnostics: FxIndexMap<(Span, StashKey), (DiagInner, Option)>, + stashed_diagnostics: + FxIndexMap)>>, future_breakage_diagnostics: Vec, @@ -912,8 +913,12 @@ impl<'a> DiagCtxtHandle<'a> { // FIXME(Centril, #69537): Consider reintroducing panic on overwriting a stashed diagnostic // if/when we have a more robust macro-friendly replacement for `(span, key)` as a key. // See the PR for a discussion. - let key = (span.with_parent(None), key); - self.inner.borrow_mut().stashed_diagnostics.insert(key, (diag, guar)); + self.inner + .borrow_mut() + .stashed_diagnostics + .entry(key) + .or_default() + .insert(span.with_parent(None), (diag, guar)); guar } @@ -922,9 +927,10 @@ impl<'a> DiagCtxtHandle<'a> { /// and [`StashKey`] as the key. Panics if the found diagnostic is an /// error. pub fn steal_non_err(self, span: Span, key: StashKey) -> Option> { - let key = (span.with_parent(None), key); // FIXME(#120456) - is `swap_remove` correct? - let (diag, guar) = self.inner.borrow_mut().stashed_diagnostics.swap_remove(&key)?; + let (diag, guar) = self.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then( + |stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)), + )?; assert!(!diag.is_error()); assert!(guar.is_none()); Some(Diag::new_diagnostic(self, diag)) @@ -943,9 +949,10 @@ impl<'a> DiagCtxtHandle<'a> { where F: FnMut(&mut Diag<'_>), { - let key = (span.with_parent(None), key); // FIXME(#120456) - is `swap_remove` correct? - let err = self.inner.borrow_mut().stashed_diagnostics.swap_remove(&key); + let err = self.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then( + |stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)), + ); err.map(|(err, guar)| { // The use of `::` is safe because level is `Level::Error`. assert_eq!(err.level, Error); @@ -966,9 +973,10 @@ impl<'a> DiagCtxtHandle<'a> { key: StashKey, new_err: Diag<'_>, ) -> ErrorGuaranteed { - let key = (span.with_parent(None), key); // FIXME(#120456) - is `swap_remove` correct? - let old_err = self.inner.borrow_mut().stashed_diagnostics.swap_remove(&key); + let old_err = self.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then( + |stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)), + ); match old_err { Some((old_err, guar)) => { assert_eq!(old_err.level, Error); @@ -983,7 +991,14 @@ impl<'a> DiagCtxtHandle<'a> { } pub fn has_stashed_diagnostic(&self, span: Span, key: StashKey) -> bool { - self.inner.borrow().stashed_diagnostics.get(&(span.with_parent(None), key)).is_some() + let inner = self.inner.borrow(); + if let Some(stashed_diagnostics) = inner.stashed_diagnostics.get(&key) + && !stashed_diagnostics.is_empty() + { + stashed_diagnostics.contains_key(&span.with_parent(None)) + } else { + false + } } /// Emit all stashed diagnostics. @@ -997,7 +1012,11 @@ impl<'a> DiagCtxtHandle<'a> { let inner = self.inner.borrow(); inner.err_guars.len() + inner.lint_err_guars.len() - + inner.stashed_diagnostics.values().filter(|(_diag, guar)| guar.is_some()).count() + + inner + .stashed_diagnostics + .values() + .map(|a| a.values().filter(|(_, guar)| guar.is_some()).count()) + .sum::() } /// This excludes lint errors and delayed bugs. Unless absolutely @@ -1486,16 +1505,18 @@ impl DiagCtxtInner { fn emit_stashed_diagnostics(&mut self) -> Option { let mut guar = None; let has_errors = !self.err_guars.is_empty(); - for (_, (diag, _guar)) in std::mem::take(&mut self.stashed_diagnostics).into_iter() { - if !diag.is_error() { - // Unless they're forced, don't flush stashed warnings when - // there are errors, to avoid causing warning overload. The - // stash would've been stolen already if it were important. - if !diag.is_force_warn() && has_errors { - continue; + for (_, stashed_diagnostics) in std::mem::take(&mut self.stashed_diagnostics).into_iter() { + for (_, (diag, _guar)) in stashed_diagnostics { + if !diag.is_error() { + // Unless they're forced, don't flush stashed warnings when + // there are errors, to avoid causing warning overload. The + // stash would've been stolen already if it were important. + if !diag.is_force_warn() && has_errors { + continue; + } } + guar = guar.or(self.emit_diagnostic(diag, None)); } - guar = guar.or(self.emit_diagnostic(diag, None)); } guar } @@ -1688,6 +1709,7 @@ impl DiagCtxtInner { if let Some((_diag, guar)) = self .stashed_diagnostics .values() + .flat_map(|stashed_diagnostics| stashed_diagnostics.values()) .find(|(diag, guar)| guar.is_some() && diag.is_lint.is_none()) { *guar @@ -1700,13 +1722,9 @@ impl DiagCtxtInner { fn has_errors(&self) -> Option { self.err_guars.get(0).copied().or_else(|| self.lint_err_guars.get(0).copied()).or_else( || { - if let Some((_diag, guar)) = - self.stashed_diagnostics.values().find(|(_diag, guar)| guar.is_some()) - { - *guar - } else { - None - } + self.stashed_diagnostics.values().find_map(|stashed_diagnostics| { + stashed_diagnostics.values().find_map(|(_, guar)| *guar) + }) }, ) } From 4c5babdab59e07630ac064301dd24c334363d00b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 7 Apr 2025 08:26:44 +0200 Subject: [PATCH 156/606] big-allocs benchmark: use up less of the address space on 32bit --- src/tools/miri/bench-cargo-miri/big-allocs/src/main.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/tools/miri/bench-cargo-miri/big-allocs/src/main.rs b/src/tools/miri/bench-cargo-miri/big-allocs/src/main.rs index a1c1708cf3ba..5b807ac3df1f 100644 --- a/src/tools/miri/bench-cargo-miri/big-allocs/src/main.rs +++ b/src/tools/miri/bench-cargo-miri/big-allocs/src/main.rs @@ -7,7 +7,10 @@ fn main() { // We can't use too big of an allocation or this code will encounter an allocation failure in // CI. Since the allocation can't be huge, we need to do a few iterations so that the effect // we're trying to measure is clearly visible above the interpreter's startup time. - for _ in 0..10 { + // FIXME (https://github.com/rust-lang/miri/issues/4253): On 32bit targets, we can run out of + // usable addresses if we don't reuse, leading to random test failures. + let count = if cfg!(target_pointer_width = "32") { 8 } else { 12 }; + for _ in 0..count { drop(Vec::::with_capacity(512 * 1024 * 1024)); } } From 6ac0120a60d543d9557d2affd334ba02704c9fb8 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 7 Apr 2025 08:35:17 +0200 Subject: [PATCH 157/606] reduce the error tolerance to match algebraic and fast-math operations --- src/tools/miri/tests/pass/float.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/tools/miri/tests/pass/float.rs b/src/tools/miri/tests/pass/float.rs index 05ac5e82b564..cd60b6bd563d 100644 --- a/src/tools/miri/tests/pass/float.rs +++ b/src/tools/miri/tests/pass/float.rs @@ -38,8 +38,9 @@ macro_rules! assert_approx_eq { }}; ($a:expr, $b: expr) => { - // accept up to 64ULP (16ULP for host floats and 16ULP for miri artificial error and 32 for any rounding errors) - assert_approx_eq!($a, $b, 64); + // accept up to 12ULP (4ULP for host floats and 4ULP for miri artificial error and 4 for any additional effects + // due to having multiple error sources. + assert_approx_eq!($a, $b, 12); }; } From c8306650ba792d1415b9f67da883ed46a39ea4cd Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sat, 5 Apr 2025 09:05:11 +0300 Subject: [PATCH 158/606] enable in-tree std on some runners Signed-off-by: onur-ozkan --- src/bootstrap/defaults/bootstrap.dist.toml | 2 ++ src/ci/citool/tests/test-jobs.yml | 2 +- src/ci/docker/host-x86_64/mingw-check/Dockerfile | 1 + src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile | 1 + src/ci/github-actions/jobs.yml | 2 +- 5 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/defaults/bootstrap.dist.toml b/src/bootstrap/defaults/bootstrap.dist.toml index 7b381b416ca8..f2cbe512b5e4 100644 --- a/src/bootstrap/defaults/bootstrap.dist.toml +++ b/src/bootstrap/defaults/bootstrap.dist.toml @@ -7,6 +7,8 @@ test-stage = 2 doc-stage = 2 # When compiling from source, you usually want all tools. extended = true +# Use libtest built from the source tree instead of the precompiled one from stage 0. +compiletest-use-stage0-libtest = false # Most users installing from source want to build all parts of the project from source. [llvm] diff --git a/src/ci/citool/tests/test-jobs.yml b/src/ci/citool/tests/test-jobs.yml index 3593b3f7df63..d81be88b7087 100644 --- a/src/ci/citool/tests/test-jobs.yml +++ b/src/ci/citool/tests/test-jobs.yml @@ -27,7 +27,7 @@ runners: <<: *base-job envs: env-x86_64-apple-tests: &env-x86_64-apple-tests - SCRIPT: ./x.py --stage 2 test --skip tests/ui --skip tests/rustdoc -- --exact + SCRIPT: ./x.py check compiletest --set build.compiletest-use-stage0-libtest=true && ./x.py --stage 2 test --skip tests/ui --skip tests/rustdoc -- --exact RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 # Ensure that host tooling is tested on our minimum supported macOS version. diff --git a/src/ci/docker/host-x86_64/mingw-check/Dockerfile b/src/ci/docker/host-x86_64/mingw-check/Dockerfile index 8bb7116c3ec5..418408e9242a 100644 --- a/src/ci/docker/host-x86_64/mingw-check/Dockerfile +++ b/src/ci/docker/host-x86_64/mingw-check/Dockerfile @@ -47,6 +47,7 @@ COPY host-x86_64/mingw-check/validate-error-codes.sh /scripts/ ENV SCRIPT \ python3 ../x.py check --stage 0 --set build.optimized-compiler-builtins=false core alloc std --target=aarch64-unknown-linux-gnu,i686-pc-windows-msvc,i686-unknown-linux-gnu,x86_64-apple-darwin,x86_64-pc-windows-gnu,x86_64-pc-windows-msvc && \ /scripts/check-default-config-profiles.sh && \ + python3 ../x.py check compiletest --set build.compiletest-use-stage0-libtest=true && \ python3 ../x.py check --target=x86_64-pc-windows-gnu --host=x86_64-pc-windows-gnu && \ python3 ../x.py clippy ci && \ python3 ../x.py build --stage 0 src/tools/build-manifest && \ diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile index 89806634c6c2..05c90af78073 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile @@ -101,4 +101,5 @@ COPY scripts/shared.sh /scripts/ # the local version of the package is different than the one used by the CI. ENV SCRIPT /tmp/checktools.sh ../x.py && \ npm install browser-ui-test@$(head -n 1 /tmp/browser-ui-test.version) --unsafe-perm=true && \ + python3 ../x.py check compiletest --set build.compiletest-use-stage0-libtest=true && \ python3 ../x.py test tests/rustdoc-gui --stage 2 --test-args "'--jobs 1'" diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 26ff17e423b5..751b42d49fbc 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -58,7 +58,7 @@ runners: <<: *base-job envs: env-x86_64-apple-tests: &env-x86_64-apple-tests - SCRIPT: ./x.py --stage 2 test --skip tests/ui --skip tests/rustdoc -- --exact + SCRIPT: ./x.py check compiletest --set build.compiletest-use-stage0-libtest=true && ./x.py --stage 2 test --skip tests/ui --skip tests/rustdoc -- --exact RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 # Ensure that host tooling is tested on our minimum supported macOS version. From 4322b6e97d6ad438c6c9ef1ea92e8ba00c056d9c Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 31 Mar 2025 12:51:16 +1100 Subject: [PATCH 159/606] coverage: Build the CGU's global file table as late as possible --- .../src/coverageinfo/mapgen.rs | 146 ++++++++++-------- .../src/coverageinfo/mapgen/covfun.rs | 42 +++-- .../src/coverageinfo/mapgen/unused.rs | 4 +- 3 files changed, 107 insertions(+), 85 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index 5e62ce285dd8..55b1e728b70d 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -53,13 +53,6 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) { None => return, }; - // The order of entries in this global file table needs to be deterministic, - // and ideally should also be independent of the details of stable-hashing, - // because coverage tests snapshots (`.cov-map`) can observe the order and - // would need to be re-blessed if it changes. As long as those requirements - // are satisfied, the order can be arbitrary. - let mut global_file_table = GlobalFileTable::new(); - let mut covfun_records = instances_used .iter() .copied() @@ -67,17 +60,13 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) { // order that doesn't depend on the stable-hash-based order in which // instances were visited during codegen. .sorted_by_cached_key(|&instance| tcx.symbol_name(instance).name) - .filter_map(|instance| prepare_covfun_record(tcx, &mut global_file_table, instance, true)) + .filter_map(|instance| prepare_covfun_record(tcx, instance, true)) .collect::>(); // In a single designated CGU, also prepare covfun records for functions // in this crate that were instrumented for coverage, but are unused. if cx.codegen_unit.is_code_coverage_dead_code_cgu() { - unused::prepare_covfun_records_for_unused_functions( - cx, - &mut global_file_table, - &mut covfun_records, - ); + unused::prepare_covfun_records_for_unused_functions(cx, &mut covfun_records); } // If there are no covfun records for this CGU, don't generate a covmap record. @@ -89,68 +78,88 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) { return; } - // Encode all filenames referenced by coverage mappings in this CGU. - let filenames_buffer = global_file_table.make_filenames_buffer(tcx); - // The `llvm-cov` tool uses this hash to associate each covfun record with - // its corresponding filenames table, since the final binary will typically - // contain multiple covmap records from different compilation units. - let filenames_hash = llvm_cov::hash_bytes(&filenames_buffer); + // Prepare the global file table for this CGU, containing all paths needed + // by one or more covfun records. + let global_file_table = + GlobalFileTable::build(tcx, covfun_records.iter().flat_map(|c| c.all_source_files())); for covfun in &covfun_records { - covfun::generate_covfun_record(cx, filenames_hash, covfun) + covfun::generate_covfun_record(cx, &global_file_table, covfun) } // Generate the coverage map header, which contains the filenames used by // this CGU's coverage mappings, and store it in a well-known global. // (This is skipped if we returned early due to having no covfun records.) - generate_covmap_record(cx, covmap_version, &filenames_buffer); + generate_covmap_record(cx, covmap_version, &global_file_table.filenames_buffer); } -/// Maps "global" (per-CGU) file ID numbers to their underlying source files. +/// Maps "global" (per-CGU) file ID numbers to their underlying source file paths. +#[derive(Debug)] struct GlobalFileTable { /// This "raw" table doesn't include the working dir, so a file's /// global ID is its index in this set **plus one**. - raw_file_table: FxIndexMap>, + raw_file_table: FxIndexMap, + + /// The file table in encoded form (possibly compressed), which can be + /// included directly in this CGU's `__llvm_covmap` record. + filenames_buffer: Vec, + + /// Truncated hash of the bytes in `filenames_buffer`. + /// + /// The `llvm-cov` tool uses this hash to associate each covfun record with + /// its corresponding filenames table, since the final binary will typically + /// contain multiple covmap records from different compilation units. + filenames_hash: u64, } impl GlobalFileTable { - fn new() -> Self { - Self { raw_file_table: FxIndexMap::default() } - } + /// Builds a "global file table" for this CGU, mapping numeric IDs to + /// path strings. + fn build<'a>(tcx: TyCtxt<'_>, all_files: impl Iterator) -> Self { + let mut raw_file_table = FxIndexMap::default(); - fn global_file_id_for_file(&mut self, file: &Arc) -> GlobalFileId { - // Ensure the given file has a table entry, and get its index. - let entry = self.raw_file_table.entry(file.stable_id); - let raw_id = entry.index(); - entry.or_insert_with(|| Arc::clone(file)); + for file in all_files { + raw_file_table.entry(file.stable_id).or_insert_with(|| { + file.name + .for_scope(tcx.sess, RemapPathScopeComponents::MACRO) + .to_string_lossy() + .into_owned() + }); + } - // The raw file table doesn't include an entry for the working dir - // (which has ID 0), so add 1 to get the correct ID. - GlobalFileId::from_usize(raw_id + 1) - } + // FIXME(Zalathar): Consider sorting the file table here, but maybe + // only after adding filename support to coverage-dump, so that the + // table order isn't directly visible in `.coverage-map` snapshots. - fn make_filenames_buffer(&self, tcx: TyCtxt<'_>) -> Vec { - let mut table = Vec::with_capacity(self.raw_file_table.len() + 1); + let mut table = Vec::with_capacity(raw_file_table.len() + 1); - // LLVM Coverage Mapping Format version 6 (zero-based encoded as 5) - // requires setting the first filename to the compilation directory. - // Since rustc generates coverage maps with relative paths, the - // compilation directory can be combined with the relative paths - // to get absolute paths, if needed. - table.push( - tcx.sess - .opts - .working_dir - .for_scope(tcx.sess, RemapPathScopeComponents::MACRO) - .to_string_lossy(), - ); + // Since version 6 of the LLVM coverage mapping format, the first entry + // in the global file table is treated as a base directory, used to + // resolve any other entries that are stored as relative paths. + let base_dir = tcx + .sess + .opts + .working_dir + .for_scope(tcx.sess, RemapPathScopeComponents::MACRO) + .to_string_lossy(); + table.push(base_dir.as_ref()); // Add the regular entries after the base directory. - table.extend(self.raw_file_table.values().map(|file| { - file.name.for_scope(tcx.sess, RemapPathScopeComponents::MACRO).to_string_lossy() - })); + table.extend(raw_file_table.values().map(|name| name.as_str())); - llvm_cov::write_filenames_to_buffer(&table) + // Encode the file table into a buffer, and get the hash of its encoded + // bytes, so that we can embed that hash in `__llvm_covfun` records. + let filenames_buffer = llvm_cov::write_filenames_to_buffer(&table); + let filenames_hash = llvm_cov::hash_bytes(&filenames_buffer); + + Self { raw_file_table, filenames_buffer, filenames_hash } + } + + fn get_existing_id(&self, file: &SourceFile) -> Option { + let raw_id = self.raw_file_table.get_index_of(&file.stable_id)?; + // The raw file table doesn't include an entry for the base dir + // (which has ID 0), so add 1 to get the correct ID. + Some(GlobalFileId::from_usize(raw_id + 1)) } } @@ -166,26 +175,31 @@ rustc_index::newtype_index! { struct LocalFileId {} } -/// Holds a mapping from "local" (per-function) file IDs to "global" (per-CGU) -/// file IDs. +/// Holds a mapping from "local" (per-function) file IDs to their corresponding +/// source files. #[derive(Debug, Default)] struct VirtualFileMapping { - local_to_global: IndexVec, - global_to_local: FxIndexMap, + local_file_table: IndexVec>, } impl VirtualFileMapping { - fn local_id_for_global(&mut self, global_file_id: GlobalFileId) -> LocalFileId { - *self - .global_to_local - .entry(global_file_id) - .or_insert_with(|| self.local_to_global.push(global_file_id)) + fn push_file(&mut self, source_file: &Arc) -> LocalFileId { + self.local_file_table.push(Arc::clone(source_file)) } - fn to_vec(&self) -> Vec { - // This clone could be avoided by transmuting `&[GlobalFileId]` to `&[u32]`, - // but it isn't hot or expensive enough to justify the extra unsafety. - self.local_to_global.iter().map(|&global| GlobalFileId::as_u32(global)).collect() + /// Resolves all of the filenames in this local file mapping to a list of + /// global file IDs in its CGU, for inclusion in this function's + /// `__llvm_covfun` record. + /// + /// The global file IDs are returned as `u32` to make FFI easier. + fn resolve_all(&self, global_file_table: &GlobalFileTable) -> Option> { + self.local_file_table + .iter() + .map(|file| try { + let id = global_file_table.get_existing_id(file)?; + GlobalFileId::as_u32(id) + }) + .collect::>>() } } diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs index 93419c2caad2..7bdbc6859529 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs @@ -5,6 +5,7 @@ //! [^win]: On Windows the section name is `.lcovfun`. use std::ffi::CString; +use std::sync::Arc; use rustc_abi::Align; use rustc_codegen_ssa::traits::{ @@ -15,7 +16,7 @@ use rustc_middle::mir::coverage::{ MappingKind, Op, }; use rustc_middle::ty::{Instance, TyCtxt}; -use rustc_span::Span; +use rustc_span::{SourceFile, Span}; use rustc_target::spec::HasTargetSpec; use tracing::debug; @@ -37,9 +38,16 @@ pub(crate) struct CovfunRecord<'tcx> { regions: ffi::Regions, } +impl<'tcx> CovfunRecord<'tcx> { + /// Iterator that yields all source files referred to by this function's + /// coverage mappings. Used to build the global file table for the CGU. + pub(crate) fn all_source_files(&self) -> impl Iterator { + self.virtual_file_mapping.local_file_table.iter().map(Arc::as_ref) + } +} + pub(crate) fn prepare_covfun_record<'tcx>( tcx: TyCtxt<'tcx>, - global_file_table: &mut GlobalFileTable, instance: Instance<'tcx>, is_used: bool, ) -> Option> { @@ -57,7 +65,7 @@ pub(crate) fn prepare_covfun_record<'tcx>( regions: ffi::Regions::default(), }; - fill_region_tables(tcx, global_file_table, fn_cov_info, ids_info, &mut covfun); + fill_region_tables(tcx, fn_cov_info, ids_info, &mut covfun); if covfun.regions.has_no_regions() { debug!(?covfun, "function has no mappings to embed; skipping"); @@ -92,7 +100,6 @@ fn prepare_expressions(ids_info: &CoverageIdsInfo) -> Vec( tcx: TyCtxt<'tcx>, - global_file_table: &mut GlobalFileTable, fn_cov_info: &'tcx FunctionCoverageInfo, ids_info: &'tcx CoverageIdsInfo, covfun: &mut CovfunRecord<'tcx>, @@ -106,11 +113,7 @@ fn fill_region_tables<'tcx>( }; let source_file = source_map.lookup_source_file(first_span.lo()); - // Look up the global file ID for that file. - let global_file_id = global_file_table.global_file_id_for_file(&source_file); - - // Associate that global file ID with a local file ID for this function. - let local_file_id = covfun.virtual_file_mapping.local_id_for_global(global_file_id); + let local_file_id = covfun.virtual_file_mapping.push_file(&source_file); // In rare cases, _all_ of a function's spans are discarded, and coverage // codegen needs to handle that gracefully to avoid #133606. @@ -179,7 +182,7 @@ fn fill_region_tables<'tcx>( /// as a global variable in the `__llvm_covfun` section. pub(crate) fn generate_covfun_record<'tcx>( cx: &CodegenCx<'_, 'tcx>, - filenames_hash: u64, + global_file_table: &GlobalFileTable, covfun: &CovfunRecord<'tcx>, ) { let &CovfunRecord { @@ -191,12 +194,19 @@ pub(crate) fn generate_covfun_record<'tcx>( ref regions, } = covfun; + let Some(local_file_table) = virtual_file_mapping.resolve_all(global_file_table) else { + debug_assert!( + false, + "all local files should be present in the global file table: \ + global_file_table = {global_file_table:?}, \ + virtual_file_mapping = {virtual_file_mapping:?}" + ); + return; + }; + // Encode the function's coverage mappings into a buffer. - let coverage_mapping_buffer = llvm_cov::write_function_mappings_to_buffer( - &virtual_file_mapping.to_vec(), - expressions, - regions, - ); + let coverage_mapping_buffer = + llvm_cov::write_function_mappings_to_buffer(&local_file_table, expressions, regions); // A covfun record consists of four target-endian integers, followed by the // encoded mapping data in bytes. Note that the length field is 32 bits. @@ -209,7 +219,7 @@ pub(crate) fn generate_covfun_record<'tcx>( cx.const_u64(func_name_hash), cx.const_u32(coverage_mapping_buffer.len() as u32), cx.const_u64(source_hash), - cx.const_u64(filenames_hash), + cx.const_u64(global_file_table.filenames_hash), cx.const_bytes(&coverage_mapping_buffer), ], // This struct needs to be packed, so that the 32-bit length field diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/unused.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/unused.rs index ab030f5b6152..68f60f169b5b 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/unused.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/unused.rs @@ -7,7 +7,6 @@ use rustc_middle::ty::{self, TyCtxt}; use rustc_span::def_id::DefIdSet; use crate::common::CodegenCx; -use crate::coverageinfo::mapgen::GlobalFileTable; use crate::coverageinfo::mapgen::covfun::{CovfunRecord, prepare_covfun_record}; use crate::llvm; @@ -21,7 +20,6 @@ use crate::llvm; /// its embedded coverage data. pub(crate) fn prepare_covfun_records_for_unused_functions<'tcx>( cx: &CodegenCx<'_, 'tcx>, - global_file_table: &mut GlobalFileTable, covfun_records: &mut Vec>, ) { assert!(cx.codegen_unit.is_code_coverage_dead_code_cgu()); @@ -33,7 +31,7 @@ pub(crate) fn prepare_covfun_records_for_unused_functions<'tcx>( // Try to create a covfun record for each unused function. let mut name_globals = Vec::with_capacity(unused_instances.len()); covfun_records.extend(unused_instances.into_iter().filter_map(|unused| try { - let record = prepare_covfun_record(cx.tcx, global_file_table, unused.instance, false)?; + let record = prepare_covfun_record(cx.tcx, unused.instance, false)?; // If successful, also store its symbol name in a global constant. name_globals.push(cx.const_str(unused.symbol_name.name).0); record From 5f7fa4f97587092a851bfb23f8620ed0919c96c3 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Mon, 7 Apr 2025 15:16:45 +0800 Subject: [PATCH 160/606] rustc-perf: update to `c0f3b53c8e5de87714d18a5f42998859302ae03a` --- src/tools/rustc-perf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rustc-perf b/src/tools/rustc-perf index e22e08623a34..c0f3b53c8e5d 160000 --- a/src/tools/rustc-perf +++ b/src/tools/rustc-perf @@ -1 +1 @@ -Subproject commit e22e08623a349b13a3296971a05394d44f769744 +Subproject commit c0f3b53c8e5de87714d18a5f42998859302ae03a From c3999f13203f06fa69cd7673ad55e077e755a19e Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Mon, 7 Apr 2025 15:19:17 +0800 Subject: [PATCH 161/606] tidy: remove `instant` dep exclusion --- src/tools/tidy/src/deps.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 682ab4875a12..1a57d2b182ac 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -164,7 +164,6 @@ const EXCEPTIONS_RUSTC_PERF: ExceptionList = &[ ("brotli-decompressor", "BSD-3-Clause/MIT"), ("encoding_rs", "(Apache-2.0 OR MIT) AND BSD-3-Clause"), ("inferno", "CDDL-1.0"), - ("instant", "BSD-3-Clause"), ("ring", NON_STANDARD_LICENSE), // see EXCEPTIONS_NON_STANDARD_LICENSE_DEPS for more. ("ryu", "Apache-2.0 OR BSL-1.0"), ("snap", "BSD-3-Clause"), From 15e1a6676cdaac8442959990806d33a40949aaca Mon Sep 17 00:00:00 2001 From: Eduard Stefes Date: Mon, 31 Mar 2025 09:39:28 +0200 Subject: [PATCH 162/606] Use -C target-cpu=z13 on s390x vector test The default s390x cpu(z10) does not have vector support. Setting target-cpu at least to z13 enables vectorisation for s390x architecture and makes the tests pass. --- tests/codegen/dont-shuffle-bswaps.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/codegen/dont-shuffle-bswaps.rs b/tests/codegen/dont-shuffle-bswaps.rs index e100474f606f..c1dab2bc2953 100644 --- a/tests/codegen/dont-shuffle-bswaps.rs +++ b/tests/codegen/dont-shuffle-bswaps.rs @@ -1,8 +1,11 @@ -//@ revisions: OPT2 OPT3 +//@ revisions: OPT2 OPT3 OPT3_S390X //@[OPT2] compile-flags: -Copt-level=2 //@[OPT3] compile-flags: -C opt-level=3 // some targets don't do the opt we are looking for //@[OPT3] only-64bit +//@[OPT3] ignore-s390x +//@[OPT3_S390X] compile-flags: -C opt-level=3 -C target-cpu=z13 +//@[OPT3_S390X] only-s390x #![crate_type = "lib"] #![no_std] @@ -17,6 +20,10 @@ // OPT3-NEXT: call <8 x i16> @llvm.bswap // OPT3-NEXT: store <8 x i16> // OPT3-NEXT: ret void +// OPT3_S390X: load <8 x i16> +// OPT3_S390X-NEXT: call <8 x i16> @llvm.bswap +// OPT3_S390X-NEXT: store <8 x i16> +// OPT3_S390X-NEXT: ret void #[no_mangle] pub fn convert(value: [u16; 8]) -> [u8; 16] { #[cfg(target_endian = "little")] From 1862b311f67dce3d503a5d09dca249cace03967e Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 7 Apr 2025 12:18:56 +0200 Subject: [PATCH 163/606] rm `RegionInferenceContext::var_infos` we already track this info in the `definitions` field --- .../src/diagnostics/bound_region_errors.rs | 4 ++-- compiler/rustc_borrowck/src/diagnostics/mod.rs | 9 +++------ compiler/rustc_borrowck/src/polonius/dump.rs | 4 ++-- compiler/rustc_borrowck/src/region_infer/mod.rs | 5 +---- 4 files changed, 8 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs index aa968a1e40f3..e12441182186 100644 --- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs @@ -406,8 +406,8 @@ impl<'tcx> TypeOpInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> { // started MIR borrowchecking with, so the region // constraints have already been taken. Use the data from // our `mbcx` instead. - |vid| mbcx.regioncx.var_infos[vid].origin, - |vid| mbcx.regioncx.var_infos[vid].universe, + |vid| RegionVariableOrigin::Nll(mbcx.regioncx.definitions[vid].origin), + |vid| mbcx.regioncx.definitions[vid].universe, ) } } diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 899e145c2c04..07555956f994 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -8,9 +8,7 @@ use rustc_errors::{Applicability, Diag, EmissionGuarantee, MultiSpan, listify}; use rustc_hir::def::{CtorKind, Namespace}; use rustc_hir::{self as hir, CoroutineKind, LangItem}; use rustc_index::IndexSlice; -use rustc_infer::infer::{ - BoundRegionConversionTime, NllRegionVariableOrigin, RegionVariableOrigin, -}; +use rustc_infer::infer::{BoundRegionConversionTime, NllRegionVariableOrigin}; use rustc_infer::traits::SelectionError; use rustc_middle::bug; use rustc_middle::mir::{ @@ -633,9 +631,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { ) { let predicate_span = path.iter().find_map(|constraint| { let outlived = constraint.sub; - if let Some(origin) = self.regioncx.var_infos.get(outlived) - && let RegionVariableOrigin::Nll(NllRegionVariableOrigin::Placeholder(_)) = - origin.origin + if let Some(origin) = self.regioncx.definitions.get(outlived) + && let NllRegionVariableOrigin::Placeholder(_) = origin.origin && let ConstraintCategory::Predicate(span) = constraint.category { Some(span) diff --git a/compiler/rustc_borrowck/src/polonius/dump.rs b/compiler/rustc_borrowck/src/polonius/dump.rs index aa64a7c4e2a6..6f3b599d26f1 100644 --- a/compiler/rustc_borrowck/src/polonius/dump.rs +++ b/compiler/rustc_borrowck/src/polonius/dump.rs @@ -334,7 +334,7 @@ fn emit_mermaid_nll_regions<'tcx>( writeln!(out, "flowchart TD")?; // Emit the region nodes. - for region in regioncx.var_infos.indices() { + for region in regioncx.definitions.indices() { write!(out, "{}[\"", region.as_usize())?; render_region(region, regioncx, out)?; writeln!(out, "\"]")?; @@ -387,7 +387,7 @@ fn emit_mermaid_nll_sccs<'tcx>( // Gather and emit the SCC nodes. let mut nodes_per_scc: IndexVec<_, _> = regioncx.constraint_sccs().all_sccs().map(|_| Vec::new()).collect(); - for region in regioncx.var_infos.indices() { + for region in regioncx.definitions.indices() { let scc = regioncx.constraint_sccs().scc(region); nodes_per_scc[scc].push(region); } diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index a80d74d9e370..3ec93e0587ef 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -139,13 +139,11 @@ impl RegionTracker { } pub struct RegionInferenceContext<'tcx> { - pub var_infos: VarInfos, - /// Contains the definition for every region variable. Region /// variables are identified by their index (`RegionVid`). The /// definition contains information about where the region came /// from as well as its final inferred value. - definitions: IndexVec>, + pub(crate) definitions: IndexVec>, /// The liveness constraints added to each region. For most /// regions, these start out empty and steadily grow, though for @@ -449,7 +447,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { Rc::new(member_constraints.into_mapped(|r| constraint_sccs.scc(r))); let mut result = Self { - var_infos, definitions, liveness_constraints, constraints, From 1a4863421bcae3ca1d50490256f4cd9236dc49cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Mon, 7 Apr 2025 12:52:09 +0200 Subject: [PATCH 164/606] Sort job duration changes by absolute duration It was supposed to be like this from the start, but I forgot to apply the `abs` operation, as I got sidetracked with how to actually compare floats... --- src/ci/citool/src/analysis.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ci/citool/src/analysis.rs b/src/ci/citool/src/analysis.rs index 7fbfad467c64..6ac485b12ba8 100644 --- a/src/ci/citool/src/analysis.rs +++ b/src/ci/citool/src/analysis.rs @@ -225,7 +225,7 @@ pub fn output_largest_duration_changes(job_metrics: &HashMap Date: Mon, 7 Apr 2025 07:07:16 -0400 Subject: [PATCH 165/606] handle sret for scalar autodiff --- .../rustc_ast/src/expand/autodiff_attrs.rs | 6 +++++ .../src/builder/autodiff.rs | 24 +++++++++++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_ast/src/expand/autodiff_attrs.rs b/compiler/rustc_ast/src/expand/autodiff_attrs.rs index f01c781f46c6..13a7c5a18057 100644 --- a/compiler/rustc_ast/src/expand/autodiff_attrs.rs +++ b/compiler/rustc_ast/src/expand/autodiff_attrs.rs @@ -92,6 +92,12 @@ pub struct AutoDiffAttrs { pub input_activity: Vec, } +impl AutoDiffAttrs { + pub fn has_primal_ret(&self) -> bool { + matches!(self.ret_activity, DiffActivity::Active | DiffActivity::Dual) + } +} + impl DiffMode { pub fn is_rev(&self) -> bool { matches!(self, DiffMode::Reverse) diff --git a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs index 7d264ba4d00c..5e7ef27143b1 100644 --- a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs +++ b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs @@ -201,7 +201,23 @@ fn compute_enzyme_fn_ty<'ll>( } if attrs.width == 1 { - todo!("Handle sret for scalar ad"); + // Enzyme returns a struct of style: + // `{ original_ret(if requested), float, float, ... }` + let mut struct_elements = vec![]; + if attrs.has_primal_ret() { + struct_elements.push(inner_ret_ty); + } + // Next, we push the list of active floats, since they will be lowered to `enzyme_out`, + // and therefore part of the return struct. + let param_tys = cx.func_params_types(fn_ty); + for (act, param_ty) in attrs.input_activity.iter().zip(param_tys) { + if matches!(act, DiffActivity::Active) { + // Now find the float type at position i based on the fn_ty, + // to know what (f16/f32/f64/...) to add to the struct. + struct_elements.push(param_ty); + } + } + ret_ty = cx.type_struct(&struct_elements, false); } else { // First we check if we also have to deal with the primal return. match attrs.mode { @@ -388,7 +404,11 @@ fn generate_enzyme_call<'ll>( // now store the result of the enzyme call into the sret pointer. let sret_ptr = outer_args[0]; let call_ty = cx.val_ty(call); - assert_eq!(cx.type_kind(call_ty), TypeKind::Array); + if attrs.width == 1 { + assert_eq!(cx.type_kind(call_ty), TypeKind::Struct); + } else { + assert_eq!(cx.type_kind(call_ty), TypeKind::Array); + } llvm::LLVMBuildStore(&builder.llbuilder, call, sret_ptr); } builder.ret_void(); From ca5bea3ebbc4725c187abf4eac68f6c57fa938c1 Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Mon, 7 Apr 2025 07:11:52 -0400 Subject: [PATCH 166/606] move old tests, add sret test --- .../{autodiffv.rs => autodiff/batched.rs} | 0 .../{autodiff.rs => autodiff/scalar.rs} | 0 tests/codegen/autodiff/sret.rs | 45 +++++++++++++++++++ 3 files changed, 45 insertions(+) rename tests/codegen/{autodiffv.rs => autodiff/batched.rs} (100%) rename tests/codegen/{autodiff.rs => autodiff/scalar.rs} (100%) create mode 100644 tests/codegen/autodiff/sret.rs diff --git a/tests/codegen/autodiffv.rs b/tests/codegen/autodiff/batched.rs similarity index 100% rename from tests/codegen/autodiffv.rs rename to tests/codegen/autodiff/batched.rs diff --git a/tests/codegen/autodiff.rs b/tests/codegen/autodiff/scalar.rs similarity index 100% rename from tests/codegen/autodiff.rs rename to tests/codegen/autodiff/scalar.rs diff --git a/tests/codegen/autodiff/sret.rs b/tests/codegen/autodiff/sret.rs new file mode 100644 index 000000000000..5ead90041edc --- /dev/null +++ b/tests/codegen/autodiff/sret.rs @@ -0,0 +1,45 @@ +//@ compile-flags: -Zautodiff=Enable -C opt-level=3 -Clto=fat +//@ no-prefer-dynamic +//@ needs-enzyme + +// This test is almost identical to the scalar.rs one, +// but we intentionally add a few more floats. +// `df` would ret `{ f64, f32, f32 }`, but is lowered as an sret. +// We therefore use this test to verify some of our sret handling. + +#![feature(autodiff)] + +use std::autodiff::autodiff; + +#[no_mangle] +#[autodiff(df, Reverse, Active, Active, Active)] +fn primal(x: f32, y: f32) -> f64 { + (x * x * y) as f64 +} + +// CHECK:define internal fastcc void @_ZN4sret2df17h93be4316dd8ea006E(ptr dead_on_unwind noalias nocapture noundef nonnull writable writeonly align 8 dereferenceable(16) initializes((0, 16)) %_0, float noundef %x, float noundef %y) +// CHECK-NEXT:start: +// CHECK-NEXT: %0 = tail call fastcc { double, float, float } @diffeprimal(float %x, float %y) +// CHECK-NEXT: %.elt = extractvalue { double, float, float } %0, 0 +// CHECK-NEXT: store double %.elt, ptr %_0, align 8 +// CHECK-NEXT: %_0.repack1 = getelementptr inbounds nuw i8, ptr %_0, i64 8 +// CHECK-NEXT: %.elt2 = extractvalue { double, float, float } %0, 1 +// CHECK-NEXT: store float %.elt2, ptr %_0.repack1, align 8 +// CHECK-NEXT: %_0.repack3 = getelementptr inbounds nuw i8, ptr %_0, i64 12 +// CHECK-NEXT: %.elt4 = extractvalue { double, float, float } %0, 2 +// CHECK-NEXT: store float %.elt4, ptr %_0.repack3, align 4 +// CHECK-NEXT: ret void +// CHECK-NEXT:} + +fn main() { + let x = std::hint::black_box(3.0); + let y = std::hint::black_box(2.5); + let scalar = std::hint::black_box(1.0); + let (r1, r2, r3) = df(x, y, scalar); + // 3*3*1.5 = 22.5 + assert_eq!(r1, 22.5); + // 2*x*y = 2*3*2.5 = 15.0 + assert_eq!(r2, 15.0); + // x*x*1 = 3*3 = 9 + assert_eq!(r3, 9.0); +} From cae28b5119cdb23544a80fafd02f486fdfe1183b Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Mon, 7 Apr 2025 16:23:44 +0300 Subject: [PATCH 167/606] implement `check` step for `compiletest` separately Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/check.rs | 67 +++++++++++++++++-- src/bootstrap/src/core/build_steps/compile.rs | 4 +- 2 files changed, 66 insertions(+), 5 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs index e67bc62a6035..b191d0f6b306 100644 --- a/src/bootstrap/src/core/build_steps/check.rs +++ b/src/bootstrap/src/core/build_steps/check.rs @@ -369,6 +369,69 @@ impl Step for RustAnalyzer { } } +/// Compiletest is implicitly "checked" when it gets built in order to run tests, +/// so this is mainly for people working on compiletest to run locally. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct Compiletest { + pub target: TargetSelection, +} + +impl Step for Compiletest { + type Output = (); + const ONLY_HOSTS: bool = true; + const DEFAULT: bool = false; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.path("src/tools/compiletest") + } + + fn make_run(run: RunConfig<'_>) { + run.builder.ensure(Compiletest { target: run.target }); + } + + fn run(self, builder: &Builder<'_>) { + let mode = if builder.config.compiletest_use_stage0_libtest { + Mode::ToolBootstrap + } else { + Mode::ToolStd + }; + + let compiler = builder.compiler( + if mode == Mode::ToolBootstrap { 0 } else { builder.top_stage }, + builder.config.build, + ); + + if mode != Mode::ToolBootstrap { + builder.ensure(Rustc::new(self.target, builder)); + } + + let mut cargo = prepare_tool_cargo( + builder, + compiler, + mode, + self.target, + builder.kind, + "src/tools/compiletest", + SourceType::InTree, + &[], + ); + + cargo.allow_features("test"); + + // For ./x.py clippy, don't run with --all-targets because + // linting tests and benchmarks can produce very noisy results + if builder.kind != Kind::Clippy { + cargo.arg("--all-targets"); + } + + let stamp = BuildStamp::new(&builder.cargo_out(compiler, mode, self.target)) + .with_prefix("compiletest-check"); + + let _guard = builder.msg_check("compiletest artifacts", self.target); + run_cargo(builder, cargo, builder.config.free_args.clone(), &stamp, vec![], true, false); + } +} + macro_rules! tool_check_step { ( $name:ident { @@ -464,7 +527,3 @@ tool_check_step!(Bootstrap { path: "src/bootstrap", default: false }); // `run-make-support` will be built as part of suitable run-make compiletest test steps, but support // check to make it easier to work on. tool_check_step!(RunMakeSupport { path: "src/tools/run-make-support", default: false }); - -// Compiletest is implicitly "checked" when it gets built in order to run tests, -// so this is mainly for people working on compiletest to run locally. -tool_check_step!(Compiletest { path: "src/tools/compiletest", default: false }); diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 18b5d4426b1e..dab58fccf5e6 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -2398,7 +2398,9 @@ pub fn run_cargo( // Ok now we need to actually find all the files listed in `toplevel`. We've // got a list of prefix/extensions and we basically just need to find the // most recent file in the `deps` folder corresponding to each one. - let contents = t!(target_deps_dir.read_dir()) + let contents = target_deps_dir + .read_dir() + .unwrap_or_else(|e| panic!("Couldn't read {}: {}", target_deps_dir.display(), e)) .map(|e| t!(e)) .map(|e| (e.path(), e.file_name().into_string().unwrap(), t!(e.metadata()))) .collect::>(); From da0b9a2b89d257f3198f491fdecc5a20a2e686b9 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 7 Apr 2025 15:18:51 +0200 Subject: [PATCH 168/606] f*::NAN: guarantee that this is a quiet NaN --- library/core/src/num/f128.rs | 18 ++++++++++-------- library/core/src/num/f16.rs | 18 ++++++++++-------- library/core/src/num/f32.rs | 18 ++++++++++-------- library/core/src/num/f64.rs | 18 ++++++++++-------- 4 files changed, 40 insertions(+), 32 deletions(-) diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs index 08c34e852da4..d3d1eebc2275 100644 --- a/library/core/src/num/f128.rs +++ b/library/core/src/num/f128.rs @@ -224,14 +224,16 @@ impl f128 { /// Not a Number (NaN). /// - /// Note that IEEE 754 doesn't define just a single NaN value; - /// a plethora of bit patterns are considered to be NaN. - /// Furthermore, the standard makes a difference - /// between a "signaling" and a "quiet" NaN, - /// and allows inspecting its "payload" (the unspecified bits in the bit pattern). - /// This constant isn't guaranteed to equal to any specific NaN bitpattern, - /// and the stability of its representation over Rust versions - /// and target platforms isn't guaranteed. + /// Note that IEEE 754 doesn't define just a single NaN value; a plethora of bit patterns are + /// considered to be NaN. Furthermore, the standard makes a difference between a "signaling" and + /// a "quiet" NaN, and allows inspecting its "payload" (the unspecified bits in the bit pattern) + /// and its sign. See the [specification of NaN bit patterns](f32#nan-bit-patterns) for more + /// info. + /// + /// This constant is guaranteed to be a quiet NaN (on targets that follow the Rust assumptions + /// that the quiet/signaling bit being set to 1 indicates a quiet NaN). Beyond that, nothing is + /// guaranteed about the specific bit pattern chosen here: both payload and sign are arbitrary. + /// The concrete bit pattern may change across Rust versions and target platforms. #[allow(clippy::eq_op)] #[rustc_diagnostic_item = "f128_nan"] #[unstable(feature = "f128", issue = "116909")] diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs index a33e5f530146..dceb30177e66 100644 --- a/library/core/src/num/f16.rs +++ b/library/core/src/num/f16.rs @@ -219,14 +219,16 @@ impl f16 { /// Not a Number (NaN). /// - /// Note that IEEE 754 doesn't define just a single NaN value; - /// a plethora of bit patterns are considered to be NaN. - /// Furthermore, the standard makes a difference - /// between a "signaling" and a "quiet" NaN, - /// and allows inspecting its "payload" (the unspecified bits in the bit pattern). - /// This constant isn't guaranteed to equal to any specific NaN bitpattern, - /// and the stability of its representation over Rust versions - /// and target platforms isn't guaranteed. + /// Note that IEEE 754 doesn't define just a single NaN value; a plethora of bit patterns are + /// considered to be NaN. Furthermore, the standard makes a difference between a "signaling" and + /// a "quiet" NaN, and allows inspecting its "payload" (the unspecified bits in the bit pattern) + /// and its sign. See the [specification of NaN bit patterns](f32#nan-bit-patterns) for more + /// info. + /// + /// This constant is guaranteed to be a quiet NaN (on targets that follow the Rust assumptions + /// that the quiet/signaling bit being set to 1 indicates a quiet NaN). Beyond that, nothing is + /// guaranteed about the specific bit pattern chosen here: both payload and sign are arbitrary. + /// The concrete bit pattern may change across Rust versions and target platforms. #[allow(clippy::eq_op)] #[rustc_diagnostic_item = "f16_nan"] #[unstable(feature = "f16", issue = "116909")] diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index e473fac03935..c97dbfb63ae1 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -470,14 +470,16 @@ impl f32 { /// Not a Number (NaN). /// - /// Note that IEEE 754 doesn't define just a single NaN value; - /// a plethora of bit patterns are considered to be NaN. - /// Furthermore, the standard makes a difference - /// between a "signaling" and a "quiet" NaN, - /// and allows inspecting its "payload" (the unspecified bits in the bit pattern). - /// This constant isn't guaranteed to equal to any specific NaN bitpattern, - /// and the stability of its representation over Rust versions - /// and target platforms isn't guaranteed. + /// Note that IEEE 754 doesn't define just a single NaN value; a plethora of bit patterns are + /// considered to be NaN. Furthermore, the standard makes a difference between a "signaling" and + /// a "quiet" NaN, and allows inspecting its "payload" (the unspecified bits in the bit pattern) + /// and its sign. See the [specification of NaN bit patterns](f32#nan-bit-patterns) for more + /// info. + /// + /// This constant is guaranteed to be a quiet NaN (on targets that follow the Rust assumptions + /// that the quiet/signaling bit being set to 1 indicates a quiet NaN). Beyond that, nothing is + /// guaranteed about the specific bit pattern chosen here: both payload and sign are arbitrary. + /// The concrete bit pattern may change across Rust versions and target platforms. #[stable(feature = "assoc_int_consts", since = "1.43.0")] #[rustc_diagnostic_item = "f32_nan"] #[allow(clippy::eq_op)] diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index 6522a80b0b7e..91affdb3794b 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -469,14 +469,16 @@ impl f64 { /// Not a Number (NaN). /// - /// Note that IEEE 754 doesn't define just a single NaN value; - /// a plethora of bit patterns are considered to be NaN. - /// Furthermore, the standard makes a difference - /// between a "signaling" and a "quiet" NaN, - /// and allows inspecting its "payload" (the unspecified bits in the bit pattern). - /// This constant isn't guaranteed to equal to any specific NaN bitpattern, - /// and the stability of its representation over Rust versions - /// and target platforms isn't guaranteed. + /// Note that IEEE 754 doesn't define just a single NaN value; a plethora of bit patterns are + /// considered to be NaN. Furthermore, the standard makes a difference between a "signaling" and + /// a "quiet" NaN, and allows inspecting its "payload" (the unspecified bits in the bit pattern) + /// and its sign. See the [specification of NaN bit patterns](f32#nan-bit-patterns) for more + /// info. + /// + /// This constant is guaranteed to be a quiet NaN (on targets that follow the Rust assumptions + /// that the quiet/signaling bit being set to 1 indicates a quiet NaN). Beyond that, nothing is + /// guaranteed about the specific bit pattern chosen here: both payload and sign are arbitrary. + /// The concrete bit pattern may change across Rust versions and target platforms. #[rustc_diagnostic_item = "f64_nan"] #[stable(feature = "assoc_int_consts", since = "1.43.0")] #[allow(clippy::eq_op)] From 0da46d1065eb53226211e7dea4ba6103607d6def Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 7 Apr 2025 17:00:28 +0200 Subject: [PATCH 169/606] =?UTF-8?q?targest=20=E2=86=92=20targets=20(spotte?= =?UTF-8?q?d=20as=20I=20had=20the=20same=20typo)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/tools/miri/tests/pass/tls/tls_leak_main_thread_allowed.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/tests/pass/tls/tls_leak_main_thread_allowed.rs b/src/tools/miri/tests/pass/tls/tls_leak_main_thread_allowed.rs index 341b2280e010..abc0968f7c4c 100644 --- a/src/tools/miri/tests/pass/tls/tls_leak_main_thread_allowed.rs +++ b/src/tools/miri/tests/pass/tls/tls_leak_main_thread_allowed.rs @@ -13,7 +13,7 @@ pub fn main() { TLS.set(Some(Box::leak(Box::new(123)))); // We can only ignore leaks on targets that use `#[thread_local]` statics to implement - // `thread_local!`. Ignore the test on targest that don't. + // `thread_local!`. Ignore the test on targets that don't. if cfg!(target_thread_local) { thread_local! { static TLS_KEY: Cell> = Cell::new(None); From 39c6b6c7d2834ee79cc518c42995b54d835544f8 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 7 Apr 2025 17:28:38 +0200 Subject: [PATCH 170/606] Fix CSS --- src/librustdoc/html/static/css/rustdoc.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index aa8df35258df..74d23b3143f4 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1447,7 +1447,7 @@ so that we can apply CSS-filters to change the arrow color in themes */ cursor: pointer; } .setting-check input { - flex-shrink: 0, + flex-shrink: 0; } .setting-radio input:checked { From 30f56df6f9fe396758213b5d9339e774339f5455 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 7 Apr 2025 17:28:28 +0200 Subject: [PATCH 171/606] Add regression test for #139282 --- tests/rustdoc-gui/settings.goml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/rustdoc-gui/settings.goml b/tests/rustdoc-gui/settings.goml index 4ab5b83d7c41..11d3696ccf6a 100644 --- a/tests/rustdoc-gui/settings.goml +++ b/tests/rustdoc-gui/settings.goml @@ -314,6 +314,13 @@ compare-elements-position: (".sub form", "#settings", ["x"]) // Check that setting-line has the same margin in this mode as in the popover. assert-css: (".setting-line", {"margin": |setting_line_margin|}) +// We will check that the checkboxes size doesn't change either. +assert-size: ( + "#settings label > input[type='checkbox']", + {"width": 19, "height": 19}, + ALL, +) + // We now check the display with JS disabled. assert-false: "noscript section" javascript: false @@ -327,3 +334,10 @@ reload: set-window-size: (300, 1000) wait-for: "#settings" assert-css: (".setting-radio", {"cursor": "pointer"}) + +// We ensure that the checkboxes size didn't change. +assert-size: ( + "#settings label > input[type='checkbox']", + {"width": 19, "height": 19}, + ALL, +) From 6ece1de0cd85156e211f58979081163405c8c5c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Mon, 7 Apr 2025 14:08:31 +0200 Subject: [PATCH 172/606] Add job summary links to post-merge report This should make it much easier to investigate the individual job changes. --- src/ci/citool/src/analysis.rs | 42 ++++++++++--- src/ci/citool/src/github.rs | 109 ++++++++++++++++++++++++++++++++++ src/ci/citool/src/main.rs | 11 +++- 3 files changed, 152 insertions(+), 10 deletions(-) create mode 100644 src/ci/citool/src/github.rs diff --git a/src/ci/citool/src/analysis.rs b/src/ci/citool/src/analysis.rs index 6ac485b12ba8..208a494183c0 100644 --- a/src/ci/citool/src/analysis.rs +++ b/src/ci/citool/src/analysis.rs @@ -7,6 +7,7 @@ use build_helper::metrics::{ format_build_steps, }; +use crate::github::JobInfoResolver; use crate::metrics; use crate::metrics::{JobMetrics, JobName, get_test_suites}; use crate::utils::{output_details, pluralize}; @@ -185,13 +186,19 @@ fn render_table(suites: BTreeMap) -> String { } /// Outputs a report of test differences between the `parent` and `current` commits. -pub fn output_test_diffs(job_metrics: &HashMap) { +pub fn output_test_diffs( + job_metrics: &HashMap, + job_info_resolver: &mut JobInfoResolver, +) { let aggregated_test_diffs = aggregate_test_diffs(&job_metrics); - report_test_diffs(aggregated_test_diffs); + report_test_diffs(aggregated_test_diffs, job_metrics, job_info_resolver); } /// Prints the ten largest differences in bootstrap durations. -pub fn output_largest_duration_changes(job_metrics: &HashMap) { +pub fn output_largest_duration_changes( + job_metrics: &HashMap, + job_info_resolver: &mut JobInfoResolver, +) { struct Entry<'a> { job: &'a JobName, before: Duration, @@ -230,9 +237,9 @@ pub fn output_largest_duration_changes(job_metrics: &HashMap {:.1}s ({:.1}%)", + "{}. {}: {:.1}s -> {:.1}s ({:.1}%)", index + 1, - entry.job, + format_job_link(job_info_resolver, job_metrics, entry.job), entry.before.as_secs_f64(), entry.after.as_secs_f64(), entry.change @@ -400,7 +407,11 @@ fn generate_test_name(name: &str) -> String { } /// Prints test changes in Markdown format to stdout. -fn report_test_diffs(diff: AggregatedTestDiffs) { +fn report_test_diffs( + diff: AggregatedTestDiffs, + job_metrics: &HashMap, + job_info_resolver: &mut JobInfoResolver, +) { println!("# Test differences"); if diff.diffs.is_empty() { println!("No test diffs found"); @@ -521,9 +532,26 @@ fn report_test_diffs(diff: AggregatedTestDiffs) { println!( "- {}: {}", format_job_group(group as u64), - jobs.iter().map(|j| format!("`{j}`")).collect::>().join(", ") + jobs.iter() + .map(|j| format_job_link(job_info_resolver, job_metrics, j)) + .collect::>() + .join(", ") ); } }, ); } + +/// Tries to get a GitHub Actions job summary URL from the resolver. +/// If it is not available, just wraps the job name in backticks. +fn format_job_link( + job_info_resolver: &mut JobInfoResolver, + job_metrics: &HashMap, + job_name: &str, +) -> String { + job_metrics + .get(job_name) + .and_then(|metrics| job_info_resolver.get_job_summary_link(job_name, &metrics.current)) + .map(|summary_url| format!("[{job_name}]({summary_url})")) + .unwrap_or_else(|| format!("`{job_name}`")) +} diff --git a/src/ci/citool/src/github.rs b/src/ci/citool/src/github.rs new file mode 100644 index 000000000000..35e4c3f9599d --- /dev/null +++ b/src/ci/citool/src/github.rs @@ -0,0 +1,109 @@ +use std::collections::HashMap; + +use anyhow::Context; +use build_helper::metrics::{CiMetadata, JsonRoot}; + +pub struct GitHubClient; + +impl GitHubClient { + fn get_workflow_run_jobs( + &self, + repo: &str, + workflow_run_id: u64, + ) -> anyhow::Result> { + let req = ureq::get(format!( + "https://api.github.com/repos/{repo}/actions/runs/{workflow_run_id}/jobs?per_page=100" + )) + .header("User-Agent", "rust-lang/rust/citool") + .header("Accept", "application/vnd.github+json") + .header("X-GitHub-Api-Version", "2022-11-28") + .call() + .context("cannot get workflow job list")?; + + let status = req.status(); + let mut body = req.into_body(); + if status.is_success() { + // This API response is actually paged, but we assume for now that there are at + // most 100 jobs per workflow. + let response = body + .read_json::() + .context("cannot deserialize workflow run jobs response")?; + // The CI job names have a prefix, e.g. `auto - foo`. We remove the prefix here to + // normalize the job name. + Ok(response + .jobs + .into_iter() + .map(|mut job| { + job.name = job + .name + .split_once(" - ") + .map(|res| res.1.to_string()) + .unwrap_or_else(|| job.name); + job + }) + .collect()) + } else { + Err(anyhow::anyhow!( + "Cannot get jobs of workflow run {workflow_run_id}: {status}\n{}", + body.read_to_string()? + )) + } + } +} + +#[derive(serde::Deserialize)] +struct WorkflowRunJobsResponse { + jobs: Vec, +} + +#[derive(serde::Deserialize)] +struct GitHubJob { + name: String, + id: u64, +} + +/// Can be used to resolve information about GitHub Actions jobs. +/// Caches results internally to avoid too unnecessary GitHub API calls. +pub struct JobInfoResolver { + client: GitHubClient, + // Workflow run ID -> jobs + workflow_job_cache: HashMap>, +} + +impl JobInfoResolver { + pub fn new() -> Self { + Self { client: GitHubClient, workflow_job_cache: Default::default() } + } + + /// Get a link to a job summary for the given job name and bootstrap execution. + pub fn get_job_summary_link(&mut self, job_name: &str, metrics: &JsonRoot) -> Option { + metrics.ci_metadata.as_ref().and_then(|metadata| { + self.get_job_id(metadata, job_name).map(|job_id| { + format!( + "https://github.com/{}/actions/runs/{}#summary-{job_id}", + metadata.repository, metadata.workflow_run_id + ) + }) + }) + } + + fn get_job_id(&mut self, ci_metadata: &CiMetadata, job_name: &str) -> Option { + if let Some(job) = self + .workflow_job_cache + .get(&ci_metadata.workflow_run_id) + .and_then(|jobs| jobs.iter().find(|j| j.name == job_name)) + { + return Some(job.id); + } + + let jobs = self + .client + .get_workflow_run_jobs(&ci_metadata.repository, ci_metadata.workflow_run_id) + .inspect_err(|e| eprintln!("Cannot download workflow jobs: {e:?}")) + .ok()?; + let job_id = jobs.iter().find(|j| j.name == job_name).map(|j| j.id); + // Save the cache even if the job name was not found, it could be useful for further lookups + self.workflow_job_cache.insert(ci_metadata.workflow_run_id, jobs); + job_id + } +} diff --git a/src/ci/citool/src/main.rs b/src/ci/citool/src/main.rs index 6db5eab458cc..a1956da352f5 100644 --- a/src/ci/citool/src/main.rs +++ b/src/ci/citool/src/main.rs @@ -1,6 +1,7 @@ mod analysis; mod cpu_usage; mod datadog; +mod github; mod jobs; mod metrics; mod utils; @@ -18,6 +19,7 @@ use serde_yaml::Value; use crate::analysis::{output_largest_duration_changes, output_test_diffs}; use crate::cpu_usage::load_cpu_usage; use crate::datadog::upload_datadog_metric; +use crate::github::JobInfoResolver; use crate::jobs::RunType; use crate::metrics::{JobMetrics, download_auto_job_metrics, download_job_metrics, load_metrics}; use crate::utils::load_env_var; @@ -145,6 +147,7 @@ fn postprocess_metrics( ) -> anyhow::Result<()> { let metrics = load_metrics(&metrics_path)?; + let mut job_info_resolver = JobInfoResolver::new(); if let (Some(parent), Some(job_name)) = (parent, job_name) { // This command is executed also on PR builds, which might not have parent metrics // available, because some PR jobs don't run on auto builds, and PR jobs do not upload metrics @@ -160,7 +163,7 @@ fn postprocess_metrics( job_name, JobMetrics { parent: Some(parent_metrics), current: metrics }, )]); - output_test_diffs(&job_metrics); + output_test_diffs(&job_metrics, &mut job_info_resolver); return Ok(()); } Err(error) => { @@ -180,8 +183,10 @@ fn post_merge_report(db: JobDatabase, current: String, parent: String) -> anyhow let metrics = download_auto_job_metrics(&db, &parent, ¤t)?; println!("\nComparing {parent} (parent) -> {current} (this PR)\n"); - output_test_diffs(&metrics); - output_largest_duration_changes(&metrics); + + let mut job_info_resolver = JobInfoResolver::new(); + output_test_diffs(&metrics, &mut job_info_resolver); + output_largest_duration_changes(&metrics, &mut job_info_resolver); Ok(()) } From 42048ea12298da75415ce0c2b25a381bbe81eade Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 7 Apr 2025 14:32:56 +0300 Subject: [PATCH 173/606] compiletest: Cleanup collection of actual errors --- src/tools/compiletest/src/json.rs | 83 +++++++++++++------------------ 1 file changed, 35 insertions(+), 48 deletions(-) diff --git a/src/tools/compiletest/src/json.rs b/src/tools/compiletest/src/json.rs index 9bc26fedf8f4..132e9070650d 100644 --- a/src/tools/compiletest/src/json.rs +++ b/src/tools/compiletest/src/json.rs @@ -142,43 +142,34 @@ pub fn extract_rendered(output: &str) -> String { } pub fn parse_output(file_name: &str, output: &str, proc_res: &ProcRes) -> Vec { - output.lines().flat_map(|line| parse_line(file_name, line, output, proc_res)).collect() -} - -fn parse_line(file_name: &str, line: &str, output: &str, proc_res: &ProcRes) -> Vec { - // The compiler sometimes intermingles non-JSON stuff into the - // output. This hack just skips over such lines. Yuck. - if line.starts_with('{') { - match serde_json::from_str::(line) { - Ok(diagnostic) => { - let mut expected_errors = vec![]; - push_expected_errors(&mut expected_errors, &diagnostic, &[], file_name); - expected_errors - } - Err(error) => { - // Ignore the future compat report message - this is handled - // by `extract_rendered` - if serde_json::from_str::(line).is_ok() { - vec![] - } else { - proc_res.fatal( + let mut errors = Vec::new(); + for line in output.lines() { + // The compiler sometimes intermingles non-JSON stuff into the + // output. This hack just skips over such lines. Yuck. + if line.starts_with('{') { + match serde_json::from_str::(line) { + Ok(diagnostic) => push_actual_errors(&mut errors, &diagnostic, &[], file_name), + Err(error) => { + // Ignore the future compat report message - this is handled + // by `extract_rendered` + if serde_json::from_str::(line).is_err() { + proc_res.fatal( Some(&format!( - "failed to decode compiler output as json: \ - `{}`\nline: {}\noutput: {}", + "failed to decode compiler output as json: `{}`\nline: {}\noutput: {}", error, line, output )), || (), ); + } } } } - } else { - vec![] } + errors } -fn push_expected_errors( - expected_errors: &mut Vec, +fn push_actual_errors( + errors: &mut Vec, diagnostic: &Diagnostic, default_spans: &[&DiagnosticSpan], file_name: &str, @@ -236,10 +227,10 @@ fn push_expected_errors( } }; - // Convert multi-line messages into multiple expected - // errors. We expect to replace these with something - // more structured shortly anyhow. + // Convert multi-line messages into multiple errors. + // We expect to replace these with something more structured anyhow. let mut message_lines = diagnostic.message.lines(); + let kind = ErrorKind::from_str(&diagnostic.level).ok(); if let Some(first_line) = message_lines.next() { let ignore = |s| { static RE: OnceLock = OnceLock::new(); @@ -250,27 +241,23 @@ fn push_expected_errors( }; if primary_spans.is_empty() && !ignore(first_line) { - let msg = with_code(None, first_line); - let kind = ErrorKind::from_str(&diagnostic.level).ok(); - expected_errors.push(Error { line_num: None, kind, msg }); + errors.push(Error { line_num: None, kind, msg: with_code(None, first_line) }); } else { for span in primary_spans { - let msg = with_code(Some(span), first_line); - let kind = ErrorKind::from_str(&diagnostic.level).ok(); - expected_errors.push(Error { line_num: Some(span.line_start), kind, msg }); + errors.push(Error { + line_num: Some(span.line_start), + kind, + msg: with_code(Some(span), first_line), + }); } } } for next_line in message_lines { if primary_spans.is_empty() { - expected_errors.push(Error { - line_num: None, - kind: None, - msg: with_code(None, next_line), - }); + errors.push(Error { line_num: None, kind: None, msg: with_code(None, next_line) }); } else { for span in primary_spans { - expected_errors.push(Error { + errors.push(Error { line_num: Some(span.line_start), kind: None, msg: with_code(Some(span), next_line), @@ -283,7 +270,7 @@ fn push_expected_errors( for span in primary_spans { if let Some(ref suggested_replacement) = span.suggested_replacement { for (index, line) in suggested_replacement.lines().enumerate() { - expected_errors.push(Error { + errors.push(Error { line_num: Some(span.line_start + index), kind: Some(ErrorKind::Suggestion), msg: line.to_string(), @@ -295,13 +282,13 @@ fn push_expected_errors( // Add notes for the backtrace for span in primary_spans { if let Some(frame) = &span.expansion { - push_backtrace(expected_errors, frame, file_name); + push_backtrace(errors, frame, file_name); } } // Add notes for any labels that appear in the message. for span in spans_in_this_file.iter().filter(|span| span.label.is_some()) { - expected_errors.push(Error { + errors.push(Error { line_num: Some(span.line_start), kind: Some(ErrorKind::Note), msg: span.label.clone().unwrap(), @@ -310,17 +297,17 @@ fn push_expected_errors( // Flatten out the children. for child in &diagnostic.children { - push_expected_errors(expected_errors, child, primary_spans, file_name); + push_actual_errors(errors, child, primary_spans, file_name); } } fn push_backtrace( - expected_errors: &mut Vec, + errors: &mut Vec, expansion: &DiagnosticSpanMacroExpansion, file_name: &str, ) { if Path::new(&expansion.span.file_name) == Path::new(&file_name) { - expected_errors.push(Error { + errors.push(Error { line_num: Some(expansion.span.line_start), kind: Some(ErrorKind::Note), msg: format!("in this expansion of {}", expansion.macro_decl_name), @@ -328,6 +315,6 @@ fn push_backtrace( } if let Some(previous_expansion) = &expansion.span.expansion { - push_backtrace(expected_errors, previous_expansion, file_name); + push_backtrace(errors, previous_expansion, file_name); } } From b86b3fb640e4f914db9013872e8ff67b74ba286d Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 7 Apr 2025 14:45:53 +0300 Subject: [PATCH 174/606] compiletest: Always preserve kind for compiler diagnostics Those that didn't previously preserved kind are now marked as not requiring annotations to keep the previous behavior. Also, do not lose diagnostics with an empty message. --- src/tools/compiletest/src/errors.rs | 6 ++- src/tools/compiletest/src/json.rs | 57 +++++++++++++++----------- src/tools/compiletest/src/runtest.rs | 1 + tests/ui/proc-macro/issue-91800.rs | 3 ++ tests/ui/proc-macro/issue-91800.stderr | 8 ++-- 5 files changed, 46 insertions(+), 29 deletions(-) diff --git a/src/tools/compiletest/src/errors.rs b/src/tools/compiletest/src/errors.rs index b68f817146fd..e1face32716c 100644 --- a/src/tools/compiletest/src/errors.rs +++ b/src/tools/compiletest/src/errors.rs @@ -53,6 +53,10 @@ pub struct Error { /// `None` if not specified or unknown message kind. pub kind: Option, pub msg: String, + /// For some `Error`s, like secondary lines of multi-line diagnostics, line annotations + /// are not mandatory, even if they would otherwise be mandatory for primary errors. + /// Only makes sense for "actual" errors, not for "expected" errors. + pub require_annotation: bool, } impl Error { @@ -182,7 +186,7 @@ fn parse_expected( kind, msg ); - Some((follow_prev, Error { line_num, kind, msg })) + Some((follow_prev, Error { line_num, kind, msg, require_annotation: true })) } #[cfg(test)] diff --git a/src/tools/compiletest/src/json.rs b/src/tools/compiletest/src/json.rs index 132e9070650d..2a6fcd6cf81a 100644 --- a/src/tools/compiletest/src/json.rs +++ b/src/tools/compiletest/src/json.rs @@ -231,36 +231,42 @@ fn push_actual_errors( // We expect to replace these with something more structured anyhow. let mut message_lines = diagnostic.message.lines(); let kind = ErrorKind::from_str(&diagnostic.level).ok(); - if let Some(first_line) = message_lines.next() { - let ignore = |s| { - static RE: OnceLock = OnceLock::new(); - RE.get_or_init(|| { - Regex::new(r"aborting due to \d+ previous errors?|\d+ warnings? emitted").unwrap() - }) - .is_match(s) - }; - - if primary_spans.is_empty() && !ignore(first_line) { - errors.push(Error { line_num: None, kind, msg: with_code(None, first_line) }); + let first_line = message_lines.next().unwrap_or(&diagnostic.message); + if primary_spans.is_empty() { + static RE: OnceLock = OnceLock::new(); + let re_init = + || Regex::new(r"aborting due to \d+ previous errors?|\d+ warnings? emitted").unwrap(); + errors.push(Error { + line_num: None, + kind, + msg: with_code(None, first_line), + require_annotation: !RE.get_or_init(re_init).is_match(first_line), + }); + } else { + for span in primary_spans { + errors.push(Error { + line_num: Some(span.line_start), + kind, + msg: with_code(Some(span), first_line), + require_annotation: true, + }); + } + } + for next_line in message_lines { + if primary_spans.is_empty() { + errors.push(Error { + line_num: None, + kind, + msg: with_code(None, next_line), + require_annotation: false, + }); } else { for span in primary_spans { errors.push(Error { line_num: Some(span.line_start), kind, - msg: with_code(Some(span), first_line), - }); - } - } - } - for next_line in message_lines { - if primary_spans.is_empty() { - errors.push(Error { line_num: None, kind: None, msg: with_code(None, next_line) }); - } else { - for span in primary_spans { - errors.push(Error { - line_num: Some(span.line_start), - kind: None, msg: with_code(Some(span), next_line), + require_annotation: false, }); } } @@ -274,6 +280,7 @@ fn push_actual_errors( line_num: Some(span.line_start + index), kind: Some(ErrorKind::Suggestion), msg: line.to_string(), + require_annotation: true, }); } } @@ -292,6 +299,7 @@ fn push_actual_errors( line_num: Some(span.line_start), kind: Some(ErrorKind::Note), msg: span.label.clone().unwrap(), + require_annotation: true, }); } @@ -311,6 +319,7 @@ fn push_backtrace( line_num: Some(expansion.span.line_start), kind: Some(ErrorKind::Note), msg: format!("in this expansion of {}", expansion.macro_decl_name), + require_annotation: true, }); } diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index c8a60b68da8b..1002c290b603 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -811,6 +811,7 @@ impl<'test> TestCx<'test> { expect_note: bool, ) -> bool { !actual_error.msg.is_empty() + && actual_error.require_annotation && match actual_error.kind { Some(ErrorKind::Help) => expect_help, Some(ErrorKind::Note) => expect_note, diff --git a/tests/ui/proc-macro/issue-91800.rs b/tests/ui/proc-macro/issue-91800.rs index bc78bcacfd0f..8cecfad32b55 100644 --- a/tests/ui/proc-macro/issue-91800.rs +++ b/tests/ui/proc-macro/issue-91800.rs @@ -6,11 +6,14 @@ extern crate issue_91800_macro; #[derive(MyTrait)] //~^ ERROR macros that expand to items must be delimited with braces or followed by a semicolon //~| ERROR proc-macro derive produced unparsable tokens +//~| ERROR #[attribute_macro] //~^ ERROR macros that expand to items must be delimited with braces or followed by a semicolon +//~| ERROR struct MyStruct; fn_macro! {} //~^ ERROR macros that expand to items must be delimited with braces or followed by a semicolon +//~| ERROR fn main() {} diff --git a/tests/ui/proc-macro/issue-91800.stderr b/tests/ui/proc-macro/issue-91800.stderr index d831d62e919d..63ebc0a552e3 100644 --- a/tests/ui/proc-macro/issue-91800.stderr +++ b/tests/ui/proc-macro/issue-91800.stderr @@ -21,7 +21,7 @@ LL | #[derive(MyTrait)] = note: this error originates in the derive macro `MyTrait` (in Nightly builds, run with -Z macro-backtrace for more info) error: macros that expand to items must be delimited with braces or followed by a semicolon - --> $DIR/issue-91800.rs:9:1 + --> $DIR/issue-91800.rs:10:1 | LL | #[attribute_macro] | ^^^^^^^^^^^^^^^^^^ @@ -29,7 +29,7 @@ LL | #[attribute_macro] = note: this error originates in the attribute macro `attribute_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: - --> $DIR/issue-91800.rs:9:1 + --> $DIR/issue-91800.rs:10:1 | LL | #[attribute_macro] | ^^^^^^^^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL | #[attribute_macro] = note: this error originates in the attribute macro `attribute_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: macros that expand to items must be delimited with braces or followed by a semicolon - --> $DIR/issue-91800.rs:13:1 + --> $DIR/issue-91800.rs:15:1 | LL | fn_macro! {} | ^^^^^^^^^^^^ @@ -45,7 +45,7 @@ LL | fn_macro! {} = note: this error originates in the macro `fn_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: - --> $DIR/issue-91800.rs:13:1 + --> $DIR/issue-91800.rs:15:1 | LL | fn_macro! {} | ^^^^^^^^^^^^ From 5c160f511e321a89eef01fcf17c6cc4c0f4e5c00 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 7 Apr 2025 15:44:12 +0300 Subject: [PATCH 175/606] compiletest: Stricter parsing for diagnostic kinds --- src/tools/compiletest/src/errors.rs | 66 ++++++++++--------- src/tools/compiletest/src/json.rs | 6 +- tests/ui/async-await/issue-70818.rs | 2 +- tests/ui/async-await/issue-71137.rs | 2 +- tests/ui/const-generics/defaults/mismatch.rs | 10 +-- .../dont-evaluate-array-len-on-err-1.rs | 2 +- .../abstract-const-as-cast-3.rs | 24 +++---- .../generic_const_exprs/issue-72787.rs | 8 +-- ...9518-default_trait_method_normalization.rs | 2 +- tests/ui/impl-trait/impl-generic-mismatch.rs | 8 +-- .../assignment-operator-unimplemented.rs | 2 +- tests/ui/modules/issue-107649.rs | 2 +- .../cache-after-waiting-issue-111528.rs | 2 +- ...iable-with-name-similar-to-struct-field.rs | 6 +- tests/ui/suggestions/issue-103646.rs | 2 +- tests/ui/type-alias-impl-trait/issue-53598.rs | 2 +- 16 files changed, 74 insertions(+), 72 deletions(-) diff --git a/src/tools/compiletest/src/errors.rs b/src/tools/compiletest/src/errors.rs index e1face32716c..9b59e4968a3d 100644 --- a/src/tools/compiletest/src/errors.rs +++ b/src/tools/compiletest/src/errors.rs @@ -3,7 +3,6 @@ use std::fs::File; use std::io::BufReader; use std::io::prelude::*; use std::path::Path; -use std::str::FromStr; use std::sync::OnceLock; use regex::Regex; @@ -18,30 +17,39 @@ pub enum ErrorKind { Warning, } -impl FromStr for ErrorKind { - type Err = (); - fn from_str(s: &str) -> Result { - let s = s.to_uppercase(); - let part0: &str = s.split(':').next().unwrap(); - match part0 { - "HELP" => Ok(ErrorKind::Help), - "ERROR" => Ok(ErrorKind::Error), - "NOTE" => Ok(ErrorKind::Note), - "SUGGESTION" => Ok(ErrorKind::Suggestion), - "WARN" | "WARNING" => Ok(ErrorKind::Warning), - _ => Err(()), +impl ErrorKind { + pub fn from_compiler_str(s: &str) -> ErrorKind { + match s { + "help" => ErrorKind::Help, + "error" | "error: internal compiler error" => ErrorKind::Error, + "note" | "failure-note" => ErrorKind::Note, + "warning" => ErrorKind::Warning, + _ => panic!("unexpected compiler diagnostic kind `{s}`"), } } + + /// Either the canonical uppercase string, or some additional versions for compatibility. + /// FIXME: consider keeping only the canonical versions here. + fn from_user_str(s: &str) -> Option { + Some(match s { + "HELP" | "help" => ErrorKind::Help, + "ERROR" | "error" => ErrorKind::Error, + "NOTE" | "note" => ErrorKind::Note, + "SUGGESTION" => ErrorKind::Suggestion, + "WARN" | "WARNING" | "warn" | "warning" => ErrorKind::Warning, + _ => return None, + }) + } } impl fmt::Display for ErrorKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { - ErrorKind::Help => write!(f, "help message"), - ErrorKind::Error => write!(f, "error"), - ErrorKind::Note => write!(f, "note"), - ErrorKind::Suggestion => write!(f, "suggestion"), - ErrorKind::Warning => write!(f, "warning"), + ErrorKind::Help => write!(f, "HELP"), + ErrorKind::Error => write!(f, "ERROR"), + ErrorKind::Note => write!(f, "NOTE"), + ErrorKind::Suggestion => write!(f, "SUGGESTION"), + ErrorKind::Warning => write!(f, "WARN"), } } } @@ -64,7 +72,7 @@ impl Error { use colored::Colorize; format!( "{: <10}line {: >3}: {}", - self.kind.map(|kind| kind.to_string()).unwrap_or_default().to_uppercase(), + self.kind.map(|kind| kind.to_string()).unwrap_or_default(), self.line_num_str(), self.msg.cyan(), ) @@ -154,18 +162,12 @@ fn parse_expected( } // Get the part of the comment after the sigil (e.g. `~^^` or ~|). - let whole_match = captures.get(0).unwrap(); - let (_, mut msg) = line.split_at(whole_match.end()); - - let first_word = msg.split_whitespace().next().expect("Encountered unexpected empty comment"); - - // If we find `//~ ERROR foo` or something like that, skip the first word. - let kind = first_word.parse::().ok(); - if kind.is_some() { - msg = &msg.trim_start().split_at(first_word.len()).1; - } - - let msg = msg.trim().to_owned(); + let tag = captures.get(0).unwrap(); + let rest = line[tag.end()..].trim_start(); + let (kind_str, _) = rest.split_once(|c: char| !c.is_ascii_alphabetic()).unwrap_or((rest, "")); + let kind = ErrorKind::from_user_str(kind_str); + let untrimmed_msg = if kind.is_some() { &rest[kind_str.len()..] } else { rest }; + let msg = untrimmed_msg.strip_prefix(':').unwrap_or(untrimmed_msg).trim().to_owned(); let line_num_adjust = &captures["adjust"]; let (follow_prev, line_num) = if line_num_adjust == "|" { @@ -181,7 +183,7 @@ fn parse_expected( debug!( "line={:?} tag={:?} follow_prev={:?} kind={:?} msg={:?}", line_num, - whole_match.as_str(), + tag.as_str(), follow_prev, kind, msg diff --git a/src/tools/compiletest/src/json.rs b/src/tools/compiletest/src/json.rs index 2a6fcd6cf81a..62fe538ee32e 100644 --- a/src/tools/compiletest/src/json.rs +++ b/src/tools/compiletest/src/json.rs @@ -1,7 +1,6 @@ //! These structs are a subset of the ones found in `rustc_errors::json`. use std::path::{Path, PathBuf}; -use std::str::FromStr; use std::sync::OnceLock; use regex::Regex; @@ -230,7 +229,7 @@ fn push_actual_errors( // Convert multi-line messages into multiple errors. // We expect to replace these with something more structured anyhow. let mut message_lines = diagnostic.message.lines(); - let kind = ErrorKind::from_str(&diagnostic.level).ok(); + let kind = Some(ErrorKind::from_compiler_str(&diagnostic.level)); let first_line = message_lines.next().unwrap_or(&diagnostic.message); if primary_spans.is_empty() { static RE: OnceLock = OnceLock::new(); @@ -240,7 +239,8 @@ fn push_actual_errors( line_num: None, kind, msg: with_code(None, first_line), - require_annotation: !RE.get_or_init(re_init).is_match(first_line), + require_annotation: diagnostic.level != "failure-note" + && !RE.get_or_init(re_init).is_match(first_line), }); } else { for span in primary_spans { diff --git a/tests/ui/async-await/issue-70818.rs b/tests/ui/async-await/issue-70818.rs index 36295a84e7ad..bc181de8d925 100644 --- a/tests/ui/async-await/issue-70818.rs +++ b/tests/ui/async-await/issue-70818.rs @@ -2,7 +2,7 @@ use std::future::Future; fn foo(ty: T, ty1: U) -> impl Future + Send { - //~^ Error future cannot be sent between threads safely + //~^ ERROR future cannot be sent between threads safely async { (ty, ty1) } } diff --git a/tests/ui/async-await/issue-71137.rs b/tests/ui/async-await/issue-71137.rs index 551cf85047ca..6fbf17ccf0d0 100644 --- a/tests/ui/async-await/issue-71137.rs +++ b/tests/ui/async-await/issue-71137.rs @@ -19,5 +19,5 @@ async fn wrong_mutex() { } fn main() { - fake_spawn(wrong_mutex()); //~ Error future cannot be sent between threads safely + fake_spawn(wrong_mutex()); //~ ERROR future cannot be sent between threads safely } diff --git a/tests/ui/const-generics/defaults/mismatch.rs b/tests/ui/const-generics/defaults/mismatch.rs index ec131505ed75..3e35c2060b1e 100644 --- a/tests/ui/const-generics/defaults/mismatch.rs +++ b/tests/ui/const-generics/defaults/mismatch.rs @@ -5,18 +5,18 @@ pub struct Example4; fn main() { let e: Example<13> = (); - //~^ Error: mismatched types + //~^ ERROR mismatched types //~| expected struct `Example` let e: Example2 = (); - //~^ Error: mismatched types + //~^ ERROR mismatched types //~| expected struct `Example2` let e: Example3<13, u32> = (); - //~^ Error: mismatched types + //~^ ERROR mismatched types //~| expected struct `Example3` let e: Example3<7> = (); - //~^ Error: mismatched types + //~^ ERROR mismatched types //~| expected struct `Example3<7>` let e: Example4<7> = (); - //~^ Error: mismatched types + //~^ ERROR mismatched types //~| expected struct `Example4<7>` } diff --git a/tests/ui/const-generics/dont-evaluate-array-len-on-err-1.rs b/tests/ui/const-generics/dont-evaluate-array-len-on-err-1.rs index 6c4ee1af210b..e7f050dae367 100644 --- a/tests/ui/const-generics/dont-evaluate-array-len-on-err-1.rs +++ b/tests/ui/const-generics/dont-evaluate-array-len-on-err-1.rs @@ -13,7 +13,7 @@ trait Foo { [Adt; std::mem::size_of::()]: , { <[Adt; std::mem::size_of::()] as Foo>::bar() - //~^ Error: the trait bound + //~^ ERROR the trait bound } fn bar() {} diff --git a/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.rs b/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.rs index 7561ae2febbd..33872ce7f0f2 100644 --- a/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.rs +++ b/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.rs @@ -15,15 +15,15 @@ where // errors are bad but seems to be pre-existing issue #86198 assert_impl::>(); - //~^ Error: mismatched types - //~^^ Error: unconstrained generic constant + //~^ ERROR mismatched types + //~^^ ERROR unconstrained generic constant assert_impl::>(); - //~^ Error: mismatched types - //~^^ Error: unconstrained generic constant + //~^ ERROR mismatched types + //~^^ ERROR unconstrained generic constant assert_impl::>(); - //~^ Error: mismatched types + //~^ ERROR mismatched types assert_impl::>(); - //~^ Error: mismatched types + //~^ ERROR mismatched types } pub fn use_trait_impl_2() where @@ -33,15 +33,15 @@ where // errors are bad but seems to be pre-existing issue #86198 assert_impl::>(); - //~^ Error: mismatched types - //~^^ Error: unconstrained generic constant + //~^ ERROR mismatched types + //~^^ ERROR unconstrained generic constant assert_impl::>(); - //~^ Error: mismatched types - //~^^ Error: unconstrained generic constant + //~^ ERROR mismatched types + //~^^ ERROR unconstrained generic constant assert_impl::>(); - //~^ Error: mismatched types + //~^ ERROR mismatched types assert_impl::>(); - //~^ Error: mismatched types + //~^ ERROR mismatched types } fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-72787.rs b/tests/ui/const-generics/generic_const_exprs/issue-72787.rs index c3208786708b..ea65b6d3fdf2 100644 --- a/tests/ui/const-generics/generic_const_exprs/issue-72787.rs +++ b/tests/ui/const-generics/generic_const_exprs/issue-72787.rs @@ -9,8 +9,8 @@ pub trait True {} impl True for IsLessOrEqual where Condition<{ LHS <= RHS }>: True -//[min]~^ Error generic parameters may not be used in const operations -//[min]~| Error generic parameters may not be used in const operations +//[min]~^ ERROR generic parameters may not be used in const operations +//[min]~| ERROR generic parameters may not be used in const operations { } impl True for Condition {} @@ -21,8 +21,8 @@ where IsLessOrEqual: True, IsLessOrEqual: True, IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, -//[min]~^ Error generic parameters may not be used in const operations -//[min]~| Error generic parameters may not be used in const operations +//[min]~^ ERROR generic parameters may not be used in const operations +//[min]~| ERROR generic parameters may not be used in const operations // Condition<{ 8 - I <= 8 - J }>: True, { fn print() { diff --git a/tests/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.rs b/tests/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.rs index 2fa9a71fbb33..f08b9ceffb96 100644 --- a/tests/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.rs +++ b/tests/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.rs @@ -14,7 +14,7 @@ trait Foo { [(); std::mem::size_of::()]: , { Self::AssocInstance == [(); std::mem::size_of::()]; - //~^ Error: mismatched types + //~^ ERROR mismatched types } } diff --git a/tests/ui/impl-trait/impl-generic-mismatch.rs b/tests/ui/impl-trait/impl-generic-mismatch.rs index fb8bde0d0813..f05e01716c31 100644 --- a/tests/ui/impl-trait/impl-generic-mismatch.rs +++ b/tests/ui/impl-trait/impl-generic-mismatch.rs @@ -6,7 +6,7 @@ trait Foo { impl Foo for () { fn foo(&self, _: &U) { } - //~^ Error method `foo` has incompatible signature for trait + //~^ ERROR method `foo` has incompatible signature for trait } trait Bar { @@ -15,7 +15,7 @@ trait Bar { impl Bar for () { fn bar(&self, _: &impl Debug) { } - //~^ Error method `bar` has incompatible signature for trait + //~^ ERROR method `bar` has incompatible signature for trait } trait Baz { @@ -24,7 +24,7 @@ trait Baz { impl Baz for () { fn baz(&self, _: &impl Debug, _: &T) { } - //~^ Error method `baz` has incompatible signature for trait + //~^ ERROR method `baz` has incompatible signature for trait } // With non-local trait (#49841): @@ -35,7 +35,7 @@ struct X; impl Hash for X { fn hash(&self, hasher: &mut impl Hasher) {} - //~^ Error method `hash` has incompatible signature for trait + //~^ ERROR method `hash` has incompatible signature for trait } fn main() {} diff --git a/tests/ui/mismatched_types/assignment-operator-unimplemented.rs b/tests/ui/mismatched_types/assignment-operator-unimplemented.rs index 21df464d5e45..04a379bbd048 100644 --- a/tests/ui/mismatched_types/assignment-operator-unimplemented.rs +++ b/tests/ui/mismatched_types/assignment-operator-unimplemented.rs @@ -3,5 +3,5 @@ struct Foo; fn main() { let mut a = Foo; let ref b = Foo; - a += *b; //~ Error: binary assignment operation `+=` cannot be applied to type `Foo` + a += *b; //~ ERROR binary assignment operation `+=` cannot be applied to type `Foo` } diff --git a/tests/ui/modules/issue-107649.rs b/tests/ui/modules/issue-107649.rs index af5758d79858..f93fb07e17af 100644 --- a/tests/ui/modules/issue-107649.rs +++ b/tests/ui/modules/issue-107649.rs @@ -102,5 +102,5 @@ fn main() { (); (); (); - dbg!(lib::Dummy); //~ Error: `Dummy` doesn't implement `Debug` + dbg!(lib::Dummy); //~ ERROR `Dummy` doesn't implement `Debug` } diff --git a/tests/ui/parallel-rustc/cache-after-waiting-issue-111528.rs b/tests/ui/parallel-rustc/cache-after-waiting-issue-111528.rs index b23cb9ce917b..73d173022f6a 100644 --- a/tests/ui/parallel-rustc/cache-after-waiting-issue-111528.rs +++ b/tests/ui/parallel-rustc/cache-after-waiting-issue-111528.rs @@ -10,7 +10,7 @@ pub fn a() { #[export_name="fail"] pub fn b() { -//~^ Error symbol `fail` is already defined +//~^ ERROR symbol `fail` is already defined } fn main() {} diff --git a/tests/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs b/tests/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs index ecd3f5881190..7216b0294dce 100644 --- a/tests/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs +++ b/tests/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs @@ -4,15 +4,15 @@ struct A { impl A { fn new(cofig: String) -> Self { - Self { config } //~ Error cannot find value `config` in this scope + Self { config } //~ ERROR cannot find value `config` in this scope } fn do_something(cofig: String) { - println!("{config}"); //~ Error cannot find value `config` in this scope + println!("{config}"); //~ ERROR cannot find value `config` in this scope } fn self_is_available(self, cofig: String) { - println!("{config}"); //~ Error cannot find value `config` in this scope + println!("{config}"); //~ ERROR cannot find value `config` in this scope } } diff --git a/tests/ui/suggestions/issue-103646.rs b/tests/ui/suggestions/issue-103646.rs index f679640c5dc9..d8b06d663aff 100644 --- a/tests/ui/suggestions/issue-103646.rs +++ b/tests/ui/suggestions/issue-103646.rs @@ -5,7 +5,7 @@ trait Cat { fn uwu(c: T) { c.nya(); //~^ ERROR no method named `nya` found for type parameter `T` in the current scope - //~| Suggestion T::nya() + //~| SUGGESTION T::nya() } fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-53598.rs b/tests/ui/type-alias-impl-trait/issue-53598.rs index 3262c69cf5a4..d8eee3218ed3 100644 --- a/tests/ui/type-alias-impl-trait/issue-53598.rs +++ b/tests/ui/type-alias-impl-trait/issue-53598.rs @@ -17,7 +17,7 @@ impl Foo for S2 { type Item = impl Debug; fn foo(_: T) -> Self::Item { - //~^ Error type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias + //~^ ERROR type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias S::(Default::default()) } } From e1a69da856c31bfaad602388f69ea86f111ebfe6 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 7 Apr 2025 18:16:07 +0200 Subject: [PATCH 176/606] unstable-book/intrinsics: wordsmith MIR-lowering intrinsic docs --- src/doc/unstable-book/src/language-features/intrinsics.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/doc/unstable-book/src/language-features/intrinsics.md b/src/doc/unstable-book/src/language-features/intrinsics.md index a0e38f340f58..9e59dd889985 100644 --- a/src/doc/unstable-book/src/language-features/intrinsics.md +++ b/src/doc/unstable-book/src/language-features/intrinsics.md @@ -53,7 +53,8 @@ Various intrinsics have native MIR operations that they correspond to. Instead o backends to implement both the intrinsic and the MIR operation, the `lower_intrinsics` pass will convert the calls to the MIR operation. Backends do not need to know about these intrinsics at all. These intrinsics only make sense without a body, and can be declared as a `#[rustc_intrinsic]`. -The body is never used, as calls to the intrinsic do not exist anymore after MIR analyses. +The body is never used as the lowering pass implements support for all backends, so we never have to +use the fallback logic. ## Intrinsics without fallback logic From fd854a772e12ee51c0028e9dbb9443d831e28327 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 7 Apr 2025 19:13:16 +0300 Subject: [PATCH 177/606] compiletest: Avoid ignoring empty diagnostics in one more place This catches some silly notes emitted by rustc, which should ideally be fixed --- src/tools/compiletest/src/runtest.rs | 3 +-- tests/incremental/circular-dependencies.rs | 1 + .../consts/const_in_pattern/reject_non_structural.rs | 1 + .../const_in_pattern/reject_non_structural.stderr | 8 ++++---- tests/ui/fn/param-mismatch-foreign.rs | 1 + tests/ui/fn/param-mismatch-foreign.stderr | 2 +- tests/ui/mismatched_types/similar_paths_primitive.rs | 3 ++- .../mismatched_types/similar_paths_primitive.stderr | 6 +++--- .../moves/nested-loop-moved-value-wrong-continue.rs | 6 +++++- .../nested-loop-moved-value-wrong-continue.stderr | 12 ++++++------ .../issue-87217-keyword-order/const-async-const.rs | 1 + .../issue-87217-keyword-order/several-kw-jump.rs | 1 + 12 files changed, 27 insertions(+), 18 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 1002c290b603..13f3479247a2 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -810,8 +810,7 @@ impl<'test> TestCx<'test> { expect_help: bool, expect_note: bool, ) -> bool { - !actual_error.msg.is_empty() - && actual_error.require_annotation + actual_error.require_annotation && match actual_error.kind { Some(ErrorKind::Help) => expect_help, Some(ErrorKind::Note) => expect_note, diff --git a/tests/incremental/circular-dependencies.rs b/tests/incremental/circular-dependencies.rs index c7b5b931fbbe..bd3b109b62c7 100644 --- a/tests/incremental/circular-dependencies.rs +++ b/tests/incremental/circular-dependencies.rs @@ -15,6 +15,7 @@ pub struct Foo; pub fn consume_foo(_: Foo) {} //[cfail2]~^ NOTE function defined here +//[cfail2]~| NOTE pub fn produce_foo() -> Foo { Foo diff --git a/tests/ui/consts/const_in_pattern/reject_non_structural.rs b/tests/ui/consts/const_in_pattern/reject_non_structural.rs index 39e5f732a898..6478bf9c6ee1 100644 --- a/tests/ui/consts/const_in_pattern/reject_non_structural.rs +++ b/tests/ui/consts/const_in_pattern/reject_non_structural.rs @@ -93,6 +93,7 @@ fn main() { //~| NOTE constant of non-structural type trait Trait: Sized { const ASSOC: Option; } //~ NOTE constant defined here + //~^ NOTE impl Trait for NoDerive { const ASSOC: Option = Some(NoDerive); } match Some(NoDerive) { NoDerive::ASSOC => dbg!(NoDerive::ASSOC), _ => panic!("whoops"), }; //~^ ERROR constant of non-structural type `NoDerive` in a pattern diff --git a/tests/ui/consts/const_in_pattern/reject_non_structural.stderr b/tests/ui/consts/const_in_pattern/reject_non_structural.stderr index fa16d0b06a7f..bf54d3d76aed 100644 --- a/tests/ui/consts/const_in_pattern/reject_non_structural.stderr +++ b/tests/ui/consts/const_in_pattern/reject_non_structural.stderr @@ -118,14 +118,14 @@ LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: constant of non-structural type `NoDerive` in a pattern - --> $DIR/reject_non_structural.rs:97:28 + --> $DIR/reject_non_structural.rs:98:28 | LL | struct NoDerive; | --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns ... LL | trait Trait: Sized { const ASSOC: Option; } | ------------------ ------------------------- constant defined here -LL | impl Trait for NoDerive { const ASSOC: Option = Some(NoDerive); } +... LL | match Some(NoDerive) { NoDerive::ASSOC => dbg!(NoDerive::ASSOC), _ => panic!("whoops"), }; | ^^^^^^^^^^^^^^^ constant of non-structural type | @@ -136,7 +136,7 @@ LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: constant of non-structural type `NoDerive` in a pattern - --> $DIR/reject_non_structural.rs:102:28 + --> $DIR/reject_non_structural.rs:103:28 | LL | struct NoDerive; | --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns @@ -153,7 +153,7 @@ LL | impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: constant of non-structural type `NoDerive` in a pattern - --> $DIR/reject_non_structural.rs:107:29 + --> $DIR/reject_non_structural.rs:108:29 | LL | struct NoDerive; | --------------- `NoDerive` must be annotated with `#[derive(PartialEq)]` to be usable in patterns diff --git a/tests/ui/fn/param-mismatch-foreign.rs b/tests/ui/fn/param-mismatch-foreign.rs index 2ab2bf95448a..eebca29d6c93 100644 --- a/tests/ui/fn/param-mismatch-foreign.rs +++ b/tests/ui/fn/param-mismatch-foreign.rs @@ -1,6 +1,7 @@ extern "C" { fn foo(x: i32, y: u32, z: i32); //~^ NOTE function defined here + //~| NOTE } fn main() { diff --git a/tests/ui/fn/param-mismatch-foreign.stderr b/tests/ui/fn/param-mismatch-foreign.stderr index 835e0a3343e9..fff3283cbb6c 100644 --- a/tests/ui/fn/param-mismatch-foreign.stderr +++ b/tests/ui/fn/param-mismatch-foreign.stderr @@ -1,5 +1,5 @@ error[E0061]: this function takes 3 arguments but 2 arguments were supplied - --> $DIR/param-mismatch-foreign.rs:7:5 + --> $DIR/param-mismatch-foreign.rs:8:5 | LL | foo(1i32, 2i32); | ^^^ ---- argument #2 of type `u32` is missing diff --git a/tests/ui/mismatched_types/similar_paths_primitive.rs b/tests/ui/mismatched_types/similar_paths_primitive.rs index a58fe68b8638..b20ca80ac071 100644 --- a/tests/ui/mismatched_types/similar_paths_primitive.rs +++ b/tests/ui/mismatched_types/similar_paths_primitive.rs @@ -4,8 +4,9 @@ struct bool; //~ NOTE the other `bool` is defined in the current crate struct str; //~ NOTE the other `str` is defined in the current crate fn foo(_: bool) {} //~ NOTE function defined here + //~^ NOTE fn bar(_: &str) {} //~ NOTE function defined here - + //~^ NOTE fn main() { foo(true); //~^ ERROR mismatched types [E0308] diff --git a/tests/ui/mismatched_types/similar_paths_primitive.stderr b/tests/ui/mismatched_types/similar_paths_primitive.stderr index cf26234dba85..9c1aa0d7105b 100644 --- a/tests/ui/mismatched_types/similar_paths_primitive.stderr +++ b/tests/ui/mismatched_types/similar_paths_primitive.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/similar_paths_primitive.rs:10:9 + --> $DIR/similar_paths_primitive.rs:11:9 | LL | foo(true); | --- ^^^^ expected `bool`, found a different `bool` @@ -20,7 +20,7 @@ LL | fn foo(_: bool) {} | ^^^ ------- error[E0308]: mismatched types - --> $DIR/similar_paths_primitive.rs:16:9 + --> $DIR/similar_paths_primitive.rs:17:9 | LL | bar("hello"); | --- ^^^^^^^ expected `str`, found a different `str` @@ -35,7 +35,7 @@ note: the other `str` is defined in the current crate LL | struct str; | ^^^^^^^^^^ note: function defined here - --> $DIR/similar_paths_primitive.rs:7:4 + --> $DIR/similar_paths_primitive.rs:8:4 | LL | fn bar(_: &str) {} | ^^^ ------- diff --git a/tests/ui/moves/nested-loop-moved-value-wrong-continue.rs b/tests/ui/moves/nested-loop-moved-value-wrong-continue.rs index 0235b291df54..87800d314ed5 100644 --- a/tests/ui/moves/nested-loop-moved-value-wrong-continue.rs +++ b/tests/ui/moves/nested-loop-moved-value-wrong-continue.rs @@ -9,6 +9,8 @@ fn foo() { //~| NOTE inside of this loop //~| HELP consider moving the expression out of the loop //~| NOTE in this expansion of desugaring of `for` loop + //~| NOTE + //~| NOTE baz.push(foo); //~^ NOTE value moved here //~| HELP consider cloning the value @@ -30,17 +32,19 @@ fn main() { for foo in foos { //~^ NOTE this reinitialization might get skipped //~| NOTE move occurs because `foo` has type `String` + //~| NOTE for bar in &bars { //~^ NOTE inside of this loop //~| HELP consider moving the expression out of the loop //~| NOTE in this expansion of desugaring of `for` loop + //~| NOTE if foo == *bar { baz.push(foo); //~^ NOTE value moved here //~| HELP consider cloning the value continue; //~^ NOTE verify that your loop breaking logic is correct - //~| NOTE this `continue` advances the loop at line 33 + //~| NOTE this `continue` advances the loop at line 36 } } qux.push(foo); diff --git a/tests/ui/moves/nested-loop-moved-value-wrong-continue.stderr b/tests/ui/moves/nested-loop-moved-value-wrong-continue.stderr index cf863ff8af14..6ef1a4193b1a 100644 --- a/tests/ui/moves/nested-loop-moved-value-wrong-continue.stderr +++ b/tests/ui/moves/nested-loop-moved-value-wrong-continue.stderr @@ -1,5 +1,5 @@ error[E0382]: use of moved value: `foo` - --> $DIR/nested-loop-moved-value-wrong-continue.rs:19:14 + --> $DIR/nested-loop-moved-value-wrong-continue.rs:21:14 | LL | for foo in foos { for bar in &bars { if foo == *bar { | --- ---------------- inside of this loop @@ -14,13 +14,13 @@ LL | qux.push(foo); | ^^^ value used here after move | note: verify that your loop breaking logic is correct - --> $DIR/nested-loop-moved-value-wrong-continue.rs:15:9 + --> $DIR/nested-loop-moved-value-wrong-continue.rs:17:9 | LL | for foo in foos { for bar in &bars { if foo == *bar { | --------------- ---------------- ... LL | continue; - | ^^^^^^^^ this `continue` advances the loop at $DIR/nested-loop-moved-value-wrong-continue.rs:6:23: 18:8 + | ^^^^^^^^ this `continue` advances the loop at $DIR/nested-loop-moved-value-wrong-continue.rs:6:23: 20:8 help: consider moving the expression out of the loop so it is only moved once | LL ~ for foo in foos { let mut value = baz.push(foo); @@ -36,7 +36,7 @@ LL | baz.push(foo.clone()); | ++++++++ error[E0382]: use of moved value: `foo` - --> $DIR/nested-loop-moved-value-wrong-continue.rs:46:18 + --> $DIR/nested-loop-moved-value-wrong-continue.rs:50:18 | LL | for foo in foos { | --- @@ -54,7 +54,7 @@ LL | qux.push(foo); | ^^^ value used here after move | note: verify that your loop breaking logic is correct - --> $DIR/nested-loop-moved-value-wrong-continue.rs:41:17 + --> $DIR/nested-loop-moved-value-wrong-continue.rs:45:17 | LL | for foo in foos { | --------------- @@ -63,7 +63,7 @@ LL | for bar in &bars { | ---------------- ... LL | continue; - | ^^^^^^^^ this `continue` advances the loop at line 33 + | ^^^^^^^^ this `continue` advances the loop at line 36 help: consider moving the expression out of the loop so it is only moved once | LL ~ let mut value = baz.push(foo); diff --git a/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.rs b/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.rs index e6235b1e8923..c137e1363359 100644 --- a/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.rs +++ b/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.rs @@ -10,5 +10,6 @@ const async const fn test() {} //~| ERROR functions cannot be both `const` and `async` //~| NOTE `const` because of this //~| NOTE `async` because of this +//~| NOTE fn main() {} diff --git a/tests/ui/parser/issues/issue-87217-keyword-order/several-kw-jump.rs b/tests/ui/parser/issues/issue-87217-keyword-order/several-kw-jump.rs index 40f993eafbb1..49a49d337c47 100644 --- a/tests/ui/parser/issues/issue-87217-keyword-order/several-kw-jump.rs +++ b/tests/ui/parser/issues/issue-87217-keyword-order/several-kw-jump.rs @@ -15,5 +15,6 @@ async unsafe const fn test() {} //~| ERROR functions cannot be both `const` and `async` //~| NOTE `const` because of this //~| NOTE `async` because of this +//~| NOTE fn main() {} From 2fb550bd548f11086c633a2f9640780f9692bb9b Mon Sep 17 00:00:00 2001 From: rustbot <47979223+rustbot@users.noreply.github.com> Date: Mon, 7 Apr 2025 19:01:05 +0200 Subject: [PATCH 178/606] Update books --- src/doc/reference | 2 +- src/doc/rust-by-example | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/reference b/src/doc/reference index e95ebdfee025..46435cd4eba1 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit e95ebdfee02514d93f79ec92ae310a804e87f01f +Subproject commit 46435cd4eba11b66acaa42c01da5c80ad88aee4b diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index 6f69823c28ae..0d7964d5b22c 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit 6f69823c28ae8d929d6c815181c73d3e99ef16d3 +Subproject commit 0d7964d5b22cf920237ef1282d869564b4883b88 From a7400a8b9065b3563d7345c220590282d768be65 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 7 Apr 2025 19:06:34 +0200 Subject: [PATCH 179/606] update intrinsics/mod.rs comment about const intrinsics --- library/core/src/intrinsics/mod.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 7fa57df9928c..933b5aec70c6 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -5,15 +5,11 @@ //! //! # Const intrinsics //! -//! Note: any changes to the constness of intrinsics should be discussed with the language team. -//! This includes changes in the stability of the constness. -//! -//! //FIXME(#132735) "old" style intrinsics support has been removed -//! In order to make an intrinsic usable at compile-time, it needs to be declared in the "new" -//! style, i.e. as a `#[rustc_intrinsic]` function, not inside an `extern` block. Then copy the -//! implementation from to +//! In order to make an intrinsic unstable usable at compile-time, copy the implementation from +//! to //! -//! and make the intrinsic declaration a `const fn`. +//! and make the intrinsic declaration below a `const fn`. This should be done in coordination with +//! wg-const-eval. //! //! If an intrinsic is supposed to be used from a `const fn` with a `rustc_const_stable` attribute, //! `#[rustc_intrinsic_const_stable_indirect]` needs to be added to the intrinsic. Such a change requires From 14d1215719d4f06baa44831c5c22f2c7ef4cc687 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 7 Apr 2025 18:06:21 +0000 Subject: [PATCH 180/606] Restrict some queries by def-kind more --- compiler/rustc_hir_analysis/src/collect.rs | 4 ++- .../rustc_hir_analysis/src/variance/mod.rs | 10 ++++-- compiler/rustc_metadata/src/rmeta/encoder.rs | 2 +- compiler/rustc_ty_utils/src/implied_bounds.rs | 31 ++++++++++++------- compiler/rustc_ty_utils/src/opaque_types.rs | 20 +++++++----- compiler/rustc_ty_utils/src/sig_types.rs | 2 +- 6 files changed, 43 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index e9cd22435d95..a33707649fcf 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -14,6 +14,7 @@ //! At present, however, we do run collection across all items in the //! crate as a kind of pass. This should eventually be factored away. +use std::assert_matches::assert_matches; use std::cell::Cell; use std::iter; use std::ops::Bound; @@ -1344,7 +1345,8 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn compute_sig_of_foreign_fn_decl(tcx, def_id, sig.decl, abi, sig.header.safety()) } - Ctor(data) | Variant(hir::Variant { data, .. }) if data.ctor().is_some() => { + Ctor(data) => { + assert_matches!(data.ctor(), Some(_)); let adt_def_id = tcx.hir_get_parent_item(hir_id).def_id.to_def_id(); let ty = tcx.type_of(adt_def_id).instantiate_identity(); let inputs = data.fields().iter().map(|f| tcx.type_of(f.def_id).instantiate_identity()); diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs index 0800d99e9452..dbba45dc7bb5 100644 --- a/compiler/rustc_hir_analysis/src/variance/mod.rs +++ b/compiler/rustc_hir_analysis/src/variance/mod.rs @@ -44,13 +44,13 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] { return &[]; } - match tcx.def_kind(item_def_id) { + let kind = tcx.def_kind(item_def_id); + match kind { DefKind::Fn | DefKind::AssocFn | DefKind::Enum | DefKind::Struct | DefKind::Union - | DefKind::Variant | DefKind::Ctor(..) => { // These are inferred. let crate_map = tcx.crate_variances(()); @@ -89,7 +89,11 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] { } // Variance not relevant. - span_bug!(tcx.def_span(item_def_id), "asked to compute variance for wrong kind of item"); + span_bug!( + tcx.def_span(item_def_id), + "asked to compute variance for {}", + kind.descr(item_def_id.to_def_id()) + ); } #[derive(Debug, Copy, Clone)] diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 167122a9793a..55bb984c5b69 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1099,7 +1099,6 @@ fn should_encode_variances<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, def_kind: Def DefKind::Struct | DefKind::Union | DefKind::Enum - | DefKind::Variant | DefKind::OpaqueTy | DefKind::Fn | DefKind::Ctor(..) @@ -1109,6 +1108,7 @@ fn should_encode_variances<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, def_kind: Def matches!(tcx.opt_rpitit_info(def_id), Some(ty::ImplTraitInTraitData::Trait { .. })) } DefKind::Mod + | DefKind::Variant | DefKind::Field | DefKind::AssocConst | DefKind::TyParam diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs index 088d5e76b868..492a20a7d5b7 100644 --- a/compiler/rustc_ty_utils/src/implied_bounds.rs +++ b/compiler/rustc_ty_utils/src/implied_bounds.rs @@ -4,9 +4,9 @@ use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; -use rustc_middle::bug; use rustc_middle::query::Providers; use rustc_middle::ty::{self, Ty, TyCtxt, fold_regions}; +use rustc_middle::{bug, span_bug}; use rustc_span::Span; pub(crate) fn provide(providers: &mut Providers) { @@ -21,7 +21,8 @@ pub(crate) fn provide(providers: &mut Providers) { } fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<'tcx>, Span)] { - match tcx.def_kind(def_id) { + let kind = tcx.def_kind(def_id); + match kind { DefKind::Fn => { let sig = tcx.fn_sig(def_id).instantiate_identity(); let liberated_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig); @@ -121,32 +122,38 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<' } } DefKind::AssocConst | DefKind::AssocTy => tcx.assumed_wf_types(tcx.local_parent(def_id)), - DefKind::OpaqueTy => bug!("implied bounds are not defined for opaques"), - DefKind::Mod + DefKind::Static { .. } + | DefKind::Const + | DefKind::AnonConst + | DefKind::InlineConst | DefKind::Struct | DefKind::Union | DefKind::Enum - | DefKind::Variant | DefKind::Trait - | DefKind::TyAlias - | DefKind::ForeignTy | DefKind::TraitAlias + | DefKind::TyAlias => ty::List::empty(), + DefKind::OpaqueTy + | DefKind::Mod + | DefKind::Variant + | DefKind::ForeignTy | DefKind::TyParam - | DefKind::Const | DefKind::ConstParam - | DefKind::Static { .. } | DefKind::Ctor(_, _) | DefKind::Macro(_) | DefKind::ExternCrate | DefKind::Use | DefKind::ForeignMod - | DefKind::AnonConst - | DefKind::InlineConst | DefKind::Field | DefKind::LifetimeParam | DefKind::GlobalAsm | DefKind::Closure - | DefKind::SyntheticCoroutineBody => ty::List::empty(), + | DefKind::SyntheticCoroutineBody => { + span_bug!( + tcx.def_span(def_id), + "`assumed_wf_types` not defined for {} `{def_id:?}`", + kind.descr(def_id.to_def_id()) + ); + } } } diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index 3aad97d86cca..cd730aeeea90 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -3,10 +3,10 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit; use rustc_hir::intravisit::Visitor; -use rustc_middle::bug; use rustc_middle::query::Providers; use rustc_middle::ty::util::{CheckRegions, NotUniqueParam}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor}; +use rustc_middle::{bug, span_bug}; use rustc_span::Span; use tracing::{instrument, trace}; @@ -320,9 +320,12 @@ fn opaque_types_defined_by<'tcx>( | DefKind::AnonConst => { collector.collect_taits_declared_in_body(); } + // Closures and coroutines are type checked with their parent + DefKind::Closure | DefKind::InlineConst => { + collector.opaques.extend(tcx.opaque_types_defined_by(tcx.local_parent(item))); + } + DefKind::AssocTy | DefKind::TyAlias | DefKind::GlobalAsm => {} DefKind::OpaqueTy - | DefKind::TyAlias - | DefKind::AssocTy | DefKind::Mod | DefKind::Struct | DefKind::Union @@ -340,12 +343,13 @@ fn opaque_types_defined_by<'tcx>( | DefKind::ForeignMod | DefKind::Field | DefKind::LifetimeParam - | DefKind::GlobalAsm | DefKind::Impl { .. } - | DefKind::SyntheticCoroutineBody => {} - // Closures and coroutines are type checked with their parent - DefKind::Closure | DefKind::InlineConst => { - collector.opaques.extend(tcx.opaque_types_defined_by(tcx.local_parent(item))); + | DefKind::SyntheticCoroutineBody => { + span_bug!( + tcx.def_span(item), + "`opaque_types_defined_by` not defined for {} `{item:?}`", + kind.descr(item.to_def_id()) + ); } } tcx.mk_local_def_ids(&collector.opaques) diff --git a/compiler/rustc_ty_utils/src/sig_types.rs b/compiler/rustc_ty_utils/src/sig_types.rs index 5bb96f90029a..dc6009116ac5 100644 --- a/compiler/rustc_ty_utils/src/sig_types.rs +++ b/compiler/rustc_ty_utils/src/sig_types.rs @@ -116,7 +116,7 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( "{kind:?} has not seen any uses of `walk_types` yet, ping oli-obk if you'd like any help" ) } - // These don't have any types. + // These don't have any types, but are visited during privacy checking. | DefKind::ExternCrate | DefKind::ForeignMod | DefKind::ForeignTy From b9754f9e7bfe2d8eed780962b550a25a87118ce4 Mon Sep 17 00:00:00 2001 From: "Celina G. Val" Date: Tue, 25 Feb 2025 13:24:07 -0800 Subject: [PATCH 181/606] Enable contracts for const functions Use `const_eval_select!()` macro to enable contract checking only at runtime. The existing contract logic relies on closures, which are not supported in constant functions. This commit also removes one level of indirection for ensures clauses, however, it currently has a spurious warning message when the bottom of the function is unreachable. --- compiler/rustc_ast_lowering/src/expr.rs | 13 +++-- compiler/rustc_hir/src/lang_items.rs | 2 + .../rustc_hir_analysis/src/check/intrinsic.rs | 12 ++-- library/core/src/contracts.rs | 13 ++--- library/core/src/intrinsics/mod.rs | 47 ++++++++++++++-- library/core/src/lib.rs | 1 - .../contract-attributes-nest.chk_pass.stderr | 13 ++++- .../ui/contracts/contract-attributes-nest.rs | 1 + ...act-attributes-nest.unchk_fail_post.stderr | 13 ++++- ...ract-attributes-nest.unchk_fail_pre.stderr | 13 ++++- ...contract-attributes-nest.unchk_pass.stderr | 13 ++++- .../contract-const-fn.all_pass.stderr | 11 ++++ tests/ui/contracts/contract-const-fn.rs | 56 +++++++++++++++++++ ...contract-const-fn.runtime_fail_post.stderr | 11 ++++ .../contract-const-fn.runtime_fail_pre.stderr | 11 ++++ .../contract-ast-extensions-nest.rs | 1 + .../internal_machinery/contract-intrinsics.rs | 6 +- .../internal_machinery/contract-lang-items.rs | 4 +- 18 files changed, 206 insertions(+), 35 deletions(-) create mode 100644 tests/ui/contracts/contract-const-fn.all_pass.stderr create mode 100644 tests/ui/contracts/contract-const-fn.rs create mode 100644 tests/ui/contracts/contract-const-fn.runtime_fail_post.stderr create mode 100644 tests/ui/contracts/contract-const-fn.runtime_fail_pre.stderr diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 80bb1e8fc414..0b7a76304311 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -397,12 +397,17 @@ impl<'hir> LoweringContext<'_, 'hir> { &mut self, expr: &'hir hir::Expr<'hir>, span: Span, - check_ident: Ident, - check_hir_id: HirId, + cond_ident: Ident, + cond_hir_id: HirId, ) -> &'hir hir::Expr<'hir> { - let checker_fn = self.expr_ident(span, check_ident, check_hir_id); + let cond_fn = self.expr_ident(span, cond_ident, cond_hir_id); let span = self.mark_span_with_reason(DesugaringKind::Contract, span, None); - self.expr_call(span, checker_fn, std::slice::from_ref(expr)) + let call_expr = self.expr_call_lang_item_fn_mut( + span, + hir::LangItem::ContractCheckEnsures, + arena_vec![self; *expr, *cond_fn], + ); + self.arena.alloc(call_expr) } pub(crate) fn lower_const_block(&mut self, c: &AnonConst) -> hir::ConstBlock { diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 90fab01ba2d4..fd15d0543179 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -439,6 +439,8 @@ language_item_table! { DefaultTrait3, sym::default_trait3, default_trait3_trait, Target::Trait, GenericRequirement::None; DefaultTrait2, sym::default_trait2, default_trait2_trait, Target::Trait, GenericRequirement::None; DefaultTrait1, sym::default_trait1, default_trait1_trait, Target::Trait, GenericRequirement::None; + + ContractCheckEnsures, sym::contract_check_ensures, contract_check_ensures_fn, Target::Fn, GenericRequirement::None; } /// The requirement imposed on the generics of a lang item diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 42d785c8dd0f..290e47b42b56 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -232,15 +232,11 @@ pub fn check_intrinsic_type( }; (n_tps, 0, 0, inputs, output, hir::Safety::Unsafe) } else if intrinsic_name == sym::contract_check_ensures { - // contract_check_ensures::<'a, Ret, C>(&'a Ret, C) - // where C: impl Fn(&'a Ret) -> bool, + // contract_check_ensures::(Ret, C) -> Ret + // where C: for<'a> Fn(&'a Ret) -> bool, // - // so: two type params, one lifetime param, 0 const params, two inputs, no return - - let p = generics.param_at(0, tcx); - let r = ty::Region::new_early_param(tcx, p.to_early_bound_region_data()); - let ref_ret = Ty::new_imm_ref(tcx, r, param(1)); - (2, 1, 0, vec![ref_ret, param(2)], tcx.types.unit, hir::Safety::Safe) + // so: two type params, 0 lifetime param, 0 const params, two inputs, no return + (2, 0, 0, vec![param(0), param(1)], param(0), hir::Safety::Safe) } else { let safety = intrinsic_operation_unsafety(tcx, intrinsic_id); let (n_tps, n_cts, inputs, output) = match intrinsic_name { diff --git a/library/core/src/contracts.rs b/library/core/src/contracts.rs index 8b79a3a7eba8..829226420181 100644 --- a/library/core/src/contracts.rs +++ b/library/core/src/contracts.rs @@ -5,16 +5,15 @@ pub use crate::macros::builtin::{contracts_ensures as ensures, contracts_require /// Emitted by rustc as a desugaring of `#[ensures(PRED)] fn foo() -> R { ... [return R;] ... }` /// into: `fn foo() { let _check = build_check_ensures(|ret| PRED) ... [return _check(R);] ... }` /// (including the implicit return of the tail expression, if any). +/// +/// This call helps with type inference for the predicate. #[unstable(feature = "contracts_internals", issue = "128044" /* compiler-team#759 */)] +#[rustc_const_unstable(feature = "contracts", issue = "128044")] #[lang = "contract_build_check_ensures"] #[track_caller] -pub fn build_check_ensures(cond: C) -> impl (Fn(Ret) -> Ret) + Copy +pub const fn build_check_ensures(cond: C) -> C where - C: for<'a> Fn(&'a Ret) -> bool + Copy + 'static, + C: Fn(&Ret) -> bool + Copy + 'static, { - #[track_caller] - move |ret| { - crate::intrinsics::contract_check_ensures(&ret, cond); - ret - } + cond } diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 81e59a1f349e..8812cb66526b 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -3450,20 +3450,55 @@ pub const fn contract_checks() -> bool { /// /// By default, if `contract_checks` is enabled, this will panic with no unwind if the condition /// returns false. -#[unstable(feature = "contracts_internals", issue = "128044" /* compiler-team#759 */)] +/// +/// Note that this function is a no-op during constant evaluation. +#[unstable(feature = "contracts_internals", issue = "128044")] +#[rustc_const_unstable(feature = "contracts", issue = "128044")] #[lang = "contract_check_requires"] #[rustc_intrinsic] -pub fn contract_check_requires bool>(cond: C) { - if contract_checks() && !cond() { - // Emit no unwind panic in case this was a safety requirement. - crate::panicking::panic_nounwind("failed requires check"); - } +pub const fn contract_check_requires bool + Copy>(cond: C) { + const_eval_select!( + @capture[C: Fn() -> bool + Copy] { cond: C } : + if const { + // Do nothing + } else { + if contract_checks() && !cond() { + // Emit no unwind panic in case this was a safety requirement. + crate::panicking::panic_nounwind("failed requires check"); + } + } + ) } /// Check if the post-condition `cond` has been met. /// /// By default, if `contract_checks` is enabled, this will panic with no unwind if the condition /// returns false. +/// +/// Note that this function is a no-op during constant evaluation. +#[cfg(not(bootstrap))] +#[unstable(feature = "contracts_internals", issue = "128044")] +#[rustc_const_unstable(feature = "contracts", issue = "128044")] +#[lang = "contract_check_ensures"] +#[rustc_intrinsic] +pub const fn contract_check_ensures bool + Copy>(ret: Ret, cond: C) -> Ret { + const_eval_select!( + @capture[Ret, C: Fn(&Ret) -> bool + Copy] { ret: Ret, cond: C } -> Ret : + if const { + // Do nothing + ret + } else { + if contract_checks() && !cond(&ret) { + // Emit no unwind panic in case this was a safety requirement. + crate::panicking::panic_nounwind("failed ensures check"); + } + ret + } + ) +} + +/// This is the old version of contract_check_ensures kept here for bootstrap only. +#[cfg(bootstrap)] #[unstable(feature = "contracts_internals", issue = "128044" /* compiler-team#759 */)] #[rustc_intrinsic] pub fn contract_check_ensures<'a, Ret, C: Fn(&'a Ret) -> bool>(ret: &'a Ret, cond: C) { diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index dc06aa4c38d5..8c68e57897cb 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -101,7 +101,6 @@ #![feature(bstr)] #![feature(bstr_internals)] #![feature(cfg_match)] -#![feature(closure_track_caller)] #![feature(const_carrying_mul_add)] #![feature(const_eval_select)] #![feature(core_intrinsics)] diff --git a/tests/ui/contracts/contract-attributes-nest.chk_pass.stderr b/tests/ui/contracts/contract-attributes-nest.chk_pass.stderr index 9ca95b8bb01a..e7c42ad98a57 100644 --- a/tests/ui/contracts/contract-attributes-nest.chk_pass.stderr +++ b/tests/ui/contracts/contract-attributes-nest.chk_pass.stderr @@ -7,5 +7,16 @@ LL | #![feature(contracts)] = note: see issue #128044 for more information = note: `#[warn(incomplete_features)]` on by default -warning: 1 warning emitted +warning: unreachable expression + --> $DIR/contract-attributes-nest.rs:23:1 + | +LL | #[core::contracts::ensures(|ret| *ret > 100)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unreachable expression +... +LL | return x.baz + 50; + | ----------------- any code following this expression is unreachable + | + = note: `#[warn(unreachable_code)]` on by default + +warning: 2 warnings emitted diff --git a/tests/ui/contracts/contract-attributes-nest.rs b/tests/ui/contracts/contract-attributes-nest.rs index e1e61b88f282..7c35e54c18bc 100644 --- a/tests/ui/contracts/contract-attributes-nest.rs +++ b/tests/ui/contracts/contract-attributes-nest.rs @@ -21,6 +21,7 @@ #[core::contracts::requires(x.baz > 0)] #[core::contracts::ensures(|ret| *ret > 100)] +//~^ WARN unreachable expression [unreachable_code] fn nest(x: Baz) -> i32 { loop { diff --git a/tests/ui/contracts/contract-attributes-nest.unchk_fail_post.stderr b/tests/ui/contracts/contract-attributes-nest.unchk_fail_post.stderr index 9ca95b8bb01a..e7c42ad98a57 100644 --- a/tests/ui/contracts/contract-attributes-nest.unchk_fail_post.stderr +++ b/tests/ui/contracts/contract-attributes-nest.unchk_fail_post.stderr @@ -7,5 +7,16 @@ LL | #![feature(contracts)] = note: see issue #128044 for more information = note: `#[warn(incomplete_features)]` on by default -warning: 1 warning emitted +warning: unreachable expression + --> $DIR/contract-attributes-nest.rs:23:1 + | +LL | #[core::contracts::ensures(|ret| *ret > 100)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unreachable expression +... +LL | return x.baz + 50; + | ----------------- any code following this expression is unreachable + | + = note: `#[warn(unreachable_code)]` on by default + +warning: 2 warnings emitted diff --git a/tests/ui/contracts/contract-attributes-nest.unchk_fail_pre.stderr b/tests/ui/contracts/contract-attributes-nest.unchk_fail_pre.stderr index 9ca95b8bb01a..e7c42ad98a57 100644 --- a/tests/ui/contracts/contract-attributes-nest.unchk_fail_pre.stderr +++ b/tests/ui/contracts/contract-attributes-nest.unchk_fail_pre.stderr @@ -7,5 +7,16 @@ LL | #![feature(contracts)] = note: see issue #128044 for more information = note: `#[warn(incomplete_features)]` on by default -warning: 1 warning emitted +warning: unreachable expression + --> $DIR/contract-attributes-nest.rs:23:1 + | +LL | #[core::contracts::ensures(|ret| *ret > 100)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unreachable expression +... +LL | return x.baz + 50; + | ----------------- any code following this expression is unreachable + | + = note: `#[warn(unreachable_code)]` on by default + +warning: 2 warnings emitted diff --git a/tests/ui/contracts/contract-attributes-nest.unchk_pass.stderr b/tests/ui/contracts/contract-attributes-nest.unchk_pass.stderr index 9ca95b8bb01a..e7c42ad98a57 100644 --- a/tests/ui/contracts/contract-attributes-nest.unchk_pass.stderr +++ b/tests/ui/contracts/contract-attributes-nest.unchk_pass.stderr @@ -7,5 +7,16 @@ LL | #![feature(contracts)] = note: see issue #128044 for more information = note: `#[warn(incomplete_features)]` on by default -warning: 1 warning emitted +warning: unreachable expression + --> $DIR/contract-attributes-nest.rs:23:1 + | +LL | #[core::contracts::ensures(|ret| *ret > 100)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unreachable expression +... +LL | return x.baz + 50; + | ----------------- any code following this expression is unreachable + | + = note: `#[warn(unreachable_code)]` on by default + +warning: 2 warnings emitted diff --git a/tests/ui/contracts/contract-const-fn.all_pass.stderr b/tests/ui/contracts/contract-const-fn.all_pass.stderr new file mode 100644 index 000000000000..e5b1df655823 --- /dev/null +++ b/tests/ui/contracts/contract-const-fn.all_pass.stderr @@ -0,0 +1,11 @@ +warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/contract-const-fn.rs:17:12 + | +LL | #![feature(contracts)] + | ^^^^^^^^^ + | + = note: see issue #128044 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/contracts/contract-const-fn.rs b/tests/ui/contracts/contract-const-fn.rs new file mode 100644 index 000000000000..733a06ae5709 --- /dev/null +++ b/tests/ui/contracts/contract-const-fn.rs @@ -0,0 +1,56 @@ +//! Check if we can annotate a constant function with contracts. +//! +//! The contract is only checked at runtime, and it will not fail if evaluated statically. +//! This is an existing limitation due to the existing architecture and the lack of constant +//! closures. +//! +//@ revisions: all_pass runtime_fail_pre runtime_fail_post +// +//@ [all_pass] run-pass +// +//@ [runtime_fail_pre] run-fail +//@ [runtime_fail_post] run-fail +// +//@ [all_pass] compile-flags: -Zcontract-checks=yes +//@ [runtime_fail_pre] compile-flags: -Zcontract-checks=yes +//@ [runtime_fail_post] compile-flags: -Zcontract-checks=yes +#![feature(contracts)] +//~^ WARN the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features] + +extern crate core; +use core::contracts::*; + +#[requires(x < 100)] +const fn less_than_100(x: u8) -> u8 { + x +} + +// This is wrong on purpose. +#[ensures(|ret| *ret)] +const fn always_true(b: bool) -> bool { + b +} + +const ZERO: u8 = less_than_100(0); +// This is no-op because the contract cannot be checked at compilation time. +const TWO_HUNDRED: u8 = less_than_100(200); + +/// Example from . +#[ensures(move |ret: &u32| *ret > x)] +const fn broken_sum(x: u32, y: u32) -> u32 { + x + y +} + +fn main() { + assert_eq!(ZERO, 0); + assert_eq!(TWO_HUNDRED, 200); + assert_eq!(broken_sum(0, 1), 1); + assert_eq!(always_true(true), true); + + #[cfg(runtime_fail_post)] + let _ok = always_true(false); + + // Runtime check should fail. + #[cfg(runtime_fail_pre)] + let _200 = less_than_100(200); +} diff --git a/tests/ui/contracts/contract-const-fn.runtime_fail_post.stderr b/tests/ui/contracts/contract-const-fn.runtime_fail_post.stderr new file mode 100644 index 000000000000..e5b1df655823 --- /dev/null +++ b/tests/ui/contracts/contract-const-fn.runtime_fail_post.stderr @@ -0,0 +1,11 @@ +warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/contract-const-fn.rs:17:12 + | +LL | #![feature(contracts)] + | ^^^^^^^^^ + | + = note: see issue #128044 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/contracts/contract-const-fn.runtime_fail_pre.stderr b/tests/ui/contracts/contract-const-fn.runtime_fail_pre.stderr new file mode 100644 index 000000000000..e5b1df655823 --- /dev/null +++ b/tests/ui/contracts/contract-const-fn.runtime_fail_pre.stderr @@ -0,0 +1,11 @@ +warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/contract-const-fn.rs:17:12 + | +LL | #![feature(contracts)] + | ^^^^^^^^^ + | + = note: see issue #128044 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/contracts/internal_machinery/contract-ast-extensions-nest.rs b/tests/ui/contracts/internal_machinery/contract-ast-extensions-nest.rs index 6d8cd3949eed..7f9c3fe28cef 100644 --- a/tests/ui/contracts/internal_machinery/contract-ast-extensions-nest.rs +++ b/tests/ui/contracts/internal_machinery/contract-ast-extensions-nest.rs @@ -21,6 +21,7 @@ fn nest(x: Baz) -> i32 contract_requires(|| x.baz > 0) contract_ensures(|ret| *ret > 100) + //~^ WARN unreachable expression [unreachable_code] { loop { return x.baz + 50; diff --git a/tests/ui/contracts/internal_machinery/contract-intrinsics.rs b/tests/ui/contracts/internal_machinery/contract-intrinsics.rs index ae692afd146f..f94dfbde75fb 100644 --- a/tests/ui/contracts/internal_machinery/contract-intrinsics.rs +++ b/tests/ui/contracts/internal_machinery/contract-intrinsics.rs @@ -26,11 +26,11 @@ fn main() { #[cfg(any(default, unchk_pass, chk_fail_requires))] core::intrinsics::contract_check_requires(|| false); - let doubles_to_two = { let old = 2; move |ret| ret + ret == old }; + let doubles_to_two = { let old = 2; move |ret: &u32 | ret + ret == old }; // Always pass - core::intrinsics::contract_check_ensures(&1, doubles_to_two); + core::intrinsics::contract_check_ensures(1, doubles_to_two); // Fail if enabled #[cfg(any(default, unchk_pass, chk_fail_ensures))] - core::intrinsics::contract_check_ensures(&2, doubles_to_two); + core::intrinsics::contract_check_ensures(2, doubles_to_two); } diff --git a/tests/ui/contracts/internal_machinery/contract-lang-items.rs b/tests/ui/contracts/internal_machinery/contract-lang-items.rs index e91bbed294d1..26042cf688fd 100644 --- a/tests/ui/contracts/internal_machinery/contract-lang-items.rs +++ b/tests/ui/contracts/internal_machinery/contract-lang-items.rs @@ -15,14 +15,14 @@ #![feature(contracts)] // to access core::contracts //~^ WARN the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features] #![feature(contracts_internals)] // to access check_requires lang item - +#![feature(core_intrinsics)] fn foo(x: Baz) -> i32 { let injected_checker = { core::contracts::build_check_ensures(|ret| *ret > 100) }; let ret = x.baz + 50; - injected_checker(ret) + core::intrinsics::contract_check_ensures(ret, injected_checker) } struct Baz { baz: i32 } From bc2912386f6841869a74e129a06f6dbe3fffacfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bennet=20Ble=C3=9Fmann?= Date: Mon, 7 Apr 2025 20:30:27 +0200 Subject: [PATCH 182/606] Revert "remove rust-analyser support for `extern "rust-intrinsic"` blocks" This reverts commit 51b51b51d7931da85280382a81c4dd80c73ca754. --- .../rust-analyzer/crates/hir-ty/src/lib.rs | 3 +++ .../crates/hir-ty/src/mir/eval/shim.rs | 14 +++++++++- .../rust-analyzer/crates/hir-ty/src/utils.rs | 26 ++++++++++++++----- .../src/completions/extern_abi.rs | 1 + .../crates/intern/src/symbol/symbols.rs | 1 + 5 files changed, 38 insertions(+), 7 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs index e4c50f2ebdb4..cc02b71f05c1 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs @@ -400,6 +400,7 @@ pub enum FnAbi { Rust, RustCall, RustCold, + RustIntrinsic, Stdcall, StdcallUnwind, System, @@ -456,6 +457,7 @@ impl FnAbi { s if *s == sym::riscv_dash_interrupt_dash_s => FnAbi::RiscvInterruptS, s if *s == sym::rust_dash_call => FnAbi::RustCall, s if *s == sym::rust_dash_cold => FnAbi::RustCold, + s if *s == sym::rust_dash_intrinsic => FnAbi::RustIntrinsic, s if *s == sym::Rust => FnAbi::Rust, s if *s == sym::stdcall_dash_unwind => FnAbi::StdcallUnwind, s if *s == sym::stdcall => FnAbi::Stdcall, @@ -498,6 +500,7 @@ impl FnAbi { FnAbi::Rust => "Rust", FnAbi::RustCall => "rust-call", FnAbi::RustCold => "rust-cold", + FnAbi::RustIntrinsic => "rust-intrinsic", FnAbi::Stdcall => "stdcall", FnAbi::StdcallUnwind => "stdcall-unwind", FnAbi::System => "system", diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs index 06ac5b1ffad9..f61ecabb7e41 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs @@ -59,7 +59,19 @@ impl Evaluator<'_> { let function_data = self.db.function_data(def); let attrs = self.db.attrs(def.into()); - let is_intrinsic = attrs.by_key(&sym::rustc_intrinsic).exists(); + let is_intrinsic = attrs.by_key(&sym::rustc_intrinsic).exists() + // Keep this around for a bit until extern "rustc-intrinsic" abis are no longer used + || (match &function_data.abi { + Some(abi) => *abi == sym::rust_dash_intrinsic, + None => match def.lookup(self.db.upcast()).container { + hir_def::ItemContainerId::ExternBlockId(block) => { + let id = block.lookup(self.db.upcast()).id; + id.item_tree(self.db.upcast())[id.value].abi.as_ref() + == Some(&sym::rust_dash_intrinsic) + } + _ => false, + }, + }); if is_intrinsic { return self.exec_intrinsic( diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs index 0cfd36d9166b..89d89fe2230a 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs @@ -18,6 +18,7 @@ use hir_def::{ TypeOrConstParamId, }; use hir_expand::name::Name; +use intern::sym; use rustc_abi::TargetDataLayout; use rustc_hash::FxHashSet; use smallvec::{smallvec, SmallVec}; @@ -302,13 +303,26 @@ pub fn is_fn_unsafe_to_call( let loc = func.lookup(db.upcast()); match loc.container { - hir_def::ItemContainerId::ExternBlockId(_block) => { - // Function in an `extern` block are always unsafe to call, except when - // it is marked as `safe`. - if data.is_safe() { - Unsafety::Safe + hir_def::ItemContainerId::ExternBlockId(block) => { + let id = block.lookup(db.upcast()).id; + let is_intrinsic_block = + id.item_tree(db.upcast())[id.value].abi.as_ref() == Some(&sym::rust_dash_intrinsic); + if is_intrinsic_block { + // legacy intrinsics + // extern "rust-intrinsic" intrinsics are unsafe unless they have the rustc_safe_intrinsic attribute + if db.attrs(func.into()).by_key(&sym::rustc_safe_intrinsic).exists() { + Unsafety::Safe + } else { + Unsafety::Unsafe + } } else { - Unsafety::Unsafe + // Function in an `extern` block are always unsafe to call, except when + // it is marked as `safe`. + if data.is_safe() { + Unsafety::Safe + } else { + Unsafety::Unsafe + } } } _ => Unsafety::Safe, diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs index a3554114f4c3..7c2cc2a6c1d8 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs @@ -36,6 +36,7 @@ const SUPPORTED_CALLING_CONVENTIONS: &[&str] = &[ "wasm", "system", "system-unwind", + "rust-intrinsic", "rust-call", "unadjusted", ]; diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs index d4f334289f03..6b77c72cee89 100644 --- a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs +++ b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs @@ -125,6 +125,7 @@ define_symbols! { riscv_dash_interrupt_dash_s = "riscv-interrupt-s", rust_dash_call = "rust-call", rust_dash_cold = "rust-cold", + rust_dash_intrinsic = "rust-intrinsic", stdcall_dash_unwind = "stdcall-unwind", system_dash_unwind = "system-unwind", sysv64_dash_unwind = "sysv64-unwind", From 8866af388497e9ed3254147c015379d5d6cdb054 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Wed, 26 Mar 2025 19:44:53 +0100 Subject: [PATCH 183/606] Add `naked_functions_rustic_abi` feature gate --- compiler/rustc_feature/src/unstable.rs | 2 ++ compiler/rustc_lint/src/lib.rs | 5 +++ compiler/rustc_lint_defs/src/builtin.rs | 34 ------------------- compiler/rustc_passes/messages.ftl | 3 -- compiler/rustc_passes/src/check_attr.rs | 15 ++++++++ compiler/rustc_passes/src/errors.rs | 4 --- compiler/rustc_passes/src/naked_functions.rs | 33 ++++-------------- compiler/rustc_span/src/symbol.rs | 1 + tests/ui/asm/naked-functions-rustic-abi.rs | 27 +++++++++++++++ tests/ui/asm/naked-functions-testattrs.rs | 9 +++-- tests/ui/asm/naked-functions-testattrs.stderr | 8 ++--- tests/ui/asm/naked-functions.rs | 12 ------- tests/ui/asm/naked-functions.stderr | 22 +++--------- ...feature-gate-naked_functions_rustic_abi.rs | 26 ++++++++++++++ ...ure-gate-naked_functions_rustic_abi.stderr | 33 ++++++++++++++++++ .../undefined_naked_function_abi.rs | 5 +++ .../undefined_naked_function_abi.stderr | 10 ++++++ 17 files changed, 142 insertions(+), 107 deletions(-) create mode 100644 tests/ui/asm/naked-functions-rustic-abi.rs create mode 100644 tests/ui/feature-gates/feature-gate-naked_functions_rustic_abi.rs create mode 100644 tests/ui/feature-gates/feature-gate-naked_functions_rustic_abi.stderr create mode 100644 tests/ui/lint/removed-lints/undefined_naked_function_abi.rs create mode 100644 tests/ui/lint/removed-lints/undefined_naked_function_abi.stderr diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 72468dd4714d..e0af871d3fd4 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -566,6 +566,8 @@ declare_features! ( (incomplete, mut_ref, "1.79.0", Some(123076)), /// Allows using `#[naked]` on functions. (unstable, naked_functions, "1.9.0", Some(90957)), + /// Allows using `#[naked]` on `extern "Rust"` functions. + (unstable, naked_functions_rustic_abi, "CURRENT_RUSTC_VERSION", Some(138997)), /// Allows using `#[target_feature(enable = "...")]` on `#[naked]` on functions. (unstable, naked_functions_target_feature, "1.86.0", Some(138568)), /// Allows specifying the as-needed link modifier diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index c38a75400181..1863ba8f8fb6 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -604,6 +604,11 @@ fn register_builtins(store: &mut LintStore) { "converted into hard error, see issue #127323 \ for more information", ); + store.register_removed( + "undefined_naked_function_abi", + "converted into hard error, see PR #139001 \ + for more information", + ); } fn register_internals(store: &mut LintStore) { diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 8a761a0a0969..b25d2a30681c 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -110,7 +110,6 @@ declare_lint_pass! { UNCONDITIONAL_PANIC, UNCONDITIONAL_RECURSION, UNCOVERED_PARAM_IN_PROJECTION, - UNDEFINED_NAKED_FUNCTION_ABI, UNEXPECTED_CFGS, UNFULFILLED_LINT_EXPECTATIONS, UNINHABITED_STATIC, @@ -2830,39 +2829,6 @@ declare_lint! { "detects deprecation attributes with no effect", } -declare_lint! { - /// The `undefined_naked_function_abi` lint detects naked function definitions that - /// either do not specify an ABI or specify the Rust ABI. - /// - /// ### Example - /// - /// ```rust - /// #![feature(asm_experimental_arch, naked_functions)] - /// - /// use std::arch::naked_asm; - /// - /// #[naked] - /// pub fn default_abi() -> u32 { - /// unsafe { naked_asm!(""); } - /// } - /// - /// #[naked] - /// pub extern "Rust" fn rust_abi() -> u32 { - /// unsafe { naked_asm!(""); } - /// } - /// ``` - /// - /// {{produces}} - /// - /// ### Explanation - /// - /// The Rust ABI is currently undefined. Therefore, naked functions should - /// specify a non-Rust ABI. - pub UNDEFINED_NAKED_FUNCTION_ABI, - Warn, - "undefined naked function ABI" -} - declare_lint! { /// The `ineffective_unstable_trait_impl` lint detects `#[unstable]` attributes which are not used. /// diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 06398dd4f725..18cbbad92b6c 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -738,9 +738,6 @@ passes_trait_impl_const_stable = passes_transparent_incompatible = transparent {$target} cannot have other repr hints -passes_undefined_naked_function_abi = - Rust ABI is unsupported in naked functions - passes_unknown_external_lang_item = unknown external lang item: `{$lang_item}` diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 9238c73cdb11..50ce20641293 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -607,6 +607,21 @@ impl<'tcx> CheckAttrVisitor<'tcx> { match target { Target::Fn | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => { + let fn_sig = self.tcx.hir_node(hir_id).fn_sig().unwrap(); + let abi = fn_sig.header.abi; + if abi.is_rustic_abi() && !self.tcx.features().naked_functions_rustic_abi() { + feature_err( + &self.tcx.sess, + sym::naked_functions_rustic_abi, + fn_sig.span, + format!( + "`#[naked]` is currently unstable on `extern \"{}\"` functions", + abi.as_str() + ), + ) + .emit(); + } + for other_attr in attrs { // this covers "sugared doc comments" of the form `/// ...` // it does not cover `#[doc = "..."]`, which is handled below diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 0ee17430aab8..536cb96bf466 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1197,10 +1197,6 @@ pub(crate) struct UnlabeledCfInWhileCondition<'a> { pub cf_type: &'a str, } -#[derive(LintDiagnostic)] -#[diag(passes_undefined_naked_function_abi)] -pub(crate) struct UndefinedNakedFunctionAbi; - #[derive(Diagnostic)] #[diag(passes_no_patterns)] pub(crate) struct NoPatterns { diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs index d35aedf9a564..3c9f8b72c363 100644 --- a/compiler/rustc_passes/src/naked_functions.rs +++ b/compiler/rustc_passes/src/naked_functions.rs @@ -1,6 +1,5 @@ //! Checks validity of naked functions. -use rustc_abi::ExternAbi; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{LocalDefId, LocalModDefId}; @@ -10,12 +9,11 @@ use rustc_middle::hir::nested_filter::OnlyBodies; use rustc_middle::query::Providers; use rustc_middle::span_bug; use rustc_middle::ty::TyCtxt; -use rustc_session::lint::builtin::UNDEFINED_NAKED_FUNCTION_ABI; use rustc_span::{Span, sym}; use crate::errors::{ NakedAsmOutsideNakedFn, NakedFunctionsAsmBlock, NakedFunctionsMustNakedAsm, NoPatterns, - ParamsNotAllowed, UndefinedNakedFunctionAbi, + ParamsNotAllowed, }; pub(crate) fn provide(providers: &mut Providers) { @@ -29,26 +27,21 @@ fn check_mod_naked_functions(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { continue; } - let (fn_header, body_id) = match tcx.hir_node_by_def_id(def_id) { + let body = match tcx.hir_node_by_def_id(def_id) { hir::Node::Item(hir::Item { - kind: hir::ItemKind::Fn { sig, body: body_id, .. }, - .. + kind: hir::ItemKind::Fn { body: body_id, .. }, .. }) | hir::Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)), + kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body_id)), .. }) | hir::Node::ImplItem(hir::ImplItem { - kind: hir::ImplItemKind::Fn(sig, body_id), - .. - }) => (sig.header, *body_id), + kind: hir::ImplItemKind::Fn(_, body_id), .. + }) => tcx.hir_body(*body_id), _ => continue, }; - let body = tcx.hir_body(body_id); - if tcx.has_attr(def_id, sym::naked) { - check_abi(tcx, def_id, fn_header.abi); check_no_patterns(tcx, body.params); check_no_parameters_use(tcx, body); check_asm(tcx, def_id, body); @@ -60,20 +53,6 @@ fn check_mod_naked_functions(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { } } -/// Checks that function uses non-Rust ABI. -fn check_abi(tcx: TyCtxt<'_>, def_id: LocalDefId, abi: ExternAbi) { - if abi == ExternAbi::Rust { - let hir_id = tcx.local_def_id_to_hir_id(def_id); - let span = tcx.def_span(def_id); - tcx.emit_node_span_lint( - UNDEFINED_NAKED_FUNCTION_ABI, - hir_id, - span, - UndefinedNakedFunctionAbi, - ); - } -} - /// Checks that parameters don't use patterns. Mirrors the checks for function declarations. fn check_no_patterns(tcx: TyCtxt<'_>, params: &[hir::Param<'_>]) { for param in params { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 3e4742439655..5906b242dda6 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1387,6 +1387,7 @@ symbols! { naked, naked_asm, naked_functions, + naked_functions_rustic_abi, naked_functions_target_feature, name, names, diff --git a/tests/ui/asm/naked-functions-rustic-abi.rs b/tests/ui/asm/naked-functions-rustic-abi.rs new file mode 100644 index 000000000000..b654d38ccc1a --- /dev/null +++ b/tests/ui/asm/naked-functions-rustic-abi.rs @@ -0,0 +1,27 @@ +//@ revisions: x86_64 aarch64 +// +//@[aarch64] only-aarch64 +//@[x86_64] only-x86_64 +// +//@ build-pass +//@ needs-asm-support + +#![feature(naked_functions, naked_functions_rustic_abi, rust_cold_cc)] +#![crate_type = "lib"] + +use std::arch::{asm, naked_asm}; + +#[naked] +pub unsafe fn rust_implicit() { + naked_asm!("ret"); +} + +#[naked] +pub unsafe extern "Rust" fn rust_explicit() { + naked_asm!("ret"); +} + +#[naked] +pub unsafe extern "rust-cold" fn rust_cold() { + naked_asm!("ret"); +} diff --git a/tests/ui/asm/naked-functions-testattrs.rs b/tests/ui/asm/naked-functions-testattrs.rs index 7e373270e9fc..ad31876a77a5 100644 --- a/tests/ui/asm/naked-functions-testattrs.rs +++ b/tests/ui/asm/naked-functions-testattrs.rs @@ -1,7 +1,6 @@ //@ needs-asm-support //@ compile-flags: --test -#![allow(undefined_naked_function_abi)] #![feature(naked_functions)] #![feature(test)] #![crate_type = "lib"] @@ -11,7 +10,7 @@ use std::arch::naked_asm; #[test] #[naked] //~^ ERROR [E0736] -fn test_naked() { +extern "C" fn test_naked() { unsafe { naked_asm!("") }; } @@ -19,7 +18,7 @@ fn test_naked() { #[test] #[naked] //~^ ERROR [E0736] -fn test_naked_should_panic() { +extern "C" fn test_naked_should_panic() { unsafe { naked_asm!("") }; } @@ -27,13 +26,13 @@ fn test_naked_should_panic() { #[test] #[naked] //~^ ERROR [E0736] -fn test_naked_ignore() { +extern "C" fn test_naked_ignore() { unsafe { naked_asm!("") }; } #[bench] #[naked] //~^ ERROR [E0736] -fn bench_naked() { +extern "C" fn bench_naked() { unsafe { naked_asm!("") }; } diff --git a/tests/ui/asm/naked-functions-testattrs.stderr b/tests/ui/asm/naked-functions-testattrs.stderr index 4dabe41964a5..0f0bb91b9541 100644 --- a/tests/ui/asm/naked-functions-testattrs.stderr +++ b/tests/ui/asm/naked-functions-testattrs.stderr @@ -1,5 +1,5 @@ error[E0736]: cannot use `#[naked]` with testing attributes - --> $DIR/naked-functions-testattrs.rs:12:1 + --> $DIR/naked-functions-testattrs.rs:11:1 | LL | #[test] | ------- function marked with testing attribute here @@ -7,7 +7,7 @@ LL | #[naked] | ^^^^^^^^ `#[naked]` is incompatible with testing attributes error[E0736]: cannot use `#[naked]` with testing attributes - --> $DIR/naked-functions-testattrs.rs:20:1 + --> $DIR/naked-functions-testattrs.rs:19:1 | LL | #[test] | ------- function marked with testing attribute here @@ -15,7 +15,7 @@ LL | #[naked] | ^^^^^^^^ `#[naked]` is incompatible with testing attributes error[E0736]: cannot use `#[naked]` with testing attributes - --> $DIR/naked-functions-testattrs.rs:28:1 + --> $DIR/naked-functions-testattrs.rs:27:1 | LL | #[test] | ------- function marked with testing attribute here @@ -23,7 +23,7 @@ LL | #[naked] | ^^^^^^^^ `#[naked]` is incompatible with testing attributes error[E0736]: cannot use `#[naked]` with testing attributes - --> $DIR/naked-functions-testattrs.rs:35:1 + --> $DIR/naked-functions-testattrs.rs:34:1 | LL | #[bench] | -------- function marked with testing attribute here diff --git a/tests/ui/asm/naked-functions.rs b/tests/ui/asm/naked-functions.rs index 3d4d414539c1..5bf2e2a3abd0 100644 --- a/tests/ui/asm/naked-functions.rs +++ b/tests/ui/asm/naked-functions.rs @@ -122,18 +122,6 @@ unsafe extern "C" fn invalid_may_unwind() { //~^ ERROR the `may_unwind` option cannot be used with `naked_asm!` } -#[naked] -pub unsafe fn default_abi() { - //~^ WARN Rust ABI is unsupported in naked functions - naked_asm!(""); -} - -#[naked] -pub unsafe fn rust_abi() { - //~^ WARN Rust ABI is unsupported in naked functions - naked_asm!(""); -} - #[naked] pub extern "C" fn valid_a() -> T { unsafe { diff --git a/tests/ui/asm/naked-functions.stderr b/tests/ui/asm/naked-functions.stderr index 0898f3620f24..0a55bb9cd837 100644 --- a/tests/ui/asm/naked-functions.stderr +++ b/tests/ui/asm/naked-functions.stderr @@ -53,19 +53,19 @@ LL | naked_asm!("", options(may_unwind)); | ^^^^^^^^^^ the `may_unwind` option is not meaningful for global-scoped inline assembly error: this is a user specified error - --> $DIR/naked-functions.rs:169:5 + --> $DIR/naked-functions.rs:157:5 | LL | compile_error!("this is a user specified error") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this is a user specified error - --> $DIR/naked-functions.rs:175:5 + --> $DIR/naked-functions.rs:163:5 | LL | compile_error!("this is a user specified error"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: asm template must be a string literal - --> $DIR/naked-functions.rs:182:16 + --> $DIR/naked-functions.rs:170:16 | LL | naked_asm!(invalid_syntax) | ^^^^^^^^^^^^^^ @@ -175,20 +175,6 @@ LL | LL | *&y | --- not allowed in naked functions -warning: Rust ABI is unsupported in naked functions - --> $DIR/naked-functions.rs:126:1 - | -LL | pub unsafe fn default_abi() { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `#[warn(undefined_naked_function_abi)]` on by default - -warning: Rust ABI is unsupported in naked functions - --> $DIR/naked-functions.rs:132:1 - | -LL | pub unsafe fn rust_abi() { - | ^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 25 previous errors; 2 warnings emitted +error: aborting due to 25 previous errors For more information about this error, try `rustc --explain E0787`. diff --git a/tests/ui/feature-gates/feature-gate-naked_functions_rustic_abi.rs b/tests/ui/feature-gates/feature-gate-naked_functions_rustic_abi.rs new file mode 100644 index 000000000000..c91d83399441 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-naked_functions_rustic_abi.rs @@ -0,0 +1,26 @@ +//@ needs-asm-support +//@ only-x86_64 + +#![feature(naked_functions, rust_cold_cc)] + +use std::arch::naked_asm; + +#[naked] +pub unsafe fn rust_implicit() { + //~^ ERROR `#[naked]` is currently unstable on `extern "Rust"` functions + naked_asm!("ret"); +} + +#[naked] +pub unsafe extern "Rust" fn rust_explicit() { + //~^ ERROR `#[naked]` is currently unstable on `extern "Rust"` functions + naked_asm!("ret"); +} + +#[naked] +pub unsafe extern "rust-cold" fn rust_cold() { + //~^ ERROR `#[naked]` is currently unstable on `extern "rust-cold"` functions + naked_asm!("ret"); +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-naked_functions_rustic_abi.stderr b/tests/ui/feature-gates/feature-gate-naked_functions_rustic_abi.stderr new file mode 100644 index 000000000000..ba45e15ec86b --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-naked_functions_rustic_abi.stderr @@ -0,0 +1,33 @@ +error[E0658]: `#[naked]` is currently unstable on `extern "Rust"` functions + --> $DIR/feature-gate-naked_functions_rustic_abi.rs:9:1 + | +LL | pub unsafe fn rust_implicit() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #138997 for more information + = help: add `#![feature(naked_functions_rustic_abi)]` 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]: `#[naked]` is currently unstable on `extern "Rust"` functions + --> $DIR/feature-gate-naked_functions_rustic_abi.rs:15:1 + | +LL | pub unsafe extern "Rust" fn rust_explicit() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #138997 for more information + = help: add `#![feature(naked_functions_rustic_abi)]` 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]: `#[naked]` is currently unstable on `extern "rust-cold"` functions + --> $DIR/feature-gate-naked_functions_rustic_abi.rs:21:1 + | +LL | pub unsafe extern "rust-cold" fn rust_cold() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #138997 for more information + = help: add `#![feature(naked_functions_rustic_abi)]` 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 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/lint/removed-lints/undefined_naked_function_abi.rs b/tests/ui/lint/removed-lints/undefined_naked_function_abi.rs new file mode 100644 index 000000000000..cf3ac66ac86d --- /dev/null +++ b/tests/ui/lint/removed-lints/undefined_naked_function_abi.rs @@ -0,0 +1,5 @@ +//@ check-pass + +#![deny(undefined_naked_function_abi)] +//~^ WARN lint `undefined_naked_function_abi` has been removed +fn main() {} diff --git a/tests/ui/lint/removed-lints/undefined_naked_function_abi.stderr b/tests/ui/lint/removed-lints/undefined_naked_function_abi.stderr new file mode 100644 index 000000000000..5a546688beb5 --- /dev/null +++ b/tests/ui/lint/removed-lints/undefined_naked_function_abi.stderr @@ -0,0 +1,10 @@ +warning: lint `undefined_naked_function_abi` has been removed: converted into hard error, see PR #139001 for more information + --> $DIR/undefined_naked_function_abi.rs:3:9 + | +LL | #![deny(undefined_naked_function_abi)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(renamed_and_removed_lints)]` on by default + +warning: 1 warning emitted + From b078564fe627922790917d8d8a9b28a8877a8028 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 28 Mar 2025 10:01:29 -0300 Subject: [PATCH 184/606] Make use generated TerminatorKind::Call have call_source Use --- compiler/rustc_middle/src/mir/syntax.rs | 2 ++ compiler/rustc_mir_build/src/builder/expr/into.rs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 707c8d04d557..ff9d32ebb719 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -652,6 +652,8 @@ pub enum CallSource { /// Other types of desugaring that did not come from the HIR, but we don't care about /// for diagnostics (yet). Misc, + /// Use of value, generating a clone function call + Use, /// Normal function call, no special source Normal, } diff --git a/compiler/rustc_mir_build/src/builder/expr/into.rs b/compiler/rustc_mir_build/src/builder/expr/into.rs index 333e69475c50..a9a07997410c 100644 --- a/compiler/rustc_mir_build/src/builder/expr/into.rs +++ b/compiler/rustc_mir_build/src/builder/expr/into.rs @@ -328,7 +328,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { destination, target: Some(success), unwind: UnwindAction::Unreachable, - call_source: CallSource::Misc, + call_source: CallSource::Use, fn_span: expr_span, }, ); From b9159e09a7c2bba670fee45b554c7c2e7aba9dd8 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 1 Apr 2025 14:14:13 -0300 Subject: [PATCH 185/606] Use a local var for tcx --- compiler/rustc_codegen_ssa/src/mir/mod.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 0758e5d04567..ea47d32ea03c 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -170,6 +170,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( ) { assert!(!instance.args.has_infer()); + let tcx = cx.tcx(); let llfn = cx.get_fn(instance); let mir = cx.tcx().instance_mir(instance.def); @@ -177,7 +178,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty()); debug!("fn_abi: {:?}", fn_abi); - if cx.tcx().codegen_fn_attrs(instance.def_id()).flags.contains(CodegenFnAttrFlags::NAKED) { + if tcx.codegen_fn_attrs(instance.def_id()).flags.contains(CodegenFnAttrFlags::NAKED) { crate::mir::naked_asm::codegen_naked_asm::(cx, &mir, instance); return; } @@ -194,7 +195,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( } let cleanup_kinds = - base::wants_new_eh_instructions(cx.tcx().sess).then(|| analyze::cleanup_kinds(mir)); + base::wants_new_eh_instructions(tcx.sess).then(|| analyze::cleanup_kinds(mir)); let cached_llbbs: IndexVec> = mir.basic_blocks @@ -217,7 +218,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( cleanup_kinds, landing_pads: IndexVec::from_elem(None, &mir.basic_blocks), funclets: IndexVec::from_fn_n(|_| None, mir.basic_blocks.len()), - cold_blocks: find_cold_blocks(cx.tcx(), mir), + cold_blocks: find_cold_blocks(tcx, mir), locals: locals::Locals::empty(), debug_context, per_local_var_debug_info: None, @@ -233,7 +234,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( fx.compute_per_local_var_debug_info(&mut start_bx).unzip(); fx.per_local_var_debug_info = per_local_var_debug_info; - let traversal_order = traversal::mono_reachable_reverse_postorder(mir, cx.tcx(), instance); + let traversal_order = traversal::mono_reachable_reverse_postorder(mir, tcx, instance); let memory_locals = analyze::non_ssa_locals(&fx, &traversal_order); // Allocate variable and temp allocas From 9f69c66a47d80cbced17d4d74d6e5c349db952d2 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 28 Mar 2025 10:03:00 -0300 Subject: [PATCH 186/606] Optimize codegen of use values that are copy post monomorphization --- compiler/rustc_codegen_ssa/src/mir/mod.rs | 70 +++++++++++++++++++++-- 1 file changed, 66 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index ea47d32ea03c..fbbf93e2dc4d 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -3,7 +3,7 @@ use std::iter; use rustc_index::IndexVec; use rustc_index::bit_set::DenseBitSet; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; -use rustc_middle::mir::{Local, UnwindTerminateReason, traversal}; +use rustc_middle::mir::{Body, Local, UnwindTerminateReason, traversal}; use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv, TyAndLayout}; use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; use rustc_middle::{bug, mir, span_bug}; @@ -173,7 +173,12 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let tcx = cx.tcx(); let llfn = cx.get_fn(instance); - let mir = cx.tcx().instance_mir(instance.def); + let mir = tcx.instance_mir(instance.def); + let mir = instance.instantiate_mir_and_normalize_erasing_regions( + tcx, + ty::TypingEnv::fully_monomorphized(), + ty::EarlyBinder::bind(mir.clone()), + ); let fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty()); debug!("fn_abi: {:?}", fn_abi); @@ -183,7 +188,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( return; } - let debug_context = cx.create_function_debug_context(instance, fn_abi, llfn, mir); + let debug_context = cx.create_function_debug_context(instance, fn_abi, llfn, &mir); let start_llbb = Bx::append_block(cx, llfn, "start"); let mut start_bx = Bx::build(cx, start_llbb); @@ -195,7 +200,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( } let cleanup_kinds = - base::wants_new_eh_instructions(tcx.sess).then(|| analyze::cleanup_kinds(mir)); + base::wants_new_eh_instructions(tcx.sess).then(|| analyze::cleanup_kinds(&mir)); let cached_llbbs: IndexVec> = mir.basic_blocks @@ -205,6 +210,8 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( }) .collect(); + let mir = tcx.arena.alloc(optimize_use_clone::(cx, mir)); + let mut fx = FunctionCx { instance, mir, @@ -311,6 +318,61 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( } } +// FIXME: Move this function to mir::transform when post-mono MIR passes land. +fn optimize_use_clone<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( + cx: &'a Bx::CodegenCx, + mut mir: Body<'tcx>, +) -> Body<'tcx> { + let tcx = cx.tcx(); + + if tcx.features().ergonomic_clones() { + for bb in mir.basic_blocks.as_mut() { + let mir::TerminatorKind::Call { + args, + destination, + target, + call_source: mir::CallSource::Use, + .. + } = &bb.terminator().kind + else { + continue; + }; + + // CallSource::Use calls always use 1 argument. + assert_eq!(args.len(), 1); + let arg = &args[0]; + + // These types are easily available from locals, so check that before + // doing DefId lookups to figure out what we're actually calling. + let arg_ty = arg.node.ty(&mir.local_decls, tcx); + + let ty::Ref(_region, inner_ty, mir::Mutability::Not) = *arg_ty.kind() else { continue }; + + if !tcx.type_is_copy_modulo_regions(cx.typing_env(), inner_ty) { + continue; + } + + let Some(arg_place) = arg.node.place() else { continue }; + + let destination_block = target.unwrap(); + + bb.statements.push(mir::Statement { + source_info: bb.terminator().source_info, + kind: mir::StatementKind::Assign(Box::new(( + *destination, + mir::Rvalue::Use(mir::Operand::Copy( + arg_place.project_deeper(&[mir::ProjectionElem::Deref], tcx), + )), + ))), + }); + + bb.terminator_mut().kind = mir::TerminatorKind::Goto { target: destination_block }; + } + } + + mir +} + /// Produces, for each argument, a `Value` pointing at the /// argument's value. As arguments are places, these are always /// indirect. From a0856eaff6dcf69456dd186bb310a88af210865a Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 28 Mar 2025 15:20:18 -0300 Subject: [PATCH 187/606] Add mir opt tests to be sure we generate copy, clones and moves when corresponds --- tests/mir-opt/ergonomic-clones/closure.rs | 55 +++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 tests/mir-opt/ergonomic-clones/closure.rs diff --git a/tests/mir-opt/ergonomic-clones/closure.rs b/tests/mir-opt/ergonomic-clones/closure.rs new file mode 100644 index 000000000000..682f48449841 --- /dev/null +++ b/tests/mir-opt/ergonomic-clones/closure.rs @@ -0,0 +1,55 @@ +#![crate_type = "lib"] +#![feature(ergonomic_clones)] +#![allow(incomplete_features)] + +use std::clone::UseCloned; + +pub fn ergonomic_clone_closure_move() -> String { + // CHECK-LABEL: fn ergonomic_clone_closure_move( + // CHECK: _0 = move (_1.0: std::string::String); + // CHECK-NOT: ::clone + let s = String::from("hi"); + + let cl = use || s; + cl() +} + +#[derive(Clone)] +struct Foo; + +impl UseCloned for Foo {} + +pub fn ergonomic_clone_closure_use_cloned() -> Foo { + // CHECK-LABEL: fn ergonomic_clone_closure_use_cloned( + // CHECK: ::clone + let f = Foo; + + let f1 = use || f; + + let f2 = use || f; + + f +} + +pub fn ergonomic_clone_closure_copy() -> i32 { + // CHECK-LABEL: fn ergonomic_clone_closure_copy( + // CHECK: _0 = copy ((*_1).0: i32); + // CHECK-NOT: ::clone + let i = 1; + + let i1 = use || i; + + let i2 = use || i; + + i +} + +pub fn ergonomic_clone_closure_use_cloned_generics(f: T) -> T { + // CHECK-LABEL: fn ergonomic_clone_closure_use_cloned_generics( + // CHECK: ::clone + let f1 = use || f; + + let f2 = use || f; + + f +} From 20f93c9e8e15f956b4f31afd0d5be42c1c0eea3f Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 28 Mar 2025 16:33:45 -0300 Subject: [PATCH 188/606] Add codegen test to be sure we get rid of uneeded clones after monomorphization --- tests/codegen/ergonomic-clones/closure.rs | 55 +++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 tests/codegen/ergonomic-clones/closure.rs diff --git a/tests/codegen/ergonomic-clones/closure.rs b/tests/codegen/ergonomic-clones/closure.rs new file mode 100644 index 000000000000..b6fc81726419 --- /dev/null +++ b/tests/codegen/ergonomic-clones/closure.rs @@ -0,0 +1,55 @@ +//@ compile-flags: -C no-prepopulate-passes -Copt-level=0 -Zmir-opt-level=0 + +#![crate_type = "lib"] + +#![feature(ergonomic_clones)] +#![allow(incomplete_features)] + +use std::clone::UseCloned; + +pub fn ergonomic_clone_closure_move() -> String { + let s = String::from("hi"); + + // CHECK-NOT: ; call core::clone::impls::::clone + let cl = use || s; + cl() +} + +#[derive(Clone)] +struct Foo; + +impl UseCloned for Foo {} + +pub fn ergonomic_clone_closure_use_cloned() -> Foo { + let f = Foo; + + // CHECK: ; call ::clone + let f1 = use || f; + + // CHECK: ; call ::clone + let f2 = use || f; + + f +} + +pub fn ergonomic_clone_closure_copy() -> i32 { + let i = 1; + + // CHECK-NOT: ; call core::clone::impls::::clone + let i1 = use || i; + + // CHECK-NOT: ; call core::clone::impls::::clone + let i2 = use || i; + + i +} + +pub fn ergonomic_clone_closure_use_cloned_generics(f: T) -> T { + // CHECK-NOT: ; call core::clone::impls::::clone + let f1 = use || f; + + // CHECK-NOT: ; call core::clone::impls::::clone + let f2 = use || f; + + f +} From dfa58e39c812348f74624eb8ff9f8a7c6bafeb4b Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 31 Mar 2025 14:36:09 -0300 Subject: [PATCH 189/606] rustfmt does not support use closures yet --- rustfmt.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/rustfmt.toml b/rustfmt.toml index c884a33729c4..7c384b876bf7 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -53,4 +53,8 @@ ignore = [ # Code automatically generated and included. "compiler/rustc_codegen_gcc/src/intrinsic/archs.rs", "compiler/rustc_codegen_gcc/example", + + # Rustfmt doesn't support use closures yet + "tests/mir-opt/ergonomic-clones/closure.rs", + "tests/codegen/ergonomic-clones/closure.rs", ] From d6ad9e6191cd70234a9fd20a1e6e4f5e90cd1985 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 31 Mar 2025 12:03:39 -0300 Subject: [PATCH 190/606] Remove crash test that do not ICE anymore --- tests/crashes/129372.rs | 52 ----------------------------------------- 1 file changed, 52 deletions(-) delete mode 100644 tests/crashes/129372.rs diff --git a/tests/crashes/129372.rs b/tests/crashes/129372.rs deleted file mode 100644 index 43be01b35df2..000000000000 --- a/tests/crashes/129372.rs +++ /dev/null @@ -1,52 +0,0 @@ -//@ known-bug: #129372 -//@ compile-flags: -Cdebuginfo=2 -Copt-level=0 - -pub struct Wrapper(T); -struct Struct; - -pub trait TraitA { - type AssocA<'t>; -} -pub trait TraitB { - type AssocB; -} - -pub fn helper(v: impl MethodTrait) { - let _local_that_causes_ice = v.method(); -} - -pub fn main() { - helper(Wrapper(Struct)); -} - -pub trait MethodTrait { - type Assoc<'a>; - - fn method(self) -> impl for<'a> FnMut(&'a ()) -> Self::Assoc<'a>; -} - -impl MethodTrait for T -where - ::AssocB: TraitA, -{ - type Assoc<'a> = ::AssocA<'a>; - - fn method(self) -> impl for<'a> FnMut(&'a ()) -> Self::Assoc<'a> { - move |_| loop {} - } -} - -impl TraitB for Wrapper -where - B: TraitB, -{ - type AssocB = T; -} - -impl TraitB for Struct { - type AssocB = Struct; -} - -impl TraitA for Struct { - type AssocA<'t> = Self; -} From 4a0ea02e3a8a799bdb58ac62078c56434cc51a27 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 7 Apr 2025 16:47:22 -0300 Subject: [PATCH 191/606] Only clone mir body if tcx.features().ergonomic_clones() --- compiler/rustc_codegen_ssa/src/mir/mod.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index fbbf93e2dc4d..6a37889217ab 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -173,12 +173,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let tcx = cx.tcx(); let llfn = cx.get_fn(instance); - let mir = tcx.instance_mir(instance.def); - let mir = instance.instantiate_mir_and_normalize_erasing_regions( - tcx, - ty::TypingEnv::fully_monomorphized(), - ty::EarlyBinder::bind(mir.clone()), - ); + let mut mir = tcx.instance_mir(instance.def); let fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty()); debug!("fn_abi: {:?}", fn_abi); @@ -188,6 +183,15 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( return; } + if tcx.features().ergonomic_clones() { + let monomorphized_mir = instance.instantiate_mir_and_normalize_erasing_regions( + tcx, + ty::TypingEnv::fully_monomorphized(), + ty::EarlyBinder::bind(mir.clone()), + ); + mir = tcx.arena.alloc(optimize_use_clone::(cx, monomorphized_mir)); + } + let debug_context = cx.create_function_debug_context(instance, fn_abi, llfn, &mir); let start_llbb = Bx::append_block(cx, llfn, "start"); @@ -210,8 +214,6 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( }) .collect(); - let mir = tcx.arena.alloc(optimize_use_clone::(cx, mir)); - let mut fx = FunctionCx { instance, mir, From 250b848272d24d79e815994053a4a690d92b7264 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 27 Mar 2025 17:24:06 +0000 Subject: [PATCH 192/606] Make error message for missing fields with .. and without .. more consistent --- compiler/rustc_hir_typeck/src/expr.rs | 8 ++++-- .../structs/default-field-values/failures.rs | 5 ++-- .../default-field-values/failures.stderr | 26 ++++++++++++------- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index a75f6f4caac9..9de961dbdbc7 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -2204,8 +2204,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let fields = listify(&missing_mandatory_fields, |f| format!("`{f}`")).unwrap(); self.dcx() .struct_span_err( - span.shrink_to_hi(), - format!("missing mandatory field{s} {fields}"), + span.shrink_to_lo(), + format!("missing field{s} {fields} in initializer"), + ) + .with_span_label( + span.shrink_to_lo(), + "fields that do not have a defaulted value must be provided explicitly", ) .emit(); return; diff --git a/tests/ui/structs/default-field-values/failures.rs b/tests/ui/structs/default-field-values/failures.rs index 1e94eecb4f87..4461302e841d 100644 --- a/tests/ui/structs/default-field-values/failures.rs +++ b/tests/ui/structs/default-field-values/failures.rs @@ -1,4 +1,4 @@ -#![feature(default_field_values)] + #![feature(default_field_values)] #[derive(Debug)] pub struct S; @@ -50,7 +50,8 @@ enum E { fn main () { let _ = Foo { .. }; // ok let _ = Foo::default(); // ok - let _ = Bar { .. }; //~ ERROR mandatory field + let _ = Bar { .. }; //~ ERROR missing field + let _ = Bar { baz: 0, .. }; //~ ERROR missing field let _ = Bar::default(); // silenced let _ = Bar { bar: S, .. }; // ok let _ = Qux::<4> { .. }; diff --git a/tests/ui/structs/default-field-values/failures.stderr b/tests/ui/structs/default-field-values/failures.stderr index 58f7baee4b28..21c9bfb44b43 100644 --- a/tests/ui/structs/default-field-values/failures.stderr +++ b/tests/ui/structs/default-field-values/failures.stderr @@ -27,14 +27,20 @@ LL + #[derive(Default)] LL | pub struct S; | -error: missing mandatory field `bar` - --> $DIR/failures.rs:53:21 +error: missing field `bar` in initializer + --> $DIR/failures.rs:53:19 | LL | let _ = Bar { .. }; - | ^ + | ^ fields that do not have a defaulted value must be provided explicitly + +error: missing field `bar` in initializer + --> $DIR/failures.rs:54:27 + | +LL | let _ = Bar { baz: 0, .. }; + | ^ fields that do not have a defaulted value must be provided explicitly error[E0308]: mismatched types - --> $DIR/failures.rs:57:17 + --> $DIR/failures.rs:58:17 | LL | let _ = Rak(..); | --- ^^ expected `i32`, found `RangeFull` @@ -47,19 +53,19 @@ note: tuple struct defined here LL | pub struct Rak(i32 = 42); | ^^^ help: you might have meant to use `..` to skip providing a value for expected fields, but this is only supported on non-tuple struct literals; it is instead interpreted as a `std::ops::RangeFull` literal - --> $DIR/failures.rs:57:17 + --> $DIR/failures.rs:58:17 | LL | let _ = Rak(..); | ^^ error[E0061]: this struct takes 1 argument but 2 arguments were supplied - --> $DIR/failures.rs:59:13 + --> $DIR/failures.rs:60:13 | LL | let _ = Rak(0, ..); | ^^^ -- unexpected argument #2 of type `RangeFull` | help: you might have meant to use `..` to skip providing a value for expected fields, but this is only supported on non-tuple struct literals; it is instead interpreted as a `std::ops::RangeFull` literal - --> $DIR/failures.rs:59:20 + --> $DIR/failures.rs:60:20 | LL | let _ = Rak(0, ..); | ^^ @@ -75,13 +81,13 @@ LL + let _ = Rak(0); | error[E0061]: this struct takes 1 argument but 2 arguments were supplied - --> $DIR/failures.rs:61:13 + --> $DIR/failures.rs:62:13 | LL | let _ = Rak(.., 0); | ^^^ -- unexpected argument #1 of type `RangeFull` | help: you might have meant to use `..` to skip providing a value for expected fields, but this is only supported on non-tuple struct literals; it is instead interpreted as a `std::ops::RangeFull` literal - --> $DIR/failures.rs:61:17 + --> $DIR/failures.rs:62:17 | LL | let _ = Rak(.., 0); | ^^ @@ -96,7 +102,7 @@ LL - let _ = Rak(.., 0); LL + let _ = Rak(0); | -error: aborting due to 7 previous errors +error: aborting due to 8 previous errors Some errors have detailed explanations: E0061, E0277, E0308. For more information about an error, try `rustc --explain E0061`. From effef88ac70f2d12229b77b8e428037df8028b7e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 6 Apr 2025 23:37:30 +0000 Subject: [PATCH 193/606] Simplify temp path creation a bit --- .../rustc_codegen_cranelift/src/driver/aot.rs | 24 ++++------- .../rustc_codegen_cranelift/src/global_asm.rs | 2 +- compiler/rustc_codegen_gcc/src/back/write.rs | 13 +++--- compiler/rustc_codegen_llvm/src/back/write.rs | 27 +++++------- .../src/debuginfo/metadata.rs | 2 +- compiler/rustc_codegen_ssa/src/back/link.rs | 3 +- compiler/rustc_codegen_ssa/src/back/write.rs | 24 ++++------- compiler/rustc_codegen_ssa/src/base.rs | 5 ++- compiler/rustc_codegen_ssa/src/errors.rs | 4 +- compiler/rustc_codegen_ssa/src/lib.rs | 11 ++--- compiler/rustc_middle/src/ty/error.rs | 2 +- compiler/rustc_middle/src/ty/print/mod.rs | 2 +- compiler/rustc_session/src/config.rs | 43 +++++++++---------- 13 files changed, 70 insertions(+), 92 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs index 444dc4412868..4ac7b86f0856 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs @@ -169,8 +169,8 @@ fn produce_final_output_artifacts( if codegen_results.modules.len() == 1 { // 1) Only one codegen unit. In this case it's no difficulty // to copy `foo.0.x` to `foo.x`. - let module_name = Some(&codegen_results.modules[0].name[..]); - let path = crate_output.temp_path(output_type, module_name); + let path = + crate_output.temp_path_for_cgu(output_type, &codegen_results.modules[0].name); let output = crate_output.path(output_type); if !output_type.is_text_output() && output.is_tty() { sess.dcx() @@ -183,22 +183,16 @@ fn produce_final_output_artifacts( ensure_removed(sess.dcx(), &path); } } else { - let extension = crate_output - .temp_path(output_type, None) - .extension() - .unwrap() - .to_str() - .unwrap() - .to_owned(); - if crate_output.outputs.contains_explicit_name(&output_type) { // 2) Multiple codegen units, with `--emit foo=some_name`. We have // no good solution for this case, so warn the user. - sess.dcx().emit_warn(ssa_errors::IgnoringEmitPath { extension }); + sess.dcx() + .emit_warn(ssa_errors::IgnoringEmitPath { extension: output_type.extension() }); } else if crate_output.single_output_file.is_some() { // 3) Multiple codegen units, with `-o some_name`. We have // no good solution for this case, so warn the user. - sess.dcx().emit_warn(ssa_errors::IgnoringOutput { extension }); + sess.dcx() + .emit_warn(ssa_errors::IgnoringOutput { extension: output_type.extension() }); } else { // 4) Multiple codegen units, but no explicit name. We // just leave the `foo.0.x` files in place. @@ -409,7 +403,7 @@ fn emit_module( object.set_section_data(comment_section, producer, 1); } - let tmp_file = output_filenames.temp_path(OutputType::Object, Some(&name)); + let tmp_file = output_filenames.temp_path_for_cgu(OutputType::Object, &name); let file = match File::create(&tmp_file) { Ok(file) => file, Err(err) => return Err(format!("error creating object file: {}", err)), @@ -450,7 +444,7 @@ fn reuse_workproduct_for_cgu( ) -> Result { let work_product = cgu.previous_work_product(tcx); let obj_out_regular = - tcx.output_filenames(()).temp_path(OutputType::Object, Some(cgu.name().as_str())); + tcx.output_filenames(()).temp_path_for_cgu(OutputType::Object, cgu.name().as_str()); let source_file_regular = rustc_incremental::in_incr_comp_dir_sess( &tcx.sess, &work_product.saved_files.get("o").expect("no saved object file in work product"), @@ -627,7 +621,7 @@ fn emit_metadata_module(tcx: TyCtxt<'_>, metadata: &EncodedMetadata) -> Compiled .to_string(); let tmp_file = - tcx.output_filenames(()).temp_path(OutputType::Metadata, Some(&metadata_cgu_name)); + tcx.output_filenames(()).temp_path_for_cgu(OutputType::Metadata, &metadata_cgu_name); let symbol_name = rustc_middle::middle::exported_symbols::metadata_symbol_name(tcx); let obj = create_compressed_metadata_file(tcx.sess, metadata, &symbol_name); diff --git a/compiler/rustc_codegen_cranelift/src/global_asm.rs b/compiler/rustc_codegen_cranelift/src/global_asm.rs index 9ea92c300f89..6e3b3677a7ff 100644 --- a/compiler/rustc_codegen_cranelift/src/global_asm.rs +++ b/compiler/rustc_codegen_cranelift/src/global_asm.rs @@ -146,7 +146,7 @@ pub(crate) fn compile_global_asm( global_asm.push('\n'); let global_asm_object_file = add_file_stem_postfix( - config.output_filenames.temp_path(OutputType::Object, Some(cgu_name)), + config.output_filenames.temp_path_for_cgu(OutputType::Object, cgu_name), ".asm", ); diff --git a/compiler/rustc_codegen_gcc/src/back/write.rs b/compiler/rustc_codegen_gcc/src/back/write.rs index 51c5ba73e32b..3427b38ce830 100644 --- a/compiler/rustc_codegen_gcc/src/back/write.rs +++ b/compiler/rustc_codegen_gcc/src/back/write.rs @@ -24,19 +24,15 @@ pub(crate) unsafe fn codegen( { let context = &module.module_llvm.context; - let module_name = module.name.clone(); - let should_combine_object_files = module.module_llvm.should_combine_object_files; - let module_name = Some(&module_name[..]); - // NOTE: Only generate object files with GIMPLE when this environment variable is set for // now because this requires a particular setup (same gcc/lto1/lto-wrapper commit as libgccjit). // TODO(antoyo): remove this environment variable. let fat_lto = env::var("EMBED_LTO_BITCODE").as_deref() == Ok("1"); - let bc_out = cgcx.output_filenames.temp_path(OutputType::Bitcode, module_name); - let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name); + let bc_out = cgcx.output_filenames.temp_path_for_cgu(OutputType::Bitcode, &module.name); + let obj_out = cgcx.output_filenames.temp_path_for_cgu(OutputType::Object, &module.name); if config.bitcode_needed() { if fat_lto { @@ -117,14 +113,15 @@ pub(crate) unsafe fn codegen( } if config.emit_ir { - let out = cgcx.output_filenames.temp_path(OutputType::LlvmAssembly, module_name); + let out = + cgcx.output_filenames.temp_path_for_cgu(OutputType::LlvmAssembly, &module.name); std::fs::write(out, "").expect("write file"); } if config.emit_asm { let _timer = cgcx.prof.generic_activity_with_arg("GCC_module_codegen_emit_asm", &*module.name); - let path = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name); + let path = cgcx.output_filenames.temp_path_for_cgu(OutputType::Assembly, &module.name); context.compile_to_file(OutputKind::Assembler, path.to_str().expect("path to str")); } diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 76d431a49756..c89217947114 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -119,14 +119,14 @@ pub(crate) fn create_target_machine(tcx: TyCtxt<'_>, mod_name: &str) -> OwnedTar tcx.output_filenames(()).split_dwarf_path( tcx.sess.split_debuginfo(), tcx.sess.opts.unstable_opts.split_dwarf_kind, - Some(mod_name), + mod_name, ) } else { None }; let output_obj_file = - Some(tcx.output_filenames(()).temp_path(OutputType::Object, Some(mod_name))); + Some(tcx.output_filenames(()).temp_path_for_cgu(OutputType::Object, mod_name)); let config = TargetMachineFactoryConfig { split_dwarf_file, output_obj_file }; target_machine_factory( @@ -330,8 +330,7 @@ pub(crate) fn save_temp_bitcode( return; } let ext = format!("{name}.bc"); - let cgu = Some(&module.name[..]); - let path = cgcx.output_filenames.temp_path_ext(&ext, cgu); + let path = cgcx.output_filenames.temp_path_ext_for_cgu(&ext, &module.name); write_bitcode_to_file(module, &path) } @@ -694,11 +693,8 @@ pub(crate) unsafe fn optimize( let llcx = &*module.module_llvm.llcx; let _handlers = DiagnosticHandlers::new(cgcx, dcx, llcx, module, CodegenDiagnosticsStage::Opt); - let module_name = module.name.clone(); - let module_name = Some(&module_name[..]); - if config.emit_no_opt_bc { - let out = cgcx.output_filenames.temp_path_ext("no-opt.bc", module_name); + let out = cgcx.output_filenames.temp_path_ext_for_cgu("no-opt.bc", &module.name); write_bitcode_to_file(module, &out) } @@ -744,7 +740,7 @@ pub(crate) unsafe fn optimize( let thin_lto_buffer = unsafe { ThinBuffer::from_raw_ptr(thin_lto_buffer) }; module.thin_lto_buffer = Some(thin_lto_buffer.data().to_vec()); let bc_summary_out = - cgcx.output_filenames.temp_path(OutputType::ThinLinkBitcode, module_name); + cgcx.output_filenames.temp_path_for_cgu(OutputType::ThinLinkBitcode, &module.name); if config.emit_thin_lto_summary && let Some(thin_link_bitcode_filename) = bc_summary_out.file_name() { @@ -801,8 +797,6 @@ pub(crate) unsafe fn codegen( let llmod = module.module_llvm.llmod(); let llcx = &*module.module_llvm.llcx; let tm = &*module.module_llvm.tm; - let module_name = module.name.clone(); - let module_name = Some(&module_name[..]); let _handlers = DiagnosticHandlers::new(cgcx, dcx, llcx, &module, CodegenDiagnosticsStage::Codegen); @@ -814,8 +808,8 @@ pub(crate) unsafe fn codegen( // copy it to the .o file, and delete the bitcode if it wasn't // otherwise requested. - let bc_out = cgcx.output_filenames.temp_path(OutputType::Bitcode, module_name); - let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name); + let bc_out = cgcx.output_filenames.temp_path_for_cgu(OutputType::Bitcode, &module.name); + let obj_out = cgcx.output_filenames.temp_path_for_cgu(OutputType::Object, &module.name); if config.bitcode_needed() { if config.emit_bc || config.emit_obj == EmitObj::Bitcode { @@ -857,7 +851,8 @@ pub(crate) unsafe fn codegen( if config.emit_ir { let _timer = cgcx.prof.generic_activity_with_arg("LLVM_module_codegen_emit_ir", &*module.name); - let out = cgcx.output_filenames.temp_path(OutputType::LlvmAssembly, module_name); + let out = + cgcx.output_filenames.temp_path_for_cgu(OutputType::LlvmAssembly, &module.name); let out_c = path_to_c_string(&out); extern "C" fn demangle_callback( @@ -899,7 +894,7 @@ pub(crate) unsafe fn codegen( if config.emit_asm { let _timer = cgcx.prof.generic_activity_with_arg("LLVM_module_codegen_emit_asm", &*module.name); - let path = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name); + let path = cgcx.output_filenames.temp_path_for_cgu(OutputType::Assembly, &module.name); // We can't use the same module for asm and object code output, // because that triggers various errors like invalid IR or broken @@ -929,7 +924,7 @@ pub(crate) unsafe fn codegen( .prof .generic_activity_with_arg("LLVM_module_codegen_emit_obj", &*module.name); - let dwo_out = cgcx.output_filenames.temp_path_dwo(module_name); + let dwo_out = cgcx.output_filenames.temp_path_dwo_for_cgu(&module.name); let dwo_out = match (cgcx.split_debuginfo, cgcx.split_dwarf_kind) { // Don't change how DWARF is emitted when disabled. (SplitDebuginfo::Off, _) => None, diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 2eaaf127e41e..4b0ec4a6415c 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -910,7 +910,7 @@ pub(crate) fn build_compile_unit_di_node<'ll, 'tcx>( && let Some(f) = output_filenames.split_dwarf_path( tcx.sess.split_debuginfo(), tcx.sess.opts.unstable_opts.split_dwarf_kind, - Some(codegen_unit_name), + codegen_unit_name, ) { // We get a path relative to the working directory from split_dwarf_path Some(tcx.sess.source_map().path_mapping().to_real_filename(f)) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 1d05c4eee4d1..2785664595f3 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -112,8 +112,7 @@ pub fn link_binary( codegen_results.crate_info.local_crate_name, ); let crate_name = format!("{}", codegen_results.crate_info.local_crate_name); - let out_filename = - output.file_for_writing(outputs, OutputType::Exe, Some(crate_name.as_str())); + let out_filename = output.file_for_writing(outputs, OutputType::Exe, &crate_name); match crate_type { CrateType::Rlib => { let _timer = sess.timer("link_rlib"); diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index e816e71379aa..fa698ff59a2b 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -306,14 +306,14 @@ impl TargetMachineFactoryConfig { cgcx.output_filenames.split_dwarf_path( cgcx.split_debuginfo, cgcx.split_dwarf_kind, - Some(module_name), + module_name, ) } else { None }; let output_obj_file = - Some(cgcx.output_filenames.temp_path(OutputType::Object, Some(module_name))); + Some(cgcx.output_filenames.temp_path_for_cgu(OutputType::Object, module_name)); TargetMachineFactoryConfig { split_dwarf_file, output_obj_file } } } @@ -582,8 +582,7 @@ fn produce_final_output_artifacts( if let [module] = &compiled_modules.modules[..] { // 1) Only one codegen unit. In this case it's no difficulty // to copy `foo.0.x` to `foo.x`. - let module_name = Some(&module.name[..]); - let path = crate_output.temp_path(output_type, module_name); + let path = crate_output.temp_path_for_cgu(output_type, &module.name); let output = crate_output.path(output_type); if !output_type.is_text_output() && output.is_tty() { sess.dcx() @@ -596,22 +595,15 @@ fn produce_final_output_artifacts( ensure_removed(sess.dcx(), &path); } } else { - let extension = crate_output - .temp_path(output_type, None) - .extension() - .unwrap() - .to_str() - .unwrap() - .to_owned(); - if crate_output.outputs.contains_explicit_name(&output_type) { // 2) Multiple codegen units, with `--emit foo=some_name`. We have // no good solution for this case, so warn the user. - sess.dcx().emit_warn(errors::IgnoringEmitPath { extension }); + sess.dcx() + .emit_warn(errors::IgnoringEmitPath { extension: output_type.extension() }); } else if crate_output.single_output_file.is_some() { // 3) Multiple codegen units, with `-o some_name`. We have // no good solution for this case, so warn the user. - sess.dcx().emit_warn(errors::IgnoringOutput { extension }); + sess.dcx().emit_warn(errors::IgnoringOutput { extension: output_type.extension() }); } else { // 4) Multiple codegen units, but no explicit name. We // just leave the `foo.0.x` files in place. @@ -967,7 +959,7 @@ fn execute_copy_from_cache_work_item( module.source.saved_files.get("dwo").as_ref().and_then(|saved_dwarf_object_file| { let dwarf_obj_out = cgcx .output_filenames - .split_dwarf_path(cgcx.split_debuginfo, cgcx.split_dwarf_kind, Some(&module.name)) + .split_dwarf_path(cgcx.split_debuginfo, cgcx.split_dwarf_kind, &module.name) .expect( "saved dwarf object in work product but `split_dwarf_path` returned `None`", ); @@ -977,7 +969,7 @@ fn execute_copy_from_cache_work_item( let mut load_from_incr_cache = |perform, output_type: OutputType| { if perform { let saved_file = module.source.saved_files.get(output_type.extension())?; - let output_path = cgcx.output_filenames.temp_path(output_type, Some(&module.name)); + let output_path = cgcx.output_filenames.temp_path_for_cgu(output_type, &module.name); load_from_incr_comp_dir(output_path, &saved_file) } else { None diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 1985b3b71706..511c79c93a26 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -640,8 +640,9 @@ pub fn codegen_crate( let metadata_cgu_name = cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("metadata")).to_string(); tcx.sess.time("write_compressed_metadata", || { - let file_name = - tcx.output_filenames(()).temp_path(OutputType::Metadata, Some(&metadata_cgu_name)); + let file_name = tcx + .output_filenames(()) + .temp_path_for_cgu(OutputType::Metadata, &metadata_cgu_name); let data = create_compressed_metadata_file( tcx.sess, &metadata, diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index b33de8802d83..42cea5c86d4a 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -277,13 +277,13 @@ pub struct BinaryOutputToTty { #[derive(Diagnostic)] #[diag(codegen_ssa_ignoring_emit_path)] pub struct IgnoringEmitPath { - pub extension: String, + pub extension: &'static str, } #[derive(Diagnostic)] #[diag(codegen_ssa_ignoring_output)] pub struct IgnoringOutput { - pub extension: String, + pub extension: &'static str, } #[derive(Diagnostic)] diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 67217927a872..491fe4a57a44 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -106,12 +106,13 @@ impl ModuleCodegen { emit_ir: bool, outputs: &OutputFilenames, ) -> CompiledModule { - let object = emit_obj.then(|| outputs.temp_path(OutputType::Object, Some(&self.name))); - let dwarf_object = emit_dwarf_obj.then(|| outputs.temp_path_dwo(Some(&self.name))); - let bytecode = emit_bc.then(|| outputs.temp_path(OutputType::Bitcode, Some(&self.name))); - let assembly = emit_asm.then(|| outputs.temp_path(OutputType::Assembly, Some(&self.name))); + let object = emit_obj.then(|| outputs.temp_path_for_cgu(OutputType::Object, &self.name)); + let dwarf_object = emit_dwarf_obj.then(|| outputs.temp_path_dwo_for_cgu(&self.name)); + let bytecode = emit_bc.then(|| outputs.temp_path_for_cgu(OutputType::Bitcode, &self.name)); + let assembly = + emit_asm.then(|| outputs.temp_path_for_cgu(OutputType::Assembly, &self.name)); let llvm_ir = - emit_ir.then(|| outputs.temp_path(OutputType::LlvmAssembly, Some(&self.name))); + emit_ir.then(|| outputs.temp_path_for_cgu(OutputType::LlvmAssembly, &self.name)); CompiledModule { name: self.name.clone(), diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index a0e67929c528..5ecf1174defe 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -279,7 +279,7 @@ impl<'tcx> TyCtxt<'tcx> { p.hash(&mut s); let hash = s.finish(); *path = Some(path.take().unwrap_or_else(|| { - self.output_filenames(()).temp_path_ext(&format!("long-type-{hash}.txt"), None) + self.output_filenames(()).temp_path_for_diagnostic(&format!("long-type-{hash}.txt")) })); let Ok(mut file) = File::options().create(true).read(true).append(true).open(&path.as_ref().unwrap()) diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index 5904deaaaad8..9172c5d3ab75 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -382,7 +382,7 @@ pub fn shrunk_instance_name<'tcx>( return (s, None); } - let path = tcx.output_filenames(()).temp_path_ext("long-type.txt", None); + let path = tcx.output_filenames(()).temp_path_for_diagnostic("long-type.txt"); let written_to_path = std::fs::write(&path, s).ok().map(|_| path); (shrunk, written_to_path) diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 56b3fe2ab4cb..946b1201e051 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1015,11 +1015,11 @@ impl OutFileName { &self, outputs: &OutputFilenames, flavor: OutputType, - codegen_unit_name: Option<&str>, + codegen_unit_name: &str, ) -> PathBuf { match *self { OutFileName::Real(ref path) => path.clone(), - OutFileName::Stdout => outputs.temp_path(flavor, codegen_unit_name), + OutFileName::Stdout => outputs.temp_path_for_cgu(flavor, codegen_unit_name), } } @@ -1094,40 +1094,39 @@ impl OutputFilenames { /// Gets the path where a compilation artifact of the given type for the /// given codegen unit should be placed on disk. If codegen_unit_name is /// None, a path distinct from those of any codegen unit will be generated. - pub fn temp_path(&self, flavor: OutputType, codegen_unit_name: Option<&str>) -> PathBuf { + pub fn temp_path_for_cgu(&self, flavor: OutputType, codegen_unit_name: &str) -> PathBuf { let extension = flavor.extension(); - self.temp_path_ext(extension, codegen_unit_name) + self.temp_path_ext_for_cgu(extension, codegen_unit_name) } /// Like `temp_path`, but specifically for dwarf objects. - pub fn temp_path_dwo(&self, codegen_unit_name: Option<&str>) -> PathBuf { - self.temp_path_ext(DWARF_OBJECT_EXT, codegen_unit_name) + pub fn temp_path_dwo_for_cgu(&self, codegen_unit_name: &str) -> PathBuf { + self.temp_path_ext_for_cgu(DWARF_OBJECT_EXT, codegen_unit_name) } /// Like `temp_path`, but also supports things where there is no corresponding /// OutputType, like noopt-bitcode or lto-bitcode. - pub fn temp_path_ext(&self, ext: &str, codegen_unit_name: Option<&str>) -> PathBuf { - let mut extension = String::new(); - - if let Some(codegen_unit_name) = codegen_unit_name { - extension.push_str(codegen_unit_name); - } + pub fn temp_path_ext_for_cgu(&self, ext: &str, codegen_unit_name: &str) -> PathBuf { + let mut extension = codegen_unit_name.to_string(); + // FIXME: This is sketchy that we're not appending `.rcgu` when the ext is empty. + // Append `.rcgu.{ext}`. if !ext.is_empty() { - if !extension.is_empty() { - extension.push('.'); - extension.push_str(RUST_CGU_EXT); - extension.push('.'); - } - + extension.push('.'); + extension.push_str(RUST_CGU_EXT); + extension.push('.'); extension.push_str(ext); } let temps_directory = self.temps_directory.as_ref().unwrap_or(&self.out_directory); - self.with_directory_and_extension(temps_directory, &extension) } + pub fn temp_path_for_diagnostic(&self, ext: &str) -> PathBuf { + let temps_directory = self.temps_directory.as_ref().unwrap_or(&self.out_directory); + self.with_directory_and_extension(temps_directory, &ext) + } + pub fn with_extension(&self, extension: &str) -> PathBuf { self.with_directory_and_extension(&self.out_directory, extension) } @@ -1144,10 +1143,10 @@ impl OutputFilenames { &self, split_debuginfo_kind: SplitDebuginfo, split_dwarf_kind: SplitDwarfKind, - cgu_name: Option<&str>, + cgu_name: &str, ) -> Option { - let obj_out = self.temp_path(OutputType::Object, cgu_name); - let dwo_out = self.temp_path_dwo(cgu_name); + let obj_out = self.temp_path_for_cgu(OutputType::Object, cgu_name); + let dwo_out = self.temp_path_dwo_for_cgu(cgu_name); match (split_debuginfo_kind, split_dwarf_kind) { (SplitDebuginfo::Off, SplitDwarfKind::Single | SplitDwarfKind::Split) => None, // Single mode doesn't change how DWARF is emitted, but does add Split DWARF attributes From 3c3a6a299593d045141faee662ecde9aeb6ec13b Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 6 Apr 2025 23:37:30 +0000 Subject: [PATCH 194/606] Simplify temp path creation a bit --- src/back/write.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/back/write.rs b/src/back/write.rs index 51c5ba73e32b..3427b38ce830 100644 --- a/src/back/write.rs +++ b/src/back/write.rs @@ -24,19 +24,15 @@ pub(crate) unsafe fn codegen( { let context = &module.module_llvm.context; - let module_name = module.name.clone(); - let should_combine_object_files = module.module_llvm.should_combine_object_files; - let module_name = Some(&module_name[..]); - // NOTE: Only generate object files with GIMPLE when this environment variable is set for // now because this requires a particular setup (same gcc/lto1/lto-wrapper commit as libgccjit). // TODO(antoyo): remove this environment variable. let fat_lto = env::var("EMBED_LTO_BITCODE").as_deref() == Ok("1"); - let bc_out = cgcx.output_filenames.temp_path(OutputType::Bitcode, module_name); - let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name); + let bc_out = cgcx.output_filenames.temp_path_for_cgu(OutputType::Bitcode, &module.name); + let obj_out = cgcx.output_filenames.temp_path_for_cgu(OutputType::Object, &module.name); if config.bitcode_needed() { if fat_lto { @@ -117,14 +113,15 @@ pub(crate) unsafe fn codegen( } if config.emit_ir { - let out = cgcx.output_filenames.temp_path(OutputType::LlvmAssembly, module_name); + let out = + cgcx.output_filenames.temp_path_for_cgu(OutputType::LlvmAssembly, &module.name); std::fs::write(out, "").expect("write file"); } if config.emit_asm { let _timer = cgcx.prof.generic_activity_with_arg("GCC_module_codegen_emit_asm", &*module.name); - let path = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name); + let path = cgcx.output_filenames.temp_path_for_cgu(OutputType::Assembly, &module.name); context.compile_to_file(OutputKind::Assembler, path.to_str().expect("path to str")); } From 9c372d8940a8dad14d586f6bd4dd42541f25cd80 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 6 Apr 2025 23:50:16 +0000 Subject: [PATCH 195/606] Prepend temp files with a string per invocation of rustc --- Cargo.lock | 1 + .../rustc_codegen_cranelift/src/driver/aot.rs | 35 +++++++++--- .../rustc_codegen_cranelift/src/global_asm.rs | 3 +- compiler/rustc_codegen_cranelift/src/lib.rs | 2 + compiler/rustc_codegen_gcc/src/back/write.rs | 26 +++++++-- compiler/rustc_codegen_llvm/src/back/write.rs | 57 +++++++++++++++---- .../src/debuginfo/metadata.rs | 1 + compiler/rustc_codegen_ssa/src/back/link.rs | 7 ++- compiler/rustc_codegen_ssa/src/back/write.rs | 29 ++++++++-- compiler/rustc_codegen_ssa/src/base.rs | 8 ++- compiler/rustc_codegen_ssa/src/lib.rs | 19 ++++--- compiler/rustc_interface/src/passes.rs | 1 + compiler/rustc_session/Cargo.toml | 1 + compiler/rustc_session/src/config.rs | 40 ++++++++++--- compiler/rustc_session/src/session.rs | 17 ++++++ .../dirty-incr-due-to-hard-link/rmake.rs | 32 +++++++++++ .../dirty-incr-due-to-hard-link/test.rs | 31 ++++++++++ 17 files changed, 260 insertions(+), 50 deletions(-) create mode 100644 tests/run-make/dirty-incr-due-to-hard-link/rmake.rs create mode 100644 tests/run-make/dirty-incr-due-to-hard-link/test.rs diff --git a/Cargo.lock b/Cargo.lock index 52c9269fa87f..4654b99960f9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4407,6 +4407,7 @@ dependencies = [ "bitflags", "getopts", "libc", + "rand 0.9.0", "rustc_abi", "rustc_ast", "rustc_data_structures", diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs index 4ac7b86f0856..0ea0dbfc44b6 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs @@ -169,8 +169,11 @@ fn produce_final_output_artifacts( if codegen_results.modules.len() == 1 { // 1) Only one codegen unit. In this case it's no difficulty // to copy `foo.0.x` to `foo.x`. - let path = - crate_output.temp_path_for_cgu(output_type, &codegen_results.modules[0].name); + let path = crate_output.temp_path_for_cgu( + output_type, + &codegen_results.modules[0].name, + sess.invocation_temp.as_deref(), + ); let output = crate_output.path(output_type); if !output_type.is_text_output() && output.is_tty() { sess.dcx() @@ -345,6 +348,7 @@ fn make_module(sess: &Session, name: String) -> UnwindModule { fn emit_cgu( output_filenames: &OutputFilenames, + invocation_temp: Option<&str>, prof: &SelfProfilerRef, name: String, module: UnwindModule, @@ -360,6 +364,7 @@ fn emit_cgu( let module_regular = emit_module( output_filenames, + invocation_temp, prof, product.object, ModuleKind::Regular, @@ -385,6 +390,7 @@ fn emit_cgu( fn emit_module( output_filenames: &OutputFilenames, + invocation_temp: Option<&str>, prof: &SelfProfilerRef, mut object: cranelift_object::object::write::Object<'_>, kind: ModuleKind, @@ -403,7 +409,7 @@ fn emit_module( object.set_section_data(comment_section, producer, 1); } - let tmp_file = output_filenames.temp_path_for_cgu(OutputType::Object, &name); + let tmp_file = output_filenames.temp_path_for_cgu(OutputType::Object, &name, invocation_temp); let file = match File::create(&tmp_file) { Ok(file) => file, Err(err) => return Err(format!("error creating object file: {}", err)), @@ -443,8 +449,11 @@ fn reuse_workproduct_for_cgu( cgu: &CodegenUnit<'_>, ) -> Result { let work_product = cgu.previous_work_product(tcx); - let obj_out_regular = - tcx.output_filenames(()).temp_path_for_cgu(OutputType::Object, cgu.name().as_str()); + let obj_out_regular = tcx.output_filenames(()).temp_path_for_cgu( + OutputType::Object, + cgu.name().as_str(), + tcx.sess.invocation_temp.as_deref(), + ); let source_file_regular = rustc_incremental::in_incr_comp_dir_sess( &tcx.sess, &work_product.saved_files.get("o").expect("no saved object file in work product"), @@ -589,13 +598,19 @@ fn module_codegen( let global_asm_object_file = profiler.generic_activity_with_arg("compile assembly", &*cgu_name).run(|| { - crate::global_asm::compile_global_asm(&global_asm_config, &cgu_name, &cx.global_asm) + crate::global_asm::compile_global_asm( + &global_asm_config, + &cgu_name, + &cx.global_asm, + cx.invocation_temp.as_deref(), + ) })?; let codegen_result = profiler.generic_activity_with_arg("write object file", &*cgu_name).run(|| { emit_cgu( &global_asm_config.output_filenames, + cx.invocation_temp.as_deref(), &profiler, cgu_name, module, @@ -620,8 +635,11 @@ fn emit_metadata_module(tcx: TyCtxt<'_>, metadata: &EncodedMetadata) -> Compiled .as_str() .to_string(); - let tmp_file = - tcx.output_filenames(()).temp_path_for_cgu(OutputType::Metadata, &metadata_cgu_name); + let tmp_file = tcx.output_filenames(()).temp_path_for_cgu( + OutputType::Metadata, + &metadata_cgu_name, + tcx.sess.invocation_temp.as_deref(), + ); let symbol_name = rustc_middle::middle::exported_symbols::metadata_symbol_name(tcx); let obj = create_compressed_metadata_file(tcx.sess, metadata, &symbol_name); @@ -651,6 +669,7 @@ fn emit_allocator_module(tcx: TyCtxt<'_>) -> Option { match emit_module( tcx.output_filenames(()), + tcx.sess.invocation_temp.as_deref(), &tcx.sess.prof, product.object, ModuleKind::Allocator, diff --git a/compiler/rustc_codegen_cranelift/src/global_asm.rs b/compiler/rustc_codegen_cranelift/src/global_asm.rs index 6e3b3677a7ff..79cefb05de32 100644 --- a/compiler/rustc_codegen_cranelift/src/global_asm.rs +++ b/compiler/rustc_codegen_cranelift/src/global_asm.rs @@ -132,6 +132,7 @@ pub(crate) fn compile_global_asm( config: &GlobalAsmConfig, cgu_name: &str, global_asm: &str, + invocation_temp: Option<&str>, ) -> Result, String> { if global_asm.is_empty() { return Ok(None); @@ -146,7 +147,7 @@ pub(crate) fn compile_global_asm( global_asm.push('\n'); let global_asm_object_file = add_file_stem_postfix( - config.output_filenames.temp_path_for_cgu(OutputType::Object, cgu_name), + config.output_filenames.temp_path_for_cgu(OutputType::Object, cgu_name, invocation_temp), ".asm", ); diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index e7afaff3b428..9d9e790289cf 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -124,6 +124,7 @@ impl String> Drop for PrintOnPanic { /// inside a single codegen unit with the exception of the Cranelift [`Module`](cranelift_module::Module). struct CodegenCx { output_filenames: Arc, + invocation_temp: Option, should_write_ir: bool, global_asm: String, inline_asm_index: usize, @@ -142,6 +143,7 @@ impl CodegenCx { }; CodegenCx { output_filenames: tcx.output_filenames(()).clone(), + invocation_temp: tcx.sess.invocation_temp.clone(), should_write_ir: crate::pretty_clif::should_write_ir(tcx), global_asm: String::new(), inline_asm_index: 0, diff --git a/compiler/rustc_codegen_gcc/src/back/write.rs b/compiler/rustc_codegen_gcc/src/back/write.rs index 3427b38ce830..16c895322e88 100644 --- a/compiler/rustc_codegen_gcc/src/back/write.rs +++ b/compiler/rustc_codegen_gcc/src/back/write.rs @@ -31,8 +31,16 @@ pub(crate) unsafe fn codegen( // TODO(antoyo): remove this environment variable. let fat_lto = env::var("EMBED_LTO_BITCODE").as_deref() == Ok("1"); - let bc_out = cgcx.output_filenames.temp_path_for_cgu(OutputType::Bitcode, &module.name); - let obj_out = cgcx.output_filenames.temp_path_for_cgu(OutputType::Object, &module.name); + let bc_out = cgcx.output_filenames.temp_path_for_cgu( + OutputType::Bitcode, + &module.name, + cgcx.invocation_temp.as_deref(), + ); + let obj_out = cgcx.output_filenames.temp_path_for_cgu( + OutputType::Object, + &module.name, + cgcx.invocation_temp.as_deref(), + ); if config.bitcode_needed() { if fat_lto { @@ -113,15 +121,22 @@ pub(crate) unsafe fn codegen( } if config.emit_ir { - let out = - cgcx.output_filenames.temp_path_for_cgu(OutputType::LlvmAssembly, &module.name); + let out = cgcx.output_filenames.temp_path_for_cgu( + OutputType::LlvmAssembly, + &module.name, + cgcx.invocation_temp.as_deref(), + ); std::fs::write(out, "").expect("write file"); } if config.emit_asm { let _timer = cgcx.prof.generic_activity_with_arg("GCC_module_codegen_emit_asm", &*module.name); - let path = cgcx.output_filenames.temp_path_for_cgu(OutputType::Assembly, &module.name); + let path = cgcx.output_filenames.temp_path_for_cgu( + OutputType::Assembly, + &module.name, + cgcx.invocation_temp.as_deref(), + ); context.compile_to_file(OutputKind::Assembler, path.to_str().expect("path to str")); } @@ -235,6 +250,7 @@ pub(crate) unsafe fn codegen( config.emit_asm, config.emit_ir, &cgcx.output_filenames, + cgcx.invocation_temp.as_deref(), )) } diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index c89217947114..18d221d232e8 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -120,13 +120,17 @@ pub(crate) fn create_target_machine(tcx: TyCtxt<'_>, mod_name: &str) -> OwnedTar tcx.sess.split_debuginfo(), tcx.sess.opts.unstable_opts.split_dwarf_kind, mod_name, + tcx.sess.invocation_temp.as_deref(), ) } else { None }; - let output_obj_file = - Some(tcx.output_filenames(()).temp_path_for_cgu(OutputType::Object, mod_name)); + let output_obj_file = Some(tcx.output_filenames(()).temp_path_for_cgu( + OutputType::Object, + mod_name, + tcx.sess.invocation_temp.as_deref(), + )); let config = TargetMachineFactoryConfig { split_dwarf_file, output_obj_file }; target_machine_factory( @@ -330,7 +334,11 @@ pub(crate) fn save_temp_bitcode( return; } let ext = format!("{name}.bc"); - let path = cgcx.output_filenames.temp_path_ext_for_cgu(&ext, &module.name); + let path = cgcx.output_filenames.temp_path_ext_for_cgu( + &ext, + &module.name, + cgcx.invocation_temp.as_deref(), + ); write_bitcode_to_file(module, &path) } @@ -694,7 +702,11 @@ pub(crate) unsafe fn optimize( let _handlers = DiagnosticHandlers::new(cgcx, dcx, llcx, module, CodegenDiagnosticsStage::Opt); if config.emit_no_opt_bc { - let out = cgcx.output_filenames.temp_path_ext_for_cgu("no-opt.bc", &module.name); + let out = cgcx.output_filenames.temp_path_ext_for_cgu( + "no-opt.bc", + &module.name, + cgcx.invocation_temp.as_deref(), + ); write_bitcode_to_file(module, &out) } @@ -739,8 +751,11 @@ pub(crate) unsafe fn optimize( if let Some(thin_lto_buffer) = thin_lto_buffer { let thin_lto_buffer = unsafe { ThinBuffer::from_raw_ptr(thin_lto_buffer) }; module.thin_lto_buffer = Some(thin_lto_buffer.data().to_vec()); - let bc_summary_out = - cgcx.output_filenames.temp_path_for_cgu(OutputType::ThinLinkBitcode, &module.name); + let bc_summary_out = cgcx.output_filenames.temp_path_for_cgu( + OutputType::ThinLinkBitcode, + &module.name, + cgcx.invocation_temp.as_deref(), + ); if config.emit_thin_lto_summary && let Some(thin_link_bitcode_filename) = bc_summary_out.file_name() { @@ -808,8 +823,16 @@ pub(crate) unsafe fn codegen( // copy it to the .o file, and delete the bitcode if it wasn't // otherwise requested. - let bc_out = cgcx.output_filenames.temp_path_for_cgu(OutputType::Bitcode, &module.name); - let obj_out = cgcx.output_filenames.temp_path_for_cgu(OutputType::Object, &module.name); + let bc_out = cgcx.output_filenames.temp_path_for_cgu( + OutputType::Bitcode, + &module.name, + cgcx.invocation_temp.as_deref(), + ); + let obj_out = cgcx.output_filenames.temp_path_for_cgu( + OutputType::Object, + &module.name, + cgcx.invocation_temp.as_deref(), + ); if config.bitcode_needed() { if config.emit_bc || config.emit_obj == EmitObj::Bitcode { @@ -851,8 +874,11 @@ pub(crate) unsafe fn codegen( if config.emit_ir { let _timer = cgcx.prof.generic_activity_with_arg("LLVM_module_codegen_emit_ir", &*module.name); - let out = - cgcx.output_filenames.temp_path_for_cgu(OutputType::LlvmAssembly, &module.name); + let out = cgcx.output_filenames.temp_path_for_cgu( + OutputType::LlvmAssembly, + &module.name, + cgcx.invocation_temp.as_deref(), + ); let out_c = path_to_c_string(&out); extern "C" fn demangle_callback( @@ -894,7 +920,11 @@ pub(crate) unsafe fn codegen( if config.emit_asm { let _timer = cgcx.prof.generic_activity_with_arg("LLVM_module_codegen_emit_asm", &*module.name); - let path = cgcx.output_filenames.temp_path_for_cgu(OutputType::Assembly, &module.name); + let path = cgcx.output_filenames.temp_path_for_cgu( + OutputType::Assembly, + &module.name, + cgcx.invocation_temp.as_deref(), + ); // We can't use the same module for asm and object code output, // because that triggers various errors like invalid IR or broken @@ -924,7 +954,9 @@ pub(crate) unsafe fn codegen( .prof .generic_activity_with_arg("LLVM_module_codegen_emit_obj", &*module.name); - let dwo_out = cgcx.output_filenames.temp_path_dwo_for_cgu(&module.name); + let dwo_out = cgcx + .output_filenames + .temp_path_dwo_for_cgu(&module.name, cgcx.invocation_temp.as_deref()); let dwo_out = match (cgcx.split_debuginfo, cgcx.split_dwarf_kind) { // Don't change how DWARF is emitted when disabled. (SplitDebuginfo::Off, _) => None, @@ -989,6 +1021,7 @@ pub(crate) unsafe fn codegen( config.emit_asm, config.emit_ir, &cgcx.output_filenames, + cgcx.invocation_temp.as_deref(), )) } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 4b0ec4a6415c..1eb8f367c544 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -911,6 +911,7 @@ pub(crate) fn build_compile_unit_di_node<'ll, 'tcx>( tcx.sess.split_debuginfo(), tcx.sess.opts.unstable_opts.split_dwarf_kind, codegen_unit_name, + tcx.sess.invocation_temp.as_deref(), ) { // We get a path relative to the working directory from split_dwarf_path Some(tcx.sess.source_map().path_mapping().to_real_filename(f)) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 2785664595f3..8de68925cabb 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -112,7 +112,12 @@ pub fn link_binary( codegen_results.crate_info.local_crate_name, ); let crate_name = format!("{}", codegen_results.crate_info.local_crate_name); - let out_filename = output.file_for_writing(outputs, OutputType::Exe, &crate_name); + let out_filename = output.file_for_writing( + outputs, + OutputType::Exe, + &crate_name, + sess.invocation_temp.as_deref(), + ); match crate_type { CrateType::Rlib => { let _timer = sess.timer("link_rlib"); diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index fa698ff59a2b..0fd4ed8475b4 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -307,13 +307,17 @@ impl TargetMachineFactoryConfig { cgcx.split_debuginfo, cgcx.split_dwarf_kind, module_name, + cgcx.invocation_temp.as_deref(), ) } else { None }; - let output_obj_file = - Some(cgcx.output_filenames.temp_path_for_cgu(OutputType::Object, module_name)); + let output_obj_file = Some(cgcx.output_filenames.temp_path_for_cgu( + OutputType::Object, + module_name, + cgcx.invocation_temp.as_deref(), + )); TargetMachineFactoryConfig { split_dwarf_file, output_obj_file } } } @@ -344,6 +348,7 @@ pub struct CodegenContext { pub crate_types: Vec, pub each_linked_rlib_for_lto: Vec<(CrateNum, PathBuf)>, pub output_filenames: Arc, + pub invocation_temp: Option, pub regular_module_config: Arc, pub metadata_module_config: Arc, pub allocator_module_config: Arc, @@ -582,7 +587,11 @@ fn produce_final_output_artifacts( if let [module] = &compiled_modules.modules[..] { // 1) Only one codegen unit. In this case it's no difficulty // to copy `foo.0.x` to `foo.x`. - let path = crate_output.temp_path_for_cgu(output_type, &module.name); + let path = crate_output.temp_path_for_cgu( + output_type, + &module.name, + sess.invocation_temp.as_deref(), + ); let output = crate_output.path(output_type); if !output_type.is_text_output() && output.is_tty() { sess.dcx() @@ -959,7 +968,12 @@ fn execute_copy_from_cache_work_item( module.source.saved_files.get("dwo").as_ref().and_then(|saved_dwarf_object_file| { let dwarf_obj_out = cgcx .output_filenames - .split_dwarf_path(cgcx.split_debuginfo, cgcx.split_dwarf_kind, &module.name) + .split_dwarf_path( + cgcx.split_debuginfo, + cgcx.split_dwarf_kind, + &module.name, + cgcx.invocation_temp.as_deref(), + ) .expect( "saved dwarf object in work product but `split_dwarf_path` returned `None`", ); @@ -969,7 +983,11 @@ fn execute_copy_from_cache_work_item( let mut load_from_incr_cache = |perform, output_type: OutputType| { if perform { let saved_file = module.source.saved_files.get(output_type.extension())?; - let output_path = cgcx.output_filenames.temp_path_for_cgu(output_type, &module.name); + let output_path = cgcx.output_filenames.temp_path_for_cgu( + output_type, + &module.name, + cgcx.invocation_temp.as_deref(), + ); load_from_incr_comp_dir(output_path, &saved_file) } else { None @@ -1214,6 +1232,7 @@ fn start_executing_work( split_dwarf_kind: tcx.sess.opts.unstable_opts.split_dwarf_kind, parallel: backend.supports_parallel() && !sess.opts.unstable_opts.no_parallel_backend, pointer_size: tcx.data_layout.pointer_size, + invocation_temp: sess.invocation_temp.clone(), }; // This is the "main loop" of parallel work happening for parallel codegen. diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 511c79c93a26..597d2340116b 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -640,9 +640,11 @@ pub fn codegen_crate( let metadata_cgu_name = cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("metadata")).to_string(); tcx.sess.time("write_compressed_metadata", || { - let file_name = tcx - .output_filenames(()) - .temp_path_for_cgu(OutputType::Metadata, &metadata_cgu_name); + let file_name = tcx.output_filenames(()).temp_path_for_cgu( + OutputType::Metadata, + &metadata_cgu_name, + tcx.sess.invocation_temp.as_deref(), + ); let data = create_compressed_metadata_file( tcx.sess, &metadata, diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 491fe4a57a44..153935f25313 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -105,14 +105,19 @@ impl ModuleCodegen { emit_asm: bool, emit_ir: bool, outputs: &OutputFilenames, + invocation_temp: Option<&str>, ) -> CompiledModule { - let object = emit_obj.then(|| outputs.temp_path_for_cgu(OutputType::Object, &self.name)); - let dwarf_object = emit_dwarf_obj.then(|| outputs.temp_path_dwo_for_cgu(&self.name)); - let bytecode = emit_bc.then(|| outputs.temp_path_for_cgu(OutputType::Bitcode, &self.name)); - let assembly = - emit_asm.then(|| outputs.temp_path_for_cgu(OutputType::Assembly, &self.name)); - let llvm_ir = - emit_ir.then(|| outputs.temp_path_for_cgu(OutputType::LlvmAssembly, &self.name)); + let object = emit_obj + .then(|| outputs.temp_path_for_cgu(OutputType::Object, &self.name, invocation_temp)); + let dwarf_object = + emit_dwarf_obj.then(|| outputs.temp_path_dwo_for_cgu(&self.name, invocation_temp)); + let bytecode = emit_bc + .then(|| outputs.temp_path_for_cgu(OutputType::Bitcode, &self.name, invocation_temp)); + let assembly = emit_asm + .then(|| outputs.temp_path_for_cgu(OutputType::Assembly, &self.name, invocation_temp)); + let llvm_ir = emit_ir.then(|| { + outputs.temp_path_for_cgu(OutputType::LlvmAssembly, &self.name, invocation_temp) + }); CompiledModule { name: self.name.clone(), diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 747e36b6a1a2..ad7fb1ad05f3 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -800,6 +800,7 @@ pub fn create_and_enter_global_ctxt FnOnce(TyCtxt<'tcx>) -> T>( sess.opts.cg.metadata.clone(), sess.cfg_version, ); + let outputs = util::build_output_filenames(&pre_configured_attrs, sess); let dep_type = DepsType { dep_names: rustc_query_impl::dep_kind_names() }; diff --git a/compiler/rustc_session/Cargo.toml b/compiler/rustc_session/Cargo.toml index a087725d34dd..63772a322221 100644 --- a/compiler/rustc_session/Cargo.toml +++ b/compiler/rustc_session/Cargo.toml @@ -7,6 +7,7 @@ edition = "2024" # tidy-alphabetical-start bitflags = "2.4.1" getopts = "0.2" +rand = "0.9.0" rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 946b1201e051..bdd54a15147b 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1016,10 +1016,13 @@ impl OutFileName { outputs: &OutputFilenames, flavor: OutputType, codegen_unit_name: &str, + invocation_temp: Option<&str>, ) -> PathBuf { match *self { OutFileName::Real(ref path) => path.clone(), - OutFileName::Stdout => outputs.temp_path_for_cgu(flavor, codegen_unit_name), + OutFileName::Stdout => { + outputs.temp_path_for_cgu(flavor, codegen_unit_name, invocation_temp) + } } } @@ -1094,21 +1097,41 @@ impl OutputFilenames { /// Gets the path where a compilation artifact of the given type for the /// given codegen unit should be placed on disk. If codegen_unit_name is /// None, a path distinct from those of any codegen unit will be generated. - pub fn temp_path_for_cgu(&self, flavor: OutputType, codegen_unit_name: &str) -> PathBuf { + pub fn temp_path_for_cgu( + &self, + flavor: OutputType, + codegen_unit_name: &str, + invocation_temp: Option<&str>, + ) -> PathBuf { let extension = flavor.extension(); - self.temp_path_ext_for_cgu(extension, codegen_unit_name) + self.temp_path_ext_for_cgu(extension, codegen_unit_name, invocation_temp) } /// Like `temp_path`, but specifically for dwarf objects. - pub fn temp_path_dwo_for_cgu(&self, codegen_unit_name: &str) -> PathBuf { - self.temp_path_ext_for_cgu(DWARF_OBJECT_EXT, codegen_unit_name) + pub fn temp_path_dwo_for_cgu( + &self, + codegen_unit_name: &str, + invocation_temp: Option<&str>, + ) -> PathBuf { + self.temp_path_ext_for_cgu(DWARF_OBJECT_EXT, codegen_unit_name, invocation_temp) } /// Like `temp_path`, but also supports things where there is no corresponding /// OutputType, like noopt-bitcode or lto-bitcode. - pub fn temp_path_ext_for_cgu(&self, ext: &str, codegen_unit_name: &str) -> PathBuf { + pub fn temp_path_ext_for_cgu( + &self, + ext: &str, + codegen_unit_name: &str, + invocation_temp: Option<&str>, + ) -> PathBuf { let mut extension = codegen_unit_name.to_string(); + // Append `.{invocation_temp}` to ensure temporary files are unique. + if let Some(rng) = invocation_temp { + extension.push('.'); + extension.push_str(rng); + } + // FIXME: This is sketchy that we're not appending `.rcgu` when the ext is empty. // Append `.rcgu.{ext}`. if !ext.is_empty() { @@ -1144,9 +1167,10 @@ impl OutputFilenames { split_debuginfo_kind: SplitDebuginfo, split_dwarf_kind: SplitDwarfKind, cgu_name: &str, + invocation_temp: Option<&str>, ) -> Option { - let obj_out = self.temp_path_for_cgu(OutputType::Object, cgu_name); - let dwo_out = self.temp_path_dwo_for_cgu(cgu_name); + let obj_out = self.temp_path_for_cgu(OutputType::Object, cgu_name, invocation_temp); + let dwo_out = self.temp_path_dwo_for_cgu(cgu_name, invocation_temp); match (split_debuginfo_kind, split_dwarf_kind) { (SplitDebuginfo::Off, SplitDwarfKind::Single | SplitDwarfKind::Split) => None, // Single mode doesn't change how DWARF is emitted, but does add Split DWARF attributes diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index fb4a437a4879..1359f7eb7bb4 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -6,6 +6,8 @@ use std::sync::Arc; use std::sync::atomic::AtomicBool; use std::{env, fmt, io}; +use rand::{RngCore, rng}; +use rustc_data_structures::base_n::{CASE_INSENSITIVE, ToBaseN}; use rustc_data_structures::flock; use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_data_structures::profiling::{SelfProfiler, SelfProfilerRef}; @@ -203,6 +205,14 @@ pub struct Session { target_filesearch: FileSearch, host_filesearch: FileSearch, + + /// A random string generated per invocation of rustc. + /// + /// This is prepended to all temporary files so that they do not collide + /// during concurrent invocations of rustc, or past invocations that were + /// preserved with a flag like `-C save-temps`, since these files may be + /// hard linked. + pub invocation_temp: Option, } #[derive(PartialEq, Eq, PartialOrd, Ord)] @@ -1117,6 +1127,12 @@ pub fn build_session( let target_filesearch = filesearch::FileSearch::new(&sopts.search_paths, &target_tlib_path, &target); let host_filesearch = filesearch::FileSearch::new(&sopts.search_paths, &host_tlib_path, &host); + + let invocation_temp = sopts + .incremental + .as_ref() + .map(|_| rng().next_u32().to_base_fixed_len(CASE_INSENSITIVE).to_string()); + let sess = Session { target, host, @@ -1140,6 +1156,7 @@ pub fn build_session( expanded_args, target_filesearch, host_filesearch, + invocation_temp, }; validate_commandline_args_with_session_available(&sess); diff --git a/tests/run-make/dirty-incr-due-to-hard-link/rmake.rs b/tests/run-make/dirty-incr-due-to-hard-link/rmake.rs new file mode 100644 index 000000000000..942b667814a9 --- /dev/null +++ b/tests/run-make/dirty-incr-due-to-hard-link/rmake.rs @@ -0,0 +1,32 @@ +//@ only-x86_64-unknown-linux-gnu + +// Regression test for the incremental bug in . +// +// A detailed explanation is described in , +// however the gist of the issue is that hard-linking temporary files can interact strangely +// across incremental sessions that are not finalized due to errors originating from the +// codegen backend. + +use run_make_support::{run, rustc}; + +fn main() { + let mk_rustc = || { + let mut rustc = rustc(); + rustc.input("test.rs").incremental("incr").arg("-Csave-temps").output("test"); + rustc + }; + + // Revision 1 + mk_rustc().cfg("rpass1").run(); + + run("test"); + + // Revision 2 + mk_rustc().cfg("cfail2").run_fail(); + // Expected to fail. + + // Revision 3 + mk_rustc().cfg("rpass3").run(); + + run("test"); +} diff --git a/tests/run-make/dirty-incr-due-to-hard-link/test.rs b/tests/run-make/dirty-incr-due-to-hard-link/test.rs new file mode 100644 index 000000000000..dba5a6bbc826 --- /dev/null +++ b/tests/run-make/dirty-incr-due-to-hard-link/test.rs @@ -0,0 +1,31 @@ +#[inline(never)] +#[cfg(any(rpass1, rpass3))] +fn a() -> i32 { + 0 +} + +#[cfg(any(cfail2))] +fn a() -> i32 { + 1 +} + +fn main() { + evil::evil(); + assert_eq!(a(), 0); +} + +mod evil { + #[cfg(any(rpass1, rpass3))] + pub fn evil() { + unsafe { + std::arch::asm!("/* */"); + } + } + + #[cfg(any(cfail2))] + pub fn evil() { + unsafe { + std::arch::asm!("missing"); + } + } +} From 22d3c0d70a023f3f1641b4b70e4b48949dcface3 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 6 Apr 2025 23:50:16 +0000 Subject: [PATCH 196/606] Prepend temp files with a string per invocation of rustc --- src/back/write.rs | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/back/write.rs b/src/back/write.rs index 3427b38ce830..16c895322e88 100644 --- a/src/back/write.rs +++ b/src/back/write.rs @@ -31,8 +31,16 @@ pub(crate) unsafe fn codegen( // TODO(antoyo): remove this environment variable. let fat_lto = env::var("EMBED_LTO_BITCODE").as_deref() == Ok("1"); - let bc_out = cgcx.output_filenames.temp_path_for_cgu(OutputType::Bitcode, &module.name); - let obj_out = cgcx.output_filenames.temp_path_for_cgu(OutputType::Object, &module.name); + let bc_out = cgcx.output_filenames.temp_path_for_cgu( + OutputType::Bitcode, + &module.name, + cgcx.invocation_temp.as_deref(), + ); + let obj_out = cgcx.output_filenames.temp_path_for_cgu( + OutputType::Object, + &module.name, + cgcx.invocation_temp.as_deref(), + ); if config.bitcode_needed() { if fat_lto { @@ -113,15 +121,22 @@ pub(crate) unsafe fn codegen( } if config.emit_ir { - let out = - cgcx.output_filenames.temp_path_for_cgu(OutputType::LlvmAssembly, &module.name); + let out = cgcx.output_filenames.temp_path_for_cgu( + OutputType::LlvmAssembly, + &module.name, + cgcx.invocation_temp.as_deref(), + ); std::fs::write(out, "").expect("write file"); } if config.emit_asm { let _timer = cgcx.prof.generic_activity_with_arg("GCC_module_codegen_emit_asm", &*module.name); - let path = cgcx.output_filenames.temp_path_for_cgu(OutputType::Assembly, &module.name); + let path = cgcx.output_filenames.temp_path_for_cgu( + OutputType::Assembly, + &module.name, + cgcx.invocation_temp.as_deref(), + ); context.compile_to_file(OutputKind::Assembler, path.to_str().expect("path to str")); } @@ -235,6 +250,7 @@ pub(crate) unsafe fn codegen( config.emit_asm, config.emit_ir, &cgcx.output_filenames, + cgcx.invocation_temp.as_deref(), )) } From 268c56e14455d8889b818c4ea55470b94649aebc Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 7 Apr 2025 20:35:41 +0000 Subject: [PATCH 197/606] Implement overflow for infinite implied lifetime bounds --- .../src/outlives/implicit_infer.rs | 21 +++++++++++++++---- tests/ui/implied-bounds/overflow.rs | 11 ++++++++++ tests/ui/implied-bounds/overflow.stderr | 8 +++++++ 3 files changed, 36 insertions(+), 4 deletions(-) create mode 100644 tests/ui/implied-bounds/overflow.rs create mode 100644 tests/ui/implied-bounds/overflow.stderr diff --git a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs index a0faa5e8429e..780c27d45954 100644 --- a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs +++ b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs @@ -24,8 +24,8 @@ pub(super) fn infer_predicates( // If new predicates were added then we need to re-calculate // all crates since there could be new implied predicates. - loop { - let mut predicates_added = false; + for i in 0.. { + let mut predicates_added = vec![]; // Visit all the crates and infer predicates for id in tcx.hir_free_items() { @@ -83,14 +83,27 @@ pub(super) fn infer_predicates( .get(&item_did.to_def_id()) .map_or(0, |p| p.as_ref().skip_binder().len()); if item_required_predicates.len() > item_predicates_len { - predicates_added = true; + predicates_added.push(item_did); global_inferred_outlives .insert(item_did.to_def_id(), ty::EarlyBinder::bind(item_required_predicates)); } } - if !predicates_added { + if predicates_added.is_empty() { + // We've reached a fixed point. break; + } else if !tcx.recursion_limit().value_within_limit(i) { + let msg = if let &[id] = &predicates_added[..] { + format!("overflow computing implied lifetime bounds for `{}`", tcx.def_path_str(id),) + } else { + "overflow computing implied lifetime bounds".to_string() + }; + tcx.dcx() + .struct_span_fatal( + predicates_added.iter().map(|id| tcx.def_span(*id)).collect::>(), + msg, + ) + .emit(); } } diff --git a/tests/ui/implied-bounds/overflow.rs b/tests/ui/implied-bounds/overflow.rs new file mode 100644 index 000000000000..7c36998dd4d3 --- /dev/null +++ b/tests/ui/implied-bounds/overflow.rs @@ -0,0 +1,11 @@ +trait Tailed<'a>: 'a { + type Tail: Tailed<'a>; +} + +struct List<'a, T: Tailed<'a>> { + //~^ ERROR overflow computing implied lifetime bounds for `List` + next: Box>, + node: &'a T, +} + +fn main() {} diff --git a/tests/ui/implied-bounds/overflow.stderr b/tests/ui/implied-bounds/overflow.stderr new file mode 100644 index 000000000000..2e5a9ab141cf --- /dev/null +++ b/tests/ui/implied-bounds/overflow.stderr @@ -0,0 +1,8 @@ +error: overflow computing implied lifetime bounds for `List` + --> $DIR/overflow.rs:5:1 + | +LL | struct List<'a, T: Tailed<'a>> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + From 4aab8e88e467589e5cf4274c830fd964e30f4166 Mon Sep 17 00:00:00 2001 From: Jonathan Gruner Date: Tue, 8 Apr 2025 00:00:38 +0200 Subject: [PATCH 198/606] document panic behavior of Vec::resize and Vec::resize_with --- library/alloc/src/vec/mod.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 633ef717e04d..e6867febf6c6 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -2803,6 +2803,10 @@ impl Vec { /// want to use the [`Default`] trait to generate values, you can /// pass [`Default::default`] as the second argument. /// + /// # Panics + /// + /// Panics if the new capacity exceeds `isize::MAX` _bytes_. + /// /// # Examples /// /// ``` @@ -3010,6 +3014,10 @@ impl Vec { /// [`Clone`]), use [`Vec::resize_with`]. /// If you only need to resize to a smaller size, use [`Vec::truncate`]. /// + /// # Panics + /// + /// Panics if the new capacity exceeds `isize::MAX` _bytes_. + /// /// # Examples /// /// ``` From f05a23be5c521b865d459154fd7a6cd0f08869ae Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 14 Mar 2025 16:01:09 +0100 Subject: [PATCH 199/606] borrowck typeck children together with their parent --- compiler/rustc_borrowck/src/consumers.rs | 6 +- compiler/rustc_borrowck/src/lib.rs | 117 ++++++++++-------- compiler/rustc_borrowck/src/nll.rs | 19 +-- compiler/rustc_borrowck/src/opaque_types.rs | 55 -------- .../src/region_infer/opaque_types.rs | 12 +- compiler/rustc_borrowck/src/root_cx.rs | 102 +++++++++++++++ compiler/rustc_borrowck/src/type_check/mod.rs | 15 +-- .../rustc_hir_analysis/src/check/check.rs | 10 +- .../src/collect/type_of/opaque.rs | 58 +++++---- compiler/rustc_interface/src/passes.rs | 4 +- compiler/rustc_middle/src/arena.rs | 2 +- compiler/rustc_middle/src/mir/query.rs | 16 +-- compiler/rustc_middle/src/query/mod.rs | 7 +- compiler/rustc_middle/src/ty/codec.rs | 2 +- compiler/rustc_mir_transform/src/lib.rs | 9 +- .../non-structural-match-types-cycle-err.rs | 24 ++++ ...on-structural-match-types-cycle-err.stderr | 64 ++++++++++ .../ui/pattern/non-structural-match-types.rs | 8 -- .../pattern/non-structural-match-types.stderr | 22 +--- 19 files changed, 335 insertions(+), 217 deletions(-) delete mode 100644 compiler/rustc_borrowck/src/opaque_types.rs create mode 100644 compiler/rustc_borrowck/src/root_cx.rs create mode 100644 tests/ui/pattern/non-structural-match-types-cycle-err.rs create mode 100644 tests/ui/pattern/non-structural-match-types-cycle-err.stderr diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs index 45cdd2325647..1f087b092346 100644 --- a/compiler/rustc_borrowck/src/consumers.rs +++ b/compiler/rustc_borrowck/src/consumers.rs @@ -15,6 +15,7 @@ pub use super::polonius::legacy::{ RichLocation, RustcFacts, }; pub use super::region_infer::RegionInferenceContext; +use crate::{BorrowCheckRootCtxt, do_mir_borrowck}; /// Options determining the output behavior of [`get_body_with_borrowck_facts`]. /// @@ -97,8 +98,9 @@ pub struct BodyWithBorrowckFacts<'tcx> { /// * Polonius is highly unstable, so expect regular changes in its signature or other details. pub fn get_body_with_borrowck_facts( tcx: TyCtxt<'_>, - def: LocalDefId, + def_id: LocalDefId, options: ConsumerOptions, ) -> BodyWithBorrowckFacts<'_> { - *super::do_mir_borrowck(tcx, def, Some(options)).1.unwrap() + let mut root_cx = BorrowCheckRootCtxt::new(tcx, def_id); + *do_mir_borrowck(&mut root_cx, def_id, Some(options)).1.unwrap() } diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 240bd20053b1..92519f2aa7b9 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -21,6 +21,7 @@ use std::cell::RefCell; use std::marker::PhantomData; use std::ops::{ControlFlow, Deref}; +use root_cx::BorrowCheckRootCtxt; use rustc_abi::FieldIdx; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::graph::dominators::Dominators; @@ -45,7 +46,7 @@ use rustc_mir_dataflow::move_paths::{ }; use rustc_mir_dataflow::{Analysis, EntryStates, Results, ResultsVisitor, visit_results}; use rustc_session::lint::builtin::{TAIL_EXPR_DROP_ORDER, UNUSED_MUT}; -use rustc_span::{Span, Symbol}; +use rustc_span::{ErrorGuaranteed, Span, Symbol}; use smallvec::SmallVec; use tracing::{debug, instrument}; @@ -73,7 +74,6 @@ mod def_use; mod diagnostics; mod member_constraints; mod nll; -mod opaque_types; mod path_utils; mod place_ext; mod places_conflict; @@ -81,6 +81,7 @@ mod polonius; mod prefixes; mod region_infer; mod renumber; +mod root_cx; mod session_diagnostics; mod type_check; mod universal_regions; @@ -102,44 +103,64 @@ pub fn provide(providers: &mut Providers) { *providers = Providers { mir_borrowck, ..*providers }; } -fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> { +/// Provider for `query mir_borrowck`. Similar to `typeck`, this must +/// only be called for typeck roots which will then borrowck all +/// nested bodies as well. +fn mir_borrowck( + tcx: TyCtxt<'_>, + def: LocalDefId, +) -> Result<&ConcreteOpaqueTypes<'_>, ErrorGuaranteed> { + assert!(!tcx.is_typeck_child(def.to_def_id())); let (input_body, _) = tcx.mir_promoted(def); + debug!("run query mir_borrowck: {}", tcx.def_path_str(def)); + let input_body: &Body<'_> = &input_body.borrow(); - if input_body.should_skip() || input_body.tainted_by_errors.is_some() { - debug!("Skipping borrowck because of injected body or tainted body"); - // Let's make up a borrowck result! Fun times! - let result = BorrowCheckResult { - concrete_opaque_types: FxIndexMap::default(), - closure_requirements: None, - used_mut_upvars: SmallVec::new(), - tainted_by_errors: input_body.tainted_by_errors, - }; - return tcx.arena.alloc(result); + if let Some(guar) = input_body.tainted_by_errors { + debug!("Skipping borrowck because of tainted body"); + Err(guar) + } else if input_body.should_skip() { + debug!("Skipping borrowck because of injected body"); + let opaque_types = ConcreteOpaqueTypes(Default::default()); + Ok(tcx.arena.alloc(opaque_types)) + } else { + let mut root_cx = BorrowCheckRootCtxt::new(tcx, def); + let PropagatedBorrowCheckResults { closure_requirements, used_mut_upvars } = + do_mir_borrowck(&mut root_cx, def, None).0; + debug_assert!(closure_requirements.is_none()); + debug_assert!(used_mut_upvars.is_empty()); + root_cx.finalize() } +} - let borrowck_result = do_mir_borrowck(tcx, def, None).0; - debug!("mir_borrowck done"); - - tcx.arena.alloc(borrowck_result) +/// Data propagated to the typeck parent by nested items. +/// This should always be empty for the typeck root. +#[derive(Debug)] +struct PropagatedBorrowCheckResults<'tcx> { + closure_requirements: Option>, + used_mut_upvars: SmallVec<[FieldIdx; 8]>, } /// Perform the actual borrow checking. /// /// Use `consumer_options: None` for the default behavior of returning -/// [`BorrowCheckResult`] only. Otherwise, return [`BodyWithBorrowckFacts`] according -/// to the given [`ConsumerOptions`]. -#[instrument(skip(tcx), level = "debug")] +/// [`PropagatedBorrowCheckResults`] only. Otherwise, return [`BodyWithBorrowckFacts`] +/// according to the given [`ConsumerOptions`]. +/// +/// For nested bodies this should only be called through `root_cx.get_or_insert_nested`. +#[instrument(skip(root_cx), level = "debug")] fn do_mir_borrowck<'tcx>( - tcx: TyCtxt<'tcx>, + root_cx: &mut BorrowCheckRootCtxt<'tcx>, def: LocalDefId, consumer_options: Option, -) -> (BorrowCheckResult<'tcx>, Option>>) { +) -> (PropagatedBorrowCheckResults<'tcx>, Option>>) { + let tcx = root_cx.tcx; let infcx = BorrowckInferCtxt::new(tcx, def); let (input_body, promoted) = tcx.mir_promoted(def); let input_body: &Body<'_> = &input_body.borrow(); let input_promoted: &IndexSlice<_, _> = &promoted.borrow(); if let Some(e) = input_body.tainted_by_errors { infcx.set_tainted_by_errors(e); + root_cx.set_tainted_by_errors(e); } let mut local_names = IndexVec::from_elem(None, &input_body.local_decls); @@ -185,13 +206,13 @@ fn do_mir_borrowck<'tcx>( // Compute non-lexical lifetimes. let nll::NllOutput { regioncx, - concrete_opaque_types, polonius_input, polonius_output, opt_closure_req, nll_errors, polonius_diagnostics, } = nll::compute_regions( + root_cx, &infcx, free_regions, body, @@ -210,26 +231,19 @@ fn do_mir_borrowck<'tcx>( // We also have a `#[rustc_regions]` annotation that causes us to dump // information. let diags_buffer = &mut BorrowckDiagnosticsBuffer::default(); - nll::dump_annotation( - &infcx, - body, - ®ioncx, - &opt_closure_req, - &concrete_opaque_types, - diags_buffer, - ); + nll::dump_annotation(&infcx, body, ®ioncx, &opt_closure_req, diags_buffer); let movable_coroutine = - // The first argument is the coroutine type passed by value - if let Some(local) = body.local_decls.raw.get(1) - // Get the interior types and args which typeck computed - && let ty::Coroutine(def_id, _) = *local.ty.kind() - && tcx.coroutine_movability(def_id) == hir::Movability::Movable - { - true - } else { - false - }; + // The first argument is the coroutine type passed by value + if let Some(local) = body.local_decls.raw.get(1) + // Get the interior types and args which typeck computed + && let ty::Coroutine(def_id, _) = *local.ty.kind() + && tcx.coroutine_movability(def_id) == hir::Movability::Movable +{ + true +} else { + false +}; // While promoteds should mostly be correct by construction, we need to check them for // invalid moves to detect moving out of arrays:`struct S; fn main() { &([S][0]); }`. @@ -240,6 +254,7 @@ fn do_mir_borrowck<'tcx>( // this check out of `MirBorrowckCtxt`, actually doing so is far from trivial. let move_data = MoveData::gather_moves(promoted_body, tcx, |_| true); let mut promoted_mbcx = MirBorrowckCtxt { + root_cx, infcx: &infcx, body: promoted_body, move_data: &move_data, @@ -280,6 +295,7 @@ fn do_mir_borrowck<'tcx>( } let mut mbcx = MirBorrowckCtxt { + root_cx, infcx: &infcx, body, move_data: &move_data, @@ -347,13 +363,13 @@ fn do_mir_borrowck<'tcx>( debug!("mbcx.used_mut: {:?}", mbcx.used_mut); mbcx.lint_unused_mut(); - let tainted_by_errors = mbcx.emit_errors(); + if let Some(guar) = mbcx.emit_errors() { + mbcx.root_cx.set_tainted_by_errors(guar); + } - let result = BorrowCheckResult { - concrete_opaque_types: concrete_opaque_types.into_inner(), + let result = PropagatedBorrowCheckResults { closure_requirements: opt_closure_req, used_mut_upvars: mbcx.used_mut_upvars, - tainted_by_errors, }; let body_with_facts = if consumer_options.is_some() { @@ -488,6 +504,7 @@ impl<'tcx> Deref for BorrowckInferCtxt<'tcx> { } struct MirBorrowckCtxt<'a, 'infcx, 'tcx> { + root_cx: &'a mut BorrowCheckRootCtxt<'tcx>, infcx: &'infcx BorrowckInferCtxt<'tcx>, body: &'a Body<'tcx>, move_data: &'a MoveData<'tcx>, @@ -1361,11 +1378,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { | AggregateKind::CoroutineClosure(def_id, _) | AggregateKind::Coroutine(def_id, _) => { let def_id = def_id.expect_local(); - let BorrowCheckResult { used_mut_upvars, .. } = - self.infcx.tcx.mir_borrowck(def_id); + let used_mut_upvars = self.root_cx.used_mut_upvars(def_id); debug!("{:?} used_mut_upvars={:?}", def_id, used_mut_upvars); - for field in used_mut_upvars { - self.propagate_closure_used_mut_upvar(&operands[*field]); + // FIXME: We're cloning the `SmallVec` here to avoid borrowing `root_cx` + // when calling `propagate_closure_used_mut_upvar`. This should ideally + // be unnecessary. + for field in used_mut_upvars.clone() { + self.propagate_closure_used_mut_upvar(&operands[field]); } } AggregateKind::Adt(..) diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 8e7b6f083aca..df2fbaeffe13 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -25,7 +25,6 @@ use tracing::{debug, instrument}; use crate::borrow_set::BorrowSet; use crate::consumers::ConsumerOptions; use crate::diagnostics::{BorrowckDiagnosticsBuffer, RegionErrors}; -use crate::opaque_types::ConcreteOpaqueTypes; use crate::polonius::PoloniusDiagnosticsContext; use crate::polonius::legacy::{ PoloniusFacts, PoloniusFactsExt, PoloniusLocationTable, PoloniusOutput, @@ -33,13 +32,12 @@ use crate::polonius::legacy::{ use crate::region_infer::RegionInferenceContext; use crate::type_check::{self, MirTypeckResults}; use crate::universal_regions::UniversalRegions; -use crate::{BorrowckInferCtxt, polonius, renumber}; +use crate::{BorrowCheckRootCtxt, BorrowckInferCtxt, polonius, renumber}; /// The output of `nll::compute_regions`. This includes the computed `RegionInferenceContext`, any /// closure requirements to propagate, and any generated errors. pub(crate) struct NllOutput<'tcx> { pub regioncx: RegionInferenceContext<'tcx>, - pub concrete_opaque_types: ConcreteOpaqueTypes<'tcx>, pub polonius_input: Option>, pub polonius_output: Option>, pub opt_closure_req: Option>, @@ -78,6 +76,7 @@ pub(crate) fn replace_regions_in_mir<'tcx>( /// /// This may result in errors being reported. pub(crate) fn compute_regions<'a, 'tcx>( + root_cx: &mut BorrowCheckRootCtxt<'tcx>, infcx: &BorrowckInferCtxt<'tcx>, universal_regions: UniversalRegions<'tcx>, body: &Body<'tcx>, @@ -98,8 +97,6 @@ pub(crate) fn compute_regions<'a, 'tcx>( let location_map = Rc::new(DenseLocationMap::new(body)); - let mut concrete_opaque_types = ConcreteOpaqueTypes::default(); - // Run the MIR type-checker. let MirTypeckResults { constraints, @@ -107,6 +104,7 @@ pub(crate) fn compute_regions<'a, 'tcx>( opaque_type_values, polonius_context, } = type_check::type_check( + root_cx, infcx, body, promoted, @@ -117,7 +115,6 @@ pub(crate) fn compute_regions<'a, 'tcx>( flow_inits, move_data, Rc::clone(&location_map), - &mut concrete_opaque_types, ); // Create the region inference context, taking ownership of the @@ -181,11 +178,10 @@ pub(crate) fn compute_regions<'a, 'tcx>( infcx.set_tainted_by_errors(guar); } - regioncx.infer_opaque_types(infcx, opaque_type_values, &mut concrete_opaque_types); + regioncx.infer_opaque_types(root_cx, infcx, opaque_type_values); NllOutput { regioncx, - concrete_opaque_types, polonius_input: polonius_facts.map(Box::new), polonius_output, opt_closure_req: closure_region_requirements, @@ -301,7 +297,6 @@ pub(super) fn dump_annotation<'tcx, 'infcx>( body: &Body<'tcx>, regioncx: &RegionInferenceContext<'tcx>, closure_region_requirements: &Option>, - concrete_opaque_types: &ConcreteOpaqueTypes<'tcx>, diagnostics_buffer: &mut BorrowckDiagnosticsBuffer<'infcx, 'tcx>, ) { let tcx = infcx.tcx; @@ -318,7 +313,7 @@ pub(super) fn dump_annotation<'tcx, 'infcx>( // better. let def_span = tcx.def_span(body.source.def_id()); - let mut err = if let Some(closure_region_requirements) = closure_region_requirements { + let err = if let Some(closure_region_requirements) = closure_region_requirements { let mut err = infcx.dcx().struct_span_note(def_span, "external requirements"); regioncx.annotate(tcx, &mut err); @@ -344,9 +339,7 @@ pub(super) fn dump_annotation<'tcx, 'infcx>( err }; - if !concrete_opaque_types.is_empty() { - err.note(format!("Inferred opaque type values:\n{concrete_opaque_types:#?}")); - } + // FIXME(@lcnr): We currently don't dump the inferred hidden types here. diagnostics_buffer.buffer_non_error(err); } diff --git a/compiler/rustc_borrowck/src/opaque_types.rs b/compiler/rustc_borrowck/src/opaque_types.rs deleted file mode 100644 index 5c78814abdd2..000000000000 --- a/compiler/rustc_borrowck/src/opaque_types.rs +++ /dev/null @@ -1,55 +0,0 @@ -use rustc_data_structures::fx::FxIndexMap; -use rustc_hir::def_id::LocalDefId; -use rustc_middle::ty::{OpaqueHiddenType, Ty, TyCtxt}; - -#[derive(Debug, Default)] -pub(super) struct ConcreteOpaqueTypes<'tcx> { - concrete_opaque_types: FxIndexMap>, -} - -impl<'tcx> ConcreteOpaqueTypes<'tcx> { - pub(super) fn is_empty(&self) -> bool { - self.concrete_opaque_types.is_empty() - } - - pub(super) fn into_inner(self) -> FxIndexMap> { - self.concrete_opaque_types - } - - /// Insert an opaque type into the list of opaque types defined by this function - /// after mapping the hidden type to the generic parameters of the opaque type - /// definition. - pub(super) fn insert( - &mut self, - tcx: TyCtxt<'tcx>, - def_id: LocalDefId, - hidden_ty: OpaqueHiddenType<'tcx>, - ) { - // Sometimes two opaque types are the same only after we remap the generic parameters - // back to the opaque type definition. E.g. we may have `OpaqueType` mapped to - // `(X, Y)` and `OpaqueType` mapped to `(Y, X)`, and those are the same, but we - // only know that once we convert the generic parameters to those of the opaque type. - if let Some(prev) = self.concrete_opaque_types.get_mut(&def_id) { - if prev.ty != hidden_ty.ty { - let (Ok(guar) | Err(guar)) = - prev.build_mismatch_error(&hidden_ty, tcx).map(|d| d.emit()); - prev.ty = Ty::new_error(tcx, guar); - } - // Pick a better span if there is one. - // FIXME(oli-obk): collect multiple spans for better diagnostics down the road. - prev.span = prev.span.substitute_dummy(hidden_ty.span); - } else { - self.concrete_opaque_types.insert(def_id, hidden_ty); - } - } - - pub(super) fn extend_from_nested_body( - &mut self, - tcx: TyCtxt<'tcx>, - nested_body: &FxIndexMap>, - ) { - for (&def_id, &hidden_ty) in nested_body { - self.insert(tcx, def_id, hidden_ty); - } - } -} diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index a098450352ff..5dc21667447e 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -10,7 +10,7 @@ use rustc_trait_selection::opaque_types::check_opaque_type_parameter_valid; use tracing::{debug, instrument}; use super::RegionInferenceContext; -use crate::opaque_types::ConcreteOpaqueTypes; +use crate::BorrowCheckRootCtxt; use crate::session_diagnostics::LifetimeMismatchOpaqueParam; use crate::universal_regions::RegionClassification; @@ -58,12 +58,12 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// /// [rustc-dev-guide chapter]: /// https://rustc-dev-guide.rust-lang.org/opaque-types-region-infer-restrictions.html - #[instrument(level = "debug", skip(self, infcx), ret)] + #[instrument(level = "debug", skip(self, root_cx, infcx), ret)] pub(crate) fn infer_opaque_types( &self, + root_cx: &mut BorrowCheckRootCtxt<'tcx>, infcx: &InferCtxt<'tcx>, opaque_ty_decls: FxIndexMap, OpaqueHiddenType<'tcx>>, - concrete_opaque_types: &mut ConcreteOpaqueTypes<'tcx>, ) { let mut decls_modulo_regions: FxIndexMap, (OpaqueTypeKey<'tcx>, Span)> = FxIndexMap::default(); @@ -140,11 +140,11 @@ impl<'tcx> RegionInferenceContext<'tcx> { } } - concrete_opaque_types.insert( - infcx.tcx, + root_cx.add_concrete_opaque_type( opaque_type_key.def_id, - OpaqueHiddenType { ty, span: concrete_type.span }, + OpaqueHiddenType { span: concrete_type.span, ty }, ); + // Check that all opaque types have the same region parameters if they have the same // non-region parameters. This is necessary because within the new solver we perform // various query operations modulo regions, and thus could unsoundly select some impls diff --git a/compiler/rustc_borrowck/src/root_cx.rs b/compiler/rustc_borrowck/src/root_cx.rs new file mode 100644 index 000000000000..ed9e244f7537 --- /dev/null +++ b/compiler/rustc_borrowck/src/root_cx.rs @@ -0,0 +1,102 @@ +use rustc_abi::FieldIdx; +use rustc_data_structures::fx::FxHashMap; +use rustc_hir::def_id::LocalDefId; +use rustc_middle::bug; +use rustc_middle::mir::{ClosureRegionRequirements, ConcreteOpaqueTypes}; +use rustc_middle::ty::{OpaqueHiddenType, Ty, TyCtxt, TypeVisitableExt}; +use rustc_span::ErrorGuaranteed; +use smallvec::SmallVec; + +use crate::PropagatedBorrowCheckResults; + +/// The shared context used by both the root as well as all its nested +/// items. +pub(super) struct BorrowCheckRootCtxt<'tcx> { + pub tcx: TyCtxt<'tcx>, + root_def_id: LocalDefId, + concrete_opaque_types: ConcreteOpaqueTypes<'tcx>, + nested_bodies: FxHashMap>, + tainted_by_errors: Option, +} + +impl<'tcx> BorrowCheckRootCtxt<'tcx> { + pub(super) fn new(tcx: TyCtxt<'tcx>, root_def_id: LocalDefId) -> BorrowCheckRootCtxt<'tcx> { + BorrowCheckRootCtxt { + tcx, + root_def_id, + concrete_opaque_types: Default::default(), + nested_bodies: Default::default(), + tainted_by_errors: None, + } + } + + /// Collect all defining uses of opaque types inside of this typeck root. This + /// expects the hidden type to be mapped to the definition parameters of the opaque + /// and errors if we end up with distinct hidden types. + pub(super) fn add_concrete_opaque_type( + &mut self, + def_id: LocalDefId, + hidden_ty: OpaqueHiddenType<'tcx>, + ) { + // Sometimes two opaque types are the same only after we remap the generic parameters + // back to the opaque type definition. E.g. we may have `OpaqueType` mapped to + // `(X, Y)` and `OpaqueType` mapped to `(Y, X)`, and those are the same, but we + // only know that once we convert the generic parameters to those of the opaque type. + if let Some(prev) = self.concrete_opaque_types.0.get_mut(&def_id) { + if prev.ty != hidden_ty.ty { + let guar = hidden_ty.ty.error_reported().err().unwrap_or_else(|| { + let (Ok(e) | Err(e)) = + prev.build_mismatch_error(&hidden_ty, self.tcx).map(|d| d.emit()); + e + }); + prev.ty = Ty::new_error(self.tcx, guar); + } + // Pick a better span if there is one. + // FIXME(oli-obk): collect multiple spans for better diagnostics down the road. + prev.span = prev.span.substitute_dummy(hidden_ty.span); + } else { + self.concrete_opaque_types.0.insert(def_id, hidden_ty); + } + } + + pub(super) fn set_tainted_by_errors(&mut self, guar: ErrorGuaranteed) { + self.tainted_by_errors = Some(guar); + } + + fn get_or_insert_nested(&mut self, def_id: LocalDefId) -> &PropagatedBorrowCheckResults<'tcx> { + debug_assert_eq!( + self.tcx.typeck_root_def_id(def_id.to_def_id()), + self.root_def_id.to_def_id() + ); + if !self.nested_bodies.contains_key(&def_id) { + let result = super::do_mir_borrowck(self, def_id, None).0; + if let Some(prev) = self.nested_bodies.insert(def_id, result) { + bug!("unexpected previous nested body: {prev:?}"); + } + } + + self.nested_bodies.get(&def_id).unwrap() + } + + pub(super) fn closure_requirements( + &mut self, + nested_body_def_id: LocalDefId, + ) -> &Option> { + &self.get_or_insert_nested(nested_body_def_id).closure_requirements + } + + pub(super) fn used_mut_upvars( + &mut self, + nested_body_def_id: LocalDefId, + ) -> &SmallVec<[FieldIdx; 8]> { + &self.get_or_insert_nested(nested_body_def_id).used_mut_upvars + } + + pub(super) fn finalize(self) -> Result<&'tcx ConcreteOpaqueTypes<'tcx>, ErrorGuaranteed> { + if let Some(guar) = self.tainted_by_errors { + Err(guar) + } else { + Ok(self.tcx.arena.alloc(self.concrete_opaque_types)) + } + } +} diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index f6144a25938c..a17dff5d2715 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -45,7 +45,6 @@ use crate::borrow_set::BorrowSet; use crate::constraints::{OutlivesConstraint, OutlivesConstraintSet}; use crate::diagnostics::UniverseInfo; use crate::member_constraints::MemberConstraintSet; -use crate::opaque_types::ConcreteOpaqueTypes; use crate::polonius::legacy::{PoloniusFacts, PoloniusLocationTable}; use crate::polonius::{PoloniusContext, PoloniusLivenessContext}; use crate::region_infer::TypeTest; @@ -53,7 +52,7 @@ use crate::region_infer::values::{LivenessValues, PlaceholderIndex, PlaceholderI use crate::session_diagnostics::{MoveUnsized, SimdIntrinsicArgConst}; use crate::type_check::free_region_relations::{CreateResult, UniversalRegionRelations}; use crate::universal_regions::{DefiningTy, UniversalRegions}; -use crate::{BorrowckInferCtxt, path_utils}; +use crate::{BorrowCheckRootCtxt, BorrowckInferCtxt, path_utils}; macro_rules! span_mirbug { ($context:expr, $elem:expr, $($message:tt)*) => ({ @@ -102,6 +101,7 @@ mod relate_tys; /// - `move_data` -- move-data constructed when performing the maybe-init dataflow analysis /// - `location_map` -- map between MIR `Location` and `PointIndex` pub(crate) fn type_check<'a, 'tcx>( + root_cx: &mut BorrowCheckRootCtxt<'tcx>, infcx: &BorrowckInferCtxt<'tcx>, body: &Body<'tcx>, promoted: &IndexSlice>, @@ -112,7 +112,6 @@ pub(crate) fn type_check<'a, 'tcx>( flow_inits: ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>, move_data: &MoveData<'tcx>, location_map: Rc, - concrete_opaque_types: &mut ConcreteOpaqueTypes<'tcx>, ) -> MirTypeckResults<'tcx> { let implicit_region_bound = ty::Region::new_var(infcx.tcx, universal_regions.fr_fn_body); let mut constraints = MirTypeckRegionConstraints { @@ -153,6 +152,7 @@ pub(crate) fn type_check<'a, 'tcx>( }; let mut typeck = TypeChecker { + root_cx, infcx, last_span: body.span, body, @@ -167,7 +167,6 @@ pub(crate) fn type_check<'a, 'tcx>( polonius_facts, borrow_set, constraints: &mut constraints, - concrete_opaque_types, polonius_liveness, }; @@ -215,6 +214,7 @@ enum FieldAccessError { /// way, it accrues region constraints -- these can later be used by /// NLL region checking. struct TypeChecker<'a, 'tcx> { + root_cx: &'a mut BorrowCheckRootCtxt<'tcx>, infcx: &'a BorrowckInferCtxt<'tcx>, last_span: Span, body: &'a Body<'tcx>, @@ -233,7 +233,6 @@ struct TypeChecker<'a, 'tcx> { polonius_facts: &'a mut Option, borrow_set: &'a BorrowSet<'tcx>, constraints: &'a mut MirTypeckRegionConstraints<'tcx>, - concrete_opaque_types: &'a mut ConcreteOpaqueTypes<'tcx>, /// When using `-Zpolonius=next`, the liveness helper data used to create polonius constraints. polonius_liveness: Option, } @@ -2503,11 +2502,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { args: GenericArgsRef<'tcx>, locations: Locations, ) -> ty::InstantiatedPredicates<'tcx> { - let closure_borrowck_results = tcx.mir_borrowck(def_id); - self.concrete_opaque_types - .extend_from_nested_body(tcx, &closure_borrowck_results.concrete_opaque_types); - - if let Some(closure_requirements) = &closure_borrowck_results.closure_requirements { + if let Some(closure_requirements) = &self.root_cx.closure_requirements(def_id) { constraint_conversion::ConstraintConversion::new( self.infcx, self.universal_regions, diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index e3ed20e1b318..18ef00dc8b18 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -397,8 +397,11 @@ fn best_definition_site_of_opaque<'tcx>( return ControlFlow::Continue(()); } - if let Some(hidden_ty) = - self.tcx.mir_borrowck(item_def_id).concrete_opaque_types.get(&self.opaque_def_id) + if let Some(hidden_ty) = self + .tcx + .mir_borrowck(item_def_id) + .ok() + .and_then(|opaque_types| opaque_types.0.get(&self.opaque_def_id)) { ControlFlow::Break((hidden_ty.span, item_def_id)) } else { @@ -413,9 +416,6 @@ fn best_definition_site_of_opaque<'tcx>( self.tcx } fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) -> Self::Result { - if let hir::ExprKind::Closure(closure) = ex.kind { - self.check(closure.def_id)?; - } intravisit::walk_expr(self, ex) } fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) -> Self::Result { diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs index 3fe3d71b32da..772197a53ace 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs @@ -183,25 +183,23 @@ impl<'tcx> TaitConstraintLocator<'tcx> { self.non_defining_use_in_defining_scope(item_def_id); } } - DefiningScopeKind::MirBorrowck => { - let borrowck_result = tcx.mir_borrowck(item_def_id); - if let Some(guar) = borrowck_result.tainted_by_errors { - self.insert_found(ty::OpaqueHiddenType::new_error(tcx, guar)); - } else if let Some(&hidden_type) = - borrowck_result.concrete_opaque_types.get(&self.def_id) - { - debug!(?hidden_type, "found constraint"); - self.insert_found(hidden_type); - } else if let Err(guar) = tcx - .type_of_opaque_hir_typeck(self.def_id) - .instantiate_identity() - .error_reported() - { - self.insert_found(ty::OpaqueHiddenType::new_error(tcx, guar)); - } else { - self.non_defining_use_in_defining_scope(item_def_id); + DefiningScopeKind::MirBorrowck => match tcx.mir_borrowck(item_def_id) { + Err(guar) => self.insert_found(ty::OpaqueHiddenType::new_error(tcx, guar)), + Ok(concrete_opaque_types) => { + if let Some(&hidden_type) = concrete_opaque_types.0.get(&self.def_id) { + debug!(?hidden_type, "found constraint"); + self.insert_found(hidden_type); + } else if let Err(guar) = tcx + .type_of_opaque_hir_typeck(self.def_id) + .instantiate_identity() + .error_reported() + { + self.insert_found(ty::OpaqueHiddenType::new_error(tcx, guar)); + } else { + self.non_defining_use_in_defining_scope(item_def_id); + } } - } + }, } } } @@ -264,20 +262,20 @@ pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>( Ty::new_diverging_default(tcx) } } - DefiningScopeKind::MirBorrowck => { - let borrowck_result = tcx.mir_borrowck(owner_def_id); - if let Some(guar) = borrowck_result.tainted_by_errors { - Ty::new_error(tcx, guar) - } else if let Some(hidden_ty) = borrowck_result.concrete_opaque_types.get(&def_id) { - hidden_ty.ty - } else { - let hir_ty = tcx.type_of_opaque_hir_typeck(def_id).instantiate_identity(); - if let Err(guar) = hir_ty.error_reported() { - Ty::new_error(tcx, guar) + DefiningScopeKind::MirBorrowck => match tcx.mir_borrowck(owner_def_id) { + Ok(concrete_opaque_types) => { + if let Some(hidden_ty) = concrete_opaque_types.0.get(&def_id) { + hidden_ty.ty } else { - hir_ty + let hir_ty = tcx.type_of_opaque_hir_typeck(def_id).instantiate_identity(); + if let Err(guar) = hir_ty.error_reported() { + Ty::new_error(tcx, guar) + } else { + hir_ty + } } } - } + Err(guar) => Ty::new_error(tcx, guar), + }, } } diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 747e36b6a1a2..7dfad1658365 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -955,7 +955,9 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { // Run unsafety check because it's responsible for stealing and // deallocating THIR. tcx.ensure_ok().check_unsafety(def_id); - tcx.ensure_ok().mir_borrowck(def_id) + if !tcx.is_typeck_child(def_id.to_def_id()) { + tcx.ensure_ok().mir_borrowck(def_id) + } }); }); sess.time("MIR_effect_checking", || { diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index aef56ea46e95..98273a05446a 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -28,7 +28,7 @@ macro_rules! arena_types { rustc_middle::mir::Body<'tcx> >, [decode] typeck_results: rustc_middle::ty::TypeckResults<'tcx>, - [decode] borrowck_result: rustc_middle::mir::BorrowCheckResult<'tcx>, + [decode] borrowck_result: rustc_middle::mir::ConcreteOpaqueTypes<'tcx>, [] resolver: rustc_data_structures::steal::Steal<( rustc_middle::ty::ResolverAstLowering, std::sync::Arc, diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 5a9fe10938ae..5b44fedeaed3 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -10,7 +10,6 @@ use rustc_index::bit_set::BitMatrix; use rustc_index::{Idx, IndexVec}; use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; use rustc_span::{Span, Symbol}; -use smallvec::SmallVec; use super::{ConstValue, SourceInfo}; use crate::ty::{self, CoroutineArgsExt, OpaqueHiddenType, Ty, TyCtxt, fold_regions}; @@ -85,16 +84,11 @@ impl Debug for CoroutineLayout<'_> { } } -#[derive(Debug, TyEncodable, TyDecodable, HashStable)] -pub struct BorrowCheckResult<'tcx> { - /// All the opaque types that are restricted to concrete types - /// by this function. Unlike the value in `TypeckResults`, this has - /// unerased regions. - pub concrete_opaque_types: FxIndexMap>, - pub closure_requirements: Option>, - pub used_mut_upvars: SmallVec<[FieldIdx; 8]>, - pub tainted_by_errors: Option, -} +/// All the opaque types that are restricted to concrete types +/// by this function. Unlike the value in `TypeckResults`, this has +/// unerased regions. +#[derive(Default, Debug, TyEncodable, TyDecodable, HashStable)] +pub struct ConcreteOpaqueTypes<'tcx>(pub FxIndexMap>); /// The result of the `mir_const_qualif` query. /// diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 0d5fba3cc69b..4fae01b57bc0 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1153,11 +1153,10 @@ rustc_queries! { return_result_from_ensure_ok } - /// Borrow-checks the function body. If this is a closure, returns - /// additional requirements that the closure's creator must verify. - query mir_borrowck(key: LocalDefId) -> &'tcx mir::BorrowCheckResult<'tcx> { + /// Borrow-checks the given typeck root, e.g. functions, const/static items, + /// and its children, e.g. closures, inline consts. + query mir_borrowck(key: LocalDefId) -> Result<&'tcx mir::ConcreteOpaqueTypes<'tcx>, ErrorGuaranteed> { desc { |tcx| "borrow-checking `{}`", tcx.def_path_str(key) } - cache_on_disk_if(tcx) { tcx.is_typeck_child(key.to_def_id()) } } /// Gets a complete map from all types to their inherent impls. diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index 74b34afe616b..23927c112bcd 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -501,7 +501,7 @@ impl_decodable_via_ref! { &'tcx ty::List>, &'tcx traits::ImplSource<'tcx, ()>, &'tcx mir::Body<'tcx>, - &'tcx mir::BorrowCheckResult<'tcx>, + &'tcx mir::ConcreteOpaqueTypes<'tcx>, &'tcx ty::List, &'tcx ty::ListWithCachedTypeInfo>, &'tcx ty::List, diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 6429d3f67ec6..dfd07f0fb168 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -498,8 +498,11 @@ fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> & } // We only need to borrowck non-synthetic MIR. - let tainted_by_errors = - if !tcx.is_synthetic_mir(def) { tcx.mir_borrowck(def).tainted_by_errors } else { None }; + let tainted_by_errors = if !tcx.is_synthetic_mir(def) { + tcx.mir_borrowck(tcx.typeck_root_def_id(def.to_def_id()).expect_local()).err() + } else { + None + }; let is_fn_like = tcx.def_kind(def).is_fn_like(); if is_fn_like { @@ -795,7 +798,7 @@ fn promoted_mir(tcx: TyCtxt<'_>, def: LocalDefId) -> &IndexVec(T); +impl AnyOption { + const NONE: Option = None; +} + +// This is an unfortunate side-effect of borrowchecking nested items +// together with their parent. Evaluating the `AnyOption::<_>::NONE` +// pattern for exhaustiveness checking relies on the layout of the +// async block. This layout relies on `optimized_mir` of the nested +// item which is now borrowck'd together with its parent. As +// borrowck of the parent requires us to have already lowered the match, +// this is a query cycle. + +fn uwu() {} +fn defines() { + match Some(async {}) { + AnyOption::<_>::NONE => {} + //~^ ERROR cycle detected when building THIR for `defines` + _ => {} + } +} +fn main() {} diff --git a/tests/ui/pattern/non-structural-match-types-cycle-err.stderr b/tests/ui/pattern/non-structural-match-types-cycle-err.stderr new file mode 100644 index 000000000000..2f4ac63fc570 --- /dev/null +++ b/tests/ui/pattern/non-structural-match-types-cycle-err.stderr @@ -0,0 +1,64 @@ +error[E0391]: cycle detected when building THIR for `defines` + --> $DIR/non-structural-match-types-cycle-err.rs:19:9 + | +LL | AnyOption::<_>::NONE => {} + | ^^^^^^^^^^^^^^^^^^^^ + | +note: ...which requires evaluating type-level constant... + --> $DIR/non-structural-match-types-cycle-err.rs:5:5 + | +LL | const NONE: Option = None; + | ^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires const-evaluating + checking `::NONE`... + --> $DIR/non-structural-match-types-cycle-err.rs:5:5 + | +LL | const NONE: Option = None; + | ^^^^^^^^^^^^^^^^^^^^^ + = note: ...which requires computing layout of `core::option::Option<{async block@$DIR/non-structural-match-types-cycle-err.rs:18:16: 18:21}>`... + = note: ...which requires computing layout of `{async block@$DIR/non-structural-match-types-cycle-err.rs:18:16: 18:21}`... +note: ...which requires optimizing MIR for `defines::{closure#0}`... + --> $DIR/non-structural-match-types-cycle-err.rs:18:16 + | +LL | match Some(async {}) { + | ^^^^^ +note: ...which requires elaborating drops for `defines::{closure#0}`... + --> $DIR/non-structural-match-types-cycle-err.rs:18:16 + | +LL | match Some(async {}) { + | ^^^^^ +note: ...which requires borrow-checking `defines`... + --> $DIR/non-structural-match-types-cycle-err.rs:17:1 + | +LL | fn defines() { + | ^^^^^^^^^^^^ +note: ...which requires promoting constants in MIR for `defines`... + --> $DIR/non-structural-match-types-cycle-err.rs:17:1 + | +LL | fn defines() { + | ^^^^^^^^^^^^ +note: ...which requires checking if `defines` contains FFI-unwind calls... + --> $DIR/non-structural-match-types-cycle-err.rs:17:1 + | +LL | fn defines() { + | ^^^^^^^^^^^^ +note: ...which requires building MIR for `defines`... + --> $DIR/non-structural-match-types-cycle-err.rs:17:1 + | +LL | fn defines() { + | ^^^^^^^^^^^^ +note: ...which requires match-checking `defines`... + --> $DIR/non-structural-match-types-cycle-err.rs:17:1 + | +LL | fn defines() { + | ^^^^^^^^^^^^ + = note: ...which again requires building THIR for `defines`, completing the cycle +note: cycle used when unsafety-checking `defines` + --> $DIR/non-structural-match-types-cycle-err.rs:17:1 + | +LL | fn defines() { + | ^^^^^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/pattern/non-structural-match-types.rs b/tests/ui/pattern/non-structural-match-types.rs index 5869767c936b..a5ff7fcdb5e4 100644 --- a/tests/ui/pattern/non-structural-match-types.rs +++ b/tests/ui/pattern/non-structural-match-types.rs @@ -1,6 +1,4 @@ //@ edition:2021 -#![feature(const_async_blocks)] - struct AnyOption(T); impl AnyOption { const NONE: Option = None; @@ -19,11 +17,5 @@ fn defines() { //~^ ERROR constant of non-structural type _ => {} } - - match Some(async {}) { - AnyOption::<_>::NONE => {} - //~^ ERROR constant of non-structural type - _ => {} - } } fn main() {} diff --git a/tests/ui/pattern/non-structural-match-types.stderr b/tests/ui/pattern/non-structural-match-types.stderr index da675a9f3ff5..3b74ffe7cb7f 100644 --- a/tests/ui/pattern/non-structural-match-types.stderr +++ b/tests/ui/pattern/non-structural-match-types.stderr @@ -1,5 +1,5 @@ error: constant of non-structural type `Option` in a pattern - --> $DIR/non-structural-match-types.rs:12:9 + --> $DIR/non-structural-match-types.rs:10:9 | LL | impl AnyOption { | -------------------- @@ -11,8 +11,8 @@ LL | AnyOption::<_>::NONE => {} | = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details -error: constant of non-structural type `Option<{closure@$DIR/non-structural-match-types.rs:17:16: 17:18}>` in a pattern - --> $DIR/non-structural-match-types.rs:18:9 +error: constant of non-structural type `Option<{closure@$DIR/non-structural-match-types.rs:15:16: 15:18}>` in a pattern + --> $DIR/non-structural-match-types.rs:16:9 | LL | impl AnyOption { | -------------------- @@ -24,19 +24,5 @@ LL | AnyOption::<_>::NONE => {} | = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details -error: constant of non-structural type `Option<{async block@$DIR/non-structural-match-types.rs:23:16: 23:21}>` in a pattern - --> $DIR/non-structural-match-types.rs:24:9 - | -LL | impl AnyOption { - | -------------------- -LL | const NONE: Option = None; - | --------------------- constant defined here -... -LL | AnyOption::<_>::NONE => {} - | ^^^^^^^^^^^^^^^^^^^^ constant of non-structural type - | - = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details - = note: `ResumeTy` must be annotated with `#[derive(PartialEq)]` to be usable in patterns - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors From 474ec7a3f4da6bdedf2d967d72bc9c6282dfcbb2 Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 2 Apr 2025 14:05:35 +0200 Subject: [PATCH 200/606] move `ClosureRegionRequirements` to `rustc_borrowck` --- compiler/rustc_borrowck/src/lib.rs | 139 ++++++++++++++++- compiler/rustc_borrowck/src/nll.rs | 10 +- compiler/rustc_borrowck/src/polonius/dump.rs | 4 +- .../rustc_borrowck/src/region_infer/mod.rs | 10 +- compiler/rustc_borrowck/src/root_cx.rs | 3 +- .../src/type_check/constraint_conversion.rs | 2 +- compiler/rustc_middle/src/mir/query.rs | 142 +----------------- 7 files changed, 155 insertions(+), 155 deletions(-) diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 92519f2aa7b9..d4924e1514de 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -36,7 +36,7 @@ use rustc_infer::infer::{ }; use rustc_middle::mir::*; use rustc_middle::query::Providers; -use rustc_middle::ty::{self, ParamEnv, RegionVid, TyCtxt, TypingMode}; +use rustc_middle::ty::{self, ParamEnv, RegionVid, Ty, TyCtxt, TypingMode, fold_regions}; use rustc_middle::{bug, span_bug}; use rustc_mir_dataflow::impls::{ EverInitializedPlaces, MaybeInitializedPlaces, MaybeUninitializedPlaces, @@ -140,6 +140,143 @@ struct PropagatedBorrowCheckResults<'tcx> { used_mut_upvars: SmallVec<[FieldIdx; 8]>, } +/// After we borrow check a closure, we are left with various +/// requirements that we have inferred between the free regions that +/// appear in the closure's signature or on its field types. These +/// requirements are then verified and proved by the closure's +/// creating function. This struct encodes those requirements. +/// +/// The requirements are listed as being between various `RegionVid`. The 0th +/// region refers to `'static`; subsequent region vids refer to the free +/// regions that appear in the closure (or coroutine's) type, in order of +/// appearance. (This numbering is actually defined by the `UniversalRegions` +/// struct in the NLL region checker. See for example +/// `UniversalRegions::closure_mapping`.) Note the free regions in the +/// closure's signature and captures are erased. +/// +/// Example: If type check produces a closure with the closure args: +/// +/// ```text +/// ClosureArgs = [ +/// 'a, // From the parent. +/// 'b, +/// i8, // the "closure kind" +/// for<'x> fn(&' &'x u32) -> &'x u32, // the "closure signature" +/// &' String, // some upvar +/// ] +/// ``` +/// +/// We would "renumber" each free region to a unique vid, as follows: +/// +/// ```text +/// ClosureArgs = [ +/// '1, // From the parent. +/// '2, +/// i8, // the "closure kind" +/// for<'x> fn(&'3 &'x u32) -> &'x u32, // the "closure signature" +/// &'4 String, // some upvar +/// ] +/// ``` +/// +/// Now the code might impose a requirement like `'1: '2`. When an +/// instance of the closure is created, the corresponding free regions +/// can be extracted from its type and constrained to have the given +/// outlives relationship. +#[derive(Clone, Debug)] +pub struct ClosureRegionRequirements<'tcx> { + /// The number of external regions defined on the closure. In our + /// example above, it would be 3 -- one for `'static`, then `'1` + /// and `'2`. This is just used for a sanity check later on, to + /// make sure that the number of regions we see at the callsite + /// matches. + pub num_external_vids: usize, + + /// Requirements between the various free regions defined in + /// indices. + pub outlives_requirements: Vec>, +} + +/// Indicates an outlives-constraint between a type or between two +/// free regions declared on the closure. +#[derive(Copy, Clone, Debug)] +pub struct ClosureOutlivesRequirement<'tcx> { + // This region or type ... + pub subject: ClosureOutlivesSubject<'tcx>, + + // ... must outlive this one. + pub outlived_free_region: ty::RegionVid, + + // If not, report an error here ... + pub blame_span: Span, + + // ... due to this reason. + pub category: ConstraintCategory<'tcx>, +} + +// Make sure this enum doesn't unintentionally grow +#[cfg(target_pointer_width = "64")] +rustc_data_structures::static_assert_size!(ConstraintCategory<'_>, 16); + +/// The subject of a `ClosureOutlivesRequirement` -- that is, the thing +/// that must outlive some region. +#[derive(Copy, Clone, Debug)] +pub enum ClosureOutlivesSubject<'tcx> { + /// Subject is a type, typically a type parameter, but could also + /// be a projection. Indicates a requirement like `T: 'a` being + /// passed to the caller, where the type here is `T`. + Ty(ClosureOutlivesSubjectTy<'tcx>), + + /// Subject is a free region from the closure. Indicates a requirement + /// like `'a: 'b` being passed to the caller; the region here is `'a`. + Region(ty::RegionVid), +} + +/// Represents a `ty::Ty` for use in [`ClosureOutlivesSubject`]. +/// +/// This abstraction is necessary because the type may include `ReVar` regions, +/// which is what we use internally within NLL code, and they can't be used in +/// a query response. +/// +/// DO NOT implement `TypeVisitable` or `TypeFoldable` traits, because this +/// type is not recognized as a binder for late-bound region. +#[derive(Copy, Clone, Debug)] +pub struct ClosureOutlivesSubjectTy<'tcx> { + inner: Ty<'tcx>, +} + +impl<'tcx> ClosureOutlivesSubjectTy<'tcx> { + /// All regions of `ty` must be of kind `ReVar` and must represent + /// universal regions *external* to the closure. + pub fn bind(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self { + let inner = fold_regions(tcx, ty, |r, depth| match r.kind() { + ty::ReVar(vid) => { + let br = ty::BoundRegion { + var: ty::BoundVar::from_usize(vid.index()), + kind: ty::BoundRegionKind::Anon, + }; + ty::Region::new_bound(tcx, depth, br) + } + _ => bug!("unexpected region in ClosureOutlivesSubjectTy: {r:?}"), + }); + + Self { inner } + } + + pub fn instantiate( + self, + tcx: TyCtxt<'tcx>, + mut map: impl FnMut(ty::RegionVid) -> ty::Region<'tcx>, + ) -> Ty<'tcx> { + fold_regions(tcx, self.inner, |r, depth| match r.kind() { + ty::ReBound(debruijn, br) => { + debug_assert_eq!(debruijn, depth); + map(ty::RegionVid::from_usize(br.var.index())) + } + _ => bug!("unexpected region {r:?}"), + }) + } +} + /// Perform the actual borrow checking. /// /// Use `consumer_options: None` for the default behavior of returning diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index df2fbaeffe13..8a2a34f207aa 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -8,10 +8,7 @@ use std::str::FromStr; use polonius_engine::{Algorithm, Output}; use rustc_index::IndexSlice; use rustc_middle::mir::pretty::{PrettyPrintMirOptions, dump_mir_with_options}; -use rustc_middle::mir::{ - Body, ClosureOutlivesSubject, ClosureRegionRequirements, PassWhere, Promoted, create_dump_file, - dump_enabled, dump_mir, -}; +use rustc_middle::mir::{Body, PassWhere, Promoted, create_dump_file, dump_enabled, dump_mir}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, TyCtxt}; use rustc_mir_dataflow::ResultsCursor; @@ -32,7 +29,10 @@ use crate::polonius::legacy::{ use crate::region_infer::RegionInferenceContext; use crate::type_check::{self, MirTypeckResults}; use crate::universal_regions::UniversalRegions; -use crate::{BorrowCheckRootCtxt, BorrowckInferCtxt, polonius, renumber}; +use crate::{ + BorrowCheckRootCtxt, BorrowckInferCtxt, ClosureOutlivesSubject, ClosureRegionRequirements, + polonius, renumber, +}; /// The output of `nll::compute_regions`. This includes the computed `RegionInferenceContext`, any /// closure requirements to propagate, and any generated errors. diff --git a/compiler/rustc_borrowck/src/polonius/dump.rs b/compiler/rustc_borrowck/src/polonius/dump.rs index aa64a7c4e2a6..9e4ebfa59301 100644 --- a/compiler/rustc_borrowck/src/polonius/dump.rs +++ b/compiler/rustc_borrowck/src/polonius/dump.rs @@ -5,7 +5,7 @@ use rustc_index::IndexVec; use rustc_middle::mir::pretty::{ PassWhere, PrettyPrintMirOptions, create_dump_file, dump_enabled, dump_mir_to_writer, }; -use rustc_middle::mir::{Body, ClosureRegionRequirements, Location}; +use rustc_middle::mir::{Body, Location}; use rustc_middle::ty::{RegionVid, TyCtxt}; use rustc_mir_dataflow::points::PointIndex; use rustc_session::config::MirIncludeSpans; @@ -17,7 +17,7 @@ use crate::polonius::{ }; use crate::region_infer::values::LivenessValues; use crate::type_check::Locations; -use crate::{BorrowckInferCtxt, RegionInferenceContext}; +use crate::{BorrowckInferCtxt, ClosureRegionRequirements, RegionInferenceContext}; /// `-Zdump-mir=polonius` dumps MIR annotated with NLL and polonius specific information. pub(crate) fn dump_polonius_mir<'tcx>( diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 5756a5e7c7c5..15a515a501ad 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -13,9 +13,8 @@ use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound, use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin}; use rustc_middle::bug; use rustc_middle::mir::{ - AnnotationSource, BasicBlock, Body, ClosureOutlivesRequirement, ClosureOutlivesSubject, - ClosureOutlivesSubjectTy, ClosureRegionRequirements, ConstraintCategory, Local, Location, - ReturnConstraint, TerminatorKind, + AnnotationSource, BasicBlock, Body, ConstraintCategory, Local, Location, ReturnConstraint, + TerminatorKind, }; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, UniverseIndex, fold_regions}; @@ -24,7 +23,6 @@ use rustc_span::hygiene::DesugaringKind; use rustc_span::{DUMMY_SP, Span}; use tracing::{Level, debug, enabled, instrument, trace}; -use crate::BorrowckInferCtxt; use crate::constraints::graph::{self, NormalConstraintGraph, RegionGraph}; use crate::constraints::{ConstraintSccIndex, OutlivesConstraint, OutlivesConstraintSet}; use crate::dataflow::BorrowIndex; @@ -37,6 +35,10 @@ use crate::region_infer::values::{LivenessValues, RegionElement, RegionValues, T use crate::type_check::free_region_relations::UniversalRegionRelations; use crate::type_check::{Locations, MirTypeckRegionConstraints}; use crate::universal_regions::UniversalRegions; +use crate::{ + BorrowckInferCtxt, ClosureOutlivesRequirement, ClosureOutlivesSubject, + ClosureOutlivesSubjectTy, ClosureRegionRequirements, +}; mod dump_mir; mod graphviz; diff --git a/compiler/rustc_borrowck/src/root_cx.rs b/compiler/rustc_borrowck/src/root_cx.rs index ed9e244f7537..13daa5c72214 100644 --- a/compiler/rustc_borrowck/src/root_cx.rs +++ b/compiler/rustc_borrowck/src/root_cx.rs @@ -2,12 +2,11 @@ use rustc_abi::FieldIdx; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::LocalDefId; use rustc_middle::bug; -use rustc_middle::mir::{ClosureRegionRequirements, ConcreteOpaqueTypes}; use rustc_middle::ty::{OpaqueHiddenType, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::ErrorGuaranteed; use smallvec::SmallVec; -use crate::PropagatedBorrowCheckResults; +use crate::{ClosureRegionRequirements, ConcreteOpaqueTypes, PropagatedBorrowCheckResults}; /// The shared context used by both the root as well as all its nested /// items. diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index 6fbe1db6330e..a1fb64e85dc1 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -6,7 +6,6 @@ use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound}; use rustc_infer::infer::{self, InferCtxt, SubregionOrigin}; use rustc_infer::traits::query::type_op::DeeplyNormalize; use rustc_middle::bug; -use rustc_middle::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, ConstraintCategory}; use rustc_middle::ty::{ self, GenericArgKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, fold_regions, }; @@ -18,6 +17,7 @@ use crate::constraints::OutlivesConstraint; use crate::region_infer::TypeTest; use crate::type_check::{Locations, MirTypeckRegionConstraints}; use crate::universal_regions::UniversalRegions; +use crate::{ClosureOutlivesSubject, ClosureRegionRequirements, ConstraintCategory}; pub(crate) struct ConstraintConversion<'a, 'tcx> { infcx: &'a InferCtxt<'tcx>, diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 5b44fedeaed3..3fc05f2caf2a 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -6,13 +6,13 @@ use rustc_abi::{FieldIdx, VariantIdx}; use rustc_data_structures::fx::FxIndexMap; use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::LocalDefId; +use rustc_index::IndexVec; use rustc_index::bit_set::BitMatrix; -use rustc_index::{Idx, IndexVec}; use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; use rustc_span::{Span, Symbol}; use super::{ConstValue, SourceInfo}; -use crate::ty::{self, CoroutineArgsExt, OpaqueHiddenType, Ty, TyCtxt, fold_regions}; +use crate::ty::{self, CoroutineArgsExt, OpaqueHiddenType, Ty}; rustc_index::newtype_index! { #[derive(HashStable)] @@ -102,84 +102,6 @@ pub struct ConstQualifs { pub needs_non_const_drop: bool, pub tainted_by_errors: Option, } - -/// After we borrow check a closure, we are left with various -/// requirements that we have inferred between the free regions that -/// appear in the closure's signature or on its field types. These -/// requirements are then verified and proved by the closure's -/// creating function. This struct encodes those requirements. -/// -/// The requirements are listed as being between various `RegionVid`. The 0th -/// region refers to `'static`; subsequent region vids refer to the free -/// regions that appear in the closure (or coroutine's) type, in order of -/// appearance. (This numbering is actually defined by the `UniversalRegions` -/// struct in the NLL region checker. See for example -/// `UniversalRegions::closure_mapping`.) Note the free regions in the -/// closure's signature and captures are erased. -/// -/// Example: If type check produces a closure with the closure args: -/// -/// ```text -/// ClosureArgs = [ -/// 'a, // From the parent. -/// 'b, -/// i8, // the "closure kind" -/// for<'x> fn(&' &'x u32) -> &'x u32, // the "closure signature" -/// &' String, // some upvar -/// ] -/// ``` -/// -/// We would "renumber" each free region to a unique vid, as follows: -/// -/// ```text -/// ClosureArgs = [ -/// '1, // From the parent. -/// '2, -/// i8, // the "closure kind" -/// for<'x> fn(&'3 &'x u32) -> &'x u32, // the "closure signature" -/// &'4 String, // some upvar -/// ] -/// ``` -/// -/// Now the code might impose a requirement like `'1: '2`. When an -/// instance of the closure is created, the corresponding free regions -/// can be extracted from its type and constrained to have the given -/// outlives relationship. -#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)] -pub struct ClosureRegionRequirements<'tcx> { - /// The number of external regions defined on the closure. In our - /// example above, it would be 3 -- one for `'static`, then `'1` - /// and `'2`. This is just used for a sanity check later on, to - /// make sure that the number of regions we see at the callsite - /// matches. - pub num_external_vids: usize, - - /// Requirements between the various free regions defined in - /// indices. - pub outlives_requirements: Vec>, -} - -/// Indicates an outlives-constraint between a type or between two -/// free regions declared on the closure. -#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)] -pub struct ClosureOutlivesRequirement<'tcx> { - // This region or type ... - pub subject: ClosureOutlivesSubject<'tcx>, - - // ... must outlive this one. - pub outlived_free_region: ty::RegionVid, - - // If not, report an error here ... - pub blame_span: Span, - - // ... due to this reason. - pub category: ConstraintCategory<'tcx>, -} - -// Make sure this enum doesn't unintentionally grow -#[cfg(target_pointer_width = "64")] -rustc_data_structures::static_assert_size!(ConstraintCategory<'_>, 16); - /// Outlives-constraints can be categorized to determine whether and why they /// are interesting (for error reporting). Order of variants indicates sort /// order of the category, thereby influencing diagnostic output. @@ -247,66 +169,6 @@ pub enum AnnotationSource { GenericArg, } -/// The subject of a `ClosureOutlivesRequirement` -- that is, the thing -/// that must outlive some region. -#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)] -pub enum ClosureOutlivesSubject<'tcx> { - /// Subject is a type, typically a type parameter, but could also - /// be a projection. Indicates a requirement like `T: 'a` being - /// passed to the caller, where the type here is `T`. - Ty(ClosureOutlivesSubjectTy<'tcx>), - - /// Subject is a free region from the closure. Indicates a requirement - /// like `'a: 'b` being passed to the caller; the region here is `'a`. - Region(ty::RegionVid), -} - -/// Represents a `ty::Ty` for use in [`ClosureOutlivesSubject`]. -/// -/// This abstraction is necessary because the type may include `ReVar` regions, -/// which is what we use internally within NLL code, and they can't be used in -/// a query response. -/// -/// DO NOT implement `TypeVisitable` or `TypeFoldable` traits, because this -/// type is not recognized as a binder for late-bound region. -#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)] -pub struct ClosureOutlivesSubjectTy<'tcx> { - inner: Ty<'tcx>, -} - -impl<'tcx> ClosureOutlivesSubjectTy<'tcx> { - /// All regions of `ty` must be of kind `ReVar` and must represent - /// universal regions *external* to the closure. - pub fn bind(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self { - let inner = fold_regions(tcx, ty, |r, depth| match r.kind() { - ty::ReVar(vid) => { - let br = ty::BoundRegion { - var: ty::BoundVar::new(vid.index()), - kind: ty::BoundRegionKind::Anon, - }; - ty::Region::new_bound(tcx, depth, br) - } - _ => bug!("unexpected region in ClosureOutlivesSubjectTy: {r:?}"), - }); - - Self { inner } - } - - pub fn instantiate( - self, - tcx: TyCtxt<'tcx>, - mut map: impl FnMut(ty::RegionVid) -> ty::Region<'tcx>, - ) -> Ty<'tcx> { - fold_regions(tcx, self.inner, |r, depth| match r.kind() { - ty::ReBound(debruijn, br) => { - debug_assert_eq!(debruijn, depth); - map(ty::RegionVid::new(br.var.index())) - } - _ => bug!("unexpected region {r:?}"), - }) - } -} - /// The constituent parts of a mir constant of kind ADT or array. #[derive(Copy, Clone, Debug, HashStable)] pub struct DestructuredConstant<'tcx> { From d35ad8d8362071410fd934dbb737379d736019ca Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 8 Apr 2025 00:34:35 +0200 Subject: [PATCH 201/606] add negative impl --- compiler/rustc_borrowck/src/lib.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index d4924e1514de..64ad1c968565 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -9,6 +9,7 @@ #![feature(file_buffered)] #![feature(if_let_guard)] #![feature(let_chains)] +#![feature(negative_impls)] #![feature(never_type)] #![feature(rustc_attrs)] #![feature(rustdoc_internals)] @@ -36,7 +37,9 @@ use rustc_infer::infer::{ }; use rustc_middle::mir::*; use rustc_middle::query::Providers; -use rustc_middle::ty::{self, ParamEnv, RegionVid, Ty, TyCtxt, TypingMode, fold_regions}; +use rustc_middle::ty::{ + self, ParamEnv, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitable, TypingMode, fold_regions, +}; use rustc_middle::{bug, span_bug}; use rustc_mir_dataflow::impls::{ EverInitializedPlaces, MaybeInitializedPlaces, MaybeUninitializedPlaces, @@ -236,13 +239,14 @@ pub enum ClosureOutlivesSubject<'tcx> { /// This abstraction is necessary because the type may include `ReVar` regions, /// which is what we use internally within NLL code, and they can't be used in /// a query response. -/// -/// DO NOT implement `TypeVisitable` or `TypeFoldable` traits, because this -/// type is not recognized as a binder for late-bound region. #[derive(Copy, Clone, Debug)] pub struct ClosureOutlivesSubjectTy<'tcx> { inner: Ty<'tcx>, } +// DO NOT implement `TypeVisitable` or `TypeFoldable` traits, because this +// type is not recognized as a binder for late-bound region. +impl<'tcx, I> !TypeVisitable for ClosureOutlivesSubjectTy<'tcx> {} +impl<'tcx, I> !TypeFoldable for ClosureOutlivesSubjectTy<'tcx> {} impl<'tcx> ClosureOutlivesSubjectTy<'tcx> { /// All regions of `ty` must be of kind `ReVar` and must represent From b08e9c2a60f4dbab4bdaa733727947b3395de329 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 7 Apr 2025 22:32:49 +0000 Subject: [PATCH 202/606] Fix stack overflow in exhaustiveness due to recursive HIR opaque type values --- compiler/rustc_pattern_analysis/src/rustc.rs | 40 ++++++++-- ...recursive-in-exhaustiveness.current.stderr | 56 +++++++++++++ .../recursive-in-exhaustiveness.next.stderr | 80 +++++++++++++++++++ .../impl-trait/recursive-in-exhaustiveness.rs | 53 ++++++++++++ 4 files changed, 224 insertions(+), 5 deletions(-) create mode 100644 tests/ui/impl-trait/recursive-in-exhaustiveness.current.stderr create mode 100644 tests/ui/impl-trait/recursive-in-exhaustiveness.next.stderr create mode 100644 tests/ui/impl-trait/recursive-in-exhaustiveness.rs diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index 88d45ead2953..7c12f69f14c1 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -1,5 +1,6 @@ use std::fmt; use std::iter::once; +use std::ops::ControlFlow; use rustc_abi::{FIRST_VARIANT, FieldIdx, Integer, VariantIdx}; use rustc_arena::DroplessArena; @@ -11,7 +12,8 @@ use rustc_middle::mir::{self, Const}; use rustc_middle::thir::{self, Pat, PatKind, PatRange, PatRangeBoundary}; use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::{ - self, FieldDef, OpaqueTypeKey, ScalarInt, Ty, TyCtxt, TypeVisitableExt, VariantDef, + self, FieldDef, OpaqueTypeKey, ScalarInt, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, + TypeVisitableExt, TypeVisitor, VariantDef, }; use rustc_middle::{bug, span_bug}; use rustc_session::lint; @@ -135,11 +137,22 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { /// Returns the hidden type corresponding to this key if the body under analysis is allowed to /// know it. fn reveal_opaque_key(&self, key: OpaqueTypeKey<'tcx>) -> Option> { - self.typeck_results - .concrete_opaque_types - .get(&key.def_id) - .map(|x| ty::EarlyBinder::bind(x.ty).instantiate(self.tcx, key.args)) + if let Some(hidden_ty) = self.typeck_results.concrete_opaque_types.get(&key.def_id) { + let ty = ty::EarlyBinder::bind(hidden_ty.ty).instantiate(self.tcx, key.args); + if ty.visit_with(&mut RecursiveOpaque { def_id: key.def_id.into() }).is_continue() { + Some(ty) + } else { + // HACK: We skip revealing opaque types which recursively expand + // to themselves. This is because we may infer hidden types like + // `Opaque = Opaque>` or `Opaque = Opaque<(T,)>` + // in hir typeck. + None + } + } else { + None + } } + // This can take a non-revealed `Ty` because it reveals opaques itself. pub fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool { !ty.inhabited_predicate(self.tcx).apply_revealing_opaque( @@ -1105,3 +1118,20 @@ pub fn analyze_match<'p, 'tcx>( Ok(report) } + +struct RecursiveOpaque { + def_id: DefId, +} +impl<'tcx> TypeVisitor> for RecursiveOpaque { + type Result = ControlFlow<()>; + + fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { + if let ty::Alias(ty::Opaque, alias_ty) = t.kind() { + if alias_ty.def_id == self.def_id { + return ControlFlow::Break(()); + } + } + + if t.has_opaque_types() { t.super_visit_with(self) } else { ControlFlow::Continue(()) } + } +} diff --git a/tests/ui/impl-trait/recursive-in-exhaustiveness.current.stderr b/tests/ui/impl-trait/recursive-in-exhaustiveness.current.stderr new file mode 100644 index 000000000000..42dbc7c91607 --- /dev/null +++ b/tests/ui/impl-trait/recursive-in-exhaustiveness.current.stderr @@ -0,0 +1,56 @@ +warning: function cannot return without recursing + --> $DIR/recursive-in-exhaustiveness.rs:17:1 + | +LL | fn build(x: T) -> impl Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +LL | +LL | let (x,) = (build(x),); + | -------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + +warning: function cannot return without recursing + --> $DIR/recursive-in-exhaustiveness.rs:27:1 + | +LL | fn build2(x: T) -> impl Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +... +LL | let (x,) = (build2(x),); + | --------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error[E0720]: cannot resolve opaque type + --> $DIR/recursive-in-exhaustiveness.rs:27:23 + | +LL | fn build2(x: T) -> impl Sized { + | ^^^^^^^^^^ recursive opaque type +... +LL | (build2(x),) + | ------------ returning here with type `(impl Sized,)` + +warning: function cannot return without recursing + --> $DIR/recursive-in-exhaustiveness.rs:40:1 + | +LL | fn build3(x: T) -> impl Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +LL | +LL | let (x,) = (build3((x,)),); + | ------------ recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error[E0792]: expected generic type parameter, found `(T,)` + --> $DIR/recursive-in-exhaustiveness.rs:49:5 + | +LL | fn build3(x: T) -> impl Sized { + | - this generic parameter must be used with a generic type parameter +... +LL | build3(x) + | ^^^^^^^^^ + +error: aborting due to 2 previous errors; 3 warnings emitted + +Some errors have detailed explanations: E0720, E0792. +For more information about an error, try `rustc --explain E0720`. diff --git a/tests/ui/impl-trait/recursive-in-exhaustiveness.next.stderr b/tests/ui/impl-trait/recursive-in-exhaustiveness.next.stderr new file mode 100644 index 000000000000..4c3d5aa8fb8f --- /dev/null +++ b/tests/ui/impl-trait/recursive-in-exhaustiveness.next.stderr @@ -0,0 +1,80 @@ +error[E0284]: type annotations needed: cannot satisfy `impl Sized == _` + --> $DIR/recursive-in-exhaustiveness.rs:19:17 + | +LL | let (x,) = (build(x),); + | ^^^^^^^^ cannot satisfy `impl Sized == _` + +error[E0271]: type mismatch resolving `build2<(_,)>::{opaque#0} normalizes-to _` + --> $DIR/recursive-in-exhaustiveness.rs:31:6 + | +LL | (build2(x),) + | ^^^^^^^^^ types differ + +error[E0271]: type mismatch resolving `build2<(_,)>::{opaque#0} normalizes-to _` + --> $DIR/recursive-in-exhaustiveness.rs:31:5 + | +LL | (build2(x),) + | ^^^^^^^^^^^^ types differ + +error[E0277]: the size for values of type `(impl Sized,)` cannot be known at compilation time + --> $DIR/recursive-in-exhaustiveness.rs:31:5 + | +LL | (build2(x),) + | ^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(impl Sized,)` + = note: tuples must have a statically known size to be initialized + +error[E0271]: type mismatch resolving `build3<(T,)>::{opaque#0} normalizes-to _` + --> $DIR/recursive-in-exhaustiveness.rs:42:17 + | +LL | let (x,) = (build3((x,)),); + | ^^^^^^^^^^^^ types differ + +error[E0277]: the size for values of type `(impl Sized,)` cannot be known at compilation time + --> $DIR/recursive-in-exhaustiveness.rs:42:16 + | +LL | let (x,) = (build3((x,)),); + | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(impl Sized,)` + = note: tuples must have a statically known size to be initialized + +error[E0308]: mismatched types + --> $DIR/recursive-in-exhaustiveness.rs:42:16 + | +LL | fn build3(x: T) -> impl Sized { + | ---------- the found opaque type +LL | +LL | let (x,) = (build3((x,)),); + | ^^^^^^^^^^^^^^^ types differ + | + = note: expected type `_` + found tuple `(impl Sized,)` + +error[E0271]: type mismatch resolving `build3<(T,)>::{opaque#0} normalizes-to _` + --> $DIR/recursive-in-exhaustiveness.rs:42:17 + | +LL | let (x,) = (build3((x,)),); + | ^^^^^^^^^^^^ types differ + | + = note: the return type of a function must have a statically known size + +error[E0271]: type mismatch resolving `build3<(T,)>::{opaque#0} normalizes-to _` + --> $DIR/recursive-in-exhaustiveness.rs:42:16 + | +LL | let (x,) = (build3((x,)),); + | ^^^^^^^^^^^^^^^ types differ + +error[E0271]: type mismatch resolving `build3<(T,)>::{opaque#0} normalizes-to _` + --> $DIR/recursive-in-exhaustiveness.rs:42:17 + | +LL | let (x,) = (build3((x,)),); + | ^^^^^^^^^^^^ types differ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 10 previous errors + +Some errors have detailed explanations: E0271, E0277, E0284, E0308. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/impl-trait/recursive-in-exhaustiveness.rs b/tests/ui/impl-trait/recursive-in-exhaustiveness.rs new file mode 100644 index 000000000000..58944533686c --- /dev/null +++ b/tests/ui/impl-trait/recursive-in-exhaustiveness.rs @@ -0,0 +1,53 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +// Test several spicy non-trivial recursive opaque definitions inferred from HIR typeck +// don't cause stack overflows in exhaustiveness code, which currently reveals opaques +// manually in a way that is not overflow aware. +// +// These should eventually be outright rejected, but today (some) non-trivial recursive +// opaque definitions are accepted, and changing that requires an FCP, so for now just +// make sure we don't stack overflow :^) + +// Opaque = Opaque> +// +// We unfortunately accept this today, and due to how opaque type relating is implemented +// in the NLL type relation, this defines `Opaque = T`. +fn build(x: T) -> impl Sized { + //[current]~^ WARN function cannot return without recursing + let (x,) = (build(x),); + //[next]~^ ERROR type annotations needed + build(x) +} + +// Opaque = (Opaque,) +// +// Not allowed today. Detected as recursive. +fn build2(x: T) -> impl Sized { + //[current]~^ ERROR cannot resolve opaque type + //[current]~| WARN function cannot return without recursing + let (x,) = (build2(x),); + (build2(x),) + //[next]~^ ERROR type mismatch resolving + //[next]~| ERROR type mismatch resolving + //[next]~| ERROR the size for values of type +} + +// Opaque = Opaque<(T,)> +// +// Not allowed today. Detected as not defining. +fn build3(x: T) -> impl Sized { + //[current]~^ WARN function cannot return without recursing + let (x,) = (build3((x,)),); + //[next]~^ ERROR type mismatch resolving + //[next]~| ERROR type mismatch resolving + //[next]~| ERROR type mismatch resolving + //[next]~| ERROR type mismatch resolving + //[next]~| ERROR the size for values of type + //[next]~| ERROR mismatched types + build3(x) + //[current]~^ ERROR expected generic type parameter, found `(T,)` +} + +fn main() {} From 01e44b140d5129ab05e833b2f0b7c9f00b279c43 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Tue, 8 Apr 2025 02:44:06 +0200 Subject: [PATCH 203/606] add missing word in doc comment --- src/bootstrap/src/core/builder/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index a9058f888d38..f329c4358c08 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -104,7 +104,7 @@ pub trait Step: 'static + Clone + Debug + PartialEq + Eq + Hash { /// 1. Directly from [`Builder::execute_cli`]. /// 2. Indirectly by being called from other `Step`s using [`Builder::ensure`]. /// - /// When called with [`Builder::execute_cli`] (as done by `Build::build`), this function executed twice: + /// When called with [`Builder::execute_cli`] (as done by `Build::build`), this function is executed twice: /// - First in "dry-run" mode to validate certain things (like cyclic Step invocations, /// directory creation, etc) super quickly. /// - Then it's called again to run the actual, very expensive process. From 8501dcbd4b7ce0b5563c915a9e49f316a6572d43 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Tue, 8 Apr 2025 02:59:48 +0200 Subject: [PATCH 204/606] remove unusual indentation This also fixes markdown rendering --- src/bootstrap/src/core/builder/mod.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index f329c4358c08..f002903996b2 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -101,13 +101,13 @@ pub trait Step: 'static + Clone + Debug + PartialEq + Eq + Hash { /// Primary function to implement `Step` logic. /// /// This function can be triggered in two ways: - /// 1. Directly from [`Builder::execute_cli`]. - /// 2. Indirectly by being called from other `Step`s using [`Builder::ensure`]. + /// 1. Directly from [`Builder::execute_cli`]. + /// 2. Indirectly by being called from other `Step`s using [`Builder::ensure`]. /// /// When called with [`Builder::execute_cli`] (as done by `Build::build`), this function is executed twice: - /// - First in "dry-run" mode to validate certain things (like cyclic Step invocations, - /// directory creation, etc) super quickly. - /// - Then it's called again to run the actual, very expensive process. + /// - First in "dry-run" mode to validate certain things (like cyclic Step invocations, + /// directory creation, etc) super quickly. + /// - Then it's called again to run the actual, very expensive process. /// /// When triggered indirectly from other `Step`s, it may still run twice (as dry-run and real mode) /// depending on the `Step::run` implementation of the caller. From 502f7f9c241b35d65f4538d28c43e6feca474df2 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Mon, 7 Apr 2025 18:12:06 -0700 Subject: [PATCH 205/606] Address PR feedback --- compiler/rustc_codegen_ssa/src/mir/operand.rs | 4 +++- tests/codegen/enum/enum-two-variants-match.rs | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index fca0695f296f..eade9e52de95 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -581,7 +581,9 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { ); // In principle we could insert assumes on the possible range of `discr`, but - // currently in LLVM this seems to be a pessimization. + // currently in LLVM this isn't worth it because the original `tag` will + // have either a `range` parameter attribute or `!range` metadata, + // or come from a `transmute` that already `assume`d it. discr } diff --git a/tests/codegen/enum/enum-two-variants-match.rs b/tests/codegen/enum/enum-two-variants-match.rs index 5b6c0e2f8ad1..12d9edc4d623 100644 --- a/tests/codegen/enum/enum-two-variants-match.rs +++ b/tests/codegen/enum/enum-two-variants-match.rs @@ -3,6 +3,10 @@ #![crate_type = "lib"] +// This directly tests what we emit for these matches, rather than what happens +// after optimization, so it doesn't need to worry about extra flags on the +// instructions and is less susceptible to being broken on LLVM updates. + // CHECK-LABEL: @option_match #[no_mangle] pub fn option_match(x: Option) -> u16 { @@ -103,10 +107,22 @@ pub fn option_ordering_match(x: Option) -> char { // CHECK-LABEL: @option_nonzero_match( #[no_mangle] pub fn option_nonzero_match(x: Option>) -> u16 { + // CHECK: %[[OUT:.+]] = alloca [2 x i8] + // CHECK: %[[IS_NONE:.+]] = icmp eq i16 %x, 0 // CHECK: %[[OPT_DISCR:.+]] = select i1 %[[IS_NONE]], i64 0, i64 1 // CHECK: %[[OPT_DISCR_T:.+]] = trunc nuw i64 %[[OPT_DISCR]] to i1 // CHECK: br i1 %[[OPT_DISCR_T]], label %[[BB_SOME:.+]], label %[[BB_NONE:.+]] + + // CHECK: [[BB_SOME]]: + // CHECK: store i16 987, ptr %[[OUT]] + + // CHECK: [[BB_NONE]]: + // CHECK: store i16 123, ptr %[[OUT]] + + // CHECK: %[[RET:.+]] = load i16, ptr %[[OUT]] + // CHECK: ret i16 %[[RET]] + match x { None => 123, Some(_) => 987, From eb4bc2ccfb4f8dc345d14edd07602ddea1b1798f Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Tue, 8 Apr 2025 03:48:14 +0200 Subject: [PATCH 206/606] add missing word in doc comment (part 2) --- src/bootstrap/src/core/config/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 1712be7f947f..9c6750198c73 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -189,7 +189,7 @@ pub enum GccCiMode { /// /// Note that this structure is not decoded directly into, but rather it is /// filled out from the decoded forms of the structs below. For documentation -/// each field, see the corresponding fields in +/// on each field, see the corresponding fields in /// `bootstrap.example.toml`. #[derive(Default, Clone)] pub struct Config { From eb5d8923fce0a025921368d175905c9cab481954 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 3 Apr 2025 14:23:49 +1100 Subject: [PATCH 207/606] Allow for missing invisible close delim when reparsing an expression. This can happen when invalid syntax is passed to a declarative macro. We shouldn't be too strict about the token stream position once the parser has rejected the invalid syntax. Fixes #139248. --- compiler/rustc_parse/src/parser/mod.rs | 7 +++- .../ui/macros/no-close-delim-issue-139248.rs | 14 ++++++++ .../macros/no-close-delim-issue-139248.stderr | 33 +++++++++++++++++++ 3 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 tests/ui/macros/no-close-delim-issue-139248.rs create mode 100644 tests/ui/macros/no-close-delim-issue-139248.stderr diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 3b0861a9942a..b277cb804fa7 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -793,7 +793,12 @@ impl<'a> Parser<'a> { self.bump(); Some(res) } else { - panic!("no close delim when reparsing {mv_kind:?}"); + // This can occur when invalid syntax is passed to a decl macro. E.g. see #139248, + // where the reparse attempt of an invalid expr consumed the trailing invisible + // delimiter. + self.dcx() + .span_delayed_bug(self.token.span, "no close delim with reparsing {mv_kind:?}"); + None } } else { None diff --git a/tests/ui/macros/no-close-delim-issue-139248.rs b/tests/ui/macros/no-close-delim-issue-139248.rs new file mode 100644 index 000000000000..86583b2724ed --- /dev/null +++ b/tests/ui/macros/no-close-delim-issue-139248.rs @@ -0,0 +1,14 @@ +// This code caused a "no close delim when reparsing Expr" ICE in #139248. + +macro_rules! m { + (static a : () = $e:expr) => { + static a : () = $e; + //~^ ERROR macro expansion ends with an incomplete expression: expected expression + } +} + +m! { static a : () = (if b) } +//~^ ERROR expected `{`, found `)` +//~| ERROR expected `{`, found `)` + +fn main() {} diff --git a/tests/ui/macros/no-close-delim-issue-139248.stderr b/tests/ui/macros/no-close-delim-issue-139248.stderr new file mode 100644 index 000000000000..6ed41ae9b46a --- /dev/null +++ b/tests/ui/macros/no-close-delim-issue-139248.stderr @@ -0,0 +1,33 @@ +error: expected `{`, found `)` + --> $DIR/no-close-delim-issue-139248.rs:10:27 + | +LL | m! { static a : () = (if b) } + | ^ expected `{` + | +note: the `if` expression is missing a block after this condition + --> $DIR/no-close-delim-issue-139248.rs:10:26 + | +LL | m! { static a : () = (if b) } + | ^ + +error: expected `{`, found `)` + --> $DIR/no-close-delim-issue-139248.rs:10:27 + | +LL | m! { static a : () = (if b) } + | ^ expected `{` + | +note: the `if` expression is missing a block after this condition + --> $DIR/no-close-delim-issue-139248.rs:10:26 + | +LL | m! { static a : () = (if b) } + | ^ + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: macro expansion ends with an incomplete expression: expected expression + --> $DIR/no-close-delim-issue-139248.rs:5:28 + | +LL | static a : () = $e; + | ^ expected expression + +error: aborting due to 3 previous errors + From e177921ae9bca5d697e682551c27c5baefcfbb60 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 7 Apr 2025 13:54:24 +1000 Subject: [PATCH 208/606] Allow for reparsing failure when reparsing a pasted metavar. Fixes #139445. The additional errors aren't great but the first one is still good and it's the most important, and imperfect errors are better than ICEing. --- compiler/rustc_parse/src/parser/mod.rs | 13 +++++++--- .../macros/failed-to-reparse-issue-139445.rs | 6 +++++ .../failed-to-reparse-issue-139445.stderr | 24 +++++++++++++++++++ 3 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 tests/ui/macros/failed-to-reparse-issue-139445.rs create mode 100644 tests/ui/macros/failed-to-reparse-issue-139445.stderr diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index b277cb804fa7..fafd1b1ae007 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -782,9 +782,16 @@ impl<'a> Parser<'a> { // Recovery is disabled when parsing macro arguments, so it must // also be disabled when reparsing pasted macro arguments, // otherwise we get inconsistent results (e.g. #137874). - let res = self.with_recovery(Recovery::Forbidden, |this| { - f(this).expect("failed to reparse {mv_kind:?}") - }); + let res = self.with_recovery(Recovery::Forbidden, |this| f(this)); + + let res = match res { + Ok(res) => res, + Err(err) => { + // This can occur in unusual error cases, e.g. #139445. + err.delay_as_bug(); + return None; + } + }; if let token::CloseDelim(delim) = self.token.kind && let Delimiter::Invisible(InvisibleOrigin::MetaVar(mv_kind)) = delim diff --git a/tests/ui/macros/failed-to-reparse-issue-139445.rs b/tests/ui/macros/failed-to-reparse-issue-139445.rs new file mode 100644 index 000000000000..babe26b9d293 --- /dev/null +++ b/tests/ui/macros/failed-to-reparse-issue-139445.rs @@ -0,0 +1,6 @@ +fn main() { + assert_eq!(3, 'a,) + //~^ ERROR expected `while`, `for`, `loop` or `{` after a label + //~| ERROR expected `while`, `for`, `loop` or `{` after a label + //~| ERROR expected expression, found `` +} diff --git a/tests/ui/macros/failed-to-reparse-issue-139445.stderr b/tests/ui/macros/failed-to-reparse-issue-139445.stderr new file mode 100644 index 000000000000..6f7d88fb3446 --- /dev/null +++ b/tests/ui/macros/failed-to-reparse-issue-139445.stderr @@ -0,0 +1,24 @@ +error: expected `while`, `for`, `loop` or `{` after a label + --> $DIR/failed-to-reparse-issue-139445.rs:2:21 + | +LL | assert_eq!(3, 'a,) + | ^ expected `while`, `for`, `loop` or `{` after a label + +error: expected `while`, `for`, `loop` or `{` after a label + --> $DIR/failed-to-reparse-issue-139445.rs:2:5 + | +LL | assert_eq!(3, 'a,) + | ^^^^^^^^^^^^^^^^^^ expected `while`, `for`, `loop` or `{` after a label + | + = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected expression, found `` + --> $DIR/failed-to-reparse-issue-139445.rs:2:5 + | +LL | assert_eq!(3, 'a,) + | ^^^^^^^^^^^^^^^^^^ expected expression + | + = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 3 previous errors + From c7272a6cbc999a187d564624594889532e47ffa0 Mon Sep 17 00:00:00 2001 From: xizheyin Date: Tue, 8 Apr 2025 10:51:41 +0800 Subject: [PATCH 209/606] clean code: remove Deref impl for Region and use `.kind()` Signed-off-by: xizheyin --- .../src/diagnostics/bound_region_errors.rs | 2 +- .../rustc_borrowck/src/diagnostics/mod.rs | 4 +- .../src/diagnostics/region_errors.rs | 6 +-- .../src/diagnostics/region_name.rs | 10 ++--- .../src/region_infer/opaque_types.rs | 2 +- .../src/type_check/constraint_conversion.rs | 4 +- .../src/type_check/opaque_types.rs | 2 +- .../rustc_borrowck/src/universal_regions.rs | 4 +- .../src/check/compare_impl_item.rs | 2 +- .../rustc_hir_analysis/src/check/wfcheck.rs | 4 +- .../src/coherence/builtin.rs | 2 +- compiler/rustc_hir_analysis/src/collect.rs | 2 +- .../src/collect/predicates_of.rs | 2 +- .../src/constrained_generic_params.rs | 2 +- .../rustc_hir_analysis/src/outlives/utils.rs | 2 +- .../src/variance/constraints.rs | 2 +- .../src/infer/canonical/canonicalizer.rs | 8 ++-- .../src/infer/canonical/query_response.rs | 2 +- compiler/rustc_infer/src/infer/freshen.rs | 2 +- .../src/infer/lexical_region_resolve/mod.rs | 28 +++++++------- .../rustc_infer/src/infer/outlives/env.rs | 2 +- .../src/infer/outlives/for_liveness.rs | 2 +- .../infer/region_constraints/leak_check.rs | 2 +- .../src/infer/region_constraints/mod.rs | 4 +- .../src/infer/relate/generalize.rs | 2 +- compiler/rustc_infer/src/infer/resolve.rs | 4 +- compiler/rustc_lint/src/builtin.rs | 4 +- .../rustc_lint/src/impl_trait_overcaptures.rs | 4 +- compiler/rustc_middle/src/ty/erase_regions.rs | 2 +- compiler/rustc_middle/src/ty/flags.rs | 2 +- compiler/rustc_middle/src/ty/fold.rs | 4 +- compiler/rustc_middle/src/ty/opaque_types.rs | 2 +- compiler/rustc_middle/src/ty/print/pretty.rs | 8 ++-- compiler/rustc_middle/src/ty/region.rs | 37 +++++++------------ .../rustc_middle/src/ty/typeck_results.rs | 2 +- compiler/rustc_middle/src/ty/visit.rs | 6 +-- compiler/rustc_symbol_mangling/src/v0.rs | 2 +- .../infer/nice_region_error/util.rs | 2 +- .../src/error_reporting/infer/region.rs | 10 ++--- .../src/errors/note_and_explain.rs | 2 +- .../rustc_trait_selection/src/opaque_types.rs | 2 +- .../src/traits/auto_trait.rs | 2 +- .../src/traits/coherence.rs | 2 +- .../src/traits/dyn_compatibility.rs | 2 +- .../src/traits/query/normalize.rs | 2 +- .../rustc_trait_selection/src/traits/util.rs | 6 +-- compiler/rustc_ty_utils/src/implied_bounds.rs | 2 +- src/librustdoc/clean/auto_trait.rs | 4 +- src/librustdoc/clean/mod.rs | 8 ++-- 49 files changed, 107 insertions(+), 118 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs index aa968a1e40f3..1d7ec02d8adf 100644 --- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs @@ -487,7 +487,7 @@ fn try_extract_error_from_region_constraints<'a, 'tcx>( let (sub_region, cause) = info?; debug!(?sub_region, "cause = {:#?}", cause); - let error = match (error_region, *sub_region) { + let error = match (error_region, sub_region.kind()) { (Some(error_region), ty::ReVar(vid)) => RegionResolutionError::SubSupConflict( vid, region_var_origin(vid), diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 899e145c2c04..5dcfe69857a4 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -587,7 +587,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { // this by hooking into the pretty printer and telling it to label the // lifetimes without names with the value `'0`. if let ty::Ref(region, ..) = ty.kind() { - match **region { + match region.kind() { ty::ReBound(_, ty::BoundRegion { kind: br, .. }) | ty::RePlaceholder(ty::PlaceholderRegion { bound: ty::BoundRegion { kind: br, .. }, @@ -607,7 +607,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { let mut printer = ty::print::FmtPrinter::new(self.infcx.tcx, Namespace::TypeNS); let region = if let ty::Ref(region, ..) = ty.kind() { - match **region { + match region.kind() { ty::ReBound(_, ty::BoundRegion { kind: br, .. }) | ty::RePlaceholder(ty::PlaceholderRegion { bound: ty::BoundRegion { kind: br, .. }, diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index d1d783c22e35..5b5cacdf4c81 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -190,7 +190,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { where T: TypeFoldable>, { - fold_regions(tcx, ty, |region, _| match *region { + fold_regions(tcx, ty, |region, _| match region.kind() { ty::ReVar(vid) => self.to_error_region(vid).unwrap_or(region), _ => region, }) @@ -198,7 +198,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { /// Returns `true` if a closure is inferred to be an `FnMut` closure. fn is_closure_fn_mut(&self, fr: RegionVid) -> bool { - if let Some(ty::ReLateParam(late_param)) = self.to_error_region(fr).as_deref() + if let Some(ty::ReLateParam(late_param)) = self.to_error_region(fr).map(|r| r.kind()) && let ty::LateParamRegionKind::ClosureEnv = late_param.kind && let DefiningTy::Closure(_, args) = self.regioncx.universal_regions().defining_ty { @@ -832,7 +832,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { if let (Some(f), Some(outlived_f)) = (self.to_error_region(fr), self.to_error_region(outlived_fr)) { - if *outlived_f != ty::ReStatic { + if outlived_f.kind() != ty::ReStatic { return; } let suitable_region = self.infcx.tcx.is_suitable_region(self.mir_def_id(), f); diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 45f5eaa514b2..b08c10983bbc 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -288,7 +288,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { let tcx = self.infcx.tcx; debug!("give_region_a_name: error_region = {:?}", error_region); - match *error_region { + match error_region.kind() { ty::ReEarlyParam(ebr) => ebr.has_name().then(|| { let def_id = tcx.generics_of(self.mir_def_id()).region_param(ebr, tcx).def_id; let span = tcx.hir_span_if_local(def_id).unwrap_or(DUMMY_SP); @@ -896,7 +896,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { &self, fr: RegionVid, ) -> Option { - let ty::ReEarlyParam(region) = *self.to_error_region(fr)? else { + let ty::ReEarlyParam(region) = self.to_error_region(fr)?.kind() else { return None; }; if region.has_name() { @@ -912,7 +912,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { let found = tcx .any_free_region_meets(&tcx.type_of(region_parent).instantiate_identity(), |r| { - *r == ty::ReEarlyParam(region) + r.kind() == ty::ReEarlyParam(region) }); Some(RegionName { @@ -931,7 +931,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { &self, fr: RegionVid, ) -> Option { - let ty::ReEarlyParam(region) = *self.to_error_region(fr)? else { + let ty::ReEarlyParam(region) = self.to_error_region(fr)?.kind() else { return None; }; if region.has_name() { @@ -1007,7 +1007,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { if data.projection_term.self_ty() == ty => {} _ => return false, } - tcx.any_free_region_meets(pred, |r| *r == ty::ReEarlyParam(region)) + tcx.any_free_region_meets(pred, |r| r.kind() == ty::ReEarlyParam(region)) }) } else { false diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index a098450352ff..840533226dfd 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -186,7 +186,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { where T: TypeFoldable>, { - fold_regions(tcx, ty, |region, _| match *region { + fold_regions(tcx, ty, |region, _| match region.kind() { ty::ReVar(vid) => { let scc = self.constraint_sccs.scc(vid); diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index 6fbe1db6330e..c50949bfcdce 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -205,7 +205,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { /// are dealt with during trait solving. fn replace_placeholders_with_nll>>(&mut self, value: T) -> T { if value.has_placeholders() { - fold_regions(self.tcx, value, |r, _| match *r { + fold_regions(self.tcx, value, |r, _| match r.kind() { ty::RePlaceholder(placeholder) => { self.constraints.placeholder_region(self.infcx, placeholder) } @@ -227,7 +227,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { } fn to_region_vid(&mut self, r: ty::Region<'tcx>) -> ty::RegionVid { - if let ty::RePlaceholder(placeholder) = *r { + if let ty::RePlaceholder(placeholder) = r.kind() { self.constraints.placeholder_region(self.infcx, placeholder).as_var() } else { self.universal_regions.to_region_vid(r) diff --git a/compiler/rustc_borrowck/src/type_check/opaque_types.rs b/compiler/rustc_borrowck/src/type_check/opaque_types.rs index 8bab979a7246..d41cbf757d7f 100644 --- a/compiler/rustc_borrowck/src/type_check/opaque_types.rs +++ b/compiler/rustc_borrowck/src/type_check/opaque_types.rs @@ -271,7 +271,7 @@ where } fn visit_region(&mut self, r: ty::Region<'tcx>) { - match *r { + match r.kind() { // ignore bound regions, keep visiting ty::ReBound(_, _) => {} _ => (self.op)(r), diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 8f6b405fcef2..ab7cc10ae30a 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -909,9 +909,9 @@ impl<'tcx> UniversalRegionIndices<'tcx> { /// if it is a placeholder. Handling placeholders requires access to the /// `MirTypeckRegionConstraints`. fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid { - if let ty::ReVar(..) = *r { + if let ty::ReVar(..) = r.kind() { r.as_var() - } else if let ty::ReError(guar) = *r { + } else if let ty::ReError(guar) = r.kind() { self.tainted_by_errors.set(Some(guar)); // We use the `'static` `RegionVid` because `ReError` doesn't actually exist in the // `UniversalRegionIndices`. This is fine because 1) it is a fallback only used if diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 5e68bb310015..32a8f101849c 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -442,7 +442,7 @@ impl<'tcx> TypeFolder> for RemapLateParam<'tcx> { } fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - if let ty::ReLateParam(fr) = *r { + if let ty::ReLateParam(fr) = r.kind() { ty::Region::new_late_param( self.tcx, fr.scope, diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 83d095ab72e8..6292d03bf6ac 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -631,7 +631,7 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable>>( // Ignore `'static` lifetimes for the purpose of this lint: it's // because we know it outlives everything and so doesn't give meaningful // clues. Also ignore `ReError`, to avoid knock-down errors. - if let ty::ReStatic | ty::ReError(_) = **region_a { + if let ty::ReStatic | ty::ReError(_) = region_a.kind() { continue; } // For each region argument (e.g., `'a` in our example), check for a @@ -672,7 +672,7 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable>>( // Again, skip `'static` because it outlives everything. Also, we trivially // know that a region outlives itself. Also ignore `ReError`, to avoid // knock-down errors. - if matches!(**region_b, ty::ReStatic | ty::ReError(_)) || region_a == region_b { + if matches!(region_b.kind(), ty::ReStatic | ty::ReError(_)) || region_a == region_b { continue; } if region_known_to_outlive(tcx, item_def_id, param_env, wf_tys, *region_a, *region_b) { diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 1f3f0b754bb1..8ad9d80c6b5a 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -656,7 +656,7 @@ fn infringing_fields_error<'tcx>( .entry((ty.clone(), predicate.clone())) .or_default() .push(origin.span()); - if let ty::RegionKind::ReEarlyParam(ebr) = *b + if let ty::RegionKind::ReEarlyParam(ebr) = b.kind() && ebr.has_name() { bounds.push((b.to_string(), a.to_string(), None)); diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index e9cd22435d95..f577f0c457e7 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1416,7 +1416,7 @@ fn recover_infer_ret_ty<'tcx>( GenericParamKind::Lifetime { .. } => true, _ => false, }); - let fn_sig = fold_regions(tcx, fn_sig, |r, _| match *r { + let fn_sig = fold_regions(tcx, fn_sig, |r, _| match r.kind() { ty::ReErased => { if has_region_params { ty::Region::new_error_with_message( diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 320225a7a663..e90a1cc24c16 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -359,7 +359,7 @@ fn compute_bidirectional_outlives_predicates<'tcx>( ) { for param in opaque_own_params { let orig_lifetime = tcx.map_opaque_lifetime_to_parent_lifetime(param.def_id.expect_local()); - if let ty::ReEarlyParam(..) = *orig_lifetime { + if let ty::ReEarlyParam(..) = orig_lifetime.kind() { let dup_lifetime = ty::Region::new_early_param( tcx, ty::EarlyParamRegion { index: param.index, name: param.name }, diff --git a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs index 53866aa27b16..951eda72ffed 100644 --- a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs +++ b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs @@ -80,7 +80,7 @@ impl<'tcx> TypeVisitor> for ParameterCollector { } fn visit_region(&mut self, r: ty::Region<'tcx>) { - if let ty::ReEarlyParam(data) = *r { + if let ty::ReEarlyParam(data) = r.kind() { self.parameters.push(Parameter::from(data)); } } diff --git a/compiler/rustc_hir_analysis/src/outlives/utils.rs b/compiler/rustc_hir_analysis/src/outlives/utils.rs index d0a2a2230ab7..044fb64ca821 100644 --- a/compiler/rustc_hir_analysis/src/outlives/utils.rs +++ b/compiler/rustc_hir_analysis/src/outlives/utils.rs @@ -146,7 +146,7 @@ pub(crate) fn insert_outlives_predicate<'tcx>( fn is_free_region(region: Region<'_>) -> bool { // First, screen for regions that might appear in a type header. - match *region { + match region.kind() { // These correspond to `T: 'a` relationships: // // struct Foo<'a, T> { diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs index 8475903c68fd..23223de918cf 100644 --- a/compiler/rustc_hir_analysis/src/variance/constraints.rs +++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs @@ -428,7 +428,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { region: ty::Region<'tcx>, variance: VarianceTermPtr<'a>, ) { - match *region { + match region.kind() { ty::ReEarlyParam(ref data) => { self.add_constraint(current, data.index, variance); } diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index 307110d9fbc2..a1a0926cd818 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -159,7 +159,7 @@ impl CanonicalizeMode for CanonicalizeQueryResponse { ) -> ty::Region<'tcx> { let infcx = canonicalizer.infcx.unwrap(); - if let ty::ReVar(vid) = *r { + if let ty::ReVar(vid) = r.kind() { r = infcx .inner .borrow_mut() @@ -171,7 +171,7 @@ impl CanonicalizeMode for CanonicalizeQueryResponse { ); }; - match *r { + match r.kind() { ty::ReLateParam(_) | ty::ReErased | ty::ReStatic | ty::ReEarlyParam(..) => r, ty::RePlaceholder(placeholder) => canonicalizer.canonical_var_for_region( @@ -227,7 +227,7 @@ impl CanonicalizeMode for CanonicalizeUserTypeAnnotation { canonicalizer: &mut Canonicalizer<'_, 'tcx>, r: ty::Region<'tcx>, ) -> ty::Region<'tcx> { - match *r { + match r.kind() { ty::ReEarlyParam(_) | ty::ReLateParam(_) | ty::ReErased @@ -321,7 +321,7 @@ impl<'cx, 'tcx> TypeFolder> for Canonicalizer<'cx, 'tcx> { } fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - match *r { + match r.kind() { ty::ReBound(index, ..) => { if index >= self.binder_index { bug!("escaping late-bound region during canonicalization"); diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index d53f631cc07a..5220071c5005 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -432,7 +432,7 @@ impl<'tcx> InferCtxt<'tcx> { } GenericArgKind::Lifetime(result_value) => { // e.g., here `result_value` might be `'?1` in the example above... - if let ty::ReBound(debruijn, br) = *result_value { + if let ty::ReBound(debruijn, br) = result_value.kind() { // ... in which case we would set `canonical_vars[0]` to `Some('static)`. // We only allow a `ty::INNERMOST` index in generic parameters. diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs index f2bb66ff7368..cae674165f0e 100644 --- a/compiler/rustc_infer/src/infer/freshen.rs +++ b/compiler/rustc_infer/src/infer/freshen.rs @@ -109,7 +109,7 @@ impl<'a, 'tcx> TypeFolder> for TypeFreshener<'a, 'tcx> { } fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - match *r { + match r.kind() { ty::ReBound(..) => { // leave bound regions alone r diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs index 91595de97f7d..e3522137d838 100644 --- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs +++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs @@ -218,7 +218,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { true } VarValue::Value(cur_region) => { - match *cur_region { + match cur_region.kind() { // If this empty region is from a universe that can name the // placeholder universe, then the LUB is the Placeholder region // (which is the cur_region). Otherwise, the LUB is the Static @@ -310,7 +310,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { match *b_data { VarValue::Empty(empty_ui) => { - let lub = match *a_region { + let lub = match a_region.kind() { RePlaceholder(placeholder) => { // If this empty region is from a universe that can // name the placeholder, then the placeholder is @@ -350,7 +350,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { // tighter bound than `'static`. // // (This might e.g. arise from being asked to prove `for<'a> { 'b: 'a }`.) - if let ty::RePlaceholder(p) = *lub + if let ty::RePlaceholder(p) = lub.kind() && b_universe.cannot_name(p.universe) { lub = self.tcx().lifetimes.re_static; @@ -377,7 +377,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { a_ui.min(b_ui) == b_ui } (VarValue::Value(a), VarValue::Empty(_)) => { - match *a { + match a.kind() { // this is always on an error path, // so it doesn't really matter if it's shorter or longer than an empty region ReError(_) => false, @@ -410,7 +410,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { } } (VarValue::Empty(a_ui), VarValue::Value(b)) => { - match *b { + match b.kind() { // this is always on an error path, // so it doesn't really matter if it's shorter or longer than an empty region ReError(_) => false, @@ -479,7 +479,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { /// term "concrete regions"). #[instrument(level = "trace", skip(self), ret)] fn lub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> Region<'tcx> { - match (*a, *b) { + match (a.kind(), b.kind()) { (ReBound(..), _) | (_, ReBound(..)) | (ReErased, _) | (_, ReErased) => { bug!("cannot relate region: LUB({:?}, {:?})", a, b); } @@ -725,7 +725,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { // SubSupConflict(ReLateParam, ReLateParam) when reporting error, and so // the user will more likely get a specific suggestion. fn region_order_key(x: &RegionAndOrigin<'_>) -> u8 { - match *x.region { + match x.region.kind() { ReEarlyParam(_) => 0, ReLateParam(_) => 1, _ => 2, @@ -737,7 +737,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { let node_universe = self.var_infos[node_idx].universe; for lower_bound in &lower_bounds { - let effective_lower_bound = if let ty::RePlaceholder(p) = *lower_bound.region { + let effective_lower_bound = if let ty::RePlaceholder(p) = lower_bound.region.kind() { if node_universe.cannot_name(p.universe) { self.tcx().lifetimes.re_static } else { @@ -785,7 +785,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { .expect("lower_vid_bounds should at least include `node_idx`"); for upper_bound in &upper_bounds { - if let ty::RePlaceholder(p) = *upper_bound.region { + if let ty::RePlaceholder(p) = upper_bound.region.kind() { if min_universe.cannot_name(p.universe) { let origin = self.var_infos[node_idx].origin; errors.push(RegionResolutionError::UpperBoundUniverseConflict( @@ -913,7 +913,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { generic_ty: Ty<'tcx>, min: ty::Region<'tcx>, ) -> bool { - if let ty::ReError(_) = *min { + if let ty::ReError(_) = min.kind() { return true; } @@ -931,18 +931,18 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { } VerifyBound::OutlivedBy(r) => { - let a = match *min { + let a = match min.kind() { ty::ReVar(rid) => var_values.values[rid], _ => VarValue::Value(min), }; - let b = match **r { + let b = match r.kind() { ty::ReVar(rid) => var_values.values[rid], _ => VarValue::Value(*r), }; self.sub_region_values(a, b) } - VerifyBound::IsEmpty => match *min { + VerifyBound::IsEmpty => match min.kind() { ty::ReVar(rid) => match var_values.values[rid] { VarValue::ErrorValue => false, VarValue::Empty(_) => true, @@ -989,7 +989,7 @@ impl<'tcx> LexicalRegionResolutions<'tcx> { tcx: TyCtxt<'tcx>, r: ty::Region<'tcx>, ) -> ty::Region<'tcx> { - let result = match *r { + let result = match r.kind() { ty::ReVar(rid) => match self.values[rid] { VarValue::Empty(_) => r, VarValue::Value(r) => r, diff --git a/compiler/rustc_infer/src/infer/outlives/env.rs b/compiler/rustc_infer/src/infer/outlives/env.rs index e924c974a02c..cb5a33c5c972 100644 --- a/compiler/rustc_infer/src/infer/outlives/env.rs +++ b/compiler/rustc_infer/src/infer/outlives/env.rs @@ -69,7 +69,7 @@ impl<'tcx> OutlivesEnvironment<'tcx> { region_bound_pairs .insert(ty::OutlivesPredicate(GenericKind::Alias(alias_b), r_a)); } - OutlivesBound::RegionSubRegion(r_a, r_b) => match (*r_a, *r_b) { + OutlivesBound::RegionSubRegion(r_a, r_b) => match (r_a.kind(), r_b.kind()) { ( ty::ReStatic | ty::ReEarlyParam(_) | ty::ReLateParam(_), ty::ReStatic | ty::ReEarlyParam(_) | ty::ReLateParam(_), diff --git a/compiler/rustc_infer/src/infer/outlives/for_liveness.rs b/compiler/rustc_infer/src/infer/outlives/for_liveness.rs index 379410641fe5..c44d9723f29d 100644 --- a/compiler/rustc_infer/src/infer/outlives/for_liveness.rs +++ b/compiler/rustc_infer/src/infer/outlives/for_liveness.rs @@ -29,7 +29,7 @@ where } fn visit_region(&mut self, r: ty::Region<'tcx>) { - match *r { + match r.kind() { // ignore bound regions, keep visiting ty::ReBound(_, _) => {} _ => (self.op)(r), diff --git a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs index 3cfc58dea05b..e332b6d0447a 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs @@ -155,7 +155,7 @@ impl<'a, 'tcx> LeakCheck<'a, 'tcx> { self.scc_universes[scc].take_min(universe, *region); // Detect those SCCs that directly contain a placeholder - if let ty::RePlaceholder(placeholder) = **region { + if let ty::RePlaceholder(placeholder) = region.kind() { if self.outer_universe.cannot_name(placeholder.universe) { // Update `scc_placeholders` to account for the fact that `P: S` must hold. match self.scc_placeholders[scc] { diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index 57555db37abd..8366aa6ec422 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -463,7 +463,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { // cannot add constraints once regions are resolved debug!("origin = {:#?}", origin); - match (*sub, *sup) { + match (sub.kind(), sup.kind()) { (ReBound(..), _) | (_, ReBound(..)) => { span_bug!(origin.span(), "cannot relate bound region: {:?} <= {:?}", sub, sup); } @@ -595,7 +595,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { } pub fn universe(&mut self, region: Region<'tcx>) -> ty::UniverseIndex { - match *region { + match region.kind() { ty::ReStatic | ty::ReErased | ty::ReLateParam(..) diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs index e16212955ffe..b0ccd35e8f0f 100644 --- a/compiler/rustc_infer/src/infer/relate/generalize.rs +++ b/compiler/rustc_infer/src/infer/relate/generalize.rs @@ -571,7 +571,7 @@ impl<'tcx> TypeRelation> for Generalizer<'_, 'tcx> { ) -> RelateResult<'tcx, ty::Region<'tcx>> { assert_eq!(r, r2); // we are misusing TypeRelation here; both LHS and RHS ought to be == - match *r { + match r.kind() { // Never make variables for regions bound within the type itself, // nor for erased regions. ty::ReBound(..) | ty::ReErased => { diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs index 4a99c2209755..245f1a4ac5ed 100644 --- a/compiler/rustc_infer/src/infer/resolve.rs +++ b/compiler/rustc_infer/src/infer/resolve.rs @@ -89,7 +89,7 @@ impl<'a, 'tcx> TypeFolder> for OpportunisticRegionResolver<'a, 'tcx } fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - match *r { + match r.kind() { ty::ReVar(vid) => self .infcx .inner @@ -153,7 +153,7 @@ impl<'a, 'tcx> FallibleTypeFolder> for FullTypeResolver<'a, 'tcx> { } fn try_fold_region(&mut self, r: ty::Region<'tcx>) -> Result, Self::Error> { - match *r { + match r.kind() { ty::ReVar(_) => Ok(self .infcx .lexical_region_resolutions diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 38c2bf544323..e65f4beab241 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1988,7 +1988,7 @@ impl ExplicitOutlivesRequirements { inferred_outlives .filter_map(|(clause, _)| match clause.kind().skip_binder() { - ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => match *a { + ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => match a.kind() { ty::ReEarlyParam(ebr) if item_generics.region_param(ebr, tcx).def_id == lifetime.to_def_id() => { @@ -2038,7 +2038,7 @@ impl ExplicitOutlivesRequirements { let is_inferred = match tcx.named_bound_var(lifetime.hir_id) { Some(ResolvedArg::EarlyBound(def_id)) => inferred_outlives .iter() - .any(|r| matches!(**r, ty::ReEarlyParam(ebr) if { item_generics.region_param(ebr, tcx).def_id == def_id.to_def_id() })), + .any(|r| matches!(r.kind(), ty::ReEarlyParam(ebr) if { item_generics.region_param(ebr, tcx).def_id == def_id.to_def_id() })), _ => false, }; diff --git a/compiler/rustc_lint/src/impl_trait_overcaptures.rs b/compiler/rustc_lint/src/impl_trait_overcaptures.rs index 26481b97076f..f1dc420aa3c9 100644 --- a/compiler/rustc_lint/src/impl_trait_overcaptures.rs +++ b/compiler/rustc_lint/src/impl_trait_overcaptures.rs @@ -461,7 +461,7 @@ fn extract_def_id_from_arg<'tcx>( arg: ty::GenericArg<'tcx>, ) -> DefId { match arg.unpack() { - ty::GenericArgKind::Lifetime(re) => match *re { + ty::GenericArgKind::Lifetime(re) => match re.kind() { ty::ReEarlyParam(ebr) => generics.region_param(ebr, tcx).def_id, ty::ReBound( _, @@ -530,7 +530,7 @@ impl<'tcx> TypeRelation> for FunctionalVariances<'tcx> { a: ty::Region<'tcx>, _: ty::Region<'tcx>, ) -> RelateResult<'tcx, ty::Region<'tcx>> { - let def_id = match *a { + let def_id = match a.kind() { ty::ReEarlyParam(ebr) => self.generics.region_param(ebr, self.tcx).def_id, ty::ReBound( _, diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs index 8bddb5c0fd77..45a0b1288db8 100644 --- a/compiler/rustc_middle/src/ty/erase_regions.rs +++ b/compiler/rustc_middle/src/ty/erase_regions.rs @@ -65,7 +65,7 @@ impl<'tcx> TypeFolder> for RegionEraserVisitor<'tcx> { // We must not erase bound regions. `for<'a> fn(&'a ())` and // `fn(&'free ())` are different types: they may implement different // traits and have a different `TypeId`. - match *r { + match r.kind() { ty::ReBound(..) => r, _ => self.tcx.lifetimes.re_erased, } diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index b0c442d28f0a..2424923fb787 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -288,7 +288,7 @@ impl FlagComputation { fn add_region(&mut self, r: ty::Region<'_>) { self.add_flags(r.type_flags()); - if let ty::ReBound(debruijn, _) = *r { + if let ty::ReBound(debruijn, _) = r.kind() { self.add_bound_var(debruijn); } } diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index dc2c9e3d9f11..8dc73e4ce85e 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -145,10 +145,10 @@ where } fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - match *r { + match r.kind() { ty::ReBound(debruijn, br) if debruijn == self.current_index => { let region = self.delegate.replace_region(br); - if let ty::ReBound(debruijn1, br) = *region { + if let ty::ReBound(debruijn1, br) = region.kind() { // If the callback returns a bound region, // that region should always use the INNERMOST // debruijn index. Then we adjust it to the diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs index c72efde09949..9445a18ad76b 100644 --- a/compiler/rustc_middle/src/ty/opaque_types.rs +++ b/compiler/rustc_middle/src/ty/opaque_types.rs @@ -95,7 +95,7 @@ impl<'tcx> TypeFolder> for ReverseMapper<'tcx> { #[instrument(skip(self), level = "debug")] fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - match *r { + match r.kind() { // Ignore bound regions and `'static` regions that appear in the // type, we only need to remap regions that reference lifetimes // from the function declaration. diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 3281cb4135a0..0765d066fe9f 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2520,7 +2520,7 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> { let identify_regions = self.tcx.sess.opts.unstable_opts.identify_regions; - match *region { + match region.kind() { ty::ReEarlyParam(ref data) => data.has_name(), ty::ReLateParam(ty::LateParamRegion { kind, .. }) => kind.is_named(), @@ -2590,7 +2590,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { // the user might want to diagnose an error, but there is basically no way // to fit that into a short string. Hence the recommendation to use // `explain_region()` or `note_and_explain_region()`. - match *region { + match region.kind() { ty::ReEarlyParam(data) => { p!(write("{}", data.name)); return Ok(()); @@ -2680,7 +2680,7 @@ impl<'a, 'tcx> ty::TypeFolder> for RegionFolder<'a, 'tcx> { fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { let name = &mut self.name; - let region = match *r { + let region = match r.kind() { ty::ReBound(db, br) if db >= self.current_index => { *self.region_map.entry(br).or_insert_with(|| name(Some(db), self.current_index, br)) } @@ -2704,7 +2704,7 @@ impl<'a, 'tcx> ty::TypeFolder> for RegionFolder<'a, 'tcx> { } _ => return r, }; - if let ty::ReBound(debruijn1, br) = *region { + if let ty::ReBound(debruijn1, br) = region.kind() { assert_eq!(debruijn1, ty::INNERMOST); ty::Region::new_bound(self.tcx, self.current_index, br) } else { diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs index c78306f2ca37..3e4f7a79d539 100644 --- a/compiler/rustc_middle/src/ty/region.rs +++ b/compiler/rustc_middle/src/ty/region.rs @@ -1,5 +1,3 @@ -use std::ops::Deref; - use rustc_data_structures::intern::Interned; use rustc_errors::MultiSpan; use rustc_hir::def_id::DefId; @@ -22,7 +20,7 @@ impl<'tcx> rustc_type_ir::inherent::IntoKind for Region<'tcx> { type Kind = RegionKind<'tcx>; fn kind(self) -> RegionKind<'tcx> { - *self + *self.0.0 } } @@ -32,7 +30,7 @@ impl<'tcx> rustc_type_ir::Flags for Region<'tcx> { } fn outer_exclusive_binder(&self) -> ty::DebruijnIndex { - match **self { + match self.kind() { ty::ReBound(debruijn, _) => debruijn.shifted_in(1), _ => ty::INNERMOST, } @@ -163,7 +161,7 @@ impl<'tcx> Region<'tcx> { pub fn get_name(self) -> Option { if self.has_name() { - match *self { + match self.kind() { ty::ReEarlyParam(ebr) => Some(ebr.name), ty::ReBound(_, br) => br.kind.get_name(), ty::ReLateParam(fr) => fr.kind.get_name(), @@ -185,7 +183,7 @@ impl<'tcx> Region<'tcx> { /// Is this region named by the user? pub fn has_name(self) -> bool { - match *self { + match self.kind() { ty::ReEarlyParam(ebr) => ebr.has_name(), ty::ReBound(_, br) => br.kind.is_named(), ty::ReLateParam(fr) => fr.kind.is_named(), @@ -199,32 +197,32 @@ impl<'tcx> Region<'tcx> { #[inline] pub fn is_error(self) -> bool { - matches!(*self, ty::ReError(_)) + matches!(self.kind(), ty::ReError(_)) } #[inline] pub fn is_static(self) -> bool { - matches!(*self, ty::ReStatic) + matches!(self.kind(), ty::ReStatic) } #[inline] pub fn is_erased(self) -> bool { - matches!(*self, ty::ReErased) + matches!(self.kind(), ty::ReErased) } #[inline] pub fn is_bound(self) -> bool { - matches!(*self, ty::ReBound(..)) + matches!(self.kind(), ty::ReBound(..)) } #[inline] pub fn is_placeholder(self) -> bool { - matches!(*self, ty::RePlaceholder(..)) + matches!(self.kind(), ty::RePlaceholder(..)) } #[inline] pub fn bound_at_or_above_binder(self, index: ty::DebruijnIndex) -> bool { - match *self { + match self.kind() { ty::ReBound(debruijn, _) => debruijn >= index, _ => false, } @@ -233,7 +231,7 @@ impl<'tcx> Region<'tcx> { pub fn type_flags(self) -> TypeFlags { let mut flags = TypeFlags::empty(); - match *self { + match self.kind() { ty::ReVar(..) => { flags = flags | TypeFlags::HAS_FREE_REGIONS; flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; @@ -275,14 +273,14 @@ impl<'tcx> Region<'tcx> { /// True for free regions other than `'static`. pub fn is_param(self) -> bool { - matches!(*self, ty::ReEarlyParam(_) | ty::ReLateParam(_)) + matches!(self.kind(), ty::ReEarlyParam(_) | ty::ReLateParam(_)) } /// True for free region in the current context. /// /// This is the case for `'static` and param regions. pub fn is_free(self) -> bool { - match *self { + match self.kind() { ty::ReStatic | ty::ReEarlyParam(..) | ty::ReLateParam(..) => true, ty::ReVar(..) | ty::RePlaceholder(..) @@ -319,15 +317,6 @@ impl<'tcx> Region<'tcx> { } } -impl<'tcx> Deref for Region<'tcx> { - type Target = RegionKind<'tcx>; - - #[inline] - fn deref(&self) -> &RegionKind<'tcx> { - self.0.0 - } -} - #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] #[derive(HashStable)] pub struct EarlyParamRegion { diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index 7c437abfe24c..90c6ef67fb88 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -758,7 +758,7 @@ impl<'tcx> IsIdentity for CanonicalUserType<'tcx> { _ => false, }, - GenericArgKind::Lifetime(r) => match *r { + GenericArgKind::Lifetime(r) => match r.kind() { ty::ReBound(debruijn, br) => { // We only allow a `ty::INNERMOST` index in generic parameters. assert_eq!(debruijn, ty::INNERMOST); diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index e3b7a258c395..b341b30af6ac 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -77,7 +77,7 @@ impl<'tcx> TyCtxt<'tcx> { } fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result { - match *r { + match r.kind() { ty::ReBound(debruijn, _) if debruijn < self.outer_index => { ControlFlow::Continue(()) } @@ -205,7 +205,7 @@ impl<'tcx> TypeVisitor> for LateBoundRegionsCollector { } fn visit_region(&mut self, r: ty::Region<'tcx>) { - if let ty::ReBound(debruijn, br) = *r { + if let ty::ReBound(debruijn, br) = r.kind() { if debruijn == self.current_index { self.regions.insert(br.kind); } @@ -250,7 +250,7 @@ impl<'tcx> TypeVisitor> for MaxUniverse { } fn visit_region(&mut self, r: ty::Region<'tcx>) { - if let ty::RePlaceholder(placeholder) = *r { + if let ty::RePlaceholder(placeholder) = r.kind() { self.max_universe = ty::UniverseIndex::from_u32( self.max_universe.as_u32().max(placeholder.universe.as_u32()), ); diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 99d44bcd7eb8..8edfd16016c3 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -368,7 +368,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { } fn print_region(&mut self, region: ty::Region<'_>) -> Result<(), PrintError> { - let i = match *region { + let i = match region.kind() { // Erased lifetimes use the index 0, for a // shorter mangling of `L_`. ty::ReErased => 0, diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs index 683b5b528c6e..fd2d2fa72105 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs @@ -42,7 +42,7 @@ pub fn find_param_with_region<'tcx>( anon_region: Region<'tcx>, replace_region: Region<'tcx>, ) -> Option> { - let (id, kind) = match *anon_region { + let (id, kind) = match anon_region.kind() { ty::ReLateParam(late_param) => (late_param.scope, late_param.kind), ty::ReEarlyParam(ebr) => { let region_def = tcx.generics_of(generic_param_scope).region_param(ebr, tcx).def_id; diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs index c7f0a88f951a..593baa9ad454 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -299,7 +299,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { self.tcx.param_env(generic_param_scope), terr, ); - match (*sub, *sup) { + match (sub.kind(), sup.kind()) { (ty::RePlaceholder(_), ty::RePlaceholder(_)) => {} (ty::RePlaceholder(_), _) => { note_and_explain_region( @@ -391,7 +391,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }) } infer::RelateParamBound(span, ty, opt_span) => { - let prefix = match *sub { + let prefix = match sub.kind() { ty::ReStatic => note_and_explain::PrefixKind::TypeSatisfy, _ => note_and_explain::PrefixKind::TypeOutlive, }; @@ -1048,7 +1048,7 @@ pub(super) fn note_and_explain_region<'tcx>( suffix: &str, alt_span: Option, ) { - let (description, span) = match *region { + let (description, span) = match region.kind() { ty::ReEarlyParam(_) | ty::ReLateParam(_) | ty::RePlaceholder(_) | ty::ReStatic => { msg_span_from_named_region(tcx, generic_param_scope, region, alt_span) } @@ -1085,7 +1085,7 @@ fn msg_span_from_named_region<'tcx>( region: ty::Region<'tcx>, alt_span: Option, ) -> (String, Option) { - match *region { + match region.kind() { ty::ReEarlyParam(br) => { let param_def_id = tcx.generics_of(generic_param_scope).region_param(br, tcx).def_id; let span = tcx.def_span(param_def_id); @@ -1185,7 +1185,7 @@ pub fn unexpected_hidden_region_diagnostic<'a, 'tcx>( }); // Explain the region we are capturing. - match *hidden_region { + match hidden_region.kind() { ty::ReEarlyParam(_) | ty::ReLateParam(_) | ty::ReStatic => { // Assuming regionck succeeded (*), we ought to always be // capturing *some* region from the fn header, and hence it diff --git a/compiler/rustc_trait_selection/src/errors/note_and_explain.rs b/compiler/rustc_trait_selection/src/errors/note_and_explain.rs index 46622246a178..e4ab78b62477 100644 --- a/compiler/rustc_trait_selection/src/errors/note_and_explain.rs +++ b/compiler/rustc_trait_selection/src/errors/note_and_explain.rs @@ -20,7 +20,7 @@ impl<'a> DescriptionCtx<'a> { region: ty::Region<'tcx>, alt_span: Option, ) -> Option { - let (span, kind, arg) = match *region { + let (span, kind, arg) = match region.kind() { ty::ReEarlyParam(br) => { let scope = tcx .parent(tcx.generics_of(generic_param_scope).region_param(br, tcx).def_id) diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index c7b8f0631962..309bf4dda3d8 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -46,7 +46,7 @@ pub fn check_opaque_type_parameter_valid<'tcx>( GenericArgKind::Lifetime(lt) => match defining_scope_kind { DefiningScopeKind::HirTypeck => continue, DefiningScopeKind::MirBorrowck => { - matches!(*lt, ty::ReEarlyParam(_) | ty::ReLateParam(_)) + matches!(lt.kind(), ty::ReEarlyParam(_) | ty::ReLateParam(_)) || (lt.is_static() && opaque_env.param_equal_static(i)) } }, diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 1fca2f4da7ee..02521c9453d9 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -382,7 +382,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { for (new_region, old_region) in iter::zip(new_args.regions(), old_args.regions()) { - match (*new_region, *old_region) { + match (new_region.kind(), old_region.kind()) { // If both predicates have an `ReBound` (a HRTB) in the // same spot, we do nothing. (ty::ReBound(_, _), ty::ReBound(_, _)) => {} diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index bcc247ba53c2..93c7dae9c5be 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -537,7 +537,7 @@ fn plug_infer_with_placeholders<'tcx>( } fn visit_region(&mut self, r: ty::Region<'tcx>) { - if let ty::ReVar(vid) = *r { + if let ty::ReVar(vid) = r.kind() { let r = self .infcx .inner diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index fa6bbf1d6e57..bf9fcb0915a5 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -797,7 +797,7 @@ impl<'tcx> TypeFolder> for EraseEscapingBoundRegions<'tcx> { } fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - if let ty::ReBound(debruijn, _) = *r + if let ty::ReBound(debruijn, _) = r.kind() && debruijn < self.binder { r diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 5dbb4382fd1b..507932699c7c 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -144,7 +144,7 @@ impl<'tcx> TypeVisitor> for MaxEscapingBoundVarVisitor { #[inline] fn visit_region(&mut self, r: ty::Region<'tcx>) { - match *r { + match r.kind() { ty::ReBound(debruijn, _) if debruijn > self.outer_index => { self.escaping = self.escaping.max(debruijn.as_usize() - self.outer_index.as_usize()); diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index 15f5cf916a48..9f20cd7eacb4 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -289,7 +289,7 @@ impl<'tcx> TypeFolder> for BoundVarReplacer<'_, 'tcx> { } fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - match *r { + match r.kind() { ty::ReBound(debruijn, _) if debruijn.as_usize() >= self.current_index.as_usize() + self.universe_indices.len() => @@ -407,7 +407,7 @@ impl<'tcx> TypeFolder> for PlaceholderReplacer<'_, 'tcx> { } fn fold_region(&mut self, r0: ty::Region<'tcx>) -> ty::Region<'tcx> { - let r1 = match *r0 { + let r1 = match r0.kind() { ty::ReVar(vid) => self .infcx .inner @@ -417,7 +417,7 @@ impl<'tcx> TypeFolder> for PlaceholderReplacer<'_, 'tcx> { _ => r0, }; - let r2 = match *r1 { + let r2 = match r1.kind() { ty::RePlaceholder(p) => { let replace_var = self.mapped_regions.get(&p); match replace_var { diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs index 088d5e76b868..c44f90eb7b40 100644 --- a/compiler/rustc_ty_utils/src/implied_bounds.rs +++ b/compiler/rustc_ty_utils/src/implied_bounds.rs @@ -75,7 +75,7 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<' { let orig_lt = tcx.map_opaque_lifetime_to_parent_lifetime(param.def_id.expect_local()); - if matches!(*orig_lt, ty::ReLateParam(..)) { + if matches!(orig_lt.kind(), ty::ReLateParam(..)) { mapping.insert( orig_lt, ty::Region::new_early_param( diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index a48f5c623cd2..138ac3c97f7b 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -182,7 +182,7 @@ fn clean_param_env<'tcx>( .is_some_and(|pred| tcx.lang_items().sized_trait() == Some(pred.def_id())) }) .map(|pred| { - fold_regions(tcx, pred, |r, _| match *r { + fold_regions(tcx, pred, |r, _| match r.kind() { // FIXME: Don't `unwrap_or`, I think we should panic if we encounter an infer var that // we can't map to a concrete region. However, `AutoTraitFinder` *does* leak those kinds // of `ReVar`s for some reason at the time of writing. See `rustdoc-ui/` tests. @@ -362,7 +362,7 @@ fn clean_region_outlives_constraints<'tcx>( } fn early_bound_region_name(region: Region<'_>) -> Option { - match *region { + match region.kind() { ty::ReEarlyParam(r) => Some(r.name), _ => None, } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index c08ae168d692..ee6008b7851d 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -320,7 +320,7 @@ pub(crate) fn clean_middle_const<'tcx>( } pub(crate) fn clean_middle_region(region: ty::Region<'_>) -> Option { - match *region { + match region.kind() { ty::ReStatic => Some(Lifetime::statik()), _ if !region.has_name() => None, ty::ReBound(_, ty::BoundRegion { kind: ty::BoundRegionKind::Named(_, name), .. }) => { @@ -1941,7 +1941,7 @@ fn clean_trait_object_lifetime_bound<'tcx>( // Since there is a semantic difference between an implicitly elided (i.e. "defaulted") object // lifetime and an explicitly elided object lifetime (`'_`), we intentionally don't hide the // latter contrary to `clean_middle_region`. - match *region { + match region.kind() { ty::ReStatic => Some(Lifetime::statik()), ty::ReEarlyParam(region) => Some(Lifetime(region.name)), ty::ReBound(_, ty::BoundRegion { kind: ty::BoundRegionKind::Named(_, name), .. }) => { @@ -1972,7 +1972,7 @@ fn can_elide_trait_object_lifetime_bound<'tcx>( // > If there is a unique bound from the containing type then that is the default // If there is a default object lifetime and the given region is lexically equal to it, elide it. match default { - ObjectLifetimeDefault::Static => return *region == ty::ReStatic, + ObjectLifetimeDefault::Static => return region.kind() == ty::ReStatic, // FIXME(fmease): Don't compare lexically but respect de Bruijn indices etc. to handle shadowing correctly. ObjectLifetimeDefault::Arg(default) => return region.get_name() == default.get_name(), // > If there is more than one bound from the containing type then an explicit bound must be specified @@ -1992,7 +1992,7 @@ fn can_elide_trait_object_lifetime_bound<'tcx>( // Note however that at the time of this writing it should be fine to disregard this subtlety // as we neither render const exprs faithfully anyway (hiding them in some places or using `_` instead) // nor show the contents of fn bodies. - [] => *region == ty::ReStatic, + [] => region.kind() == ty::ReStatic, // > If the trait is defined with a single lifetime bound then that bound is used. // > If 'static is used for any lifetime bound then 'static is used. // FIXME(fmease): Don't compare lexically but respect de Bruijn indices etc. to handle shadowing correctly. From 44d1d86124e7229a59a13899a14e468fee9dc923 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 8 Apr 2025 13:26:22 +1000 Subject: [PATCH 210/606] libtest: Pass the test's panic payload as Option instead of Result Passing a `Result<(), &dyn Any>` to `calc_result` requires awkward code at both call sites, for no real benefit. It's much easier to just pass the payload as `Option<&dyn Any>`. No functional change, except that the owned payload is dropped slightly later. --- library/test/src/lib.rs | 14 ++++++-------- library/test/src/test_result.rs | 21 ++++++++++++++------- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index 7ada3f269a00..acaf026c679b 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -666,10 +666,11 @@ fn run_test_in_process( io::set_output_capture(None); - let test_result = match result { - Ok(()) => calc_result(&desc, Ok(()), time_opts.as_ref(), exec_time.as_ref()), - Err(e) => calc_result(&desc, Err(e.as_ref()), time_opts.as_ref(), exec_time.as_ref()), - }; + // Determine whether the test passed or failed, by comparing its panic + // payload (if any) with its `ShouldPanic` value, and by checking for + // fatal timeout. + let test_result = + calc_result(&desc, result.err().as_deref(), time_opts.as_ref(), exec_time.as_ref()); let stdout = data.lock().unwrap_or_else(|e| e.into_inner()).to_vec(); let message = CompletedTest::new(id, desc, test_result, exec_time, stdout); monitor_ch.send(message).unwrap(); @@ -741,10 +742,7 @@ fn spawn_test_subprocess( fn run_test_in_spawned_subprocess(desc: TestDesc, runnable_test: RunnableTest) -> ! { let builtin_panic_hook = panic::take_hook(); let record_result = Arc::new(move |panic_info: Option<&'_ PanicHookInfo<'_>>| { - let test_result = match panic_info { - Some(info) => calc_result(&desc, Err(info.payload()), None, None), - None => calc_result(&desc, Ok(()), None, None), - }; + let test_result = calc_result(&desc, panic_info.map(|info| info.payload()), None, None); // We don't support serializing TrFailedMsg, so just // print the message out to stderr. diff --git a/library/test/src/test_result.rs b/library/test/src/test_result.rs index 73dcc2e2a0cc..959cd730fa43 100644 --- a/library/test/src/test_result.rs +++ b/library/test/src/test_result.rs @@ -39,15 +39,18 @@ pub enum TestResult { /// Creates a `TestResult` depending on the raw result of test execution /// and associated data. -pub(crate) fn calc_result<'a>( +pub(crate) fn calc_result( desc: &TestDesc, - task_result: Result<(), &'a (dyn Any + 'static + Send)>, + panic_payload: Option<&(dyn Any + Send)>, time_opts: Option<&time::TestTimeOptions>, exec_time: Option<&time::TestExecTime>, ) -> TestResult { - let result = match (&desc.should_panic, task_result) { - (&ShouldPanic::No, Ok(())) | (&ShouldPanic::Yes, Err(_)) => TestResult::TrOk, - (&ShouldPanic::YesWithMessage(msg), Err(err)) => { + let result = match (desc.should_panic, panic_payload) { + // The test did or didn't panic, as expected. + (ShouldPanic::No, None) | (ShouldPanic::Yes, Some(_)) => TestResult::TrOk, + + // Check the actual panic message against the expected message. + (ShouldPanic::YesWithMessage(msg), Some(err)) => { let maybe_panic_str = err .downcast_ref::() .map(|e| &**e) @@ -71,10 +74,14 @@ pub(crate) fn calc_result<'a>( )) } } - (&ShouldPanic::Yes, Ok(())) | (&ShouldPanic::YesWithMessage(_), Ok(())) => { + + // The test should have panicked, but didn't panic. + (ShouldPanic::Yes, None) | (ShouldPanic::YesWithMessage(_), None) => { TestResult::TrFailedMsg("test did not panic as expected".to_string()) } - _ => TestResult::TrFailed, + + // The test should not have panicked, but did panic. + (ShouldPanic::No, Some(_)) => TestResult::TrFailed, }; // If test is already failed (or allowed to fail), do not change the result. From c5320454ed47736d17d1e07438e27345f08782bc Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 8 Apr 2025 05:54:44 +0000 Subject: [PATCH 211/606] Improve presentation of closure signature mismatch from Fn trait goal --- .../traits/fulfillment_errors.rs | 76 +++++++++++++------ .../issue-62529-3.stderr | 4 +- tests/ui/implied-bounds/issue-100690.stderr | 4 +- ...-arg-type-mismatch-issue-45727.next.stderr | 8 +- .../ui/trait-bounds/mismatch-fn-trait.stderr | 8 +- 5 files changed, 63 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index bc45fc11e9bb..a01574f28265 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -2,6 +2,7 @@ use core::ops::ControlFlow; use std::borrow::Cow; use std::path::PathBuf; +use rustc_abi::ExternAbi; use rustc_ast::TraitObjectSyntax; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::unord::UnordSet; @@ -2799,32 +2800,57 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } // Note any argument mismatches - let given_ty = params.skip_binder(); + let ty::Tuple(given) = *params.skip_binder().kind() else { + return; + }; + let expected_ty = trait_pred.skip_binder().trait_ref.args.type_at(1); - if let ty::Tuple(given) = given_ty.kind() - && let ty::Tuple(expected) = expected_ty.kind() - { - if expected.len() != given.len() { - // Note number of types that were expected and given - err.note( - format!( - "expected a closure taking {} argument{}, but one taking {} argument{} was given", - given.len(), - pluralize!(given.len()), - expected.len(), - pluralize!(expected.len()), - ) - ); - } else if !self.same_type_modulo_infer(given_ty, expected_ty) { - // Print type mismatch - let (expected_args, given_args) = self.cmp(given_ty, expected_ty); - err.note_expected_found( - &"a closure with arguments", - expected_args, - &"a closure with arguments", - given_args, - ); - } + let ty::Tuple(expected) = *expected_ty.kind() else { + return; + }; + + if expected.len() != given.len() { + // Note number of types that were expected and given + err.note(format!( + "expected a closure taking {} argument{}, but one taking {} argument{} was given", + given.len(), + pluralize!(given.len()), + expected.len(), + pluralize!(expected.len()), + )); + return; + } + + let given_ty = Ty::new_fn_ptr( + self.tcx, + params.rebind(self.tcx.mk_fn_sig( + given, + self.tcx.types.unit, + false, + hir::Safety::Safe, + ExternAbi::Rust, + )), + ); + let expected_ty = Ty::new_fn_ptr( + self.tcx, + trait_pred.rebind(self.tcx.mk_fn_sig( + expected, + self.tcx.types.unit, + false, + hir::Safety::Safe, + ExternAbi::Rust, + )), + ); + + if !self.same_type_modulo_infer(given_ty, expected_ty) { + // Print type mismatch + let (expected_args, given_args) = self.cmp(expected_ty, given_ty); + err.note_expected_found( + &"a closure with signature", + expected_args, + &"a closure with signature", + given_args, + ); } } diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr index 64707642eeb0..36264b0d997b 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr @@ -6,8 +6,8 @@ LL | call(f, ()); | | | required by a bound introduced by this call | - = note: expected a closure with arguments `((),)` - found a closure with arguments `(<_ as ATC<'a>>::Type,)` + = note: expected a closure with signature `for<'a> fn(<_ as ATC<'a>>::Type)` + found a closure with signature `fn(())` note: this is a known limitation of the trait solver that will be lifted in the future --> $DIR/issue-62529-3.rs:25:14 | diff --git a/tests/ui/implied-bounds/issue-100690.stderr b/tests/ui/implied-bounds/issue-100690.stderr index 4964dccd551d..d00895d8fc9c 100644 --- a/tests/ui/implied-bounds/issue-100690.stderr +++ b/tests/ui/implied-bounds/issue-100690.stderr @@ -6,8 +6,8 @@ LL | real_dispatch(f) | | | required by a bound introduced by this call | - = note: expected a closure with arguments `(&mut UIView<'a, _>,)` - found a closure with arguments `(&mut UIView<'_, _>,)` + = note: expected a closure with signature `for<'a, 'b> fn(&'a mut UIView<'b, _>)` + found a closure with signature `fn(&mut UIView<'a, _>)` note: required by a bound in `real_dispatch` --> $DIR/issue-100690.rs:8:8 | diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr index b71613106199..7912ed4d7071 100644 --- a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr +++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr @@ -7,8 +7,8 @@ LL | let _ = (-10..=10).find(|x: i32| x.signum() == 0); | required by a bound introduced by this call | = help: the trait `for<'a> FnMut(&'a as Iterator>::Item)` is not implemented for closure `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:6:29: 6:37}` - = note: expected a closure with arguments `(i32,)` - found a closure with arguments `(& as Iterator>::Item,)` + = note: expected a closure with signature `for<'a> fn(&'a as Iterator>::Item)` + found a closure with signature `fn(i32)` note: required by a bound in `find` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL @@ -27,8 +27,8 @@ LL | let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0); | required by a bound introduced by this call | = help: the trait `for<'a> FnMut(&'a as Iterator>::Item)` is not implemented for closure `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:9:29: 9:40}` - = note: expected a closure with arguments `(&&&i32,)` - found a closure with arguments `(& as Iterator>::Item,)` + = note: expected a closure with signature `for<'a> fn(&'a as Iterator>::Item)` + found a closure with signature `fn(&&&i32)` note: required by a bound in `find` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL diff --git a/tests/ui/trait-bounds/mismatch-fn-trait.stderr b/tests/ui/trait-bounds/mismatch-fn-trait.stderr index 519aa9ea3f3b..051e660c2d10 100644 --- a/tests/ui/trait-bounds/mismatch-fn-trait.stderr +++ b/tests/ui/trait-bounds/mismatch-fn-trait.stderr @@ -6,8 +6,8 @@ LL | take(f) | | | required by a bound introduced by this call | - = note: expected a closure with arguments `(u32,)` - found a closure with arguments `(i32,)` + = note: expected a closure with signature `fn(i32)` + found a closure with signature `fn(u32)` note: required by a bound in `take` --> $DIR/mismatch-fn-trait.rs:1:18 | @@ -68,8 +68,8 @@ LL | take(f) | required by a bound introduced by this call | = note: `impl FnOnce(u32)` implements `FnOnce`, but it must implement `FnMut`, which is more general - = note: expected a closure with arguments `(u32,)` - found a closure with arguments `(i32,)` + = note: expected a closure with signature `fn(i32)` + found a closure with signature `fn(u32)` note: required by a bound in `take` --> $DIR/mismatch-fn-trait.rs:1:18 | From d940038636c3694c896988c5cb035da4456a2cb0 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 8 Apr 2025 06:09:04 +0000 Subject: [PATCH 212/606] Remove unnecessary dyn Display in favor of str --- compiler/rustc_errors/src/diagnostic.rs | 8 ++++---- compiler/rustc_lint/src/lints.rs | 2 +- .../src/error_reporting/infer/region.rs | 2 +- .../src/error_reporting/traits/fulfillment_errors.rs | 4 ++-- compiler/rustc_trait_selection/src/errors.rs | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 794502d7aaee..bd13c413a4df 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -647,9 +647,9 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { #[rustc_lint_diagnostics] pub fn note_expected_found( &mut self, - expected_label: &dyn fmt::Display, + expected_label: &str, expected: DiagStyledString, - found_label: &dyn fmt::Display, + found_label: &str, found: DiagStyledString, ) -> &mut Self { self.note_expected_found_extra( @@ -665,9 +665,9 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { #[rustc_lint_diagnostics] pub fn note_expected_found_extra( &mut self, - expected_label: &dyn fmt::Display, + expected_label: &str, expected: DiagStyledString, - found_label: &dyn fmt::Display, + found_label: &str, found: DiagStyledString, expected_extra: DiagStyledString, found_extra: DiagStyledString, diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 55d010e6d34a..51214c8e8a4c 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -513,7 +513,7 @@ impl Subdiagnostic for BuiltinClashingExternSub<'_> { expected_str.push(self.expected.fn_sig(self.tcx).to_string(), false); let mut found_str = DiagStyledString::new(); found_str.push(self.found.fn_sig(self.tcx).to_string(), true); - diag.note_expected_found(&"", expected_str, &"", found_str); + diag.note_expected_found("", expected_str, "", found_str); } } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs index c7f0a88f951a..fcb98f740b01 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -967,7 +967,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { format!("...so that the {}", sup_trace.cause.as_requirement_str()), ); - err.note_expected_found(&"", sup_expected, &"", sup_found); + err.note_expected_found("", sup_expected, "", sup_found); return if sub_region.is_error() | sup_region.is_error() { err.delay_as_bug() } else { diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index a01574f28265..5648021f6134 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -2846,9 +2846,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // Print type mismatch let (expected_args, given_args) = self.cmp(expected_ty, given_ty); err.note_expected_found( - &"a closure with signature", + "a closure with signature", expected_args, - &"a closure with signature", + "a closure with signature", given_args, ); } diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index 9f7bfe5101ab..bb4aba9d29e4 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -415,7 +415,7 @@ impl Subdiagnostic for RegionOriginNote<'_> { label_or_note(span, fluent::trait_selection_subtype); diag.arg("requirement", requirement); - diag.note_expected_found(&"", expected, &"", found); + diag.note_expected_found("", expected, "", found); } RegionOriginNote::WithRequirement { span, requirement, expected_found: None } => { // FIXME: this really should be handled at some earlier stage. Our From e160d93e606e1529cdcd0b8b83ad3d6c323808de Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 8 Apr 2025 10:07:38 +0200 Subject: [PATCH 213/606] test_dependencies: bump tokio --- src/tools/miri/test_dependencies/Cargo.lock | 4 ++-- src/tools/miri/test_dependencies/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tools/miri/test_dependencies/Cargo.lock b/src/tools/miri/test_dependencies/Cargo.lock index d02d2dffbdb8..24a8efc873d6 100644 --- a/src/tools/miri/test_dependencies/Cargo.lock +++ b/src/tools/miri/test_dependencies/Cargo.lock @@ -319,9 +319,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.44.1" +version = "1.44.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f382da615b842244d4b8738c82ed1275e6c5dd90c459a30941cd07080b06c91a" +checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48" dependencies = [ "backtrace", "bytes", diff --git a/src/tools/miri/test_dependencies/Cargo.toml b/src/tools/miri/test_dependencies/Cargo.toml index 7e16592ca7a8..837cb1c50816 100644 --- a/src/tools/miri/test_dependencies/Cargo.toml +++ b/src/tools/miri/test_dependencies/Cargo.toml @@ -22,7 +22,7 @@ tempfile = "3" page_size = "0.6" # Avoid pulling in all of tokio's dependencies. # However, without `net` and `signal`, tokio uses fewer relevant system APIs. -tokio = { version = "1.24", features = ["macros", "rt-multi-thread", "time", "net", "fs", "sync", "signal", "io-util"] } +tokio = { version = "1", features = ["macros", "rt-multi-thread", "time", "net", "fs", "sync", "signal", "io-util"] } [target.'cfg(windows)'.dependencies] windows-sys = { version = "0.59", features = [ "Win32_Foundation", "Win32_System_Threading" ] } From 3dec37f1cc0d2dc30a47116678ebfe69165ea600 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Tue, 8 Apr 2025 16:09:03 +0800 Subject: [PATCH 214/606] compiletest: sort dependencies alphabetically --- src/tools/compiletest/Cargo.toml | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml index 4f8e475e7625..4c661207bf45 100644 --- a/src/tools/compiletest/Cargo.toml +++ b/src/tools/compiletest/Cargo.toml @@ -7,25 +7,27 @@ edition = "2021" doctest = false [dependencies] +# tidy-alphabetical-start anstyle-svg = "0.1.3" +anyhow = "1" +build_helper = { path = "../../build_helper" } colored = "2" diff = "0.1.10" -unified-diff = "0.2.1" getopts = "0.2" +glob = "0.3.0" +home = "0.5.5" indexmap = "2.0.0" miropt-test-tools = { path = "../miropt-test-tools" } -build_helper = { path = "../../build_helper" } -tracing = "0.1" -tracing-subscriber = { version = "0.3.3", default-features = false, features = ["ansi", "env-filter", "fmt", "parking_lot", "smallvec"] } regex = "1.0" +rustfix = "0.8.1" semver = { version = "1.0.23", features = ["serde"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -rustfix = "0.8.1" +tracing = "0.1" +tracing-subscriber = { version = "0.3.3", default-features = false, features = ["ansi", "env-filter", "fmt", "parking_lot", "smallvec"] } +unified-diff = "0.2.1" walkdir = "2" -glob = "0.3.0" -anyhow = "1" -home = "0.5.5" +# tidy-alphabetical-end [target.'cfg(unix)'.dependencies] libc = "0.2" From 603685cd7469265a014e9865b4fb840f713453eb Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Tue, 8 Apr 2025 16:11:26 +0800 Subject: [PATCH 215/606] compiletest: drop dependency on `anyhow` Currently `compiletest` panics all over the place but doesn't really use `anyhow` anyway. I'd like to introduce some more principled error handling and disciplined diagnostic reporting in the near future. --- Cargo.lock | 1 - src/tools/compiletest/Cargo.toml | 1 - src/tools/compiletest/src/runtest.rs | 11 +++++------ 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 52c9269fa87f..0d184fa280bd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -676,7 +676,6 @@ name = "compiletest" version = "0.0.0" dependencies = [ "anstyle-svg", - "anyhow", "build_helper", "colored", "diff", diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml index 4c661207bf45..06e618c2d254 100644 --- a/src/tools/compiletest/Cargo.toml +++ b/src/tools/compiletest/Cargo.toml @@ -9,7 +9,6 @@ doctest = false [dependencies] # tidy-alphabetical-start anstyle-svg = "0.1.3" -anyhow = "1" build_helper = { path = "../../build_helper" } colored = "2" diff = "0.1.10" diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index c8a60b68da8b..6446f9b11ae7 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -10,7 +10,6 @@ use std::process::{Child, Command, ExitStatus, Output, Stdio}; use std::sync::Arc; use std::{env, iter, str}; -use anyhow::Context; use colored::Colorize; use regex::{Captures, Regex}; use tracing::*; @@ -143,11 +142,11 @@ pub fn run(config: Arc, testpaths: &TestPaths, revision: Option<&str>) { } let cx = TestCx { config: &config, props: &props, testpaths, revision }; - create_dir_all(&cx.output_base_dir()) - .with_context(|| { - format!("failed to create output base directory {}", cx.output_base_dir().display()) - }) - .unwrap(); + + if let Err(e) = create_dir_all(&cx.output_base_dir()) { + panic!("failed to create output base directory {}: {e}", cx.output_base_dir().display()); + } + if props.incremental { cx.init_incremental_test(); } From a8b0eb7c65bba72de8bc5cd5068a46ab4563d201 Mon Sep 17 00:00:00 2001 From: xizheyin Date: Tue, 8 Apr 2025 17:36:44 +0800 Subject: [PATCH 216/606] Update compiler/rustc_borrowck/src/diagnostics/region_errors.rs Co-authored-by: lcnr --- compiler/rustc_borrowck/src/diagnostics/region_errors.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 5b5cacdf4c81..8d530b51636a 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -198,7 +198,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { /// Returns `true` if a closure is inferred to be an `FnMut` closure. fn is_closure_fn_mut(&self, fr: RegionVid) -> bool { - if let Some(ty::ReLateParam(late_param)) = self.to_error_region(fr).map(|r| r.kind()) + if let Some(r) = self.to_error_region(fr) + && let ty::ReLateParam(late_param) = r.kind() && let ty::LateParamRegionKind::ClosureEnv = late_param.kind && let DefiningTy::Closure(_, args) = self.regioncx.universal_regions().defining_ty { From c66d35e946ff3c9007c531589537628ad5003c75 Mon Sep 17 00:00:00 2001 From: xizheyin Date: Tue, 8 Apr 2025 17:39:15 +0800 Subject: [PATCH 217/606] update if let to match in universal_regions.rs Signed-off-by: xizheyin --- .../rustc_borrowck/src/universal_regions.rs | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index ab7cc10ae30a..5c57ab99a859 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -909,19 +909,19 @@ impl<'tcx> UniversalRegionIndices<'tcx> { /// if it is a placeholder. Handling placeholders requires access to the /// `MirTypeckRegionConstraints`. fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid { - if let ty::ReVar(..) = r.kind() { - r.as_var() - } else if let ty::ReError(guar) = r.kind() { - self.tainted_by_errors.set(Some(guar)); - // We use the `'static` `RegionVid` because `ReError` doesn't actually exist in the - // `UniversalRegionIndices`. This is fine because 1) it is a fallback only used if - // errors are being emitted and 2) it leaves the happy path unaffected. - self.fr_static - } else { - *self + match r.kind() { + ty::ReVar(..) => r.as_var(), + ty::ReError(guar) => { + self.tainted_by_errors.set(Some(guar)); + // We use the `'static` `RegionVid` because `ReError` doesn't actually exist in the + // `UniversalRegionIndices`. This is fine because 1) it is a fallback only used if + // errors are being emitted and 2) it leaves the happy path unaffected. + self.fr_static + } + _ => *self .indices .get(&r) - .unwrap_or_else(|| bug!("cannot convert `{:?}` to a region vid", r)) + .unwrap_or_else(|| bug!("cannot convert `{:?}` to a region vid", r)), } } From 742b37837165ef0263f70c1fea533b7a3e598fce Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 8 Apr 2025 12:13:17 +0200 Subject: [PATCH 218/606] make hover_feature test less fragile --- .../crates/ide/src/hover/tests.rs | 87 ++----------------- 1 file changed, 8 insertions(+), 79 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs index 5dfd826d7f96..80a2d4690d4a 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs @@ -6882,85 +6882,14 @@ pub fn foo() {} #[test] fn hover_feature() { - check( - r#"#![feature(intrinsics$0)]"#, - expect![[r#" - *intrinsics* - ``` - intrinsics - ``` - ___ - - # `intrinsics` - - The tracking issue for this feature is: None. - - Intrinsics are rarely intended to be stable directly, but are usually - exported in some sort of stable manner. Prefer using the stable interfaces to - the intrinsic directly when you can. - - ------------------------ - - - ## Intrinsics with fallback logic - - Many intrinsics can be written in pure rust, albeit inefficiently or without supporting - some features that only exist on some backends. Backends can simply not implement those - intrinsics without causing any code miscompilations or failures to compile. - All intrinsic fallback bodies are automatically made cross-crate inlineable (like `#[inline]`) - by the codegen backend, but not the MIR inliner. - - ```rust - #![feature(intrinsics)] - #![allow(internal_features)] - - #[rustc_intrinsic] - const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {} - ``` - - Since these are just regular functions, it is perfectly ok to create the intrinsic twice: - - ```rust - #![feature(intrinsics)] - #![allow(internal_features)] - - #[rustc_intrinsic] - const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {} - - mod foo { - #[rustc_intrinsic] - const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) { - panic!("noisy const dealloc") - } - } - - ``` - - The behaviour on backends that override the intrinsic is exactly the same. On other - backends, the intrinsic behaviour depends on which implementation is called, just like - with any regular function. - - ## Intrinsics lowered to MIR instructions - - Various intrinsics have native MIR operations that they correspond to. Instead of requiring - backends to implement both the intrinsic and the MIR operation, the `lower_intrinsics` pass - will convert the calls to the MIR operation. Backends do not need to know about these intrinsics - at all. These intrinsics only make sense without a body, and can be as a `#[rustc_intrinsic]`. - The body is never used, as calls to the intrinsic do not exist anymore after MIR analyses. - - ## Intrinsics without fallback logic - - These must be implemented by all backends. - - ### `#[rustc_intrinsic]` declarations - - These are written like intrinsics with fallback bodies, but the body is irrelevant. - Use `loop {}` for the body or call the intrinsic recursively and add - `#[rustc_intrinsic_must_be_overridden]` to the function to ensure that backends don't - invoke the body. - - "#]], - ) + let (analysis, position) = fixture::position(r#"#![feature(intrinsics$0)]"#); + analysis + .hover( + &HoverConfig { links_in_hover: true, ..HOVER_BASE_CONFIG }, + FileRange { file_id: position.file_id, range: TextRange::empty(position.offset) }, + ) + .unwrap() + .unwrap(); } #[test] From 34e97592f4dc8f4e44a309e3bf69cdcea22fc047 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 8 Apr 2025 12:23:01 +1000 Subject: [PATCH 219/606] compiletest: Trim whitespace from environment variable names --- src/tools/compiletest/src/header.rs | 21 ++++++++--------- src/tools/compiletest/src/runtest.rs | 8 +++---- .../ui/compiletest-self-test/trim-env-name.rs | 23 +++++++++++++++++++ 3 files changed, 36 insertions(+), 16 deletions(-) create mode 100644 tests/ui/compiletest-self-test/trim-env-name.rs diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index a0178f4bcc57..e3adbb66dd9e 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -441,7 +441,7 @@ impl TestProps { ln, UNSET_EXEC_ENV, &mut self.unset_exec_env, - |r| r, + |r| r.trim().to_owned(), ); config.push_name_value_directive( ln, @@ -453,7 +453,7 @@ impl TestProps { ln, UNSET_RUSTC_ENV, &mut self.unset_rustc_env, - |r| r, + |r| r.trim().to_owned(), ); config.push_name_value_directive( ln, @@ -979,16 +979,13 @@ impl Config { fn parse_env(nv: String) -> (String, String) { // nv is either FOO or FOO=BAR - let mut strs: Vec = nv.splitn(2, '=').map(str::to_owned).collect(); - - match strs.len() { - 1 => (strs.pop().unwrap(), String::new()), - 2 => { - let end = strs.pop().unwrap(); - (strs.pop().unwrap(), end) - } - n => panic!("Expected 1 or 2 strings, not {}", n), - } + // FIXME(Zalathar): The form without `=` seems to be unused; should + // we drop support for it? + let (name, value) = nv.split_once('=').unwrap_or((&nv, "")); + // Trim whitespace from the name, so that `//@ exec-env: FOO=BAR` + // sees the name as `FOO` and not ` FOO`. + let name = name.trim(); + (name.to_owned(), value.to_owned()) } fn parse_pp_exact(&self, line: &str, testfile: &Path) -> Option { diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index c8a60b68da8b..70d07b5f1323 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -971,16 +971,16 @@ impl<'test> TestCx<'test> { delete_after_success: bool, ) -> ProcRes { let prepare_env = |cmd: &mut Command| { - for key in &self.props.unset_exec_env { - cmd.env_remove(key); - } - for (key, val) in &self.props.exec_env { cmd.env(key, val); } for (key, val) in env_extra { cmd.env(key, val); } + + for key in &self.props.unset_exec_env { + cmd.env_remove(key); + } }; let proc_res = match &*self.config.target { diff --git a/tests/ui/compiletest-self-test/trim-env-name.rs b/tests/ui/compiletest-self-test/trim-env-name.rs new file mode 100644 index 000000000000..0cb6efe9f765 --- /dev/null +++ b/tests/ui/compiletest-self-test/trim-env-name.rs @@ -0,0 +1,23 @@ +//@ edition: 2024 +//@ revisions: set unset +//@ run-pass +//@ ignore-cross-compile (assume that non-cross targets have working env vars) +//@ rustc-env: MY_RUSTC_ENV = my-rustc-value +//@ exec-env: MY_EXEC_ENV = my-exec-value +//@[unset] unset-rustc-env: MY_RUSTC_ENV +//@[unset] unset-exec-env: MY_EXEC_ENV + +// Check that compiletest trims whitespace from environment variable names +// specified in `rustc-env` and `exec-env` directives, so that +// `//@ exec-env: FOO=bar` sees the name as `FOO` and not ` FOO`. +// +// Values are currently not trimmed. +// +// Since this is a compiletest self-test, only run it on non-cross targets, +// to avoid having to worry about weird targets that don't support env vars. + +fn main() { + let is_set = cfg!(set); + assert_eq!(option_env!("MY_RUSTC_ENV"), is_set.then_some(" my-rustc-value")); + assert_eq!(std::env::var("MY_EXEC_ENV").ok().as_deref(), is_set.then_some(" my-exec-value")); +} From 245cf8e7349df58b5e09dc7c7fa1c523d7634fab Mon Sep 17 00:00:00 2001 From: Stan Manilov Date: Tue, 8 Apr 2025 14:35:56 +0300 Subject: [PATCH 220/606] Fix deprecation note for std::intrinsics Also checked the rest of the mentions of std::mem in the changed file and they look good to me. --- library/core/src/intrinsics/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 7fa57df9928c..73c630df0d3f 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -3724,7 +3724,7 @@ pub const fn ptr_metadata + ?Sized, M>(ptr: *const /// [`Vec::append`]: ../../std/vec/struct.Vec.html#method.append #[doc(alias = "memcpy")] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_allowed_through_unstable_modules = "import this function via `std::mem` instead"] +#[rustc_allowed_through_unstable_modules = "import this function via `std::ptr` instead"] #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces @@ -3827,7 +3827,7 @@ pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: us /// ``` #[doc(alias = "memmove")] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_allowed_through_unstable_modules = "import this function via `std::mem` instead"] +#[rustc_allowed_through_unstable_modules = "import this function via `std::ptr` instead"] #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces @@ -3907,7 +3907,7 @@ pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { /// ``` #[doc(alias = "memset")] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_allowed_through_unstable_modules = "import this function via `std::mem` instead"] +#[rustc_allowed_through_unstable_modules = "import this function via `std::ptr` instead"] #[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces From 63fcd2419dc1db3bc298c033e603a7e3069aa76b Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 8 Apr 2025 22:15:17 +1000 Subject: [PATCH 221/606] compiletest: Remove the `--logfile` flag This flag is deprecated in libtest, and there's no evidence in-tree of this flag actually being passed to compiletest. (For detailed information about test results, bootstrap parses JSON output from compiletest instead.) --- src/tools/compiletest/src/common.rs | 3 --- src/tools/compiletest/src/executor.rs | 2 +- src/tools/compiletest/src/lib.rs | 2 -- 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 9e35d2b46676..36218b2f9045 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -275,9 +275,6 @@ pub struct Config { /// Explicitly enable or disable running. pub run: Option, - /// Write out a parseable log of tests that were run - pub logfile: Option, - /// A command line to prefix program execution with, /// for running under valgrind for example. /// diff --git a/src/tools/compiletest/src/executor.rs b/src/tools/compiletest/src/executor.rs index 7588fee2b2b0..527d6b8a36eb 100644 --- a/src/tools/compiletest/src/executor.rs +++ b/src/tools/compiletest/src/executor.rs @@ -138,7 +138,7 @@ fn test_opts(config: &Config) -> test::TestOpts { filter_exact: config.filter_exact, run_ignored: if config.run_ignored { test::RunIgnored::Yes } else { test::RunIgnored::No }, format: config.format.to_libtest(), - logfile: config.logfile.clone(), + logfile: None, run_tests: true, bench_benchmarks: true, nocapture: config.nocapture, diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 8145ae1c1bce..782f6e0f2d8d 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -139,7 +139,6 @@ pub fn parse_config(args: Vec) -> Config { .optflag("", "quiet", "print one character per test instead of one line") .optopt("", "color", "coloring: auto, always, never", "WHEN") .optflag("", "json", "emit json output instead of plaintext output") - .optopt("", "logfile", "file to log test execution to", "FILE") .optopt("", "target", "the target to build for", "TARGET") .optopt("", "host", "the host to build for", "HOST") .optopt("", "cdb", "path to CDB to use for CDB debuginfo tests", "PATH") @@ -378,7 +377,6 @@ pub fn parse_config(args: Vec) -> Config { "never" => Some(false), _ => panic!("unknown `--run` option `{}` given", mode), }), - logfile: matches.opt_str("logfile").map(|s| PathBuf::from(&s)), runner: matches.opt_str("runner"), host_rustcflags: matches.opt_strs("host-rustcflags"), target_rustcflags: matches.opt_strs("target-rustcflags"), From f2dee82052783ad6447d69aa26869db1f71f04cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Bj=C3=B8rnager=20Jensen?= Date: Tue, 8 Apr 2025 17:07:41 +0200 Subject: [PATCH 222/606] Update 'u8'-to-and-from-'i8' suggestions; --- library/core/src/num/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 151e128cd78a..4c51fcf3b520 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -99,8 +99,8 @@ macro_rules! i8_xe_bytes_doc { **Note**: This function is meaningless on `i8`. Byte order does not exist as a concept for byte-sized integers. This function is only provided in symmetry -with larger integer types. You can cast from and to `u8` using `as i8` and `as -u8`. +with larger integer types. You can cast from and to `u8` using +[`cast_signed`](u8::cast_signed) and [`cast_unsigned`](Self::cast_unsigned). " }; From fe079c4e578fddf2704746abf7303a153ace6a81 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Tue, 8 Apr 2025 08:10:41 -0700 Subject: [PATCH 223/606] Update library tracking issue template to set S-tracking-unimplemented This will help people notice the `S-tracking-*` labels, and if the tracking issue *is* implemented, they can change the label. --- .github/ISSUE_TEMPLATE/library_tracking_issue.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/library_tracking_issue.md b/.github/ISSUE_TEMPLATE/library_tracking_issue.md index 934312662beb..d56da9d5d025 100644 --- a/.github/ISSUE_TEMPLATE/library_tracking_issue.md +++ b/.github/ISSUE_TEMPLATE/library_tracking_issue.md @@ -2,7 +2,7 @@ name: Library Tracking Issue about: A tracking issue for an unstable library feature. title: Tracking Issue for XXX -labels: C-tracking-issue, T-libs-api +labels: C-tracking-issue, T-libs-api, S-tracking-unimplemented --- +(Remember to update the `S-tracking-*` label when checking boxes.) + - [ ] Implementation: #... - [ ] Final comment period (FCP)[^1] - [ ] Stabilization PR From ec3820a10dbf4976fa19a79bfac945dfee8dd20f Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 17 Mar 2025 17:24:02 -0300 Subject: [PATCH 224/606] Add .use block test --- tests/ui/ergonomic-clones/dotuse/block.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 tests/ui/ergonomic-clones/dotuse/block.rs diff --git a/tests/ui/ergonomic-clones/dotuse/block.rs b/tests/ui/ergonomic-clones/dotuse/block.rs new file mode 100644 index 000000000000..2e423c67d02b --- /dev/null +++ b/tests/ui/ergonomic-clones/dotuse/block.rs @@ -0,0 +1,11 @@ +//@ check-pass + +#![feature(ergonomic_clones)] +#![allow(incomplete_features)] + +fn use_block_test(x: i32) -> i32 { + let x = { let x = x + 1; x }.use; + x +} + +fn main() {} From c717c599604c50454933fe58f8a23aa0a0236b5b Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 17 Mar 2025 17:24:16 -0300 Subject: [PATCH 225/606] Add multiple closure use variants --- .../closure/multiple-use-variants.rs | 35 +++++++++++++++++++ .../closure/multiple-use-variants.stderr | 13 +++++++ 2 files changed, 48 insertions(+) create mode 100644 tests/ui/ergonomic-clones/closure/multiple-use-variants.rs create mode 100644 tests/ui/ergonomic-clones/closure/multiple-use-variants.stderr diff --git a/tests/ui/ergonomic-clones/closure/multiple-use-variants.rs b/tests/ui/ergonomic-clones/closure/multiple-use-variants.rs new file mode 100644 index 000000000000..e2e9820a740f --- /dev/null +++ b/tests/ui/ergonomic-clones/closure/multiple-use-variants.rs @@ -0,0 +1,35 @@ +#![feature(ergonomic_clones)] +#![allow(incomplete_features)] + +use std::clone::UseCloned; + +fn takes_val(_: T) {} +fn takes_ref<'a, T>(_: &'a T) {} + +#[derive(Clone)] +struct Inner<'a, T>(&'a T); + +impl<'a, T> UseCloned for Inner<'a, T> where T: Clone {} + +fn main() { + let v = String::new(); + let inner = Inner(&v); + + let _ = use || { + takes_ref(inner.0); + takes_val(inner.0) + }; + let _ = use || { + takes_ref(inner.0); + takes_val(inner.0); + takes_val(inner.0); + takes_val(inner) + }; + let _ = use || { + takes_ref(inner.0); + takes_val(inner.0); + takes_val(inner); + takes_val(inner) + //~^ ERROR: use of moved value: `inner` [E0382] + }; +} diff --git a/tests/ui/ergonomic-clones/closure/multiple-use-variants.stderr b/tests/ui/ergonomic-clones/closure/multiple-use-variants.stderr new file mode 100644 index 000000000000..7b25ca9bba83 --- /dev/null +++ b/tests/ui/ergonomic-clones/closure/multiple-use-variants.stderr @@ -0,0 +1,13 @@ +error[E0382]: use of moved value: `inner` + --> $DIR/multiple-use-variants.rs:32:19 + | +LL | takes_val(inner); + | ----- value moved here +LL | takes_val(inner) + | ^^^^^ value used here after move + | + = note: move occurs because `inner` has type `Inner<'_, String>`, which does not implement the `Copy` trait + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0382`. From 3f21ebcb7a7cdb11c29a5f47718ad6a5b0e12fdd Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 13 Mar 2025 18:31:34 -0300 Subject: [PATCH 226/606] Test interaction between RFC 2229 migration and use closures --- .../closure/rfc2229-migration.fixed | 26 ++++++++++++++++++ .../closure/rfc2229-migration.rs | 25 +++++++++++++++++ .../closure/rfc2229-migration.stderr | 27 +++++++++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 tests/ui/ergonomic-clones/closure/rfc2229-migration.fixed create mode 100644 tests/ui/ergonomic-clones/closure/rfc2229-migration.rs create mode 100644 tests/ui/ergonomic-clones/closure/rfc2229-migration.stderr diff --git a/tests/ui/ergonomic-clones/closure/rfc2229-migration.fixed b/tests/ui/ergonomic-clones/closure/rfc2229-migration.fixed new file mode 100644 index 000000000000..fa83b53526a8 --- /dev/null +++ b/tests/ui/ergonomic-clones/closure/rfc2229-migration.fixed @@ -0,0 +1,26 @@ +//@ run-rustfix +//@ edition:2018 +//@ check-pass +#![feature(ergonomic_clones)] +#![warn(rust_2021_compatibility)] +#![allow(incomplete_features)] + +#[derive(Debug)] +struct Foo(i32); +impl Drop for Foo { + fn drop(&mut self) { + println!("{:?} dropped", self.0); + } +} + +fn main() { + let a = (Foo(0), Foo(1)); + let f = use || { + let _ = &a; + //~^ HELP: add a dummy + //~| WARNING: drop order + let x = a.0; + println!("{:?}", x); + }; + f(); +} diff --git a/tests/ui/ergonomic-clones/closure/rfc2229-migration.rs b/tests/ui/ergonomic-clones/closure/rfc2229-migration.rs new file mode 100644 index 000000000000..4070e5c35a44 --- /dev/null +++ b/tests/ui/ergonomic-clones/closure/rfc2229-migration.rs @@ -0,0 +1,25 @@ +//@ run-rustfix +//@ edition:2018 +//@ check-pass +#![feature(ergonomic_clones)] +#![warn(rust_2021_compatibility)] +#![allow(incomplete_features)] + +#[derive(Debug)] +struct Foo(i32); +impl Drop for Foo { + fn drop(&mut self) { + println!("{:?} dropped", self.0); + } +} + +fn main() { + let a = (Foo(0), Foo(1)); + let f = use || { + //~^ HELP: add a dummy + //~| WARNING: drop order + let x = a.0; + println!("{:?}", x); + }; + f(); +} diff --git a/tests/ui/ergonomic-clones/closure/rfc2229-migration.stderr b/tests/ui/ergonomic-clones/closure/rfc2229-migration.stderr new file mode 100644 index 000000000000..b980be6cb86b --- /dev/null +++ b/tests/ui/ergonomic-clones/closure/rfc2229-migration.stderr @@ -0,0 +1,27 @@ +warning: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/rfc2229-migration.rs:18:13 + | +LL | let f = use || { + | ^^^^^^ +... +LL | let x = a.0; + | --- in Rust 2018, this closure captures all of `a`, but in Rust 2021, it will only capture `a.0` +... +LL | } + | - in Rust 2018, `a` is dropped here, but in Rust 2021, only `a.0` will be dropped here as part of the closure + | + = note: for more information, see +note: the lint level is defined here + --> $DIR/rfc2229-migration.rs:5:9 + | +LL | #![warn(rust_2021_compatibility)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + = note: `#[warn(rust_2021_incompatible_closure_captures)]` implied by `#[warn(rust_2021_compatibility)]` +help: add a dummy let to cause `a` to be fully captured + | +LL ~ let f = use || { +LL + let _ = &a; + | + +warning: 1 warning emitted + From 68692b7fbb674ea51c0b504ac4b8cc791311b10d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 8 Apr 2025 17:00:11 +0000 Subject: [PATCH 227/606] Instantiate higher-ranked transmute goal --- .../src/traits/select/confirmation.rs | 6 +++--- .../transmutability/transmute-higher-ranked.rs | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 3 deletions(-) create mode 100644 tests/ui/transmutability/transmute-higher-ranked.rs diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 2cb7d2d89313..e78abc84137f 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -317,7 +317,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation.cause.clone(), obligation.recursion_depth + 1, obligation.param_env, - obligation.predicate.rebind(trait_ref), + trait_ref, ) }; @@ -343,7 +343,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation.cause.clone(), obligation.recursion_depth + 1, obligation.param_env, - obligation.predicate.rebind(outlives), + outlives, ) }; @@ -404,7 +404,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } - let predicate = obligation.predicate.skip_binder(); + let predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); let mut assume = predicate.trait_ref.args.const_at(2); // FIXME(mgca): We should shallowly normalize this. diff --git a/tests/ui/transmutability/transmute-higher-ranked.rs b/tests/ui/transmutability/transmute-higher-ranked.rs new file mode 100644 index 000000000000..f0fe02a7908e --- /dev/null +++ b/tests/ui/transmutability/transmute-higher-ranked.rs @@ -0,0 +1,18 @@ +// Ensure we don't ICE when transmuting higher-ranked types via a +// higher-ranked transmute goal. + +//@ check-pass + +#![feature(transmutability)] + +use std::mem::TransmuteFrom; + +pub fn transmute() +where + for<'a> &'a &'a i32: TransmuteFrom<&'a &'a u32>, +{ +} + +fn main() { + transmute(); +} From ca4a58241bee6e5cd42ac26a73747cc04a8316c5 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 17 Mar 2025 17:50:36 -0300 Subject: [PATCH 228/606] Add spawn thread test --- .../closure/spawn-thread.edition2018.stderr | 28 +++++++++++ .../ergonomic-clones/closure/spawn-thread.rs | 50 +++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 tests/ui/ergonomic-clones/closure/spawn-thread.edition2018.stderr create mode 100644 tests/ui/ergonomic-clones/closure/spawn-thread.rs diff --git a/tests/ui/ergonomic-clones/closure/spawn-thread.edition2018.stderr b/tests/ui/ergonomic-clones/closure/spawn-thread.edition2018.stderr new file mode 100644 index 000000000000..ac8e1c5fa858 --- /dev/null +++ b/tests/ui/ergonomic-clones/closure/spawn-thread.edition2018.stderr @@ -0,0 +1,28 @@ +error[E0382]: use of moved value: `x` + --> $DIR/spawn-thread.rs:15:42 + | +LL | let x = (Arc::new("foo".to_owned()), Arc::new(vec![1, 2, 3]), Arc::new(1)); + | - move occurs because `x` has type `(Arc, Arc>, Arc)`, which does not implement the `Copy` trait +LL | for _ in 0..10 { + | -------------- inside of this loop +LL | let handler = std::thread::spawn(use || { + | __________________________________________-^^^^^ +LL | | +LL | | drop((x.0, x.1, x.2)); + | | --- use occurs due to use in closure +LL | | }); + | |_________- value moved here, in previous iteration of loop + | +help: consider moving the expression out of the loop so it is only moved once + | +LL ~ let mut value = std::thread::spawn(use || { +LL + +LL + drop((x.0, x.1, x.2)); +LL + }); +LL ~ for _ in 0..10 { +LL ~ let handler = value; + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/ergonomic-clones/closure/spawn-thread.rs b/tests/ui/ergonomic-clones/closure/spawn-thread.rs new file mode 100644 index 000000000000..289d446c6e6f --- /dev/null +++ b/tests/ui/ergonomic-clones/closure/spawn-thread.rs @@ -0,0 +1,50 @@ +//@ revisions: edition2018 edition2024 +//@ [edition2018] edition: 2018 +//@ [edition2024] edition: 2024 +//@ [edition2024] check-pass + +#![feature(ergonomic_clones)] +#![allow(incomplete_features)] + +use std::sync::Arc; + +fn foo() { + // The type is a tuple and doesn't implement UseCloned + let x = (Arc::new("foo".to_owned()), Arc::new(vec![1, 2, 3]), Arc::new(1)); + for _ in 0..10 { + let handler = std::thread::spawn(use || { + //[edition2018]~^ ERROR use of moved value: `x` [E0382] + drop((x.0, x.1, x.2)); + }); + handler.join().unwrap(); + } +} + +fn bar() { + let x = Arc::new("foo".to_owned()); + let y = Arc::new(vec![1, 2, 3]); + let z = Arc::new(1); + + for _ in 0..10 { + let handler = std::thread::spawn(use || { + drop((x, y, z)); + }); + handler.join().unwrap(); + } +} + +fn baz() { + use std::sync::Arc; + use std::thread; + + let five = Arc::new(5); + + for _ in 0..10 { + let handler = thread::spawn(use || { + println!("{five:?}"); + }); + handler.join().unwrap(); + } +} + +fn main() {} From 3feac59b794acf326c0efebaabd500e47fc65ba9 Mon Sep 17 00:00:00 2001 From: "Celina G. Val" Date: Mon, 7 Apr 2025 17:42:08 -0700 Subject: [PATCH 229/606] Fix unreachable expression warning Invert the order that we pass the arguments to the `contract_check_ensures` function to avoid the warning when the tail of the function is unreachable. Note that the call itself is also unreachable, but we have already handled that case by ignoring unreachable call for contract calls. --- compiler/rustc_ast_lowering/src/expr.rs | 3 +-- compiler/rustc_ast_lowering/src/item.rs | 9 ++++++++- .../rustc_hir_analysis/src/check/intrinsic.rs | 2 +- library/core/src/contracts.rs | 15 ++++++++++----- library/core/src/intrinsics/mod.rs | 11 +++++++++-- .../contract-attributes-nest.chk_pass.stderr | 13 +------------ tests/ui/contracts/contract-attributes-nest.rs | 1 - ...ontract-attributes-nest.unchk_fail_post.stderr | 13 +------------ ...contract-attributes-nest.unchk_fail_pre.stderr | 13 +------------ .../contract-attributes-nest.unchk_pass.stderr | 13 +------------ .../contract-captures-via-closure-noncopy.stderr | 1 + .../contract-ast-extensions-nest.rs | 1 - .../internal_machinery/contract-intrinsics.rs | 4 ++-- .../internal_machinery/contract-lang-items.rs | 2 +- .../internal_machinery/internal-feature-gating.rs | 2 +- .../internal-feature-gating.stderr | 2 +- 16 files changed, 39 insertions(+), 66 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 0b7a76304311..c3f57e111830 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -401,11 +401,10 @@ impl<'hir> LoweringContext<'_, 'hir> { cond_hir_id: HirId, ) -> &'hir hir::Expr<'hir> { let cond_fn = self.expr_ident(span, cond_ident, cond_hir_id); - let span = self.mark_span_with_reason(DesugaringKind::Contract, span, None); let call_expr = self.expr_call_lang_item_fn_mut( span, hir::LangItem::ContractCheckEnsures, - arena_vec![self; *expr, *cond_fn], + arena_vec![self; *cond_fn, *expr], ); self.arena.alloc(call_expr) } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 28f596ac0926..c89112fc5a37 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1209,8 +1209,13 @@ impl<'hir> LoweringContext<'_, 'hir> { let precond = if let Some(req) = &contract.requires { // Lower the precondition check intrinsic. let lowered_req = this.lower_expr_mut(&req); + let req_span = this.mark_span_with_reason( + DesugaringKind::Contract, + lowered_req.span, + None, + ); let precond = this.expr_call_lang_item_fn_mut( - req.span, + req_span, hir::LangItem::ContractCheckRequires, &*arena_vec![this; lowered_req], ); @@ -1220,6 +1225,8 @@ impl<'hir> LoweringContext<'_, 'hir> { }; let (postcond, body) = if let Some(ens) = &contract.ensures { let ens_span = this.lower_span(ens.span); + let ens_span = + this.mark_span_with_reason(DesugaringKind::Contract, ens_span, None); // Set up the postcondition `let` statement. let check_ident: Ident = Ident::from_str_and_span("__ensures_checker", ens_span); diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 290e47b42b56..e54fa89328cd 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -236,7 +236,7 @@ pub fn check_intrinsic_type( // where C: for<'a> Fn(&'a Ret) -> bool, // // so: two type params, 0 lifetime param, 0 const params, two inputs, no return - (2, 0, 0, vec![param(0), param(1)], param(0), hir::Safety::Safe) + (2, 0, 0, vec![param(0), param(1)], param(1), hir::Safety::Safe) } else { let safety = intrinsic_operation_unsafety(tcx, intrinsic_id); let (n_tps, n_cts, inputs, output) = match intrinsic_name { diff --git a/library/core/src/contracts.rs b/library/core/src/contracts.rs index 829226420181..53f459debabc 100644 --- a/library/core/src/contracts.rs +++ b/library/core/src/contracts.rs @@ -2,15 +2,20 @@ pub use crate::macros::builtin::{contracts_ensures as ensures, contracts_requires as requires}; -/// Emitted by rustc as a desugaring of `#[ensures(PRED)] fn foo() -> R { ... [return R;] ... }` -/// into: `fn foo() { let _check = build_check_ensures(|ret| PRED) ... [return _check(R);] ... }` -/// (including the implicit return of the tail expression, if any). +/// This is an identity function used as part of the desugaring of the `#[ensures]` attribute. /// -/// This call helps with type inference for the predicate. +/// This is an existing hack to allow users to omit the type of the return value in their ensures +/// attribute. +/// +/// Ideally, rustc should be able to generate the type annotation. +/// The existing lowering logic makes it rather hard to add the explicit type annotation, +/// while the function call is fairly straight forward. #[unstable(feature = "contracts_internals", issue = "128044" /* compiler-team#759 */)] +// Similar to `contract_check_requires`, we need to use the user-facing +// `contracts` feature rather than the perma-unstable `contracts_internals`. +// Const-checking doesn't honor allow internal unstable logic used by contract expansion. #[rustc_const_unstable(feature = "contracts", issue = "128044")] #[lang = "contract_build_check_ensures"] -#[track_caller] pub const fn build_check_ensures(cond: C) -> C where C: Fn(&Ret) -> bool + Copy + 'static, diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 8812cb66526b..90f686a67288 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -3453,6 +3453,10 @@ pub const fn contract_checks() -> bool { /// /// Note that this function is a no-op during constant evaluation. #[unstable(feature = "contracts_internals", issue = "128044")] +// Calls to this function get inserted by an AST expansion pass, which uses the equivalent of +// `#[allow_internal_unstable]` to allow using `contracts_internals` functions. Const-checking +// doesn't honor `#[allow_internal_unstable]`, so for the const feature gate we use the user-facing +// `contracts` feature rather than the perma-unstable `contracts_internals` #[rustc_const_unstable(feature = "contracts", issue = "128044")] #[lang = "contract_check_requires"] #[rustc_intrinsic] @@ -3478,12 +3482,15 @@ pub const fn contract_check_requires bool + Copy>(cond: C) { /// Note that this function is a no-op during constant evaluation. #[cfg(not(bootstrap))] #[unstable(feature = "contracts_internals", issue = "128044")] +// Similar to `contract_check_requires`, we need to use the user-facing +// `contracts` feature rather than the perma-unstable `contracts_internals`. +// Const-checking doesn't honor allow internal unstable logic used by contract expansion. #[rustc_const_unstable(feature = "contracts", issue = "128044")] #[lang = "contract_check_ensures"] #[rustc_intrinsic] -pub const fn contract_check_ensures bool + Copy>(ret: Ret, cond: C) -> Ret { +pub const fn contract_check_ensures bool + Copy, Ret>(cond: C, ret: Ret) -> Ret { const_eval_select!( - @capture[Ret, C: Fn(&Ret) -> bool + Copy] { ret: Ret, cond: C } -> Ret : + @capture[C: Fn(&Ret) -> bool + Copy, Ret] { cond: C, ret: Ret } -> Ret : if const { // Do nothing ret diff --git a/tests/ui/contracts/contract-attributes-nest.chk_pass.stderr b/tests/ui/contracts/contract-attributes-nest.chk_pass.stderr index e7c42ad98a57..9ca95b8bb01a 100644 --- a/tests/ui/contracts/contract-attributes-nest.chk_pass.stderr +++ b/tests/ui/contracts/contract-attributes-nest.chk_pass.stderr @@ -7,16 +7,5 @@ LL | #![feature(contracts)] = note: see issue #128044 for more information = note: `#[warn(incomplete_features)]` on by default -warning: unreachable expression - --> $DIR/contract-attributes-nest.rs:23:1 - | -LL | #[core::contracts::ensures(|ret| *ret > 100)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unreachable expression -... -LL | return x.baz + 50; - | ----------------- any code following this expression is unreachable - | - = note: `#[warn(unreachable_code)]` on by default - -warning: 2 warnings emitted +warning: 1 warning emitted diff --git a/tests/ui/contracts/contract-attributes-nest.rs b/tests/ui/contracts/contract-attributes-nest.rs index 7c35e54c18bc..e1e61b88f282 100644 --- a/tests/ui/contracts/contract-attributes-nest.rs +++ b/tests/ui/contracts/contract-attributes-nest.rs @@ -21,7 +21,6 @@ #[core::contracts::requires(x.baz > 0)] #[core::contracts::ensures(|ret| *ret > 100)] -//~^ WARN unreachable expression [unreachable_code] fn nest(x: Baz) -> i32 { loop { diff --git a/tests/ui/contracts/contract-attributes-nest.unchk_fail_post.stderr b/tests/ui/contracts/contract-attributes-nest.unchk_fail_post.stderr index e7c42ad98a57..9ca95b8bb01a 100644 --- a/tests/ui/contracts/contract-attributes-nest.unchk_fail_post.stderr +++ b/tests/ui/contracts/contract-attributes-nest.unchk_fail_post.stderr @@ -7,16 +7,5 @@ LL | #![feature(contracts)] = note: see issue #128044 for more information = note: `#[warn(incomplete_features)]` on by default -warning: unreachable expression - --> $DIR/contract-attributes-nest.rs:23:1 - | -LL | #[core::contracts::ensures(|ret| *ret > 100)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unreachable expression -... -LL | return x.baz + 50; - | ----------------- any code following this expression is unreachable - | - = note: `#[warn(unreachable_code)]` on by default - -warning: 2 warnings emitted +warning: 1 warning emitted diff --git a/tests/ui/contracts/contract-attributes-nest.unchk_fail_pre.stderr b/tests/ui/contracts/contract-attributes-nest.unchk_fail_pre.stderr index e7c42ad98a57..9ca95b8bb01a 100644 --- a/tests/ui/contracts/contract-attributes-nest.unchk_fail_pre.stderr +++ b/tests/ui/contracts/contract-attributes-nest.unchk_fail_pre.stderr @@ -7,16 +7,5 @@ LL | #![feature(contracts)] = note: see issue #128044 for more information = note: `#[warn(incomplete_features)]` on by default -warning: unreachable expression - --> $DIR/contract-attributes-nest.rs:23:1 - | -LL | #[core::contracts::ensures(|ret| *ret > 100)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unreachable expression -... -LL | return x.baz + 50; - | ----------------- any code following this expression is unreachable - | - = note: `#[warn(unreachable_code)]` on by default - -warning: 2 warnings emitted +warning: 1 warning emitted diff --git a/tests/ui/contracts/contract-attributes-nest.unchk_pass.stderr b/tests/ui/contracts/contract-attributes-nest.unchk_pass.stderr index e7c42ad98a57..9ca95b8bb01a 100644 --- a/tests/ui/contracts/contract-attributes-nest.unchk_pass.stderr +++ b/tests/ui/contracts/contract-attributes-nest.unchk_pass.stderr @@ -7,16 +7,5 @@ LL | #![feature(contracts)] = note: see issue #128044 for more information = note: `#[warn(incomplete_features)]` on by default -warning: unreachable expression - --> $DIR/contract-attributes-nest.rs:23:1 - | -LL | #[core::contracts::ensures(|ret| *ret > 100)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unreachable expression -... -LL | return x.baz + 50; - | ----------------- any code following this expression is unreachable - | - = note: `#[warn(unreachable_code)]` on by default - -warning: 2 warnings emitted +warning: 1 warning emitted diff --git a/tests/ui/contracts/contract-captures-via-closure-noncopy.stderr b/tests/ui/contracts/contract-captures-via-closure-noncopy.stderr index 4a47671fee19..b6f2e014e0a8 100644 --- a/tests/ui/contracts/contract-captures-via-closure-noncopy.stderr +++ b/tests/ui/contracts/contract-captures-via-closure-noncopy.stderr @@ -16,6 +16,7 @@ LL | #[core::contracts::ensures({let old = x; move |ret:&Baz| ret.baz == old.baz | | within this `{closure@$DIR/contract-captures-via-closure-noncopy.rs:12:42: 12:57}` | | this tail expression is of type `{closure@contract-captures-via-closure-noncopy.rs:12:42}` | unsatisfied trait bound + | required by a bound introduced by this call | = help: within `{closure@$DIR/contract-captures-via-closure-noncopy.rs:12:42: 12:57}`, the trait `std::marker::Copy` is not implemented for `Baz` note: required because it's used within this closure diff --git a/tests/ui/contracts/internal_machinery/contract-ast-extensions-nest.rs b/tests/ui/contracts/internal_machinery/contract-ast-extensions-nest.rs index 7f9c3fe28cef..6d8cd3949eed 100644 --- a/tests/ui/contracts/internal_machinery/contract-ast-extensions-nest.rs +++ b/tests/ui/contracts/internal_machinery/contract-ast-extensions-nest.rs @@ -21,7 +21,6 @@ fn nest(x: Baz) -> i32 contract_requires(|| x.baz > 0) contract_ensures(|ret| *ret > 100) - //~^ WARN unreachable expression [unreachable_code] { loop { return x.baz + 50; diff --git a/tests/ui/contracts/internal_machinery/contract-intrinsics.rs b/tests/ui/contracts/internal_machinery/contract-intrinsics.rs index f94dfbde75fb..c62b8cca75ab 100644 --- a/tests/ui/contracts/internal_machinery/contract-intrinsics.rs +++ b/tests/ui/contracts/internal_machinery/contract-intrinsics.rs @@ -28,9 +28,9 @@ fn main() { let doubles_to_two = { let old = 2; move |ret: &u32 | ret + ret == old }; // Always pass - core::intrinsics::contract_check_ensures(1, doubles_to_two); + core::intrinsics::contract_check_ensures(doubles_to_two, 1); // Fail if enabled #[cfg(any(default, unchk_pass, chk_fail_ensures))] - core::intrinsics::contract_check_ensures(2, doubles_to_two); + core::intrinsics::contract_check_ensures(doubles_to_two, 2); } diff --git a/tests/ui/contracts/internal_machinery/contract-lang-items.rs b/tests/ui/contracts/internal_machinery/contract-lang-items.rs index 26042cf688fd..73c591945310 100644 --- a/tests/ui/contracts/internal_machinery/contract-lang-items.rs +++ b/tests/ui/contracts/internal_machinery/contract-lang-items.rs @@ -22,7 +22,7 @@ fn foo(x: Baz) -> i32 { }; let ret = x.baz + 50; - core::intrinsics::contract_check_ensures(ret, injected_checker) + core::intrinsics::contract_check_ensures(injected_checker, ret) } struct Baz { baz: i32 } diff --git a/tests/ui/contracts/internal_machinery/internal-feature-gating.rs b/tests/ui/contracts/internal_machinery/internal-feature-gating.rs index 1b76eef6780f..6e5a7a3f9500 100644 --- a/tests/ui/contracts/internal_machinery/internal-feature-gating.rs +++ b/tests/ui/contracts/internal_machinery/internal-feature-gating.rs @@ -6,7 +6,7 @@ fn main() { //~^ ERROR use of unstable library feature `contracts_internals` core::intrinsics::contract_check_requires(|| true); //~^ ERROR use of unstable library feature `contracts_internals` - core::intrinsics::contract_check_ensures(&1, |_|true); + core::intrinsics::contract_check_ensures( |_|true, &1); //~^ ERROR use of unstable library feature `contracts_internals` core::contracts::build_check_ensures(|_: &()| true); diff --git a/tests/ui/contracts/internal_machinery/internal-feature-gating.stderr b/tests/ui/contracts/internal_machinery/internal-feature-gating.stderr index 7302694a7874..1e39bd62e245 100644 --- a/tests/ui/contracts/internal_machinery/internal-feature-gating.stderr +++ b/tests/ui/contracts/internal_machinery/internal-feature-gating.stderr @@ -41,7 +41,7 @@ LL | core::intrinsics::contract_check_requires(|| true); error[E0658]: use of unstable library feature `contracts_internals` --> $DIR/internal-feature-gating.rs:9:5 | -LL | core::intrinsics::contract_check_ensures(&1, |_|true); +LL | core::intrinsics::contract_check_ensures( |_|true, &1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #128044 for more information From df6254f7a204b383bd8346880247a68dc32cab32 Mon Sep 17 00:00:00 2001 From: Jonathan Gruner Date: Tue, 8 Apr 2025 20:49:50 +0200 Subject: [PATCH 230/606] report call site of inlined scopes for large assignment lints --- .../src/mono_checks/move_check.rs | 20 +++++++++++++--- tests/ui/lint/large_assignments/inline_mir.rs | 24 +++++++++++++++++++ .../lint/large_assignments/inline_mir.stderr | 15 ++++++++++++ 3 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 tests/ui/lint/large_assignments/inline_mir.rs create mode 100644 tests/ui/lint/large_assignments/inline_mir.stderr diff --git a/compiler/rustc_monomorphize/src/mono_checks/move_check.rs b/compiler/rustc_monomorphize/src/mono_checks/move_check.rs index 838bfdab1ea5..946714e3e48a 100644 --- a/compiler/rustc_monomorphize/src/mono_checks/move_check.rs +++ b/compiler/rustc_monomorphize/src/mono_checks/move_check.rs @@ -162,13 +162,27 @@ impl<'tcx> MoveCheckVisitor<'tcx> { // but correct span? This would make the lint at least accept crate-level lint attributes. return; }; + + // If the source scope is inlined by the MIR inliner, report the lint on the call site. + let reported_span = self + .body + .source_scopes + .get(source_info.scope) + .and_then(|source_scope_data| source_scope_data.inlined) + .map(|(_, call_site)| call_site) + .unwrap_or(span); + self.tcx.emit_node_span_lint( LARGE_ASSIGNMENTS, lint_root, - span, - LargeAssignmentsLint { span, size: too_large_size.bytes(), limit: limit as u64 }, + reported_span, + LargeAssignmentsLint { + span: reported_span, + size: too_large_size.bytes(), + limit: limit as u64, + }, ); - self.move_size_spans.push(span); + self.move_size_spans.push(reported_span); } } diff --git a/tests/ui/lint/large_assignments/inline_mir.rs b/tests/ui/lint/large_assignments/inline_mir.rs new file mode 100644 index 000000000000..fc27b8ff244d --- /dev/null +++ b/tests/ui/lint/large_assignments/inline_mir.rs @@ -0,0 +1,24 @@ +#![feature(large_assignments)] +#![deny(large_assignments)] +#![move_size_limit = "1000"] + +//! Tests that with `-Zinline-mir`, we do NOT get an error that points to the +//! implementation of `UnsafeCell` since that is not actionable by the user: +//! +//! ```text +//! error: moving 9999 bytes +//! --> /rustc/FAKE_PREFIX/library/core/src/cell.rs:2054:9 +//! | +//! = note: value moved from here +//! ``` +//! +//! We want the diagnostics to point to the relevant user code. + +//@ build-fail +//@ compile-flags: -Zmir-opt-level=1 -Zinline-mir + +pub fn main() { + let data = [10u8; 9999]; + let cell = std::cell::UnsafeCell::new(data); //~ ERROR large_assignments + std::hint::black_box(cell); +} diff --git a/tests/ui/lint/large_assignments/inline_mir.stderr b/tests/ui/lint/large_assignments/inline_mir.stderr new file mode 100644 index 000000000000..d9010e24d03b --- /dev/null +++ b/tests/ui/lint/large_assignments/inline_mir.stderr @@ -0,0 +1,15 @@ +error: moving 9999 bytes + --> $DIR/inline_mir.rs:22:16 + | +LL | let cell = std::cell::UnsafeCell::new(data); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ value moved from here + | + = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` +note: the lint level is defined here + --> $DIR/inline_mir.rs:2:9 + | +LL | #![deny(large_assignments)] + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + From 6d71fc15d8983960745bf2f61ab74ca272f0585f Mon Sep 17 00:00:00 2001 From: Jonathan Gruner Date: Tue, 8 Apr 2025 21:22:20 +0200 Subject: [PATCH 231/606] for large assignment lint, use the correct span for checking for duplicate lints --- .../src/mono_checks/move_check.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_monomorphize/src/mono_checks/move_check.rs b/compiler/rustc_monomorphize/src/mono_checks/move_check.rs index 946714e3e48a..a484573f0d86 100644 --- a/compiler/rustc_monomorphize/src/mono_checks/move_check.rs +++ b/compiler/rustc_monomorphize/src/mono_checks/move_check.rs @@ -148,11 +148,7 @@ impl<'tcx> MoveCheckVisitor<'tcx> { span: Span, ) { let source_info = self.body.source_info(location); - for reported_span in &self.move_size_spans { - if reported_span.overlaps(span) { - return; - } - } + let lint_root = source_info.scope.lint_root(&self.body.source_scopes); let Some(lint_root) = lint_root else { // This happens when the issue is in a function from a foreign crate that @@ -172,6 +168,12 @@ impl<'tcx> MoveCheckVisitor<'tcx> { .map(|(_, call_site)| call_site) .unwrap_or(span); + for previously_reported_span in &self.move_size_spans { + if previously_reported_span.overlaps(reported_span) { + return; + } + } + self.tcx.emit_node_span_lint( LARGE_ASSIGNMENTS, lint_root, @@ -182,6 +184,7 @@ impl<'tcx> MoveCheckVisitor<'tcx> { limit: limit as u64, }, ); + self.move_size_spans.push(reported_span); } } From b3f75353a237f3623483c1e237be480140a8c3e1 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 5 Apr 2025 19:19:56 +0300 Subject: [PATCH 232/606] UI tests: add missing diagnostic kinds where possible --- tests/rustdoc-ui/invalid-syntax.rs | 2 +- .../issues/ice-generic-type-alias-105742.rs | 74 ++++++++--------- tests/rustdoc-ui/issues/ice-typeof-102986.rs | 2 +- tests/ui-fulldeps/hash-stable-is-unstable.rs | 10 +-- tests/ui-fulldeps/try-from-u32/errors.rs | 10 +-- tests/ui/abi/simd-abi-checks-avx.rs | 6 +- tests/ui/abi/simd-abi-checks-empty-list.rs | 2 +- tests/ui/abi/simd-abi-checks-sse.rs | 2 +- tests/ui/abi/vectorcall-abi-checks.rs | 4 +- .../ui/anon-params/anon-params-denied-2018.rs | 2 +- tests/ui/argument-suggestions/issue-100478.rs | 2 +- tests/ui/argument-suggestions/issue-101097.rs | 6 +- .../ui/array-slice-vec/array_const_index-0.rs | 2 +- .../ui/array-slice-vec/array_const_index-1.rs | 2 +- tests/ui/asm/issue-85247.rs | 2 +- tests/ui/asm/issue-99071.rs | 2 +- tests/ui/asm/type-check-4.rs | 4 +- tests/ui/asm/x86_64/issue-82869.rs | 6 +- .../associated-consts/defaults-cyclic-fail.rs | 2 +- .../generic-associated-types-bad.rs | 4 +- .../return-type-notation/path-missing.rs | 2 +- .../hr-associated-type-bound-2.rs | 2 +- .../hr-associated-type-bound-param-2.rs | 10 +-- .../hr-associated-type-projection-1.rs | 4 +- .../issue-85103-layout-debug.rs | 2 +- ...invalid-type-bound-suggest-issue-127555.rs | 2 +- .../drop-track-field-assign-nonsend.rs | 2 +- tests/ui/async-await/field-assign-nonsend.rs | 2 +- tests/ui/async-await/suggest-missing-await.rs | 2 +- tests/ui/attributes/issue-90873.rs | 6 +- tests/ui/attributes/used_with_multi_args.rs | 2 +- tests/ui/augmented-assignments.rs | 4 +- .../auto-traits/auto-trait-validation.fixed | 8 +- tests/ui/auto-traits/auto-trait-validation.rs | 8 +- tests/ui/borrowck/borrowck-fn-in-const-c.rs | 2 +- .../borrowck/borrowck-vec-pattern-nesting.rs | 2 +- tests/ui/borrowck/issue-36082.fixed | 2 +- tests/ui/borrowck/issue-36082.rs | 2 +- tests/ui/borrowck/two-phase-multi-mut.rs | 4 +- .../2229_closure_analysis/by_value.rs | 4 +- .../capture-analysis-1.rs | 4 +- .../capture-analysis-2.rs | 4 +- .../capture-analysis-3.rs | 4 +- .../capture-analysis-4.rs | 4 +- .../capture-disjoint-field-struct.rs | 4 +- .../capture-disjoint-field-tuple.rs | 4 +- .../2229_closure_analysis/capture-enums.rs | 8 +- .../diagnostics/union.rs | 10 +-- .../match/patterns-capture-analysis.rs | 36 ++++----- .../2229_closure_analysis/move_closure.rs | 12 +-- tests/ui/closures/binder/implicit-return.rs | 2 +- .../obligation-with-leaking-placeholders.rs | 2 +- .../wrong-closure-arg-suggestion-125325.rs | 4 +- .../coerce-reborrow-multi-arg-fail.rs | 2 +- tests/ui/coercion/mut-mut-wont-coerce.rs | 2 +- .../nested_bad_const_param_ty.rs | 12 +-- .../early/invalid-const-arguments.rs | 4 +- tests/ui/const-generics/issues/issue-68366.rs | 2 +- tests/ui/const-generics/issues/issue-74950.rs | 8 +- tests/ui/const-generics/issues/issue-90318.rs | 4 +- tests/ui/consts/async-block.rs | 4 +- tests/ui/consts/const-array-oob-arith.rs | 4 +- tests/ui/consts/const-deref-ptr.rs | 2 +- .../ui/consts/const-err-enum-discriminant.rs | 2 +- .../assign-to-static-within-other-static.rs | 2 +- tests/ui/consts/const-eval/const-eval-span.rs | 2 +- .../consts/const-eval/const_raw_ptr_ops2.rs | 4 +- .../issue-91827-extern-types-field-offset.rs | 2 +- .../const-eval/partial_ptr_overwrite.rs | 2 +- .../ui/consts/const-eval/ub-enum-overwrite.rs | 2 +- .../const-eval/ub-write-through-immutable.rs | 4 +- tests/ui/consts/const-eval/union-ice.rs | 6 +- tests/ui/consts/const-eval/union_promotion.rs | 2 +- .../const-extern-fn-requires-unsafe.rs | 4 +- tests/ui/consts/const-integer-bool-ops.rs | 36 ++++----- .../ui/consts/const-len-underflow-subspans.rs | 2 +- tests/ui/consts/const-slice-oob.rs | 2 +- tests/ui/consts/copy-intrinsic.rs | 10 +-- tests/ui/consts/drop_zst.rs | 2 +- tests/ui/consts/eval-enum.rs | 4 +- .../consts/extra-const-ub/detect-extra-ub.rs | 16 ++-- tests/ui/consts/issue-19244-2.rs | 2 +- tests/ui/consts/min_const_fn/min_const_fn.rs | 4 +- tests/ui/consts/miri_unleashed/ptr_arith.rs | 4 +- ...no-ice-from-static-in-const-issue-52060.rs | 2 +- ...oted_running_out_of_memory_issue-130687.rs | 2 +- tests/ui/consts/promoted_size_overflow.rs | 2 +- tests/ui/consts/recursive-zst-static.rs | 2 +- .../slice-index-overflow-issue-130284.rs | 2 +- tests/ui/coroutine/auto-trait-regions.rs | 4 +- tests/ui/coroutine/coroutine-with-nll.rs | 2 +- tests/ui/coroutine/retain-resume-ref.rs | 2 +- tests/ui/deref-patterns/gate.rs | 2 +- .../do_not_recommend/as_expression.rs | 4 +- .../custom-on-unimplemented-diagnostic.rs | 2 +- ...ed_options_and_continue_to_use_fallback.rs | 4 +- tests/ui/did_you_mean/issue-38147-1.rs | 2 +- tests/ui/did_you_mean/issue-40006.rs | 2 +- tests/ui/did_you_mean/issue-42764.rs | 2 +- .../lint-tail-expr-drop-order-borrowck.rs | 8 +- tests/ui/duplicate/dupe-symbols-1.rs | 2 +- tests/ui/duplicate/dupe-symbols-2.rs | 2 +- tests/ui/duplicate/dupe-symbols-3.rs | 2 +- tests/ui/duplicate/dupe-symbols-5.rs | 2 +- tests/ui/duplicate/dupe-symbols-6.rs | 2 +- .../ui/dyn-compatibility/taint-const-eval.rs | 6 +- tests/ui/dyn-star/async-block-dyn-star.rs | 2 +- tests/ui/dyn-star/feature-gate-dyn_star.rs | 2 +- .../never-type-fallback-breaking.e2021.fixed | 20 ++--- .../editions/never-type-fallback-breaking.rs | 20 ++--- .../discriminant-ill-typed.rs | 16 ++-- tests/ui/error-codes/E0063.rs | 2 +- tests/ui/error-codes/E0186.rs | 4 +- tests/ui/error-codes/E0261.rs | 4 +- tests/ui/error-codes/E0262.rs | 2 +- tests/ui/error-codes/E0516.rs | 2 +- tests/ui/error-codes/E0597.rs | 2 +- tests/ui/error-codes/E0606.rs | 2 +- tests/ui/extern/extern-main-issue-86110.rs | 2 +- ...363-extern-item-where-clauses-debug-ice.rs | 10 +-- .../feature-gates/feature-gate-c_variadic.rs | 2 +- .../feature-gate-cfg-emscripten-wasm-eh.rs | 2 +- .../feature-gate-cfg-sanitizer_cfi.rs | 4 +- .../feature-gate-cfg_sanitize.rs | 2 +- .../feature-gate-closure_track_caller.rs | 6 +- .../feature-gates/feature-gate-custom_mir.rs | 4 +- .../feature-gate-freeze-impls.rs | 4 +- .../feature-gate-naked_functions.rs | 4 +- .../feature-gates/feature-gate-new_range.rs | 6 +- .../feature-gates/feature-gate-no_sanitize.rs | 2 +- .../feature-gate-rustc_const_unstable.rs | 2 +- .../issue-43106-gating-of-builtin-attrs.rs | 8 +- ...ssue-74120-lowering-of-ffi-block-bodies.rs | 2 +- .../issue-91370-foreign-fn-block-impl.rs | 2 +- .../ambig-hr-projection-issue-93340.rs | 2 +- .../bugs/hrtb-implied-3.rs | 2 +- .../collectivity-regression.rs | 2 +- .../gat-in-trait-path.rs | 6 +- .../generic-associated-types/issue-74816.rs | 2 +- ...e-78113-lifetime-mismatch-dyn-trait-box.rs | 6 +- .../generic-associated-types/issue-86787.rs | 2 +- .../issue-88360.fixed | 2 +- .../generic-associated-types/issue-88360.rs | 2 +- .../missing-where-clause-on-trait.rs | 2 +- .../self-outlives-lint.rs | 32 ++++---- .../generic-associated-types/trait-objects.rs | 6 +- .../type-param-defaults.rs | 6 +- ...gate-half-open-range-patterns-in-slices.rs | 2 +- .../slice_pattern_syntax_problem0.rs | 2 +- .../slice_pattern_syntax_problem1.rs | 2 +- .../normalize-under-binder/issue-62529-3.rs | 2 +- tests/ui/illegal-sized-bound/regular.rs | 4 +- tests/ui/impl-trait/call_method_ambiguous.rs | 2 +- .../call_method_on_inherent_impl.rs | 2 +- .../call_method_on_inherent_impl_ref.rs | 6 +- ...-type-whensubstituting-in-region-112823.rs | 2 +- tests/ui/impl-trait/implicit-capture-late.rs | 2 +- .../in-trait/default-body-type-err.rs | 2 +- ...-hidden-types-self-implied-wf-via-param.rs | 2 +- tests/ui/impl-trait/in-trait/variance.rs | 12 +-- tests/ui/impl-trait/issues/issue-54600.rs | 2 +- tests/ui/impl-trait/issues/issue-54840.rs | 2 +- tests/ui/impl-trait/issues/issue-58504.rs | 2 +- tests/ui/impl-trait/issues/issue-58956.rs | 4 +- tests/ui/impl-trait/issues/issue-70971.rs | 2 +- tests/ui/impl-trait/issues/issue-79099.rs | 4 +- tests/ui/impl-trait/issues/issue-84919.rs | 2 +- tests/ui/impl-trait/issues/issue-86642.rs | 2 +- tests/ui/impl-trait/issues/issue-87295.rs | 2 +- .../issues/issue-99348-impl-compatibility.rs | 2 +- tests/ui/impl-trait/method-resolution4.rs | 2 +- tests/ui/impl-trait/nested_impl_trait.rs | 2 +- tests/ui/impl-trait/variance.rs | 12 +-- .../implied-bounds-on-trait-hierarchy-1.rs | 2 +- tests/ui/implied-bounds/sod_service_chain.rs | 12 +-- tests/ui/imports/import-from-missing.rs | 2 +- tests/ui/imports/import2.rs | 2 +- tests/ui/imports/issue-13404.rs | 2 +- tests/ui/imports/issue-2937.rs | 2 +- tests/ui/imports/issue-32833.rs | 2 +- tests/ui/imports/issue-8208.rs | 6 +- tests/ui/inline-const/in-pat-recovery.rs | 2 +- .../using-late-bound-from-closure.rs | 2 +- .../intrinsics/intrinsic-raw_eq-const-bad.rs | 6 +- ...ustc_legacy_const_generics-issue-123077.rs | 14 ++-- tests/ui/invalid_dispatch_from_dyn_impls.rs | 2 +- tests/ui/issues/issue-11004.rs | 4 +- tests/ui/issues/issue-14721.rs | 2 +- tests/ui/issues/issue-17740.rs | 4 +- tests/ui/issues/issue-23253.rs | 2 +- tests/ui/issues/issue-24363.rs | 2 +- tests/ui/issues/issue-24365.rs | 6 +- tests/ui/issues/issue-27008.rs | 2 +- tests/ui/issues/issue-2848.rs | 4 +- tests/ui/issues/issue-31011.rs | 2 +- tests/ui/issues/issue-51102.rs | 2 +- tests/ui/issues/issue-69130.rs | 2 +- tests/ui/issues/issue-87199.rs | 2 +- tests/ui/issues/issue-8761.rs | 4 +- tests/ui/iterators/float_iterator_hint.rs | 2 +- tests/ui/layout/post-mono-layout-cycle.rs | 2 +- tests/ui/lifetimes/conflicting-bounds.rs | 2 +- ...invalid-associated-type-supertrait-hrtb.rs | 2 +- .../issue-83907-invalid-fn-like-path.rs | 4 +- tests/ui/limits/huge-static.rs | 4 +- tests/ui/lint/lint-attr-everywhere-early.rs | 2 +- tests/ui/lint/lints-in-foreign-macros.rs | 2 +- .../lint-uncommon-codepoints.rs | 2 +- tests/ui/lint/unused-borrows.rs | 12 +-- tests/ui/lint/unused/must_use-unit.rs | 4 +- tests/ui/lint/unused/useless-comment.rs | 2 +- tests/ui/macros/issue-42954.fixed | 2 +- tests/ui/macros/issue-42954.rs | 2 +- tests/ui/macros/issue-88228.rs | 2 +- .../intended-binding-pattern-is-const.rs | 6 +- .../postfix-match/pf-match-exhaustiveness.rs | 2 +- .../methods/bad-wf-when-selecting-method.rs | 2 +- ...ambiguate-associated-function-first-arg.rs | 2 +- tests/ui/methods/issues/issue-90315.rs | 2 +- tests/ui/mir/enable_passes_validation.rs | 8 +- ...-or-removing-ref-for-binding-pattern.fixed | 2 +- ...ing-or-removing-ref-for-binding-pattern.rs | 2 +- tests/ui/moves/moves-based-on-type-tuple.rs | 2 +- .../use_of_moved_value_clone_suggestions.rs | 2 +- .../use_of_moved_value_copy_suggestions.fixed | 22 ++--- .../use_of_moved_value_copy_suggestions.rs | 22 ++--- tests/ui/never_type/fallback-closure-wrap.rs | 2 +- tests/ui/nll/borrowed-match-issue-45045.rs | 2 +- tests/ui/nll/issue-48697.rs | 2 +- .../nll/issue-54779-anon-static-lifetime.rs | 2 +- .../nested-impl-trait-fail.rs | 8 +- tests/ui/nonscalar-cast.fixed | 2 +- tests/ui/nonscalar-cast.rs | 2 +- tests/ui/offset-of/offset-of-self.rs | 8 +- tests/ui/offset-of/offset-of-tuple.rs | 2 +- tests/ui/on-unimplemented/bad-annotation.rs | 16 ++-- tests/ui/or-patterns/inner-or-pat.rs | 2 +- .../while-parsing-this-or-pattern.rs | 2 +- .../panic-handler-bad-signature-1.rs | 2 +- .../panic-handler-bad-signature-2.rs | 2 +- .../panic-handler-bad-signature-3.rs | 2 +- .../panic-handler-bad-signature-5.rs | 2 +- .../diff-markers/unclosed-delims-in-macro.rs | 2 +- .../unclosed-delims-in-macro.stderr | 4 +- .../ui/parser/diff-markers/unclosed-delims.rs | 2 +- .../diff-markers/unclosed-delims.stderr | 4 +- tests/ui/parser/do-catch-suggests-try.rs | 2 +- tests/ui/parser/float-field.rs | 4 +- tests/ui/parser/intersection-patterns-1.fixed | 8 +- tests/ui/parser/intersection-patterns-1.rs | 8 +- tests/ui/parser/intersection-patterns-2.rs | 4 +- .../ui/parser/issues/issue-101477-enum.fixed | 2 +- tests/ui/parser/issues/issue-101477-enum.rs | 2 +- tests/ui/parser/issues/issue-102806.rs | 2 +- tests/ui/parser/issues/issue-89574.rs | 2 +- tests/ui/parser/issues/issue-93867.rs | 2 +- .../ui/parser/macro/macro-expand-to-field.rs | 2 +- ...77-panic-on-unterminated-raw-str-at-eof.rs | 2 +- tests/ui/parser/raw/raw-byte-string-eof.rs | 2 +- .../recover/recover-fn-trait-from-fn-kw.rs | 4 +- .../require-parens-for-chained-comparison.rs | 2 +- .../parser/shebang/issue-71471-ignore-tidy.rs | 2 +- .../parser/shebang/shebang-must-start-file.rs | 2 +- .../patkind-ref-binding-issue-114896.fixed | 2 +- .../patkind-ref-binding-issue-114896.rs | 2 +- .../experimental/borrowck-errors.rs | 6 +- .../experimental/mut-ref-mut.rs | 2 +- .../experimental/well-typed-edition-2024.rs | 36 ++++----- .../pattern/usefulness/doc-hidden-fields.rs | 8 +- .../usefulness/doc-hidden-non-exhaustive.rs | 10 +-- .../usefulness/non-exhaustive-defined-here.rs | 24 +++--- .../pattern/usefulness/stable-gated-fields.rs | 4 +- .../usefulness/stable-gated-patterns.rs | 4 +- .../usefulness/unstable-gated-fields.rs | 4 +- .../usefulness/unstable-gated-patterns.rs | 2 +- tests/ui/privacy/privacy3.rs | 2 +- tests/ui/proc-macro/issue-50493.rs | 2 +- tests/ui/proc-macro/pub-at-crate-root.rs | 2 +- tests/ui/pub/pub-restricted.rs | 10 +-- tests/ui/repr/attr-usage-repr.rs | 2 +- tests/ui/resolve/crate-called-as-function.rs | 2 +- tests/ui/resolve/issue-118295.rs | 4 +- tests/ui/resolve/tool-import.rs | 2 +- .../omitted-patterns.rs | 38 ++++----- .../stable-omitted-patterns.rs | 4 +- .../regions-enum-not-wf.rs | 2 +- .../extern_block_nonascii_forbidden.rs | 6 +- .../mod_file_nonascii_forbidden.rs | 4 +- .../no_mangle_nonascii_forbidden.rs | 6 +- .../issue-92010-trait-bound-not-satisfied.rs | 2 +- .../rust-2018/edition-lint-nested-paths.fixed | 8 +- .../ui/rust-2018/edition-lint-nested-paths.rs | 8 +- ...ture-prelude-collision-generic-trait.fixed | 2 +- .../future-prelude-collision-generic-trait.rs | 2 +- .../future-prelude-collision-generic.fixed | 6 +- .../future-prelude-collision-generic.rs | 6 +- .../ui/rust-2024/reserved-guarded-strings.rs | 12 +-- .../arbitrary_self_type_infinite_recursion.rs | 10 +-- ..._self_types_pin_lifetime_mismatch-async.rs | 6 +- tests/ui/simd/empty-simd-vector-in-operand.rs | 2 +- tests/ui/simd/monomorphize-shuffle-index.rs | 2 +- .../generics-default-stability.rs | 80 +++++++++---------- tests/ui/static/bad-const-type.rs | 2 +- tests/ui/structs/struct-missing-comma.fixed | 2 +- tests/ui/structs/struct-missing-comma.rs | 2 +- ...placing-field-when-specifying-same-type.rs | 2 +- .../derive-trait-for-method-call.rs | 6 +- tests/ui/suggestions/field-has-method.rs | 2 +- tests/ui/suggestions/issue-101465.rs | 2 +- tests/ui/suggestions/issue-81839.rs | 2 +- .../ui/suggestions/partialeq_suggest_swap.rs | 2 +- .../partialeq_suggest_swap_on_e0277.rs | 2 +- ...adding-reference-to-trait-assoc-item.fixed | 4 +- ...st-adding-reference-to-trait-assoc-item.rs | 4 +- .../suggest-let-for-assignment.fixed | 4 +- .../suggestions/suggest-let-for-assignment.rs | 4 +- tests/ui/suggestions/suggest-null-ptr.fixed | 16 ++-- tests/ui/suggestions/suggest-null-ptr.rs | 16 ++-- .../types/dont-suggest-path-names.rs | 4 +- ...unmet-trait-alias-bound-on-generic-impl.rs | 2 +- .../check-trait-object-bounds-2.rs | 2 +- .../check-trait-object-bounds-5.rs | 2 +- .../ice-119717-constant-lifetime.rs | 4 +- tests/ui/traits/const-traits/staged-api.rs | 10 +-- tests/ui/traits/copy-is-not-modulo-regions.rs | 2 +- .../rustc_must_implement_one_of.rs | 2 +- .../rustc_must_implement_one_of_duplicates.rs | 8 +- .../rustc_must_implement_one_of_gated.rs | 2 +- .../rustc_must_implement_one_of_misuse.rs | 22 ++--- .../maybe-bounds-in-traits.rs | 2 +- tests/ui/traits/issue-106072.rs | 6 +- .../builtin-fn-must-return-sized.rs | 2 +- .../diagnostics/point-at-failing-nested.rs | 2 +- tests/ui/traits/next-solver/gat-wf.rs | 2 +- .../non-lifetime-binder-in-constraint.rs | 2 +- tests/ui/traits/object/vs-lifetime.rs | 2 +- tests/ui/transmutability/issue-101739-1.rs | 2 +- .../unknown_dst.rs | 2 +- .../unknown_dst_field.rs | 4 +- .../unknown_src.rs | 2 +- .../unknown_src_field.rs | 4 +- .../auto-trait-leakage2.rs | 8 +- .../constrain_in_projection.rs | 4 +- .../declared_but_not_defined_in_scope.rs | 2 +- .../generic_duplicate_param_use8.rs | 2 +- .../ui/type-alias-impl-trait/issue-104817.rs | 2 +- .../type-alias-impl-trait/not_well_formed.rs | 4 +- .../structural-match-no-leak.rs | 2 +- .../type-alias-impl-trait/structural-match.rs | 2 +- tests/ui/type-alias-impl-trait/variance.rs | 30 +++---- tests/ui/type/issue-103271.rs | 6 +- .../feature-gate-pattern_types.rs | 10 +-- tests/ui/type/pattern_types/literals.rs | 36 ++++----- tests/ui/typeck/attempted-access-non-fatal.rs | 12 +-- .../typeck/autoderef-with-param-env-error.rs | 2 +- tests/ui/typeck/issue-46112.rs | 2 +- tests/ui/typeck/issue-79040.rs | 2 +- tests/ui/typeck/issue-83693.rs | 2 +- tests/ui/typeck/no-type-for-node-ice.rs | 2 +- ...nfer-argument-types-two-region-pointers.rs | 2 +- .../ui/uninhabited/uninhabited-irrefutable.rs | 2 +- .../ui/unsafe-binders/lifetime-resolution.rs | 2 +- tests/ui/unsafe/unsafe-unstable-const-fn.rs | 2 +- .../issue-30276-feature-flagged.rs | 3 +- tests/ui/unsized-locals/issue-30276.rs | 3 +- tests/ui/use/use-keyword.rs | 4 +- tests/ui/use/use-mod/use-mod-2.rs | 4 +- .../variance-btree-invariant-types.rs | 32 ++++---- tests/ui/wf/issue-95665.rs | 2 +- tests/ui/wf/wf-normalization-sized.rs | 8 +- 370 files changed, 930 insertions(+), 928 deletions(-) diff --git a/tests/rustdoc-ui/invalid-syntax.rs b/tests/rustdoc-ui/invalid-syntax.rs index 42469da83761..3b60239df8dd 100644 --- a/tests/rustdoc-ui/invalid-syntax.rs +++ b/tests/rustdoc-ui/invalid-syntax.rs @@ -47,7 +47,7 @@ pub fn baz() {} /// /// Indented block end pub fn quux() {} -//~^^^^^ could not parse code block as Rust code +//~^^^^^ WARN could not parse code block as Rust code /// Unclosed fence /// diff --git a/tests/rustdoc-ui/issues/ice-generic-type-alias-105742.rs b/tests/rustdoc-ui/issues/ice-generic-type-alias-105742.rs index 89b55beaea18..73a68777c6d8 100644 --- a/tests/rustdoc-ui/issues/ice-generic-type-alias-105742.rs +++ b/tests/rustdoc-ui/issues/ice-generic-type-alias-105742.rs @@ -5,10 +5,10 @@ use std::ops::Index; pub fn next<'a, T>(s: &'a mut dyn SVec) { //~^ expected 1 lifetime argument //~| expected 1 generic argument - //~| the trait `SVec` is not dyn compatible + //~| ERROR the trait `SVec` is not dyn compatible //~| `SVec` is not dyn compatible - //~| missing generics for associated type `SVec::Item` - //~| missing generics for associated type `SVec::Item` + //~| ERROR missing generics for associated type `SVec::Item` + //~| ERROR missing generics for associated type `SVec::Item` let _ = s; } @@ -16,52 +16,52 @@ pub trait SVec: Index< ::Item, //~^ expected 1 lifetime argument //~| expected 1 generic argument - //~| missing generics for associated type `SVec::Item` - //~| missing generics for associated type `SVec::Item` - //~| missing generics for associated type `SVec::Item` - //~| missing generics for associated type `SVec::Item` - //~| missing generics for associated type `SVec::Item` - //~| missing generics for associated type `SVec::Item` - //~| missing generics for associated type `SVec::Item` - //~| missing generics for associated type `SVec::Item` + //~| ERROR missing generics for associated type `SVec::Item` + //~| ERROR missing generics for associated type `SVec::Item` + //~| ERROR missing generics for associated type `SVec::Item` + //~| ERROR missing generics for associated type `SVec::Item` + //~| ERROR missing generics for associated type `SVec::Item` + //~| ERROR missing generics for associated type `SVec::Item` + //~| ERROR missing generics for associated type `SVec::Item` + //~| ERROR missing generics for associated type `SVec::Item` Output = ::Item, //~^ expected 1 lifetime argument //~| expected 1 generic argument - //~| missing generics for associated type `SVec::Item` - //~| missing generics for associated type `SVec::Item` - //~| missing generics for associated type `SVec::Item` - //~| missing generics for associated type `SVec::Item` - //~| missing generics for associated type `SVec::Item` - //~| missing generics for associated type `SVec::Item` - //~| missing generics for associated type `SVec::Item` - //~| missing generics for associated type `SVec::Item` + //~| ERROR missing generics for associated type `SVec::Item` + //~| ERROR missing generics for associated type `SVec::Item` + //~| ERROR missing generics for associated type `SVec::Item` + //~| ERROR missing generics for associated type `SVec::Item` + //~| ERROR missing generics for associated type `SVec::Item` + //~| ERROR missing generics for associated type `SVec::Item` + //~| ERROR missing generics for associated type `SVec::Item` + //~| ERROR missing generics for associated type `SVec::Item` Output = ::Item> as SVec>::Item, //~^ expected 1 lifetime argument //~| expected 1 generic argument //~| expected 1 lifetime argument - //~| missing generics for associated type `SVec::Item` - //~| missing generics for associated type `SVec::Item` - //~| missing generics for associated type `SVec::Item` - //~| missing generics for associated type `SVec::Item` - //~| missing generics for associated type `SVec::Item` - //~| missing generics for associated type `SVec::Item` + //~| ERROR missing generics for associated type `SVec::Item` + //~| ERROR missing generics for associated type `SVec::Item` + //~| ERROR missing generics for associated type `SVec::Item` + //~| ERROR missing generics for associated type `SVec::Item` + //~| ERROR missing generics for associated type `SVec::Item` + //~| ERROR missing generics for associated type `SVec::Item` //~| expected 1 generic argument - //~| missing generics for associated type `SVec::Item` - //~| missing generics for associated type `SVec::Item` - //~| missing generics for associated type `SVec::Item` - //~| missing generics for associated type `SVec::Item` - //~| missing generics for associated type `SVec::Item` - //~| missing generics for associated type `SVec::Item` - //~| missing generics for associated type `SVec::Item` - //~| missing generics for associated type `SVec::Item` - //~| missing generics for associated type `SVec::Item` - //~| missing generics for associated type `SVec::Item` + //~| ERROR missing generics for associated type `SVec::Item` + //~| ERROR missing generics for associated type `SVec::Item` + //~| ERROR missing generics for associated type `SVec::Item` + //~| ERROR missing generics for associated type `SVec::Item` + //~| ERROR missing generics for associated type `SVec::Item` + //~| ERROR missing generics for associated type `SVec::Item` + //~| ERROR missing generics for associated type `SVec::Item` + //~| ERROR missing generics for associated type `SVec::Item` + //~| ERROR missing generics for associated type `SVec::Item` + //~| ERROR missing generics for associated type `SVec::Item` > { type Item<'a, T>; fn len(&self) -> ::Item; //~^ expected 1 lifetime argument - //~| missing generics for associated type `SVec::Item` + //~| ERROR missing generics for associated type `SVec::Item` //~| expected 1 generic argument - //~| missing generics for associated type `SVec::Item` + //~| ERROR missing generics for associated type `SVec::Item` } diff --git a/tests/rustdoc-ui/issues/ice-typeof-102986.rs b/tests/rustdoc-ui/issues/ice-typeof-102986.rs index 8fcbfffe1724..b1ad19cb9ff4 100644 --- a/tests/rustdoc-ui/issues/ice-typeof-102986.rs +++ b/tests/rustdoc-ui/issues/ice-typeof-102986.rs @@ -1,5 +1,5 @@ // https://github.com/rust-lang/rust/issues/102986 struct Struct { y: (typeof("hey"),), - //~^ `typeof` is a reserved keyword but unimplemented + //~^ ERROR `typeof` is a reserved keyword but unimplemented } diff --git a/tests/ui-fulldeps/hash-stable-is-unstable.rs b/tests/ui-fulldeps/hash-stable-is-unstable.rs index a4b8533eb045..7f62b6044104 100644 --- a/tests/ui-fulldeps/hash-stable-is-unstable.rs +++ b/tests/ui-fulldeps/hash-stable-is-unstable.rs @@ -1,24 +1,24 @@ //@ compile-flags: -Zdeduplicate-diagnostics=yes extern crate rustc_data_structures; -//~^ use of unstable library feature `rustc_private` +//~^ ERROR use of unstable library feature `rustc_private` //~| NOTE: issue #27812 for more information //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date extern crate rustc_macros; -//~^ use of unstable library feature `rustc_private` +//~^ ERROR use of unstable library feature `rustc_private` //~| NOTE: see issue #27812 for more information //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date extern crate rustc_query_system; -//~^ use of unstable library feature `rustc_private` +//~^ ERROR use of unstable library feature `rustc_private` //~| NOTE: see issue #27812 for more information //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date use rustc_macros::HashStable; -//~^ use of unstable library feature `rustc_private` +//~^ ERROR use of unstable library feature `rustc_private` //~| NOTE: see issue #27812 for more information //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date #[derive(HashStable)] -//~^ use of unstable library feature `rustc_private` +//~^ ERROR use of unstable library feature `rustc_private` //~| NOTE: in this expansion of #[derive(HashStable)] //~| NOTE: in this expansion of #[derive(HashStable)] //~| NOTE: in this expansion of #[derive(HashStable)] diff --git a/tests/ui-fulldeps/try-from-u32/errors.rs b/tests/ui-fulldeps/try-from-u32/errors.rs index 0470063312cb..a25069c0a53c 100644 --- a/tests/ui-fulldeps/try-from-u32/errors.rs +++ b/tests/ui-fulldeps/try-from-u32/errors.rs @@ -8,17 +8,17 @@ extern crate rustc_macros; use rustc_macros::TryFromU32; #[derive(TryFromU32)] -struct MyStruct {} //~ type is not an enum +struct MyStruct {} //~ ERROR type is not an enum #[derive(TryFromU32)] enum NonTrivial { A, B(), C {}, - D(bool), //~ enum variant cannot have fields - E(bool, bool), //~ enum variant cannot have fields - F { x: bool }, //~ enum variant cannot have fields - G { x: bool, y: bool }, //~ enum variant cannot have fields + D(bool), //~ ERROR enum variant cannot have fields + E(bool, bool), //~ ERROR enum variant cannot have fields + F { x: bool }, //~ ERROR enum variant cannot have fields + G { x: bool, y: bool }, //~ ERROR enum variant cannot have fields } fn main() {} diff --git a/tests/ui/abi/simd-abi-checks-avx.rs b/tests/ui/abi/simd-abi-checks-avx.rs index fa4b3ba3054f..c31af6460fc8 100644 --- a/tests/ui/abi/simd-abi-checks-avx.rs +++ b/tests/ui/abi/simd-abi-checks-avx.rs @@ -14,19 +14,19 @@ use std::arch::x86_64::*; struct Wrapper(__m256); unsafe extern "C" fn w(_: Wrapper) { - //~^ requires the `avx` target feature, which is not enabled + //~^ WARN requires the `avx` target feature, which is not enabled //~| WARNING this was previously accepted by the compiler todo!() } unsafe extern "C" fn f(_: __m256) { - //~^ requires the `avx` target feature, which is not enabled + //~^ WARN requires the `avx` target feature, which is not enabled //~| WARNING this was previously accepted by the compiler todo!() } unsafe extern "C" fn g() -> __m256 { - //~^ requires the `avx` target feature, which is not enabled + //~^ WARN requires the `avx` target feature, which is not enabled //~| WARNING this was previously accepted by the compiler todo!() } diff --git a/tests/ui/abi/simd-abi-checks-empty-list.rs b/tests/ui/abi/simd-abi-checks-empty-list.rs index ca0889364fc3..ba1b38af5b34 100644 --- a/tests/ui/abi/simd-abi-checks-empty-list.rs +++ b/tests/ui/abi/simd-abi-checks-empty-list.rs @@ -14,5 +14,5 @@ use minicore::*; pub struct SimdVec([i32; 4]); pub extern "C" fn pass_by_vec(_: SimdVec) {} -//~^ this function definition uses SIMD vector type `SimdVec` which is not currently supported with the chosen ABI +//~^ WARN this function definition uses SIMD vector type `SimdVec` which is not currently supported with the chosen ABI //~| WARNING this was previously accepted by the compiler diff --git a/tests/ui/abi/simd-abi-checks-sse.rs b/tests/ui/abi/simd-abi-checks-sse.rs index cb708bea3cae..d5fa9c0c0a3c 100644 --- a/tests/ui/abi/simd-abi-checks-sse.rs +++ b/tests/ui/abi/simd-abi-checks-sse.rs @@ -18,6 +18,6 @@ pub struct SseVector([i64; 2]); #[no_mangle] pub unsafe extern "C" fn f(_: SseVector) { - //~^ this function definition uses SIMD vector type `SseVector` which (with the chosen ABI) requires the `sse` target feature, which is not enabled + //~^ WARN this function definition uses SIMD vector type `SseVector` which (with the chosen ABI) requires the `sse` target feature, which is not enabled //~| WARNING this was previously accepted by the compiler } diff --git a/tests/ui/abi/vectorcall-abi-checks.rs b/tests/ui/abi/vectorcall-abi-checks.rs index d83bbffa745f..f3f399e0e313 100644 --- a/tests/ui/abi/vectorcall-abi-checks.rs +++ b/tests/ui/abi/vectorcall-abi-checks.rs @@ -11,11 +11,11 @@ use minicore::*; #[no_mangle] pub extern "vectorcall" fn f() { - //~^ ABI "vectorcall" which requires the `sse2` target feature + //~^ ERROR ABI "vectorcall" which requires the `sse2` target feature } #[no_mangle] pub fn call_site() { f(); - //~^ ABI "vectorcall" which requires the `sse2` target feature + //~^ ERROR ABI "vectorcall" which requires the `sse2` target feature } diff --git a/tests/ui/anon-params/anon-params-denied-2018.rs b/tests/ui/anon-params/anon-params-denied-2018.rs index 3602b401f857..d9d4363a6816 100644 --- a/tests/ui/anon-params/anon-params-denied-2018.rs +++ b/tests/ui/anon-params/anon-params-denied-2018.rs @@ -3,7 +3,7 @@ //@ edition:2018 trait T { - fn foo(i32); //~ expected one of `:`, `@`, or `|`, found `)` + fn foo(i32); //~ ERROR expected one of `:`, `@`, or `|`, found `)` // Also checks with `&` fn foo_with_ref(&mut i32); diff --git a/tests/ui/argument-suggestions/issue-100478.rs b/tests/ui/argument-suggestions/issue-100478.rs index fb50fa115376..b0a9703112e3 100644 --- a/tests/ui/argument-suggestions/issue-100478.rs +++ b/tests/ui/argument-suggestions/issue-100478.rs @@ -45,7 +45,7 @@ fn main() { let p8 = Arc::default(); foo( - //~^ 47:5: 47:8: this function takes 8 arguments but 7 arguments were supplied [E0061] + //~^ ERROR this function takes 8 arguments but 7 arguments were supplied [E0061] p1, //p2, p3, p4, p5, p6, p7, p8, ); diff --git a/tests/ui/argument-suggestions/issue-101097.rs b/tests/ui/argument-suggestions/issue-101097.rs index 25f7f5837992..9b1565fef6ff 100644 --- a/tests/ui/argument-suggestions/issue-101097.rs +++ b/tests/ui/argument-suggestions/issue-101097.rs @@ -15,7 +15,7 @@ fn f( fn main() { f(C, A, A, A, B, B, C); //~ ERROR function takes 6 arguments but 7 arguments were supplied [E0061] f(C, C, A, A, B, B); //~ ERROR arguments to this function are incorrect [E0308] - f(A, A, D, D, B, B); //~ arguments to this function are incorrect [E0308] - f(C, C, B, B, A, A); //~ arguments to this function are incorrect [E0308] - f(C, C, A, B, A, A); //~ arguments to this function are incorrect [E0308] + f(A, A, D, D, B, B); //~ ERROR arguments to this function are incorrect [E0308] + f(C, C, B, B, A, A); //~ ERROR arguments to this function are incorrect [E0308] + f(C, C, A, B, A, A); //~ ERROR arguments to this function are incorrect [E0308] } diff --git a/tests/ui/array-slice-vec/array_const_index-0.rs b/tests/ui/array-slice-vec/array_const_index-0.rs index 96755802ec7f..f4fe89a50c25 100644 --- a/tests/ui/array-slice-vec/array_const_index-0.rs +++ b/tests/ui/array-slice-vec/array_const_index-0.rs @@ -1,6 +1,6 @@ const A: &'static [i32] = &[]; const B: i32 = (&A)[1]; -//~^ index out of bounds: the length is 0 but the index is 1 +//~^ NOTE index out of bounds: the length is 0 but the index is 1 //~| ERROR evaluation of constant value failed fn main() { diff --git a/tests/ui/array-slice-vec/array_const_index-1.rs b/tests/ui/array-slice-vec/array_const_index-1.rs index 625bf06a745e..0d4de137a6e0 100644 --- a/tests/ui/array-slice-vec/array_const_index-1.rs +++ b/tests/ui/array-slice-vec/array_const_index-1.rs @@ -1,6 +1,6 @@ const A: [i32; 0] = []; const B: i32 = A[1]; -//~^ index out of bounds: the length is 0 but the index is 1 +//~^ NOTE index out of bounds: the length is 0 but the index is 1 //~| ERROR evaluation of constant value failed fn main() { diff --git a/tests/ui/asm/issue-85247.rs b/tests/ui/asm/issue-85247.rs index 47bfda14092d..f54c868dd561 100644 --- a/tests/ui/asm/issue-85247.rs +++ b/tests/ui/asm/issue-85247.rs @@ -18,6 +18,6 @@ use minicore::*; fn main() { unsafe { asm!("", out("r9") _); - //[rwpi]~^ cannot use register `r9` + //[rwpi]~^ ERROR cannot use register `r9` } } diff --git a/tests/ui/asm/issue-99071.rs b/tests/ui/asm/issue-99071.rs index 6a00fce7de46..522ac1fe8877 100644 --- a/tests/ui/asm/issue-99071.rs +++ b/tests/ui/asm/issue-99071.rs @@ -13,6 +13,6 @@ use minicore::*; pub fn foo() { unsafe { asm!("", in("r8") 0); - //~^ cannot use register `r8`: high registers (r8+) can only be used as clobbers in Thumb-1 code + //~^ ERROR cannot use register `r8`: high registers (r8+) can only be used as clobbers in Thumb-1 code } } diff --git a/tests/ui/asm/type-check-4.rs b/tests/ui/asm/type-check-4.rs index a5b5e29294bb..97b1ab74a7ec 100644 --- a/tests/ui/asm/type-check-4.rs +++ b/tests/ui/asm/type-check-4.rs @@ -11,7 +11,7 @@ fn main() { let mut a = 0isize; let p = &a; asm!("{}", out(reg) a); - //~^ cannot assign to `a` because it is borrowed + //~^ ERROR cannot assign to `a` because it is borrowed println!("{}", p); // Can't read from mutable borrowed values. @@ -19,7 +19,7 @@ fn main() { let mut a = 0isize; let p = &mut a; asm!("{}", in(reg) a); - //~^ cannot use `a` because it was mutably borrowed + //~^ ERROR cannot use `a` because it was mutably borrowed println!("{}", p); } } diff --git a/tests/ui/asm/x86_64/issue-82869.rs b/tests/ui/asm/x86_64/issue-82869.rs index 5d3f417f7337..448ebd9c99f4 100644 --- a/tests/ui/asm/x86_64/issue-82869.rs +++ b/tests/ui/asm/x86_64/issue-82869.rs @@ -12,9 +12,9 @@ pub unsafe fn aarch64(a: f64, b: f64) -> f64 { || {}; b }); - //~^^^^ invalid register class - //~^^^^^ invalid register class - //~^^^^^^ invalid register + //~^^^^ ERROR invalid register class + //~^^^^^ ERROR invalid register class + //~^^^^^^ ERROR invalid register c } diff --git a/tests/ui/associated-consts/defaults-cyclic-fail.rs b/tests/ui/associated-consts/defaults-cyclic-fail.rs index b868ef310041..cc3b60b30e5d 100644 --- a/tests/ui/associated-consts/defaults-cyclic-fail.rs +++ b/tests/ui/associated-consts/defaults-cyclic-fail.rs @@ -3,7 +3,7 @@ // Cyclic assoc. const defaults don't error unless *used* trait Tr { const A: u8 = Self::B; - //~^ cycle detected + //~^ ERROR cycle detected const B: u8 = Self::A; } diff --git a/tests/ui/associated-inherent-types/generic-associated-types-bad.rs b/tests/ui/associated-inherent-types/generic-associated-types-bad.rs index fdc2a0f64e49..fd3281cefeef 100644 --- a/tests/ui/associated-inherent-types/generic-associated-types-bad.rs +++ b/tests/ui/associated-inherent-types/generic-associated-types-bad.rs @@ -13,8 +13,8 @@ impl Ty { } #[cfg(item)] -const _: Ty::Pr = String::new(); //[item]~ the trait bound `String: Copy` is not satisfied -//[item]~^ the trait bound `String: Copy` is not satisfied +const _: Ty::Pr = String::new(); //[item]~ ERROR the trait bound `String: Copy` is not satisfied +//[item]~^ ERROR the trait bound `String: Copy` is not satisfied fn main() { #[cfg(local)] diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-missing.rs b/tests/ui/associated-type-bounds/return-type-notation/path-missing.rs index 8cab48bd0c45..1ad02f754db5 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/path-missing.rs +++ b/tests/ui/associated-type-bounds/return-type-notation/path-missing.rs @@ -17,7 +17,7 @@ where fn type_dependent() where T::method(..): Send, - //~^ associated function `method` not found for `T` + //~^ ERROR associated function `method` not found for `T` { } diff --git a/tests/ui/associated-types/hr-associated-type-bound-2.rs b/tests/ui/associated-types/hr-associated-type-bound-2.rs index a89f61a81a57..467400f4b800 100644 --- a/tests/ui/associated-types/hr-associated-type-bound-2.rs +++ b/tests/ui/associated-types/hr-associated-type-bound-2.rs @@ -8,7 +8,7 @@ where } } -impl X<'_> for u32 //~ overflow evaluating the requirement `for<'b> u32: X<'b>` +impl X<'_> for u32 //~ ERROR overflow evaluating the requirement `for<'b> u32: X<'b>` where for<'b> >::U: Clone, { diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-2.rs b/tests/ui/associated-types/hr-associated-type-bound-param-2.rs index 673f02c7cd0e..d6546c24dc50 100644 --- a/tests/ui/associated-types/hr-associated-type-bound-param-2.rs +++ b/tests/ui/associated-types/hr-associated-type-bound-param-2.rs @@ -1,16 +1,16 @@ trait Z<'a, T: ?Sized> where T: Z<'a, u16>, - //~^ the trait bound `str: Clone` is not satisfied - //~| the trait bound `str: Clone` is not satisfied + //~^ ERROR the trait bound `str: Clone` is not satisfied + //~| ERROR the trait bound `str: Clone` is not satisfied for<'b> >::W: Clone, { type W: ?Sized; fn h(&self, x: &T::W) { ::clone(x); - //~^ the trait bound `str: Clone` is not satisfied - //~| the trait bound `str: Clone` is not satisfied - //~| the trait bound `str: Clone` is not satisfied + //~^ ERROR the trait bound `str: Clone` is not satisfied + //~| ERROR the trait bound `str: Clone` is not satisfied + //~| ERROR the trait bound `str: Clone` is not satisfied } } diff --git a/tests/ui/associated-types/hr-associated-type-projection-1.rs b/tests/ui/associated-types/hr-associated-type-projection-1.rs index d7fc5d122c3e..1d272a660446 100644 --- a/tests/ui/associated-types/hr-associated-type-projection-1.rs +++ b/tests/ui/associated-types/hr-associated-type-projection-1.rs @@ -12,10 +12,10 @@ where impl UnsafeCopy<'_, T> for T { type Item = T; - //~^ type mismatch resolving `::Target == T` + //~^ ERROR type mismatch resolving `::Target == T` } pub fn main() { <&'static str>::bug(&""); - //~^ type mismatch resolving `<&str as Deref>::Target == &str` + //~^ ERROR type mismatch resolving `<&str as Deref>::Target == &str` } diff --git a/tests/ui/associated-types/issue-85103-layout-debug.rs b/tests/ui/associated-types/issue-85103-layout-debug.rs index 77c9876ffa57..29a59924ef08 100644 --- a/tests/ui/associated-types/issue-85103-layout-debug.rs +++ b/tests/ui/associated-types/issue-85103-layout-debug.rs @@ -4,6 +4,6 @@ use std::borrow::Cow; #[rustc_layout(debug)] type Edges<'a, E> = Cow<'a, [E]>; -//~^ the trait bound `[E]: ToOwned` is not satisfied +//~^ ERROR the trait bound `[E]: ToOwned` is not satisfied fn main() {} diff --git a/tests/ui/associated-types/remove-invalid-type-bound-suggest-issue-127555.rs b/tests/ui/associated-types/remove-invalid-type-bound-suggest-issue-127555.rs index 4dfeab9e8c3f..70685504cccc 100644 --- a/tests/ui/associated-types/remove-invalid-type-bound-suggest-issue-127555.rs +++ b/tests/ui/associated-types/remove-invalid-type-bound-suggest-issue-127555.rs @@ -13,7 +13,7 @@ impl Foo for Baz { async fn bar(&mut self, _func: F) -> () where F: FnMut() + Send, - //~^ impl has stricter requirements than trait + //~^ ERROR impl has stricter requirements than trait { () } diff --git a/tests/ui/async-await/drop-track-field-assign-nonsend.rs b/tests/ui/async-await/drop-track-field-assign-nonsend.rs index 7002836ee47f..2b93f9013767 100644 --- a/tests/ui/async-await/drop-track-field-assign-nonsend.rs +++ b/tests/ui/async-await/drop-track-field-assign-nonsend.rs @@ -40,5 +40,5 @@ fn main() { let agent = Agent { info_result: InfoResult { node: None } }; // FIXME: It would be nice for this to work. See #94067. assert_send(agent.handle()); - //~^ cannot be sent between threads safely + //~^ ERROR cannot be sent between threads safely } diff --git a/tests/ui/async-await/field-assign-nonsend.rs b/tests/ui/async-await/field-assign-nonsend.rs index 7002836ee47f..2b93f9013767 100644 --- a/tests/ui/async-await/field-assign-nonsend.rs +++ b/tests/ui/async-await/field-assign-nonsend.rs @@ -40,5 +40,5 @@ fn main() { let agent = Agent { info_result: InfoResult { node: None } }; // FIXME: It would be nice for this to work. See #94067. assert_send(agent.handle()); - //~^ cannot be sent between threads safely + //~^ ERROR cannot be sent between threads safely } diff --git a/tests/ui/async-await/suggest-missing-await.rs b/tests/ui/async-await/suggest-missing-await.rs index 0bd67cec335b..989792825cf8 100644 --- a/tests/ui/async-await/suggest-missing-await.rs +++ b/tests/ui/async-await/suggest-missing-await.rs @@ -43,7 +43,7 @@ async fn suggest_await_on_previous_match_arms() { 0 => dummy(), //~ HELP consider `await`ing on the `Future` 1 => dummy(), 2 => dummy().await, - //~^ `match` arms have incompatible types [E0308] + //~^ ERROR `match` arms have incompatible types [E0308] }; } diff --git a/tests/ui/attributes/issue-90873.rs b/tests/ui/attributes/issue-90873.rs index 53339ce7e28f..50336e04c888 100644 --- a/tests/ui/attributes/issue-90873.rs +++ b/tests/ui/attributes/issue-90873.rs @@ -1,7 +1,7 @@ #![u=||{static d=||1;}] -//~^ attribute value must be a literal -//~| cannot find attribute `u` in this scope -//~| missing type for `static` item +//~^ ERROR attribute value must be a literal +//~| ERROR cannot find attribute `u` in this scope +//~| ERROR missing type for `static` item #![a={impl std::ops::Neg for i8 {}}] //~^ ERROR attribute value must be a literal diff --git a/tests/ui/attributes/used_with_multi_args.rs b/tests/ui/attributes/used_with_multi_args.rs index 2e17fcfd7a49..d3109cc64442 100644 --- a/tests/ui/attributes/used_with_multi_args.rs +++ b/tests/ui/attributes/used_with_multi_args.rs @@ -1,6 +1,6 @@ #![feature(used_with_arg)] -#[used(compiler, linker)] //~ expected `used`, `used(compiler)` or `used(linker)` +#[used(compiler, linker)] //~ ERROR expected `used`, `used(compiler)` or `used(linker)` static mut USED_COMPILER_LINKER: [usize; 1] = [0]; fn main() {} diff --git a/tests/ui/augmented-assignments.rs b/tests/ui/augmented-assignments.rs index 440a4a7fd650..35ab2d454f7b 100644 --- a/tests/ui/augmented-assignments.rs +++ b/tests/ui/augmented-assignments.rs @@ -16,13 +16,13 @@ fn main() { += x; //~^ ERROR cannot move out of `x` because it is borrowed - //~| move out of `x` occurs here + //~| NOTE move out of `x` occurs here let y = Int(2); //~^ HELP consider changing this to be mutable //~| SUGGESTION mut y //~ ERROR cannot borrow `y` as mutable, as it is not declared as mutable - //~| cannot borrow as mutable + //~| NOTE cannot borrow as mutable += Int(1); } diff --git a/tests/ui/auto-traits/auto-trait-validation.fixed b/tests/ui/auto-traits/auto-trait-validation.fixed index f65952e00f58..8a445448c858 100644 --- a/tests/ui/auto-traits/auto-trait-validation.fixed +++ b/tests/ui/auto-traits/auto-trait-validation.fixed @@ -4,11 +4,11 @@ //@ run-rustfix auto trait Generic {} -//~^ auto traits cannot have generic parameters [E0567] +//~^ ERROR auto traits cannot have generic parameters [E0567] auto trait Bound {} -//~^ auto traits cannot have super traits or lifetime bounds [E0568] +//~^ ERROR auto traits cannot have super traits or lifetime bounds [E0568] auto trait LifetimeBound {} -//~^ auto traits cannot have super traits or lifetime bounds [E0568] +//~^ ERROR auto traits cannot have super traits or lifetime bounds [E0568] auto trait MyTrait { } -//~^ auto traits cannot have associated items [E0380] +//~^ ERROR auto traits cannot have associated items [E0380] fn main() {} diff --git a/tests/ui/auto-traits/auto-trait-validation.rs b/tests/ui/auto-traits/auto-trait-validation.rs index c83d7426e47c..b5e7505d86a2 100644 --- a/tests/ui/auto-traits/auto-trait-validation.rs +++ b/tests/ui/auto-traits/auto-trait-validation.rs @@ -4,11 +4,11 @@ //@ run-rustfix auto trait Generic {} -//~^ auto traits cannot have generic parameters [E0567] +//~^ ERROR auto traits cannot have generic parameters [E0567] auto trait Bound : Copy {} -//~^ auto traits cannot have super traits or lifetime bounds [E0568] +//~^ ERROR auto traits cannot have super traits or lifetime bounds [E0568] auto trait LifetimeBound : 'static {} -//~^ auto traits cannot have super traits or lifetime bounds [E0568] +//~^ ERROR auto traits cannot have super traits or lifetime bounds [E0568] auto trait MyTrait { fn foo() {} } -//~^ auto traits cannot have associated items [E0380] +//~^ ERROR auto traits cannot have associated items [E0380] fn main() {} diff --git a/tests/ui/borrowck/borrowck-fn-in-const-c.rs b/tests/ui/borrowck/borrowck-fn-in-const-c.rs index c638cd08bc9a..3cabedfe994c 100644 --- a/tests/ui/borrowck/borrowck-fn-in-const-c.rs +++ b/tests/ui/borrowck/borrowck-fn-in-const-c.rs @@ -14,7 +14,7 @@ impl Drop for DropString { const LOCAL_REF: fn() -> &'static str = { fn broken() -> &'static str { let local = DropString { inner: format!("Some local string") }; - return &local.inner; //~ borrow may still be in use when destructor runs + return &local.inner; //~ ERROR borrow may still be in use when destructor runs } broken }; diff --git a/tests/ui/borrowck/borrowck-vec-pattern-nesting.rs b/tests/ui/borrowck/borrowck-vec-pattern-nesting.rs index ec074d2cf1c9..400e5f010ecb 100644 --- a/tests/ui/borrowck/borrowck-vec-pattern-nesting.rs +++ b/tests/ui/borrowck/borrowck-vec-pattern-nesting.rs @@ -19,7 +19,7 @@ fn b() { let vec: &mut [Box] = &mut vec; match vec { &mut [ref _b @ ..] => { - //~^ `vec[_]` is borrowed here + //~^ NOTE `vec[_]` is borrowed here vec[0] = Box::new(4); //~ ERROR cannot assign //~^ NOTE `vec[_]` is assigned to here _b.use_ref(); diff --git a/tests/ui/borrowck/issue-36082.fixed b/tests/ui/borrowck/issue-36082.fixed index 2209c56048e4..9ac89b016071 100644 --- a/tests/ui/borrowck/issue-36082.fixed +++ b/tests/ui/borrowck/issue-36082.fixed @@ -13,5 +13,5 @@ fn main() { //~| NOTE creates a temporary value which is freed while still in use //~| HELP consider using a `let` binding to create a longer lived value println!("{}", val); - //~^ borrow later used here + //~^ NOTE borrow later used here } diff --git a/tests/ui/borrowck/issue-36082.rs b/tests/ui/borrowck/issue-36082.rs index da8b0068882b..f2f769ea1c3a 100644 --- a/tests/ui/borrowck/issue-36082.rs +++ b/tests/ui/borrowck/issue-36082.rs @@ -12,5 +12,5 @@ fn main() { //~| NOTE creates a temporary value which is freed while still in use //~| HELP consider using a `let` binding to create a longer lived value println!("{}", val); - //~^ borrow later used here + //~^ NOTE borrow later used here } diff --git a/tests/ui/borrowck/two-phase-multi-mut.rs b/tests/ui/borrowck/two-phase-multi-mut.rs index bb646d7caf1e..8ff924ccc2a8 100644 --- a/tests/ui/borrowck/two-phase-multi-mut.rs +++ b/tests/ui/borrowck/two-phase-multi-mut.rs @@ -9,6 +9,6 @@ impl Foo { fn main() { let mut foo = Foo { }; foo.method(&mut foo); - //~^ cannot borrow `foo` as mutable more than once at a time - //~^^ cannot borrow `foo` as mutable more than once at a time + //~^ ERROR cannot borrow `foo` as mutable more than once at a time + //~^^ ERROR cannot borrow `foo` as mutable more than once at a time } diff --git a/tests/ui/closures/2229_closure_analysis/by_value.rs b/tests/ui/closures/2229_closure_analysis/by_value.rs index 2c9202fd6172..605b8ea35e51 100644 --- a/tests/ui/closures/2229_closure_analysis/by_value.rs +++ b/tests/ui/closures/2229_closure_analysis/by_value.rs @@ -20,8 +20,8 @@ fn big_box() { //~| NOTE: see issue #15701 //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date || { - //~^ First Pass analysis includes: - //~| Min Capture analysis includes: + //~^ ERROR First Pass analysis includes: + //~| ERROR Min Capture analysis includes: let p = t.0.0; //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue //~| NOTE: Min Capture t[(0, 0)] -> ByValue diff --git a/tests/ui/closures/2229_closure_analysis/capture-analysis-1.rs b/tests/ui/closures/2229_closure_analysis/capture-analysis-1.rs index 0c42e66a2faf..3eb5cef30056 100644 --- a/tests/ui/closures/2229_closure_analysis/capture-analysis-1.rs +++ b/tests/ui/closures/2229_closure_analysis/capture-analysis-1.rs @@ -17,8 +17,8 @@ fn main() { //~| NOTE: see issue #15701 //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date || { - //~^ First Pass analysis includes: - //~| Min Capture analysis includes: + //~^ ERROR First Pass analysis includes: + //~| ERROR Min Capture analysis includes: println!("{:?}", p); //~^ NOTE: Capturing p[] -> Immutable //~| NOTE: Min Capture p[] -> Immutable diff --git a/tests/ui/closures/2229_closure_analysis/capture-analysis-2.rs b/tests/ui/closures/2229_closure_analysis/capture-analysis-2.rs index adb618d1771e..e6cda8248093 100644 --- a/tests/ui/closures/2229_closure_analysis/capture-analysis-2.rs +++ b/tests/ui/closures/2229_closure_analysis/capture-analysis-2.rs @@ -16,8 +16,8 @@ fn main() { //~| NOTE: see issue #15701 //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date || { - //~^ First Pass analysis includes: - //~| Min Capture analysis includes: + //~^ ERROR First Pass analysis includes: + //~| ERROR Min Capture analysis includes: let _x = p.x; //~^ NOTE: Capturing p[(0, 0)] -> ByValue //~| NOTE: p[] captured as ByValue here diff --git a/tests/ui/closures/2229_closure_analysis/capture-analysis-3.rs b/tests/ui/closures/2229_closure_analysis/capture-analysis-3.rs index 0a21eaaaa121..b25b613b61c0 100644 --- a/tests/ui/closures/2229_closure_analysis/capture-analysis-3.rs +++ b/tests/ui/closures/2229_closure_analysis/capture-analysis-3.rs @@ -21,8 +21,8 @@ fn main() { //~| NOTE: see issue #15701 //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date || { - //~^ First Pass analysis includes: - //~| Min Capture analysis includes: + //~^ ERROR First Pass analysis includes: + //~| ERROR Min Capture analysis includes: let _x = a.b.c; //~^ NOTE: Capturing a[(0, 0),(0, 0)] -> ByValue //~| NOTE: a[(0, 0)] captured as ByValue here diff --git a/tests/ui/closures/2229_closure_analysis/capture-analysis-4.rs b/tests/ui/closures/2229_closure_analysis/capture-analysis-4.rs index 790dad0710bc..355e36c1463b 100644 --- a/tests/ui/closures/2229_closure_analysis/capture-analysis-4.rs +++ b/tests/ui/closures/2229_closure_analysis/capture-analysis-4.rs @@ -21,8 +21,8 @@ fn main() { //~| NOTE: see issue #15701 //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date || { - //~^ First Pass analysis includes: - //~| Min Capture analysis includes: + //~^ ERROR First Pass analysis includes: + //~| ERROR Min Capture analysis includes: let _x = a.b; //~^ NOTE: Capturing a[(0, 0)] -> ByValue //~| NOTE: Min Capture a[(0, 0)] -> ByValue diff --git a/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.rs b/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.rs index af12e0b259d9..52f0dcba6bee 100644 --- a/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.rs +++ b/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.rs @@ -15,8 +15,8 @@ fn main() { //~| NOTE: see issue #15701 //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date || { - //~^ First Pass analysis includes: - //~| Min Capture analysis includes: + //~^ ERROR First Pass analysis includes: + //~| ERROR Min Capture analysis includes: println!("{}", p.x); //~^ NOTE: Capturing p[(0, 0)] -> Immutable //~| NOTE: Min Capture p[(0, 0)] -> Immutable diff --git a/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.rs b/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.rs index ccd260492643..bac79ad2860f 100644 --- a/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.rs +++ b/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.rs @@ -10,8 +10,8 @@ fn main() { //~| NOTE: see issue #15701 //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date || { - //~^ First Pass analysis includes: - //~| Min Capture analysis includes: + //~^ ERROR First Pass analysis includes: + //~| ERROR Min Capture analysis includes: println!("{}", t.0); //~^ NOTE: Capturing t[(0, 0)] -> Immutable //~| NOTE: Min Capture t[(0, 0)] -> Immutable diff --git a/tests/ui/closures/2229_closure_analysis/capture-enums.rs b/tests/ui/closures/2229_closure_analysis/capture-enums.rs index b1e21bd0f8d6..d9c06a68c95b 100644 --- a/tests/ui/closures/2229_closure_analysis/capture-enums.rs +++ b/tests/ui/closures/2229_closure_analysis/capture-enums.rs @@ -18,8 +18,8 @@ fn multi_variant_enum() { //~| NOTE: see issue #15701 //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date || { - //~^ First Pass analysis includes: - //~| Min Capture analysis includes: + //~^ ERROR First Pass analysis includes: + //~| ERROR Min Capture analysis includes: if let Info::Point(_, _, str) = point { //~^ NOTE: Capturing point[] -> Immutable //~| NOTE: Capturing point[(2, 0)] -> ByValue @@ -50,8 +50,8 @@ fn single_variant_enum() { //~| NOTE: see issue #15701 //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date || { - //~^ First Pass analysis includes: - //~| Min Capture analysis includes: + //~^ ERROR First Pass analysis includes: + //~| ERROR Min Capture analysis includes: let SingleVariant::Point(_, _, str) = point; //~^ NOTE: Capturing point[(2, 0)] -> ByValue //~| NOTE: Min Capture point[(2, 0)] -> ByValue diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/union.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/union.rs index 647005bc1c97..c036712381ce 100644 --- a/tests/ui/closures/2229_closure_analysis/diagnostics/union.rs +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/union.rs @@ -11,15 +11,15 @@ union A { fn main() { let mut a = A { y: 1 }; let mut c = || { - //~^ `a.y` is borrowed here + //~^ NOTE `a.y` is borrowed here let _ = unsafe { &a.y }; let _ = &mut a; - //~^ borrow occurs due to use in closure + //~^ NOTE borrow occurs due to use in closure let _ = unsafe { &mut a.y }; }; a.y = 1; - //~^ cannot assign to `a.y` because it is borrowed [E0506] - //~| `a.y` is assigned to here + //~^ ERROR cannot assign to `a.y` because it is borrowed [E0506] + //~| NOTE `a.y` is assigned to here c(); - //~^ borrow later used here + //~^ NOTE borrow later used here } diff --git a/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs index 9c7b70457d98..40330af4088c 100644 --- a/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs +++ b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs @@ -10,8 +10,8 @@ fn test_1_should_capture() { let variant = Some(2229); let c = #[rustc_capture_analysis] || { - //~^ First Pass analysis includes: - //~| Min Capture analysis includes: + //~^ ERROR First Pass analysis includes: + //~| ERROR Min Capture analysis includes: match variant { //~^ NOTE: Capturing variant[] -> Immutable //~| NOTE: Min Capture variant[] -> Immutable @@ -28,7 +28,7 @@ fn test_2_should_not_capture() { let variant = Some(2229); let c = #[rustc_capture_analysis] || { - //~^ First Pass analysis includes: + //~^ ERROR First Pass analysis includes: match variant { _ => {} } @@ -47,7 +47,7 @@ fn test_3_should_not_capture_single_variant() { let variant = SingleVariant::Points(1); let c = #[rustc_capture_analysis] || { - //~^ First Pass analysis includes: + //~^ ERROR First Pass analysis includes: match variant { SingleVariant::Points(_) => {} } @@ -61,8 +61,8 @@ fn test_6_should_capture_single_variant() { let variant = SingleVariant::Points(1); let c = #[rustc_capture_analysis] || { - //~^ First Pass analysis includes: - //~| Min Capture analysis includes: + //~^ ERROR First Pass analysis includes: + //~| ERROR Min Capture analysis includes: match variant { //~^ NOTE: Capturing variant[] -> Immutable //~| NOTE: Capturing variant[(0, 0)] -> Immutable @@ -81,7 +81,7 @@ fn test_4_should_not_capture_array() { let array: [i32; 3] = [0; 3]; let c = #[rustc_capture_analysis] || { - //~^ First Pass analysis includes: + //~^ ERROR First Pass analysis includes: match array { [_,_,_] => {} } @@ -93,7 +93,7 @@ fn test_4_should_not_capture_array() { let array: &[i32; 3] = &[0; 3]; let c = #[rustc_capture_analysis] || { - //~^ First Pass analysis includes: + //~^ ERROR First Pass analysis includes: match array { [_, _, _] => {} } @@ -106,7 +106,7 @@ fn test_4_should_not_capture_array() { let f = &Foo(&[10; 3]); let c = #[rustc_capture_analysis] || { - //~^ First Pass analysis includes: + //~^ ERROR First Pass analysis includes: match f { Foo([_, _, _]) => () } @@ -128,8 +128,8 @@ fn test_5_should_capture_multi_variant() { let variant = MVariant::A; let c = #[rustc_capture_analysis] || { - //~^ First Pass analysis includes: - //~| Min Capture analysis includes: + //~^ ERROR First Pass analysis includes: + //~| ERROR Min Capture analysis includes: match variant { //~^ NOTE: Capturing variant[] -> Immutable //~| NOTE: Min Capture variant[] -> Immutable @@ -146,8 +146,8 @@ fn test_7_should_capture_slice_len() { let slice: &[i32] = &[1, 2, 3]; let c = #[rustc_capture_analysis] || { - //~^ First Pass analysis includes: - //~| Min Capture analysis includes: + //~^ ERROR First Pass analysis includes: + //~| ERROR Min Capture analysis includes: match slice { //~^ NOTE: Capturing slice[] -> Immutable //~| NOTE: Min Capture slice[] -> Immutable @@ -158,8 +158,8 @@ fn test_7_should_capture_slice_len() { c(); let c = #[rustc_capture_analysis] || { - //~^ First Pass analysis includes: - //~| Min Capture analysis includes: + //~^ ERROR First Pass analysis includes: + //~| ERROR Min Capture analysis includes: match slice { //~^ NOTE: Capturing slice[] -> Immutable //~| NOTE: Min Capture slice[] -> Immutable @@ -170,8 +170,8 @@ fn test_7_should_capture_slice_len() { c(); let c = #[rustc_capture_analysis] || { - //~^ First Pass analysis includes: - //~| Min Capture analysis includes: + //~^ ERROR First Pass analysis includes: + //~| ERROR Min Capture analysis includes: match slice { //~^ NOTE: Capturing slice[] -> Immutable //~| NOTE: Min Capture slice[] -> Immutable @@ -187,7 +187,7 @@ fn test_8_capture_slice_wild() { let slice: &[i32] = &[1, 2, 3]; let c = #[rustc_capture_analysis] || { - //~^ First Pass analysis includes: + //~^ ERROR First Pass analysis includes: match slice { [..] => {}, _ => {} diff --git a/tests/ui/closures/2229_closure_analysis/move_closure.rs b/tests/ui/closures/2229_closure_analysis/move_closure.rs index b6690d060118..c681559f6190 100644 --- a/tests/ui/closures/2229_closure_analysis/move_closure.rs +++ b/tests/ui/closures/2229_closure_analysis/move_closure.rs @@ -181,9 +181,9 @@ fn box_mut_1() { //~^ ERROR: attributes on expressions are experimental //~| NOTE: see issue #15701 //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - //~| First Pass analysis includes: + //~| ERROR First Pass analysis includes: //~| NOTE: Capturing box_p_foo[Deref,Deref,(0, 0)] -> Mutable - //~| Min Capture analysis includes: + //~| ERROR Min Capture analysis includes: //~| NOTE: Min Capture box_p_foo[] -> ByValue } @@ -199,9 +199,9 @@ fn box_mut_2() { //~^ ERROR: attributes on expressions are experimental //~| NOTE: see issue #15701 //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - //~| First Pass analysis includes: + //~| ERROR First Pass analysis includes: //~| NOTE: Capturing p_foo[Deref,Deref,(0, 0)] -> Mutable - //~| Min Capture analysis includes: + //~| ERROR Min Capture analysis includes: //~| NOTE: Min Capture p_foo[] -> ByValue } @@ -213,9 +213,9 @@ fn returned_closure_owns_copy_type_data() -> impl Fn() -> i32 { //~^ ERROR: attributes on expressions are experimental //~| NOTE: see issue #15701 //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - //~| First Pass analysis includes: + //~| ERROR First Pass analysis includes: //~| NOTE: Capturing x[] -> Immutable - //~| Min Capture analysis includes: + //~| ERROR Min Capture analysis includes: //~| NOTE: Min Capture x[] -> ByValue c diff --git a/tests/ui/closures/binder/implicit-return.rs b/tests/ui/closures/binder/implicit-return.rs index d34e5721d919..9889d055a366 100644 --- a/tests/ui/closures/binder/implicit-return.rs +++ b/tests/ui/closures/binder/implicit-return.rs @@ -2,5 +2,5 @@ fn main() { let _f = for<'a> |_: &'a ()| {}; - //~^ implicit types in closure signatures are forbidden when `for<...>` is present + //~^ ERROR implicit types in closure signatures are forbidden when `for<...>` is present } diff --git a/tests/ui/closures/deduce-signature/obligation-with-leaking-placeholders.rs b/tests/ui/closures/deduce-signature/obligation-with-leaking-placeholders.rs index deb888ec2867..f8e3b14f9276 100644 --- a/tests/ui/closures/deduce-signature/obligation-with-leaking-placeholders.rs +++ b/tests/ui/closures/deduce-signature/obligation-with-leaking-placeholders.rs @@ -16,7 +16,7 @@ impl<'a, T> Foo<'a> for Wrap where T: Fn(&'a i32) {} fn main() { needs_foo(|x| { - //[current]~^ implementation of `Foo` is not general enough + //[current]~^ ERROR implementation of `Foo` is not general enough //[next]~^^ ERROR type annotations needed x.to_string(); }); diff --git a/tests/ui/closures/wrong-closure-arg-suggestion-125325.rs b/tests/ui/closures/wrong-closure-arg-suggestion-125325.rs index ce575697cf68..c72d19e84816 100644 --- a/tests/ui/closures/wrong-closure-arg-suggestion-125325.rs +++ b/tests/ui/closures/wrong-closure-arg-suggestion-125325.rs @@ -21,9 +21,9 @@ fn func(_f: impl Fn()) -> usize { fn test_func(s: &S) -> usize { let mut x = (); s.assoc_func(|| x = ()); - //~^ cannot assign to `x`, as it is a captured variable in a `Fn` closure + //~^ ERROR cannot assign to `x`, as it is a captured variable in a `Fn` closure func(|| x = ()) - //~^ cannot assign to `x`, as it is a captured variable in a `Fn` closure + //~^ ERROR cannot assign to `x`, as it is a captured variable in a `Fn` closure } fn main() {} diff --git a/tests/ui/coercion/coerce-reborrow-multi-arg-fail.rs b/tests/ui/coercion/coerce-reborrow-multi-arg-fail.rs index 48be2d3146b8..0a58f0897aae 100644 --- a/tests/ui/coercion/coerce-reborrow-multi-arg-fail.rs +++ b/tests/ui/coercion/coerce-reborrow-multi-arg-fail.rs @@ -2,5 +2,5 @@ fn test(_a: T, _b: T) {} fn main() { test(&mut 7, &7); - //~^ mismatched types + //~^ ERROR mismatched types } diff --git a/tests/ui/coercion/mut-mut-wont-coerce.rs b/tests/ui/coercion/mut-mut-wont-coerce.rs index e99566461a24..33016e1e48a8 100644 --- a/tests/ui/coercion/mut-mut-wont-coerce.rs +++ b/tests/ui/coercion/mut-mut-wont-coerce.rs @@ -33,7 +33,7 @@ fn make_foo(_: *mut *mut Foo) { fn main() { let mut result: SmartPtr = SmartPtr(std::ptr::null_mut()); - make_foo(&mut &mut *result); //~ mismatched types + make_foo(&mut &mut *result); //~ ERROR mismatched types //~^ expected `*mut *mut Foo`, found `&mut &mut Foo` make_foo(out(&mut result)); // works, but makes one wonder why above coercion cannot happen } diff --git a/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.rs b/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.rs index 3a283442a0b0..34ea143d2546 100644 --- a/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.rs +++ b/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.rs @@ -4,18 +4,18 @@ use std::marker::ConstParamTy; #[derive(ConstParamTy)] -//~^ the trait `ConstParamTy_` cannot be implemented for this ty -//~| the trait `ConstParamTy_` cannot be implemented for this ty +//~^ ERROR the trait `ConstParamTy_` cannot be implemented for this ty +//~| ERROR the trait `ConstParamTy_` cannot be implemented for this ty struct Foo([*const u8; 1]); #[derive(ConstParamTy)] -//~^ the trait `ConstParamTy_` cannot be implemented for this ty -//~| the trait `ConstParamTy_` cannot be implemented for this ty +//~^ ERROR the trait `ConstParamTy_` cannot be implemented for this ty +//~| ERROR the trait `ConstParamTy_` cannot be implemented for this ty struct Foo2([*mut u8; 1]); #[derive(ConstParamTy)] -//~^ the trait `ConstParamTy_` cannot be implemented for this ty -//~| the trait `ConstParamTy_` cannot be implemented for this ty +//~^ ERROR the trait `ConstParamTy_` cannot be implemented for this ty +//~| ERROR the trait `ConstParamTy_` cannot be implemented for this ty struct Foo3([fn(); 1]); fn main() {} diff --git a/tests/ui/const-generics/early/invalid-const-arguments.rs b/tests/ui/const-generics/early/invalid-const-arguments.rs index 6619c9758859..68e6b2ac458e 100644 --- a/tests/ui/const-generics/early/invalid-const-arguments.rs +++ b/tests/ui/const-generics/early/invalid-const-arguments.rs @@ -4,7 +4,7 @@ struct A; trait Foo {} impl Foo for A {} //~^ ERROR cannot find type -//~| unresolved item provided when a constant +//~| ERROR unresolved item provided when a constant struct B; impl Foo for B {} @@ -13,4 +13,4 @@ impl Foo for B {} struct C; impl Foo for C {} //~^ ERROR cannot find type -//~| unresolved item provided when a constant +//~| ERROR unresolved item provided when a constant diff --git a/tests/ui/const-generics/issues/issue-68366.rs b/tests/ui/const-generics/issues/issue-68366.rs index d9d5e21857b1..6f745b260b63 100644 --- a/tests/ui/const-generics/issues/issue-68366.rs +++ b/tests/ui/const-generics/issues/issue-68366.rs @@ -11,7 +11,7 @@ struct Collatz>; impl Collatz<{Some(N)}> {} //~^ ERROR the const parameter -//[min]~^^ generic parameters may not be used in const operations +//[min]~^^ ERROR generic parameters may not be used in const operations //[full]~^^^ ERROR overly complex struct Foo; diff --git a/tests/ui/const-generics/issues/issue-74950.rs b/tests/ui/const-generics/issues/issue-74950.rs index f79676ccee8e..150566e98c04 100644 --- a/tests/ui/const-generics/issues/issue-74950.rs +++ b/tests/ui/const-generics/issues/issue-74950.rs @@ -17,9 +17,9 @@ struct Inner; // - impl StructuralPartialEq #[derive(PartialEq, Eq)] struct Outer; -//[min]~^ `Inner` is forbidden -//[min]~| `Inner` is forbidden -//[min]~| `Inner` is forbidden -//[min]~| `Inner` is forbidden +//[min]~^ ERROR `Inner` is forbidden +//[min]~| ERROR `Inner` is forbidden +//[min]~| ERROR `Inner` is forbidden +//[min]~| ERROR `Inner` is forbidden fn main() {} diff --git a/tests/ui/const-generics/issues/issue-90318.rs b/tests/ui/const-generics/issues/issue-90318.rs index cebc1ce21420..317ddad49cd4 100644 --- a/tests/ui/const-generics/issues/issue-90318.rs +++ b/tests/ui/const-generics/issues/issue-90318.rs @@ -12,7 +12,7 @@ impl True for If {} fn consume(_val: T) where If<{ TypeId::of::() != TypeId::of::<()>() }>: True, - //~^ overly complex generic constant + //~^ ERROR overly complex generic constant //~| ERROR: cannot call { } @@ -20,7 +20,7 @@ where fn test() where If<{ TypeId::of::() != TypeId::of::<()>() }>: True, - //~^ overly complex generic constant + //~^ ERROR overly complex generic constant //~| ERROR: cannot call { } diff --git a/tests/ui/consts/async-block.rs b/tests/ui/consts/async-block.rs index 1211a150f7d5..96881bc91340 100644 --- a/tests/ui/consts/async-block.rs +++ b/tests/ui/consts/async-block.rs @@ -10,9 +10,9 @@ use std::future::Future; // From const _: i32 = { core::mem::ManuallyDrop::new(async { 0 }); 4 }; -//[without_feature]~^ `async` block +//[without_feature]~^ ERROR `async` block static _FUT: &(dyn Future + Sync) = &async {}; -//[without_feature]~^ `async` block +//[without_feature]~^ ERROR `async` block fn main() {} diff --git a/tests/ui/consts/const-array-oob-arith.rs b/tests/ui/consts/const-array-oob-arith.rs index 0f6e76768cd1..8e5c56e0ea82 100644 --- a/tests/ui/consts/const-array-oob-arith.rs +++ b/tests/ui/consts/const-array-oob-arith.rs @@ -4,10 +4,10 @@ const VAL: i32 = ARR[IDX]; const BONG: [i32; (ARR[0] - 41) as usize] = [5]; const BLUB: [i32; (ARR[0] - 40) as usize] = [5]; //~^ ERROR: mismatched types -//~| expected an array +//~| NOTE expected an array const BOO: [i32; (ARR[0] - 41) as usize] = [5, 99]; //~^ ERROR: mismatched types -//~| expected an array +//~| NOTE expected an array fn main() { let _ = VAL; diff --git a/tests/ui/consts/const-deref-ptr.rs b/tests/ui/consts/const-deref-ptr.rs index 2607d4de2291..c80cb95ea936 100644 --- a/tests/ui/consts/const-deref-ptr.rs +++ b/tests/ui/consts/const-deref-ptr.rs @@ -3,6 +3,6 @@ fn main() { static C: u64 = unsafe {*(0xdeadbeef as *const u64)}; //~^ ERROR could not evaluate static initializer - //~| dangling pointer + //~| NOTE dangling pointer println!("{}", C); } diff --git a/tests/ui/consts/const-err-enum-discriminant.rs b/tests/ui/consts/const-err-enum-discriminant.rs index ebb3e551ba81..42165ff53465 100644 --- a/tests/ui/consts/const-err-enum-discriminant.rs +++ b/tests/ui/consts/const-err-enum-discriminant.rs @@ -7,7 +7,7 @@ union Foo { enum Bar { Boo = [unsafe { Foo { b: () }.a }; 4][3], //~^ ERROR evaluation of constant value failed - //~| uninitialized + //~| NOTE uninitialized } fn main() { diff --git a/tests/ui/consts/const-eval/assign-to-static-within-other-static.rs b/tests/ui/consts/const-eval/assign-to-static-within-other-static.rs index ecf97223f6ad..30e40bd8be13 100644 --- a/tests/ui/consts/const-eval/assign-to-static-within-other-static.rs +++ b/tests/ui/consts/const-eval/assign-to-static-within-other-static.rs @@ -6,7 +6,7 @@ use std::cell::UnsafeCell; static mut FOO: u32 = 42; static BOO: () = unsafe { FOO = 5; - //~^ could not evaluate static initializer [E0080] + //~^ ERROR could not evaluate static initializer [E0080] }; fn main() {} diff --git a/tests/ui/consts/const-eval/const-eval-span.rs b/tests/ui/consts/const-eval/const-eval-span.rs index 1667c77d124c..f1904c76b6c1 100644 --- a/tests/ui/consts/const-eval/const-eval-span.rs +++ b/tests/ui/consts/const-eval/const-eval-span.rs @@ -8,7 +8,7 @@ const CONSTANT: S = S(0); enum E { V = CONSTANT, //~^ ERROR mismatched types - //~| expected `isize`, found `S` + //~| NOTE expected `isize`, found `S` } fn main() {} diff --git a/tests/ui/consts/const-eval/const_raw_ptr_ops2.rs b/tests/ui/consts/const-eval/const_raw_ptr_ops2.rs index ec5508a1e90c..ca96cfd9d193 100644 --- a/tests/ui/consts/const-eval/const_raw_ptr_ops2.rs +++ b/tests/ui/consts/const-eval/const_raw_ptr_ops2.rs @@ -5,6 +5,6 @@ const Z: i32 = unsafe { *(&1 as *const i32) }; // bad, will thus error in miri const Z2: i32 = unsafe { *(42 as *const i32) }; //~ ERROR evaluation of constant value failed -//~| is a dangling pointer +//~| NOTE is a dangling pointer const Z3: i32 = unsafe { *(44 as *const i32) }; //~ ERROR evaluation of constant value failed -//~| is a dangling pointer +//~| NOTE is a dangling pointer diff --git a/tests/ui/consts/const-eval/issue-91827-extern-types-field-offset.rs b/tests/ui/consts/const-eval/issue-91827-extern-types-field-offset.rs index c6960fa7259d..3a932343ddda 100644 --- a/tests/ui/consts/const-eval/issue-91827-extern-types-field-offset.rs +++ b/tests/ui/consts/const-eval/issue-91827-extern-types-field-offset.rs @@ -37,7 +37,7 @@ const OFFSET: () = unsafe { // fails. let field = &x.a; //~^ ERROR: evaluation of constant value failed - //~| does not have a known offset + //~| NOTE does not have a known offset }; fn main() {} diff --git a/tests/ui/consts/const-eval/partial_ptr_overwrite.rs b/tests/ui/consts/const-eval/partial_ptr_overwrite.rs index 1e99d84bba4b..9438de5e3fe7 100644 --- a/tests/ui/consts/const-eval/partial_ptr_overwrite.rs +++ b/tests/ui/consts/const-eval/partial_ptr_overwrite.rs @@ -5,7 +5,7 @@ const PARTIAL_OVERWRITE: () = { unsafe { let ptr: *mut _ = &mut p; *(ptr as *mut u8) = 123; //~ ERROR constant - //~| unable to overwrite parts of a pointer + //~| NOTE unable to overwrite parts of a pointer } let x = *p; }; diff --git a/tests/ui/consts/const-eval/ub-enum-overwrite.rs b/tests/ui/consts/const-eval/ub-enum-overwrite.rs index 69f1d01b2f31..e37c25718f8e 100644 --- a/tests/ui/consts/const-eval/ub-enum-overwrite.rs +++ b/tests/ui/consts/const-eval/ub-enum-overwrite.rs @@ -10,7 +10,7 @@ const _: u8 = { e = E::B; unsafe { *p } //~^ ERROR evaluation of constant value failed - //~| uninitialized + //~| NOTE uninitialized }; fn main() {} diff --git a/tests/ui/consts/const-eval/ub-write-through-immutable.rs b/tests/ui/consts/const-eval/ub-write-through-immutable.rs index d3ae2d818848..795ac602a1c6 100644 --- a/tests/ui/consts/const-eval/ub-write-through-immutable.rs +++ b/tests/ui/consts/const-eval/ub-write-through-immutable.rs @@ -8,14 +8,14 @@ const WRITE_AFTER_CAST: () = unsafe { let mut x = 0; let ptr = &x as *const i32 as *mut i32; *ptr = 0; //~ERROR: evaluation of constant value failed - //~| immutable + //~| NOTE immutable }; const WRITE_AFTER_TRANSMUTE: () = unsafe { let mut x = 0; let ptr: *mut i32 = mem::transmute(&x); *ptr = 0; //~ERROR: evaluation of constant value failed - //~| immutable + //~| NOTE immutable }; // it's okay when there is interior mutability; diff --git a/tests/ui/consts/const-eval/union-ice.rs b/tests/ui/consts/const-eval/union-ice.rs index 1db9470912d3..8ce5f6d89a8f 100644 --- a/tests/ui/consts/const-eval/union-ice.rs +++ b/tests/ui/consts/const-eval/union-ice.rs @@ -13,13 +13,13 @@ const UNION: DummyUnion = DummyUnion { field1: 1065353216 }; const FIELD3: Field3 = unsafe { UNION.field3 }; //~^ ERROR evaluation of constant value failed -//~| uninitialized +//~| NOTE uninitialized const FIELD_PATH: Struct = Struct { a: 42, b: unsafe { UNION.field3 }, //~^ ERROR evaluation of constant value failed - //~| uninitialized + //~| NOTE uninitialized }; struct Struct { @@ -32,7 +32,7 @@ const FIELD_PATH2: Struct2 = Struct2 { 21, unsafe { UNION.field3 }, //~^ ERROR evaluation of constant value failed - //~| uninitialized + //~| NOTE uninitialized 23, 24, ], diff --git a/tests/ui/consts/const-eval/union_promotion.rs b/tests/ui/consts/const-eval/union_promotion.rs index 18894c45fd82..3868b0b18b1e 100644 --- a/tests/ui/consts/const-eval/union_promotion.rs +++ b/tests/ui/consts/const-eval/union_promotion.rs @@ -5,7 +5,7 @@ union Foo { } fn main() { - let x: &'static bool = &unsafe { //~ temporary value dropped while borrowed + let x: &'static bool = &unsafe { //~ ERROR temporary value dropped while borrowed Foo { a: &1 }.b == Foo { a: &2 }.b }; } diff --git a/tests/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.rs b/tests/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.rs index a77ee2938207..89a8d1429b4d 100644 --- a/tests/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.rs +++ b/tests/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.rs @@ -8,11 +8,11 @@ const unsafe extern "C-unwind" fn bar() -> usize { fn main() { let a: [u8; foo()]; - //~^ call to unsafe function `foo` is unsafe and requires unsafe function or block + //~^ ERROR call to unsafe function `foo` is unsafe and requires unsafe function or block foo(); //~^ ERROR call to unsafe function `foo` is unsafe and requires unsafe function or block let b: [u8; bar()]; - //~^ call to unsafe function `bar` is unsafe and requires unsafe function or block + //~^ ERROR call to unsafe function `bar` is unsafe and requires unsafe function or block bar(); //~^ ERROR call to unsafe function `bar` is unsafe and requires unsafe function or block } diff --git a/tests/ui/consts/const-integer-bool-ops.rs b/tests/ui/consts/const-integer-bool-ops.rs index 35915a7a606a..fbbd51adfe88 100644 --- a/tests/ui/consts/const-integer-bool-ops.rs +++ b/tests/ui/consts/const-integer-bool-ops.rs @@ -1,67 +1,67 @@ const X: usize = 42 && 39; //~^ ERROR mismatched types -//~| expected `bool`, found integer +//~| NOTE expected `bool`, found integer //~| ERROR mismatched types -//~| expected `bool`, found integer +//~| NOTE expected `bool`, found integer //~| ERROR mismatched types -//~| expected `usize`, found `bool` +//~| NOTE expected `usize`, found `bool` const ARR: [i32; X] = [99; 34]; const X1: usize = 42 || 39; //~^ ERROR mismatched types -//~| expected `bool`, found integer +//~| NOTE expected `bool`, found integer //~| ERROR mismatched types -//~| expected `bool`, found integer +//~| NOTE expected `bool`, found integer //~| ERROR mismatched types -//~| expected `usize`, found `bool` +//~| NOTE expected `usize`, found `bool` const ARR1: [i32; X1] = [99; 47]; const X2: usize = -42 || -39; //~^ ERROR mismatched types -//~| expected `bool`, found integer +//~| NOTE expected `bool`, found integer //~| ERROR mismatched types -//~| expected `bool`, found integer +//~| NOTE expected `bool`, found integer //~| ERROR mismatched types -//~| expected `usize`, found `bool` +//~| NOTE expected `usize`, found `bool` const ARR2: [i32; X2] = [99; 18446744073709551607]; const X3: usize = -42 && -39; //~^ ERROR mismatched types -//~| expected `bool`, found integer +//~| NOTE expected `bool`, found integer //~| ERROR mismatched types -//~| expected `bool`, found integer +//~| NOTE expected `bool`, found integer //~| ERROR mismatched types -//~| expected `usize`, found `bool` +//~| NOTE expected `usize`, found `bool` const ARR3: [i32; X3] = [99; 6]; const Y: usize = 42.0 == 42.0; //~^ ERROR mismatched types -//~| expected `usize`, found `bool` +//~| NOTE expected `usize`, found `bool` const ARRR: [i32; Y] = [99; 1]; const Y1: usize = 42.0 >= 42.0; //~^ ERROR mismatched types -//~| expected `usize`, found `bool` +//~| NOTE expected `usize`, found `bool` const ARRR1: [i32; Y1] = [99; 1]; const Y2: usize = 42.0 <= 42.0; //~^ ERROR mismatched types -//~| expected `usize`, found `bool` +//~| NOTE expected `usize`, found `bool` const ARRR2: [i32; Y2] = [99; 1]; const Y3: usize = 42.0 > 42.0; //~^ ERROR mismatched types -//~| expected `usize`, found `bool` +//~| NOTE expected `usize`, found `bool` const ARRR3: [i32; Y3] = [99; 0]; const Y4: usize = 42.0 < 42.0; //~^ ERROR mismatched types -//~| expected `usize`, found `bool` +//~| NOTE expected `usize`, found `bool` const ARRR4: [i32; Y4] = [99; 0]; const Y5: usize = 42.0 != 42.0; //~^ ERROR mismatched types -//~| expected `usize`, found `bool` +//~| NOTE expected `usize`, found `bool` const ARRR5: [i32; Y5] = [99; 0]; fn main() { diff --git a/tests/ui/consts/const-len-underflow-subspans.rs b/tests/ui/consts/const-len-underflow-subspans.rs index ed77e9078425..5afb1bf89d09 100644 --- a/tests/ui/consts/const-len-underflow-subspans.rs +++ b/tests/ui/consts/const-len-underflow-subspans.rs @@ -7,5 +7,5 @@ const TWO: usize = 2; fn main() { let a: [i8; ONE - TWO] = unimplemented!(); //~^ ERROR evaluation of constant value failed - //~| attempt to compute `1_usize - 2_usize`, which would overflow + //~| NOTE attempt to compute `1_usize - 2_usize`, which would overflow } diff --git a/tests/ui/consts/const-slice-oob.rs b/tests/ui/consts/const-slice-oob.rs index 429b97821321..09202df72c0f 100644 --- a/tests/ui/consts/const-slice-oob.rs +++ b/tests/ui/consts/const-slice-oob.rs @@ -1,6 +1,6 @@ const FOO: &'static[u32] = &[1, 2, 3]; const BAR: u32 = FOO[5]; -//~^ index out of bounds: the length is 3 but the index is 5 +//~^ NOTE index out of bounds: the length is 3 but the index is 5 //~| ERROR evaluation of constant value failed fn main() { diff --git a/tests/ui/consts/copy-intrinsic.rs b/tests/ui/consts/copy-intrinsic.rs index 08fbcc107e7e..5ae467878001 100644 --- a/tests/ui/consts/copy-intrinsic.rs +++ b/tests/ui/consts/copy-intrinsic.rs @@ -32,7 +32,7 @@ const COPY_OOB_1: () = unsafe { copy_nonoverlapping(0x100 as *const i32, dangle, 0); // Non-zero-sized copy is not. copy_nonoverlapping(0x100 as *const i32, dangle, 1); //~ ERROR evaluation of constant value failed [E0080] - //~| got 0x100[noalloc] which is a dangling pointer + //~| NOTE got 0x100[noalloc] which is a dangling pointer }; const COPY_OOB_2: () = unsafe { let x = 0i32; @@ -41,20 +41,20 @@ const COPY_OOB_2: () = unsafe { copy_nonoverlapping(dangle, 0x100 as *mut i32, 0); // Non-zero-sized copy is not. copy_nonoverlapping(dangle, 0x100 as *mut i32, 1); //~ ERROR evaluation of constant value failed [E0080] - //~| +0x28 which is at or beyond the end of the allocation + //~| NOTE +0x28 which is at or beyond the end of the allocation }; const COPY_SIZE_OVERFLOW: () = unsafe { let x = 0; let mut y = 0; copy(&x, &mut y, 1usize << (mem::size_of::() * 8 - 1)); //~ ERROR evaluation of constant value failed [E0080] - //~| overflow computing total size of `copy` + //~| NOTE overflow computing total size of `copy` }; const COPY_NONOVERLAPPING_SIZE_OVERFLOW: () = unsafe { let x = 0; let mut y = 0; - copy_nonoverlapping(&x, &mut y, 1usize << (mem::size_of::() * 8 - 1)); //~ evaluation of constant value failed [E0080] - //~| overflow computing total size of `copy_nonoverlapping` + copy_nonoverlapping(&x, &mut y, 1usize << (mem::size_of::() * 8 - 1)); //~ ERROR evaluation of constant value failed [E0080] + //~| NOTE overflow computing total size of `copy_nonoverlapping` }; fn main() { diff --git a/tests/ui/consts/drop_zst.rs b/tests/ui/consts/drop_zst.rs index 40c66043f9fd..daf8f1b0343d 100644 --- a/tests/ui/consts/drop_zst.rs +++ b/tests/ui/consts/drop_zst.rs @@ -11,7 +11,7 @@ impl Drop for S { } const fn foo() { - let s = S; //~ destructor + let s = S; //~ ERROR destructor } fn main() {} diff --git a/tests/ui/consts/eval-enum.rs b/tests/ui/consts/eval-enum.rs index 551f10e66e35..fa9ad6736e29 100644 --- a/tests/ui/consts/eval-enum.rs +++ b/tests/ui/consts/eval-enum.rs @@ -1,9 +1,9 @@ enum Test { DivZero = 1/0, - //~^ attempt to divide `1_isize` by zero + //~^ NOTE attempt to divide `1_isize` by zero //~| ERROR evaluation of constant value failed RemZero = 1%0, - //~^ attempt to calculate the remainder of `1_isize` with a divisor of zero + //~^ NOTE attempt to calculate the remainder of `1_isize` with a divisor of zero //~| ERROR evaluation of constant value failed } diff --git a/tests/ui/consts/extra-const-ub/detect-extra-ub.rs b/tests/ui/consts/extra-const-ub/detect-extra-ub.rs index d2b157e03e7c..481f2ff88df6 100644 --- a/tests/ui/consts/extra-const-ub/detect-extra-ub.rs +++ b/tests/ui/consts/extra-const-ub/detect-extra-ub.rs @@ -28,32 +28,32 @@ enum UninhDiscriminant { const INVALID_BOOL: () = unsafe { let _x: bool = transmute(3u8); //[with_flag]~^ ERROR: evaluation of constant value failed - //[with_flag]~| invalid value + //[with_flag]~| NOTE invalid value }; const INVALID_PTR_IN_INT: () = unsafe { let _x: usize = transmute(&3u8); //[with_flag]~^ ERROR: evaluation of constant value failed - //[with_flag]~| invalid value + //[with_flag]~| NOTE invalid value }; const INVALID_PTR_IN_ENUM: () = unsafe { let _x: PtrSizedEnum = transmute(&3u8); //[with_flag]~^ ERROR: evaluation of constant value failed - //[with_flag]~| invalid value + //[with_flag]~| NOTE invalid value }; const INVALID_SLICE_TO_USIZE_TRANSMUTE: () = unsafe { let x: &[u8] = &[0; 32]; let _x: (usize, usize) = transmute(x); //[with_flag]~^ ERROR: evaluation of constant value failed - //[with_flag]~| invalid value + //[with_flag]~| NOTE invalid value }; const UNALIGNED_PTR: () = unsafe { let _x: &u32 = transmute(&[0u8; 4]); //[with_flag]~^ ERROR: evaluation of constant value failed - //[with_flag]~| invalid value + //[with_flag]~| NOTE invalid value }; const UNINHABITED_VARIANT: () = unsafe { @@ -61,7 +61,7 @@ const UNINHABITED_VARIANT: () = unsafe { // Not using transmute, we want to hit the ImmTy code path. let v = *addr_of!(data).cast::(); //[with_flag]~^ ERROR: evaluation of constant value failed - //[with_flag]~| invalid value + //[with_flag]~| NOTE invalid value }; const PARTIAL_POINTER: () = unsafe { @@ -81,7 +81,7 @@ const PARTIAL_POINTER: () = unsafe { let mem = Align { p: mem, align: 0 }; let _val = *(&mem as *const Align as *const [*const u8; 2]); //[with_flag]~^ ERROR: evaluation of constant value failed - //[with_flag]~| invalid value + //[with_flag]~| NOTE invalid value }; // Regression tests for an ICE (related to ). @@ -96,7 +96,7 @@ const OVERSIZED_REF: () = { unsafe { let slice: *const [u8] = transmute((1usize, usize::MAX)); let _val = &*slice; //[with_flag]~^ ERROR: evaluation of constant value failed - //[with_flag]~| slice is bigger than largest supported object + //[with_flag]~| NOTE slice is bigger than largest supported object } }; fn main() {} diff --git a/tests/ui/consts/issue-19244-2.rs b/tests/ui/consts/issue-19244-2.rs index c9a68b05c5ba..87f8c1581a75 100644 --- a/tests/ui/consts/issue-19244-2.rs +++ b/tests/ui/consts/issue-19244-2.rs @@ -3,5 +3,5 @@ const STRUCT: MyStruct = MyStruct { field: 42 }; fn main() { let a: [isize; STRUCT.nonexistent_field]; - //~^ no field `nonexistent_field` on type `MyStruct` + //~^ ERROR no field `nonexistent_field` on type `MyStruct` } diff --git a/tests/ui/consts/min_const_fn/min_const_fn.rs b/tests/ui/consts/min_const_fn/min_const_fn.rs index e6d9d184e041..38ca10858b19 100644 --- a/tests/ui/consts/min_const_fn/min_const_fn.rs +++ b/tests/ui/consts/min_const_fn/min_const_fn.rs @@ -34,13 +34,13 @@ const fn foo35(a: bool, b: bool) -> bool { a ^ b } struct Foo(T); impl Foo { const fn new(t: T) -> Self { Foo(t) } - const fn into_inner(self) -> T { self.0 } //~ destructor of + const fn into_inner(self) -> T { self.0 } //~ ERROR destructor of const fn get(&self) -> &T { &self.0 } const fn get_mut(&mut self) -> &mut T { &mut self.0 } } impl<'a, T> Foo { const fn new_lt(t: T) -> Self { Foo(t) } - const fn into_inner_lt(self) -> T { self.0 } //~ destructor of + const fn into_inner_lt(self) -> T { self.0 } //~ ERROR destructor of const fn get_lt(&self) -> &T { &self.0 } const fn get_mut_lt(&mut self) -> &mut T { &mut self.0 } } diff --git a/tests/ui/consts/miri_unleashed/ptr_arith.rs b/tests/ui/consts/miri_unleashed/ptr_arith.rs index 4e1183220792..408aa5db24d1 100644 --- a/tests/ui/consts/miri_unleashed/ptr_arith.rs +++ b/tests/ui/consts/miri_unleashed/ptr_arith.rs @@ -6,7 +6,7 @@ static PTR_INT_CAST: () = { let x = &0 as *const _ as usize; //~^ ERROR could not evaluate static initializer - //~| exposing pointers + //~| NOTE exposing pointers let _v = x == x; }; @@ -14,7 +14,7 @@ static PTR_INT_TRANSMUTE: () = unsafe { let x: usize = std::mem::transmute(&0); let _v = x + 0; //~^ ERROR could not evaluate static initializer - //~| unable to turn pointer into integer + //~| NOTE unable to turn pointer into integer }; // I'd love to test pointer comparison, but that is not possible since diff --git a/tests/ui/consts/no-ice-from-static-in-const-issue-52060.rs b/tests/ui/consts/no-ice-from-static-in-const-issue-52060.rs index e0f9e462d32e..e3cd8ec7d8a6 100644 --- a/tests/ui/consts/no-ice-from-static-in-const-issue-52060.rs +++ b/tests/ui/consts/no-ice-from-static-in-const-issue-52060.rs @@ -4,6 +4,6 @@ static mut A: &'static [u32] = &[1]; static B: [u32; 1] = [0; unsafe { A.len() }]; //~^ ERROR: evaluation of constant value failed -//~| mutable global memory +//~| NOTE mutable global memory fn main() {} diff --git a/tests/ui/consts/promoted_running_out_of_memory_issue-130687.rs b/tests/ui/consts/promoted_running_out_of_memory_issue-130687.rs index 75765596fa17..e458a6f98adf 100644 --- a/tests/ui/consts/promoted_running_out_of_memory_issue-130687.rs +++ b/tests/ui/consts/promoted_running_out_of_memory_issue-130687.rs @@ -12,6 +12,6 @@ pub struct Data([u8; (1 << 47) - 1]); const _: &'static Data = &Data([0; (1 << 47) - 1]); //~^ERROR: evaluation of constant value failed -//~| tried to allocate more memory than available to compiler +//~| NOTE tried to allocate more memory than available to compiler fn main() {} diff --git a/tests/ui/consts/promoted_size_overflow.rs b/tests/ui/consts/promoted_size_overflow.rs index 3d606905e782..ebd5ab064871 100644 --- a/tests/ui/consts/promoted_size_overflow.rs +++ b/tests/ui/consts/promoted_size_overflow.rs @@ -2,6 +2,6 @@ pub struct Data([u8; usize::MAX >> 2]); const _: &'static [Data] = &[]; //~^ERROR: evaluation of constant value failed -//~| too big for the target architecture +//~| NOTE too big for the target architecture fn main() {} diff --git a/tests/ui/consts/recursive-zst-static.rs b/tests/ui/consts/recursive-zst-static.rs index 53d32254a684..a52624fada8d 100644 --- a/tests/ui/consts/recursive-zst-static.rs +++ b/tests/ui/consts/recursive-zst-static.rs @@ -10,7 +10,7 @@ static FOO: () = FOO; //~^ ERROR could not evaluate static initializer -static A: () = B; //~ cycle detected when evaluating initializer of static `A` +static A: () = B; //~ ERROR cycle detected when evaluating initializer of static `A` static B: () = A; fn main() { diff --git a/tests/ui/consts/slice-index-overflow-issue-130284.rs b/tests/ui/consts/slice-index-overflow-issue-130284.rs index 299009082563..6877ebe14768 100644 --- a/tests/ui/consts/slice-index-overflow-issue-130284.rs +++ b/tests/ui/consts/slice-index-overflow-issue-130284.rs @@ -6,7 +6,7 @@ const C: () = { // This used to ICE, but it should just report UB. let _ice = (*fat)[usize::MAX - 1]; //~^ERROR: constant value failed - //~| overflow + //~| NOTE overflow } }; diff --git a/tests/ui/coroutine/auto-trait-regions.rs b/tests/ui/coroutine/auto-trait-regions.rs index 4c239f9ee76c..1c7f0304ddbe 100644 --- a/tests/ui/coroutine/auto-trait-regions.rs +++ b/tests/ui/coroutine/auto-trait-regions.rs @@ -43,8 +43,8 @@ fn main() { // Disallow impls which relates lifetimes in the coroutine interior let gen = #[coroutine] move || { let a = A(&mut true, &mut true, No); - //~^ temporary value dropped while borrowed - //~| temporary value dropped while borrowed + //~^ ERROR temporary value dropped while borrowed + //~| ERROR temporary value dropped while borrowed yield; assert_foo(a); }; diff --git a/tests/ui/coroutine/coroutine-with-nll.rs b/tests/ui/coroutine/coroutine-with-nll.rs index fa77ab4e0495..44ead560cf88 100644 --- a/tests/ui/coroutine/coroutine-with-nll.rs +++ b/tests/ui/coroutine/coroutine-with-nll.rs @@ -6,7 +6,7 @@ fn main() { // The reference in `_a` is a Legal with NLL since it ends before the yield let _a = &mut true; let b = &mut true; - //~^ borrow may still be in use when coroutine yields + //~^ ERROR borrow may still be in use when coroutine yields yield (); println!("{}", b); }; diff --git a/tests/ui/coroutine/retain-resume-ref.rs b/tests/ui/coroutine/retain-resume-ref.rs index 6e688c33979a..000e40d47fbe 100644 --- a/tests/ui/coroutine/retain-resume-ref.rs +++ b/tests/ui/coroutine/retain-resume-ref.rs @@ -22,5 +22,5 @@ fn main() { let mut gen = Pin::new(&mut gen); gen.as_mut().resume(&mut thing); gen.as_mut().resume(&mut thing); - //~^ cannot borrow `thing` as mutable more than once at a time + //~^ ERROR cannot borrow `thing` as mutable more than once at a time } diff --git a/tests/ui/deref-patterns/gate.rs b/tests/ui/deref-patterns/gate.rs index ff50e30dea8c..835fdf854d2c 100644 --- a/tests/ui/deref-patterns/gate.rs +++ b/tests/ui/deref-patterns/gate.rs @@ -2,6 +2,6 @@ fn main() { match String::new() { "" | _ => {} - //~^ mismatched types + //~^ ERROR mismatched types } } diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs index 73a238ddf50d..b5ff76809a2c 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs +++ b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs @@ -55,6 +55,6 @@ impl Foo for T where T: Expression {} fn main() { SelectInt.check("bar"); //[current]~^ ERROR the trait bound `&str: AsExpression` is not satisfied - //[next]~^^ the trait bound `&str: AsExpression<::SqlType>` is not satisfied - //[next]~| type mismatch + //[next]~^^ ERROR the trait bound `&str: AsExpression<::SqlType>` is not satisfied + //[next]~| ERROR type mismatch } diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/custom-on-unimplemented-diagnostic.rs b/tests/ui/diagnostic_namespace/on_unimplemented/custom-on-unimplemented-diagnostic.rs index 1173c939038a..3bb0939b5f91 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/custom-on-unimplemented-diagnostic.rs +++ b/tests/ui/diagnostic_namespace/on_unimplemented/custom-on-unimplemented-diagnostic.rs @@ -15,7 +15,7 @@ struct B; fn main() { B.request(); - //~^ my message [E0599] + //~^ ERROR my message [E0599] //~| my label //~| my note } diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.rs b/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.rs index c638681173d9..b06f56bd66e4 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.rs +++ b/tests/ui/diagnostic_namespace/on_unimplemented/ignore_unsupported_options_and_continue_to_use_fallback.rs @@ -8,8 +8,8 @@ note = "custom note" )] #[diagnostic::on_unimplemented(message = "fallback!!")] -//~^ `message` is ignored due to previous definition of `message` -//~| `message` is ignored due to previous definition of `message` +//~^ WARN `message` is ignored due to previous definition of `message` +//~| WARN `message` is ignored due to previous definition of `message` #[diagnostic::on_unimplemented(label = "fallback label")] #[diagnostic::on_unimplemented(note = "fallback note")] trait Foo {} diff --git a/tests/ui/did_you_mean/issue-38147-1.rs b/tests/ui/did_you_mean/issue-38147-1.rs index c068a1834f35..80f71b8b821e 100644 --- a/tests/ui/did_you_mean/issue-38147-1.rs +++ b/tests/ui/did_you_mean/issue-38147-1.rs @@ -14,7 +14,7 @@ struct Foo<'a> { impl<'a> Foo<'a> { fn f(&self) { - self.s.push('x'); //~ cannot borrow `*self.s` as mutable, as it is behind a `&` reference + self.s.push('x'); //~ ERROR cannot borrow `*self.s` as mutable, as it is behind a `&` reference } } diff --git a/tests/ui/did_you_mean/issue-40006.rs b/tests/ui/did_you_mean/issue-40006.rs index fff31bfc85e3..fcb86814c6e5 100644 --- a/tests/ui/did_you_mean/issue-40006.rs +++ b/tests/ui/did_you_mean/issue-40006.rs @@ -35,5 +35,5 @@ impl S { } fn main() { - S.hello_method(); //~ no method named `hello_method` found + S.hello_method(); //~ ERROR no method named `hello_method` found } diff --git a/tests/ui/did_you_mean/issue-42764.rs b/tests/ui/did_you_mean/issue-42764.rs index eb96c2480630..2766bb2c1b61 100644 --- a/tests/ui/did_you_mean/issue-42764.rs +++ b/tests/ui/did_you_mean/issue-42764.rs @@ -26,5 +26,5 @@ struct Context { wrapper: Wrapper } fn overton() { let _c = Context { wrapper: Payload{} }; //~^ ERROR mismatched types - //~| try wrapping the expression in `Wrapper` + //~| HELP try wrapping the expression in `Wrapper` } diff --git a/tests/ui/drop/lint-tail-expr-drop-order-borrowck.rs b/tests/ui/drop/lint-tail-expr-drop-order-borrowck.rs index 6f64d83f8a0c..e8368b0a369d 100644 --- a/tests/ui/drop/lint-tail-expr-drop-order-borrowck.rs +++ b/tests/ui/drop/lint-tail-expr-drop-order-borrowck.rs @@ -10,7 +10,7 @@ fn should_lint_with_potential_borrowck_err() { //~^ ERROR: relative drop order changing //~| WARN: this changes meaning in Rust 2024 //~| NOTE: this temporary value will be dropped at the end of the block - //~| borrow later used by call + //~| NOTE: borrow later used by call //~| NOTE: for more information, see } @@ -20,7 +20,7 @@ fn should_lint_with_unsafe_block() { //~^ ERROR: relative drop order changing //~| WARN: this changes meaning in Rust 2024 //~| NOTE: this temporary value will be dropped at the end of the block - //~| borrow later used by call + //~| NOTE: borrow later used by call //~| NOTE: for more information, see } @@ -32,7 +32,7 @@ fn should_lint_with_big_block() { //~^ ERROR: relative drop order changing //~| WARN: this changes meaning in Rust 2024 //~| NOTE: this temporary value will be dropped at the end of the block - //~| borrow later used here + //~| NOTE: borrow later used here //~| NOTE: for more information, see }) } @@ -44,7 +44,7 @@ fn another_temp_that_is_copy_in_arg() { //~^ ERROR: relative drop order changing //~| WARN: this changes meaning in Rust 2024 //~| NOTE: this temporary value will be dropped at the end of the block - //~| borrow later used by call + //~| NOTE: borrow later used by call //~| NOTE: for more information, see } diff --git a/tests/ui/duplicate/dupe-symbols-1.rs b/tests/ui/duplicate/dupe-symbols-1.rs index f49bf44a0612..4e03d7c4ce5a 100644 --- a/tests/ui/duplicate/dupe-symbols-1.rs +++ b/tests/ui/duplicate/dupe-symbols-1.rs @@ -10,5 +10,5 @@ pub fn a() { #[export_name="fail"] pub fn b() { -//~^ symbol `fail` is already defined +//~^ ERROR symbol `fail` is already defined } diff --git a/tests/ui/duplicate/dupe-symbols-2.rs b/tests/ui/duplicate/dupe-symbols-2.rs index 343c7131d1fb..03fff570dff5 100644 --- a/tests/ui/duplicate/dupe-symbols-2.rs +++ b/tests/ui/duplicate/dupe-symbols-2.rs @@ -13,6 +13,6 @@ pub mod a { pub mod b { #[no_mangle] pub extern "C" fn fail() { - //~^ symbol `fail` is already defined + //~^ ERROR symbol `fail` is already defined } } diff --git a/tests/ui/duplicate/dupe-symbols-3.rs b/tests/ui/duplicate/dupe-symbols-3.rs index 365ec182f53a..41bbe5173573 100644 --- a/tests/ui/duplicate/dupe-symbols-3.rs +++ b/tests/ui/duplicate/dupe-symbols-3.rs @@ -10,5 +10,5 @@ pub fn a() { #[no_mangle] pub fn fail() { -//~^ symbol `fail` is already defined +//~^ ERROR symbol `fail` is already defined } diff --git a/tests/ui/duplicate/dupe-symbols-5.rs b/tests/ui/duplicate/dupe-symbols-5.rs index 2ed803c1ddad..4aaf2bd29c5c 100644 --- a/tests/ui/duplicate/dupe-symbols-5.rs +++ b/tests/ui/duplicate/dupe-symbols-5.rs @@ -9,5 +9,5 @@ static HELLO: u8 = 0; #[export_name="fail"] pub fn b() { -//~^ symbol `fail` is already defined +//~^ ERROR symbol `fail` is already defined } diff --git a/tests/ui/duplicate/dupe-symbols-6.rs b/tests/ui/duplicate/dupe-symbols-6.rs index 9841be7365a3..b3f430f51bb9 100644 --- a/tests/ui/duplicate/dupe-symbols-6.rs +++ b/tests/ui/duplicate/dupe-symbols-6.rs @@ -8,4 +8,4 @@ static HELLO: u8 = 0; #[export_name="fail"] static HELLO_TWICE: u16 = 0; -//~^ symbol `fail` is already defined +//~^ ERROR symbol `fail` is already defined diff --git a/tests/ui/dyn-compatibility/taint-const-eval.rs b/tests/ui/dyn-compatibility/taint-const-eval.rs index 7ea763e18469..64c4df611e65 100644 --- a/tests/ui/dyn-compatibility/taint-const-eval.rs +++ b/tests/ui/dyn-compatibility/taint-const-eval.rs @@ -5,8 +5,8 @@ trait Qux { } static FOO: &(dyn Qux + Sync) = "desc"; -//~^ the trait `Qux` is not dyn compatible -//~| the trait `Qux` is not dyn compatible -//~| the trait `Qux` is not dyn compatible +//~^ ERROR the trait `Qux` is not dyn compatible +//~| ERROR the trait `Qux` is not dyn compatible +//~| ERROR the trait `Qux` is not dyn compatible fn main() {} diff --git a/tests/ui/dyn-star/async-block-dyn-star.rs b/tests/ui/dyn-star/async-block-dyn-star.rs index 9bffd6c67253..db133d94c918 100644 --- a/tests/ui/dyn-star/async-block-dyn-star.rs +++ b/tests/ui/dyn-star/async-block-dyn-star.rs @@ -4,6 +4,6 @@ //~^ WARN the feature `dyn_star` is incomplete static S: dyn* Send + Sync = async { 42 }; -//~^ needs to have the same ABI as a pointer +//~^ ERROR needs to have the same ABI as a pointer pub fn main() {} diff --git a/tests/ui/dyn-star/feature-gate-dyn_star.rs b/tests/ui/dyn-star/feature-gate-dyn_star.rs index 41eed71cdc30..b12fd7755be0 100644 --- a/tests/ui/dyn-star/feature-gate-dyn_star.rs +++ b/tests/ui/dyn-star/feature-gate-dyn_star.rs @@ -3,7 +3,7 @@ /// dyn* is not necessarily the final surface syntax (if we have one at all), /// but for now we will support it to aid in writing tests independently. pub fn dyn_star_parameter(_: &dyn* Send) { - //~^ `dyn*` trait objects are experimental + //~^ ERROR `dyn*` trait objects are experimental } fn main() {} diff --git a/tests/ui/editions/never-type-fallback-breaking.e2021.fixed b/tests/ui/editions/never-type-fallback-breaking.e2021.fixed index 11ec273fc4bf..8c11ab0791dd 100644 --- a/tests/ui/editions/never-type-fallback-breaking.e2021.fixed +++ b/tests/ui/editions/never-type-fallback-breaking.e2021.fixed @@ -16,8 +16,8 @@ fn main() { } fn m() { - //[e2021]~^ this function depends on never type fallback being `()` - //[e2021]~| this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! + //[e2021]~^ WARN this function depends on never type fallback being `()` + //[e2021]~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! let x: () = match true { true => Default::default(), //[e2024]~^ error: the trait bound `!: Default` is not satisfied @@ -28,8 +28,8 @@ fn m() { } fn q() -> Option<()> { - //[e2021]~^ this function depends on never type fallback being `()` - //[e2021]~| this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! + //[e2021]~^ WARN this function depends on never type fallback being `()` + //[e2021]~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! fn deserialize() -> Option { Some(T::default()) } @@ -45,8 +45,8 @@ fn help<'a: 'a, T: Into<()>, U>(_: U) -> Result { Err(()) } fn meow() -> Result<(), ()> { - //[e2021]~^ this function depends on never type fallback being `()` - //[e2021]~| this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! + //[e2021]~^ WARN this function depends on never type fallback being `()` + //[e2021]~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! help::<(), _>(1)?; //[e2024]~^ error: the trait bound `(): From` is not satisfied Ok(()) @@ -57,8 +57,8 @@ pub fn takes_apit(_y: impl Fn() -> T) -> Result { } pub fn fallback_return() -> Result<(), ()> { - //[e2021]~^ this function depends on never type fallback being `()` - //[e2021]~| this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! + //[e2021]~^ WARN this function depends on never type fallback being `()` + //[e2021]~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! takes_apit::<()>(|| Default::default())?; //[e2024]~^ error: the trait bound `!: Default` is not satisfied Ok(()) @@ -71,8 +71,8 @@ fn mk() -> Result { fn takes_apit2(_x: impl Default) {} fn fully_apit() -> Result<(), ()> { - //[e2021]~^ this function depends on never type fallback being `()` - //[e2021]~| this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! + //[e2021]~^ WARN this function depends on never type fallback being `()` + //[e2021]~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! takes_apit2(mk::<()>()?); //[e2024]~^ error: the trait bound `!: Default` is not satisfied Ok(()) diff --git a/tests/ui/editions/never-type-fallback-breaking.rs b/tests/ui/editions/never-type-fallback-breaking.rs index daafc526eff4..80974f830137 100644 --- a/tests/ui/editions/never-type-fallback-breaking.rs +++ b/tests/ui/editions/never-type-fallback-breaking.rs @@ -16,8 +16,8 @@ fn main() { } fn m() { - //[e2021]~^ this function depends on never type fallback being `()` - //[e2021]~| this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! + //[e2021]~^ WARN this function depends on never type fallback being `()` + //[e2021]~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! let x = match true { true => Default::default(), //[e2024]~^ error: the trait bound `!: Default` is not satisfied @@ -28,8 +28,8 @@ fn m() { } fn q() -> Option<()> { - //[e2021]~^ this function depends on never type fallback being `()` - //[e2021]~| this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! + //[e2021]~^ WARN this function depends on never type fallback being `()` + //[e2021]~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! fn deserialize() -> Option { Some(T::default()) } @@ -45,8 +45,8 @@ fn help<'a: 'a, T: Into<()>, U>(_: U) -> Result { Err(()) } fn meow() -> Result<(), ()> { - //[e2021]~^ this function depends on never type fallback being `()` - //[e2021]~| this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! + //[e2021]~^ WARN this function depends on never type fallback being `()` + //[e2021]~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! help(1)?; //[e2024]~^ error: the trait bound `(): From` is not satisfied Ok(()) @@ -57,8 +57,8 @@ pub fn takes_apit(_y: impl Fn() -> T) -> Result { } pub fn fallback_return() -> Result<(), ()> { - //[e2021]~^ this function depends on never type fallback being `()` - //[e2021]~| this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! + //[e2021]~^ WARN this function depends on never type fallback being `()` + //[e2021]~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! takes_apit(|| Default::default())?; //[e2024]~^ error: the trait bound `!: Default` is not satisfied Ok(()) @@ -71,8 +71,8 @@ fn mk() -> Result { fn takes_apit2(_x: impl Default) {} fn fully_apit() -> Result<(), ()> { - //[e2021]~^ this function depends on never type fallback being `()` - //[e2021]~| this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! + //[e2021]~^ WARN this function depends on never type fallback being `()` + //[e2021]~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! takes_apit2(mk()?); //[e2024]~^ error: the trait bound `!: Default` is not satisfied Ok(()) diff --git a/tests/ui/enum-discriminant/discriminant-ill-typed.rs b/tests/ui/enum-discriminant/discriminant-ill-typed.rs index 3cf0ea0e6b99..e3cbd01a1ddf 100644 --- a/tests/ui/enum-discriminant/discriminant-ill-typed.rs +++ b/tests/ui/enum-discriminant/discriminant-ill-typed.rs @@ -14,7 +14,7 @@ fn f_i8() { Ok2, OhNo = 0_u8, //~^ ERROR mismatched types - //~| expected `i8`, found `u8` + //~| NOTE expected `i8`, found `u8` } let x = A::Ok; @@ -27,7 +27,7 @@ fn f_u8() { Ok2, OhNo = 0_i8, //~^ ERROR mismatched types - //~| expected `u8`, found `i8` + //~| NOTE expected `u8`, found `i8` } let x = A::Ok; @@ -40,7 +40,7 @@ fn f_i16() { Ok2, OhNo = 0_u16, //~^ ERROR mismatched types - //~| expected `i16`, found `u16` + //~| NOTE expected `i16`, found `u16` } let x = A::Ok; @@ -53,7 +53,7 @@ fn f_u16() { Ok2, OhNo = 0_i16, //~^ ERROR mismatched types - //~| expected `u16`, found `i16` + //~| NOTE expected `u16`, found `i16` } let x = A::Ok; @@ -66,7 +66,7 @@ fn f_i32() { Ok2, OhNo = 0_u32, //~^ ERROR mismatched types - //~| expected `i32`, found `u32` + //~| NOTE expected `i32`, found `u32` } let x = A::Ok; @@ -79,7 +79,7 @@ fn f_u32() { Ok2, OhNo = 0_i32, //~^ ERROR mismatched types - //~| expected `u32`, found `i32` + //~| NOTE expected `u32`, found `i32` } let x = A::Ok; @@ -92,7 +92,7 @@ fn f_i64() { Ok2, OhNo = 0_u64, //~^ ERROR mismatched types - //~| expected `i64`, found `u64` + //~| NOTE expected `i64`, found `u64` } let x = A::Ok; @@ -105,7 +105,7 @@ fn f_u64() { Ok2, OhNo = 0_i64, //~^ ERROR mismatched types - //~| expected `u64`, found `i64` + //~| NOTE expected `u64`, found `i64` } let x = A::Ok; diff --git a/tests/ui/error-codes/E0063.rs b/tests/ui/error-codes/E0063.rs index 48c9c13f018f..2ef09b0a426a 100644 --- a/tests/ui/error-codes/E0063.rs +++ b/tests/ui/error-codes/E0063.rs @@ -32,7 +32,7 @@ fn main() { let x = PluralFoo {x: 1}; //~^ ERROR missing fields `y` and `z` in initializer of `PluralFoo` let y = TruncatedFoo{x:1}; - //~^ missing fields `a`, `b`, `y` and 1 other field in initializer of `TruncatedFoo` + //~^ ERROR missing fields `a`, `b`, `y` and 1 other field in initializer of `TruncatedFoo` let z = TruncatedPluralFoo{x:1}; //~^ ERROR missing fields `a`, `b`, `c` and 2 other fields in initializer of `TruncatedPluralFoo` } diff --git a/tests/ui/error-codes/E0186.rs b/tests/ui/error-codes/E0186.rs index 83ef78ef2c03..9b507f9b9882 100644 --- a/tests/ui/error-codes/E0186.rs +++ b/tests/ui/error-codes/E0186.rs @@ -1,12 +1,12 @@ trait Foo { - fn foo(&self); //~ `&self` used in trait + fn foo(&self); //~ NOTE `&self` used in trait } struct Bar; impl Foo for Bar { fn foo() {} //~ ERROR E0186 - //~^ expected `&self` in impl + //~^ NOTE expected `&self` in impl } fn main() { diff --git a/tests/ui/error-codes/E0261.rs b/tests/ui/error-codes/E0261.rs index f05e09aa0da6..e37eab9501ed 100644 --- a/tests/ui/error-codes/E0261.rs +++ b/tests/ui/error-codes/E0261.rs @@ -1,9 +1,9 @@ fn foo(x: &'a str) { } //~ ERROR E0261 - //~| undeclared lifetime + //~| NOTE undeclared lifetime struct Foo { x: &'a str, //~ ERROR E0261 - //~| undeclared lifetime + //~| NOTE undeclared lifetime } fn main() {} diff --git a/tests/ui/error-codes/E0262.rs b/tests/ui/error-codes/E0262.rs index 55264f1387f8..460ea95148c4 100644 --- a/tests/ui/error-codes/E0262.rs +++ b/tests/ui/error-codes/E0262.rs @@ -1,4 +1,4 @@ fn foo<'static>(x: &'static str) { } //~ ERROR E0262 - //~| 'static is a reserved lifetime name + //~| NOTE 'static is a reserved lifetime name fn main() {} diff --git a/tests/ui/error-codes/E0516.rs b/tests/ui/error-codes/E0516.rs index 834bb630989f..f81b98cdadc8 100644 --- a/tests/ui/error-codes/E0516.rs +++ b/tests/ui/error-codes/E0516.rs @@ -1,4 +1,4 @@ fn main() { let x: typeof(92) = 92; //~ ERROR E0516 - //~| reserved keyword + //~| NOTE reserved keyword } diff --git a/tests/ui/error-codes/E0597.rs b/tests/ui/error-codes/E0597.rs index 7217e351281d..ebe42f54212f 100644 --- a/tests/ui/error-codes/E0597.rs +++ b/tests/ui/error-codes/E0597.rs @@ -6,7 +6,7 @@ fn main() { let mut x = Foo { x: None }; let y = 0; x.x = Some(&y); - //~^ `y` does not live long enough [E0597] + //~^ ERROR `y` does not live long enough [E0597] } impl<'a> Drop for Foo<'a> { fn drop(&mut self) { } } diff --git a/tests/ui/error-codes/E0606.rs b/tests/ui/error-codes/E0606.rs index 6f6c6513846c..2d430fcdc169 100644 --- a/tests/ui/error-codes/E0606.rs +++ b/tests/ui/error-codes/E0606.rs @@ -1,4 +1,4 @@ fn main() { let x = &(&0u8 as u8); //~ ERROR E0606 - x as u8; //~ casting `&u8` as `u8` is invalid [E0606] + x as u8; //~ ERROR casting `&u8` as `u8` is invalid [E0606] } diff --git a/tests/ui/extern/extern-main-issue-86110.rs b/tests/ui/extern/extern-main-issue-86110.rs index 83af7a14ccc7..007d13717040 100644 --- a/tests/ui/extern/extern-main-issue-86110.rs +++ b/tests/ui/extern/extern-main-issue-86110.rs @@ -2,6 +2,6 @@ extern "C" { fn missing(); fn main(); - //~^ the `main` function cannot be declared in an `extern` block + //~^ ERROR the `main` function cannot be declared in an `extern` block fn missing2(); } diff --git a/tests/ui/extern/issue-112363-extern-item-where-clauses-debug-ice.rs b/tests/ui/extern/issue-112363-extern-item-where-clauses-debug-ice.rs index 17e08f511d71..6a4b7814ef18 100644 --- a/tests/ui/extern/issue-112363-extern-item-where-clauses-debug-ice.rs +++ b/tests/ui/extern/issue-112363-extern-item-where-clauses-debug-ice.rs @@ -1,10 +1,10 @@ extern "C" { type Item = [T] where [T]: Sized; - //~^ incorrect `type` inside `extern` block - //~| `type`s inside `extern` blocks cannot have `where` clauses - //~| cannot find type `T` in this scope - //~| cannot find type `T` in this scope - //~| extern types are experimental + //~^ ERROR incorrect `type` inside `extern` block + //~| ERROR `type`s inside `extern` blocks cannot have `where` clauses + //~| ERROR cannot find type `T` in this scope + //~| ERROR cannot find type `T` in this scope + //~| ERROR extern types are experimental } fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-c_variadic.rs b/tests/ui/feature-gates/feature-gate-c_variadic.rs index 8b40c36c7db5..f189f02a26dd 100644 --- a/tests/ui/feature-gates/feature-gate-c_variadic.rs +++ b/tests/ui/feature-gates/feature-gate-c_variadic.rs @@ -1,4 +1,4 @@ #![crate_type="lib"] pub unsafe extern "C" fn test(_: i32, ap: ...) { } -//~^ C-variadic functions are unstable +//~^ ERROR C-variadic functions are unstable diff --git a/tests/ui/feature-gates/feature-gate-cfg-emscripten-wasm-eh.rs b/tests/ui/feature-gates/feature-gate-cfg-emscripten-wasm-eh.rs index cff98b43fe74..232061e239c9 100644 --- a/tests/ui/feature-gates/feature-gate-cfg-emscripten-wasm-eh.rs +++ b/tests/ui/feature-gates/feature-gate-cfg-emscripten-wasm-eh.rs @@ -1,4 +1,4 @@ //@ compile-flags: --check-cfg=cfg(emscripten_wasm_eh) #[cfg(not(emscripten_wasm_eh))] -//~^ `cfg(emscripten_wasm_eh)` is experimental +//~^ ERROR `cfg(emscripten_wasm_eh)` is experimental fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-cfg-sanitizer_cfi.rs b/tests/ui/feature-gates/feature-gate-cfg-sanitizer_cfi.rs index 76d96de750a6..1419a978138a 100644 --- a/tests/ui/feature-gates/feature-gate-cfg-sanitizer_cfi.rs +++ b/tests/ui/feature-gates/feature-gate-cfg-sanitizer_cfi.rs @@ -1,9 +1,9 @@ #[cfg(sanitizer_cfi_generalize_pointers)] -//~^ `cfg(sanitizer_cfi_generalize_pointers)` is experimental +//~^ ERROR `cfg(sanitizer_cfi_generalize_pointers)` is experimental fn foo() {} #[cfg(sanitizer_cfi_normalize_integers)] -//~^ `cfg(sanitizer_cfi_normalize_integers)` is experimental +//~^ ERROR `cfg(sanitizer_cfi_normalize_integers)` is experimental fn bar() {} fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-cfg_sanitize.rs b/tests/ui/feature-gates/feature-gate-cfg_sanitize.rs index c3e7cc9ed8a9..0933f43e76b6 100644 --- a/tests/ui/feature-gates/feature-gate-cfg_sanitize.rs +++ b/tests/ui/feature-gates/feature-gate-cfg_sanitize.rs @@ -1,3 +1,3 @@ #[cfg(not(sanitize = "thread"))] -//~^ `cfg(sanitize)` is experimental +//~^ ERROR `cfg(sanitize)` is experimental fn main() {} 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 d90fb765a237..d7cfc13cae55 100644 --- a/tests/ui/feature-gates/feature-gate-closure_track_caller.rs +++ b/tests/ui/feature-gates/feature-gate-closure_track_caller.rs @@ -3,7 +3,7 @@ #![feature(coroutines)] fn main() { - let _closure = #[track_caller] || {}; //~ `#[track_caller]` on closures - let _coroutine = #[coroutine] #[track_caller] || { yield; }; //~ `#[track_caller]` on closures - let _future = #[track_caller] async {}; //~ `#[track_caller]` on closures + let _closure = #[track_caller] || {}; //~ ERROR `#[track_caller]` on closures + let _coroutine = #[coroutine] #[track_caller] || { yield; }; //~ ERROR `#[track_caller]` on closures + let _future = #[track_caller] async {}; //~ ERROR `#[track_caller]` on closures } diff --git a/tests/ui/feature-gates/feature-gate-custom_mir.rs b/tests/ui/feature-gates/feature-gate-custom_mir.rs index e100df08ee70..4d713c524b33 100644 --- a/tests/ui/feature-gates/feature-gate-custom_mir.rs +++ b/tests/ui/feature-gates/feature-gate-custom_mir.rs @@ -1,13 +1,13 @@ #![feature(core_intrinsics)] extern crate core; -use core::intrinsics::mir::*; //~ custom_mir +use core::intrinsics::mir::*; //~ ERROR custom_mir #[custom_mir(dialect = "built")] //~ ERROR the `#[custom_mir]` attribute is just used for the Rust test suite pub fn foo(_x: i32) -> i32 { mir! { { - Return() //~ custom_mir + Return() //~ ERROR custom_mir } } } diff --git a/tests/ui/feature-gates/feature-gate-freeze-impls.rs b/tests/ui/feature-gates/feature-gate-freeze-impls.rs index c14c9494874a..401095dd83ba 100644 --- a/tests/ui/feature-gates/feature-gate-freeze-impls.rs +++ b/tests/ui/feature-gates/feature-gate-freeze-impls.rs @@ -5,11 +5,11 @@ use std::marker::Freeze; struct Foo; unsafe impl Freeze for Foo {} -//~^ explicit impls for the `Freeze` trait are not permitted +//~^ ERROR explicit impls for the `Freeze` trait are not permitted struct Bar; impl !Freeze for Bar {} -//~^ explicit impls for the `Freeze` trait are not permitted +//~^ ERROR explicit impls for the `Freeze` trait are not permitted fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-naked_functions.rs b/tests/ui/feature-gates/feature-gate-naked_functions.rs index abb55b9a557a..77a67e0696eb 100644 --- a/tests/ui/feature-gates/feature-gate-naked_functions.rs +++ b/tests/ui/feature-gates/feature-gate-naked_functions.rs @@ -4,7 +4,7 @@ use std::arch::naked_asm; //~^ ERROR use of unstable library feature `naked_functions` #[naked] -//~^ the `#[naked]` attribute is an experimental feature +//~^ ERROR the `#[naked]` attribute is an experimental feature extern "C" fn naked() { naked_asm!("") //~^ ERROR use of unstable library feature `naked_functions` @@ -12,7 +12,7 @@ extern "C" fn naked() { } #[naked] -//~^ the `#[naked]` attribute is an experimental feature +//~^ ERROR the `#[naked]` attribute is an experimental feature extern "C" fn naked_2() -> isize { naked_asm!("") //~^ ERROR use of unstable library feature `naked_functions` diff --git a/tests/ui/feature-gates/feature-gate-new_range.rs b/tests/ui/feature-gates/feature-gate-new_range.rs index ecb73546d6a6..32eeb0424b64 100644 --- a/tests/ui/feature-gates/feature-gate-new_range.rs +++ b/tests/ui/feature-gates/feature-gate-new_range.rs @@ -2,9 +2,9 @@ fn main() { let a: core::range::RangeFrom = 1..; - //~^ mismatched types + //~^ ERROR mismatched types let b: core::range::Range = 2..3; - //~^ mismatched types + //~^ ERROR mismatched types let c: core::range::RangeInclusive = 4..=5; - //~^ mismatched types + //~^ ERROR mismatched types } diff --git a/tests/ui/feature-gates/feature-gate-no_sanitize.rs b/tests/ui/feature-gates/feature-gate-no_sanitize.rs index 66a9263e13a5..5ac014f1c5bf 100644 --- a/tests/ui/feature-gates/feature-gate-no_sanitize.rs +++ b/tests/ui/feature-gates/feature-gate-no_sanitize.rs @@ -1,4 +1,4 @@ #[no_sanitize(address)] -//~^ the `#[no_sanitize]` attribute is an experimental feature +//~^ ERROR the `#[no_sanitize]` attribute is an experimental feature fn main() { } diff --git a/tests/ui/feature-gates/feature-gate-rustc_const_unstable.rs b/tests/ui/feature-gates/feature-gate-rustc_const_unstable.rs index d7daaaaa101e..522db1643fd4 100644 --- a/tests/ui/feature-gates/feature-gate-rustc_const_unstable.rs +++ b/tests/ui/feature-gates/feature-gate-rustc_const_unstable.rs @@ -1,6 +1,6 @@ // Test internal const fn feature gate. -#[rustc_const_unstable(feature="fzzzzzt")] //~ stability attributes may not be used outside +#[rustc_const_unstable(feature="fzzzzzt")] //~ ERROR stability attributes may not be used outside pub const fn bazinga() {} fn main() { diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs index a196b8ecdb3e..d07201ebbd1a 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs @@ -174,16 +174,16 @@ mod macro_use { mod inner { #![macro_use] } #[macro_use] fn f() { } - //~^ `#[macro_use]` only has an effect + //~^ WARN `#[macro_use]` only has an effect #[macro_use] struct S; - //~^ `#[macro_use]` only has an effect + //~^ WARN `#[macro_use]` only has an effect #[macro_use] type T = S; - //~^ `#[macro_use]` only has an effect + //~^ WARN `#[macro_use]` only has an effect #[macro_use] impl S { } - //~^ `#[macro_use]` only has an effect + //~^ WARN `#[macro_use]` only has an effect } #[macro_export] diff --git a/tests/ui/foreign/issue-74120-lowering-of-ffi-block-bodies.rs b/tests/ui/foreign/issue-74120-lowering-of-ffi-block-bodies.rs index 7f1625c9265a..97cf3e9d51cd 100644 --- a/tests/ui/foreign/issue-74120-lowering-of-ffi-block-bodies.rs +++ b/tests/ui/foreign/issue-74120-lowering-of-ffi-block-bodies.rs @@ -5,7 +5,7 @@ extern "C" { fn f() { - //~^ incorrect function inside `extern` block + //~^ ERROR incorrect function inside `extern` block fn g() {} } } diff --git a/tests/ui/foreign/issue-91370-foreign-fn-block-impl.rs b/tests/ui/foreign/issue-91370-foreign-fn-block-impl.rs index e8634de86ea4..23e08e01e6a6 100644 --- a/tests/ui/foreign/issue-91370-foreign-fn-block-impl.rs +++ b/tests/ui/foreign/issue-91370-foreign-fn-block-impl.rs @@ -3,7 +3,7 @@ extern "C" { //~^ `extern` blocks define existing foreign functions fn f() { - //~^ incorrect function inside `extern` block + //~^ ERROR incorrect function inside `extern` block //~| cannot have a body impl Copy for u8 {} } diff --git a/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.rs b/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.rs index 5f2e134109e2..6ba3c4c65d07 100644 --- a/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.rs +++ b/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.rs @@ -13,7 +13,7 @@ fn cmp_eq<'a, 'b, A: Scalar, B: Scalar, O: Scalar>(a: A::RefType<'a>, b: B::RefT fn build_expression( ) -> impl Fn(A::RefType<'_>, B::RefType<'_>) -> O { - //[next]~^^ expected a `Fn(::RefType<'_>, ::RefType<'_>)` closure + //[next]~^^ ERROR expected a `Fn(::RefType<'_>, ::RefType<'_>)` closure cmp_eq //~^ ERROR type annotations needed } diff --git a/tests/ui/generic-associated-types/bugs/hrtb-implied-3.rs b/tests/ui/generic-associated-types/bugs/hrtb-implied-3.rs index bc9e6c8aea85..8f2b5bf8f526 100644 --- a/tests/ui/generic-associated-types/bugs/hrtb-implied-3.rs +++ b/tests/ui/generic-associated-types/bugs/hrtb-implied-3.rs @@ -17,7 +17,7 @@ where fn fails(iter: &str) { trivial_bound(iter); - //~^ borrowed data escapes + //~^ ERROR borrowed data escapes } fn main() {} diff --git a/tests/ui/generic-associated-types/collectivity-regression.rs b/tests/ui/generic-associated-types/collectivity-regression.rs index 54154f9d1fc8..d499a9ca8580 100644 --- a/tests/ui/generic-associated-types/collectivity-regression.rs +++ b/tests/ui/generic-associated-types/collectivity-regression.rs @@ -11,7 +11,7 @@ where for<'a> T: Get = ()>, { || { - //~^ `T` does not live long enough + //~^ ERROR `T` does not live long enough // // FIXME(#98437). This regressed at some point and // probably should work. diff --git a/tests/ui/generic-associated-types/gat-in-trait-path.rs b/tests/ui/generic-associated-types/gat-in-trait-path.rs index 24cae213e0aa..7523803eacff 100644 --- a/tests/ui/generic-associated-types/gat-in-trait-path.rs +++ b/tests/ui/generic-associated-types/gat-in-trait-path.rs @@ -20,11 +20,11 @@ impl Foo for Fooer { } fn f(_arg : Box Foo = &'a ()>>) {} -//~^ the trait `Foo` is not dyn compatible +//~^ ERROR the trait `Foo` is not dyn compatible fn main() { let foo = Fooer(5); f(Box::new(foo)); - //~^ the trait `Foo` is not dyn compatible - //~| the trait `Foo` is not dyn compatible + //~^ ERROR the trait `Foo` is not dyn compatible + //~| ERROR the trait `Foo` is not dyn compatible } diff --git a/tests/ui/generic-associated-types/issue-74816.rs b/tests/ui/generic-associated-types/issue-74816.rs index e2f4ddc7485c..6ec0b3261739 100644 --- a/tests/ui/generic-associated-types/issue-74816.rs +++ b/tests/ui/generic-associated-types/issue-74816.rs @@ -11,7 +11,7 @@ trait Trait1 { trait Trait2 { type Associated: Trait1 = Self; //~^ ERROR: the trait bound `Self: Trait1` is not satisfied - //~| the size for values of type `Self` cannot be known + //~| ERROR the size for values of type `Self` cannot be known } impl Trait2 for () {} diff --git a/tests/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.rs b/tests/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.rs index 1c94067029da..f913efd75779 100644 --- a/tests/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.rs +++ b/tests/ui/generic-associated-types/issue-78113-lifetime-mismatch-dyn-trait-box.rs @@ -12,7 +12,7 @@ pub trait B { impl B for () { // `'a` doesn't match implicit `'static`: suggest `'_` - type T<'a> = Box; //~ incompatible lifetime on type + type T<'a> = Box; //~ ERROR incompatible lifetime on type } trait C {} @@ -22,7 +22,7 @@ pub trait D { } impl D for () { // `'a` doesn't match explicit `'static`: we *should* suggest removing `'static` - type T<'a> = Box; //~ incompatible lifetime on type + type T<'a> = Box; //~ ERROR incompatible lifetime on type } trait E {} @@ -32,7 +32,7 @@ pub trait F { } impl F for () { // `'a` doesn't match explicit `'static`: suggest `'_` - type T<'a> = (Box, Box); //~ incompatible lifetime on type + type T<'a> = (Box, Box); //~ ERROR incompatible lifetime on type } fn main() {} diff --git a/tests/ui/generic-associated-types/issue-86787.rs b/tests/ui/generic-associated-types/issue-86787.rs index 88cdd472696b..43c193b91d05 100644 --- a/tests/ui/generic-associated-types/issue-86787.rs +++ b/tests/ui/generic-associated-types/issue-86787.rs @@ -8,7 +8,7 @@ enum Either { pub trait HasChildrenOf { type T; type TRef<'a>; - //~^ missing required + //~^ ERROR missing required fn ref_children<'a>(&'a self) -> Vec>; fn take_children(self) -> Vec; diff --git a/tests/ui/generic-associated-types/issue-88360.fixed b/tests/ui/generic-associated-types/issue-88360.fixed index 2ebc459f1974..f24a86b240b8 100644 --- a/tests/ui/generic-associated-types/issue-88360.fixed +++ b/tests/ui/generic-associated-types/issue-88360.fixed @@ -14,7 +14,7 @@ where { fn copy(&self) -> Self::Gat<'_> where T: Copy { self.test() - //~^ mismatched types + //~^ ERROR mismatched types } } diff --git a/tests/ui/generic-associated-types/issue-88360.rs b/tests/ui/generic-associated-types/issue-88360.rs index 011061dd8613..12c18061d043 100644 --- a/tests/ui/generic-associated-types/issue-88360.rs +++ b/tests/ui/generic-associated-types/issue-88360.rs @@ -14,7 +14,7 @@ where { fn copy(&self) -> Self::Gat<'_> where T: Copy { *self.test() - //~^ mismatched types + //~^ ERROR mismatched types } } diff --git a/tests/ui/generic-associated-types/missing-where-clause-on-trait.rs b/tests/ui/generic-associated-types/missing-where-clause-on-trait.rs index c8a924663110..5354421f4b9b 100644 --- a/tests/ui/generic-associated-types/missing-where-clause-on-trait.rs +++ b/tests/ui/generic-associated-types/missing-where-clause-on-trait.rs @@ -5,7 +5,7 @@ trait Foo { } impl Foo for () { type Assoc<'a, 'b> = () where 'a: 'b; - //~^ impl has stricter requirements than trait + //~^ ERROR impl has stricter requirements than trait } fn main() {} diff --git a/tests/ui/generic-associated-types/self-outlives-lint.rs b/tests/ui/generic-associated-types/self-outlives-lint.rs index 699b3a8c5092..2e58a72fb5c2 100644 --- a/tests/ui/generic-associated-types/self-outlives-lint.rs +++ b/tests/ui/generic-associated-types/self-outlives-lint.rs @@ -5,7 +5,7 @@ use std::fmt::Debug; // We have a `&'a self`, so we need a `Self: 'a` trait Iterable { type Item<'x>; - //~^ missing required + //~^ ERROR missing required fn iter<'a>(&'a self) -> Self::Item<'a>; } @@ -21,7 +21,7 @@ impl Iterable for T { // We have a `&'a T`, so we need a `T: 'x` trait Deserializer { type Out<'x>; - //~^ missing required + //~^ ERROR missing required fn deserialize<'a>(&self, input: &'a T) -> Self::Out<'a>; } @@ -35,14 +35,14 @@ impl Deserializer for () { // We have a `&'b T` and a `'b: 'a`, so it is implied that `T: 'a`. Therefore, we need a `T: 'x` trait Deserializer2 { type Out<'x>; - //~^ missing required + //~^ ERROR missing required fn deserialize2<'a, 'b: 'a>(&self, input1: &'b T) -> Self::Out<'a>; } // We have a `&'a T` and a `&'b U`, so we need a `T: 'x` and a `U: 'y` trait Deserializer3 { type Out<'x, 'y>; - //~^ missing required + //~^ ERROR missing required fn deserialize2<'a, 'b>(&self, input: &'a T, input2: &'b U) -> Self::Out<'a, 'b>; } @@ -57,7 +57,7 @@ struct Wrap(T); // We pass `Wrap` and we see `&'z Wrap`, so we require `D: 'x` trait Des { type Out<'x, D>; - //~^ missing required + //~^ ERROR missing required fn des<'z, T>(&self, data: &'z Wrap) -> Self::Out<'z, Wrap>; } /* @@ -73,7 +73,7 @@ impl Des for () { // implied bound that `T: 'z`, so we require `D: 'x` trait Des2 { type Out<'x, D>; - //~^ missing required + //~^ ERROR missing required fn des<'z, T>(&self, data: &'z Wrap) -> Self::Out<'z, T>; } /* @@ -88,7 +88,7 @@ impl Des2 for () { // We see `&'z T`, so we require `D: 'x` trait Des3 { type Out<'x, D>; - //~^ missing required + //~^ ERROR missing required fn des<'z, T>(&self, data: &'z T) -> Self::Out<'z, T>; } /* @@ -110,7 +110,7 @@ trait NoGat<'a> { // FIXME: we require two bounds (`where Self: 'a, Self: 'b`) when we should only require one trait TraitLifetime<'a> { type Bar<'b>; - //~^ missing required + //~^ ERROR missing required fn method(&'a self) -> Self::Bar<'a>; } @@ -118,14 +118,14 @@ trait TraitLifetime<'a> { // FIXME: we require two bounds (`where Self: 'a, Self: 'b`) when we should only require one trait TraitLifetimeWhere<'a> where Self: 'a { type Bar<'b>; - //~^ missing required + //~^ ERROR missing required fn method(&'a self) -> Self::Bar<'a>; } // Explicit bound instead of implicit; we want to still error trait ExplicitBound { type Bar<'b>; - //~^ missing required + //~^ ERROR missing required fn method<'b>(&self, token: &'b ()) -> Self::Bar<'b> where Self: 'b; } @@ -138,15 +138,15 @@ trait NotInReturn { // We obviously error for `Iterator`, but we should also error for `Item` trait IterableTwo { type Item<'a>; - //~^ missing required + //~^ ERROR missing required type Iterator<'a>: Iterator>; - //~^ missing required + //~^ ERROR missing required fn iter<'a>(&'a self) -> Self::Iterator<'a>; } trait IterableTwoWhere { type Item<'a>; - //~^ missing required + //~^ ERROR missing required type Iterator<'a>: Iterator> where Self: 'a; fn iter<'a>(&'a self) -> Self::Iterator<'a>; } @@ -155,7 +155,7 @@ trait IterableTwoWhere { // because of `&'x &'y`, so we require that `'b: 'a`. trait RegionOutlives { type Bar<'a, 'b>; - //~^ missing required + //~^ ERROR missing required fn foo<'x, 'y>(&self, input: &'x &'y ()) -> Self::Bar<'x, 'y>; } @@ -171,7 +171,7 @@ impl Foo for () { // Similar to the above, except with explicit bounds trait ExplicitRegionOutlives<'ctx> { type Fut<'out>; - //~^ missing required + //~^ ERROR missing required fn test<'out>(ctx: &'ctx i32) -> Self::Fut<'out> where @@ -211,7 +211,7 @@ trait StaticReturnAndTakes<'a> { // We require bounds when the GAT appears in the inputs trait Input { type Item<'a>; - //~^ missing required + //~^ ERROR missing required fn takes_item<'a>(&'a self, item: Self::Item<'a>); } diff --git a/tests/ui/generic-associated-types/trait-objects.rs b/tests/ui/generic-associated-types/trait-objects.rs index ed324b562e1c..256cfee4c809 100644 --- a/tests/ui/generic-associated-types/trait-objects.rs +++ b/tests/ui/generic-associated-types/trait-objects.rs @@ -6,10 +6,10 @@ trait StreamingIterator { } fn min_size(x: &mut dyn for<'a> StreamingIterator = &'a i32>) -> usize { - //~^ the trait `StreamingIterator` is not dyn compatible + //~^ ERROR the trait `StreamingIterator` is not dyn compatible x.size_hint().0 - //~^ the trait `StreamingIterator` is not dyn compatible - //~| the trait `StreamingIterator` is not dyn compatible + //~^ ERROR the trait `StreamingIterator` is not dyn compatible + //~| ERROR the trait `StreamingIterator` is not dyn compatible } fn main() {} diff --git a/tests/ui/generic-associated-types/type-param-defaults.rs b/tests/ui/generic-associated-types/type-param-defaults.rs index a9c8c5c12d9e..eea54c460734 100644 --- a/tests/ui/generic-associated-types/type-param-defaults.rs +++ b/tests/ui/generic-associated-types/type-param-defaults.rs @@ -4,17 +4,17 @@ trait Trait { type Assoc; - //~^ defaults for type parameters are only allowed + //~^ ERROR defaults for type parameters are only allowed } impl Trait for () { type Assoc = u64; - //~^ defaults for type parameters are only allowed + //~^ ERROR defaults for type parameters are only allowed } impl Trait for u32 { type Assoc = T; - //~^ defaults for type parameters are only allowed + //~^ ERROR defaults for type parameters are only allowed } trait Other {} diff --git a/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.rs b/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.rs index a7b0ca6fe4a5..f2c873f3edf1 100644 --- a/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.rs +++ b/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.rs @@ -1,6 +1,6 @@ fn main() { let xs = [13, 1, 5, 2, 3, 1, 21, 8]; let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs; - //~^ `X..` patterns in slices are experimental + //~^ ERROR `X..` patterns in slices are experimental //~| ERROR: refutable pattern } diff --git a/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem0.rs b/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem0.rs index aa2690f37776..7bd1c100dc4f 100644 --- a/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem0.rs +++ b/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem0.rs @@ -8,7 +8,7 @@ fn main() { // What if we wanted to pull this apart without individually binding a, b, and c? let [first_three @ ..3, rest @ 2..] = xs; - //~^ pattern requires 2 elements but array has 8 + //~^ ERROR pattern requires 2 elements but array has 8 // This is somewhat unintuitive and makes slice patterns exceedingly verbose. // We want to stabilize half-open RangeFrom (`X..`) patterns // but without banning us from using them for a more efficient slice pattern syntax. diff --git a/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.rs b/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.rs index 60b056fbcb69..12ceaa8c878c 100644 --- a/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.rs +++ b/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.rs @@ -2,6 +2,6 @@ fn main() { let xs = [13, 1, 5, 2, 3, 1, 21, 8]; let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs; - //~^ `X..` patterns in slices are experimental + //~^ ERROR `X..` patterns in slices are experimental //~| ERROR: refutable pattern } diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.rs index d84e30f4984e..10bfc954a474 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.rs +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.rs @@ -23,7 +23,7 @@ impl WithDefault for () { //f(()); // Going through another generic function works fine. call(f, ()); - //~^ expected a + //~^ ERROR expected a } } diff --git a/tests/ui/illegal-sized-bound/regular.rs b/tests/ui/illegal-sized-bound/regular.rs index 7abd27ef9831..b5a4cbf10eca 100644 --- a/tests/ui/illegal-sized-bound/regular.rs +++ b/tests/ui/illegal-sized-bound/regular.rs @@ -4,7 +4,7 @@ pub trait MutTrait { fn function(&mut self) where Self: Sized; - //~^ this has a `Sized` requirement + //~^ NOTE this has a `Sized` requirement } impl MutTrait for MutType { @@ -17,7 +17,7 @@ pub trait Trait { fn function(&self) where Self: Sized; - //~^ this has a `Sized` requirement + //~^ NOTE this has a `Sized` requirement } impl Trait for Type { diff --git a/tests/ui/impl-trait/call_method_ambiguous.rs b/tests/ui/impl-trait/call_method_ambiguous.rs index 8fd6f727b73f..6bcafc8ce149 100644 --- a/tests/ui/impl-trait/call_method_ambiguous.rs +++ b/tests/ui/impl-trait/call_method_ambiguous.rs @@ -24,7 +24,7 @@ where fn foo(n: usize, m: &mut ()) -> impl Get + use<'_> { if n > 0 { let mut iter = foo(n - 1, m); - //[next]~^ type annotations needed + //[next]~^ ERROR type annotations needed assert_eq!(iter.get(), 1); } m diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl.rs b/tests/ui/impl-trait/call_method_on_inherent_impl.rs index 17f7cad660db..0e333c3260a2 100644 --- a/tests/ui/impl-trait/call_method_on_inherent_impl.rs +++ b/tests/ui/impl-trait/call_method_on_inherent_impl.rs @@ -16,7 +16,7 @@ where fn my_foo() -> impl std::fmt::Debug { if false { let x = my_foo(); - //[next]~^ type annotations needed + //[next]~^ ERROR type annotations needed x.my_debug(); } () diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl_ref.rs b/tests/ui/impl-trait/call_method_on_inherent_impl_ref.rs index abe60e5e45a3..4e4098b37f93 100644 --- a/tests/ui/impl-trait/call_method_on_inherent_impl_ref.rs +++ b/tests/ui/impl-trait/call_method_on_inherent_impl_ref.rs @@ -15,9 +15,9 @@ where fn my_foo() -> impl std::fmt::Debug { if false { let x = my_foo(); - //[next]~^ type annotations needed + //[next]~^ ERROR type annotations needed x.my_debug(); - //[current]~^ no method named `my_debug` found + //[current]~^ ERROR no method named `my_debug` found } () } @@ -25,7 +25,7 @@ fn my_foo() -> impl std::fmt::Debug { fn my_bar() -> impl std::fmt::Debug { if false { let x = &my_bar(); - //[next]~^ type annotations needed + //[next]~^ ERROR type annotations needed x.my_debug(); } () diff --git a/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.rs b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.rs index a5a37dbb210f..0b507ed948ae 100644 --- a/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.rs +++ b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.rs @@ -27,7 +27,7 @@ impl X for Y { //~| ERROR: unconstrained opaque type type LineStreamFut<'a, Repr> = impl Future>; fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {} - //~^ method `line_stream` is not a member of trait `X` + //~^ ERROR method `line_stream` is not a member of trait `X` //[current]~^^ ERROR `()` is not a future //[next]~^^^ ERROR type mismatch resolving `::LineStreamFut<'a, Repr> == ()` //[next]~| ERROR type mismatch resolving `::LineStreamFut<'a, Repr> normalizes-to _` diff --git a/tests/ui/impl-trait/implicit-capture-late.rs b/tests/ui/impl-trait/implicit-capture-late.rs index 13cbcd66f8d8..57a00357c711 100644 --- a/tests/ui/impl-trait/implicit-capture-late.rs +++ b/tests/ui/impl-trait/implicit-capture-late.rs @@ -6,7 +6,7 @@ use std::ops::Deref; -fn foo(x: Vec) -> Box Deref> { //~ ['a: o] +fn foo(x: Vec) -> Box Deref> { //~ ERROR ['a: o] //~^ ERROR cannot capture higher-ranked lifetime Box::new(x) } diff --git a/tests/ui/impl-trait/in-trait/default-body-type-err.rs b/tests/ui/impl-trait/in-trait/default-body-type-err.rs index ac7a50a365ea..0cd59bf0feb2 100644 --- a/tests/ui/impl-trait/in-trait/default-body-type-err.rs +++ b/tests/ui/impl-trait/in-trait/default-body-type-err.rs @@ -2,7 +2,7 @@ use std::ops::Deref; pub trait Foo { fn lol(&self) -> impl Deref { - //~^ type mismatch resolving `<&i32 as Deref>::Target == String` + //~^ ERROR type mismatch resolving `<&i32 as Deref>::Target == String` &1i32 } } diff --git a/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf-via-param.rs b/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf-via-param.rs index 7a3a59d37c6a..65c4542e2359 100644 --- a/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf-via-param.rs +++ b/tests/ui/impl-trait/in-trait/rpitit-hidden-types-self-implied-wf-via-param.rs @@ -6,7 +6,7 @@ impl Extend for () { fn extend<'a: 'a>(s: &'a str) -> (Option<&'static &'a ()>, &'static str) where 'a: 'static, - //~^ impl has stricter requirements than trait + //~^ ERROR impl has stricter requirements than trait { (None, s) } diff --git a/tests/ui/impl-trait/in-trait/variance.rs b/tests/ui/impl-trait/in-trait/variance.rs index c0f569c690ab..f0b8c05b2d71 100644 --- a/tests/ui/impl-trait/in-trait/variance.rs +++ b/tests/ui/impl-trait/in-trait/variance.rs @@ -4,22 +4,22 @@ trait Foo<'i> { fn implicit_capture_early<'a: 'a>() -> impl Sized {} - //~^ [Self: o, 'i: o, 'a: *, 'i: o, 'a: o] + //~^ ERROR [Self: o, 'i: o, 'a: *, 'i: o, 'a: o] fn explicit_capture_early<'a: 'a>() -> impl Sized + use<'i, 'a, Self> {} - //~^ [Self: o, 'i: o, 'a: *, 'i: o, 'a: o] + //~^ ERROR [Self: o, 'i: o, 'a: *, 'i: o, 'a: o] fn not_captured_early<'a: 'a>() -> impl Sized + use<'i, Self> {} - //~^ [Self: o, 'i: o, 'a: *, 'i: o] + //~^ ERROR [Self: o, 'i: o, 'a: *, 'i: o] fn implicit_capture_late<'a>(_: &'a ()) -> impl Sized {} - //~^ [Self: o, 'i: o, 'i: o, 'a: o] + //~^ ERROR [Self: o, 'i: o, 'i: o, 'a: o] fn explicit_capture_late<'a>(_: &'a ()) -> impl Sized + use<'i, 'a, Self> {} - //~^ [Self: o, 'i: o, 'i: o, 'a: o] + //~^ ERROR [Self: o, 'i: o, 'i: o, 'a: o] fn not_captured_late<'a>(_: &'a ()) -> impl Sized + use<'i, Self> {} - //~^ [Self: o, 'i: o, 'i: o] + //~^ ERROR [Self: o, 'i: o, 'i: o] } fn main() {} diff --git a/tests/ui/impl-trait/issues/issue-54600.rs b/tests/ui/impl-trait/issues/issue-54600.rs index 62bfd7cd9688..b349c47328bb 100644 --- a/tests/ui/impl-trait/issues/issue-54600.rs +++ b/tests/ui/impl-trait/issues/issue-54600.rs @@ -2,6 +2,6 @@ use std::fmt::Debug; fn main() { let x: Option = Some(44_u32); - //~^ `impl Trait` is not allowed in the type of variable bindings + //~^ ERROR `impl Trait` is not allowed in the type of variable bindings println!("{:?}", x); } diff --git a/tests/ui/impl-trait/issues/issue-54840.rs b/tests/ui/impl-trait/issues/issue-54840.rs index 65257d2f7f1d..853728630351 100644 --- a/tests/ui/impl-trait/issues/issue-54840.rs +++ b/tests/ui/impl-trait/issues/issue-54840.rs @@ -3,5 +3,5 @@ use std::ops::Add; fn main() { let i: i32 = 0; let j: &impl Add = &i; - //~^ `impl Trait` is not allowed in the type of variable bindings + //~^ ERROR `impl Trait` is not allowed in the type of variable bindings } diff --git a/tests/ui/impl-trait/issues/issue-58504.rs b/tests/ui/impl-trait/issues/issue-58504.rs index 856e1297e58b..57119671680e 100644 --- a/tests/ui/impl-trait/issues/issue-58504.rs +++ b/tests/ui/impl-trait/issues/issue-58504.rs @@ -8,5 +8,5 @@ fn mk_gen() -> impl Coroutine { fn main() { let gens: [impl Coroutine;2] = [ mk_gen(), mk_gen() ]; - //~^ `impl Trait` is not allowed in the type of variable bindings + //~^ ERROR `impl Trait` is not allowed in the type of variable bindings } diff --git a/tests/ui/impl-trait/issues/issue-58956.rs b/tests/ui/impl-trait/issues/issue-58956.rs index a59de2379d8f..8fb69aca9bce 100644 --- a/tests/ui/impl-trait/issues/issue-58956.rs +++ b/tests/ui/impl-trait/issues/issue-58956.rs @@ -5,9 +5,9 @@ impl Lam for B {} pub struct Wrap(T); const _A: impl Lam = { - //~^ `impl Trait` is not allowed in const types + //~^ ERROR `impl Trait` is not allowed in const types let x: Wrap = Wrap(B); - //~^ `impl Trait` is not allowed in the type of variable bindings + //~^ ERROR `impl Trait` is not allowed in the type of variable bindings x.0 }; diff --git a/tests/ui/impl-trait/issues/issue-70971.rs b/tests/ui/impl-trait/issues/issue-70971.rs index 2f2c2e8f441a..e7b51e0e6db4 100644 --- a/tests/ui/impl-trait/issues/issue-70971.rs +++ b/tests/ui/impl-trait/issues/issue-70971.rs @@ -1,4 +1,4 @@ fn main() { let x : (impl Copy,) = (true,); - //~^ `impl Trait` is not allowed in the type of variable bindings + //~^ ERROR `impl Trait` is not allowed in the type of variable bindings } diff --git a/tests/ui/impl-trait/issues/issue-79099.rs b/tests/ui/impl-trait/issues/issue-79099.rs index 757e61fb631e..c2bad59045b2 100644 --- a/tests/ui/impl-trait/issues/issue-79099.rs +++ b/tests/ui/impl-trait/issues/issue-79099.rs @@ -1,8 +1,8 @@ struct Bug { V1: [(); { let f: impl core::future::Future = async { 1 }; - //~^ `impl Trait` is not allowed in the type of variable bindings - //~| expected identifier + //~^ ERROR `impl Trait` is not allowed in the type of variable bindings + //~| ERROR expected identifier 1 }], } diff --git a/tests/ui/impl-trait/issues/issue-84919.rs b/tests/ui/impl-trait/issues/issue-84919.rs index 0f911ba23ae2..1012024f21e1 100644 --- a/tests/ui/impl-trait/issues/issue-84919.rs +++ b/tests/ui/impl-trait/issues/issue-84919.rs @@ -3,7 +3,7 @@ impl Trait for () {} fn foo<'a: 'a>() { let _x: impl Trait = (); - //~^ `impl Trait` is not allowed in the type of variable bindings + //~^ ERROR `impl Trait` is not allowed in the type of variable bindings } fn main() {} diff --git a/tests/ui/impl-trait/issues/issue-86642.rs b/tests/ui/impl-trait/issues/issue-86642.rs index 74be8779d445..2feb045abee2 100644 --- a/tests/ui/impl-trait/issues/issue-86642.rs +++ b/tests/ui/impl-trait/issues/issue-86642.rs @@ -1,5 +1,5 @@ static x: impl Fn(&str) -> Result<&str, ()> = move |source| { - //~^ `impl Trait` is not allowed in static types + //~^ ERROR `impl Trait` is not allowed in static types let res = (move |source| Ok(source))(source); let res = res.or((move |source| Ok(source))(source)); res diff --git a/tests/ui/impl-trait/issues/issue-87295.rs b/tests/ui/impl-trait/issues/issue-87295.rs index a765e14884b0..d8d1b462ca3b 100644 --- a/tests/ui/impl-trait/issues/issue-87295.rs +++ b/tests/ui/impl-trait/issues/issue-87295.rs @@ -14,5 +14,5 @@ impl Struct { fn main() { let _do_not_waste: Struct> = Struct::new(()); - //~^ `impl Trait` is not allowed in the type of variable bindings + //~^ ERROR `impl Trait` is not allowed in the type of variable bindings } diff --git a/tests/ui/impl-trait/issues/issue-99348-impl-compatibility.rs b/tests/ui/impl-trait/issues/issue-99348-impl-compatibility.rs index e19230b44b40..4937794b040c 100644 --- a/tests/ui/impl-trait/issues/issue-99348-impl-compatibility.rs +++ b/tests/ui/impl-trait/issues/issue-99348-impl-compatibility.rs @@ -6,7 +6,7 @@ type Tait = impl Sized; impl Foo for Concrete { type Item = Concrete; - //~^ type mismatch resolving + //~^ ERROR type mismatch resolving } impl Bar for Concrete { diff --git a/tests/ui/impl-trait/method-resolution4.rs b/tests/ui/impl-trait/method-resolution4.rs index 5c8813ed7922..90e7850cad51 100644 --- a/tests/ui/impl-trait/method-resolution4.rs +++ b/tests/ui/impl-trait/method-resolution4.rs @@ -11,7 +11,7 @@ fn foo(b: bool) -> impl Iterator { if b { foo(false).next().unwrap(); - //[next]~^ type annotations needed + //[next]~^ ERROR type annotations needed } std::iter::empty() } diff --git a/tests/ui/impl-trait/nested_impl_trait.rs b/tests/ui/impl-trait/nested_impl_trait.rs index 760102794c34..3e985b5dcca9 100644 --- a/tests/ui/impl-trait/nested_impl_trait.rs +++ b/tests/ui/impl-trait/nested_impl_trait.rs @@ -9,7 +9,7 @@ fn bad_in_ret_position(x: impl Into) -> impl Into { x } fn bad_in_fn_syntax(x: fn() -> impl Into) {} //~^ ERROR nested `impl Trait` is not allowed -//~| `impl Trait` is not allowed in `fn` pointer +//~| ERROR `impl Trait` is not allowed in `fn` pointer fn bad_in_arg_position(_: impl Into) { } //~^ ERROR nested `impl Trait` is not allowed diff --git a/tests/ui/impl-trait/variance.rs b/tests/ui/impl-trait/variance.rs index bde3a886a4d3..e73e0c623aa4 100644 --- a/tests/ui/impl-trait/variance.rs +++ b/tests/ui/impl-trait/variance.rs @@ -9,15 +9,15 @@ trait Captures<'a> {} impl Captures<'_> for T {} fn not_captured_early<'a: 'a>() -> impl Sized {} -//[old]~^ ['a: *] -//[e2024]~^^ ['a: *, 'a: o] +//[old]~^ ERROR ['a: *] +//[e2024]~^^ ERROR ['a: *, 'a: o] -fn captured_early<'a: 'a>() -> impl Sized + Captures<'a> {} //~ ['a: *, 'a: o] +fn captured_early<'a: 'a>() -> impl Sized + Captures<'a> {} //~ ERROR ['a: *, 'a: o] fn not_captured_late<'a>(_: &'a ()) -> impl Sized {} -//[old]~^ [] -//[e2024]~^^ ['a: o] +//[old]~^ ERROR [] +//[e2024]~^^ ERROR ['a: o] -fn captured_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {} //~ ['a: o] +fn captured_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {} //~ ERROR ['a: o] fn main() {} diff --git a/tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy-1.rs b/tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy-1.rs index b532a110a1c7..83803646a2dc 100644 --- a/tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy-1.rs +++ b/tests/ui/implied-bounds/implied-bounds-on-trait-hierarchy-1.rs @@ -32,7 +32,7 @@ fn main() { { let x = "Hello World".to_string(); subs_to_soup((x.as_str(), &mut d)); - //~^ does not live long enough + //~^ ERROR does not live long enough } println!("{}", d); } diff --git a/tests/ui/implied-bounds/sod_service_chain.rs b/tests/ui/implied-bounds/sod_service_chain.rs index 032483e1be48..73dce2fce249 100644 --- a/tests/ui/implied-bounds/sod_service_chain.rs +++ b/tests/ui/implied-bounds/sod_service_chain.rs @@ -27,17 +27,17 @@ pub struct ServiceChainBuilder> { } impl> ServiceChainBuilder { pub fn next>( - //~^ the associated type + //~^ ERROR the associated type + //~| ERROR the associated type + //~| ERROR the associated type //~| the associated type //~| the associated type //~| the associated type - //~| the associated type - //~| the associated type - //~| may not live long enough + //~| ERROR may not live long enough self, ) -> ServiceChainBuilder, NS> { - //~^ the associated type - //~| the associated type + //~^ ERROR the associated type + //~| ERROR the associated type //~| the associated type //~| the associated type panic!(); diff --git a/tests/ui/imports/import-from-missing.rs b/tests/ui/imports/import-from-missing.rs index 8eae700208f9..1dcc3a901337 100644 --- a/tests/ui/imports/import-from-missing.rs +++ b/tests/ui/imports/import-from-missing.rs @@ -1,5 +1,5 @@ use spam::{ham, eggs}; //~ ERROR unresolved import `spam::eggs` [E0432] - //~^ no `eggs` in `spam` + //~^ NOTE no `eggs` in `spam` mod spam { pub fn ham() { } diff --git a/tests/ui/imports/import2.rs b/tests/ui/imports/import2.rs index 036d6bc07e28..731ccb6f41c2 100644 --- a/tests/ui/imports/import2.rs +++ b/tests/ui/imports/import2.rs @@ -1,5 +1,5 @@ use baz::zed::bar; //~ ERROR unresolved import `baz::zed` [E0432] - //~^ could not find `zed` in `baz` + //~^ NOTE could not find `zed` in `baz` mod baz {} mod zed { diff --git a/tests/ui/imports/issue-13404.rs b/tests/ui/imports/issue-13404.rs index c5af827d50c4..b6e5804abac4 100644 --- a/tests/ui/imports/issue-13404.rs +++ b/tests/ui/imports/issue-13404.rs @@ -1,6 +1,6 @@ use a::f; use b::f; //~ ERROR: unresolved import `b::f` [E0432] - //~^ no `f` in `b` + //~^ NOTE no `f` in `b` mod a { pub fn f() {} } mod b { } diff --git a/tests/ui/imports/issue-2937.rs b/tests/ui/imports/issue-2937.rs index 335df5c07e25..7ca6ffb479e0 100644 --- a/tests/ui/imports/issue-2937.rs +++ b/tests/ui/imports/issue-2937.rs @@ -1,5 +1,5 @@ use m::f as x; //~ ERROR unresolved import `m::f` [E0432] - //~^ no `f` in `m` + //~^ NOTE no `f` in `m` mod m {} diff --git a/tests/ui/imports/issue-32833.rs b/tests/ui/imports/issue-32833.rs index 379eedde7263..8f82eb68c1ff 100644 --- a/tests/ui/imports/issue-32833.rs +++ b/tests/ui/imports/issue-32833.rs @@ -1,5 +1,5 @@ use bar::Foo; //~ ERROR unresolved import `bar::Foo` [E0432] - //~^ no `Foo` in `bar` + //~^ NOTE no `Foo` in `bar` mod bar { use Foo; } diff --git a/tests/ui/imports/issue-8208.rs b/tests/ui/imports/issue-8208.rs index 1c566938f9d0..997d4d227b3d 100644 --- a/tests/ui/imports/issue-8208.rs +++ b/tests/ui/imports/issue-8208.rs @@ -1,14 +1,14 @@ use self::*; //~ ERROR: unresolved import `self::*` [E0432] - //~^ cannot glob-import a module into itself + //~^ NOTE cannot glob-import a module into itself mod foo { use foo::*; //~ ERROR: unresolved import `foo::*` [E0432] - //~^ cannot glob-import a module into itself + //~^ NOTE cannot glob-import a module into itself mod bar { use super::bar::*; //~^ ERROR: unresolved import `super::bar::*` [E0432] - //~| cannot glob-import a module into itself + //~| NOTE cannot glob-import a module into itself } } diff --git a/tests/ui/inline-const/in-pat-recovery.rs b/tests/ui/inline-const/in-pat-recovery.rs index 0d912af09811..e9e60116ff4c 100644 --- a/tests/ui/inline-const/in-pat-recovery.rs +++ b/tests/ui/inline-const/in-pat-recovery.rs @@ -4,7 +4,7 @@ fn main() { match 1 { const { 1 + 7 } => {} - //~^ `inline_const_pat` has been removed + //~^ ERROR `inline_const_pat` has been removed 2 => {} _ => {} } diff --git a/tests/ui/inline-const/using-late-bound-from-closure.rs b/tests/ui/inline-const/using-late-bound-from-closure.rs index 2b12b2e26a22..cb3dfd957397 100644 --- a/tests/ui/inline-const/using-late-bound-from-closure.rs +++ b/tests/ui/inline-const/using-late-bound-from-closure.rs @@ -7,7 +7,7 @@ fn foo() { const { let awd = (); let _: &'a () = &awd; - //~^ `awd` does not live long enough + //~^ ERROR `awd` does not live long enough }; b }; diff --git a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs index 76b6a8c8395c..fdb25a3ae3f5 100644 --- a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs +++ b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs @@ -3,13 +3,13 @@ const RAW_EQ_PADDING: bool = unsafe { std::intrinsics::raw_eq(&(1_u8, 2_u16), &(1_u8, 2_u16)) //~^ ERROR evaluation of constant value failed -//~| requires initialized memory +//~| NOTE requires initialized memory }; const RAW_EQ_PTR: bool = unsafe { std::intrinsics::raw_eq(&(&0), &(&1)) //~^ ERROR evaluation of constant value failed -//~| unable to turn pointer into integer +//~| NOTE unable to turn pointer into integer }; const RAW_EQ_NOT_ALIGNED: bool = unsafe { @@ -17,7 +17,7 @@ const RAW_EQ_NOT_ALIGNED: bool = unsafe { let aref = &*arr.as_ptr().cast::(); std::intrinsics::raw_eq(aref, aref) //~^ ERROR evaluation of constant value failed -//~| alignment +//~| NOTE alignment }; pub fn main() { diff --git a/tests/ui/invalid/invalid-rustc_legacy_const_generics-issue-123077.rs b/tests/ui/invalid/invalid-rustc_legacy_const_generics-issue-123077.rs index 8d854c6c2370..f3a15a58f26a 100644 --- a/tests/ui/invalid/invalid-rustc_legacy_const_generics-issue-123077.rs +++ b/tests/ui/invalid/invalid-rustc_legacy_const_generics-issue-123077.rs @@ -6,26 +6,26 @@ const fn foo() -> i32 { fn main() { std::arch::x86_64::_mm_blend_ps(loop {}, loop {}, || ()); - //~^ invalid argument to a legacy const generic + //~^ ERROR invalid argument to a legacy const generic std::arch::x86_64::_mm_blend_ps(loop {}, loop {}, 5 + || ()); - //~^ invalid argument to a legacy const generic + //~^ ERROR invalid argument to a legacy const generic std::arch::x86_64::_mm_blend_ps(loop {}, loop {}, foo::<{ 1 + 2 }>()); - //~^ invalid argument to a legacy const generic + //~^ ERROR invalid argument to a legacy const generic std::arch::x86_64::_mm_blend_ps(loop {}, loop {}, foo::<3>()); - //~^ invalid argument to a legacy const generic + //~^ ERROR invalid argument to a legacy const generic std::arch::x86_64::_mm_blend_ps(loop {}, loop {}, &const {}); - //~^ invalid argument to a legacy const generic + //~^ ERROR invalid argument to a legacy const generic std::arch::x86_64::_mm_blend_ps(loop {}, loop {}, { struct F(); - //~^ invalid argument to a legacy const generic + //~^ ERROR invalid argument to a legacy const generic 1 }); std::arch::x86_64::_mm_inserti_si64(loop {}, loop {}, || (), 1 + || ()); - //~^ invalid argument to a legacy const generic + //~^ ERROR invalid argument to a legacy const generic } diff --git a/tests/ui/invalid_dispatch_from_dyn_impls.rs b/tests/ui/invalid_dispatch_from_dyn_impls.rs index 972465d71978..b1d4b261babe 100644 --- a/tests/ui/invalid_dispatch_from_dyn_impls.rs +++ b/tests/ui/invalid_dispatch_from_dyn_impls.rs @@ -20,7 +20,7 @@ struct MultiplePointers{ } impl DispatchFromDyn> for MultiplePointers -//~^ implementing `DispatchFromDyn` does not allow multiple fields to be coerced +//~^ ERROR implementing `DispatchFromDyn` does not allow multiple fields to be coerced where T: Unsize, {} diff --git a/tests/ui/issues/issue-11004.rs b/tests/ui/issues/issue-11004.rs index 09d5476dbe60..714fa51ba23f 100644 --- a/tests/ui/issues/issue-11004.rs +++ b/tests/ui/issues/issue-11004.rs @@ -4,8 +4,8 @@ struct A { x: i32, y: f64 } #[cfg(not(FALSE))] unsafe fn access(n:*mut A) -> (i32, f64) { - let x : i32 = n.x; //~ no field `x` on type `*mut A` - let y : f64 = n.y; //~ no field `y` on type `*mut A` + let x : i32 = n.x; //~ ERROR no field `x` on type `*mut A` + let y : f64 = n.y; //~ ERROR no field `y` on type `*mut A` (x, y) } diff --git a/tests/ui/issues/issue-14721.rs b/tests/ui/issues/issue-14721.rs index a5c47dd8cb3d..c015a6bab083 100644 --- a/tests/ui/issues/issue-14721.rs +++ b/tests/ui/issues/issue-14721.rs @@ -1,4 +1,4 @@ fn main() { let foo = "str"; - println!("{}", foo.desc); //~ no field `desc` on type `&str` + println!("{}", foo.desc); //~ ERROR no field `desc` on type `&str` } diff --git a/tests/ui/issues/issue-17740.rs b/tests/ui/issues/issue-17740.rs index 3b868555fc52..574d3662b4fb 100644 --- a/tests/ui/issues/issue-17740.rs +++ b/tests/ui/issues/issue-17740.rs @@ -4,11 +4,11 @@ struct Foo<'a> { impl <'a> Foo<'a>{ fn bar(self: &mut Foo) { - //~^ mismatched `self` parameter type + //~^ ERROR mismatched `self` parameter type //~| expected struct `Foo<'a>` //~| found struct `Foo<'_>` //~| lifetime mismatch - //~| mismatched `self` parameter type + //~| ERROR mismatched `self` parameter type //~| expected struct `Foo<'a>` //~| found struct `Foo<'_>` //~| lifetime mismatch diff --git a/tests/ui/issues/issue-23253.rs b/tests/ui/issues/issue-23253.rs index 22b55c285814..b285cb81ee23 100644 --- a/tests/ui/issues/issue-23253.rs +++ b/tests/ui/issues/issue-23253.rs @@ -2,5 +2,5 @@ enum Foo { Bar } fn main() { Foo::Bar.a; - //~^ no field `a` on type `Foo` + //~^ ERROR no field `a` on type `Foo` } diff --git a/tests/ui/issues/issue-24363.rs b/tests/ui/issues/issue-24363.rs index 34726fba9c66..f358b8b90171 100644 --- a/tests/ui/issues/issue-24363.rs +++ b/tests/ui/issues/issue-24363.rs @@ -1,5 +1,5 @@ fn main() { - 1.create_a_type_error[ //~ `{integer}` is a primitive type and therefore doesn't have fields + 1.create_a_type_error[ //~ ERROR `{integer}` is a primitive type and therefore doesn't have fields ()+() //~ ERROR cannot add // ^ ensure that we typeck the inner expression ^ ]; diff --git a/tests/ui/issues/issue-24365.rs b/tests/ui/issues/issue-24365.rs index eca104b6f1d8..da1951160478 100644 --- a/tests/ui/issues/issue-24365.rs +++ b/tests/ui/issues/issue-24365.rs @@ -7,13 +7,13 @@ pub enum Foo { } fn test(a: Foo) { - println!("{}", a.b); //~ no field `b` on type `Foo` + println!("{}", a.b); //~ ERROR no field `b` on type `Foo` } fn main() { let x = Attribute::Code { attr_name_idx: 42, }; - let z = (&x).attr_name_idx; //~ no field `attr_name_idx` on type `&Attribute` - let y = x.attr_name_idx; //~ no field `attr_name_idx` on type `Attribute` + let z = (&x).attr_name_idx; //~ ERROR no field `attr_name_idx` on type `&Attribute` + let y = x.attr_name_idx; //~ ERROR no field `attr_name_idx` on type `Attribute` } diff --git a/tests/ui/issues/issue-27008.rs b/tests/ui/issues/issue-27008.rs index adf8e779e0a0..20aa4f282c7e 100644 --- a/tests/ui/issues/issue-27008.rs +++ b/tests/ui/issues/issue-27008.rs @@ -3,5 +3,5 @@ struct S; fn main() { let b = [0; S]; //~^ ERROR mismatched types - //~| expected `usize`, found `S` + //~| NOTE expected `usize`, found `S` } diff --git a/tests/ui/issues/issue-2848.rs b/tests/ui/issues/issue-2848.rs index 34181acdd055..8499459cec26 100644 --- a/tests/ui/issues/issue-2848.rs +++ b/tests/ui/issues/issue-2848.rs @@ -11,8 +11,8 @@ mod bar { fn main() { use bar::foo::{alpha, charlie}; match alpha { - alpha | beta => {} //~ ERROR variable `beta` is not bound in all patterns - //~^ ERROR: `beta` is named the same as one of the variants + alpha | beta => {} //~ ERROR variable `beta` is not bound in all patterns + //~^ ERROR `beta` is named the same as one of the variants charlie => {} } } diff --git a/tests/ui/issues/issue-31011.rs b/tests/ui/issues/issue-31011.rs index 4dead04c2ca3..86fe16f48e22 100644 --- a/tests/ui/issues/issue-31011.rs +++ b/tests/ui/issues/issue-31011.rs @@ -1,7 +1,7 @@ macro_rules! log { ( $ctx:expr, $( $args:expr),* ) => { if $ctx.trace { - //~^ no field `trace` on type `&T` + //~^ ERROR no field `trace` on type `&T` println!( $( $args, )* ); } } diff --git a/tests/ui/issues/issue-51102.rs b/tests/ui/issues/issue-51102.rs index 41446cd29b0d..b5ddc7221d06 100644 --- a/tests/ui/issues/issue-51102.rs +++ b/tests/ui/issues/issue-51102.rs @@ -11,7 +11,7 @@ fn main() { match simple { SimpleStruct { state: 0, - //~^ struct `SimpleStruct` does not have a field named `state` [E0026] + //~^ ERROR struct `SimpleStruct` does not have a field named `state` [E0026] .. } => (), } diff --git a/tests/ui/issues/issue-69130.rs b/tests/ui/issues/issue-69130.rs index 9552e8ec2a87..90dffc99db7f 100644 --- a/tests/ui/issues/issue-69130.rs +++ b/tests/ui/issues/issue-69130.rs @@ -3,5 +3,5 @@ enum F { M (§& u8)} //~^ ERROR unknown start of token -//~| missing lifetime specifier +//~| ERROR missing lifetime specifier fn main() {} diff --git a/tests/ui/issues/issue-87199.rs b/tests/ui/issues/issue-87199.rs index 6664119e5798..4e4e35c6a71e 100644 --- a/tests/ui/issues/issue-87199.rs +++ b/tests/ui/issues/issue-87199.rs @@ -17,5 +17,5 @@ fn ret() -> impl Iterator + ?Send { std::iter::empty() } fn main() { ref_arg::(&5); ref_arg::<[i32]>(&[5]); - //~^ the size for values of type `[i32]` cannot be known + //~^ ERROR the size for values of type `[i32]` cannot be known } diff --git a/tests/ui/issues/issue-8761.rs b/tests/ui/issues/issue-8761.rs index 1453c3d757f7..5883bb966956 100644 --- a/tests/ui/issues/issue-8761.rs +++ b/tests/ui/issues/issue-8761.rs @@ -1,10 +1,10 @@ enum Foo { A = 1i64, //~^ ERROR mismatched types - //~| expected `isize`, found `i64` + //~| NOTE expected `isize`, found `i64` B = 2u8 //~^ ERROR mismatched types - //~| expected `isize`, found `u8` + //~| NOTE expected `isize`, found `u8` } fn main() {} diff --git a/tests/ui/iterators/float_iterator_hint.rs b/tests/ui/iterators/float_iterator_hint.rs index a3335ca41f77..9e7a10ca497e 100644 --- a/tests/ui/iterators/float_iterator_hint.rs +++ b/tests/ui/iterators/float_iterator_hint.rs @@ -3,7 +3,7 @@ fn main() { for i in 0.2 { //~^ ERROR `{float}` is not an iterator - //~| `{float}` is not an iterator + //~| NOTE `{float}` is not an iterator //~| NOTE in this expansion of desugaring of `for` loop //~| NOTE in this expansion of desugaring of `for` loop //~| NOTE in this expansion of desugaring of `for` loop diff --git a/tests/ui/layout/post-mono-layout-cycle.rs b/tests/ui/layout/post-mono-layout-cycle.rs index 6753c01267ec..841fc30a50bc 100644 --- a/tests/ui/layout/post-mono-layout-cycle.rs +++ b/tests/ui/layout/post-mono-layout-cycle.rs @@ -1,5 +1,5 @@ //@ build-fail -//~^ cycle detected when computing layout of `Wrapper<()>` +//~^ ERROR cycle detected when computing layout of `Wrapper<()>` trait Trait { type Assoc; diff --git a/tests/ui/lifetimes/conflicting-bounds.rs b/tests/ui/lifetimes/conflicting-bounds.rs index f37f163dbb63..62240792afd7 100644 --- a/tests/ui/lifetimes/conflicting-bounds.rs +++ b/tests/ui/lifetimes/conflicting-bounds.rs @@ -1,4 +1,4 @@ -//~ type annotations needed: cannot satisfy `Self: Gen<'source>` +//~ ERROR type annotations needed: cannot satisfy `Self: Gen<'source>` pub trait Gen<'source> { type Output; diff --git a/tests/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.rs b/tests/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.rs index 78069e682c13..4aa212bb4bd3 100644 --- a/tests/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.rs +++ b/tests/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.rs @@ -3,6 +3,6 @@ struct Foo {} impl Foo { fn bar(foo: Foo) {} - //~^ associated item constraints are not allowed here + //~^ ERROR associated item constraints are not allowed here } fn main() {} diff --git a/tests/ui/lifetimes/issue-83907-invalid-fn-like-path.rs b/tests/ui/lifetimes/issue-83907-invalid-fn-like-path.rs index 4e093bb2e17d..4f4e2cda9469 100644 --- a/tests/ui/lifetimes/issue-83907-invalid-fn-like-path.rs +++ b/tests/ui/lifetimes/issue-83907-invalid-fn-like-path.rs @@ -1,7 +1,7 @@ //@ check-fail static STATIC_VAR_FIVE: &One(); -//~^ cannot find type -//~| free static item without body +//~^ ERROR cannot find type +//~| ERROR free static item without body fn main() {} diff --git a/tests/ui/limits/huge-static.rs b/tests/ui/limits/huge-static.rs index 4709b46e59d1..4c3641ac7d4b 100644 --- a/tests/ui/limits/huge-static.rs +++ b/tests/ui/limits/huge-static.rs @@ -18,9 +18,9 @@ impl TooBigArray { static MY_TOO_BIG_ARRAY_1: TooBigArray = TooBigArray::new(); //~^ ERROR could not evaluate static initializer -//~| too big +//~| NOTE too big static MY_TOO_BIG_ARRAY_2: [u8; HUGE_SIZE] = [0x00; HUGE_SIZE]; //~^ ERROR could not evaluate static initializer -//~| too big +//~| NOTE too big fn main() { } diff --git a/tests/ui/lint/lint-attr-everywhere-early.rs b/tests/ui/lint/lint-attr-everywhere-early.rs index ae32ec426f23..7ca127d066f5 100644 --- a/tests/ui/lint/lint-attr-everywhere-early.rs +++ b/tests/ui/lint/lint-attr-everywhere-early.rs @@ -40,7 +40,7 @@ struct Associated; impl Associated { #![deny(unsafe_code)] - fn inherent_denied_from_inner() { unsafe {} } //~ usage of an `unsafe` block + fn inherent_denied_from_inner() { unsafe {} } //~ ERROR usage of an `unsafe` block #[deny(while_true)] fn inherent_fn() { while true {} } //~ ERROR denote infinite loops with diff --git a/tests/ui/lint/lints-in-foreign-macros.rs b/tests/ui/lint/lints-in-foreign-macros.rs index 49e83bae6421..31b59f4943a5 100644 --- a/tests/ui/lint/lints-in-foreign-macros.rs +++ b/tests/ui/lint/lints-in-foreign-macros.rs @@ -1,7 +1,7 @@ //@ aux-build:lints-in-foreign-macros.rs //@ check-pass -#![warn(unused_imports)] //~ missing documentation for the crate [missing_docs] +#![warn(unused_imports)] //~ WARN missing documentation for the crate [missing_docs] #![warn(missing_docs)] #[macro_use] diff --git a/tests/ui/lint/rfc-2457-non-ascii-idents/lint-uncommon-codepoints.rs b/tests/ui/lint/rfc-2457-non-ascii-idents/lint-uncommon-codepoints.rs index a51452f06959..787b8999a106 100644 --- a/tests/ui/lint/rfc-2457-non-ascii-idents/lint-uncommon-codepoints.rs +++ b/tests/ui/lint/rfc-2457-non-ascii-idents/lint-uncommon-codepoints.rs @@ -1,6 +1,6 @@ #![deny(uncommon_codepoints)] -const µ: f64 = 0.000001; //~ identifier contains a non normalized (NFKC) character: 'µ' +const µ: f64 = 0.000001; //~ ERROR identifier contains a non normalized (NFKC) character: 'µ' //~| WARNING should have an upper case name fn dijkstra() {} diff --git a/tests/ui/lint/unused-borrows.rs b/tests/ui/lint/unused-borrows.rs index 4518522ae00f..07d783382fae 100644 --- a/tests/ui/lint/unused-borrows.rs +++ b/tests/ui/lint/unused-borrows.rs @@ -4,24 +4,24 @@ fn foo(_: i32) -> bool { todo!() } fn bar() -> &'static i32 { &42; - //~^ unused + //~^ ERROR unused &mut foo(42); - //~^ unused + //~^ ERROR unused &&42; - //~^ unused + //~^ ERROR unused &&mut 42; - //~^ unused + //~^ ERROR unused &mut &42; - //~^ unused + //~^ ERROR unused let _result = foo(4) && foo(2); // Misplaced semi-colon (perhaps due to reordering of lines) && foo(42); - //~^ unused + //~^ ERROR unused let _ = &42; // ok diff --git a/tests/ui/lint/unused/must_use-unit.rs b/tests/ui/lint/unused/must_use-unit.rs index 4dd4798abb7c..171ae3257b6c 100644 --- a/tests/ui/lint/unused/must_use-unit.rs +++ b/tests/ui/lint/unused/must_use-unit.rs @@ -10,7 +10,7 @@ fn bar() -> ! { } fn main() { - foo(); //~ unused return value of `foo` + foo(); //~ ERROR unused return value of `foo` - bar(); //~ unused return value of `bar` + bar(); //~ ERROR unused return value of `bar` } diff --git a/tests/ui/lint/unused/useless-comment.rs b/tests/ui/lint/unused/useless-comment.rs index 7d2e5ab6f2b7..4ec52f20747d 100644 --- a/tests/ui/lint/unused/useless-comment.rs +++ b/tests/ui/lint/unused/useless-comment.rs @@ -13,7 +13,7 @@ fn foo() { /// a //~ ERROR unused doc comment let x = 12; - /// multi-line //~ unused doc comment + /// multi-line //~ ERROR unused doc comment /// doc comment /// that is unused match x { diff --git a/tests/ui/macros/issue-42954.fixed b/tests/ui/macros/issue-42954.fixed index acfc36e2bff2..b1d4e0a56a6b 100644 --- a/tests/ui/macros/issue-42954.fixed +++ b/tests/ui/macros/issue-42954.fixed @@ -4,7 +4,7 @@ macro_rules! is_plainly_printable { ($i: ident) => { - ($i as u32) < 0 //~ `<` is interpreted as a start of generic arguments + ($i as u32) < 0 //~ ERROR `<` is interpreted as a start of generic arguments }; } diff --git a/tests/ui/macros/issue-42954.rs b/tests/ui/macros/issue-42954.rs index 91362946f845..29e2aa3a682c 100644 --- a/tests/ui/macros/issue-42954.rs +++ b/tests/ui/macros/issue-42954.rs @@ -4,7 +4,7 @@ macro_rules! is_plainly_printable { ($i: ident) => { - $i as u32 < 0 //~ `<` is interpreted as a start of generic arguments + $i as u32 < 0 //~ ERROR `<` is interpreted as a start of generic arguments }; } diff --git a/tests/ui/macros/issue-88228.rs b/tests/ui/macros/issue-88228.rs index 48b405264fef..b4195a92557e 100644 --- a/tests/ui/macros/issue-88228.rs +++ b/tests/ui/macros/issue-88228.rs @@ -13,7 +13,7 @@ struct A; #[derive(println)] //~^ ERROR cannot find derive macro `println` -//~|`println` is in scope, but it is a function-like macro +//~| NOTE `println` is in scope, but it is a function-like macro struct B; fn main() { diff --git a/tests/ui/match/intended-binding-pattern-is-const.rs b/tests/ui/match/intended-binding-pattern-is-const.rs index 95c8119cdb9d..12a8e2c18bc1 100644 --- a/tests/ui/match/intended-binding-pattern-is-const.rs +++ b/tests/ui/match/intended-binding-pattern-is-const.rs @@ -1,8 +1,8 @@ fn main() { match 1 { //~ ERROR non-exhaustive patterns - //~^ patterns `i32::MIN..=3_i32` and `5_i32..=i32::MAX` not covered - //~| the matched value is of type `i32` - x => {} //~ this pattern doesn't introduce a new catch-all binding + //~^ NOTE patterns `i32::MIN..=3_i32` and `5_i32..=i32::MAX` not covered + //~| NOTE the matched value is of type `i32` + x => {} //~ NOTE this pattern doesn't introduce a new catch-all binding //~^ HELP ensure that all possible cases are being handled //~| HELP if you meant to introduce a binding, use a different name } diff --git a/tests/ui/match/postfix-match/pf-match-exhaustiveness.rs b/tests/ui/match/postfix-match/pf-match-exhaustiveness.rs index f4cac46f7cd6..cbd35482d222 100644 --- a/tests/ui/match/postfix-match/pf-match-exhaustiveness.rs +++ b/tests/ui/match/postfix-match/pf-match-exhaustiveness.rs @@ -1,7 +1,7 @@ #![feature(postfix_match)] fn main() { - Some(1).match { //~ non-exhaustive patterns + Some(1).match { //~ ERROR non-exhaustive patterns None => {}, } } diff --git a/tests/ui/methods/bad-wf-when-selecting-method.rs b/tests/ui/methods/bad-wf-when-selecting-method.rs index 638d1ffa982f..1f1a10f42046 100644 --- a/tests/ui/methods/bad-wf-when-selecting-method.rs +++ b/tests/ui/methods/bad-wf-when-selecting-method.rs @@ -12,7 +12,7 @@ fn test(t: T) { Wrapper(t).needs_sized(); //~^ ERROR the trait bound `T: Wf` is not satisfied //~| ERROR the trait bound `T: Wf` is not satisfied - //~| the method `needs_sized` exists for struct `Wrapper`, but its trait bounds were not satisfied + //~| ERROR the method `needs_sized` exists for struct `Wrapper`, but its trait bounds were not satisfied } fn main() {} diff --git a/tests/ui/methods/disambiguate-associated-function-first-arg.rs b/tests/ui/methods/disambiguate-associated-function-first-arg.rs index 4c8192fc14bd..c88be8424814 100644 --- a/tests/ui/methods/disambiguate-associated-function-first-arg.rs +++ b/tests/ui/methods/disambiguate-associated-function-first-arg.rs @@ -45,5 +45,5 @@ impl TraitB for T { fn test() { S.f(); - //~^ multiple applicable items in scope + //~^ ERROR multiple applicable items in scope } diff --git a/tests/ui/methods/issues/issue-90315.rs b/tests/ui/methods/issues/issue-90315.rs index fbecaf9b971f..3a82454b7b4f 100644 --- a/tests/ui/methods/issues/issue-90315.rs +++ b/tests/ui/methods/issues/issue-90315.rs @@ -3,7 +3,7 @@ fn main() { let arr = &[0, 1, 2, 3]; for _i in 0..arr.len().rev() { //~^ ERROR can't call method - //~| surround the range in parentheses + //~| HELP surround the range in parentheses // The above error used to say “the method `rev` exists for type `usize`”. // This regression test ensures it doesn't say that any more. } diff --git a/tests/ui/mir/enable_passes_validation.rs b/tests/ui/mir/enable_passes_validation.rs index b97ddfba37f5..99b1ba528b0c 100644 --- a/tests/ui/mir/enable_passes_validation.rs +++ b/tests/ui/mir/enable_passes_validation.rs @@ -19,7 +19,7 @@ fn main() {} //[unprefixed]~? ERROR incorrect value `CheckAlignment` for unstable option `mir-enable-passes` //[mixed]~? WARN MIR pass `ThisPassDoesNotExist` is unknown and will be ignored //[mixed]~? WARN MIR pass `ThisPassDoesNotExist` is unknown and will be ignored -//[all_unknown]~? MIR pass `ThisPass` is unknown and will be ignored -//[all_unknown]~? MIR pass `DoesNotExist` is unknown and will be ignored -//[all_unknown]~? MIR pass `ThisPass` is unknown and will be ignored -//[all_unknown]~? MIR pass `DoesNotExist` is unknown and will be ignored +//[all_unknown]~? WARN MIR pass `ThisPass` is unknown and will be ignored +//[all_unknown]~? WARN MIR pass `DoesNotExist` is unknown and will be ignored +//[all_unknown]~? WARN MIR pass `ThisPass` is unknown and will be ignored +//[all_unknown]~? WARN MIR pass `DoesNotExist` is unknown and will be ignored diff --git a/tests/ui/mismatched_types/suggest-adding-or-removing-ref-for-binding-pattern.fixed b/tests/ui/mismatched_types/suggest-adding-or-removing-ref-for-binding-pattern.fixed index cf923362ad81..04e0fcca32d6 100644 --- a/tests/ui/mismatched_types/suggest-adding-or-removing-ref-for-binding-pattern.fixed +++ b/tests/ui/mismatched_types/suggest-adding-or-removing-ref-for-binding-pattern.fixed @@ -16,6 +16,6 @@ fn main() { match Blah::A(1, 1, 2) { Blah::A(_, x, y) | Blah::B(x, y) => {} //~^ ERROR mismatched types - //~| variable `y` is bound inconsistently across alternatives separated by `|` + //~| ERROR variable `y` is bound inconsistently across alternatives separated by `|` } } diff --git a/tests/ui/mismatched_types/suggest-adding-or-removing-ref-for-binding-pattern.rs b/tests/ui/mismatched_types/suggest-adding-or-removing-ref-for-binding-pattern.rs index dc556f6576ae..dd6329c90905 100644 --- a/tests/ui/mismatched_types/suggest-adding-or-removing-ref-for-binding-pattern.rs +++ b/tests/ui/mismatched_types/suggest-adding-or-removing-ref-for-binding-pattern.rs @@ -16,6 +16,6 @@ fn main() { match Blah::A(1, 1, 2) { Blah::A(_, x, y) | Blah::B(x, ref y) => {} //~^ ERROR mismatched types - //~| variable `y` is bound inconsistently across alternatives separated by `|` + //~| ERROR variable `y` is bound inconsistently across alternatives separated by `|` } } diff --git a/tests/ui/moves/moves-based-on-type-tuple.rs b/tests/ui/moves/moves-based-on-type-tuple.rs index 2e67d8f8a691..c9951a930225 100644 --- a/tests/ui/moves/moves-based-on-type-tuple.rs +++ b/tests/ui/moves/moves-based-on-type-tuple.rs @@ -2,7 +2,7 @@ fn dup(x: Box) -> Box<(Box,Box)> { Box::new((x, x)) - //~^ use of moved value: `x` [E0382] + //~^ ERROR use of moved value: `x` [E0382] } fn main() { diff --git a/tests/ui/moves/use_of_moved_value_clone_suggestions.rs b/tests/ui/moves/use_of_moved_value_clone_suggestions.rs index d5c8d4e6bdf2..9a0a397a7338 100644 --- a/tests/ui/moves/use_of_moved_value_clone_suggestions.rs +++ b/tests/ui/moves/use_of_moved_value_clone_suggestions.rs @@ -1,6 +1,6 @@ // `Rc` is not ever `Copy`, we should not suggest adding `T: Copy` constraint fn duplicate_rc(t: std::rc::Rc) -> (std::rc::Rc, std::rc::Rc) { - (t, t) //~ use of moved value: `t` + (t, t) //~ ERROR use of moved value: `t` } fn main() {} 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 a5e0dd819b46..53d9cb20b3de 100644 --- a/tests/ui/moves/use_of_moved_value_copy_suggestions.fixed +++ b/tests/ui/moves/use_of_moved_value_copy_suggestions.fixed @@ -4,27 +4,27 @@ 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` + (t, t) //~ ERROR use of moved value: `t` } fn duplicate_opt(t: Option) -> (Option, Option) { //~^ HELP consider restricting type parameter `T` - (t, t) //~ use of moved value: `t` + (t, t) //~ ERROR use of moved value: `t` } fn duplicate_tup1(t: (T,)) -> ((T,), (T,)) { //~^ HELP consider restricting type parameter `T` - (t, t) //~ use of moved value: `t` + (t, t) //~ ERROR use of moved value: `t` } fn duplicate_tup2(t: (A, B)) -> ((A, B), (A, B)) { //~^ HELP consider restricting type parameters - (t, t) //~ use of moved value: `t` + (t, t) //~ ERROR use of moved value: `t` } fn duplicate_custom(t: S) -> (S, S) { //~^ HELP consider restricting type parameter `T` - (t, t) //~ use of moved value: `t` + (t, t) //~ ERROR use of moved value: `t` } struct S(T); @@ -42,7 +42,7 @@ trait B {} // Test where bounds are added with different bound placements fn duplicate_custom_1(t: S) -> (S, S) where { //~^ HELP consider restricting type parameter `T` - (t, t) //~ use of moved value: `t` + (t, t) //~ ERROR use of moved value: `t` } fn duplicate_custom_2(t: S) -> (S, S) @@ -50,7 +50,7 @@ where T: A + Copy + Trait, //~^ HELP consider further restricting { - (t, t) //~ use of moved value: `t` + (t, t) //~ ERROR use of moved value: `t` } fn duplicate_custom_3(t: S) -> (S, S) @@ -59,7 +59,7 @@ where //~^ HELP consider further restricting T: B, { - (t, t) //~ use of moved value: `t` + (t, t) //~ ERROR use of moved value: `t` } fn duplicate_custom_4(t: S) -> (S, S) @@ -67,14 +67,14 @@ fn duplicate_custom_4(t: S) -> (S, S) where T: B, { - (t, t) //~ use of moved value: `t` + (t, t) //~ ERROR use of moved value: `t` } #[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` + [t, t]; //~ ERROR use of moved value: `t` } fn existing_colon_in_where(t: T) //~ HELP if `T` implemented `Clone`, you could clone the value @@ -82,7 +82,7 @@ where T:, T: Copy //~^ HELP consider further restricting type parameter `T` { - [t, t]; //~ use of moved value: `t` + [t, t]; //~ ERROR use of moved value: `t` } fn main() {} 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 60ca03ed6984..c8cfc80cd82d 100644 --- a/tests/ui/moves/use_of_moved_value_copy_suggestions.rs +++ b/tests/ui/moves/use_of_moved_value_copy_suggestions.rs @@ -4,27 +4,27 @@ 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` + (t, t) //~ ERROR use of moved value: `t` } fn duplicate_opt(t: Option) -> (Option, Option) { //~^ HELP consider restricting type parameter `T` - (t, t) //~ use of moved value: `t` + (t, t) //~ ERROR use of moved value: `t` } fn duplicate_tup1(t: (T,)) -> ((T,), (T,)) { //~^ HELP consider restricting type parameter `T` - (t, t) //~ use of moved value: `t` + (t, t) //~ ERROR use of moved value: `t` } fn duplicate_tup2(t: (A, B)) -> ((A, B), (A, B)) { //~^ HELP consider restricting type parameters - (t, t) //~ use of moved value: `t` + (t, t) //~ ERROR use of moved value: `t` } fn duplicate_custom(t: S) -> (S, S) { //~^ HELP consider restricting type parameter `T` - (t, t) //~ use of moved value: `t` + (t, t) //~ ERROR use of moved value: `t` } struct S(T); @@ -42,7 +42,7 @@ trait B {} // Test where bounds are added with different bound placements fn duplicate_custom_1(t: S) -> (S, S) where { //~^ HELP consider restricting type parameter `T` - (t, t) //~ use of moved value: `t` + (t, t) //~ ERROR use of moved value: `t` } fn duplicate_custom_2(t: S) -> (S, S) @@ -50,7 +50,7 @@ where T: A, //~^ HELP consider further restricting { - (t, t) //~ use of moved value: `t` + (t, t) //~ ERROR use of moved value: `t` } fn duplicate_custom_3(t: S) -> (S, S) @@ -59,7 +59,7 @@ where //~^ HELP consider further restricting T: B, { - (t, t) //~ use of moved value: `t` + (t, t) //~ ERROR use of moved value: `t` } fn duplicate_custom_4(t: S) -> (S, S) @@ -67,14 +67,14 @@ fn duplicate_custom_4(t: S) -> (S, S) where T: B, { - (t, t) //~ use of moved value: `t` + (t, t) //~ ERROR use of moved value: `t` } #[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` + [t, t]; //~ ERROR use of moved value: `t` } fn existing_colon_in_where(t: T) //~ HELP if `T` implemented `Clone`, you could clone the value @@ -82,7 +82,7 @@ where T:, //~^ HELP consider further restricting type parameter `T` { - [t, t]; //~ use of moved value: `t` + [t, t]; //~ ERROR use of moved value: `t` } fn main() {} diff --git a/tests/ui/never_type/fallback-closure-wrap.rs b/tests/ui/never_type/fallback-closure-wrap.rs index e7f7d5aae3f8..106b82b5f781 100644 --- a/tests/ui/never_type/fallback-closure-wrap.rs +++ b/tests/ui/never_type/fallback-closure-wrap.rs @@ -17,7 +17,7 @@ use std::marker::PhantomData; fn main() { let error = Closure::wrap(Box::new(move || { panic!("Can't connect to server."); - //[fallback]~^ to return `()`, but it returns `!` + //[fallback]~^ ERROR to return `()`, but it returns `!` }) as Box); } diff --git a/tests/ui/nll/borrowed-match-issue-45045.rs b/tests/ui/nll/borrowed-match-issue-45045.rs index 978eeb868edc..a252dc817caf 100644 --- a/tests/ui/nll/borrowed-match-issue-45045.rs +++ b/tests/ui/nll/borrowed-match-issue-45045.rs @@ -10,7 +10,7 @@ fn main() { let f = &mut e; let g = f; match e { - //~^ cannot use `e` because it was mutably borrowed [E0503] + //~^ ERROR cannot use `e` because it was mutably borrowed [E0503] Xyz::A => println!("a"), Xyz::B => println!("b"), }; diff --git a/tests/ui/nll/issue-48697.rs b/tests/ui/nll/issue-48697.rs index 16e29ab2a8ad..8cb5fc36949a 100644 --- a/tests/ui/nll/issue-48697.rs +++ b/tests/ui/nll/issue-48697.rs @@ -4,7 +4,7 @@ fn foo(x: &i32) -> &i32 { let z = 4; let f = &|y| y; let k = f(&z); - f(x) //~ cannot return value referencing local variable + f(x) //~ ERROR cannot return value referencing local variable } fn main() {} diff --git a/tests/ui/nll/issue-54779-anon-static-lifetime.rs b/tests/ui/nll/issue-54779-anon-static-lifetime.rs index 6b8fa608ebbb..49e4180fe8ce 100644 --- a/tests/ui/nll/issue-54779-anon-static-lifetime.rs +++ b/tests/ui/nll/issue-54779-anon-static-lifetime.rs @@ -29,7 +29,7 @@ impl DebugWith for Foo { fmt: &mut std::fmt::Formatter<'_>, ) -> std::fmt::Result { let Foo { bar } = self; - bar.debug_with(cx); //~ borrowed data escapes outside of method + bar.debug_with(cx); //~ ERROR borrowed data escapes outside of method Ok(()) } } diff --git a/tests/ui/nll/member-constraints/nested-impl-trait-fail.rs b/tests/ui/nll/member-constraints/nested-impl-trait-fail.rs index d676c967f30f..0bf32a2624fc 100644 --- a/tests/ui/nll/member-constraints/nested-impl-trait-fail.rs +++ b/tests/ui/nll/member-constraints/nested-impl-trait-fail.rs @@ -15,8 +15,8 @@ where 's: 'b, { [a] - //~^ E0700 - //~| E0700 + //~^ ERROR E0700 + //~| ERROR E0700 } // Same as the above but with late-bound regions. @@ -26,8 +26,8 @@ fn fail_late_bound<'s, 'a, 'b>( _: &'b &'s u8, ) -> impl IntoIterator + Cap<'b>> { [a] - //~^ E0700 - //~| E0700 + //~^ ERROR E0700 + //~| ERROR E0700 } fn main() {} diff --git a/tests/ui/nonscalar-cast.fixed b/tests/ui/nonscalar-cast.fixed index f6154222ca22..cb5591dbb9de 100644 --- a/tests/ui/nonscalar-cast.fixed +++ b/tests/ui/nonscalar-cast.fixed @@ -12,5 +12,5 @@ impl From for isize { } fn main() { - println!("{}", isize::from(Foo { x: 1 })); //~ non-primitive cast: `Foo` as `isize` [E0605] + println!("{}", isize::from(Foo { x: 1 })); //~ ERROR non-primitive cast: `Foo` as `isize` [E0605] } diff --git a/tests/ui/nonscalar-cast.rs b/tests/ui/nonscalar-cast.rs index 71e7c43a1db0..27429b44cd08 100644 --- a/tests/ui/nonscalar-cast.rs +++ b/tests/ui/nonscalar-cast.rs @@ -12,5 +12,5 @@ impl From for isize { } fn main() { - println!("{}", Foo { x: 1 } as isize); //~ non-primitive cast: `Foo` as `isize` [E0605] + println!("{}", Foo { x: 1 } as isize); //~ ERROR non-primitive cast: `Foo` as `isize` [E0605] } diff --git a/tests/ui/offset-of/offset-of-self.rs b/tests/ui/offset-of/offset-of-self.rs index e5730b8cf6cd..0a6de2ebbb35 100644 --- a/tests/ui/offset-of/offset-of-self.rs +++ b/tests/ui/offset-of/offset-of-self.rs @@ -15,8 +15,8 @@ impl S { offset_of!(Self, v) } fn v_offs_wrong_syntax() { - offset_of!(Self, Self::v); //~ offset_of expects dot-separated field and variant names - offset_of!(S, Self); //~ no field `Self` on type `S` + offset_of!(Self, Self::v); //~ ERROR offset_of expects dot-separated field and variant names + offset_of!(S, Self); //~ ERROR no field `Self` on type `S` } fn offs_in_c() -> usize { offset_of!(C, w) @@ -48,6 +48,6 @@ fn main() { offset_of!(self::S, v); offset_of!(Self, v); //~ ERROR cannot find type `Self` in this scope - offset_of!(S, self); //~ no field `self` on type `S` - offset_of!(S, v.self); //~ no field `self` on type `u8` + offset_of!(S, self); //~ ERROR no field `self` on type `S` + offset_of!(S, v.self); //~ ERROR no field `self` on type `u8` } diff --git a/tests/ui/offset-of/offset-of-tuple.rs b/tests/ui/offset-of/offset-of-tuple.rs index db00fe05583f..e84472494413 100644 --- a/tests/ui/offset-of/offset-of-tuple.rs +++ b/tests/ui/offset-of/offset-of-tuple.rs @@ -11,7 +11,7 @@ fn main() { offset_of!((u8, u8), +1); //~ ERROR no rules expected offset_of!((u8, u8), -1); //~ ERROR offset_of expects dot-separated field and variant names offset_of!((u8, u8), 1.); //~ ERROR offset_of expects dot-separated field and variant names - offset_of!((u8, u8), 1 .); //~ unexpected token: `)` + offset_of!((u8, u8), 1 .); //~ ERROR unexpected token: `)` builtin # offset_of((u8, u8), 1e2); //~ ERROR no field `1e2` builtin # offset_of((u8, u8), _0); //~ ERROR no field `_0` builtin # offset_of((u8, u8), 01); //~ ERROR no field `01` diff --git a/tests/ui/on-unimplemented/bad-annotation.rs b/tests/ui/on-unimplemented/bad-annotation.rs index 4c6610f88643..3f0f69749bf7 100644 --- a/tests/ui/on-unimplemented/bad-annotation.rs +++ b/tests/ui/on-unimplemented/bad-annotation.rs @@ -25,39 +25,39 @@ trait BadAnnotation2 {} #[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{}>`"] -//~^ only named generic parameters are allowed +//~^ ERROR only named generic parameters are allowed trait BadAnnotation3 {} #[rustc_on_unimplemented(lorem="")] -//~^ this attribute must have a valid +//~^ ERROR this attribute must have a valid trait BadAnnotation4 {} #[rustc_on_unimplemented(lorem(ipsum(dolor)))] -//~^ this attribute must have a valid +//~^ ERROR this attribute must have a valid trait BadAnnotation5 {} #[rustc_on_unimplemented(message="x", message="y")] -//~^ this attribute must have a valid +//~^ ERROR this attribute must have a valid trait BadAnnotation6 {} #[rustc_on_unimplemented(message="x", on(desugared, message="y"))] -//~^ this attribute must have a valid +//~^ ERROR this attribute must have a valid trait BadAnnotation7 {} #[rustc_on_unimplemented(on(), message="y")] -//~^ empty `on`-clause +//~^ ERROR empty `on`-clause trait BadAnnotation8 {} #[rustc_on_unimplemented(on="x", message="y")] -//~^ this attribute must have a valid +//~^ ERROR this attribute must have a valid trait BadAnnotation9 {} #[rustc_on_unimplemented(on(x="y"), message="y")] trait BadAnnotation10 {} #[rustc_on_unimplemented(on(desugared, on(desugared, message="x")), message="y")] -//~^ this attribute must have a valid +//~^ ERROR this attribute must have a valid trait BadAnnotation11 {} pub fn main() { diff --git a/tests/ui/or-patterns/inner-or-pat.rs b/tests/ui/or-patterns/inner-or-pat.rs index 4d136de00535..6c7968df7265 100644 --- a/tests/ui/or-patterns/inner-or-pat.rs +++ b/tests/ui/or-patterns/inner-or-pat.rs @@ -49,7 +49,7 @@ fn hey() { match x { x @ ("foo" | "bar") | (x @ "red" | (x @ "blue" | "red")) => { - //[or4]~^ variable `x` is not bound in all patterns + //[or4]~^ ERROR variable `x` is not bound in all patterns } _ => (), } diff --git a/tests/ui/or-patterns/while-parsing-this-or-pattern.rs b/tests/ui/or-patterns/while-parsing-this-or-pattern.rs index b9bfb8638b2c..b034a52ac945 100644 --- a/tests/ui/or-patterns/while-parsing-this-or-pattern.rs +++ b/tests/ui/or-patterns/while-parsing-this-or-pattern.rs @@ -3,7 +3,7 @@ fn main() { match Some(42) { Some(42) | .=. => {} //~ ERROR expected pattern, found `.` - //~^ while parsing this or-pattern starting here + //~^ NOTE while parsing this or-pattern starting here //~| NOTE expected pattern } } diff --git a/tests/ui/panic-handler/panic-handler-bad-signature-1.rs b/tests/ui/panic-handler/panic-handler-bad-signature-1.rs index 8f42f3a8897f..71911afaa843 100644 --- a/tests/ui/panic-handler/panic-handler-bad-signature-1.rs +++ b/tests/ui/panic-handler/panic-handler-bad-signature-1.rs @@ -7,4 +7,4 @@ use core::panic::PanicInfo; #[panic_handler] fn panic(info: PanicInfo) -> () {} -//~^ `#[panic_handler]` function has wrong type [E0308] +//~^ ERROR `#[panic_handler]` function has wrong type [E0308] diff --git a/tests/ui/panic-handler/panic-handler-bad-signature-2.rs b/tests/ui/panic-handler/panic-handler-bad-signature-2.rs index 79ad4598e10c..9c0130eff21f 100644 --- a/tests/ui/panic-handler/panic-handler-bad-signature-2.rs +++ b/tests/ui/panic-handler/panic-handler-bad-signature-2.rs @@ -7,7 +7,7 @@ use core::panic::PanicInfo; #[panic_handler] fn panic(info: &'static PanicInfo) -> ! -//~^ #[panic_handler]` function has wrong type [E0308] +//~^ ERROR #[panic_handler]` function has wrong type [E0308] { loop {} } diff --git a/tests/ui/panic-handler/panic-handler-bad-signature-3.rs b/tests/ui/panic-handler/panic-handler-bad-signature-3.rs index 1c6e2e2ff492..14c8c7c63b70 100644 --- a/tests/ui/panic-handler/panic-handler-bad-signature-3.rs +++ b/tests/ui/panic-handler/panic-handler-bad-signature-3.rs @@ -6,6 +6,6 @@ use core::panic::PanicInfo; #[panic_handler] -fn panic() -> ! { //~ #[panic_handler]` function has wrong type [E0308] +fn panic() -> ! { //~ ERROR #[panic_handler]` function has wrong type [E0308] loop {} } diff --git a/tests/ui/panic-handler/panic-handler-bad-signature-5.rs b/tests/ui/panic-handler/panic-handler-bad-signature-5.rs index d7ee8f25b114..a2a0e46ec682 100644 --- a/tests/ui/panic-handler/panic-handler-bad-signature-5.rs +++ b/tests/ui/panic-handler/panic-handler-bad-signature-5.rs @@ -7,7 +7,7 @@ use core::panic::PanicInfo; #[panic_handler] fn panic(info: &PanicInfo<'static>) -> ! -//~^ #[panic_handler]` function has wrong type [E0308] +//~^ ERROR #[panic_handler]` function has wrong type [E0308] { loop {} } diff --git a/tests/ui/parser/diff-markers/unclosed-delims-in-macro.rs b/tests/ui/parser/diff-markers/unclosed-delims-in-macro.rs index 41a7de03d4b7..acd608e27c61 100644 --- a/tests/ui/parser/diff-markers/unclosed-delims-in-macro.rs +++ b/tests/ui/parser/diff-markers/unclosed-delims-in-macro.rs @@ -8,4 +8,4 @@ macro_rules! foo { () { // >>>>>>> 7a4f13c blah blah blah } -} //~ this file contains an unclosed delimiter +} //~ ERROR this file contains an unclosed delimiter diff --git a/tests/ui/parser/diff-markers/unclosed-delims-in-macro.stderr b/tests/ui/parser/diff-markers/unclosed-delims-in-macro.stderr index b33f2b5d1b8b..a5558352b694 100644 --- a/tests/ui/parser/diff-markers/unclosed-delims-in-macro.stderr +++ b/tests/ui/parser/diff-markers/unclosed-delims-in-macro.stderr @@ -1,5 +1,5 @@ error: this file contains an unclosed delimiter - --> $DIR/unclosed-delims-in-macro.rs:11:48 + --> $DIR/unclosed-delims-in-macro.rs:11:54 | LL | macro_rules! foo { | - unclosed delimiter @@ -8,7 +8,7 @@ LL | () { | - this delimiter might not be properly closed... ... LL | } - | - ^ + | - ^ | | | ...as it matches this but it has different indentation diff --git a/tests/ui/parser/diff-markers/unclosed-delims.rs b/tests/ui/parser/diff-markers/unclosed-delims.rs index 827c1eebb9d5..daf2a9bac98a 100644 --- a/tests/ui/parser/diff-markers/unclosed-delims.rs +++ b/tests/ui/parser/diff-markers/unclosed-delims.rs @@ -9,4 +9,4 @@ mod tests { fn test2() { >>>>>>> 7a4f13c blah blah blah } -} //~ this file contains an unclosed delimiter +} //~ ERROR this file contains an unclosed delimiter diff --git a/tests/ui/parser/diff-markers/unclosed-delims.stderr b/tests/ui/parser/diff-markers/unclosed-delims.stderr index b2541aa47bae..cb083a043b8e 100644 --- a/tests/ui/parser/diff-markers/unclosed-delims.stderr +++ b/tests/ui/parser/diff-markers/unclosed-delims.stderr @@ -1,5 +1,5 @@ error: this file contains an unclosed delimiter - --> $DIR/unclosed-delims.rs:12:48 + --> $DIR/unclosed-delims.rs:12:54 | LL | mod tests { | - unclosed delimiter @@ -8,7 +8,7 @@ LL | fn test1() { | - this delimiter might not be properly closed... ... LL | } - | - ^ + | - ^ | | | ...as it matches this but it has different indentation diff --git a/tests/ui/parser/do-catch-suggests-try.rs b/tests/ui/parser/do-catch-suggests-try.rs index f64568d06e96..fcd55ce4059f 100644 --- a/tests/ui/parser/do-catch-suggests-try.rs +++ b/tests/ui/parser/do-catch-suggests-try.rs @@ -3,7 +3,7 @@ fn main() { let _: Option<()> = do catch {}; //~^ ERROR found removed `do catch` syntax - //~| replace with the new syntax + //~| HELP replace with the new syntax //~| following RFC #2388, the new non-placeholder syntax is `try` let _recovery_witness: () = 1; //~ ERROR mismatched types diff --git a/tests/ui/parser/float-field.rs b/tests/ui/parser/float-field.rs index 59fefee26aa6..9bf4d90fb46b 100644 --- a/tests/ui/parser/float-field.rs +++ b/tests/ui/parser/float-field.rs @@ -39,11 +39,11 @@ fn main() { { s.0x1.1; } //~ ERROR hexadecimal float literal is not supported //~| ERROR unexpected token: `0x1.1` - //~| expected one of `.`, `;`, `?`, `}`, or an operator, found `0x1.1` + //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `0x1.1` { s.0x1.1e1; } //~ ERROR hexadecimal float literal is not supported //~| ERROR unexpected token: `0x1.1e1` - //~| expected one of `.`, `;`, `?`, `}`, or an operator, found `0x1.1e1` + //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `0x1.1e1` { s.0x1e+; } //~ ERROR expected expression, found `;` diff --git a/tests/ui/parser/intersection-patterns-1.fixed b/tests/ui/parser/intersection-patterns-1.fixed index f63d57472cf1..8ade795f7eef 100644 --- a/tests/ui/parser/intersection-patterns-1.fixed +++ b/tests/ui/parser/intersection-patterns-1.fixed @@ -16,8 +16,8 @@ fn main() { match s { y @ Some(x) => {} //~^ ERROR pattern on wrong side of `@` - //~| pattern on the left, should be on the right - //~| binding on the right, should be on the left + //~| NOTE pattern on the left, should be on the right + //~| NOTE binding on the right, should be on the left //~| HELP switch the order //~| SUGGESTION y @ Some(x) _ => {} @@ -26,8 +26,8 @@ fn main() { match 2 { e @ 1..=5 => {} //~^ ERROR pattern on wrong side of `@` - //~| pattern on the left, should be on the right - //~| binding on the right, should be on the left + //~| NOTE pattern on the left, should be on the right + //~| NOTE binding on the right, should be on the left //~| HELP switch the order //~| SUGGESTION e @ 1..=5 _ => {} diff --git a/tests/ui/parser/intersection-patterns-1.rs b/tests/ui/parser/intersection-patterns-1.rs index 3a457659aac2..b5a7892fd1c5 100644 --- a/tests/ui/parser/intersection-patterns-1.rs +++ b/tests/ui/parser/intersection-patterns-1.rs @@ -16,8 +16,8 @@ fn main() { match s { Some(x) @ y => {} //~^ ERROR pattern on wrong side of `@` - //~| pattern on the left, should be on the right - //~| binding on the right, should be on the left + //~| NOTE pattern on the left, should be on the right + //~| NOTE binding on the right, should be on the left //~| HELP switch the order //~| SUGGESTION y @ Some(x) _ => {} @@ -26,8 +26,8 @@ fn main() { match 2 { 1 ..= 5 @ e => {} //~^ ERROR pattern on wrong side of `@` - //~| pattern on the left, should be on the right - //~| binding on the right, should be on the left + //~| NOTE pattern on the left, should be on the right + //~| NOTE binding on the right, should be on the left //~| HELP switch the order //~| SUGGESTION e @ 1..=5 _ => {} diff --git a/tests/ui/parser/intersection-patterns-2.rs b/tests/ui/parser/intersection-patterns-2.rs index 408415e87ef9..387127fc4d97 100644 --- a/tests/ui/parser/intersection-patterns-2.rs +++ b/tests/ui/parser/intersection-patterns-2.rs @@ -12,8 +12,8 @@ fn main() { match s { Some(x) @ Some(y) => {} //~^ ERROR left-hand side of `@` must be a binding - //~| interpreted as a pattern, not a binding - //~| also a pattern + //~| NOTE interpreted as a pattern, not a binding + //~| NOTE also a pattern //~| NOTE bindings are `x`, `mut x`, `ref x`, and `ref mut x` _ => {} } diff --git a/tests/ui/parser/issues/issue-101477-enum.fixed b/tests/ui/parser/issues/issue-101477-enum.fixed index 92c2b7c470f9..7fd08b65929d 100644 --- a/tests/ui/parser/issues/issue-101477-enum.fixed +++ b/tests/ui/parser/issues/issue-101477-enum.fixed @@ -4,7 +4,7 @@ enum Demo { A = 1, B = 2 //~ ERROR unexpected `==` - //~^ expected item, found `==` + //~^ ERROR expected item, found `==` } fn main() {} diff --git a/tests/ui/parser/issues/issue-101477-enum.rs b/tests/ui/parser/issues/issue-101477-enum.rs index 21d377384d3f..2e9d6b25c144 100644 --- a/tests/ui/parser/issues/issue-101477-enum.rs +++ b/tests/ui/parser/issues/issue-101477-enum.rs @@ -4,7 +4,7 @@ enum Demo { A = 1, B == 2 //~ ERROR unexpected `==` - //~^ expected item, found `==` + //~^ ERROR expected item, found `==` } fn main() {} diff --git a/tests/ui/parser/issues/issue-102806.rs b/tests/ui/parser/issues/issue-102806.rs index ba297bdc9677..5ee8c5c1e3de 100644 --- a/tests/ui/parser/issues/issue-102806.rs +++ b/tests/ui/parser/issues/issue-102806.rs @@ -15,7 +15,7 @@ fn pz(v: V3) { //~^ ERROR expected `..` let _ = V3 { z: 0.0, ... }; - //~^ expected identifier + //~^ ERROR expected identifier //~| ERROR missing fields `x` and `y` in initializer of `V3` let V3 { z: val, ... } = v; diff --git a/tests/ui/parser/issues/issue-89574.rs b/tests/ui/parser/issues/issue-89574.rs index 276abfe71102..4d28ad051dfa 100644 --- a/tests/ui/parser/issues/issue-89574.rs +++ b/tests/ui/parser/issues/issue-89574.rs @@ -1,5 +1,5 @@ fn main() { const EMPTY_ARRAY = []; - //~^ missing type for `const` item + //~^ ERROR missing type for `const` item //~| ERROR type annotations needed } diff --git a/tests/ui/parser/issues/issue-93867.rs b/tests/ui/parser/issues/issue-93867.rs index 507447923915..192b15818963 100644 --- a/tests/ui/parser/issues/issue-93867.rs +++ b/tests/ui/parser/issues/issue-93867.rs @@ -5,6 +5,6 @@ pub struct Entry<'a, K, V> { pub fn entry<'a, K, V>() -> Entry<'a K, V> { // ^ missing comma -//~^^ expected one of `,` or `>`, found `K` +//~^^ ERROR expected one of `,` or `>`, found `K` unimplemented!() } diff --git a/tests/ui/parser/macro/macro-expand-to-field.rs b/tests/ui/parser/macro/macro-expand-to-field.rs index ccdcf013cd25..f5100a5d7003 100644 --- a/tests/ui/parser/macro/macro-expand-to-field.rs +++ b/tests/ui/parser/macro/macro-expand-to-field.rs @@ -49,7 +49,7 @@ enum EnumVariantField { field!(oopsies:()), //~^ NOTE macros cannot expand to struct fields //~| ERROR unexpected token: `!` - //~| unexpected token after this + //~| NOTE unexpected token after this field!(oopsies2:()), }, } diff --git a/tests/ui/parser/raw/issue-70677-panic-on-unterminated-raw-str-at-eof.rs b/tests/ui/parser/raw/issue-70677-panic-on-unterminated-raw-str-at-eof.rs index bdfc29a3d57a..b7afb8fff81d 100644 --- a/tests/ui/parser/raw/issue-70677-panic-on-unterminated-raw-str-at-eof.rs +++ b/tests/ui/parser/raw/issue-70677-panic-on-unterminated-raw-str-at-eof.rs @@ -2,4 +2,4 @@ // the last byte in the file (including not having a trailing newline) // Prior to the fix you get the error: 'expected item, found `r" ...`' // because the string being unterminated wasn't properly detected. -r" //~ unterminated raw string +r" //~ ERROR unterminated raw string diff --git a/tests/ui/parser/raw/raw-byte-string-eof.rs b/tests/ui/parser/raw/raw-byte-string-eof.rs index b74907b72b0c..d62aa332c2f2 100644 --- a/tests/ui/parser/raw/raw-byte-string-eof.rs +++ b/tests/ui/parser/raw/raw-byte-string-eof.rs @@ -1,3 +1,3 @@ pub fn main() { - br##"a"#; //~ unterminated raw string + br##"a"#; //~ ERROR unterminated raw string } diff --git a/tests/ui/parser/recover/recover-fn-trait-from-fn-kw.rs b/tests/ui/parser/recover/recover-fn-trait-from-fn-kw.rs index b6611e6273d3..1f19f4b9c064 100644 --- a/tests/ui/parser/recover/recover-fn-trait-from-fn-kw.rs +++ b/tests/ui/parser/recover/recover-fn-trait-from-fn-kw.rs @@ -6,7 +6,7 @@ fn foo2(_: T) {} fn main() { foo(|| ()); - //~^ mismatched types + //~^ ERROR mismatched types foo2(|_: ()| {}); - //~^ type mismatch in closure arguments + //~^ ERROR type mismatch in closure arguments } diff --git a/tests/ui/parser/require-parens-for-chained-comparison.rs b/tests/ui/parser/require-parens-for-chained-comparison.rs index 916f1b83db24..21a908923f22 100644 --- a/tests/ui/parser/require-parens-for-chained-comparison.rs +++ b/tests/ui/parser/require-parens-for-chained-comparison.rs @@ -27,7 +27,7 @@ fn main() { //~| ERROR invalid label name f<'_>(); - //~^ comparison operators cannot be chained + //~^ ERROR comparison operators cannot be chained //~| HELP use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments //~| ERROR expected //~| HELP add `'` to close the char literal diff --git a/tests/ui/parser/shebang/issue-71471-ignore-tidy.rs b/tests/ui/parser/shebang/issue-71471-ignore-tidy.rs index e9bff91f1e8c..858c06048cc6 100644 --- a/tests/ui/parser/shebang/issue-71471-ignore-tidy.rs +++ b/tests/ui/parser/shebang/issue-71471-ignore-tidy.rs @@ -1,4 +1,4 @@ -#!B //~ expected `[`, found `B` +#!B //~ ERROR expected `[`, found `B` //@ reference: input.shebang diff --git a/tests/ui/parser/shebang/shebang-must-start-file.rs b/tests/ui/parser/shebang/shebang-must-start-file.rs index f91e32f744e1..f956cff3b081 100644 --- a/tests/ui/parser/shebang/shebang-must-start-file.rs +++ b/tests/ui/parser/shebang/shebang-must-start-file.rs @@ -1,5 +1,5 @@ // something on the first line for tidy -#!/bin/bash //~ expected `[`, found `/` +#!/bin/bash //~ ERROR expected `[`, found `/` //@ reference: input.shebang diff --git a/tests/ui/pattern/patkind-ref-binding-issue-114896.fixed b/tests/ui/pattern/patkind-ref-binding-issue-114896.fixed index 086a119eb776..2eeca4bdb7a5 100644 --- a/tests/ui/pattern/patkind-ref-binding-issue-114896.fixed +++ b/tests/ui/pattern/patkind-ref-binding-issue-114896.fixed @@ -5,6 +5,6 @@ fn main() { fn x(a: &char) { let &(mut b) = a; b.make_ascii_uppercase(); -//~^ cannot borrow `b` as mutable, as it is not declared as mutable + //~^ ERROR cannot borrow `b` as mutable, as it is not declared as mutable } } diff --git a/tests/ui/pattern/patkind-ref-binding-issue-114896.rs b/tests/ui/pattern/patkind-ref-binding-issue-114896.rs index b4d6b72c01f2..f074246b7829 100644 --- a/tests/ui/pattern/patkind-ref-binding-issue-114896.rs +++ b/tests/ui/pattern/patkind-ref-binding-issue-114896.rs @@ -5,6 +5,6 @@ fn main() { fn x(a: &char) { let &b = a; b.make_ascii_uppercase(); -//~^ cannot borrow `b` as mutable, as it is not declared as mutable + //~^ ERROR cannot borrow `b` as mutable, as it is not declared as mutable } } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs index 621ca7cc792e..c171dcf0ca66 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs @@ -13,14 +13,14 @@ /// to fail in HIR typeck on stable. As such, they need to be separate from the other tests. fn errors_caught_in_hir_typeck_on_stable() { let [&x] = &[&mut 0]; - //[stable2021]~^ mismatched types + //[stable2021]~^ ERROR mismatched types //[stable2021]~| types differ in mutability //[classic2024]~^^^ ERROR: cannot move out of type #[cfg(any(classic2021, structural2021))] let _: u32 = x; #[cfg(structural2024)] let _: &u32 = x; let [&x] = &mut [&mut 0]; - //[stable2021]~^ mismatched types + //[stable2021]~^ ERROR mismatched types //[stable2021]~| types differ in mutability //[classic2024]~^^^ ERROR: cannot move out of type #[cfg(any(classic2021, structural2021))] let _: u32 = x; @@ -34,7 +34,7 @@ pub fn main() { } let &ref mut x = &0; - //~^ cannot borrow data in a `&` reference as mutable [E0596] + //~^ ERROR cannot borrow data in a `&` reference as mutable [E0596] // For 2021 edition, this is also a regression test for #136223 // since the maximum mutability is downgraded during the pattern check process. diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.rs index c8e988ad76d9..94691e77bd8d 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.rs @@ -28,6 +28,6 @@ pub fn main() { let [&mut mut x] = &[&mut 0]; //[classic2024]~^ ERROR: mismatched types //[classic2024]~| cannot match inherited `&` with `&mut` pattern - //[structural2024]~^^^ binding cannot be both mutable and by-reference + //[structural2024]~^^^ ERROR binding cannot be both mutable and by-reference #[cfg(any(stable2021, classic2021, structural2021))] { x = 0 } } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs index 62c1c28022b7..877b10dcfd54 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs @@ -30,63 +30,63 @@ pub fn main() { #[cfg(any(classic2024, structural2024))] let _: &u32 = x; } if let Some(Some(&&x)) = &Some(Some(&0)) { - //[stable2021,classic2021,structural2021]~^ mismatched types + //[stable2021,classic2021,structural2021]~^ ERROR mismatched types //[stable2021,classic2021,structural2021]~| expected integer, found `&_` #[cfg(any(classic2024, structural2024))] let _: u32 = x; } // Tests for eating a lone inherited reference if let Some(Some(&x)) = &Some(&Some(0)) { - //[stable2021]~^ mismatched types + //[stable2021]~^ ERROR mismatched types //[stable2021]~| expected integer, found `&_` #[cfg(any(classic2021, structural2021, classic2024, structural2024))] let _: u32 = x; } if let Some(&Some(x)) = &Some(Some(0)) { - //[stable2021]~^ mismatched types + //[stable2021]~^ ERROR mismatched types //[stable2021]~| expected `Option<{integer}>`, found `&_` #[cfg(any(classic2021, structural2021, classic2024, structural2024))] let _: u32 = x; } if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) { - //[stable2021]~^ mismatched types + //[stable2021]~^ ERROR mismatched types //[stable2021]~| expected integer, found `&mut _` #[cfg(any(classic2021, structural2021, classic2024, structural2024))] let _: u32 = x; } // Tests for `&` patterns matching real `&mut` reference types if let Some(&Some(&x)) = Some(&Some(&mut 0)) { - //[stable2021]~^ mismatched types + //[stable2021]~^ ERROR mismatched types //[stable2021]~| types differ in mutability #[cfg(any(classic2021, structural2021, classic2024, structural2024))] let _: u32 = x; } // Tests for eating only one layer and also eating a lone inherited reference if let Some(&Some(&x)) = &Some(&Some(0)) { - //[stable2021,classic2021,structural2021]~^ mismatched types + //[stable2021,classic2021,structural2021]~^ ERROR mismatched types //[stable2021,classic2021,structural2021]~| expected integer, found `&_` #[cfg(any(classic2024, structural2024))] let _: u32 = x; } // Tests for `&` matching a lone inherited possibly-`&mut` reference if let Some(&Some(Some(&x))) = &Some(Some(&mut Some(0))) { - //[stable2021]~^ mismatched types + //[stable2021]~^ ERROR mismatched types //[stable2021]~| expected `Option<&mut Option<{integer}>>`, found `&_` #[cfg(any(classic2021, structural2021, classic2024, structural2024))] let _: u32 = x; } if let Some(&Some(x)) = &mut Some(Some(0)) { - //[stable2021]~^ mismatched types + //[stable2021]~^ ERROR mismatched types //[stable2021]~| expected `Option<{integer}>`, found `&_` #[cfg(any(classic2021, structural2021, classic2024, structural2024))] let _: u32 = x; } // Tests eating one layer, eating a lone inherited ref, and `&` eating `&mut` (realness varies) if let Some(&Some(&x)) = &Some(&mut Some(0)) { - //[stable2021,classic2021,structural2021]~^ mismatched types + //[stable2021,classic2021,structural2021]~^ ERROR mismatched types //[stable2021]~| types differ in mutability //[classic2021,structural2021]~| expected integer, found `&_` #[cfg(any(classic2024, structural2024))] let _: u32 = x; } if let Some(&Some(&x)) = &mut Some(&Some(0)) { - //[stable2021,classic2021,structural2021]~^ mismatched types + //[stable2021,classic2021,structural2021]~^ ERROR mismatched types //[stable2021,classic2021,structural2021]~| expected integer, found `&_` #[cfg(any(classic2024, structural2024))] let _: u32 = x; } @@ -94,46 +94,46 @@ pub fn main() { // Tests for eat-inner and eat-both rulesets matching on the outer reference if matching on the // inner reference causes a mutability mismatch. i.e. tests for "fallback-to-outer" deref rules. let [&mut x] = &mut [&0]; - //[stable2021]~^ mismatched types + //[stable2021]~^ ERROR mismatched types //[stable2021]~| types differ in mutability #[cfg(any(classic2021, structural2021))] let _: u32 = x; #[cfg(any(classic2024, structural2024))] let _: &u32 = x; let [&mut ref x] = &mut [&0]; - //[stable2021]~^ mismatched types + //[stable2021]~^ ERROR mismatched types //[stable2021]~| types differ in mutability #[cfg(any(classic2021, structural2021))] let _: &u32 = x; #[cfg(any(classic2024, structural2024))] let _: &&u32 = x; fn borrowck_error_on_structural2021() { let [&mut ref mut x] = &mut [&0]; - //[stable2021]~^ mismatched types + //[stable2021]~^ ERROR mismatched types //[stable2021]~| types differ in mutability - //[classic2021,structural2021]~^^^ cannot borrow data in a `&` reference as mutable + //[classic2021,structural2021]~^^^ ERROR cannot borrow data in a `&` reference as mutable #[cfg(any(classic2024, structural2024))] let _: &mut &u32 = x; } borrowck_error_on_structural2021(); let [&mut mut x] = &mut [&0]; - //[stable2021]~^ mismatched types + //[stable2021]~^ ERROR mismatched types //[stable2021]~| types differ in mutability #[cfg(any(classic2021, structural2021))] let _: u32 = x; #[cfg(any(classic2024, structural2024))] let _: &u32 = x; let [&mut &x] = &mut [&0]; - //[stable2021,classic2021,structural2021]~^ mismatched types + //[stable2021,classic2021,structural2021]~^ ERROR mismatched types //[stable2021]~| types differ in mutability //[classic2021,structural2021]~| expected integer, found `&_` #[cfg(any(classic2024, structural2024))] let _: u32 = x; let [&mut &ref x] = &mut [&0]; - //[stable2021,classic2021,structural2021]~^ mismatched types + //[stable2021,classic2021,structural2021]~^ ERROR mismatched types //[stable2021]~| types differ in mutability //[classic2021,structural2021]~| expected integer, found `&_` #[cfg(any(classic2024, structural2024))] let _: &u32 = x; let [&mut &(mut x)] = &mut [&0]; - //[stable2021,classic2021,structural2021]~^ mismatched types + //[stable2021,classic2021,structural2021]~^ ERROR mismatched types //[stable2021]~| types differ in mutability //[classic2021,structural2021]~| expected integer, found `&_` #[cfg(any(classic2024, structural2024))] let _: u32 = x; diff --git a/tests/ui/pattern/usefulness/doc-hidden-fields.rs b/tests/ui/pattern/usefulness/doc-hidden-fields.rs index 549e0d1af558..a3c3740b34ad 100644 --- a/tests/ui/pattern/usefulness/doc-hidden-fields.rs +++ b/tests/ui/pattern/usefulness/doc-hidden-fields.rs @@ -13,14 +13,14 @@ struct InCrate { fn main() { let HiddenStruct { one, two } = HiddenStruct::default(); - //~^ pattern requires `..` due to inaccessible fields + //~^ ERROR pattern requires `..` due to inaccessible fields let HiddenStruct { one } = HiddenStruct::default(); - //~^ pattern does not mention field `two` and inaccessible fields + //~^ ERROR pattern does not mention field `two` and inaccessible fields let HiddenStruct { one, hide } = HiddenStruct::default(); - //~^ pattern does not mention field `two` + //~^ ERROR pattern does not mention field `two` let InCrate { a, b } = InCrate { a: 0, b: false, im_hidden: 0 }; - //~^ pattern does not mention field `im_hidden` + //~^ ERROR pattern does not mention field `im_hidden` } diff --git a/tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.rs b/tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.rs index 56842917f500..4bbdc7b139f4 100644 --- a/tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.rs +++ b/tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.rs @@ -16,28 +16,28 @@ fn main() { HiddenEnum::A => {} HiddenEnum::B => {} } - //~^^^^ non-exhaustive patterns: `_` not covered + //~^^^^ ERROR non-exhaustive patterns: `_` not covered match HiddenEnum::A { HiddenEnum::A => {} HiddenEnum::C => {} } - //~^^^^ non-exhaustive patterns: `HiddenEnum::B` not covered + //~^^^^ ERROR non-exhaustive patterns: `HiddenEnum::B` not covered match HiddenEnum::A { HiddenEnum::A => {} } - //~^^^ non-exhaustive patterns: `HiddenEnum::B` and `_` not covered + //~^^^ ERROR non-exhaustive patterns: `HiddenEnum::B` and `_` not covered match None { None => {} Some(HiddenEnum::A) => {} } - //~^^^^ non-exhaustive patterns: `Some(HiddenEnum::B)` and `Some(_)` not covered + //~^^^^ ERROR non-exhaustive patterns: `Some(HiddenEnum::B)` and `Some(_)` not covered match InCrate::A { InCrate::A => {} InCrate::B => {} } - //~^^^^ non-exhaustive patterns: `InCrate::C` not covered + //~^^^^ ERROR non-exhaustive patterns: `InCrate::C` not covered } diff --git a/tests/ui/pattern/usefulness/non-exhaustive-defined-here.rs b/tests/ui/pattern/usefulness/non-exhaustive-defined-here.rs index d0a8a10f2f37..4a7b2c956fc3 100644 --- a/tests/ui/pattern/usefulness/non-exhaustive-defined-here.rs +++ b/tests/ui/pattern/usefulness/non-exhaustive-defined-here.rs @@ -24,12 +24,12 @@ enum E { //~| NOTE not covered //~| NOTE not covered C - //~^ not covered - //~| not covered - //~| not covered - //~| not covered - //~| not covered - //~| not covered + //~^ NOTE not covered + //~| NOTE not covered + //~| NOTE not covered + //~| NOTE not covered + //~| NOTE not covered + //~| NOTE not covered } fn by_val(e: E) { @@ -42,7 +42,7 @@ fn by_val(e: E) { let E::A = e; //~^ ERROR refutable pattern in local binding - //~| patterns `E::B` and `E::C` not covered + //~| NOTE patterns `E::B` and `E::C` not covered //~| NOTE `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with //~| NOTE for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html //~| NOTE the matched value is of type `E` @@ -51,14 +51,14 @@ fn by_val(e: E) { fn by_ref_once(e: &E) { match e { //~^ ERROR non-exhaustive patterns - //~| patterns `&E::B` and `&E::C` not covered + //~| NOTE patterns `&E::B` and `&E::C` not covered //~| NOTE the matched value is of type `&E` E::A => {} } let E::A = e; //~^ ERROR refutable pattern in local binding - //~| patterns `&E::B` and `&E::C` not covered + //~| NOTE patterns `&E::B` and `&E::C` not covered //~| NOTE `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with //~| NOTE for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html //~| NOTE the matched value is of type `&E` @@ -67,14 +67,14 @@ fn by_ref_once(e: &E) { fn by_ref_thrice(e: & &mut &E) { match e { //~^ ERROR non-exhaustive patterns - //~| patterns `&&mut &E::B` and `&&mut &E::C` not covered + //~| NOTE patterns `&&mut &E::B` and `&&mut &E::C` not covered //~| NOTE the matched value is of type `&&mut &E` E::A => {} } let E::A = e; //~^ ERROR refutable pattern in local binding - //~| patterns `&&mut &E::B` and `&&mut &E::C` not covered + //~| NOTE patterns `&&mut &E::B` and `&&mut &E::C` not covered //~| NOTE `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with //~| NOTE for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html //~| NOTE the matched value is of type `&&mut &E` @@ -93,7 +93,7 @@ enum Opt { fn ref_pat(e: Opt) { match e { //~^ ERROR non-exhaustive patterns - //~| pattern `Opt::None` not covered + //~| NOTE pattern `Opt::None` not covered //~| NOTE the matched value is of type `Opt` Opt::Some(ref _x) => {} } diff --git a/tests/ui/pattern/usefulness/stable-gated-fields.rs b/tests/ui/pattern/usefulness/stable-gated-fields.rs index 61b202b77f61..7be2722daac7 100644 --- a/tests/ui/pattern/usefulness/stable-gated-fields.rs +++ b/tests/ui/pattern/usefulness/stable-gated-fields.rs @@ -6,10 +6,10 @@ use unstable::UnstableStruct; fn main() { let UnstableStruct { stable } = UnstableStruct::default(); - //~^ pattern does not mention field `stable2` and inaccessible fields + //~^ ERROR pattern does not mention field `stable2` and inaccessible fields let UnstableStruct { stable, stable2 } = UnstableStruct::default(); - //~^ pattern requires `..` due to inaccessible fields + //~^ ERROR pattern requires `..` due to inaccessible fields // OK: stable field is matched let UnstableStruct { stable, stable2, .. } = UnstableStruct::default(); diff --git a/tests/ui/pattern/usefulness/stable-gated-patterns.rs b/tests/ui/pattern/usefulness/stable-gated-patterns.rs index 5ceffbf09236..d58483441549 100644 --- a/tests/ui/pattern/usefulness/stable-gated-patterns.rs +++ b/tests/ui/pattern/usefulness/stable-gated-patterns.rs @@ -8,11 +8,11 @@ fn main() { match UnstableEnum::Stable { UnstableEnum::Stable => {} } - //~^^^ non-exhaustive patterns: `UnstableEnum::Stable2` and `_` not covered + //~^^^ ERROR non-exhaustive patterns: `UnstableEnum::Stable2` and `_` not covered match UnstableEnum::Stable { UnstableEnum::Stable => {} UnstableEnum::Stable2 => {} } - //~^^^^ non-exhaustive patterns: `_` not covered + //~^^^^ ERROR non-exhaustive patterns: `_` not covered } diff --git a/tests/ui/pattern/usefulness/unstable-gated-fields.rs b/tests/ui/pattern/usefulness/unstable-gated-fields.rs index e6a4494867a0..08b46283f659 100644 --- a/tests/ui/pattern/usefulness/unstable-gated-fields.rs +++ b/tests/ui/pattern/usefulness/unstable-gated-fields.rs @@ -8,10 +8,10 @@ use unstable::UnstableStruct; fn main() { let UnstableStruct { stable, stable2, } = UnstableStruct::default(); - //~^ pattern does not mention field `unstable` + //~^ ERROR pattern does not mention field `unstable` let UnstableStruct { stable, unstable, } = UnstableStruct::default(); - //~^ pattern does not mention field `stable2` + //~^ ERROR pattern does not mention field `stable2` // OK: stable field is matched let UnstableStruct { stable, stable2, unstable } = UnstableStruct::default(); diff --git a/tests/ui/pattern/usefulness/unstable-gated-patterns.rs b/tests/ui/pattern/usefulness/unstable-gated-patterns.rs index e6db495a1494..3acc0738bbc8 100644 --- a/tests/ui/pattern/usefulness/unstable-gated-patterns.rs +++ b/tests/ui/pattern/usefulness/unstable-gated-patterns.rs @@ -11,7 +11,7 @@ fn main() { UnstableEnum::Stable => {} UnstableEnum::Stable2 => {} } - //~^^^^ non-exhaustive patterns: `UnstableEnum::Unstable` not covered + //~^^^^ ERROR non-exhaustive patterns: `UnstableEnum::Unstable` not covered // Ok: all variants are explicitly matched match UnstableEnum::Stable { diff --git a/tests/ui/privacy/privacy3.rs b/tests/ui/privacy/privacy3.rs index 2bb3c1b3c61d..ec213285b405 100644 --- a/tests/ui/privacy/privacy3.rs +++ b/tests/ui/privacy/privacy3.rs @@ -22,7 +22,7 @@ fn test1() { //~^ ERROR requires `sized` lang_item use bar::gpriv; //~^ ERROR unresolved import `bar::gpriv` [E0432] - //~| no `gpriv` in `bar` + //~| NOTE no `gpriv` in `bar` // This should pass because the compiler will insert a fake name binding // for `gpriv` diff --git a/tests/ui/proc-macro/issue-50493.rs b/tests/ui/proc-macro/issue-50493.rs index e23f1f7c7d87..4a88eee21852 100644 --- a/tests/ui/proc-macro/issue-50493.rs +++ b/tests/ui/proc-macro/issue-50493.rs @@ -5,7 +5,7 @@ extern crate issue_50493; #[derive(Derive)] struct Restricted { - pub(in restricted) field: usize, //~ visibilities can only be restricted to ancestor modules + pub(in restricted) field: usize, //~ ERROR visibilities can only be restricted to ancestor modules } mod restricted {} diff --git a/tests/ui/proc-macro/pub-at-crate-root.rs b/tests/ui/proc-macro/pub-at-crate-root.rs index 32e4999a71bc..b8de66967b10 100644 --- a/tests/ui/proc-macro/pub-at-crate-root.rs +++ b/tests/ui/proc-macro/pub-at-crate-root.rs @@ -5,7 +5,7 @@ extern crate proc_macro; -pub mod a { //~ `proc-macro` crate types currently cannot export any items +pub mod a { //~ ERROR `proc-macro` crate types currently cannot export any items use proc_macro::TokenStream; #[proc_macro_derive(B)] diff --git a/tests/ui/pub/pub-restricted.rs b/tests/ui/pub/pub-restricted.rs index bcd21082f75c..2aa24121335c 100644 --- a/tests/ui/pub/pub-restricted.rs +++ b/tests/ui/pub/pub-restricted.rs @@ -1,8 +1,8 @@ mod a {} -pub (a) fn afn() {} //~ incorrect visibility restriction -pub (b) fn bfn() {} //~ incorrect visibility restriction -pub (crate::a) fn cfn() {} //~ incorrect visibility restriction +pub (a) fn afn() {} //~ ERROR incorrect visibility restriction +pub (b) fn bfn() {} //~ ERROR incorrect visibility restriction +pub (crate::a) fn cfn() {} //~ ERROR incorrect visibility restriction pub fn privfn() {} mod x { @@ -19,7 +19,7 @@ mod y { pub (super) s: usize, valid_private: usize, pub (in y) valid_in_x: usize, - pub (a) invalid: usize, //~ incorrect visibility restriction + pub (a) invalid: usize, //~ ERROR incorrect visibility restriction pub (in x) non_parent_invalid: usize, //~ ERROR visibilities can only be restricted } } @@ -28,4 +28,4 @@ fn main() {} // test multichar names mod xyz {} -pub (xyz) fn xyz() {} //~ incorrect visibility restriction +pub (xyz) fn xyz() {} //~ ERROR incorrect visibility restriction diff --git a/tests/ui/repr/attr-usage-repr.rs b/tests/ui/repr/attr-usage-repr.rs index d8515a12e055..cbf99f16e036 100644 --- a/tests/ui/repr/attr-usage-repr.rs +++ b/tests/ui/repr/attr-usage-repr.rs @@ -45,7 +45,7 @@ enum EInt { B, } -#[repr()] //~ attribute should be applied to a struct, enum, function, associated function, or union [E0517] +#[repr()] //~ ERROR attribute should be applied to a struct, enum, function, associated function, or union [E0517] type SirThisIsAType = i32; #[repr()] diff --git a/tests/ui/resolve/crate-called-as-function.rs b/tests/ui/resolve/crate-called-as-function.rs index e8f52c0c029a..30922d923f48 100644 --- a/tests/ui/resolve/crate-called-as-function.rs +++ b/tests/ui/resolve/crate-called-as-function.rs @@ -1,3 +1,3 @@ fn main() { - ::foo() //~ cannot find external crate `foo` in the crate root + ::foo() //~ ERROR cannot find external crate `foo` in the crate root } diff --git a/tests/ui/resolve/issue-118295.rs b/tests/ui/resolve/issue-118295.rs index 37a49baee80c..d8c6310300a3 100644 --- a/tests/ui/resolve/issue-118295.rs +++ b/tests/ui/resolve/issue-118295.rs @@ -1,11 +1,11 @@ macro_rules! {} //~^ ERROR cannot find macro `macro_rules` in this scope //~| NOTE maybe you have forgotten to define a name for this `macro_rules!` -//~| put a macro name here +//~| NOTE put a macro name here macro_rules!{} //~^ ERROR cannot find macro `macro_rules` in this scope //~| NOTE maybe you have forgotten to define a name for this `macro_rules!` -//~| put a macro name here +//~| NOTE put a macro name here fn main() {} diff --git a/tests/ui/resolve/tool-import.rs b/tests/ui/resolve/tool-import.rs index bde375a2c490..951505b92a0b 100644 --- a/tests/ui/resolve/tool-import.rs +++ b/tests/ui/resolve/tool-import.rs @@ -1,7 +1,7 @@ //@ edition: 2018 use clippy::time::Instant; -//~^ `clippy` is a tool module +//~^ ERROR `clippy` is a tool module fn main() { Instant::now(); diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns.rs index 5809e56fb7b4..ba800e315b15 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns.rs +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/omitted-patterns.rs @@ -63,14 +63,14 @@ fn main() { } match non_enum { - //~^ some variants are not matched explicitly + //~^ ERROR some variants are not matched explicitly NonExhaustiveEnum::Unit => {} NonExhaustiveEnum::Tuple(_) => {} _ => {} } match non_enum { - //~^ some variants are not matched explicitly + //~^ ERROR some variants are not matched explicitly NonExhaustiveEnum::Unit | NonExhaustiveEnum::Struct { .. } => {} _ => {} } @@ -91,7 +91,7 @@ fn main() { _ => {} } match (non_enum, true) { - //~^ some variants are not matched explicitly + //~^ ERROR some variants are not matched explicitly (NonExhaustiveEnum::Unit, true) => {} (NonExhaustiveEnum::Tuple(_), false) => {} _ => {} @@ -104,14 +104,14 @@ fn main() { _ => {} } match (true, non_enum) { - //~^ some variants are not matched explicitly + //~^ ERROR some variants are not matched explicitly (true, NonExhaustiveEnum::Unit) => {} (false, NonExhaustiveEnum::Tuple(_)) => {} _ => {} } match Some(non_enum) { - //~^ some variants are not matched explicitly + //~^ ERROR some variants are not matched explicitly Some(NonExhaustiveEnum::Unit) => {} Some(NonExhaustiveEnum::Tuple(_)) => {} _ => {} @@ -127,7 +127,7 @@ fn main() { } match NestedNonExhaustive::B { - //~^ some variants are not matched explicitly + //~^ ERROR some variants are not matched explicitly NestedNonExhaustive::A(NonExhaustiveEnum::Unit) => {} NestedNonExhaustive::A(_) => {} NestedNonExhaustive::B => {} @@ -138,17 +138,17 @@ fn main() { VariantNonExhaustive::Baz(_, _) => {} VariantNonExhaustive::Bar { x, .. } => {} } - //~^^ some fields are not explicitly listed + //~^^ ERROR some fields are not explicitly listed let FunctionalRecord { first_field, second_field, .. } = FunctionalRecord::default(); - //~^ some fields are not explicitly listed + //~^ ERROR some fields are not explicitly listed // Ok: this is local let Foo { a, b, .. } = Foo::default(); let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = NestedStruct::default(); - //~^ some fields are not explicitly listed - //~^^ some fields are not explicitly listed + //~^ ERROR some fields are not explicitly listed + //~^^ ERROR some fields are not explicitly listed // Ok: this tests https://github.com/rust-lang/rust/issues/89382 let MixedVisFields { a, b, .. } = MixedVisFields::default(); @@ -182,7 +182,7 @@ fn main() { if let NonExhaustiveEnum::Tuple(_) = non_enum {} match UnstableEnum::Stable { - //~^ some variants are not matched explicitly + //~^ ERROR some variants are not matched explicitly UnstableEnum::Stable => {} UnstableEnum::Stable2 => {} _ => {} @@ -204,19 +204,19 @@ fn main() { } match OnlyUnstableEnum::Unstable { - //~^ some variants are not matched explicitly + //~^ ERROR some variants are not matched explicitly OnlyUnstableEnum::Unstable => {} _ => {} } let OnlyUnstableStruct { unstable, .. } = OnlyUnstableStruct::new(); - //~^ some fields are not explicitly listed + //~^ ERROR some fields are not explicitly listed // OK: both unstable fields are matched with feature on let OnlyUnstableStruct { unstable, unstable2, .. } = OnlyUnstableStruct::new(); let UnstableStruct { stable, stable2, .. } = UnstableStruct::default(); - //~^ some fields are not explicitly listed + //~^ ERROR some fields are not explicitly listed // OK: both unstable and stable fields are matched with feature on let UnstableStruct { stable, stable2, unstable, .. } = UnstableStruct::default(); @@ -226,11 +226,11 @@ fn main() { // Ok: missing patterns will be blocked by the pattern being refutable let local_refutable @ NonExhaustiveEnum::Unit = NonExhaustiveEnum::Unit; - //~^ refutable pattern in local binding + //~^ ERROR refutable pattern in local binding // Check that matching on a reference results in a correct diagnostic match &non_enum { - //~^ some variants are not matched explicitly + //~^ ERROR some variants are not matched explicitly //~| pattern `&NonExhaustiveEnum::Struct { .. }` not covered NonExhaustiveEnum::Unit => {} NonExhaustiveEnum::Tuple(_) => {} @@ -238,21 +238,21 @@ fn main() { } match (true, &non_enum) { - //~^ some variants are not matched explicitly + //~^ ERROR some variants are not matched explicitly //~| patterns `(_, &NonExhaustiveEnum::Tuple(_))` and `(_, &NonExhaustiveEnum::Struct { .. })` not covered (true, NonExhaustiveEnum::Unit) => {} _ => {} } match (&non_enum, true) { - //~^ some variants are not matched explicitly + //~^ ERROR some variants are not matched explicitly //~| patterns `(&NonExhaustiveEnum::Tuple(_), _)` and `(&NonExhaustiveEnum::Struct { .. }, _)` not covered (NonExhaustiveEnum::Unit, true) => {} _ => {} } match Some(&non_enum) { - //~^ some variants are not matched explicitly + //~^ ERROR some variants are not matched explicitly //~| pattern `Some(&NonExhaustiveEnum::Struct { .. })` not covered Some(NonExhaustiveEnum::Unit | NonExhaustiveEnum::Tuple(_)) => {} _ => {} diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/stable-omitted-patterns.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/stable-omitted-patterns.rs index 6d3072f3ddd7..6e064251b721 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/stable-omitted-patterns.rs +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/stable-omitted-patterns.rs @@ -19,7 +19,7 @@ fn main() { #[deny(non_exhaustive_omitted_patterns)] match UnstableEnum::Stable { - //~^ some variants are not matched explicitly + //~^ ERROR some variants are not matched explicitly UnstableEnum::Stable => {} _ => {} } @@ -37,7 +37,7 @@ fn main() { #[warn(non_exhaustive_omitted_patterns)] let UnstableStruct { stable, .. } = UnstableStruct::default(); - //~^ some fields are not explicitly listed + //~^ WARN some fields are not explicitly listed // OK: stable field is matched #[warn(non_exhaustive_omitted_patterns)] diff --git a/tests/ui/rfcs/rfc-2093-infer-outlives/regions-enum-not-wf.rs b/tests/ui/rfcs/rfc-2093-infer-outlives/regions-enum-not-wf.rs index 8b491ee4e303..038f53034ab0 100644 --- a/tests/ui/rfcs/rfc-2093-infer-outlives/regions-enum-not-wf.rs +++ b/tests/ui/rfcs/rfc-2093-infer-outlives/regions-enum-not-wf.rs @@ -33,7 +33,7 @@ enum RefIndirect<'a, T> { enum RefDouble<'a, 'b, T> { RefDoubleVariant1(&'a RequireOutlives<'b, T>), - //~^ the parameter type `T` may not live long enough [E0309] + //~^ ERROR the parameter type `T` may not live long enough [E0309] } fn main() {} diff --git a/tests/ui/rfcs/rfc-2457-non-ascii-idents/extern_block_nonascii_forbidden.rs b/tests/ui/rfcs/rfc-2457-non-ascii-idents/extern_block_nonascii_forbidden.rs index ad6825404306..1d064ec54031 100644 --- a/tests/ui/rfcs/rfc-2457-non-ascii-idents/extern_block_nonascii_forbidden.rs +++ b/tests/ui/rfcs/rfc-2457-non-ascii-idents/extern_block_nonascii_forbidden.rs @@ -1,9 +1,9 @@ #![feature(extern_types)] extern "C" { - type 一; //~ items in `extern` blocks cannot use non-ascii identifiers - fn 二(); //~ items in `extern` blocks cannot use non-ascii identifiers - static 三: usize; //~ items in `extern` blocks cannot use non-ascii identifiers + type 一; //~ ERROR items in `extern` blocks cannot use non-ascii identifiers + fn 二(); //~ ERROR items in `extern` blocks cannot use non-ascii identifiers + static 三: usize; //~ ERROR items in `extern` blocks cannot use non-ascii identifiers } fn main() {} diff --git a/tests/ui/rfcs/rfc-2457-non-ascii-idents/mod_file_nonascii_forbidden.rs b/tests/ui/rfcs/rfc-2457-non-ascii-idents/mod_file_nonascii_forbidden.rs index e949e2319c1c..90a7347f6a10 100644 --- a/tests/ui/rfcs/rfc-2457-non-ascii-idents/mod_file_nonascii_forbidden.rs +++ b/tests/ui/rfcs/rfc-2457-non-ascii-idents/mod_file_nonascii_forbidden.rs @@ -1,4 +1,4 @@ -mod řųśť; //~ trying to load file for -//~^ file not found for +mod řųśť; //~ ERROR trying to load file for +//~^ ERROR file not found for fn main() {} diff --git a/tests/ui/rfcs/rfc-2457-non-ascii-idents/no_mangle_nonascii_forbidden.rs b/tests/ui/rfcs/rfc-2457-non-ascii-idents/no_mangle_nonascii_forbidden.rs index f4c126a6e025..dc36c7539e92 100644 --- a/tests/ui/rfcs/rfc-2457-non-ascii-idents/no_mangle_nonascii_forbidden.rs +++ b/tests/ui/rfcs/rfc-2457-non-ascii-idents/no_mangle_nonascii_forbidden.rs @@ -1,11 +1,11 @@ #[no_mangle] -pub fn řųśť() {} //~ `#[no_mangle]` requires ASCII identifier +pub fn řųśť() {} //~ ERROR `#[no_mangle]` requires ASCII identifier pub struct Foo; impl Foo { #[no_mangle] - pub fn řųśť() {} //~ `#[no_mangle]` requires ASCII identifier + pub fn řųśť() {} //~ ERROR `#[no_mangle]` requires ASCII identifier } trait Bar { @@ -14,7 +14,7 @@ trait Bar { impl Bar for Foo { #[no_mangle] - fn řųśť() {} //~ `#[no_mangle]` requires ASCII identifier + fn řųśť() {} //~ ERROR `#[no_mangle]` requires ASCII identifier } fn main() {} diff --git a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.rs b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.rs index f1a54ee5867c..3de88fcaecb6 100644 --- a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.rs +++ b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.rs @@ -6,7 +6,7 @@ struct P { impl P { fn y(&self, y: f64) -> Self { P{y, .. self.clone() } } - //~^ mismatched types [E0308] + //~^ ERROR mismatched types [E0308] } fn main() {} diff --git a/tests/ui/rust-2018/edition-lint-nested-paths.fixed b/tests/ui/rust-2018/edition-lint-nested-paths.fixed index 742732ebc494..93ccb2fe6af2 100644 --- a/tests/ui/rust-2018/edition-lint-nested-paths.fixed +++ b/tests/ui/rust-2018/edition-lint-nested-paths.fixed @@ -4,9 +4,9 @@ use crate::foo::{a, b}; //~^ ERROR absolute paths must start with -//~| this is accepted in the current edition +//~| WARN this is accepted in the current edition //~| ERROR absolute paths must start with -//~| this is accepted in the current edition +//~| WARN this is accepted in the current edition mod foo { pub(crate) fn a() {} @@ -21,9 +21,9 @@ fn main() { { use crate::foo::{self as x, c}; //~^ ERROR absolute paths must start with - //~| this is accepted in the current edition + //~| WARN this is accepted in the current edition //~| ERROR absolute paths must start with - //~| this is accepted in the current edition + //~| WARN this is accepted in the current edition x::a(); c(); } diff --git a/tests/ui/rust-2018/edition-lint-nested-paths.rs b/tests/ui/rust-2018/edition-lint-nested-paths.rs index 861ca521bb7b..1c1d21dbab91 100644 --- a/tests/ui/rust-2018/edition-lint-nested-paths.rs +++ b/tests/ui/rust-2018/edition-lint-nested-paths.rs @@ -4,9 +4,9 @@ use foo::{a, b}; //~^ ERROR absolute paths must start with -//~| this is accepted in the current edition +//~| WARN this is accepted in the current edition //~| ERROR absolute paths must start with -//~| this is accepted in the current edition +//~| WARN this is accepted in the current edition mod foo { pub(crate) fn a() {} @@ -21,9 +21,9 @@ fn main() { { use foo::{self as x, c}; //~^ ERROR absolute paths must start with - //~| this is accepted in the current edition + //~| WARN this is accepted in the current edition //~| ERROR absolute paths must start with - //~| this is accepted in the current edition + //~| WARN this is accepted in the current edition x::a(); c(); } diff --git a/tests/ui/rust-2021/future-prelude-collision-generic-trait.fixed b/tests/ui/rust-2021/future-prelude-collision-generic-trait.fixed index ea104011873c..129fdaeaeb23 100644 --- a/tests/ui/rust-2021/future-prelude-collision-generic-trait.fixed +++ b/tests/ui/rust-2021/future-prelude-collision-generic-trait.fixed @@ -23,7 +23,7 @@ where fn try_into(&self) -> Result<&U, i32> { >::try_from(self) //~^ WARNING trait-associated function `try_from` will become ambiguous in Rust 2021 - //~| this is accepted in the current edition (Rust 2018) + //~| WARN this is accepted in the current edition (Rust 2018) } } diff --git a/tests/ui/rust-2021/future-prelude-collision-generic-trait.rs b/tests/ui/rust-2021/future-prelude-collision-generic-trait.rs index ce7dd2fdac76..4e4d5d0d667c 100644 --- a/tests/ui/rust-2021/future-prelude-collision-generic-trait.rs +++ b/tests/ui/rust-2021/future-prelude-collision-generic-trait.rs @@ -23,7 +23,7 @@ where fn try_into(&self) -> Result<&U, i32> { U::try_from(self) //~^ WARNING trait-associated function `try_from` will become ambiguous in Rust 2021 - //~| this is accepted in the current edition (Rust 2018) + //~| WARN this is accepted in the current edition (Rust 2018) } } diff --git a/tests/ui/rust-2021/future-prelude-collision-generic.fixed b/tests/ui/rust-2021/future-prelude-collision-generic.fixed index 3546b1aef6ca..bb852832456a 100644 --- a/tests/ui/rust-2021/future-prelude-collision-generic.fixed +++ b/tests/ui/rust-2021/future-prelude-collision-generic.fixed @@ -27,11 +27,11 @@ impl std::iter::FromIterator for Generic<'static, i32> { fn main() { as MyFromIter>::from_iter(1); //~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021 - //~| this is accepted in the current edition (Rust 2018) + //~| WARN this is accepted in the current edition (Rust 2018) as MyFromIter>::from_iter(1); //~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021 - //~| this is accepted in the current edition (Rust 2018) + //~| WARN this is accepted in the current edition (Rust 2018) as MyFromIter>::from_iter(1); //~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021 - //~| this is accepted in the current edition (Rust 2018) + //~| WARN this is accepted in the current edition (Rust 2018) } diff --git a/tests/ui/rust-2021/future-prelude-collision-generic.rs b/tests/ui/rust-2021/future-prelude-collision-generic.rs index 1ae5e8fce23c..bcaced88763c 100644 --- a/tests/ui/rust-2021/future-prelude-collision-generic.rs +++ b/tests/ui/rust-2021/future-prelude-collision-generic.rs @@ -27,11 +27,11 @@ impl std::iter::FromIterator for Generic<'static, i32> { fn main() { Generic::from_iter(1); //~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021 - //~| this is accepted in the current edition (Rust 2018) + //~| WARN this is accepted in the current edition (Rust 2018) Generic::<'static, i32>::from_iter(1); //~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021 - //~| this is accepted in the current edition (Rust 2018) + //~| WARN this is accepted in the current edition (Rust 2018) Generic::<'_, _>::from_iter(1); //~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021 - //~| this is accepted in the current edition (Rust 2018) + //~| WARN this is accepted in the current edition (Rust 2018) } diff --git a/tests/ui/rust-2024/reserved-guarded-strings.rs b/tests/ui/rust-2024/reserved-guarded-strings.rs index ae68d34cb86e..ae4bd670fcad 100644 --- a/tests/ui/rust-2024/reserved-guarded-strings.rs +++ b/tests/ui/rust-2024/reserved-guarded-strings.rs @@ -46,13 +46,13 @@ fn main() { //~^ ERROR prefix `blah` is unknown //~| ERROR invalid string literal - demo2!(## "foo"); //~ reserved multi-hash token is forbidden - demo3!("foo"###); //~ reserved multi-hash token is forbidden - demo3!(### "foo"); //~ reserved multi-hash token is forbidden - demo3!(## "foo"#); //~ reserved multi-hash token is forbidden + demo2!(## "foo"); //~ ERROR reserved multi-hash token is forbidden + demo3!("foo"###); //~ ERROR reserved multi-hash token is forbidden + demo3!(### "foo"); //~ ERROR reserved multi-hash token is forbidden + demo3!(## "foo"#); //~ ERROR reserved multi-hash token is forbidden demo5!(### "foo"###); - //~^ reserved multi-hash token is forbidden - //~| reserved multi-hash token is forbidden + //~^ ERROR reserved multi-hash token is forbidden + //~| ERROR reserved multi-hash token is forbidden demo1!(#""); //~ ERROR invalid string literal demo1!(#""#); //~ ERROR invalid string literal diff --git a/tests/ui/self/arbitrary_self_type_infinite_recursion.rs b/tests/ui/self/arbitrary_self_type_infinite_recursion.rs index 6fbf35c0b867..79ca7079c421 100644 --- a/tests/ui/self/arbitrary_self_type_infinite_recursion.rs +++ b/tests/ui/self/arbitrary_self_type_infinite_recursion.rs @@ -10,15 +10,15 @@ struct Content; impl Content { fn method(self: MySmartPtr) { // note self type - //~^ reached the recursion limit - //~| reached the recursion limit - //~| invalid `self` parameter type + //~^ ERROR reached the recursion limit + //~| ERROR reached the recursion limit + //~| ERROR invalid `self` parameter type } } fn main() { let p = MySmartPtr(Content); p.method(); - //~^ reached the recursion limit - //~| no method named `method` + //~^ ERROR reached the recursion limit + //~| ERROR no method named `method` } diff --git a/tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.rs b/tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.rs index b5a8992542bf..2fb7aed970e5 100644 --- a/tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.rs +++ b/tests/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.rs @@ -6,16 +6,16 @@ struct Foo; impl Foo { async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f } - //~^ lifetime may not live long enough + //~^ ERROR lifetime may not live long enough async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) } - //~^ lifetime may not live long enough + //~^ ERROR lifetime may not live long enough } type Alias = Pin; impl Foo { async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg } - //~^ lifetime may not live long enough + //~^ ERROR lifetime may not live long enough } fn main() {} diff --git a/tests/ui/simd/empty-simd-vector-in-operand.rs b/tests/ui/simd/empty-simd-vector-in-operand.rs index 2a2a6c0737db..813222c8a2ed 100644 --- a/tests/ui/simd/empty-simd-vector-in-operand.rs +++ b/tests/ui/simd/empty-simd-vector-in-operand.rs @@ -10,6 +10,6 @@ struct A(); fn main() { unsafe { std::arch::asm!("{}", in(xmm_reg) A()); - //~^ use of empty SIMD vector `A` + //~^ ERROR use of empty SIMD vector `A` } } diff --git a/tests/ui/simd/monomorphize-shuffle-index.rs b/tests/ui/simd/monomorphize-shuffle-index.rs index 3a074dfd432c..a56f2ea14520 100644 --- a/tests/ui/simd/monomorphize-shuffle-index.rs +++ b/tests/ui/simd/monomorphize-shuffle-index.rs @@ -34,7 +34,7 @@ trait Shuffle { return simd_shuffle(a, b, Self::I); #[cfg(generic)] return simd_shuffle_const_generic::<_, _, { &Self::I.0 }>(a, b); - //[generic]~^ overly complex generic constant + //[generic]~^ ERROR overly complex generic constant #[cfg(generic_with_fn)] return simd_shuffle_const_generic::<_, _, { Self::J }>(a, b); } diff --git a/tests/ui/stability-attribute/generics-default-stability.rs b/tests/ui/stability-attribute/generics-default-stability.rs index e1b3971f70c0..400e22a8e6cc 100644 --- a/tests/ui/stability-attribute/generics-default-stability.rs +++ b/tests/ui/stability-attribute/generics-default-stability.rs @@ -69,30 +69,30 @@ fn main() { let _ = STRUCT4; let _: Struct4 = Struct4 { field: 1 }; - //~^ use of deprecated struct `unstable_generic_param::Struct4`: test [deprecated] - //~^^ use of deprecated struct `unstable_generic_param::Struct4`: test [deprecated] - //~^^^ use of deprecated field `unstable_generic_param::Struct4::field`: test [deprecated] + //~^ WARN use of deprecated struct `unstable_generic_param::Struct4`: test [deprecated] + //~^^ WARN use of deprecated struct `unstable_generic_param::Struct4`: test [deprecated] + //~^^^ WARN use of deprecated field `unstable_generic_param::Struct4::field`: test [deprecated] let _ = STRUCT4; - let _: Struct4 = STRUCT4; //~ use of deprecated struct `unstable_generic_param::Struct4`: test [deprecated] - let _: Struct4 = STRUCT4; //~ use of deprecated struct `unstable_generic_param::Struct4`: test [deprecated] + let _: Struct4 = STRUCT4; //~ WARN use of deprecated struct `unstable_generic_param::Struct4`: test [deprecated] + let _: Struct4 = STRUCT4; //~ WARN use of deprecated struct `unstable_generic_param::Struct4`: test [deprecated] let _: Struct4 = Struct4 { field: 0 }; - //~^ use of deprecated struct `unstable_generic_param::Struct4`: test [deprecated] - //~^^ use of deprecated struct `unstable_generic_param::Struct4`: test [deprecated] - //~^^^ use of deprecated field `unstable_generic_param::Struct4::field`: test [deprecated] + //~^ WARN use of deprecated struct `unstable_generic_param::Struct4`: test [deprecated] + //~^^ WARN use of deprecated struct `unstable_generic_param::Struct4`: test [deprecated] + //~^^^ WARN use of deprecated field `unstable_generic_param::Struct4::field`: test [deprecated] let _ = STRUCT5; let _: Struct5 = Struct5 { field: 1 }; //~ ERROR use of unstable library feature `unstable_default` - //~^ use of deprecated struct `unstable_generic_param::Struct5`: test [deprecated] - //~^^ use of deprecated struct `unstable_generic_param::Struct5`: test [deprecated] - //~^^^ use of deprecated field `unstable_generic_param::Struct5::field`: test [deprecated] + //~^ WARN use of deprecated struct `unstable_generic_param::Struct5`: test [deprecated] + //~^^ WARN use of deprecated struct `unstable_generic_param::Struct5`: test [deprecated] + //~^^^ WARN use of deprecated field `unstable_generic_param::Struct5::field`: test [deprecated] let _ = STRUCT5; - let _: Struct5 = STRUCT5; //~ use of deprecated struct `unstable_generic_param::Struct5`: test [deprecated] + let _: Struct5 = STRUCT5; //~ WARN use of deprecated struct `unstable_generic_param::Struct5`: test [deprecated] let _: Struct5 = STRUCT5; //~ ERROR use of unstable library feature `unstable_default` - //~^ use of deprecated struct `unstable_generic_param::Struct5`: test [deprecated] + //~^ WARN use of deprecated struct `unstable_generic_param::Struct5`: test [deprecated] let _: Struct5 = Struct5 { field: 0 }; //~ ERROR use of unstable library feature `unstable_default` - //~^ use of deprecated struct `unstable_generic_param::Struct5`: test [deprecated] - //~^^ use of deprecated struct `unstable_generic_param::Struct5`: test [deprecated] - //~^^^ use of deprecated field `unstable_generic_param::Struct5::field`: test [deprecated] + //~^ WARN use of deprecated struct `unstable_generic_param::Struct5`: test [deprecated] + //~^^ WARN use of deprecated struct `unstable_generic_param::Struct5`: test [deprecated] + //~^^^ WARN use of deprecated field `unstable_generic_param::Struct5::field`: test [deprecated] let _: Struct6 = Struct6 { field: 1 }; // ok let _: Struct6 = Struct6 { field: 0 }; // ok @@ -145,26 +145,26 @@ fn main() { let _ = ALIAS4; let _: Alias4 = Alias4::Some(1); - //~^ use of deprecated type alias `unstable_generic_param::Alias4`: test [deprecated] - //~^^ use of deprecated type alias `unstable_generic_param::Alias4`: test [deprecated] + //~^ WARN use of deprecated type alias `unstable_generic_param::Alias4`: test [deprecated] + //~^^ WARN use of deprecated type alias `unstable_generic_param::Alias4`: test [deprecated] let _ = ALIAS4; - let _: Alias4 = ALIAS4; //~ use of deprecated type alias `unstable_generic_param::Alias4`: test [deprecated] - let _: Alias4 = ALIAS4; //~ use of deprecated type alias `unstable_generic_param::Alias4`: test [deprecated] + let _: Alias4 = ALIAS4; //~ WARN use of deprecated type alias `unstable_generic_param::Alias4`: test [deprecated] + let _: Alias4 = ALIAS4; //~ WARN use of deprecated type alias `unstable_generic_param::Alias4`: test [deprecated] let _: Alias4 = Alias4::Some(0); - //~^ use of deprecated type alias `unstable_generic_param::Alias4`: test [deprecated] - //~^^ use of deprecated type alias `unstable_generic_param::Alias4`: test [deprecated] + //~^ WARN use of deprecated type alias `unstable_generic_param::Alias4`: test [deprecated] + //~^^ WARN use of deprecated type alias `unstable_generic_param::Alias4`: test [deprecated] let _ = ALIAS5; let _: Alias5 = Alias5::Some(1); //~ ERROR use of unstable library feature `unstable_default` - //~^ use of deprecated type alias `unstable_generic_param::Alias5`: test [deprecated] - //~^^ use of deprecated type alias `unstable_generic_param::Alias5`: test [deprecated] + //~^ WARN use of deprecated type alias `unstable_generic_param::Alias5`: test [deprecated] + //~^^ WARN use of deprecated type alias `unstable_generic_param::Alias5`: test [deprecated] let _ = ALIAS5; - let _: Alias5 = ALIAS5; //~ use of deprecated type alias `unstable_generic_param::Alias5`: test [deprecated] + let _: Alias5 = ALIAS5; //~ WARN use of deprecated type alias `unstable_generic_param::Alias5`: test [deprecated] let _: Alias5 = ALIAS5; //~ ERROR use of unstable library feature `unstable_default` - //~^ use of deprecated type alias `unstable_generic_param::Alias5`: test [deprecated] + //~^ WARN use of deprecated type alias `unstable_generic_param::Alias5`: test [deprecated] let _: Alias5 = Alias5::Some(0); //~ ERROR use of unstable library feature `unstable_default` - //~^ use of deprecated type alias `unstable_generic_param::Alias5`: test [deprecated] - //~^^ use of deprecated type alias `unstable_generic_param::Alias5`: test [deprecated] + //~^ WARN use of deprecated type alias `unstable_generic_param::Alias5`: test [deprecated] + //~^^ WARN use of deprecated type alias `unstable_generic_param::Alias5`: test [deprecated] let _: Alias6 = Alias6::Some(1); // ok let _: Alias6 = Alias6::Some(0); // ok @@ -217,26 +217,26 @@ fn main() { let _ = ENUM4; let _: Enum4 = Enum4::Some(1); - //~^ use of deprecated tuple variant `unstable_generic_param::Enum4::Some`: test [deprecated] - //~^^ use of deprecated enum `unstable_generic_param::Enum4`: test [deprecated] + //~^ WARN use of deprecated tuple variant `unstable_generic_param::Enum4::Some`: test [deprecated] + //~^^ WARN use of deprecated enum `unstable_generic_param::Enum4`: test [deprecated] let _ = ENUM4; - let _: Enum4 = ENUM4; //~ use of deprecated enum `unstable_generic_param::Enum4`: test [deprecated] - let _: Enum4 = ENUM4; //~ use of deprecated enum `unstable_generic_param::Enum4`: test [deprecated] + let _: Enum4 = ENUM4; //~ WARN use of deprecated enum `unstable_generic_param::Enum4`: test [deprecated] + let _: Enum4 = ENUM4; //~ WARN use of deprecated enum `unstable_generic_param::Enum4`: test [deprecated] let _: Enum4 = Enum4::Some(0); - //~^ use of deprecated tuple variant `unstable_generic_param::Enum4::Some`: test [deprecated] - //~^^ use of deprecated enum `unstable_generic_param::Enum4`: test [deprecated] + //~^ WARN use of deprecated tuple variant `unstable_generic_param::Enum4::Some`: test [deprecated] + //~^^ WARN use of deprecated enum `unstable_generic_param::Enum4`: test [deprecated] let _ = ENUM5; let _: Enum5 = Enum5::Some(1); //~ ERROR use of unstable library feature `unstable_default` - //~^ use of deprecated tuple variant `unstable_generic_param::Enum5::Some`: test [deprecated] - //~^^ use of deprecated enum `unstable_generic_param::Enum5`: test [deprecated] + //~^ WARN use of deprecated tuple variant `unstable_generic_param::Enum5::Some`: test [deprecated] + //~^^ WARN use of deprecated enum `unstable_generic_param::Enum5`: test [deprecated] let _ = ENUM5; - let _: Enum5 = ENUM5; //~ use of deprecated enum `unstable_generic_param::Enum5`: test [deprecated] + let _: Enum5 = ENUM5; //~ WARN use of deprecated enum `unstable_generic_param::Enum5`: test [deprecated] let _: Enum5 = ENUM5; //~ ERROR use of unstable library feature `unstable_default` - //~^ use of deprecated enum `unstable_generic_param::Enum5`: test [deprecated] + //~^ WARN use of deprecated enum `unstable_generic_param::Enum5`: test [deprecated] let _: Enum5 = Enum5::Some(0); //~ ERROR use of unstable library feature `unstable_default` - //~^ use of deprecated tuple variant `unstable_generic_param::Enum5::Some`: test [deprecated] - //~^^ use of deprecated enum `unstable_generic_param::Enum5`: test [deprecated] + //~^ WARN use of deprecated tuple variant `unstable_generic_param::Enum5::Some`: test [deprecated] + //~^^ WARN use of deprecated enum `unstable_generic_param::Enum5`: test [deprecated] let _: Enum6 = Enum6::Some(1); // ok let _: Enum6 = Enum6::Some(0); // ok diff --git a/tests/ui/static/bad-const-type.rs b/tests/ui/static/bad-const-type.rs index 24fd67ecbaac..d4e6352d7c1c 100644 --- a/tests/ui/static/bad-const-type.rs +++ b/tests/ui/static/bad-const-type.rs @@ -1,4 +1,4 @@ static i: String = 10; //~^ ERROR mismatched types -//~| expected `String`, found integer +//~| NOTE expected `String`, found integer fn main() { println!("{}", i); } diff --git a/tests/ui/structs/struct-missing-comma.fixed b/tests/ui/structs/struct-missing-comma.fixed index 800128f503bd..cd02f61f1a46 100644 --- a/tests/ui/structs/struct-missing-comma.fixed +++ b/tests/ui/structs/struct-missing-comma.fixed @@ -2,7 +2,7 @@ //@ run-rustfix pub struct S { - pub foo: u32, //~ expected `,`, or `}`, found keyword `pub` + pub foo: u32, //~ ERROR expected `,`, or `}`, found keyword `pub` // ~^ HELP try adding a comma: ',' pub bar: u32 } diff --git a/tests/ui/structs/struct-missing-comma.rs b/tests/ui/structs/struct-missing-comma.rs index b9d8c9eb3034..84944519fba9 100644 --- a/tests/ui/structs/struct-missing-comma.rs +++ b/tests/ui/structs/struct-missing-comma.rs @@ -2,7 +2,7 @@ //@ run-rustfix pub struct S { - pub foo: u32 //~ expected `,`, or `}`, found keyword `pub` + pub foo: u32 //~ ERROR expected `,`, or `}`, found keyword `pub` // ~^ HELP try adding a comma: ',' pub bar: u32 } diff --git a/tests/ui/structs/suggest-replacing-field-when-specifying-same-type.rs b/tests/ui/structs/suggest-replacing-field-when-specifying-same-type.rs index dd2fe79731ea..ab5815e23a61 100644 --- a/tests/ui/structs/suggest-replacing-field-when-specifying-same-type.rs +++ b/tests/ui/structs/suggest-replacing-field-when-specifying-same-type.rs @@ -22,7 +22,7 @@ fn main() { //~| ERROR pattern does not mention field `b` [E0027] Foo::Baz { bb: "" } => (), //~^ ERROR variant `Foo::Baz` does not have a field named `bb` [E0026] - //~| pattern does not mention field `a` [E0027] + //~| ERROR pattern does not mention field `a` [E0027] _ => (), } } diff --git a/tests/ui/suggestions/derive-trait-for-method-call.rs b/tests/ui/suggestions/derive-trait-for-method-call.rs index b5ce0078c9bc..beac24148428 100644 --- a/tests/ui/suggestions/derive-trait-for-method-call.rs +++ b/tests/ui/suggestions/derive-trait-for-method-call.rs @@ -26,19 +26,19 @@ impl Foo { fn test1() { let x = Foo(Enum::First, CloneEnum::First); let y = x.test(); - //~^the method `test` exists for struct `Foo`, but its trait bounds were not satisfied [E0599] + //~^ ERROR the method `test` exists for struct `Foo`, but its trait bounds were not satisfied [E0599] } fn test2() { let x = Foo(Struct{}, CloneStruct{}); let y = x.test(); - //~^the method `test` exists for struct `Foo`, but its trait bounds were not satisfied [E0599] + //~^ ERROR the method `test` exists for struct `Foo`, but its trait bounds were not satisfied [E0599] } fn test3() { let x = Foo(Vec::::new(), Instant::now()); let y = x.test(); - //~^the method `test` exists for struct `Foo, Instant>`, but its trait bounds were not satisfied [E0599] + //~^ ERROR the method `test` exists for struct `Foo, Instant>`, but its trait bounds were not satisfied [E0599] } fn main() {} diff --git a/tests/ui/suggestions/field-has-method.rs b/tests/ui/suggestions/field-has-method.rs index 980000151e2f..d28b6ba546c4 100644 --- a/tests/ui/suggestions/field-has-method.rs +++ b/tests/ui/suggestions/field-has-method.rs @@ -17,7 +17,7 @@ struct InferOk { fn foo(i: InferOk) { let k = i.kind(); - //~^ no method named `kind` found for struct `InferOk` in the current scope + //~^ ERROR no method named `kind` found for struct `InferOk` in the current scope } fn main() {} diff --git a/tests/ui/suggestions/issue-101465.rs b/tests/ui/suggestions/issue-101465.rs index 8e42e2c22243..3ec4e8160540 100644 --- a/tests/ui/suggestions/issue-101465.rs +++ b/tests/ui/suggestions/issue-101465.rs @@ -18,7 +18,7 @@ fn foo() -> impl Tr { match true { true => B, false => C, - //~^ `match` arms have incompatible types + //~^ ERROR `match` arms have incompatible types } } diff --git a/tests/ui/suggestions/issue-81839.rs b/tests/ui/suggestions/issue-81839.rs index 3971aa9fe841..99a03c175b39 100644 --- a/tests/ui/suggestions/issue-81839.rs +++ b/tests/ui/suggestions/issue-81839.rs @@ -8,7 +8,7 @@ async fn test(ans: &str, num: i32, cx: &issue_81839::Test) -> u32 { 1 => { cx.answer_str("hi"); } - _ => cx.answer_str("hi"), //~ `match` arms have incompatible types + _ => cx.answer_str("hi"), //~ ERROR `match` arms have incompatible types } 1 diff --git a/tests/ui/suggestions/partialeq_suggest_swap.rs b/tests/ui/suggestions/partialeq_suggest_swap.rs index ee5583a5488e..090f17f2fe2f 100644 --- a/tests/ui/suggestions/partialeq_suggest_swap.rs +++ b/tests/ui/suggestions/partialeq_suggest_swap.rs @@ -7,5 +7,5 @@ impl PartialEq for T { } fn main() { - 4i32 == T(4); //~ mismatched types [E0308] + 4i32 == T(4); //~ ERROR mismatched types [E0308] } diff --git a/tests/ui/suggestions/partialeq_suggest_swap_on_e0277.rs b/tests/ui/suggestions/partialeq_suggest_swap_on_e0277.rs index 2ebbed3c740f..a54493e5922b 100644 --- a/tests/ui/suggestions/partialeq_suggest_swap_on_e0277.rs +++ b/tests/ui/suggestions/partialeq_suggest_swap_on_e0277.rs @@ -7,5 +7,5 @@ impl PartialEq for T { } fn main() { - String::from("Girls Band Cry") == T(String::from("Girls Band Cry")); //~ can't compare `String` with `T` [E0277] + String::from("Girls Band Cry") == T(String::from("Girls Band Cry")); //~ ERROR can't compare `String` with `T` [E0277] } diff --git a/tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.fixed b/tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.fixed index 3b739312942a..735c09438e2d 100644 --- a/tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.fixed +++ b/tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.fixed @@ -10,6 +10,6 @@ fn bar(bar: &usize) { } fn main() { - foo(&mut Default::default()); //~ the trait bound `&mut usize: Default` is not satisfied - bar(&Default::default()); //~ the trait bound `&usize: Default` is not satisfied + foo(&mut Default::default()); //~ ERROR the trait bound `&mut usize: Default` is not satisfied + bar(&Default::default()); //~ ERROR the trait bound `&usize: Default` is not satisfied } diff --git a/tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.rs b/tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.rs index 7fc870946b93..7364c59fd92e 100644 --- a/tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.rs +++ b/tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.rs @@ -10,6 +10,6 @@ fn bar(bar: &usize) { } fn main() { - foo(Default::default()); //~ the trait bound `&mut usize: Default` is not satisfied - bar(Default::default()); //~ the trait bound `&usize: Default` is not satisfied + foo(Default::default()); //~ ERROR the trait bound `&mut usize: Default` is not satisfied + bar(Default::default()); //~ ERROR the trait bound `&usize: Default` is not satisfied } diff --git a/tests/ui/suggestions/suggest-let-for-assignment.fixed b/tests/ui/suggestions/suggest-let-for-assignment.fixed index 80b9333827ec..6d40f74a0d81 100644 --- a/tests/ui/suggestions/suggest-let-for-assignment.fixed +++ b/tests/ui/suggestions/suggest-let-for-assignment.fixed @@ -7,10 +7,10 @@ fn main() { let x = "x"; //~ ERROR cannot find value `x` in this scope println!("x: {}", x); //~ ERROR cannot find value `x` in this scope - let some_variable = 6; //~ cannot find value `let_some_variable` in this scope + let some_variable = 6; //~ ERROR cannot find value `let_some_variable` in this scope println!("some_variable: {}", some_variable); //~ ERROR cannot find value `some_variable` in this scope - let other_variable = 6; //~ cannot find value `letother_variable` in this scope + let other_variable = 6; //~ ERROR cannot find value `letother_variable` in this scope println!("other_variable: {}", other_variable); //~ ERROR cannot find value `other_variable` in this scope if x == "x" { diff --git a/tests/ui/suggestions/suggest-let-for-assignment.rs b/tests/ui/suggestions/suggest-let-for-assignment.rs index 22560083d34c..aeb22a0ded03 100644 --- a/tests/ui/suggestions/suggest-let-for-assignment.rs +++ b/tests/ui/suggestions/suggest-let-for-assignment.rs @@ -7,10 +7,10 @@ fn main() { x = "x"; //~ ERROR cannot find value `x` in this scope println!("x: {}", x); //~ ERROR cannot find value `x` in this scope - let_some_variable = 6; //~ cannot find value `let_some_variable` in this scope + let_some_variable = 6; //~ ERROR cannot find value `let_some_variable` in this scope println!("some_variable: {}", some_variable); //~ ERROR cannot find value `some_variable` in this scope - letother_variable = 6; //~ cannot find value `letother_variable` in this scope + letother_variable = 6; //~ ERROR cannot find value `letother_variable` in this scope println!("other_variable: {}", other_variable); //~ ERROR cannot find value `other_variable` in this scope if x == "x" { diff --git a/tests/ui/suggestions/suggest-null-ptr.fixed b/tests/ui/suggestions/suggest-null-ptr.fixed index 55c90859c83e..97a628f8662b 100644 --- a/tests/ui/suggestions/suggest-null-ptr.fixed +++ b/tests/ui/suggestions/suggest-null-ptr.fixed @@ -16,16 +16,16 @@ extern "C" { fn main() { unsafe { foo(std::ptr::null()); - //~^ mismatched types [E0308] - //~| if you meant to create a null pointer, use `std::ptr::null()` + //~^ ERROR mismatched types [E0308] + //~| HELP if you meant to create a null pointer, use `std::ptr::null()` foo_mut(std::ptr::null_mut()); - //~^ mismatched types [E0308] - //~| if you meant to create a null pointer, use `std::ptr::null_mut()` + //~^ ERROR mismatched types [E0308] + //~| HELP if you meant to create a null pointer, use `std::ptr::null_mut()` usize(std::ptr::null()); - //~^ mismatched types [E0308] - //~| if you meant to create a null pointer, use `std::ptr::null()` + //~^ ERROR mismatched types [E0308] + //~| HELP if you meant to create a null pointer, use `std::ptr::null()` usize_mut(std::ptr::null_mut()); - //~^ mismatched types [E0308] - //~| if you meant to create a null pointer, use `std::ptr::null_mut()` + //~^ ERROR mismatched types [E0308] + //~| HELP if you meant to create a null pointer, use `std::ptr::null_mut()` } } diff --git a/tests/ui/suggestions/suggest-null-ptr.rs b/tests/ui/suggestions/suggest-null-ptr.rs index f4f1269d512d..46ace90c8aea 100644 --- a/tests/ui/suggestions/suggest-null-ptr.rs +++ b/tests/ui/suggestions/suggest-null-ptr.rs @@ -16,16 +16,16 @@ extern "C" { fn main() { unsafe { foo(0); - //~^ mismatched types [E0308] - //~| if you meant to create a null pointer, use `std::ptr::null()` + //~^ ERROR mismatched types [E0308] + //~| HELP if you meant to create a null pointer, use `std::ptr::null()` foo_mut(0); - //~^ mismatched types [E0308] - //~| if you meant to create a null pointer, use `std::ptr::null_mut()` + //~^ ERROR mismatched types [E0308] + //~| HELP if you meant to create a null pointer, use `std::ptr::null_mut()` usize(0); - //~^ mismatched types [E0308] - //~| if you meant to create a null pointer, use `std::ptr::null()` + //~^ ERROR mismatched types [E0308] + //~| HELP if you meant to create a null pointer, use `std::ptr::null()` usize_mut(0); - //~^ mismatched types [E0308] - //~| if you meant to create a null pointer, use `std::ptr::null_mut()` + //~^ ERROR mismatched types [E0308] + //~| HELP if you meant to create a null pointer, use `std::ptr::null_mut()` } } diff --git a/tests/ui/suggestions/types/dont-suggest-path-names.rs b/tests/ui/suggestions/types/dont-suggest-path-names.rs index d160e49cd035..dfd671bfe556 100644 --- a/tests/ui/suggestions/types/dont-suggest-path-names.rs +++ b/tests/ui/suggestions/types/dont-suggest-path-names.rs @@ -5,11 +5,11 @@ struct Select(F, I); fn select(filter: F) -> Select {} -//~^ 7:31: 7:43: mismatched types [E0308] +//~^ ERROR mismatched types [E0308] fn parser1() { let lit = select(|x| match x { - //~^ 11:23: 11:24: type annotations needed [E0282] + //~^ ERROR type annotations needed [E0282] _ => (), }); } diff --git a/tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.rs b/tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.rs index 0b1f9ab57c98..39ca19fc3a58 100644 --- a/tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.rs +++ b/tests/ui/traits/alias/issue-108132-unmet-trait-alias-bound-on-generic-impl.rs @@ -11,5 +11,5 @@ impl Foo { } fn main() { - Foo::<()>::f() //~ trait bounds were not satisfied + Foo::<()>::f() //~ ERROR trait bounds were not satisfied } diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.rs b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.rs index 1359eb6cb87a..891cc32e7b75 100644 --- a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.rs +++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.rs @@ -11,5 +11,5 @@ fn f X<'r> + ?Sized>() { fn main() { f:: X<'x, F = i32>>(); - //~^ expected a `FnOnce(&i32)` closure, found `i32` + //~^ ERROR expected a `FnOnce(&i32)` closure, found `i32` } diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-5.rs b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-5.rs index 7d733ad26b75..829a40c64e66 100644 --- a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-5.rs +++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-5.rs @@ -21,7 +21,7 @@ fn is_obj(_: &T) {} fn f(x: &dyn Obj) { is_obj(x) - //~^ type mismatch resolving `::T == i64` + //~^ ERROR type mismatch resolving `::T == i64` } fn main() {} diff --git a/tests/ui/traits/const-traits/ice-119717-constant-lifetime.rs b/tests/ui/traits/const-traits/ice-119717-constant-lifetime.rs index dc1e719bded1..e53b87274d3a 100644 --- a/tests/ui/traits/const-traits/ice-119717-constant-lifetime.rs +++ b/tests/ui/traits/const-traits/ice-119717-constant-lifetime.rs @@ -5,9 +5,9 @@ use std::ops::FromResidual; impl const FromResidual for T { //~^ ERROR const `impl` for trait `FromResidual` which is not marked with `#[const_trait]` - //~| type parameter `T` must be used as the type parameter for some local type + //~| ERROR type parameter `T` must be used as the type parameter for some local type fn from_residual(t: T) -> _ { - //~^ the placeholder `_` is not allowed + //~^ ERROR the placeholder `_` is not allowed t } } diff --git a/tests/ui/traits/const-traits/staged-api.rs b/tests/ui/traits/const-traits/staged-api.rs index 8dd7226fc298..bf09a5f78038 100644 --- a/tests/ui/traits/const-traits/staged-api.rs +++ b/tests/ui/traits/const-traits/staged-api.rs @@ -96,12 +96,12 @@ trait S {} // implied stable impl const U for u8 {} -//~^ const stability on the impl does not match the const stability on the trait +//~^ ERROR const stability on the impl does not match the const stability on the trait #[rustc_const_stable(since = "0.0.0", feature = "beef2")] impl const U for u16 {} -//~^ const stability on the impl does not match the const stability on the trait -//~| trait implementations cannot be const stable yet +//~^ ERROR const stability on the impl does not match the const stability on the trait +//~| ERROR trait implementations cannot be const stable yet #[rustc_const_unstable(feature = "beef", issue = "none")] impl const U for u32 {} @@ -111,10 +111,10 @@ impl const S for u8 {} #[rustc_const_stable(since = "0.0.0", feature = "beef2")] impl const S for u16 {} -//~^ trait implementations cannot be const stable yet +//~^ ERROR trait implementations cannot be const stable yet #[rustc_const_unstable(feature = "beef", issue = "none")] impl const S for u32 {} -//~^ const stability on the impl does not match the const stability on the trait +//~^ ERROR const stability on the impl does not match the const stability on the trait fn main() {} diff --git a/tests/ui/traits/copy-is-not-modulo-regions.rs b/tests/ui/traits/copy-is-not-modulo-regions.rs index 1e7d2d9c691a..2efbeb4889de 100644 --- a/tests/ui/traits/copy-is-not-modulo-regions.rs +++ b/tests/ui/traits/copy-is-not-modulo-regions.rs @@ -11,7 +11,7 @@ struct Bar<'lt>(Foo<'lt>); #[cfg(not_static)] impl<'any> Copy for Bar<'any> {} -//[not_static]~^ the trait `Copy` cannot be implemented for this type +//[not_static]~^ ERROR the trait `Copy` cannot be implemented for this type #[cfg(yes_static)] impl<'any> Copy for Bar<'static> {} diff --git a/tests/ui/traits/default-method/rustc_must_implement_one_of.rs b/tests/ui/traits/default-method/rustc_must_implement_one_of.rs index 5ba2f5ce3342..a77f1d5e608e 100644 --- a/tests/ui/traits/default-method/rustc_must_implement_one_of.rs +++ b/tests/ui/traits/default-method/rustc_must_implement_one_of.rs @@ -39,6 +39,6 @@ impl Equal for T2 { } impl Equal for T3 {} -//~^ not all trait items implemented, missing one of: `eq`, `neq` +//~^ ERROR not all trait items implemented, missing one of: `eq`, `neq` fn main() {} diff --git a/tests/ui/traits/default-method/rustc_must_implement_one_of_duplicates.rs b/tests/ui/traits/default-method/rustc_must_implement_one_of_duplicates.rs index 8db5fa615c08..1e91b0607926 100644 --- a/tests/ui/traits/default-method/rustc_must_implement_one_of_duplicates.rs +++ b/tests/ui/traits/default-method/rustc_must_implement_one_of_duplicates.rs @@ -1,15 +1,15 @@ #![feature(rustc_attrs)] #[rustc_must_implement_one_of(a, a)] -//~^ functions names are duplicated +//~^ ERROR functions names are duplicated trait Trait { fn a() {} } #[rustc_must_implement_one_of(b, a, a, c, b, c)] -//~^ functions names are duplicated -//~| functions names are duplicated -//~| functions names are duplicated +//~^ ERROR functions names are duplicated +//~| ERROR functions names are duplicated +//~| ERROR functions names are duplicated trait Trait1 { fn a() {} fn b() {} diff --git a/tests/ui/traits/default-method/rustc_must_implement_one_of_gated.rs b/tests/ui/traits/default-method/rustc_must_implement_one_of_gated.rs index ec2995872de0..27e70556b7af 100644 --- a/tests/ui/traits/default-method/rustc_must_implement_one_of_gated.rs +++ b/tests/ui/traits/default-method/rustc_must_implement_one_of_gated.rs @@ -1,5 +1,5 @@ #[rustc_must_implement_one_of(eq, neq)] -//~^ the `#[rustc_must_implement_one_of]` attribute is used to change minimal complete definition of a trait, it's currently in experimental form and should be changed before being exposed outside of the std +//~^ ERROR the `#[rustc_must_implement_one_of]` attribute is used to change minimal complete definition of a trait, it's currently in experimental form and should be changed before being exposed outside of the std trait Equal { fn eq(&self, other: &Self) -> bool { !self.neq(other) diff --git a/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.rs b/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.rs index b1b91966c8d8..9b2e489c5425 100644 --- a/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.rs +++ b/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.rs @@ -1,46 +1,46 @@ #![feature(rustc_attrs)] #[rustc_must_implement_one_of(a, b)] -//~^ function not found in this trait -//~| function not found in this trait +//~^ ERROR function not found in this trait +//~| ERROR function not found in this trait trait Tr0 {} #[rustc_must_implement_one_of(a, b)] -//~^ function not found in this trait +//~^ ERROR function not found in this trait trait Tr1 { fn a() {} } #[rustc_must_implement_one_of(a)] -//~^ the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args +//~^ ERROR the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args trait Tr2 { fn a() {} } #[rustc_must_implement_one_of] -//~^ malformed `rustc_must_implement_one_of` attribute input +//~^ ERROR malformed `rustc_must_implement_one_of` attribute input trait Tr3 {} #[rustc_must_implement_one_of(A, B)] trait Tr4 { - const A: u8 = 1; //~ not a function + const A: u8 = 1; //~ ERROR not a function - type B; //~ not a function + type B; //~ ERROR not a function } #[rustc_must_implement_one_of(a, b)] trait Tr5 { - fn a(); //~ function doesn't have a default implementation + fn a(); //~ ERROR function doesn't have a default implementation - fn b(); //~ function doesn't have a default implementation + fn b(); //~ ERROR function doesn't have a default implementation } #[rustc_must_implement_one_of(abc, xyz)] -//~^ attribute should be applied to a trait +//~^ ERROR attribute should be applied to a trait fn function() {} #[rustc_must_implement_one_of(abc, xyz)] -//~^ attribute should be applied to a trait +//~^ ERROR attribute should be applied to a trait struct Struct {} fn main() {} diff --git a/tests/ui/traits/default_auto_traits/maybe-bounds-in-traits.rs b/tests/ui/traits/default_auto_traits/maybe-bounds-in-traits.rs index 761f22d1be5e..4cb38bc8e795 100644 --- a/tests/ui/traits/default_auto_traits/maybe-bounds-in-traits.rs +++ b/tests/ui/traits/default_auto_traits/maybe-bounds-in-traits.rs @@ -97,7 +97,7 @@ mod methods { fn mut_leak_foo(&mut self) {} // there is no relax bound on corresponding Receiver impl fn mut_maybe_leak_foo(&mut self) where Self: ?Leak {} - //~^ `&mut Self` cannot be used as the type of `self` without the `arbitrary_self_types` + //~^ ERROR `&mut Self` cannot be used as the type of `self` without the `arbitrary_self_types` } impl Trait for NonLeakS {} diff --git a/tests/ui/traits/issue-106072.rs b/tests/ui/traits/issue-106072.rs index d75c26642c60..d45668312218 100644 --- a/tests/ui/traits/issue-106072.rs +++ b/tests/ui/traits/issue-106072.rs @@ -1,6 +1,6 @@ #[derive(Clone)] -//~^ expected a type, found a trait -//~| expected a type, found a trait +//~^ ERROR expected a type, found a trait +//~| ERROR expected a type, found a trait struct Foo; -trait Foo {} //~ the name `Foo` is defined multiple times +trait Foo {} //~ ERROR the name `Foo` is defined multiple times fn main() {} diff --git a/tests/ui/traits/next-solver/builtin-fn-must-return-sized.rs b/tests/ui/traits/next-solver/builtin-fn-must-return-sized.rs index f8926b24e3fa..fbe801aedcd8 100644 --- a/tests/ui/traits/next-solver/builtin-fn-must-return-sized.rs +++ b/tests/ui/traits/next-solver/builtin-fn-must-return-sized.rs @@ -13,5 +13,5 @@ fn foo, T: Tuple>(f: Option, t: T) { fn main() { foo:: str, _>(None, ()); - //~^ the size for values of type `str` cannot be known at compilation time + //~^ ERROR the size for values of type `str` cannot be known at compilation time } diff --git a/tests/ui/traits/next-solver/diagnostics/point-at-failing-nested.rs b/tests/ui/traits/next-solver/diagnostics/point-at-failing-nested.rs index 840a4eb648c5..6da08619b47a 100644 --- a/tests/ui/traits/next-solver/diagnostics/point-at-failing-nested.rs +++ b/tests/ui/traits/next-solver/diagnostics/point-at-failing-nested.rs @@ -20,5 +20,5 @@ impl Constrain for () { fn needs_foo() {} fn main() { needs_foo::<()>(); - //~^ the trait bound `(): Foo` is not satisfied + //~^ ERROR the trait bound `(): Foo` is not satisfied } diff --git a/tests/ui/traits/next-solver/gat-wf.rs b/tests/ui/traits/next-solver/gat-wf.rs index ff6e2665ef3e..cd4b96b3a583 100644 --- a/tests/ui/traits/next-solver/gat-wf.rs +++ b/tests/ui/traits/next-solver/gat-wf.rs @@ -10,7 +10,7 @@ trait Foo { } impl Foo for &() { - type T<'a> = (); //~ the type `&()` does not fulfill the required lifetime + type T<'a> = (); //~ ERROR the type `&()` does not fulfill the required lifetime } fn main() {} diff --git a/tests/ui/traits/non_lifetime_binders/type-alias-impl-trait/non-lifetime-binder-in-constraint.rs b/tests/ui/traits/non_lifetime_binders/type-alias-impl-trait/non-lifetime-binder-in-constraint.rs index 2a3017885255..aff81207a930 100644 --- a/tests/ui/traits/non_lifetime_binders/type-alias-impl-trait/non-lifetime-binder-in-constraint.rs +++ b/tests/ui/traits/non_lifetime_binders/type-alias-impl-trait/non-lifetime-binder-in-constraint.rs @@ -6,7 +6,7 @@ trait Trait {} fn produce() -> impl for Trait<(), Assoc = impl Trait> { //~^ ERROR associated type `Assoc` not found for `Trait` //~| ERROR associated type `Assoc` not found for `Trait` - //~| the trait bound `{integer}: Trait<()>` is not satisfied + //~| ERROR the trait bound `{integer}: Trait<()>` is not satisfied //~| ERROR cannot capture late-bound type parameter in nested `impl Trait` 16 } diff --git a/tests/ui/traits/object/vs-lifetime.rs b/tests/ui/traits/object/vs-lifetime.rs index d3e6c0b217c9..52385b263843 100644 --- a/tests/ui/traits/object/vs-lifetime.rs +++ b/tests/ui/traits/object/vs-lifetime.rs @@ -7,7 +7,7 @@ fn main() { // `'static` is a lifetime argument, `'static +` is a type argument let _: S<'static, u8>; let _: S<'static, dyn 'static +>; - //~^ at least one trait is required for an object type + //~^ ERROR at least one trait is required for an object type let _: S<'static, 'static>; //~^ ERROR struct takes 1 lifetime argument but 2 lifetime arguments were supplied //~| ERROR struct takes 1 generic argument but 0 generic arguments were supplied diff --git a/tests/ui/transmutability/issue-101739-1.rs b/tests/ui/transmutability/issue-101739-1.rs index 4fde120e2be8..b801e2355404 100644 --- a/tests/ui/transmutability/issue-101739-1.rs +++ b/tests/ui/transmutability/issue-101739-1.rs @@ -6,7 +6,7 @@ mod assert { pub fn is_transmutable() where Dst: TransmuteFrom, //~ ERROR cannot find type `Dst` in this scope - //~| the constant `ASSUME_ALIGNMENT` is not of type `Assume` + //~| ERROR the constant `ASSUME_ALIGNMENT` is not of type `Assume` { } } diff --git a/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.rs b/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.rs index b8828c59d355..e004f2cf4feb 100644 --- a/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.rs +++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.rs @@ -15,5 +15,5 @@ mod assert { fn should_gracefully_handle_unknown_dst() { struct Src; - assert::is_transmutable::(); //~ cannot find type + assert::is_transmutable::(); //~ ERROR cannot find type } diff --git a/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst_field.rs b/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst_field.rs index 2285d2f532ee..081d1bf11ec0 100644 --- a/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst_field.rs +++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst_field.rs @@ -15,12 +15,12 @@ mod assert { fn should_gracefully_handle_unknown_dst_field() { #[repr(C)] struct Src; - #[repr(C)] struct Dst(Missing); //~ cannot find type + #[repr(C)] struct Dst(Missing); //~ ERROR cannot find type assert::is_transmutable::(); //~ ERROR cannot be safely transmuted } fn should_gracefully_handle_unknown_dst_ref_field() { #[repr(C)] struct Src(&'static Src); - #[repr(C)] struct Dst(&'static Missing); //~ cannot find type + #[repr(C)] struct Dst(&'static Missing); //~ ERROR cannot find type assert::is_transmutable::(); //~ ERROR cannot be safely transmuted } diff --git a/tests/ui/transmutability/malformed-program-gracefulness/unknown_src.rs b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src.rs index 10ba7a61b872..0aca4acd0a32 100644 --- a/tests/ui/transmutability/malformed-program-gracefulness/unknown_src.rs +++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src.rs @@ -15,5 +15,5 @@ mod assert { fn should_gracefully_handle_unknown_src() { #[repr(C)] struct Dst; - assert::is_transmutable::(); //~ cannot find type + assert::is_transmutable::(); //~ ERROR cannot find type } diff --git a/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.rs b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.rs index 598e04971e28..ee09651d7410 100644 --- a/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.rs +++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.rs @@ -14,13 +14,13 @@ mod assert { } fn should_gracefully_handle_unknown_src_field() { - #[repr(C)] struct Src(Missing); //~ cannot find type + #[repr(C)] struct Src(Missing); //~ ERROR cannot find type #[repr(C)] struct Dst(); assert::is_transmutable::(); //~ ERROR cannot be safely transmuted } fn should_gracefully_handle_unknown_src_ref_field() { - #[repr(C)] struct Src(&'static Missing); //~ cannot find type + #[repr(C)] struct Src(&'static Missing); //~ ERROR cannot find type #[repr(C)] struct Dst(&'static Dst); assert::is_transmutable::(); //~ ERROR cannot be safely transmuted } diff --git a/tests/ui/type-alias-impl-trait/auto-trait-leakage2.rs b/tests/ui/type-alias-impl-trait/auto-trait-leakage2.rs index 6132eef0db5f..0b60640272b5 100644 --- a/tests/ui/type-alias-impl-trait/auto-trait-leakage2.rs +++ b/tests/ui/type-alias-impl-trait/auto-trait-leakage2.rs @@ -4,8 +4,8 @@ use std::rc::Rc; type Foo = impl std::fmt::Debug; //~ NOTE appears within the type -//~^ within this `Foo` -//~| expansion of desugaring +//~^ NOTE within this `Foo` +//~| NOTE expansion of desugaring #[define_opaque(Foo)] pub fn foo() -> Foo { @@ -13,8 +13,8 @@ pub fn foo() -> Foo { } fn is_send(_: T) {} -//~^ required by this bound -//~| required by a bound +//~^ NOTE required by this bound +//~| NOTE required by a bound fn main() { is_send(foo()); diff --git a/tests/ui/type-alias-impl-trait/constrain_in_projection.rs b/tests/ui/type-alias-impl-trait/constrain_in_projection.rs index 64b9c583ca2e..62a105611b08 100644 --- a/tests/ui/type-alias-impl-trait/constrain_in_projection.rs +++ b/tests/ui/type-alias-impl-trait/constrain_in_projection.rs @@ -23,8 +23,8 @@ impl Trait<()> for Foo { #[define_opaque(Bar)] fn bop() { let x = >::Assoc::default(); - //[current]~^ `Foo: Trait` is not satisfied - //[current]~| `Foo: Trait` is not satisfied + //[current]~^ ERROR `Foo: Trait` is not satisfied + //[current]~| ERROR `Foo: Trait` is not satisfied } fn main() {} diff --git a/tests/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.rs b/tests/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.rs index 5bda5f0fceaa..2c538853e7ba 100644 --- a/tests/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.rs +++ b/tests/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.rs @@ -9,5 +9,5 @@ mod boo { fn bomp() -> boo::Boo { "" - //~^ mismatched types + //~^ ERROR mismatched types } diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs index d01cc7ff04eb..febe1df81ae8 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs @@ -13,6 +13,6 @@ fn two(t: T, _: U) -> Two { #[define_opaque(Two)] fn three(_: T, u: U) -> Two { - //~^ concrete type differs + //~^ ERROR concrete type differs (u, 4u32) } diff --git a/tests/ui/type-alias-impl-trait/issue-104817.rs b/tests/ui/type-alias-impl-trait/issue-104817.rs index 13bbfa12a67a..01935407e2bb 100644 --- a/tests/ui/type-alias-impl-trait/issue-104817.rs +++ b/tests/ui/type-alias-impl-trait/issue-104817.rs @@ -15,6 +15,6 @@ fn mk_opaque() -> OpaqueType { trait AnotherTrait {} impl AnotherTrait for T {} impl AnotherTrait for OpaqueType {} -//[stock]~^ conflicting implementations of trait `AnotherTrait` +//[stock]~^ ERROR conflicting implementations of trait `AnotherTrait` fn main() {} diff --git a/tests/ui/type-alias-impl-trait/not_well_formed.rs b/tests/ui/type-alias-impl-trait/not_well_formed.rs index bd4477dbf0f3..f8f7f8a20e9b 100644 --- a/tests/ui/type-alias-impl-trait/not_well_formed.rs +++ b/tests/ui/type-alias-impl-trait/not_well_formed.rs @@ -9,8 +9,8 @@ trait TraitWithAssoc { } type Foo = impl Trait; -//~^ associated type `Assoc` not found for `V` -//~| associated type `Assoc` not found for `V` +//~^ ERROR associated type `Assoc` not found for `V` +//~| ERROR associated type `Assoc` not found for `V` trait Trait {} diff --git a/tests/ui/type-alias-impl-trait/structural-match-no-leak.rs b/tests/ui/type-alias-impl-trait/structural-match-no-leak.rs index a20ae814908b..37cb2322175e 100644 --- a/tests/ui/type-alias-impl-trait/structural-match-no-leak.rs +++ b/tests/ui/type-alias-impl-trait/structural-match-no-leak.rs @@ -14,7 +14,7 @@ const LEAK_FREE: Bar = leak_free(); fn leak_free_test() { match LEAK_FREE { LEAK_FREE => (), - //~^ `Bar` cannot be used in patterns + //~^ ERROR `Bar` cannot be used in patterns _ => (), } } diff --git a/tests/ui/type-alias-impl-trait/structural-match.rs b/tests/ui/type-alias-impl-trait/structural-match.rs index 68a95560a465..e922ffb74a54 100644 --- a/tests/ui/type-alias-impl-trait/structural-match.rs +++ b/tests/ui/type-alias-impl-trait/structural-match.rs @@ -15,7 +15,7 @@ const VALUE: Foo = value(); fn test() { match VALUE { VALUE => (), - //~^ `Foo` cannot be used in patterns + //~^ ERROR `Foo` cannot be used in patterns _ => (), } } diff --git a/tests/ui/type-alias-impl-trait/variance.rs b/tests/ui/type-alias-impl-trait/variance.rs index ecd7158223c8..d9140695dae2 100644 --- a/tests/ui/type-alias-impl-trait/variance.rs +++ b/tests/ui/type-alias-impl-trait/variance.rs @@ -5,17 +5,17 @@ trait Captures<'a> {} impl Captures<'_> for T {} -type NotCapturedEarly<'a> = impl Sized; //~ ['a: *, 'a: o] +type NotCapturedEarly<'a> = impl Sized; //~ ERROR ['a: *, 'a: o] //~^ ERROR: unconstrained opaque type -type CapturedEarly<'a> = impl Sized + Captures<'a>; //~ ['a: *, 'a: o] +type CapturedEarly<'a> = impl Sized + Captures<'a>; //~ ERROR ['a: *, 'a: o] //~^ ERROR: unconstrained opaque type -type NotCapturedLate<'a> = dyn for<'b> Iterator; //~ ['a: *, 'a: o, 'b: o] +type NotCapturedLate<'a> = dyn for<'b> Iterator; //~ ERROR ['a: *, 'a: o, 'b: o] //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from `dyn` type //~| ERROR: unconstrained opaque type -type Captured<'a> = dyn for<'b> Iterator>; //~ ['a: *, 'a: o, 'b: o] +type Captured<'a> = dyn for<'b> Iterator>; //~ ERROR ['a: *, 'a: o, 'b: o] //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from `dyn` type //~| ERROR: unconstrained opaque type @@ -31,24 +31,24 @@ trait Foo<'i> { } impl<'i> Foo<'i> for &'i () { - type ImplicitCapture<'a> = impl Sized; //~ ['i: *, 'a: *, 'i: o, 'a: o] + type ImplicitCapture<'a> = impl Sized; //~ ERROR ['i: *, 'a: *, 'i: o, 'a: o] //~^ ERROR: unconstrained opaque type - type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; //~ ['i: *, 'a: *, 'i: o, 'a: o] + type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; //~ ERROR ['i: *, 'a: *, 'i: o, 'a: o] //~^ ERROR: unconstrained opaque type - type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; //~ ['i: *, 'a: *, 'i: o, 'a: o] + type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; //~ ERROR ['i: *, 'a: *, 'i: o, 'a: o] //~^ ERROR: unconstrained opaque type } impl<'i> Foo<'i> for () { - type ImplicitCapture<'a> = impl Sized; //~ ['i: *, 'a: *, 'i: o, 'a: o] + type ImplicitCapture<'a> = impl Sized; //~ ERROR ['i: *, 'a: *, 'i: o, 'a: o] //~^ ERROR: unconstrained opaque type - type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; //~ ['i: *, 'a: *, 'i: o, 'a: o] + type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; //~ ERROR ['i: *, 'a: *, 'i: o, 'a: o] //~^ ERROR: unconstrained opaque type - type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; //~ ['i: *, 'a: *, 'i: o, 'a: o] + type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; //~ ERROR ['i: *, 'a: *, 'i: o, 'a: o] //~^ ERROR: unconstrained opaque type } @@ -59,15 +59,15 @@ impl<'a> Nesting<'a> for &'a () { type Output = &'a (); } type NestedDeeply<'a> = - impl Nesting< //~ ['a: *, 'a: o] + impl Nesting< //~ ERROR ['a: *, 'a: o] 'a, - Output = impl Nesting< //~ ['a: *, 'a: o] + Output = impl Nesting< //~ ERROR ['a: *, 'a: o] 'a, - Output = impl Nesting< //~ ['a: *, 'a: o] + Output = impl Nesting< //~ ERROR ['a: *, 'a: o] 'a, - Output = impl Nesting< //~ ['a: *, 'a: o] + Output = impl Nesting< //~ ERROR ['a: *, 'a: o] 'a, - Output = impl Nesting<'a> //~ ['a: *, 'a: o] + Output = impl Nesting<'a> //~ ERROR ['a: *, 'a: o] > >, >, diff --git a/tests/ui/type/issue-103271.rs b/tests/ui/type/issue-103271.rs index 7cd76286a929..98cfaaf5cff7 100644 --- a/tests/ui/type/issue-103271.rs +++ b/tests/ui/type/issue-103271.rs @@ -1,15 +1,15 @@ fn main() { let iter_fun = <&[u32]>::iter; //~^ ERROR no function or associated item named `iter` found for reference `&[u32]` in the current scope [E0599] - //~| function or associated item not found in `&[u32]` + //~| NOTE function or associated item not found in `&[u32]` //~| HELP the function `iter` is implemented on `[u32]` for item in iter_fun(&[1,1]) { let x: &u32 = item; assert_eq!(x, &1); } let iter_fun2 = <(&[u32])>::iter; - //~^ no function or associated item named `iter` found for reference `&[u32]` in the current scope [E0599] - //~| function or associated item not found in `&[u32]` + //~^ ERROR no function or associated item named `iter` found for reference `&[u32]` in the current scope [E0599] + //~| NOTE function or associated item not found in `&[u32]` //~| HELP the function `iter` is implemented on `[u32]` for item2 in iter_fun2(&[1,1]) { let x: &u32 = item2; diff --git a/tests/ui/type/pattern_types/feature-gate-pattern_types.rs b/tests/ui/type/pattern_types/feature-gate-pattern_types.rs index b4f4bd656f5f..a51741675bbd 100644 --- a/tests/ui/type/pattern_types/feature-gate-pattern_types.rs +++ b/tests/ui/type/pattern_types/feature-gate-pattern_types.rs @@ -3,13 +3,13 @@ use std::pat::pattern_type; type NonNullU32 = pattern_type!(u32 is 1..); -//~^ use of unstable library feature `pattern_type_macro` +//~^ ERROR use of unstable library feature `pattern_type_macro` type Percent = pattern_type!(u32 is 0..=100); -//~^ use of unstable library feature `pattern_type_macro` +//~^ ERROR use of unstable library feature `pattern_type_macro` type Negative = pattern_type!(i32 is ..=0); -//~^ use of unstable library feature `pattern_type_macro` +//~^ ERROR use of unstable library feature `pattern_type_macro` type Positive = pattern_type!(i32 is 0..); -//~^ use of unstable library feature `pattern_type_macro` +//~^ ERROR use of unstable library feature `pattern_type_macro` type Always = pattern_type!(Option is Some(_)); -//~^ use of unstable library feature `pattern_type_macro` +//~^ ERROR use of unstable library feature `pattern_type_macro` //~| ERROR pattern not supported in pattern types diff --git a/tests/ui/type/pattern_types/literals.rs b/tests/ui/type/pattern_types/literals.rs index 7fd630dab3ad..b2a83a2a8bdc 100644 --- a/tests/ui/type/pattern_types/literals.rs +++ b/tests/ui/type/pattern_types/literals.rs @@ -7,7 +7,7 @@ use std::pat::pattern_type; fn out_of_range() -> pattern_type!(u32 is 1..) { 0 - //~^ mismatched types + //~^ ERROR mismatched types } fn at_range_start() -> pattern_type!(u32 is 1..) { @@ -34,7 +34,7 @@ fn positive_lit_in_range_of_signed() -> pattern_type!(i8 is -5..5) { fn negative_lit_at_range_start() -> pattern_type!(i8 is -5..5) { -5 - //~^ mismatched types + //~^ ERROR mismatched types } fn positive_lit_at_range_end() -> pattern_type!(i8 is -5..5) { @@ -43,22 +43,22 @@ fn positive_lit_at_range_end() -> pattern_type!(i8 is -5..5) { fn lit_one_beyond_range_end() -> pattern_type!(i8 is -5..5) { 5 - //~^ mismatched types + //~^ ERROR mismatched types } fn wrong_lit_kind() -> pattern_type!(u32 is 1..) { '3' - //~^ mismatched types + //~^ ERROR mismatched types } fn char_lit_in_range() -> pattern_type!(char is 'a'..'z') { 'b' - //~^ mismatched types + //~^ ERROR mismatched types } fn char_lit_out_of_range() -> pattern_type!(char is 'a'..'z') { 'A' - //~^ mismatched types + //~^ ERROR mismatched types } fn lit_at_unsigned_range_inclusive_end() -> pattern_type!(u32 is 0..=1) { @@ -71,12 +71,12 @@ fn single_element_range() -> pattern_type!(u32 is 0..=0) { fn lit_oob_single_element_range() -> pattern_type!(u32 is 0..=0) { 1 - //~^ mismatched types + //~^ ERROR mismatched types } fn lit_oob_single_element_range_exclusive() -> pattern_type!(u32 is 0..1) { 1 - //~^ mismatched types + //~^ ERROR mismatched types } fn single_element_range_exclusive() -> pattern_type!(u32 is 0..1) { @@ -84,53 +84,53 @@ fn single_element_range_exclusive() -> pattern_type!(u32 is 0..1) { } fn empty_range_at_base_type_min() -> pattern_type!(u32 is 0..0) { - //~^ evaluation of constant value failed + //~^ ERROR evaluation of constant value failed 0 } fn empty_range_at_base_type_min2() -> pattern_type!(u32 is 0..0) { - //~^ evaluation of constant value failed + //~^ ERROR evaluation of constant value failed 1 } fn empty_range() -> pattern_type!(u32 is 1..1) { 0 - //~^ mismatched types + //~^ ERROR mismatched types } fn empty_range2() -> pattern_type!(u32 is 1..1) { 1 - //~^ mismatched types + //~^ ERROR mismatched types } fn wraparound_range_at_base_ty_end() -> pattern_type!(u32 is 1..0) { - //~^ evaluation of constant value failed + //~^ ERROR evaluation of constant value failed 1 } fn wraparound_range_at_base_ty_end2() -> pattern_type!(u32 is 1..0) { - //~^ evaluation of constant value failed + //~^ ERROR evaluation of constant value failed 0 } fn wraparound_range_at_base_ty_end3() -> pattern_type!(u32 is 1..0) { - //~^ evaluation of constant value failed + //~^ ERROR evaluation of constant value failed 2 } fn wraparound_range() -> pattern_type!(u32 is 2..1) { 1 - //~^ mismatched types + //~^ ERROR mismatched types } fn lit_in_wraparound_range() -> pattern_type!(u32 is 2..1) { 0 - //~^ mismatched types + //~^ ERROR mismatched types } fn lit_at_wraparound_range_start() -> pattern_type!(u32 is 2..1) { 2 - //~^ mismatched types + //~^ ERROR mismatched types } fn main() {} diff --git a/tests/ui/typeck/attempted-access-non-fatal.rs b/tests/ui/typeck/attempted-access-non-fatal.rs index 15deb9e2f609..ba391cfa486d 100644 --- a/tests/ui/typeck/attempted-access-non-fatal.rs +++ b/tests/ui/typeck/attempted-access-non-fatal.rs @@ -1,10 +1,10 @@ // Check that bogus field access is non-fatal fn main() { let x = 0; - let _ = x.foo; //~ `{integer}` is a primitive type and therefore doesn't have fields [E0610] - let _ = x.bar; //~ `{integer}` is a primitive type and therefore doesn't have fields [E0610] - let _ = 0.f; //~ `{integer}` is a primitive type and therefore doesn't have fields [E0610] - let _ = 2.l; //~ `{integer}` is a primitive type and therefore doesn't have fields [E0610] - let _ = 12.F; //~ `{integer}` is a primitive type and therefore doesn't have fields [E0610] - let _ = 34.L; //~ `{integer}` is a primitive type and therefore doesn't have fields [E0610] + let _ = x.foo; //~ ERROR `{integer}` is a primitive type and therefore doesn't have fields [E0610] + let _ = x.bar; //~ ERROR `{integer}` is a primitive type and therefore doesn't have fields [E0610] + let _ = 0.f; //~ ERROR `{integer}` is a primitive type and therefore doesn't have fields [E0610] + let _ = 2.l; //~ ERROR `{integer}` is a primitive type and therefore doesn't have fields [E0610] + let _ = 12.F; //~ ERROR `{integer}` is a primitive type and therefore doesn't have fields [E0610] + let _ = 34.L; //~ ERROR `{integer}` is a primitive type and therefore doesn't have fields [E0610] } diff --git a/tests/ui/typeck/autoderef-with-param-env-error.rs b/tests/ui/typeck/autoderef-with-param-env-error.rs index ec96c61c63e3..d68f2d492ffe 100644 --- a/tests/ui/typeck/autoderef-with-param-env-error.rs +++ b/tests/ui/typeck/autoderef-with-param-env-error.rs @@ -1,7 +1,7 @@ fn foo() where T: Send, - //~^ cannot find type `T` in this scope + //~^ ERROR cannot find type `T` in this scope { let s = "abc".to_string(); } diff --git a/tests/ui/typeck/issue-46112.rs b/tests/ui/typeck/issue-46112.rs index cc8029771d6d..a3fe03b17c10 100644 --- a/tests/ui/typeck/issue-46112.rs +++ b/tests/ui/typeck/issue-46112.rs @@ -6,4 +6,4 @@ extern crate xcrate_issue_46112_rexport_core; fn test(r: Result, &'static str>) { } fn main() { test(Ok(())); } -//~^ mismatched types +//~^ ERROR mismatched types diff --git a/tests/ui/typeck/issue-79040.rs b/tests/ui/typeck/issue-79040.rs index f8e38e7867d5..fe8dc4534618 100644 --- a/tests/ui/typeck/issue-79040.rs +++ b/tests/ui/typeck/issue-79040.rs @@ -1,6 +1,6 @@ fn main() { const FOO = "hello" + 1; //~^ ERROR cannot add `{integer}` to `&str` - //~| missing type for `const` item + //~| ERROR missing type for `const` item println!("{}", FOO); } diff --git a/tests/ui/typeck/issue-83693.rs b/tests/ui/typeck/issue-83693.rs index 02a0bb30d7ce..68a1416517a7 100644 --- a/tests/ui/typeck/issue-83693.rs +++ b/tests/ui/typeck/issue-83693.rs @@ -8,7 +8,7 @@ impl F { fn call() { ::call //~^ ERROR: cannot find type `TestResult` in this scope [E0412] - //~| associated item constraints are not allowed here [E0229] + //~| ERROR associated item constraints are not allowed here [E0229] } } diff --git a/tests/ui/typeck/no-type-for-node-ice.rs b/tests/ui/typeck/no-type-for-node-ice.rs index d0cfdbf504de..ed56272e63cc 100644 --- a/tests/ui/typeck/no-type-for-node-ice.rs +++ b/tests/ui/typeck/no-type-for-node-ice.rs @@ -1,5 +1,5 @@ // Related issues: #20401, #20506, #20614, #20752, #20829, #20846, #20885, #20886 fn main() { - "".homura[""]; //~ no field `homura` on type `&'static str` + "".homura[""]; //~ ERROR no field `homura` on type `&'static str` } diff --git a/tests/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.rs b/tests/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.rs index 6765da42132b..c57e665724b4 100644 --- a/tests/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.rs +++ b/tests/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.rs @@ -15,6 +15,6 @@ fn doit(val: T, f: &F) pub fn main() { doit(0, &|x, y| { x.set(y); - //~^ lifetime may not live long enough + //~^ ERROR lifetime may not live long enough }); } diff --git a/tests/ui/uninhabited/uninhabited-irrefutable.rs b/tests/ui/uninhabited/uninhabited-irrefutable.rs index cbaa98960033..3f7414e596bf 100644 --- a/tests/ui/uninhabited/uninhabited-irrefutable.rs +++ b/tests/ui/uninhabited/uninhabited-irrefutable.rs @@ -29,7 +29,7 @@ fn main() { let x: Foo = Foo::D(123, 456); let Foo::D(_y, _z) = x; //~^ ERROR refutable pattern in local binding - //~| `Foo::A(_)` not covered + //~| NOTE `Foo::A(_)` not covered //~| NOTE `let` bindings require an "irrefutable pattern" //~| NOTE for more information //~| NOTE pattern `Foo::A(_)` is currently uninhabited diff --git a/tests/ui/unsafe-binders/lifetime-resolution.rs b/tests/ui/unsafe-binders/lifetime-resolution.rs index b352acfadf28..d24315401194 100644 --- a/tests/ui/unsafe-binders/lifetime-resolution.rs +++ b/tests/ui/unsafe-binders/lifetime-resolution.rs @@ -9,7 +9,7 @@ fn foo<'a>() { fn inner<'b>() { let outer: unsafe<> &'a &'b (); - //~^ can't use generic parameters from outer item + //~^ ERROR can't use generic parameters from outer item } } diff --git a/tests/ui/unsafe/unsafe-unstable-const-fn.rs b/tests/ui/unsafe/unsafe-unstable-const-fn.rs index 5398721484a0..dd1fd8463773 100644 --- a/tests/ui/unsafe/unsafe-unstable-const-fn.rs +++ b/tests/ui/unsafe/unsafe-unstable-const-fn.rs @@ -5,7 +5,7 @@ #[rustc_const_unstable(feature = "const_foo", issue = "none")] const fn unstable(a: *const i32, b: i32) -> bool { *a == b - //~^ dereference of raw pointer is unsafe + //~^ ERROR dereference of raw pointer is unsafe } fn main() {} diff --git a/tests/ui/unsized-locals/issue-30276-feature-flagged.rs b/tests/ui/unsized-locals/issue-30276-feature-flagged.rs index 635d34f82291..8b5b321ec498 100644 --- a/tests/ui/unsized-locals/issue-30276-feature-flagged.rs +++ b/tests/ui/unsized-locals/issue-30276-feature-flagged.rs @@ -5,4 +5,5 @@ struct Test([i32]); fn main() { let _x: fn(_) -> Test = Test; -} //~^the size for values of type `[i32]` cannot be known at compilation time + //~^ ERROR the size for values of type `[i32]` cannot be known at compilation time +} diff --git a/tests/ui/unsized-locals/issue-30276.rs b/tests/ui/unsized-locals/issue-30276.rs index 9c4bf062a40e..6b67ebbec1c0 100644 --- a/tests/ui/unsized-locals/issue-30276.rs +++ b/tests/ui/unsized-locals/issue-30276.rs @@ -2,4 +2,5 @@ struct Test([i32]); fn main() { let _x: fn(_) -> Test = Test; -} //~^the size for values of type `[i32]` cannot be known at compilation time + //~^ ERROR the size for values of type `[i32]` cannot be known at compilation time +} diff --git a/tests/ui/use/use-keyword.rs b/tests/ui/use/use-keyword.rs index 840cddcb907c..95f303651676 100644 --- a/tests/ui/use/use-keyword.rs +++ b/tests/ui/use/use-keyword.rs @@ -7,10 +7,10 @@ mod a { //~^ ERROR `self` imports are only allowed within a { } list use super as B; //~^ ERROR unresolved import `super` [E0432] - //~| no `super` in the root + //~| NOTE no `super` in the root use super::{self as C}; //~^ ERROR unresolved import `super` [E0432] - //~| no `super` in the root + //~| NOTE no `super` in the root } } diff --git a/tests/ui/use/use-mod/use-mod-2.rs b/tests/ui/use/use-mod/use-mod-2.rs index 9373a62ba36e..57ff135c4d85 100644 --- a/tests/ui/use/use-mod/use-mod-2.rs +++ b/tests/ui/use/use-mod/use-mod-2.rs @@ -1,11 +1,11 @@ mod foo { use self::{self}; //~^ ERROR unresolved import `self` [E0432] - //~| no `self` in the root + //~| NOTE no `self` in the root use super::{self}; //~^ ERROR unresolved import `super` [E0432] - //~| no `super` in the root + //~| NOTE no `super` in the root } fn main() {} diff --git a/tests/ui/variance/variance-btree-invariant-types.rs b/tests/ui/variance/variance-btree-invariant-types.rs index 09c93d0013cc..9e457c7fae80 100644 --- a/tests/ui/variance/variance-btree-invariant-types.rs +++ b/tests/ui/variance/variance-btree-invariant-types.rs @@ -2,78 +2,78 @@ use std::collections::btree_map::{IterMut, OccupiedEntry, RangeMut, VacantEntry} fn iter_cov_key<'a, 'new>(v: IterMut<'a, &'static (), ()>) -> IterMut<'a, &'new (), ()> { v - //~^ lifetime may not live long enough + //~^ ERROR lifetime may not live long enough } fn iter_cov_val<'a, 'new>(v: IterMut<'a, (), &'static ()>) -> IterMut<'a, (), &'new ()> { v - //~^ lifetime may not live long enough + //~^ ERROR lifetime may not live long enough } fn iter_contra_key<'a, 'new>(v: IterMut<'a, &'new (), ()>) -> IterMut<'a, &'static (), ()> { v - //~^ lifetime may not live long enough + //~^ ERROR lifetime may not live long enough } fn iter_contra_val<'a, 'new>(v: IterMut<'a, (), &'new ()>) -> IterMut<'a, (), &'static ()> { v - //~^ lifetime may not live long enough + //~^ ERROR lifetime may not live long enough } fn range_cov_key<'a, 'new>(v: RangeMut<'a, &'static (), ()>) -> RangeMut<'a, &'new (), ()> { v - //~^ lifetime may not live long enough + //~^ ERROR lifetime may not live long enough } fn range_cov_val<'a, 'new>(v: RangeMut<'a, (), &'static ()>) -> RangeMut<'a, (), &'new ()> { v - //~^ lifetime may not live long enough + //~^ ERROR lifetime may not live long enough } fn range_contra_key<'a, 'new>(v: RangeMut<'a, &'new (), ()>) -> RangeMut<'a, &'static (), ()> { v - //~^ lifetime may not live long enough + //~^ ERROR lifetime may not live long enough } fn range_contra_val<'a, 'new>(v: RangeMut<'a, (), &'new ()>) -> RangeMut<'a, (), &'static ()> { v - //~^ lifetime may not live long enough + //~^ ERROR lifetime may not live long enough } fn occ_cov_key<'a, 'new>(v: OccupiedEntry<'a, &'static (), ()>) -> OccupiedEntry<'a, &'new (), ()> { v - //~^ lifetime may not live long enough + //~^ ERROR lifetime may not live long enough } fn occ_cov_val<'a, 'new>(v: OccupiedEntry<'a, (), &'static ()>) -> OccupiedEntry<'a, (), &'new ()> { v - //~^ lifetime may not live long enough + //~^ ERROR lifetime may not live long enough } fn occ_contra_key<'a, 'new>(v: OccupiedEntry<'a, &'new (), ()>) -> OccupiedEntry<'a, &'static (), ()> { v - //~^ lifetime may not live long enough + //~^ ERROR lifetime may not live long enough } fn occ_contra_val<'a, 'new>(v: OccupiedEntry<'a, (), &'new ()>) -> OccupiedEntry<'a, (), &'static ()> { v - //~^ lifetime may not live long enough + //~^ ERROR lifetime may not live long enough } fn vac_cov_key<'a, 'new>(v: VacantEntry<'a, &'static (), ()>) -> VacantEntry<'a, &'new (), ()> { v - //~^ lifetime may not live long enough + //~^ ERROR lifetime may not live long enough } fn vac_cov_val<'a, 'new>(v: VacantEntry<'a, (), &'static ()>) -> VacantEntry<'a, (), &'new ()> { v - //~^ lifetime may not live long enough + //~^ ERROR lifetime may not live long enough } fn vac_contra_key<'a, 'new>(v: VacantEntry<'a, &'new (), ()>) -> VacantEntry<'a, &'static (), ()> { v - //~^ lifetime may not live long enough + //~^ ERROR lifetime may not live long enough } fn vac_contra_val<'a, 'new>(v: VacantEntry<'a, (), &'new ()>) -> VacantEntry<'a, (), &'static ()> { v - //~^ lifetime may not live long enough + //~^ ERROR lifetime may not live long enough } diff --git a/tests/ui/wf/issue-95665.rs b/tests/ui/wf/issue-95665.rs index 67923cbb2d6b..422ffd11ee3f 100644 --- a/tests/ui/wf/issue-95665.rs +++ b/tests/ui/wf/issue-95665.rs @@ -12,7 +12,7 @@ pub struct Struct { extern "C" { static VAR: Struct; - //~^ 14:17: 14:27: the trait bound `u8: Trait` is not satisfied [E0277] + //~^ ERROR the trait bound `u8: Trait` is not satisfied [E0277] } fn main() {} diff --git a/tests/ui/wf/wf-normalization-sized.rs b/tests/ui/wf/wf-normalization-sized.rs index 80b2c8803ff1..5396cc8b32a8 100644 --- a/tests/ui/wf/wf-normalization-sized.rs +++ b/tests/ui/wf/wf-normalization-sized.rs @@ -17,10 +17,10 @@ impl WellUnformed for T { } const _: <[[[[[[u8]]]]]] as WellUnformed>::RequestNormalize = (); -//[next]~^ the size for values of type `[[[[[u8]]]]]` cannot be known at compilation time -//[next]~| the size for values of type `[[[[[u8]]]]]` cannot be known at compilation time +//[next]~^ ERROR the size for values of type `[[[[[u8]]]]]` cannot be known at compilation time +//[next]~| ERROR the size for values of type `[[[[[u8]]]]]` cannot be known at compilation time const _: as WellUnformed>::RequestNormalize = (); -//[next]~^ the size for values of type `str` cannot be known at compilation time -//[next]~| the size for values of type `str` cannot be known at compilation time +//[next]~^ ERROR the size for values of type `str` cannot be known at compilation time +//[next]~| ERROR the size for values of type `str` cannot be known at compilation time fn main() {} From a0d9c8726678fdc6a43d51e388e1a92e388d5fc2 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 6 Apr 2025 14:34:47 +0200 Subject: [PATCH 233/606] Inline `calc_default_binding_mode` --- compiler/rustc_hir_typeck/src/pat.rs | 158 +++++++++++---------------- 1 file changed, 66 insertions(+), 92 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 8641348bffbb..e6e262279cd9 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -163,9 +163,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { enum AdjustMode { /// Peel off all immediate reference types. Peel, - /// Reset binding mode to the initial mode. - /// Used for destructuring assignment, where we don't want any match ergonomics. - Reset, /// Pass on the input binding mode and expected type. Pass, } @@ -322,6 +319,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { #[instrument(level = "debug", skip(self, pat_info))] fn check_pat(&self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo<'tcx>) { let PatInfo { binding_mode, max_ref_mutbl, top_info: ti, current_depth, .. } = pat_info; + #[cfg(debug_assertions)] + if binding_mode == ByRef::Yes(Mutability::Mut) + && max_ref_mutbl != MutblCap::Mut + && self.downgrade_mut_inside_shared() + { + span_bug!(pat.span, "Pattern mutability cap violated!"); + } let path_res = match pat.kind { PatKind::Expr(PatExpr { kind: PatExprKind::Path(qpath), hir_id, span }) => { @@ -330,8 +334,65 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => None, }; let adjust_mode = self.calc_adjust_mode(pat, path_res.map(|(res, ..)| res)); - let (expected, binding_mode, max_ref_mutbl) = - self.calc_default_binding_mode(pat, expected, binding_mode, adjust_mode, max_ref_mutbl); + let (expected, binding_mode, max_ref_mutbl) = match adjust_mode { + // When we perform destructuring assignment, we disable default match bindings, which + // are unintuitive in this context. + _ if !pat.default_binding_modes => (expected, ByRef::No, MutblCap::Mut), + AdjustMode::Pass => (expected, binding_mode, max_ref_mutbl), + // Peel off as many immediately nested `& mut?` from the expected type as possible + // and return the new expected type and binding default binding mode. + // The adjustments vector, if non-empty is stored in a table. + AdjustMode::Peel => { + let mut binding_mode = binding_mode; + let mut max_ref_mutbl = max_ref_mutbl; + let mut expected = self.try_structurally_resolve_type(pat.span, expected); + // Peel off as many `&` or `&mut` from the scrutinee type as possible. For example, + // for `match &&&mut Some(5)` the loop runs three times, aborting when it reaches + // the `Some(5)` which is not of type Ref. + // + // For each ampersand peeled off, update the binding mode and push the original + // type into the adjustments vector. + // + // See the examples in `ui/match-defbm*.rs`. + let mut pat_adjustments = vec![]; + while let ty::Ref(_, inner_ty, inner_mutability) = *expected.kind() { + debug!("inspecting {:?}", expected); + + debug!("current discriminant is Ref, inserting implicit deref"); + // Preserve the reference type. We'll need it later during THIR lowering. + pat_adjustments.push(expected); + + expected = self.try_structurally_resolve_type(pat.span, inner_ty); + binding_mode = ByRef::Yes(match binding_mode { + // If default binding mode is by value, make it `ref` or `ref mut` + // (depending on whether we observe `&` or `&mut`). + ByRef::No | + // When `ref mut`, stay a `ref mut` (on `&mut`) or downgrade to `ref` (on `&`). + ByRef::Yes(Mutability::Mut) => inner_mutability, + // Once a `ref`, always a `ref`. + // This is because a `& &mut` cannot mutate the underlying value. + ByRef::Yes(Mutability::Not) => Mutability::Not, + }); + } + + if self.downgrade_mut_inside_shared() { + binding_mode = binding_mode.cap_ref_mutability(max_ref_mutbl.as_mutbl()); + } + if binding_mode == ByRef::Yes(Mutability::Not) { + max_ref_mutbl = MutblCap::Not; + } + + if !pat_adjustments.is_empty() { + debug!("default binding mode is now {:?}", binding_mode); + self.typeck_results + .borrow_mut() + .pat_adjustments_mut() + .insert(pat.hir_id, pat_adjustments); + } + + (expected, binding_mode, max_ref_mutbl) + } + }; let pat_info = PatInfo { binding_mode, max_ref_mutbl, @@ -437,39 +498,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // `regions-relate-bound-regions-on-closures-to-inference-variables.rs`, } - /// Compute the new expected type and default binding mode from the old ones - /// as well as the pattern form we are currently checking. - fn calc_default_binding_mode( - &self, - pat: &'tcx Pat<'tcx>, - expected: Ty<'tcx>, - def_br: ByRef, - adjust_mode: AdjustMode, - max_ref_mutbl: MutblCap, - ) -> (Ty<'tcx>, ByRef, MutblCap) { - #[cfg(debug_assertions)] - if def_br == ByRef::Yes(Mutability::Mut) - && max_ref_mutbl != MutblCap::Mut - && self.downgrade_mut_inside_shared() - { - span_bug!(pat.span, "Pattern mutability cap violated!"); - } - match adjust_mode { - AdjustMode::Pass => (expected, def_br, max_ref_mutbl), - AdjustMode::Reset => (expected, ByRef::No, MutblCap::Mut), - AdjustMode::Peel => self.peel_off_references(pat, expected, def_br, max_ref_mutbl), - } - } - /// How should the binding mode and expected type be adjusted? /// /// When the pattern is a path pattern, `opt_path_res` must be `Some(res)`. fn calc_adjust_mode(&self, pat: &'tcx Pat<'tcx>, opt_path_res: Option) -> AdjustMode { - // When we perform destructuring assignment, we disable default match bindings, which are - // unintuitive in this context. - if !pat.default_binding_modes { - return AdjustMode::Reset; - } match &pat.kind { // Type checking these product-like types successfully always require // that the expected type be of those types and not reference types. @@ -526,64 +558,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - /// Peel off as many immediately nested `& mut?` from the expected type as possible - /// and return the new expected type and binding default binding mode. - /// The adjustments vector, if non-empty is stored in a table. - fn peel_off_references( - &self, - pat: &'tcx Pat<'tcx>, - expected: Ty<'tcx>, - mut def_br: ByRef, - mut max_ref_mutbl: MutblCap, - ) -> (Ty<'tcx>, ByRef, MutblCap) { - let mut expected = self.try_structurally_resolve_type(pat.span, expected); - // Peel off as many `&` or `&mut` from the scrutinee type as possible. For example, - // for `match &&&mut Some(5)` the loop runs three times, aborting when it reaches - // the `Some(5)` which is not of type Ref. - // - // For each ampersand peeled off, update the binding mode and push the original - // type into the adjustments vector. - // - // See the examples in `ui/match-defbm*.rs`. - let mut pat_adjustments = vec![]; - while let ty::Ref(_, inner_ty, inner_mutability) = *expected.kind() { - debug!("inspecting {:?}", expected); - - debug!("current discriminant is Ref, inserting implicit deref"); - // Preserve the reference type. We'll need it later during THIR lowering. - pat_adjustments.push(expected); - - expected = self.try_structurally_resolve_type(pat.span, inner_ty); - def_br = ByRef::Yes(match def_br { - // If default binding mode is by value, make it `ref` or `ref mut` - // (depending on whether we observe `&` or `&mut`). - ByRef::No | - // When `ref mut`, stay a `ref mut` (on `&mut`) or downgrade to `ref` (on `&`). - ByRef::Yes(Mutability::Mut) => inner_mutability, - // Once a `ref`, always a `ref`. - // This is because a `& &mut` cannot mutate the underlying value. - ByRef::Yes(Mutability::Not) => Mutability::Not, - }); - } - - if self.downgrade_mut_inside_shared() { - def_br = def_br.cap_ref_mutability(max_ref_mutbl.as_mutbl()); - } - if def_br == ByRef::Yes(Mutability::Not) { - max_ref_mutbl = MutblCap::Not; - } - - if !pat_adjustments.is_empty() { - debug!("default binding mode is now {:?}", def_br); - self.typeck_results - .borrow_mut() - .pat_adjustments_mut() - .insert(pat.hir_id, pat_adjustments); - } - - (expected, def_br, max_ref_mutbl) - } - fn check_pat_expr_unadjusted(&self, lt: &'tcx hir::PatExpr<'tcx>) -> Ty<'tcx> { let ty = match <.kind { rustc_hir::PatExprKind::Lit { lit, negated } => { From 9f57903e9cdafda3e32ce0e3472ad7fe2a9c1e3a Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 6 Apr 2025 14:38:16 +0200 Subject: [PATCH 234/606] Insert adjustments incrementally --- compiler/rustc_hir_typeck/src/pat.rs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index e6e262279cd9..70eb21ca3560 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -354,13 +354,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // type into the adjustments vector. // // See the examples in `ui/match-defbm*.rs`. - let mut pat_adjustments = vec![]; while let ty::Ref(_, inner_ty, inner_mutability) = *expected.kind() { debug!("inspecting {:?}", expected); debug!("current discriminant is Ref, inserting implicit deref"); // Preserve the reference type. We'll need it later during THIR lowering. - pat_adjustments.push(expected); + self.typeck_results + .borrow_mut() + .pat_adjustments_mut() + .entry(pat.hir_id) + .or_default() + .push(expected); expected = self.try_structurally_resolve_type(pat.span, inner_ty); binding_mode = ByRef::Yes(match binding_mode { @@ -382,13 +386,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { max_ref_mutbl = MutblCap::Not; } - if !pat_adjustments.is_empty() { - debug!("default binding mode is now {:?}", binding_mode); - self.typeck_results - .borrow_mut() - .pat_adjustments_mut() - .insert(pat.hir_id, pat_adjustments); - } + debug!("default binding mode is now {:?}", binding_mode); (expected, binding_mode, max_ref_mutbl) } From 19950b52c70a5989c4937c5a91e1184439bdad5c Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 6 Apr 2025 14:52:52 +0200 Subject: [PATCH 235/606] Turn the peeling loop into a recursive call --- compiler/rustc_hir_typeck/src/pat.rs | 80 ++++++++++++++++------------ 1 file changed, 46 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 70eb21ca3560..ca51a28c4be8 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -318,6 +318,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Conversely, inside this module, `check_pat_top` should never be used. #[instrument(level = "debug", skip(self, pat_info))] fn check_pat(&self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo<'tcx>) { + let opt_path_res = match pat.kind { + PatKind::Expr(PatExpr { kind: PatExprKind::Path(qpath), hir_id, span }) => { + Some(self.resolve_ty_and_res_fully_qualified_call(qpath, *hir_id, *span)) + } + _ => None, + }; + let adjust_mode = self.calc_adjust_mode(pat, opt_path_res.map(|(res, ..)| res)); + self.check_pat_inner(pat, opt_path_res, adjust_mode, expected, pat_info); + } + + // Helper to avoid resolving the same path pattern several times. + fn check_pat_inner( + &self, + pat: &'tcx Pat<'tcx>, + opt_path_res: Option<(Res, Option>, &'tcx [hir::PathSegment<'tcx>])>, + adjust_mode: AdjustMode, + expected: Ty<'tcx>, + pat_info: PatInfo<'tcx>, + ) { let PatInfo { binding_mode, max_ref_mutbl, top_info: ti, current_depth, .. } = pat_info; #[cfg(debug_assertions)] if binding_mode == ByRef::Yes(Mutability::Mut) @@ -327,34 +346,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span_bug!(pat.span, "Pattern mutability cap violated!"); } - let path_res = match pat.kind { - PatKind::Expr(PatExpr { kind: PatExprKind::Path(qpath), hir_id, span }) => { - Some(self.resolve_ty_and_res_fully_qualified_call(qpath, *hir_id, *span)) - } - _ => None, - }; - let adjust_mode = self.calc_adjust_mode(pat, path_res.map(|(res, ..)| res)); let (expected, binding_mode, max_ref_mutbl) = match adjust_mode { // When we perform destructuring assignment, we disable default match bindings, which // are unintuitive in this context. _ if !pat.default_binding_modes => (expected, ByRef::No, MutblCap::Mut), AdjustMode::Pass => (expected, binding_mode, max_ref_mutbl), - // Peel off as many immediately nested `& mut?` from the expected type as possible - // and return the new expected type and binding default binding mode. - // The adjustments vector, if non-empty is stored in a table. + // Peel an immediately nested `& mut?` from the expected type if possible and return the + // new expected type and binding default binding mode. AdjustMode::Peel => { - let mut binding_mode = binding_mode; - let mut max_ref_mutbl = max_ref_mutbl; - let mut expected = self.try_structurally_resolve_type(pat.span, expected); - // Peel off as many `&` or `&mut` from the scrutinee type as possible. For example, - // for `match &&&mut Some(5)` the loop runs three times, aborting when it reaches - // the `Some(5)` which is not of type Ref. + let expected = self.try_structurally_resolve_type(pat.span, expected); + // Peel off a `&` or `&mut` from the scrutinee type. For each ampersand peeled off, + // update the binding mode and push the original type into the adjustments vector. // - // For each ampersand peeled off, update the binding mode and push the original - // type into the adjustments vector. - // - // See the examples in `ui/match-defbm*.rs`. - while let ty::Ref(_, inner_ty, inner_mutability) = *expected.kind() { + // See the examples in `tests/ui/rfcs/rfc-2005-default-binding-mode`. + if let ty::Ref(_, inner_ty, inner_mutability) = *expected.kind() { debug!("inspecting {:?}", expected); debug!("current discriminant is Ref, inserting implicit deref"); @@ -366,8 +371,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .or_default() .push(expected); - expected = self.try_structurally_resolve_type(pat.span, inner_ty); - binding_mode = ByRef::Yes(match binding_mode { + let mut binding_mode = ByRef::Yes(match binding_mode { // If default binding mode is by value, make it `ref` or `ref mut` // (depending on whether we observe `&` or `&mut`). ByRef::No | @@ -377,18 +381,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // This is because a `& &mut` cannot mutate the underlying value. ByRef::Yes(Mutability::Not) => Mutability::Not, }); - } - if self.downgrade_mut_inside_shared() { - binding_mode = binding_mode.cap_ref_mutability(max_ref_mutbl.as_mutbl()); + if self.downgrade_mut_inside_shared() { + binding_mode = binding_mode.cap_ref_mutability(max_ref_mutbl.as_mutbl()); + } + let mut max_ref_mutbl = max_ref_mutbl; + if binding_mode == ByRef::Yes(Mutability::Not) { + max_ref_mutbl = MutblCap::Not; + } + debug!("default binding mode is now {:?}", binding_mode); + let pat_info = PatInfo { binding_mode, max_ref_mutbl, ..pat_info }; + return self.check_pat_inner( + pat, + opt_path_res, + adjust_mode, + inner_ty, + pat_info, + ); + } else { + (expected, binding_mode, max_ref_mutbl) } - if binding_mode == ByRef::Yes(Mutability::Not) { - max_ref_mutbl = MutblCap::Not; - } - - debug!("default binding mode is now {:?}", binding_mode); - - (expected, binding_mode, max_ref_mutbl) } }; let pat_info = PatInfo { @@ -409,7 +421,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pat.hir_id, *span, qpath, - path_res.unwrap(), + opt_path_res.unwrap(), expected, &pat_info.top_info, ); From 38adb9931cd934fefe2a2f65ca0071612c9ec583 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 6 Apr 2025 15:08:55 +0200 Subject: [PATCH 236/606] Reorganize `check_pat_inner` --- compiler/rustc_hir_typeck/src/pat.rs | 118 ++++++++++++++------------- 1 file changed, 61 insertions(+), 57 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index ca51a28c4be8..8f01bb1c297c 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -337,7 +337,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Ty<'tcx>, pat_info: PatInfo<'tcx>, ) { - let PatInfo { binding_mode, max_ref_mutbl, top_info: ti, current_depth, .. } = pat_info; + let PatInfo { mut binding_mode, mut max_ref_mutbl, current_depth, .. } = pat_info; #[cfg(debug_assertions)] if binding_mode == ByRef::Yes(Mutability::Mut) && max_ref_mutbl != MutblCap::Mut @@ -346,72 +346,76 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span_bug!(pat.span, "Pattern mutability cap violated!"); } - let (expected, binding_mode, max_ref_mutbl) = match adjust_mode { + if !pat.default_binding_modes { // When we perform destructuring assignment, we disable default match bindings, which // are unintuitive in this context. - _ if !pat.default_binding_modes => (expected, ByRef::No, MutblCap::Mut), - AdjustMode::Pass => (expected, binding_mode, max_ref_mutbl), - // Peel an immediately nested `& mut?` from the expected type if possible and return the - // new expected type and binding default binding mode. - AdjustMode::Peel => { - let expected = self.try_structurally_resolve_type(pat.span, expected); - // Peel off a `&` or `&mut` from the scrutinee type. For each ampersand peeled off, - // update the binding mode and push the original type into the adjustments vector. - // - // See the examples in `tests/ui/rfcs/rfc-2005-default-binding-mode`. - if let ty::Ref(_, inner_ty, inner_mutability) = *expected.kind() { - debug!("inspecting {:?}", expected); - - debug!("current discriminant is Ref, inserting implicit deref"); - // Preserve the reference type. We'll need it later during THIR lowering. - self.typeck_results - .borrow_mut() - .pat_adjustments_mut() - .entry(pat.hir_id) - .or_default() - .push(expected); - - let mut binding_mode = ByRef::Yes(match binding_mode { - // If default binding mode is by value, make it `ref` or `ref mut` - // (depending on whether we observe `&` or `&mut`). - ByRef::No | - // When `ref mut`, stay a `ref mut` (on `&mut`) or downgrade to `ref` (on `&`). - ByRef::Yes(Mutability::Mut) => inner_mutability, - // Once a `ref`, always a `ref`. - // This is because a `& &mut` cannot mutate the underlying value. - ByRef::Yes(Mutability::Not) => Mutability::Not, - }); - - if self.downgrade_mut_inside_shared() { - binding_mode = binding_mode.cap_ref_mutability(max_ref_mutbl.as_mutbl()); - } - let mut max_ref_mutbl = max_ref_mutbl; - if binding_mode == ByRef::Yes(Mutability::Not) { - max_ref_mutbl = MutblCap::Not; - } - debug!("default binding mode is now {:?}", binding_mode); - let pat_info = PatInfo { binding_mode, max_ref_mutbl, ..pat_info }; - return self.check_pat_inner( - pat, - opt_path_res, - adjust_mode, - inner_ty, - pat_info, - ); - } else { - (expected, binding_mode, max_ref_mutbl) - } - } + binding_mode = ByRef::No; + max_ref_mutbl = MutblCap::Mut; }; + // Resolve type if needed. + let expected = if let AdjustMode::Peel = adjust_mode + && pat.default_binding_modes + { + self.try_structurally_resolve_type(pat.span, expected) + } else { + expected + }; + let old_pat_info = pat_info; let pat_info = PatInfo { binding_mode, max_ref_mutbl, - top_info: ti, - decl_origin: pat_info.decl_origin, current_depth: current_depth + 1, + top_info: old_pat_info.top_info, + decl_origin: old_pat_info.decl_origin, }; let ty = match pat.kind { + // Peel off a `&` or `&mut` from the scrutinee type. See the examples in + // `tests/ui/rfcs/rfc-2005-default-binding-mode`. + _ if let AdjustMode::Peel = adjust_mode + && pat.default_binding_modes + && let ty::Ref(_, inner_ty, inner_mutability) = *expected.kind() => + { + debug!("inspecting {:?}", expected); + + debug!("current discriminant is Ref, inserting implicit deref"); + // Preserve the reference type. We'll need it later during THIR lowering. + self.typeck_results + .borrow_mut() + .pat_adjustments_mut() + .entry(pat.hir_id) + .or_default() + .push(expected); + + binding_mode = ByRef::Yes(match binding_mode { + // If default binding mode is by value, make it `ref` or `ref mut` + // (depending on whether we observe `&` or `&mut`). + ByRef::No | + // When `ref mut`, stay a `ref mut` (on `&mut`) or downgrade to `ref` (on `&`). + ByRef::Yes(Mutability::Mut) => inner_mutability, + // Once a `ref`, always a `ref`. + // This is because a `& &mut` cannot mutate the underlying value. + ByRef::Yes(Mutability::Not) => Mutability::Not, + }); + + if self.downgrade_mut_inside_shared() { + binding_mode = binding_mode.cap_ref_mutability(max_ref_mutbl.as_mutbl()); + } + if binding_mode == ByRef::Yes(Mutability::Not) { + max_ref_mutbl = MutblCap::Not; + } + debug!("default binding mode is now {:?}", binding_mode); + + // Use the old pat info to keep `current_depth` to its old value. + let new_pat_info = PatInfo { binding_mode, max_ref_mutbl, ..old_pat_info }; + return self.check_pat_inner( + pat, + opt_path_res, + adjust_mode, + inner_ty, + new_pat_info, + ); + } PatKind::Missing | PatKind::Wild | PatKind::Err(_) => expected, // We allow any type here; we ensure that the type is uninhabited during match checking. PatKind::Never => expected, From 6588018fb413efe0476773982355ba772671bd85 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 6 Apr 2025 15:10:47 +0200 Subject: [PATCH 237/606] Return a type from `check_pat_inner` --- compiler/rustc_hir_typeck/src/pat.rs | 104 +++++++++++++-------------- 1 file changed, 49 insertions(+), 55 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 8f01bb1c297c..c635c2c3f2d2 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -325,7 +325,50 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => None, }; let adjust_mode = self.calc_adjust_mode(pat, opt_path_res.map(|(res, ..)| res)); - self.check_pat_inner(pat, opt_path_res, adjust_mode, expected, pat_info); + let ty = self.check_pat_inner(pat, opt_path_res, adjust_mode, expected, pat_info); + self.write_ty(pat.hir_id, ty); + + // (note_1): In most of the cases where (note_1) is referenced + // (literals and constants being the exception), we relate types + // using strict equality, even though subtyping would be sufficient. + // There are a few reasons for this, some of which are fairly subtle + // and which cost me (nmatsakis) an hour or two debugging to remember, + // so I thought I'd write them down this time. + // + // 1. There is no loss of expressiveness here, though it does + // cause some inconvenience. What we are saying is that the type + // of `x` becomes *exactly* what is expected. This can cause unnecessary + // errors in some cases, such as this one: + // + // ``` + // fn foo<'x>(x: &'x i32) { + // let a = 1; + // let mut z = x; + // z = &a; + // } + // ``` + // + // The reason we might get an error is that `z` might be + // assigned a type like `&'x i32`, and then we would have + // a problem when we try to assign `&a` to `z`, because + // the lifetime of `&a` (i.e., the enclosing block) is + // shorter than `'x`. + // + // HOWEVER, this code works fine. The reason is that the + // expected type here is whatever type the user wrote, not + // the initializer's type. In this case the user wrote + // nothing, so we are going to create a type variable `Z`. + // Then we will assign the type of the initializer (`&'x i32`) + // as a subtype of `Z`: `&'x i32 <: Z`. And hence we + // will instantiate `Z` as a type `&'0 i32` where `'0` is + // a fresh region variable, with the constraint that `'x : '0`. + // So basically we're all set. + // + // Note that there are two tests to check that this remains true + // (`regions-reassign-{match,let}-bound-pointer.rs`). + // + // 2. An outdated issue related to the old HIR borrowck. See the test + // `regions-relate-bound-regions-on-closures-to-inference-variables.rs`, } // Helper to avoid resolving the same path pattern several times. @@ -336,7 +379,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { adjust_mode: AdjustMode, expected: Ty<'tcx>, pat_info: PatInfo<'tcx>, - ) { + ) -> Ty<'tcx> { let PatInfo { mut binding_mode, mut max_ref_mutbl, current_depth, .. } = pat_info; #[cfg(debug_assertions)] if binding_mode == ByRef::Yes(Mutability::Mut) @@ -369,7 +412,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { decl_origin: old_pat_info.decl_origin, }; - let ty = match pat.kind { + match pat.kind { // Peel off a `&` or `&mut` from the scrutinee type. See the examples in // `tests/ui/rfcs/rfc-2005-default-binding-mode`. _ if let AdjustMode::Peel = adjust_mode @@ -408,13 +451,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Use the old pat info to keep `current_depth` to its old value. let new_pat_info = PatInfo { binding_mode, max_ref_mutbl, ..old_pat_info }; - return self.check_pat_inner( - pat, - opt_path_res, - adjust_mode, - inner_ty, - new_pat_info, - ); + // Recurse with the new expected type. + self.check_pat_inner(pat, opt_path_res, adjust_mode, inner_ty, new_pat_info) } PatKind::Missing | PatKind::Wild | PatKind::Err(_) => expected, // We allow any type here; we ensure that the type is uninhabited during match checking. @@ -465,51 +503,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { PatKind::Slice(before, slice, after) => { self.check_pat_slice(pat.span, before, slice, after, expected, pat_info) } - }; - - self.write_ty(pat.hir_id, ty); - - // (note_1): In most of the cases where (note_1) is referenced - // (literals and constants being the exception), we relate types - // using strict equality, even though subtyping would be sufficient. - // There are a few reasons for this, some of which are fairly subtle - // and which cost me (nmatsakis) an hour or two debugging to remember, - // so I thought I'd write them down this time. - // - // 1. There is no loss of expressiveness here, though it does - // cause some inconvenience. What we are saying is that the type - // of `x` becomes *exactly* what is expected. This can cause unnecessary - // errors in some cases, such as this one: - // - // ``` - // fn foo<'x>(x: &'x i32) { - // let a = 1; - // let mut z = x; - // z = &a; - // } - // ``` - // - // The reason we might get an error is that `z` might be - // assigned a type like `&'x i32`, and then we would have - // a problem when we try to assign `&a` to `z`, because - // the lifetime of `&a` (i.e., the enclosing block) is - // shorter than `'x`. - // - // HOWEVER, this code works fine. The reason is that the - // expected type here is whatever type the user wrote, not - // the initializer's type. In this case the user wrote - // nothing, so we are going to create a type variable `Z`. - // Then we will assign the type of the initializer (`&'x i32`) - // as a subtype of `Z`: `&'x i32 <: Z`. And hence we - // will instantiate `Z` as a type `&'0 i32` where `'0` is - // a fresh region variable, with the constraint that `'x : '0`. - // So basically we're all set. - // - // Note that there are two tests to check that this remains true - // (`regions-reassign-{match,let}-bound-pointer.rs`). - // - // 2. An outdated issue related to the old HIR borrowck. See the test - // `regions-relate-bound-regions-on-closures-to-inference-variables.rs`, + } } /// How should the binding mode and expected type be adjusted? From f458151b7aa773a46dfce8c58aa41de9ed697c5e Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sun, 6 Apr 2025 15:48:07 +0200 Subject: [PATCH 238/606] Remove redundant assignment --- compiler/rustc_hir_typeck/src/pat.rs | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index c635c2c3f2d2..fbc783c05090 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -380,21 +380,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Ty<'tcx>, pat_info: PatInfo<'tcx>, ) -> Ty<'tcx> { - let PatInfo { mut binding_mode, mut max_ref_mutbl, current_depth, .. } = pat_info; #[cfg(debug_assertions)] - if binding_mode == ByRef::Yes(Mutability::Mut) - && max_ref_mutbl != MutblCap::Mut + if pat_info.binding_mode == ByRef::Yes(Mutability::Mut) + && pat_info.max_ref_mutbl != MutblCap::Mut && self.downgrade_mut_inside_shared() { span_bug!(pat.span, "Pattern mutability cap violated!"); } - if !pat.default_binding_modes { - // When we perform destructuring assignment, we disable default match bindings, which - // are unintuitive in this context. - binding_mode = ByRef::No; - max_ref_mutbl = MutblCap::Mut; - }; // Resolve type if needed. let expected = if let AdjustMode::Peel = adjust_mode && pat.default_binding_modes @@ -404,13 +397,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected }; let old_pat_info = pat_info; - let pat_info = PatInfo { - binding_mode, - max_ref_mutbl, - current_depth: current_depth + 1, - top_info: old_pat_info.top_info, - decl_origin: old_pat_info.decl_origin, - }; + let pat_info = PatInfo { current_depth: old_pat_info.current_depth + 1, ..old_pat_info }; match pat.kind { // Peel off a `&` or `&mut` from the scrutinee type. See the examples in @@ -430,7 +417,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .or_default() .push(expected); - binding_mode = ByRef::Yes(match binding_mode { + let mut binding_mode = ByRef::Yes(match pat_info.binding_mode { // If default binding mode is by value, make it `ref` or `ref mut` // (depending on whether we observe `&` or `&mut`). ByRef::No | @@ -441,6 +428,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ByRef::Yes(Mutability::Not) => Mutability::Not, }); + let mut max_ref_mutbl = pat_info.max_ref_mutbl; if self.downgrade_mut_inside_shared() { binding_mode = binding_mode.cap_ref_mutability(max_ref_mutbl.as_mutbl()); } From 6f5501583557d2d918cd42fab3f99ad153152afd Mon Sep 17 00:00:00 2001 From: Jane Losare-Lusby Date: Mon, 7 Apr 2025 14:26:14 -0700 Subject: [PATCH 239/606] fix "still mutable" ice while metrics are enabled --- .../rustc_data_structures/src/sync/freeze.rs | 2 +- compiler/rustc_driver_impl/src/lib.rs | 8 +- compiler/rustc_middle/src/query/mod.rs | 5 + .../main.rs | 16 ++++ .../rmake.rs | 94 +++++++++++++++++++ 5 files changed, 120 insertions(+), 5 deletions(-) create mode 100644 tests/run-make/unstable-feature-usage-metrics-incremental/main.rs create mode 100644 tests/run-make/unstable-feature-usage-metrics-incremental/rmake.rs diff --git a/compiler/rustc_data_structures/src/sync/freeze.rs b/compiler/rustc_data_structures/src/sync/freeze.rs index 9720b22ea7d1..6338afb92c34 100644 --- a/compiler/rustc_data_structures/src/sync/freeze.rs +++ b/compiler/rustc_data_structures/src/sync/freeze.rs @@ -88,7 +88,7 @@ impl FreezeLock { #[inline] #[track_caller] pub fn write(&self) -> FreezeWriteGuard<'_, T> { - self.try_write().expect("still mutable") + self.try_write().expect("data should not be frozen if we're still attempting to mutate it") } #[inline] diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 595ac1edd289..bbc18c371ea0 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -348,10 +348,6 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send)) // Make sure name resolution and macro expansion is run. let _ = tcx.resolver_for_lowering(); - if let Some(metrics_dir) = &sess.opts.unstable_opts.metrics_dir { - dump_feature_usage_metrics(tcx, metrics_dir); - } - if callbacks.after_expansion(compiler, tcx) == Compilation::Stop { return early_exit(); } @@ -370,6 +366,10 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send)) tcx.ensure_ok().analysis(()); + if let Some(metrics_dir) = &sess.opts.unstable_opts.metrics_dir { + dump_feature_usage_metrics(tcx, metrics_dir); + } + if callbacks.after_analysis(compiler, tcx) == Compilation::Stop { return early_exit(); } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 0d5fba3cc69b..dfd877c0b860 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1894,6 +1894,11 @@ rustc_queries! { // The macro which defines `rustc_metadata::provide_extern` depends on this query's name. // Changing the name should cause a compiler error, but in case that changes, be aware. + // + // The hash should not be calculated before the `analysis` pass is complete, specifically + // until `tcx.untracked().definitions.freeze()` has been called, otherwise if incremental + // compilation is enabled calculating this hash can freeze this structure too early in + // compilation and cause subsequent crashes when attempting to write to `definitions` query crate_hash(_: CrateNum) -> Svh { eval_always desc { "looking up the hash a crate" } diff --git a/tests/run-make/unstable-feature-usage-metrics-incremental/main.rs b/tests/run-make/unstable-feature-usage-metrics-incremental/main.rs new file mode 100644 index 000000000000..f970d395b2cf --- /dev/null +++ b/tests/run-make/unstable-feature-usage-metrics-incremental/main.rs @@ -0,0 +1,16 @@ +#![feature(ascii_char)] // random lib feature +#![feature(box_patterns)] // random lang feature + +// picked arbitrary unstable features, just need a random lib and lang feature, ideally ones that +// won't be stabilized any time soon so we don't have to update this test +fn main() { + for s in quix("foo/bar") { + print!("{s}"); + } + println!(); +} + +// need a latebound var to trigger the incremental compilation ICE +fn quix(foo: &str) -> impl Iterator + '_ { + foo.split('/') +} diff --git a/tests/run-make/unstable-feature-usage-metrics-incremental/rmake.rs b/tests/run-make/unstable-feature-usage-metrics-incremental/rmake.rs new file mode 100644 index 000000000000..7e070d80c793 --- /dev/null +++ b/tests/run-make/unstable-feature-usage-metrics-incremental/rmake.rs @@ -0,0 +1,94 @@ +//! This test checks if unstable feature usage metric dump files `unstable-feature-usage*.json` work +//! as expected. +//! +//! - Basic sanity checks on a default ICE dump. +//! +//! See . +//! +//! # Test history +//! +//! - forked from dump-ice-to-disk test, which has flakeyness issues on i686-mingw, I'm assuming +//! those will be present in this test as well on the same platform + +//@ ignore-windows +//FIXME(#128911): still flakey on i686-mingw. + +use std::path::{Path, PathBuf}; + +use run_make_support::rfs::create_dir_all; +use run_make_support::{ + cwd, filename_contains, has_extension, rfs, run_in_tmpdir, rustc, serde_json, + shallow_find_files, +}; + +fn find_feature_usage_metrics>(dir: P) -> Vec { + shallow_find_files(dir, |path| { + if filename_contains(path, "unstable_feature_usage") && has_extension(path, "json") { + true + } else { + dbg!(path); + false + } + }) +} + +fn main() { + test_metrics_dump(); + test_metrics_errors(); +} + +#[track_caller] +fn test_metrics_dump() { + run_in_tmpdir(|| { + let metrics_dir = cwd().join("metrics"); + create_dir_all(&metrics_dir); + rustc() + .input("main.rs") + .incremental("incremental") + .env("RUST_BACKTRACE", "short") + .arg(format!("-Zmetrics-dir={}", metrics_dir.display())) + .run(); + let mut metrics = find_feature_usage_metrics(&metrics_dir); + let json_path = + metrics.pop().expect("there should be one metrics file in the output directory"); + + // After the `pop` above, there should be no files left. + assert!( + metrics.is_empty(), + "there should be no more than one metrics file in the output directory" + ); + + let message = rfs::read_to_string(json_path); + let mut parsed: serde_json::Value = + serde_json::from_str(&message).expect("metrics should be dumped as json"); + // remove timestamps + assert!(parsed["lib_features"][0]["timestamp"].is_number()); + assert!(parsed["lang_features"][0]["timestamp"].is_number()); + parsed["lib_features"][0]["timestamp"] = serde_json::json!(null); + parsed["lang_features"][0]["timestamp"] = serde_json::json!(null); + let expected = serde_json::json!( + { + "lib_features":[{"symbol":"ascii_char", "timestamp":null}], + "lang_features":[{"symbol":"box_patterns","since":null, "timestamp":null}] + } + ); + + assert_eq!(expected, parsed); + }); +} + +#[track_caller] +fn test_metrics_errors() { + run_in_tmpdir(|| { + rustc() + .input("main.rs") + .incremental("incremental") + .env("RUST_BACKTRACE", "short") + .arg("-Zmetrics-dir=invaliddirectorythatdefinitelydoesntexist") + .run_fail() + .assert_stderr_contains( + "error: cannot dump feature usage metrics: No such file or directory", + ) + .assert_stdout_not_contains("internal compiler error"); + }); +} From 12311ef8ac93028f55fae69cb2e3caabab93ad49 Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Tue, 8 Apr 2025 16:21:52 -0700 Subject: [PATCH 240/606] fix title of offset_of_enum feature --- src/doc/unstable-book/src/language-features/offset-of-enum.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/unstable-book/src/language-features/offset-of-enum.md b/src/doc/unstable-book/src/language-features/offset-of-enum.md index 1960d6299eb0..78c0d87f639e 100644 --- a/src/doc/unstable-book/src/language-features/offset-of-enum.md +++ b/src/doc/unstable-book/src/language-features/offset-of-enum.md @@ -1,4 +1,4 @@ -# `offset_of_slice` +# `offset_of_enum` The tracking issue for this feature is: [#120141] From 616406d2f186c47ede89b5d54eadc0ac5eae289e Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Tue, 8 Apr 2025 17:20:59 +0800 Subject: [PATCH 241/606] triagebot: roll compiler reviewers for rustc/unstable book --- triagebot.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/triagebot.toml b/triagebot.toml index 756536dc2e7b..8a7797bd1ffe 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1338,9 +1338,11 @@ compiletest = [ "/src/doc/nomicon" = ["@ehuss"] "/src/doc/reference" = ["@ehuss"] "/src/doc/rust-by-example" = ["@ehuss"] +"/src/doc/rustc" = ["compiler", "@ehuss"] "/src/doc/rustc-dev-guide" = ["compiler"] "/src/doc/rustdoc" = ["rustdoc"] "/src/doc/style-guide" = ["style-team"] +"/src/doc/unstable-book" = ["compiler"] "/src/etc" = ["@Mark-Simulacrum"] "/src/librustdoc" = ["rustdoc"] "/src/llvm-project" = ["@cuviper"] From edfc74722556c659de6fa03b23af3b9c8ceb8ac2 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Mon, 24 Mar 2025 18:57:07 +0000 Subject: [PATCH 242/606] Avoid verbatim paths in Command::current_dir If possible, we should try not to use verbatim paths in Command::current_dir. It might work but it might also break code (including some Windows APIs) that assume the current directory isn't verbatim. --- library/std/src/sys/path/windows.rs | 43 +++++++++++++++++++++++ library/std/src/sys/path/windows/tests.rs | 12 +++++++ library/std/src/sys/process/windows.rs | 32 ++++++++++++++--- 3 files changed, 83 insertions(+), 4 deletions(-) diff --git a/library/std/src/sys/path/windows.rs b/library/std/src/sys/path/windows.rs index 1c5347219169..6547ed9aa5f3 100644 --- a/library/std/src/sys/path/windows.rs +++ b/library/std/src/sys/path/windows.rs @@ -350,3 +350,46 @@ pub(crate) fn absolute(path: &Path) -> io::Result { pub(crate) fn is_absolute(path: &Path) -> bool { path.has_root() && path.prefix().is_some() } + +/// Test that the path is absolute, fully qualified and unchanged when processed by the Windows API. +/// +/// For example: +/// +/// - `C:\path\to\file` will return true. +/// - `C:\path\to\nul` returns false because the Windows API will convert it to \\.\NUL +/// - `C:\path\to\..\file` returns false because it will be resolved to `C:\path\file`. +/// +/// This is a useful property because it means the path can be converted from and to and verbatim +/// path just by changing the prefix. +pub(crate) fn is_absolute_exact(path: &[u16]) -> bool { + // This is implemented by checking that passing the path through + // GetFullPathNameW does not change the path in any way. + + // Windows paths are limited to i16::MAX length + // though the API here accepts a u32 for the length. + if path.is_empty() || path.len() > u32::MAX as usize || path.last() != Some(&0) { + return false; + } + // The path returned by `GetFullPathNameW` must be the same length as the + // given path, otherwise they're not equal. + let buffer_len = path.len(); + let mut new_path = Vec::with_capacity(buffer_len); + let result = unsafe { + c::GetFullPathNameW( + path.as_ptr(), + new_path.capacity() as u32, + new_path.as_mut_ptr(), + crate::ptr::null_mut(), + ) + }; + // Note: if non-zero, the returned result is the length of the buffer without the null termination + if result == 0 || result as usize != buffer_len - 1 { + false + } else { + // SAFETY: `GetFullPathNameW` initialized `result` bytes and does not exceed `nBufferLength - 1` (capacity). + unsafe { + new_path.set_len((result as usize) + 1); + } + path == &new_path + } +} diff --git a/library/std/src/sys/path/windows/tests.rs b/library/std/src/sys/path/windows/tests.rs index f2a60e30bc61..9eb79203dcac 100644 --- a/library/std/src/sys/path/windows/tests.rs +++ b/library/std/src/sys/path/windows/tests.rs @@ -135,3 +135,15 @@ fn broken_unc_path() { assert_eq!(components.next(), Some(Component::Normal("foo".as_ref()))); assert_eq!(components.next(), Some(Component::Normal("bar".as_ref()))); } + +#[test] +fn test_is_absolute_exact() { + use crate::sys::pal::api::wide_str; + // These paths can be made verbatim by only changing their prefix. + assert!(is_absolute_exact(wide_str!(r"C:\path\to\file"))); + assert!(is_absolute_exact(wide_str!(r"\\server\share\path\to\file"))); + // These paths change more substantially + assert!(!is_absolute_exact(wide_str!(r"C:\path\to\..\file"))); + assert!(!is_absolute_exact(wide_str!(r"\\server\share\path\to\..\file"))); + assert!(!is_absolute_exact(wide_str!(r"C:\path\to\NUL"))); // Converts to \\.\NUL +} diff --git a/library/std/src/sys/process/windows.rs b/library/std/src/sys/process/windows.rs index 06c15e08f3fb..4cfdf908c58d 100644 --- a/library/std/src/sys/process/windows.rs +++ b/library/std/src/sys/process/windows.rs @@ -19,7 +19,7 @@ use crate::sys::args::{self, Arg}; use crate::sys::c::{self, EXIT_FAILURE, EXIT_SUCCESS}; use crate::sys::fs::{File, OpenOptions}; use crate::sys::handle::Handle; -use crate::sys::pal::api::{self, WinError}; +use crate::sys::pal::api::{self, WinError, utf16}; use crate::sys::pal::{ensure_no_nuls, fill_utf16_buf}; use crate::sys::pipe::{self, AnonPipe}; use crate::sys::{cvt, path, stdio}; @@ -880,9 +880,33 @@ fn make_envp(maybe_env: Option>) -> io::Result<(*mut fn make_dirp(d: Option<&OsString>) -> io::Result<(*const u16, Vec)> { match d { Some(dir) => { - let mut dir_str: Vec = ensure_no_nuls(dir)?.encode_wide().collect(); - dir_str.push(0); - Ok((dir_str.as_ptr(), dir_str)) + let mut dir_str: Vec = ensure_no_nuls(dir)?.encode_wide().chain([0]).collect(); + // Try to remove the `\\?\` prefix, if any. + // This is necessary because the current directory does not support verbatim paths. + // However. this can only be done if it doesn't change how the path will be resolved. + let ptr = if dir_str.starts_with(utf16!(r"\\?\UNC")) { + // Turn the `C` in `UNC` into a `\` so we can then use `\\rest\of\path`. + let start = r"\\?\UN".len(); + dir_str[start] = b'\\' as u16; + if path::is_absolute_exact(&dir_str[start..]) { + dir_str[start..].as_ptr() + } else { + // Revert the above change. + dir_str[start] = b'C' as u16; + dir_str.as_ptr() + } + } else if dir_str.starts_with(utf16!(r"\\?\")) { + // Strip the leading `\\?\` + let start = r"\\?\".len(); + if path::is_absolute_exact(&dir_str[start..]) { + dir_str[start..].as_ptr() + } else { + dir_str.as_ptr() + } + } else { + dir_str.as_ptr() + }; + Ok((ptr, dir_str)) } None => Ok((ptr::null(), Vec::new())), } From f151ceadfe19a4c12c1381468cc8c516f3be9f39 Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Tue, 8 Apr 2025 21:54:34 -0400 Subject: [PATCH 243/606] emit a better error message for using the macro incorrectly --- compiler/rustc_builtin_macros/src/autodiff.rs | 2 +- tests/ui/autodiff/autodiff_illegal.rs | 4 ++-- tests/ui/autodiff/autodiff_illegal.stderr | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs index 351413dea493..4161829480d3 100644 --- a/compiler/rustc_builtin_macros/src/autodiff.rs +++ b/compiler/rustc_builtin_macros/src/autodiff.rs @@ -234,7 +234,7 @@ mod llvm_enzyme { let meta_item_vec: ThinVec = match meta_item.kind { ast::MetaItemKind::List(ref vec) => vec.clone(), _ => { - dcx.emit_err(errors::AutoDiffInvalidApplication { span: item.span() }); + dcx.emit_err(errors::AutoDiffMissingConfig { span: item.span() }); return vec![item]; } }; diff --git a/tests/ui/autodiff/autodiff_illegal.rs b/tests/ui/autodiff/autodiff_illegal.rs index 2f2cd8d93532..a916bd8b857b 100644 --- a/tests/ui/autodiff/autodiff_illegal.rs +++ b/tests/ui/autodiff/autodiff_illegal.rs @@ -63,7 +63,7 @@ fn dummy() { // Malformed, where args? #[autodiff] pub fn f7(x: f64) { - //~^ ERROR autodiff must be applied to function + //~^ ERROR autodiff requires at least a name and mode unimplemented!() } @@ -77,7 +77,7 @@ pub fn f8(x: f64) { // Invalid attribute syntax #[autodiff = ""] pub fn f9(x: f64) { - //~^ ERROR autodiff must be applied to function + //~^ ERROR autodiff requires at least a name and mode unimplemented!() } diff --git a/tests/ui/autodiff/autodiff_illegal.stderr b/tests/ui/autodiff/autodiff_illegal.stderr index 3752b27e7dd1..b119f61b8ae6 100644 --- a/tests/ui/autodiff/autodiff_illegal.stderr +++ b/tests/ui/autodiff/autodiff_illegal.stderr @@ -62,7 +62,7 @@ error: autodiff must be applied to function LL | let add_one_v2 = |x: u32| -> u32 { x + 1 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: autodiff must be applied to function +error: autodiff requires at least a name and mode --> $DIR/autodiff_illegal.rs:65:1 | LL | / pub fn f7(x: f64) { @@ -80,7 +80,7 @@ LL | | unimplemented!() LL | | } | |_^ -error: autodiff must be applied to function +error: autodiff requires at least a name and mode --> $DIR/autodiff_illegal.rs:79:1 | LL | / pub fn f9(x: f64) { From 209ce5919514d40d00ec9b5e3e672f5de2e5be9c Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Sun, 1 Dec 2024 19:33:41 -0800 Subject: [PATCH 244/606] Implement trivial file operations - opening and closing handles. Just enough to get file metadata. --- src/tools/miri/Cargo.lock | 1 + src/tools/miri/Cargo.toml | 1 + src/tools/miri/src/shims/files.rs | 115 ++++- src/tools/miri/src/shims/time.rs | 36 +- src/tools/miri/src/shims/unix/fd.rs | 6 +- src/tools/miri/src/shims/unix/fs.rs | 94 +--- .../miri/src/shims/unix/linux_like/epoll.rs | 4 +- .../miri/src/shims/unix/linux_like/eventfd.rs | 2 +- .../miri/src/shims/unix/unnamed_socket.rs | 2 +- .../miri/src/shims/windows/foreign_items.rs | 32 +- src/tools/miri/src/shims/windows/fs.rs | 402 ++++++++++++++++++ src/tools/miri/src/shims/windows/handle.rs | 61 ++- src/tools/miri/src/shims/windows/mod.rs | 2 + src/tools/miri/src/shims/windows/thread.rs | 2 +- src/tools/miri/test_dependencies/Cargo.toml | 2 +- .../fail-dep/concurrency/windows_join_main.rs | 2 +- .../miri/tests/pass-dep/shims/windows-fs.rs | 198 +++++++++ src/tools/miri/tests/pass/shims/fs.rs | 36 +- 18 files changed, 838 insertions(+), 160 deletions(-) create mode 100644 src/tools/miri/src/shims/windows/fs.rs create mode 100644 src/tools/miri/tests/pass-dep/shims/windows-fs.rs diff --git a/src/tools/miri/Cargo.lock b/src/tools/miri/Cargo.lock index bb228962ecc9..0c6f4a3dd06e 100644 --- a/src/tools/miri/Cargo.lock +++ b/src/tools/miri/Cargo.lock @@ -538,6 +538,7 @@ name = "miri" version = "0.1.0" dependencies = [ "aes", + "bitflags", "chrono", "chrono-tz", "colored", diff --git a/src/tools/miri/Cargo.toml b/src/tools/miri/Cargo.toml index 5bb07648f75c..e9ee19b79326 100644 --- a/src/tools/miri/Cargo.toml +++ b/src/tools/miri/Cargo.toml @@ -26,6 +26,7 @@ measureme = "12" chrono = { version = "0.4.38", default-features = false } chrono-tz = "0.10" directories = "6" +bitflags = "2.6" # Copied from `compiler/rustc/Cargo.toml`. # But only for some targets, it fails for others. Rustc configures this in its CI, but we can't diff --git a/src/tools/miri/src/shims/files.rs b/src/tools/miri/src/shims/files.rs index 6b4f4cdc922a..42603e784bbd 100644 --- a/src/tools/miri/src/shims/files.rs +++ b/src/tools/miri/src/shims/files.rs @@ -1,6 +1,7 @@ use std::any::Any; use std::collections::BTreeMap; -use std::io::{IsTerminal, SeekFrom, Write}; +use std::fs::{File, Metadata}; +use std::io::{IsTerminal, Seek, SeekFrom, Write}; use std::marker::CoercePointee; use std::ops::Deref; use std::rc::{Rc, Weak}; @@ -192,7 +193,7 @@ pub trait FileDescription: std::fmt::Debug + FileDescriptionExt { false } - fn as_unix(&self) -> &dyn UnixFileDescription { + fn as_unix<'tcx>(&self, _ecx: &MiriInterpCx<'tcx>) -> &dyn UnixFileDescription { panic!("Not a unix file descriptor: {}", self.name()); } } @@ -278,6 +279,97 @@ impl FileDescription for io::Stderr { } } +#[derive(Debug)] +pub struct FileHandle { + pub(crate) file: File, + pub(crate) writable: bool, +} + +impl FileDescription for FileHandle { + fn name(&self) -> &'static str { + "file" + } + + fn read<'tcx>( + self: FileDescriptionRef, + communicate_allowed: bool, + ptr: Pointer, + len: usize, + ecx: &mut MiriInterpCx<'tcx>, + finish: DynMachineCallback<'tcx, Result>, + ) -> InterpResult<'tcx> { + assert!(communicate_allowed, "isolation should have prevented even opening a file"); + + let result = ecx.read_from_host(&self.file, len, ptr)?; + finish.call(ecx, result) + } + + fn write<'tcx>( + self: FileDescriptionRef, + communicate_allowed: bool, + ptr: Pointer, + len: usize, + ecx: &mut MiriInterpCx<'tcx>, + finish: DynMachineCallback<'tcx, Result>, + ) -> InterpResult<'tcx> { + assert!(communicate_allowed, "isolation should have prevented even opening a file"); + + let result = ecx.write_to_host(&self.file, len, ptr)?; + finish.call(ecx, result) + } + + fn seek<'tcx>( + &self, + communicate_allowed: bool, + offset: SeekFrom, + ) -> InterpResult<'tcx, io::Result> { + assert!(communicate_allowed, "isolation should have prevented even opening a file"); + interp_ok((&mut &self.file).seek(offset)) + } + + fn close<'tcx>( + self, + communicate_allowed: bool, + _ecx: &mut MiriInterpCx<'tcx>, + ) -> InterpResult<'tcx, io::Result<()>> { + assert!(communicate_allowed, "isolation should have prevented even opening a file"); + // We sync the file if it was opened in a mode different than read-only. + if self.writable { + // `File::sync_all` does the checks that are done when closing a file. We do this to + // to handle possible errors correctly. + let result = self.file.sync_all(); + // Now we actually close the file and return the result. + drop(self.file); + interp_ok(result) + } else { + // We drop the file, this closes it but ignores any errors + // produced when closing it. This is done because + // `File::sync_all` cannot be done over files like + // `/dev/urandom` which are read-only. Check + // https://github.com/rust-lang/miri/issues/999#issuecomment-568920439 + // for a deeper discussion. + drop(self.file); + interp_ok(Ok(())) + } + } + + fn metadata<'tcx>(&self) -> InterpResult<'tcx, io::Result> { + interp_ok(self.file.metadata()) + } + + fn is_tty(&self, communicate_allowed: bool) -> bool { + communicate_allowed && self.file.is_terminal() + } + + fn as_unix<'tcx>(&self, ecx: &MiriInterpCx<'tcx>) -> &dyn UnixFileDescription { + assert!( + ecx.target_os_is_unix(), + "unix file operations are only available for unix targets" + ); + self + } +} + /// Like /dev/null #[derive(Debug)] pub struct NullOutput; @@ -300,10 +392,13 @@ impl FileDescription for NullOutput { } } +/// Internal type of a file-descriptor - this is what [`FdTable`] expects +pub type FdNum = i32; + /// The file descriptor table #[derive(Debug)] pub struct FdTable { - pub fds: BTreeMap, + pub fds: BTreeMap, /// Unique identifier for file description, used to differentiate between various file description. next_file_description_id: FdId, } @@ -339,12 +434,12 @@ impl FdTable { } /// Insert a new file description to the FdTable. - pub fn insert_new(&mut self, fd: impl FileDescription) -> i32 { + pub fn insert_new(&mut self, fd: impl FileDescription) -> FdNum { let fd_ref = self.new_ref(fd); self.insert(fd_ref) } - pub fn insert(&mut self, fd_ref: DynFileDescriptionRef) -> i32 { + pub fn insert(&mut self, fd_ref: DynFileDescriptionRef) -> FdNum { self.insert_with_min_num(fd_ref, 0) } @@ -352,8 +447,8 @@ impl FdTable { pub fn insert_with_min_num( &mut self, file_handle: DynFileDescriptionRef, - min_fd_num: i32, - ) -> i32 { + min_fd_num: FdNum, + ) -> FdNum { // Find the lowest unused FD, starting from min_fd. If the first such unused FD is in // between used FDs, the find_map combinator will return it. If the first such unused FD // is after all other used FDs, the find_map combinator will return None, and we will use @@ -379,16 +474,16 @@ impl FdTable { new_fd_num } - pub fn get(&self, fd_num: i32) -> Option { + pub fn get(&self, fd_num: FdNum) -> Option { let fd = self.fds.get(&fd_num)?; Some(fd.clone()) } - pub fn remove(&mut self, fd_num: i32) -> Option { + pub fn remove(&mut self, fd_num: FdNum) -> Option { self.fds.remove(&fd_num) } - pub fn is_fd_num(&self, fd_num: i32) -> bool { + pub fn is_fd_num(&self, fd_num: FdNum) -> bool { self.fds.contains_key(&fd_num) } } diff --git a/src/tools/miri/src/shims/time.rs b/src/tools/miri/src/shims/time.rs index d7c445b47cb0..fb80a36af9fc 100644 --- a/src/tools/miri/src/shims/time.rs +++ b/src/tools/miri/src/shims/time.rs @@ -219,16 +219,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let filetime = this.deref_pointer_as(LPFILETIME_op, this.windows_ty_layout("FILETIME"))?; - let NANOS_PER_SEC = this.eval_windows_u64("time", "NANOS_PER_SEC"); - let INTERVALS_PER_SEC = this.eval_windows_u64("time", "INTERVALS_PER_SEC"); - let INTERVALS_TO_UNIX_EPOCH = this.eval_windows_u64("time", "INTERVALS_TO_UNIX_EPOCH"); - let NANOS_PER_INTERVAL = NANOS_PER_SEC / INTERVALS_PER_SEC; - let SECONDS_TO_UNIX_EPOCH = INTERVALS_TO_UNIX_EPOCH / INTERVALS_PER_SEC; - - let duration = system_time_to_duration(&SystemTime::now())? - + Duration::from_secs(SECONDS_TO_UNIX_EPOCH); - let duration_ticks = u64::try_from(duration.as_nanos() / u128::from(NANOS_PER_INTERVAL)) - .map_err(|_| err_unsup_format!("programs running more than 2^64 Windows ticks after the Windows epoch are not supported"))?; + let duration = this.system_time_since_windows_epoch(&SystemTime::now())?; + let duration_ticks = this.windows_ticks_for(duration)?; let dwLowDateTime = u32::try_from(duration_ticks & 0x00000000FFFFFFFF).unwrap(); let dwHighDateTime = u32::try_from((duration_ticks & 0xFFFFFFFF00000000) >> 32).unwrap(); @@ -281,6 +273,30 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { interp_ok(Scalar::from_i32(-1)) // Return non-zero on success } + #[allow(non_snake_case, clippy::arithmetic_side_effects)] + fn system_time_since_windows_epoch(&self, time: &SystemTime) -> InterpResult<'tcx, Duration> { + let this = self.eval_context_ref(); + + let INTERVALS_PER_SEC = this.eval_windows_u64("time", "INTERVALS_PER_SEC"); + let INTERVALS_TO_UNIX_EPOCH = this.eval_windows_u64("time", "INTERVALS_TO_UNIX_EPOCH"); + let SECONDS_TO_UNIX_EPOCH = INTERVALS_TO_UNIX_EPOCH / INTERVALS_PER_SEC; + + interp_ok(system_time_to_duration(time)? + Duration::from_secs(SECONDS_TO_UNIX_EPOCH)) + } + + #[allow(non_snake_case, clippy::arithmetic_side_effects)] + fn windows_ticks_for(&self, duration: Duration) -> InterpResult<'tcx, u64> { + let this = self.eval_context_ref(); + + let NANOS_PER_SEC = this.eval_windows_u64("time", "NANOS_PER_SEC"); + let INTERVALS_PER_SEC = this.eval_windows_u64("time", "INTERVALS_PER_SEC"); + let NANOS_PER_INTERVAL = NANOS_PER_SEC / INTERVALS_PER_SEC; + + let ticks = u64::try_from(duration.as_nanos() / u128::from(NANOS_PER_INTERVAL)) + .map_err(|_| err_unsup_format!("programs running more than 2^64 Windows ticks after the Windows epoch are not supported"))?; + interp_ok(ticks) + } + fn mach_absolute_time(&self) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_ref(); diff --git a/src/tools/miri/src/shims/unix/fd.rs b/src/tools/miri/src/shims/unix/fd.rs index 3f85b9ae9bd9..41be9df7e2da 100644 --- a/src/tools/miri/src/shims/unix/fd.rs +++ b/src/tools/miri/src/shims/unix/fd.rs @@ -121,7 +121,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { throw_unsup_format!("unsupported flags {:#x}", op); }; - let result = fd.as_unix().flock(this.machine.communicate(), parsed_op)?; + let result = fd.as_unix(this).flock(this.machine.communicate(), parsed_op)?; // return `0` if flock is successful let result = result.map(|()| 0i32); interp_ok(Scalar::from_i32(this.try_unwrap_io_result(result)?)) @@ -273,7 +273,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let Ok(offset) = u64::try_from(offset) else { return this.set_last_error_and_return(LibcError("EINVAL"), dest); }; - fd.as_unix().pread(communicate, offset, buf, count, this, finish)? + fd.as_unix(this).pread(communicate, offset, buf, count, this, finish)? } }; interp_ok(()) @@ -333,7 +333,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let Ok(offset) = u64::try_from(offset) else { return this.set_last_error_and_return(LibcError("EINVAL"), dest); }; - fd.as_unix().pwrite(communicate, buf, count, offset, this, finish)? + fd.as_unix(this).pwrite(communicate, buf, count, offset, this, finish)? } }; interp_ok(()) diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index f8e0c638c90d..fc0f57694a71 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -2,10 +2,9 @@ use std::borrow::Cow; use std::fs::{ - DirBuilder, File, FileType, Metadata, OpenOptions, ReadDir, read_dir, remove_dir, remove_file, - rename, + DirBuilder, File, FileType, OpenOptions, ReadDir, read_dir, remove_dir, remove_file, rename, }; -use std::io::{self, ErrorKind, IsTerminal, Read, Seek, SeekFrom, Write}; +use std::io::{self, ErrorKind, Read, Seek, SeekFrom, Write}; use std::path::{Path, PathBuf}; use std::time::SystemTime; @@ -14,98 +13,11 @@ use rustc_data_structures::fx::FxHashMap; use self::shims::time::system_time_to_duration; use crate::helpers::check_min_vararg_count; -use crate::shims::files::{EvalContextExt as _, FileDescription, FileDescriptionRef}; +use crate::shims::files::FileHandle; use crate::shims::os_str::bytes_to_os_str; use crate::shims::unix::fd::{FlockOp, UnixFileDescription}; use crate::*; -#[derive(Debug)] -struct FileHandle { - file: File, - writable: bool, -} - -impl FileDescription for FileHandle { - fn name(&self) -> &'static str { - "file" - } - - fn read<'tcx>( - self: FileDescriptionRef, - communicate_allowed: bool, - ptr: Pointer, - len: usize, - ecx: &mut MiriInterpCx<'tcx>, - finish: DynMachineCallback<'tcx, Result>, - ) -> InterpResult<'tcx> { - assert!(communicate_allowed, "isolation should have prevented even opening a file"); - - let result = ecx.read_from_host(&self.file, len, ptr)?; - finish.call(ecx, result) - } - - fn write<'tcx>( - self: FileDescriptionRef, - communicate_allowed: bool, - ptr: Pointer, - len: usize, - ecx: &mut MiriInterpCx<'tcx>, - finish: DynMachineCallback<'tcx, Result>, - ) -> InterpResult<'tcx> { - assert!(communicate_allowed, "isolation should have prevented even opening a file"); - - let result = ecx.write_to_host(&self.file, len, ptr)?; - finish.call(ecx, result) - } - - fn seek<'tcx>( - &self, - communicate_allowed: bool, - offset: SeekFrom, - ) -> InterpResult<'tcx, io::Result> { - assert!(communicate_allowed, "isolation should have prevented even opening a file"); - interp_ok((&mut &self.file).seek(offset)) - } - - fn close<'tcx>( - self, - communicate_allowed: bool, - _ecx: &mut MiriInterpCx<'tcx>, - ) -> InterpResult<'tcx, io::Result<()>> { - assert!(communicate_allowed, "isolation should have prevented even opening a file"); - // We sync the file if it was opened in a mode different than read-only. - if self.writable { - // `File::sync_all` does the checks that are done when closing a file. We do this to - // to handle possible errors correctly. - let result = self.file.sync_all(); - // Now we actually close the file and return the result. - drop(self.file); - interp_ok(result) - } else { - // We drop the file, this closes it but ignores any errors - // produced when closing it. This is done because - // `File::sync_all` cannot be done over files like - // `/dev/urandom` which are read-only. Check - // https://github.com/rust-lang/miri/issues/999#issuecomment-568920439 - // for a deeper discussion. - drop(self.file); - interp_ok(Ok(())) - } - } - - fn metadata<'tcx>(&self) -> InterpResult<'tcx, io::Result> { - interp_ok(self.file.metadata()) - } - - fn is_tty(&self, communicate_allowed: bool) -> bool { - communicate_allowed && self.file.is_terminal() - } - - fn as_unix(&self) -> &dyn UnixFileDescription { - self - } -} - impl UnixFileDescription for FileHandle { fn pread<'tcx>( &self, diff --git a/src/tools/miri/src/shims/unix/linux_like/epoll.rs b/src/tools/miri/src/shims/unix/linux_like/epoll.rs index de8bcb54aef5..b489595b4cd0 100644 --- a/src/tools/miri/src/shims/unix/linux_like/epoll.rs +++ b/src/tools/miri/src/shims/unix/linux_like/epoll.rs @@ -153,7 +153,7 @@ impl FileDescription for Epoll { interp_ok(Ok(())) } - fn as_unix(&self) -> &dyn UnixFileDescription { + fn as_unix<'tcx>(&self, _ecx: &MiriInterpCx<'tcx>) -> &dyn UnixFileDescription { self } } @@ -590,7 +590,7 @@ fn check_and_update_one_event_interest<'tcx>( ecx: &MiriInterpCx<'tcx>, ) -> InterpResult<'tcx, bool> { // Get the bitmask of ready events for a file description. - let ready_events_bitmask = fd_ref.as_unix().get_epoll_ready_events()?.get_event_bitmask(ecx); + let ready_events_bitmask = fd_ref.as_unix(ecx).get_epoll_ready_events()?.get_event_bitmask(ecx); let epoll_event_interest = interest.borrow(); let epfd = epoll_event_interest.weak_epfd.upgrade().unwrap(); // This checks if any of the events specified in epoll_event_interest.events diff --git a/src/tools/miri/src/shims/unix/linux_like/eventfd.rs b/src/tools/miri/src/shims/unix/linux_like/eventfd.rs index 936d436bd82d..ee7deb8d3830 100644 --- a/src/tools/miri/src/shims/unix/linux_like/eventfd.rs +++ b/src/tools/miri/src/shims/unix/linux_like/eventfd.rs @@ -100,7 +100,7 @@ impl FileDescription for EventFd { eventfd_write(buf_place, self, ecx, finish) } - fn as_unix(&self) -> &dyn UnixFileDescription { + fn as_unix<'tcx>(&self, _ecx: &MiriInterpCx<'tcx>) -> &dyn UnixFileDescription { self } } diff --git a/src/tools/miri/src/shims/unix/unnamed_socket.rs b/src/tools/miri/src/shims/unix/unnamed_socket.rs index e183bfdf0e13..135d8f6bee7e 100644 --- a/src/tools/miri/src/shims/unix/unnamed_socket.rs +++ b/src/tools/miri/src/shims/unix/unnamed_socket.rs @@ -107,7 +107,7 @@ impl FileDescription for AnonSocket { anonsocket_write(self, ptr, len, ecx, finish) } - fn as_unix(&self) -> &dyn UnixFileDescription { + fn as_unix<'tcx>(&self, _ecx: &MiriInterpCx<'tcx>) -> &dyn UnixFileDescription { self } } diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs index dda302092751..33b654042391 100644 --- a/src/tools/miri/src/shims/windows/foreign_items.rs +++ b/src/tools/miri/src/shims/windows/foreign_items.rs @@ -241,6 +241,32 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { }; this.write_scalar(result, dest)?; } + "CreateFileW" => { + let [ + file_name, + desired_access, + share_mode, + security_attributes, + creation_disposition, + flags_and_attributes, + template_file, + ] = this.check_shim(abi, sys_conv, link_name, args)?; + let handle = this.CreateFileW( + file_name, + desired_access, + share_mode, + security_attributes, + creation_disposition, + flags_and_attributes, + template_file, + )?; + this.write_scalar(handle.to_scalar(this), dest)?; + } + "GetFileInformationByHandle" => { + let [handle, info] = this.check_shim(abi, sys_conv, link_name, args)?; + let res = this.GetFileInformationByHandle(handle, info)?; + this.write_scalar(res, dest)?; + } // Allocation "HeapAlloc" => { @@ -493,7 +519,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "SetThreadDescription" => { let [handle, name] = this.check_shim(abi, sys_conv, link_name, args)?; - let handle = this.read_handle(handle)?; + let handle = this.read_handle(handle, "SetThreadDescription")?; let name = this.read_wide_str(this.read_pointer(name)?)?; let thread = match handle { @@ -508,7 +534,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "GetThreadDescription" => { let [handle, name_ptr] = this.check_shim(abi, sys_conv, link_name, args)?; - let handle = this.read_handle(handle)?; + let handle = this.read_handle(handle, "GetThreadDescription")?; let name_ptr = this.deref_pointer_as(name_ptr, this.machine.layouts.mut_raw_ptr)?; // the pointer where we should store the ptr to the name let thread = match handle { @@ -618,7 +644,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let [handle, filename, size] = this.check_shim(abi, sys_conv, link_name, args)?; this.check_no_isolation("`GetModuleFileNameW`")?; - let handle = this.read_handle(handle)?; + let handle = this.read_handle(handle, "GetModuleFileNameW")?; let filename = this.read_pointer(filename)?; let size = this.read_scalar(size)?.to_u32()?; diff --git a/src/tools/miri/src/shims/windows/fs.rs b/src/tools/miri/src/shims/windows/fs.rs new file mode 100644 index 000000000000..32bab5489693 --- /dev/null +++ b/src/tools/miri/src/shims/windows/fs.rs @@ -0,0 +1,402 @@ +use std::fs::{Metadata, OpenOptions}; +use std::io; +use std::path::PathBuf; +use std::time::SystemTime; + +use bitflags::bitflags; + +use crate::shims::files::{FileDescription, FileHandle}; +use crate::shims::windows::handle::{EvalContextExt as _, Handle}; +use crate::*; + +#[derive(Debug)] +pub struct DirHandle { + pub(crate) path: PathBuf, +} + +impl FileDescription for DirHandle { + fn name(&self) -> &'static str { + "directory" + } + + fn metadata<'tcx>(&self) -> InterpResult<'tcx, io::Result> { + interp_ok(self.path.metadata()) + } + + fn close<'tcx>( + self, + _communicate_allowed: bool, + _ecx: &mut MiriInterpCx<'tcx>, + ) -> InterpResult<'tcx, io::Result<()>> { + interp_ok(Ok(())) + } +} + +/// Windows supports handles without any read/write/delete permissions - these handles can get +/// metadata, but little else. We represent that by storing the metadata from the time the handle +/// was opened. +#[derive(Debug)] +pub struct MetadataHandle { + pub(crate) meta: Metadata, +} + +impl FileDescription for MetadataHandle { + fn name(&self) -> &'static str { + "metadata-only" + } + + fn metadata<'tcx>(&self) -> InterpResult<'tcx, io::Result> { + interp_ok(Ok(self.meta.clone())) + } + + fn close<'tcx>( + self, + _communicate_allowed: bool, + _ecx: &mut MiriInterpCx<'tcx>, + ) -> InterpResult<'tcx, io::Result<()>> { + interp_ok(Ok(())) + } +} + +#[derive(Copy, Clone, Debug, PartialEq)] +enum CreationDisposition { + CreateAlways, + CreateNew, + OpenAlways, + OpenExisting, + TruncateExisting, +} + +impl CreationDisposition { + fn new<'tcx>( + value: u32, + ecx: &mut MiriInterpCx<'tcx>, + ) -> InterpResult<'tcx, CreationDisposition> { + let create_always = ecx.eval_windows_u32("c", "CREATE_ALWAYS"); + let create_new = ecx.eval_windows_u32("c", "CREATE_NEW"); + let open_always = ecx.eval_windows_u32("c", "OPEN_ALWAYS"); + let open_existing = ecx.eval_windows_u32("c", "OPEN_EXISTING"); + let truncate_existing = ecx.eval_windows_u32("c", "TRUNCATE_EXISTING"); + + let out = if value == create_always { + CreationDisposition::CreateAlways + } else if value == create_new { + CreationDisposition::CreateNew + } else if value == open_always { + CreationDisposition::OpenAlways + } else if value == open_existing { + CreationDisposition::OpenExisting + } else if value == truncate_existing { + CreationDisposition::TruncateExisting + } else { + throw_unsup_format!("CreateFileW: Unsupported creation disposition: {value}"); + }; + interp_ok(out) + } +} + +bitflags! { + #[derive(PartialEq)] + struct FileAttributes: u32 { + const ZERO = 0; + const NORMAL = 1 << 0; + /// This must be passed to allow getting directory handles. If not passed, we error on trying + /// to open directories + const BACKUP_SEMANTICS = 1 << 1; + /// Open a reparse point as a regular file - this is basically similar to 'readlink' in Unix + /// terminology. A reparse point is a file with custom logic when navigated to, of which + /// a symlink is one specific example. + const OPEN_REPARSE = 1 << 2; + } +} + +impl FileAttributes { + fn new<'tcx>( + mut value: u32, + ecx: &mut MiriInterpCx<'tcx>, + ) -> InterpResult<'tcx, FileAttributes> { + let file_attribute_normal = ecx.eval_windows_u32("c", "FILE_ATTRIBUTE_NORMAL"); + let file_flag_backup_semantics = ecx.eval_windows_u32("c", "FILE_FLAG_BACKUP_SEMANTICS"); + let file_flag_open_reparse_point = + ecx.eval_windows_u32("c", "FILE_FLAG_OPEN_REPARSE_POINT"); + + let mut out = FileAttributes::ZERO; + if value & file_flag_backup_semantics != 0 { + value &= !file_flag_backup_semantics; + out |= FileAttributes::BACKUP_SEMANTICS; + } + if value & file_flag_open_reparse_point != 0 { + value &= !file_flag_open_reparse_point; + out |= FileAttributes::OPEN_REPARSE; + } + if value & file_attribute_normal != 0 { + value &= !file_attribute_normal; + out |= FileAttributes::NORMAL; + } + + if value != 0 { + throw_unsup_format!("CreateFileW: Unsupported flags_and_attributes: {value}"); + } + + if out == FileAttributes::ZERO { + // NORMAL is equivalent to 0. Avoid needing to check both cases by unifying the two. + out = FileAttributes::NORMAL; + } + interp_ok(out) + } +} + +impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} +#[allow(non_snake_case)] +pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { + fn CreateFileW( + &mut self, + file_name: &OpTy<'tcx>, // LPCWSTR + desired_access: &OpTy<'tcx>, // DWORD + share_mode: &OpTy<'tcx>, // DWORD + security_attributes: &OpTy<'tcx>, // LPSECURITY_ATTRIBUTES + creation_disposition: &OpTy<'tcx>, // DWORD + flags_and_attributes: &OpTy<'tcx>, // DWORD + template_file: &OpTy<'tcx>, // HANDLE + ) -> InterpResult<'tcx, Handle> { + // ^ Returns HANDLE + use CreationDisposition::*; + + let this = self.eval_context_mut(); + this.assert_target_os("windows", "CreateFileW"); + this.check_no_isolation("`CreateFileW`")?; + + // This function appears to always set the error to 0. This is important for some flag + // combinations, which may set error code on success. + this.set_last_error(IoError::Raw(Scalar::from_i32(0)))?; + + let file_name = this.read_path_from_wide_str(this.read_pointer(file_name)?)?; + let mut desired_access = this.read_scalar(desired_access)?.to_u32()?; + let share_mode = this.read_scalar(share_mode)?.to_u32()?; + let security_attributes = this.read_pointer(security_attributes)?; + let creation_disposition = this.read_scalar(creation_disposition)?.to_u32()?; + let flags_and_attributes = this.read_scalar(flags_and_attributes)?.to_u32()?; + let template_file = this.read_target_usize(template_file)?; + + let generic_read = this.eval_windows_u32("c", "GENERIC_READ"); + let generic_write = this.eval_windows_u32("c", "GENERIC_WRITE"); + + let file_share_delete = this.eval_windows_u32("c", "FILE_SHARE_DELETE"); + let file_share_read = this.eval_windows_u32("c", "FILE_SHARE_READ"); + let file_share_write = this.eval_windows_u32("c", "FILE_SHARE_WRITE"); + + let creation_disposition = CreationDisposition::new(creation_disposition, this)?; + let attributes = FileAttributes::new(flags_and_attributes, this)?; + + if share_mode != (file_share_delete | file_share_read | file_share_write) { + throw_unsup_format!("CreateFileW: Unsupported share mode: {share_mode}"); + } + if !this.ptr_is_null(security_attributes)? { + throw_unsup_format!("CreateFileW: Security attributes are not supported"); + } + + if attributes.contains(FileAttributes::OPEN_REPARSE) && creation_disposition == CreateAlways + { + throw_machine_stop!(TerminationInfo::Abort("Invalid CreateFileW argument combination: FILE_FLAG_OPEN_REPARSE_POINT with CREATE_ALWAYS".to_string())); + } + + if template_file != 0 { + throw_unsup_format!("CreateFileW: Template files are not supported"); + } + + // We need to know if the file is a directory to correctly open directory handles. + // This is racy, but currently the stdlib doesn't appear to offer a better solution. + let is_dir = file_name.is_dir(); + + // BACKUP_SEMANTICS is how Windows calls the act of opening a directory handle. + if !attributes.contains(FileAttributes::BACKUP_SEMANTICS) && is_dir { + this.set_last_error(IoError::WindowsError("ERROR_ACCESS_DENIED"))?; + return interp_ok(Handle::Invalid); + } + + let desired_read = desired_access & generic_read != 0; + let desired_write = desired_access & generic_write != 0; + + let mut options = OpenOptions::new(); + if desired_read { + desired_access &= !generic_read; + options.read(true); + } + if desired_write { + desired_access &= !generic_write; + options.write(true); + } + + if desired_access != 0 { + throw_unsup_format!( + "CreateFileW: Unsupported bits set for access mode: {desired_access:#x}" + ); + } + + // Per the documentation: + // If the specified file exists and is writable, the function truncates the file, + // the function succeeds, and last-error code is set to ERROR_ALREADY_EXISTS. + // If the specified file does not exist and is a valid path, a new file is created, + // the function succeeds, and the last-error code is set to zero. + // https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew + // + // This is racy, but there doesn't appear to be an std API that both succeeds if a + // file exists but tells us it isn't new. Either we accept racing one way or another, + // or we use an iffy heuristic like file creation time. This implementation prefers + // to fail in the direction of erroring more often. + if let CreateAlways | OpenAlways = creation_disposition + && file_name.exists() + { + this.set_last_error(IoError::WindowsError("ERROR_ALREADY_EXISTS"))?; + } + + let handle = if is_dir { + // Open this as a directory. + let fd_num = this.machine.fds.insert_new(DirHandle { path: file_name }); + Ok(Handle::File(fd_num)) + } else if creation_disposition == OpenExisting && !(desired_read || desired_write) { + // Windows supports handles with no permissions. These allow things such as reading + // metadata, but not file content. + file_name.metadata().map(|meta| { + let fd_num = this.machine.fds.insert_new(MetadataHandle { meta }); + Handle::File(fd_num) + }) + } else { + // Open this as a standard file. + match creation_disposition { + CreateAlways | OpenAlways => { + options.create(true); + if creation_disposition == CreateAlways { + options.truncate(true); + } + } + CreateNew => { + options.create_new(true); + // Per `create_new` documentation: + // The file must be opened with write or append access in order to create a new file. + // https://doc.rust-lang.org/std/fs/struct.OpenOptions.html#method.create_new + if !desired_write { + options.append(true); + } + } + OpenExisting => {} // Default options + TruncateExisting => { + options.truncate(true); + } + } + + options.open(file_name).map(|file| { + let fd_num = + this.machine.fds.insert_new(FileHandle { file, writable: desired_write }); + Handle::File(fd_num) + }) + }; + + match handle { + Ok(handle) => interp_ok(handle), + Err(e) => { + this.set_last_error(e)?; + interp_ok(Handle::Invalid) + } + } + } + + fn GetFileInformationByHandle( + &mut self, + file: &OpTy<'tcx>, // HANDLE + file_information: &OpTy<'tcx>, // LPBY_HANDLE_FILE_INFORMATION + ) -> InterpResult<'tcx, Scalar> { + // ^ Returns BOOL (i32 on Windows) + let this = self.eval_context_mut(); + this.assert_target_os("windows", "GetFileInformationByHandle"); + this.check_no_isolation("`GetFileInformationByHandle`")?; + + let file = this.read_handle(file, "GetFileInformationByHandle")?; + let file_information = this.deref_pointer_as( + file_information, + this.windows_ty_layout("BY_HANDLE_FILE_INFORMATION"), + )?; + + let fd_num = if let Handle::File(fd_num) = file { + fd_num + } else { + this.invalid_handle("GetFileInformationByHandle")? + }; + + let Some(desc) = this.machine.fds.get(fd_num) else { + this.invalid_handle("GetFileInformationByHandle")? + }; + + let metadata = match desc.metadata()? { + Ok(meta) => meta, + Err(e) => { + this.set_last_error(e)?; + return interp_ok(this.eval_windows("c", "FALSE")); + } + }; + + let size = metadata.len(); + + let file_type = metadata.file_type(); + let attributes = if file_type.is_dir() { + this.eval_windows_u32("c", "FILE_ATTRIBUTE_DIRECTORY") + } else if file_type.is_file() { + this.eval_windows_u32("c", "FILE_ATTRIBUTE_NORMAL") + } else { + this.eval_windows_u32("c", "FILE_ATTRIBUTE_DEVICE") + }; + + // Per the Windows documentation: + // "If the underlying file system does not support the [...] time, this member is zero (0)." + // https://learn.microsoft.com/en-us/windows/win32/api/fileapi/ns-fileapi-by_handle_file_information + let created = extract_windows_epoch(this, metadata.created())?.unwrap_or((0, 0)); + let accessed = extract_windows_epoch(this, metadata.accessed())?.unwrap_or((0, 0)); + let written = extract_windows_epoch(this, metadata.modified())?.unwrap_or((0, 0)); + + this.write_int_fields_named(&[("dwFileAttributes", attributes.into())], &file_information)?; + write_filetime_field(this, &file_information, "ftCreationTime", created)?; + write_filetime_field(this, &file_information, "ftLastAccessTime", accessed)?; + write_filetime_field(this, &file_information, "ftLastWriteTime", written)?; + this.write_int_fields_named( + &[ + ("dwVolumeSerialNumber", 0), + ("nFileSizeHigh", (size >> 32).into()), + ("nFileSizeLow", (size & 0xFFFFFFFF).into()), + ("nNumberOfLinks", 1), + ("nFileIndexHigh", 0), + ("nFileIndexLow", 0), + ], + &file_information, + )?; + + interp_ok(this.eval_windows("c", "TRUE")) + } +} + +/// Windows FILETIME is measured in 100-nanosecs since 1601 +fn extract_windows_epoch<'tcx>( + ecx: &MiriInterpCx<'tcx>, + time: io::Result, +) -> InterpResult<'tcx, Option<(u32, u32)>> { + match time.ok() { + Some(time) => { + let duration = ecx.system_time_since_windows_epoch(&time)?; + let duration_ticks = ecx.windows_ticks_for(duration)?; + #[allow(clippy::cast_possible_truncation)] + interp_ok(Some((duration_ticks as u32, (duration_ticks >> 32) as u32))) + } + None => interp_ok(None), + } +} + +fn write_filetime_field<'tcx>( + cx: &mut MiriInterpCx<'tcx>, + val: &MPlaceTy<'tcx>, + name: &str, + (low, high): (u32, u32), +) -> InterpResult<'tcx> { + cx.write_int_fields_named( + &[("dwLowDateTime", low.into()), ("dwHighDateTime", high.into())], + &cx.project_field_named(val, name)?, + ) +} diff --git a/src/tools/miri/src/shims/windows/handle.rs b/src/tools/miri/src/shims/windows/handle.rs index cac67c888f86..eec6c62bebc7 100644 --- a/src/tools/miri/src/shims/windows/handle.rs +++ b/src/tools/miri/src/shims/windows/handle.rs @@ -1,9 +1,9 @@ use std::mem::variant_count; -use std::panic::Location; use rustc_abi::HasDataLayout; use crate::concurrency::thread::ThreadNotFound; +use crate::shims::files::FdNum; use crate::*; #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] @@ -17,7 +17,7 @@ pub enum Handle { Null, Pseudo(PseudoHandle), Thread(ThreadId), - File(i32), + File(FdNum), Invalid, } @@ -51,6 +51,8 @@ impl Handle { const PSEUDO_DISCRIMINANT: u32 = 1; const THREAD_DISCRIMINANT: u32 = 2; const FILE_DISCRIMINANT: u32 = 3; + // Chosen to ensure Handle::Invalid encodes to -1. Update this value if there are ever more than + // 8 discriminants. const INVALID_DISCRIMINANT: u32 = 7; fn discriminant(self) -> u32 { @@ -70,20 +72,25 @@ impl Handle { Self::Thread(thread) => thread.to_u32(), #[expect(clippy::cast_sign_loss)] Self::File(fd) => fd as u32, + // INVALID_HANDLE_VALUE is -1. This fact is explicitly declared or implied in several + // pages of Windows documentation. + // 1: https://learn.microsoft.com/en-us/dotnet/api/microsoft.win32.safehandles.safefilehandle?view=net-9.0 + // 2: https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/get-osfhandle?view=msvc-170 Self::Invalid => 0x1FFFFFFF, } } fn packed_disc_size() -> u32 { - // ceil(log2(x)) is how many bits it takes to store x numbers - // We ensure that INVALID_HANDLE_VALUE (0xFFFFFFFF) decodes to Handle::Invalid - // see https://devblogs.microsoft.com/oldnewthing/20230914-00/?p=108766 + // ceil(log2(x)) is how many bits it takes to store x numbers. + // We ensure that INVALID_HANDLE_VALUE (0xFFFFFFFF) decodes to Handle::Invalid. + // see https://devblogs.microsoft.com/oldnewthing/20230914-00/?p=108766 for more detail on + // INVALID_HANDLE_VALUE. let variant_count = variant_count::(); - // however, std's ilog2 is floor(log2(x)) + // However, std's ilog2 is floor(log2(x)). let floor_log2 = variant_count.ilog2(); - // we need to add one for non powers of two to compensate for the difference + // We need to add one for non powers of two to compensate for the difference. #[expect(clippy::arithmetic_side_effects)] // cannot overflow if variant_count.is_power_of_two() { floor_log2 } else { floor_log2 + 1 } } @@ -105,7 +112,7 @@ impl Handle { assert!(discriminant < 2u32.pow(disc_size)); // make sure the data fits into `data_size` bits - assert!(data <= 2u32.pow(data_size)); + assert!(data < 2u32.pow(data_size)); // packs the data into the lower `data_size` bits // and packs the discriminant right above the data @@ -118,7 +125,11 @@ impl Handle { Self::PSEUDO_DISCRIMINANT => Some(Self::Pseudo(PseudoHandle::from_value(data)?)), Self::THREAD_DISCRIMINANT => Some(Self::Thread(ThreadId::new_unchecked(data))), #[expect(clippy::cast_possible_wrap)] - Self::FILE_DISCRIMINANT => Some(Self::File(data as i32)), + Self::FILE_DISCRIMINANT => { + // This cast preserves all bits. + assert_eq!(size_of_val(&data), size_of::()); + Some(Self::File(data as FdNum)) + } Self::INVALID_DISCRIMINANT => Some(Self::Invalid), _ => None, } @@ -154,7 +165,7 @@ impl Handle { /// Structurally invalid handles return [`HandleError::InvalidHandle`]. /// If the handle is structurally valid but semantically invalid, e.g. a for non-existent thread /// ID, returns [`HandleError::ThreadNotFound`]. - pub fn try_from_scalar<'tcx>( + fn try_from_scalar<'tcx>( handle: Scalar, cx: &MiriInterpCx<'tcx>, ) -> InterpResult<'tcx, Result> { @@ -186,22 +197,23 @@ impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} #[allow(non_snake_case)] pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { + /// Convert a scalar into a structured `Handle`. + /// If the handle is invalid, or references a non-existent item, execution is aborted. #[track_caller] - fn read_handle(&self, handle: &OpTy<'tcx>) -> InterpResult<'tcx, Handle> { + fn read_handle(&self, handle: &OpTy<'tcx>, function_name: &str) -> InterpResult<'tcx, Handle> { let this = self.eval_context_ref(); let handle = this.read_scalar(handle)?; match Handle::try_from_scalar(handle, this)? { Ok(handle) => interp_ok(handle), Err(HandleError::InvalidHandle) => throw_machine_stop!(TerminationInfo::Abort(format!( - "invalid handle {} at {}", + "invalid handle {} passed to {function_name}", handle.to_target_isize(this)?, - Location::caller(), ))), Err(HandleError::ThreadNotFound(_)) => throw_machine_stop!(TerminationInfo::Abort(format!( - "invalid thread ID: {}", - Location::caller() + "invalid thread ID {} passed to {function_name}", + handle.to_target_isize(this)?, ))), } } @@ -215,15 +227,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn CloseHandle(&mut self, handle_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - let handle = this.read_handle(handle_op)?; + let handle = this.read_handle(handle_op, "CloseHandle")?; let ret = match handle { Handle::Thread(thread) => { this.detach_thread(thread, /*allow_terminated_joined*/ true)?; this.eval_windows("c", "TRUE") } - Handle::File(fd) => - if let Some(file) = this.machine.fds.get(fd) { - let err = file.close(this.machine.communicate(), this)?; + Handle::File(fd_num) => + if let Some(fd) = this.machine.fds.remove(fd_num) { + let err = fd.close_ref(this.machine.communicate(), this)?; if let Err(e) = err { this.set_last_error(e)?; this.eval_windows("c", "FALSE") @@ -239,3 +251,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { interp_ok(ret) } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_invalid_encoding() { + // Ensure the invalid handle encodes to `u32::MAX`/`INVALID_HANDLE_VALUE`. + assert_eq!(Handle::Invalid.to_packed(), u32::MAX) + } +} diff --git a/src/tools/miri/src/shims/windows/mod.rs b/src/tools/miri/src/shims/windows/mod.rs index 892bd6924fc9..442c5a0dd11f 100644 --- a/src/tools/miri/src/shims/windows/mod.rs +++ b/src/tools/miri/src/shims/windows/mod.rs @@ -1,12 +1,14 @@ pub mod foreign_items; mod env; +mod fs; mod handle; mod sync; mod thread; // All the Windows-specific extension traits pub use self::env::{EvalContextExt as _, WindowsEnvVars}; +pub use self::fs::EvalContextExt as _; pub use self::handle::EvalContextExt as _; pub use self::sync::EvalContextExt as _; pub use self::thread::EvalContextExt as _; diff --git a/src/tools/miri/src/shims/windows/thread.rs b/src/tools/miri/src/shims/windows/thread.rs index 8289eea34127..d5f9ed4e968e 100644 --- a/src/tools/miri/src/shims/windows/thread.rs +++ b/src/tools/miri/src/shims/windows/thread.rs @@ -62,7 +62,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - let handle = this.read_handle(handle_op)?; + let handle = this.read_handle(handle_op, "WaitForSingleObject")?; let timeout = this.read_scalar(timeout_op)?.to_u32()?; let thread = match handle { diff --git a/src/tools/miri/test_dependencies/Cargo.toml b/src/tools/miri/test_dependencies/Cargo.toml index 7e16592ca7a8..3427ef165239 100644 --- a/src/tools/miri/test_dependencies/Cargo.toml +++ b/src/tools/miri/test_dependencies/Cargo.toml @@ -25,6 +25,6 @@ page_size = "0.6" tokio = { version = "1.24", features = ["macros", "rt-multi-thread", "time", "net", "fs", "sync", "signal", "io-util"] } [target.'cfg(windows)'.dependencies] -windows-sys = { version = "0.59", features = [ "Win32_Foundation", "Win32_System_Threading" ] } +windows-sys = { version = "0.59", features = ["Win32_Foundation", "Win32_System_Threading", "Win32_Storage_FileSystem", "Win32_Security"] } [workspace] diff --git a/src/tools/miri/tests/fail-dep/concurrency/windows_join_main.rs b/src/tools/miri/tests/fail-dep/concurrency/windows_join_main.rs index 279201df867c..3ee2bf14f9fe 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/windows_join_main.rs +++ b/src/tools/miri/tests/fail-dep/concurrency/windows_join_main.rs @@ -13,7 +13,7 @@ use windows_sys::Win32::System::Threading::{INFINITE, WaitForSingleObject}; // XXX HACK: This is how miri represents the handle for thread 0. // This value can be "legitimately" obtained by using `GetCurrentThread` with `DuplicateHandle` // but miri does not implement `DuplicateHandle` yet. -const MAIN_THREAD: HANDLE = (2i32 << 30) as HANDLE; +const MAIN_THREAD: HANDLE = (2i32 << 29) as HANDLE; fn main() { thread::spawn(|| { diff --git a/src/tools/miri/tests/pass-dep/shims/windows-fs.rs b/src/tools/miri/tests/pass-dep/shims/windows-fs.rs new file mode 100644 index 000000000000..312df9eb115d --- /dev/null +++ b/src/tools/miri/tests/pass-dep/shims/windows-fs.rs @@ -0,0 +1,198 @@ +//@only-target: windows # this directly tests windows-only functions +//@compile-flags: -Zmiri-disable-isolation +#![allow(nonstandard_style)] + +use std::os::windows::ffi::OsStrExt; +use std::path::Path; +use std::ptr; + +#[path = "../../utils/mod.rs"] +mod utils; + +use windows_sys::Win32::Foundation::{ + CloseHandle, ERROR_ALREADY_EXISTS, GENERIC_READ, GENERIC_WRITE, GetLastError, +}; +use windows_sys::Win32::Storage::FileSystem::{ + BY_HANDLE_FILE_INFORMATION, CREATE_ALWAYS, CREATE_NEW, CreateFileW, FILE_ATTRIBUTE_DIRECTORY, + FILE_ATTRIBUTE_NORMAL, FILE_FLAG_BACKUP_SEMANTICS, FILE_FLAG_OPEN_REPARSE_POINT, + FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE, GetFileInformationByHandle, OPEN_ALWAYS, + OPEN_EXISTING, +}; + +fn main() { + unsafe { + test_create_dir_file(); + test_create_normal_file(); + test_create_always_twice(); + test_open_always_twice(); + test_open_dir_reparse(); + } +} + +unsafe fn test_create_dir_file() { + let temp = utils::tmp(); + let raw_path = to_wide_cstr(&temp); + // Open the `temp` directory. + let handle = CreateFileW( + raw_path.as_ptr(), + GENERIC_READ, + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + ptr::null_mut(), + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, + ptr::null_mut(), + ); + assert_ne!(handle.addr(), usize::MAX, "CreateFileW Failed: {}", GetLastError()); + let mut info = std::mem::zeroed::(); + if GetFileInformationByHandle(handle, &mut info) == 0 { + panic!("Failed to get file information") + }; + assert!(info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY != 0); + if CloseHandle(handle) == 0 { + panic!("Failed to close file") + }; +} + +unsafe fn test_create_normal_file() { + let temp = utils::tmp().join("test.txt"); + let raw_path = to_wide_cstr(&temp); + let handle = CreateFileW( + raw_path.as_ptr(), + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + ptr::null_mut(), + CREATE_NEW, + 0, + ptr::null_mut(), + ); + assert_ne!(handle.addr(), usize::MAX, "CreateFileW Failed: {}", GetLastError()); + let mut info = std::mem::zeroed::(); + if GetFileInformationByHandle(handle, &mut info) == 0 { + panic!("Failed to get file information: {}", GetLastError()) + }; + assert!(info.dwFileAttributes & FILE_ATTRIBUTE_NORMAL != 0); + if CloseHandle(handle) == 0 { + panic!("Failed to close file") + }; + + // Test metadata-only handle + let handle = CreateFileW( + raw_path.as_ptr(), + 0, + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + ptr::null_mut(), + OPEN_EXISTING, + 0, + ptr::null_mut(), + ); + assert_ne!(handle.addr(), usize::MAX, "CreateFileW Failed: {}", GetLastError()); + let mut info = std::mem::zeroed::(); + if GetFileInformationByHandle(handle, &mut info) == 0 { + panic!("Failed to get file information: {}", GetLastError()) + }; + assert!(info.dwFileAttributes & FILE_ATTRIBUTE_NORMAL != 0); + if CloseHandle(handle) == 0 { + panic!("Failed to close file") + }; +} + +/// Tests that CREATE_ALWAYS sets the error value correctly based on whether the file already exists +unsafe fn test_create_always_twice() { + let temp = utils::tmp().join("test_create_always.txt"); + let raw_path = to_wide_cstr(&temp); + let handle = CreateFileW( + raw_path.as_ptr(), + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + ptr::null_mut(), + CREATE_ALWAYS, + 0, + ptr::null_mut(), + ); + assert_ne!(handle.addr(), usize::MAX, "CreateFileW Failed: {}", GetLastError()); + assert_eq!(GetLastError(), 0); + if CloseHandle(handle) == 0 { + panic!("Failed to close file") + }; + + let handle = CreateFileW( + raw_path.as_ptr(), + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + ptr::null_mut(), + CREATE_ALWAYS, + 0, + ptr::null_mut(), + ); + assert_ne!(handle.addr(), usize::MAX, "CreateFileW Failed: {}", GetLastError()); + assert_eq!(GetLastError(), ERROR_ALREADY_EXISTS); + if CloseHandle(handle) == 0 { + panic!("Failed to close file") + }; +} + +/// Tests that OPEN_ALWAYS sets the error value correctly based on whether the file already exists +unsafe fn test_open_always_twice() { + let temp = utils::tmp().join("test_open_always.txt"); + let raw_path = to_wide_cstr(&temp); + let handle = CreateFileW( + raw_path.as_ptr(), + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + ptr::null_mut(), + OPEN_ALWAYS, + 0, + ptr::null_mut(), + ); + assert_ne!(handle.addr(), usize::MAX, "CreateFileW Failed: {}", GetLastError()); + assert_eq!(GetLastError(), 0); + if CloseHandle(handle) == 0 { + panic!("Failed to close file") + }; + + let handle = CreateFileW( + raw_path.as_ptr(), + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + ptr::null_mut(), + OPEN_ALWAYS, + 0, + ptr::null_mut(), + ); + assert_ne!(handle.addr(), usize::MAX, "CreateFileW Failed: {}", GetLastError()); + assert_eq!(GetLastError(), ERROR_ALREADY_EXISTS); + if CloseHandle(handle) == 0 { + panic!("Failed to close file") + }; +} + +// TODO: Once we support more of the std API, it would be nice to test against an actual symlink +unsafe fn test_open_dir_reparse() { + let temp = utils::tmp(); + let raw_path = to_wide_cstr(&temp); + // Open the `temp` directory. + let handle = CreateFileW( + raw_path.as_ptr(), + GENERIC_READ, + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + ptr::null_mut(), + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, + ptr::null_mut(), + ); + assert_ne!(handle.addr(), usize::MAX, "CreateFileW Failed: {}", GetLastError()); + let mut info = std::mem::zeroed::(); + if GetFileInformationByHandle(handle, &mut info) == 0 { + panic!("Failed to get file information") + }; + assert!(info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY != 0); + if CloseHandle(handle) == 0 { + panic!("Failed to close file") + }; +} + +fn to_wide_cstr(path: &Path) -> Vec { + let mut raw_path = path.as_os_str().encode_wide().collect::>(); + raw_path.extend([0, 0]); + raw_path +} diff --git a/src/tools/miri/tests/pass/shims/fs.rs b/src/tools/miri/tests/pass/shims/fs.rs index 289c6aa2fcec..6ad23055f30e 100644 --- a/src/tools/miri/tests/pass/shims/fs.rs +++ b/src/tools/miri/tests/pass/shims/fs.rs @@ -1,4 +1,3 @@ -//@ignore-target: windows # File handling is not implemented yet //@compile-flags: -Zmiri-disable-isolation #![feature(io_error_more)] @@ -18,20 +17,23 @@ mod utils; fn main() { test_path_conversion(); - test_file(); - test_file_clone(); - test_file_create_new(); - test_seek(); - test_metadata(); - test_file_set_len(); - test_file_sync(); - test_errors(); - test_rename(); - test_directory(); - test_canonicalize(); - test_from_raw_os_error(); - #[cfg(unix)] - test_pread_pwrite(); + // Windows file handling is very incomplete. + if cfg!(not(windows)) { + test_file(); + test_file_create_new(); + test_seek(); + test_file_clone(); + test_metadata(); + test_file_set_len(); + test_file_sync(); + test_errors(); + test_rename(); + test_directory(); + test_canonicalize(); + test_from_raw_os_error(); + #[cfg(unix)] + test_pread_pwrite(); + } } fn test_path_conversion() { @@ -144,10 +146,10 @@ fn test_metadata() { let path = utils::prepare_with_content("miri_test_fs_metadata.txt", bytes); // Test that metadata of an absolute path is correct. - check_metadata(bytes, &path).unwrap(); + check_metadata(bytes, &path).expect("absolute path metadata"); // Test that metadata of a relative path is correct. std::env::set_current_dir(path.parent().unwrap()).unwrap(); - check_metadata(bytes, Path::new(path.file_name().unwrap())).unwrap(); + check_metadata(bytes, Path::new(path.file_name().unwrap())).expect("relative path metadata"); // Removing file should succeed. remove_file(&path).unwrap(); From f419b18d16be992b5db21e0008aa7be16f92803f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 9 Apr 2025 09:30:51 +1000 Subject: [PATCH 245/606] Return early on an error path in `parse_item_impl`. Currently the code continues, using an empty path, but it doesn't need to. --- compiler/rustc_parse/src/parser/item.rs | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 3647bf2c378e..915a30e5469e 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -602,21 +602,13 @@ impl<'a> Parser<'a> { let polarity = self.parse_polarity(); // Parse both types and traits as a type, then reinterpret if necessary. - let err_path = |span| ast::Path::from_ident(Ident::new(kw::Empty, span)); let ty_first = if self.token.is_keyword(kw::For) && self.look_ahead(1, |t| t != &token::Lt) { let span = self.prev_token.span.between(self.token.span); - self.dcx().emit_err(errors::MissingTraitInTraitImpl { + return Err(self.dcx().create_err(errors::MissingTraitInTraitImpl { span, for_span: span.to(self.token.span), - }); - - P(Ty { - kind: TyKind::Path(None, err_path(span)), - span, - id: DUMMY_NODE_ID, - tokens: None, - }) + })); } else { self.parse_ty_with_generics_recovery(&generics)? }; @@ -671,7 +663,7 @@ impl<'a> Parser<'a> { span: ty_first.span, }); } - err_path(ty_first.span) + ast::Path::from_ident(Ident::new(kw::Empty, ty_first.span)) } }; let trait_ref = TraitRef { path, ref_id: ty_first.id }; From 7ae5c7f32dfc85c0e57949dee1c54bd1c6586e37 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 9 Apr 2025 14:16:22 +1000 Subject: [PATCH 246/606] Avoid an empty trait name in impl blocks. `resolve_ident_in_lexical_scope` checks for an empty name. Why is this necessary? Because `parse_item_impl` can produce an `impl` block with an empty trait name in some cases. This is pretty gross and very non-obvious. This commit avoids the use of the empty trait name. In one case the trait name is instead pulled from `TyKind::ImplTrait`, which prevents the output for `tests/ui/impl-trait/extra-impl-in-trait-impl.rs` from changing. In the other case we just fail the parse and don't try to recover. I think losing error recovery in this obscure case is worth the code cleanup. This change affects `tests/ui/parser/impl-parsing.rs`, which is split in two, and the obsolete `..` syntax cases are removed (they are tested elsewhere). --- compiler/rustc_parse/src/parser/item.rs | 9 +++--- compiler/rustc_resolve/src/ident.rs | 3 -- tests/ui/parser/impl-parsing-2.rs | 4 +++ tests/ui/parser/impl-parsing-2.stderr | 18 ++++++++++++ tests/ui/parser/impl-parsing.rs | 5 ---- tests/ui/parser/impl-parsing.stderr | 37 ++----------------------- 6 files changed, 29 insertions(+), 47 deletions(-) create mode 100644 tests/ui/parser/impl-parsing-2.rs create mode 100644 tests/ui/parser/impl-parsing-2.stderr diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 915a30e5469e..065018163407 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -649,6 +649,7 @@ impl<'a> Parser<'a> { other => { if let TyKind::ImplTrait(_, bounds) = other && let [bound] = bounds.as_slice() + && let GenericBound::Trait(poly_trait_ref) = bound { // Suggest removing extra `impl` keyword: // `impl impl Default for Wrapper` @@ -658,12 +659,12 @@ impl<'a> Parser<'a> { extra_impl_kw, impl_trait_span: ty_first.span, }); + poly_trait_ref.trait_ref.path.clone() } else { - self.dcx().emit_err(errors::ExpectedTraitInTraitImplFoundType { - span: ty_first.span, - }); + return Err(self.dcx().create_err( + errors::ExpectedTraitInTraitImplFoundType { span: ty_first.span }, + )); } - ast::Path::from_ident(Ident::new(kw::Empty, ty_first.span)) } }; let trait_ref = TraitRef { path, ref_id: ty_first.id }; diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 5f0a2a597e9b..180d6af219d1 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -296,9 +296,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ) -> Option> { assert!(ns == TypeNS || ns == ValueNS); let orig_ident = ident; - if ident.name == kw::Empty { - return Some(LexicalScopeBinding::Res(Res::Err)); - } let (general_span, normalized_span) = if ident.name == kw::SelfUpper { // FIXME(jseyfried) improve `Self` hygiene let empty_span = ident.span.with_ctxt(SyntaxContext::root()); diff --git a/tests/ui/parser/impl-parsing-2.rs b/tests/ui/parser/impl-parsing-2.rs new file mode 100644 index 000000000000..7a71217b21c5 --- /dev/null +++ b/tests/ui/parser/impl-parsing-2.rs @@ -0,0 +1,4 @@ +impl ! {} // OK + +default unsafe FAIL //~ ERROR expected item, found keyword `unsafe` +//~^ ERROR `default` is not followed by an item diff --git a/tests/ui/parser/impl-parsing-2.stderr b/tests/ui/parser/impl-parsing-2.stderr new file mode 100644 index 000000000000..45e2c428242d --- /dev/null +++ b/tests/ui/parser/impl-parsing-2.stderr @@ -0,0 +1,18 @@ +error: `default` is not followed by an item + --> $DIR/impl-parsing-2.rs:3:1 + | +LL | default unsafe FAIL + | ^^^^^^^ the `default` qualifier + | + = note: only `fn`, `const`, `type`, or `impl` items may be prefixed by `default` + +error: expected item, found keyword `unsafe` + --> $DIR/impl-parsing-2.rs:3:9 + | +LL | default unsafe FAIL + | ^^^^^^ expected item + | + = note: for a full list of items that can appear in modules, see + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/impl-parsing.rs b/tests/ui/parser/impl-parsing.rs index 80ce88855707..7692a81dd42c 100644 --- a/tests/ui/parser/impl-parsing.rs +++ b/tests/ui/parser/impl-parsing.rs @@ -2,9 +2,4 @@ impl ! {} // OK impl ! where u8: Copy {} // OK impl Trait Type {} //~ ERROR missing `for` in a trait impl -impl Trait .. {} //~ ERROR missing `for` in a trait impl impl ?Sized for Type {} //~ ERROR expected a trait, found type -impl ?Sized for .. {} //~ ERROR expected a trait, found type - -default unsafe FAIL //~ ERROR expected item, found keyword `unsafe` -//~^ ERROR `default` is not followed by an item diff --git a/tests/ui/parser/impl-parsing.stderr b/tests/ui/parser/impl-parsing.stderr index 6a24a9453e63..b2512120dc87 100644 --- a/tests/ui/parser/impl-parsing.stderr +++ b/tests/ui/parser/impl-parsing.stderr @@ -9,44 +9,11 @@ help: add `for` here LL | impl Trait for Type {} | +++ -error: missing `for` in a trait impl - --> $DIR/impl-parsing.rs:5:11 - | -LL | impl Trait .. {} - | ^ - | -help: add `for` here - | -LL | impl Trait for .. {} - | +++ - error: expected a trait, found type - --> $DIR/impl-parsing.rs:6:6 + --> $DIR/impl-parsing.rs:5:6 | LL | impl ?Sized for Type {} | ^^^^^^ -error: expected a trait, found type - --> $DIR/impl-parsing.rs:7:6 - | -LL | impl ?Sized for .. {} - | ^^^^^^ - -error: `default` is not followed by an item - --> $DIR/impl-parsing.rs:9:1 - | -LL | default unsafe FAIL - | ^^^^^^^ the `default` qualifier - | - = note: only `fn`, `const`, `type`, or `impl` items may be prefixed by `default` - -error: expected item, found keyword `unsafe` - --> $DIR/impl-parsing.rs:9:9 - | -LL | default unsafe FAIL - | ^^^^^^ expected item - | - = note: for a full list of items that can appear in modules, see - -error: aborting due to 6 previous errors +error: aborting due to 2 previous errors From f0fb21e93c08e4d7b7bd24d685bd104b939f4b56 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 9 Apr 2025 08:25:40 +0200 Subject: [PATCH 247/606] update lockfile --- Cargo.lock | 61 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 35 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fc1c9cf97f0b..33bdabd18bac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -337,7 +337,7 @@ dependencies = [ name = "cargo-miri" version = "0.1.0" dependencies = [ - "cargo_metadata 0.18.1", + "cargo_metadata 0.19.2", "directories", "rustc-build-sysroot", "rustc_tools_util 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -971,11 +971,11 @@ dependencies = [ [[package]] name = "directories" -version = "5.0.1" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35" +checksum = "16f5094c54661b38d03bd7e50df373292118db60b585c08a411c6d840017fe7d" dependencies = [ - "dirs-sys", + "dirs-sys 0.5.0", ] [[package]] @@ -984,7 +984,7 @@ version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" dependencies = [ - "dirs-sys", + "dirs-sys 0.4.1", ] [[package]] @@ -1005,10 +1005,22 @@ checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" dependencies = [ "libc", "option-ext", - "redox_users", + "redox_users 0.4.6", "windows-sys 0.48.0", ] +[[package]] +name = "dirs-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" +dependencies = [ + "libc", + "option-ext", + "redox_users 0.5.0", + "windows-sys 0.59.0", +] + [[package]] name = "dirs-sys-next" version = "0.1.2" @@ -1016,7 +1028,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" dependencies = [ "libc", - "redox_users", + "redox_users 0.4.6", "winapi", ] @@ -2170,20 +2182,6 @@ dependencies = [ "digest", ] -[[package]] -name = "measureme" -version = "11.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfa4a40f09af7aa6faef38285402a78847d0d72bf8827006cd2a332e1e6e4a8d" -dependencies = [ - "log", - "memmap2", - "parking_lot", - "perf-event-open-sys", - "rustc-hash 1.1.0", - "smallvec", -] - [[package]] name = "measureme" version = "12.0.1" @@ -2281,7 +2279,7 @@ dependencies = [ "libc", "libffi", "libloading", - "measureme 11.0.1", + "measureme", "rand 0.9.0", "regex", "rustc_version", @@ -2289,7 +2287,7 @@ dependencies = [ "tempfile", "tikv-jemalloc-sys", "ui_test", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2988,6 +2986,17 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "redox_users" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" +dependencies = [ + "getrandom 0.2.15", + "libredox", + "thiserror 2.0.12", +] + [[package]] name = "regex" version = "1.11.1" @@ -3430,7 +3439,7 @@ dependencies = [ "gimli 0.31.1", "itertools", "libc", - "measureme 12.0.1", + "measureme", "object 0.36.7", "rustc-demangle", "rustc_abi", @@ -3545,7 +3554,7 @@ dependencies = [ "indexmap", "jobserver", "libc", - "measureme 12.0.1", + "measureme", "memmap2", "parking_lot", "portable-atomic", @@ -4305,7 +4314,7 @@ dependencies = [ name = "rustc_query_impl" version = "0.0.0" dependencies = [ - "measureme 12.0.1", + "measureme", "rustc_data_structures", "rustc_hashes", "rustc_hir", From cffc5c21fc49e86859ea5601a4f80d4446b594e9 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 7 Apr 2025 17:28:58 +0300 Subject: [PATCH 248/606] compiletest: Add directive `dont-require-annotations` for making matching on specific diagnostic kinds non-exhaustive --- src/tools/compiletest/src/directive-list.rs | 1 + src/tools/compiletest/src/errors.rs | 11 +++++++++- src/tools/compiletest/src/header.rs | 20 ++++++++++++++++- src/tools/compiletest/src/runtest.rs | 24 ++++++++++----------- 4 files changed, 41 insertions(+), 15 deletions(-) diff --git a/src/tools/compiletest/src/directive-list.rs b/src/tools/compiletest/src/directive-list.rs index b2ad5a3b3d0b..44d9c0330f76 100644 --- a/src/tools/compiletest/src/directive-list.rs +++ b/src/tools/compiletest/src/directive-list.rs @@ -22,6 +22,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "dont-check-compiler-stderr", "dont-check-compiler-stdout", "dont-check-failure-status", + "dont-require-annotations", "edition", "error-pattern", "exact-llvm-major-version", diff --git a/src/tools/compiletest/src/errors.rs b/src/tools/compiletest/src/errors.rs index 9b59e4968a3d..64d68eb7f23e 100644 --- a/src/tools/compiletest/src/errors.rs +++ b/src/tools/compiletest/src/errors.rs @@ -8,7 +8,7 @@ use std::sync::OnceLock; use regex::Regex; use tracing::*; -#[derive(Copy, Clone, Debug, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum ErrorKind { Help, Error, @@ -40,6 +40,15 @@ impl ErrorKind { _ => return None, }) } + + pub fn expect_from_user_str(s: &str) -> ErrorKind { + ErrorKind::from_user_str(s).unwrap_or_else(|| { + panic!( + "unexpected diagnostic kind `{s}`, expected \ + `ERROR`, `WARN`, `NOTE`, `HELP` or `SUGGESTION`" + ) + }) + } } impl fmt::Display for ErrorKind { diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index a0178f4bcc57..36a9e5df5839 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -1,4 +1,4 @@ -use std::collections::HashSet; +use std::collections::{HashMap, HashSet}; use std::env; use std::fs::File; use std::io::BufReader; @@ -11,6 +11,7 @@ use tracing::*; use crate::common::{Config, Debugger, FailMode, Mode, PassMode}; use crate::debuggers::{extract_cdb_version, extract_gdb_version}; +use crate::errors::ErrorKind; use crate::executor::{CollectedTestDesc, ShouldPanic}; use crate::header::auxiliary::{AuxProps, parse_and_update_aux}; use crate::header::needs::CachedNeedsConditions; @@ -196,6 +197,8 @@ pub struct TestProps { /// Build and use `minicore` as `core` stub for `no_core` tests in cross-compilation scenarios /// that don't otherwise want/need `-Z build-std`. pub add_core_stubs: bool, + /// Whether line annotatins are required for the given error kind. + pub require_annotations: HashMap, } mod directives { @@ -212,6 +215,7 @@ mod directives { pub const CHECK_RUN_RESULTS: &'static str = "check-run-results"; pub const DONT_CHECK_COMPILER_STDOUT: &'static str = "dont-check-compiler-stdout"; pub const DONT_CHECK_COMPILER_STDERR: &'static str = "dont-check-compiler-stderr"; + pub const DONT_REQUIRE_ANNOTATIONS: &'static str = "dont-require-annotations"; pub const NO_PREFER_DYNAMIC: &'static str = "no-prefer-dynamic"; pub const PRETTY_MODE: &'static str = "pretty-mode"; pub const PRETTY_COMPARE_ONLY: &'static str = "pretty-compare-only"; @@ -297,6 +301,13 @@ impl TestProps { no_auto_check_cfg: false, has_enzyme: false, add_core_stubs: false, + require_annotations: HashMap::from([ + (ErrorKind::Help, true), + (ErrorKind::Note, true), + (ErrorKind::Error, true), + (ErrorKind::Warning, true), + (ErrorKind::Suggestion, false), + ]), } } @@ -570,6 +581,13 @@ impl TestProps { config.set_name_directive(ln, NO_AUTO_CHECK_CFG, &mut self.no_auto_check_cfg); self.update_add_core_stubs(ln, config); + + if let Some(err_kind) = + config.parse_name_value_directive(ln, DONT_REQUIRE_ANNOTATIONS) + { + self.require_annotations + .insert(ErrorKind::expect_from_user_str(&err_kind), false); + } }, ); diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 13f3479247a2..872f5f6ce296 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -710,10 +710,6 @@ impl<'test> TestCx<'test> { self.testpaths.file.display().to_string() }; - // If the testcase being checked contains at least one expected "help" - // message, then we'll ensure that all "help" messages are expected. - // Otherwise, all "help" messages reported by the compiler will be ignored. - // This logic also applies to "note" messages. let expect_help = expected_errors.iter().any(|ee| ee.kind == Some(ErrorKind::Help)); let expect_note = expected_errors.iter().any(|ee| ee.kind == Some(ErrorKind::Note)); @@ -801,9 +797,7 @@ impl<'test> TestCx<'test> { } /// Returns `true` if we should report an error about `actual_error`, - /// which did not match any of the expected error. We always require - /// errors/warnings to be explicitly listed, but only require - /// helps/notes if there are explicit helps/notes given. + /// which did not match any of the expected error. fn is_unexpected_compiler_message( &self, actual_error: &Error, @@ -811,12 +805,16 @@ impl<'test> TestCx<'test> { expect_note: bool, ) -> bool { actual_error.require_annotation - && match actual_error.kind { - Some(ErrorKind::Help) => expect_help, - Some(ErrorKind::Note) => expect_note, - Some(ErrorKind::Error) | Some(ErrorKind::Warning) => true, - Some(ErrorKind::Suggestion) | None => false, - } + && actual_error.kind.map_or(false, |err_kind| { + // If the test being checked doesn't contain any "help" or "note" annotations, then + // we don't require annotating "help" or "note" (respecively) diagnostics at all. + let default_require_annotations = self.props.require_annotations[&err_kind]; + match err_kind { + ErrorKind::Help => expect_help && default_require_annotations, + ErrorKind::Note => expect_note && default_require_annotations, + _ => default_require_annotations, + } + }) } fn should_emit_metadata(&self, pm: Option) -> Emit { From 12829122bf2216e492e2befb0c1305b5efbfee7d Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 9 Apr 2025 09:51:50 +0300 Subject: [PATCH 249/606] Migrate some tests to `dont-require-annotations` --- tests/ui/cfg/cfg_false_no_std-2.rs | 8 ++++---- tests/ui/panic-runtime/two-panic-runtimes.rs | 8 ++++---- tests/ui/panic-runtime/want-abort-got-unwind.rs | 8 ++++---- tests/ui/panic-runtime/want-abort-got-unwind2.rs | 8 ++++---- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/tests/ui/cfg/cfg_false_no_std-2.rs b/tests/ui/cfg/cfg_false_no_std-2.rs index 35e545aae34b..349c49412ffa 100644 --- a/tests/ui/cfg/cfg_false_no_std-2.rs +++ b/tests/ui/cfg/cfg_false_no_std-2.rs @@ -1,7 +1,6 @@ // Error, the linked empty library is `no_std` and doesn't provide a panic handler. -//@ compile-flags: --error-format=human -//@ error-pattern: `#[panic_handler]` function required, but not found +//@ dont-require-annotations:ERROR //@ dont-check-compiler-stderr //@ aux-build: cfg_false_lib_no_std_before.rs @@ -11,6 +10,7 @@ extern crate cfg_false_lib_no_std_before as _; fn main() {} -// FIXME: The second error is target-dependent. -//FIXME~? ERROR `#[panic_handler]` function required, but not found +//~? ERROR `#[panic_handler]` function required, but not found +// FIXME: This error is target-dependent, could be served by some "optional error" annotation +// instead of `dont-require-annotations`. //FIXME~? ERROR unwinding panics are not supported without std diff --git a/tests/ui/panic-runtime/two-panic-runtimes.rs b/tests/ui/panic-runtime/two-panic-runtimes.rs index 15c08cbe30d3..7add07ef6004 100644 --- a/tests/ui/panic-runtime/two-panic-runtimes.rs +++ b/tests/ui/panic-runtime/two-panic-runtimes.rs @@ -1,7 +1,6 @@ // ignore-tidy-linelength //@ build-fail -//@ compile-flags: --error-format=human -//@ error-pattern: cannot link together two panic runtimes: panic_runtime_unwind and panic_runtime_unwind2 +//@ dont-require-annotations:ERROR //@ dont-check-compiler-stderr //@ aux-build:panic-runtime-unwind.rs //@ aux-build:panic-runtime-unwind2.rs @@ -16,7 +15,8 @@ extern crate panic_runtime_lang_items; fn main() {} -// FIXME: The second and third errors are target-dependent. -//FIXME~? ERROR cannot link together two panic runtimes: panic_runtime_unwind and panic_runtime_unwind2 +//~? ERROR cannot link together two panic runtimes: panic_runtime_unwind and panic_runtime_unwind2 +// FIXME: These errors are target-dependent, could be served by some "optional error" annotation +// instead of `dont-require-annotations`. //FIXME~? ERROR the linked panic runtime `panic_runtime_unwind2` is not compiled with this crate's panic strategy `abort` //FIXME~? ERROR the crate `panic_runtime_unwind` requires panic strategy `unwind` which is incompatible with this crate's strategy of `abort` diff --git a/tests/ui/panic-runtime/want-abort-got-unwind.rs b/tests/ui/panic-runtime/want-abort-got-unwind.rs index ed61c2613df8..1ae2e623f103 100644 --- a/tests/ui/panic-runtime/want-abort-got-unwind.rs +++ b/tests/ui/panic-runtime/want-abort-got-unwind.rs @@ -1,7 +1,6 @@ // ignore-tidy-linelength //@ build-fail -//@ compile-flags: --error-format=human -//@ error-pattern: the linked panic runtime `panic_runtime_unwind` is not compiled with this crate's panic strategy `abort` +//@ dont-require-annotations:ERROR //@ dont-check-compiler-stderr //@ aux-build:panic-runtime-unwind.rs //@ compile-flags:-C panic=abort @@ -10,7 +9,8 @@ extern crate panic_runtime_unwind; fn main() {} -// FIXME: The first and third errors are target-dependent. +//~? ERROR the linked panic runtime `panic_runtime_unwind` is not compiled with this crate's panic strategy `abort` +// FIXME: These errors are target-dependent, could be served by some "optional error" annotation +// instead of `dont-require-annotations`. //FIXME~? ERROR cannot link together two panic runtimes: panic_unwind and panic_runtime_unwind -//FIXME~? ERROR the linked panic runtime `panic_runtime_unwind` is not compiled with this crate's panic strategy `abort` //FIXME~? ERROR the crate `panic_unwind` requires panic strategy `unwind` which is incompatible with this crate's strategy of `abort` diff --git a/tests/ui/panic-runtime/want-abort-got-unwind2.rs b/tests/ui/panic-runtime/want-abort-got-unwind2.rs index 504fd779e09a..dc4d3ea86d86 100644 --- a/tests/ui/panic-runtime/want-abort-got-unwind2.rs +++ b/tests/ui/panic-runtime/want-abort-got-unwind2.rs @@ -1,7 +1,6 @@ // ignore-tidy-linelength //@ build-fail -//@ compile-flags: --error-format=human -//@ error-pattern: the linked panic runtime `panic_runtime_unwind` is not compiled with this crate's panic strategy `abort` +//@ dont-require-annotations:ERROR //@ dont-check-compiler-stderr //@ aux-build:panic-runtime-unwind.rs //@ aux-build:wants-panic-runtime-unwind.rs @@ -11,7 +10,8 @@ extern crate wants_panic_runtime_unwind; fn main() {} -// FIXME: The first and third errors are target-dependent. +//~? ERROR the linked panic runtime `panic_runtime_unwind` is not compiled with this crate's panic strategy `abort` +// FIXME: These errors are target-dependent, could be served by some "optional error" annotation +// instead of `dont-require-annotations`. //FIXME~? ERROR cannot link together two panic runtimes: panic_unwind and panic_runtime_unwind -//FIXME~? ERROR the linked panic runtime `panic_runtime_unwind` is not compiled with this crate's panic strategy `abort` //FIXME~? ERROR the crate `panic_unwind` requires panic strategy `unwind` which is incompatible with this crate's strategy of `abort` From 8b6ff4a378e2df03db108bcd918a77f8a759334f Mon Sep 17 00:00:00 2001 From: Romain Perier Date: Wed, 26 Mar 2025 15:49:42 +0100 Subject: [PATCH 250/606] Suggest the use of `impl Trait` in function parameter only Currently in case of a Trait object in closure parameter, the compiler suggests either to use a reference, which is correct or to use an `impl Trait` which is not. Do not emit this suggestion when the parameter is part of a closure. --- .../src/error_reporting/traits/suggestions.rs | 23 ++++++++++++++----- .../dont-suggest-impl-as-closure-arg.rs | 5 ++++ .../dont-suggest-impl-as-closure-arg.stderr | 16 +++++++++++++ 3 files changed, 38 insertions(+), 6 deletions(-) create mode 100644 tests/ui/traits/dont-suggest-impl-as-closure-arg.rs create mode 100644 tests/ui/traits/dont-suggest-impl-as-closure-arg.stderr diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 38fcba4ea625..cfe9120a4a46 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -3018,12 +3018,23 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { [] => span_bug!(ty.span, "trait object with no traits: {ty:?}"), }; let needs_parens = traits.len() != 1; - err.span_suggestion_verbose( - span, - "you can use `impl Trait` as the argument type", - "impl ", - Applicability::MaybeIncorrect, - ); + // Don't recommend impl Trait as a closure argument + if let Some(hir_id) = hir_id + && matches!( + self.tcx.parent_hir_node(hir_id), + hir::Node::Item(hir::Item { + kind: hir::ItemKind::Fn { .. }, + .. + }) + ) + { + err.span_suggestion_verbose( + span, + "you can use `impl Trait` as the argument type", + "impl ", + Applicability::MaybeIncorrect, + ); + } let sugg = if !needs_parens { vec![(span.shrink_to_lo(), format!("&{kw}"))] } else { diff --git a/tests/ui/traits/dont-suggest-impl-as-closure-arg.rs b/tests/ui/traits/dont-suggest-impl-as-closure-arg.rs new file mode 100644 index 000000000000..68e234b0f20d --- /dev/null +++ b/tests/ui/traits/dont-suggest-impl-as-closure-arg.rs @@ -0,0 +1,5 @@ +// Suggestion to use impl trait in closure parameter is invalid, see issue 138932 +fn main() { + let c = |f: dyn Fn()| f(); + //~^ ERROR: the size for values of type `(dyn Fn() + 'static)` cannot be known at compilation time +} diff --git a/tests/ui/traits/dont-suggest-impl-as-closure-arg.stderr b/tests/ui/traits/dont-suggest-impl-as-closure-arg.stderr new file mode 100644 index 000000000000..8218990503c2 --- /dev/null +++ b/tests/ui/traits/dont-suggest-impl-as-closure-arg.stderr @@ -0,0 +1,16 @@ +error[E0277]: the size for values of type `(dyn Fn() + 'static)` cannot be known at compilation time + --> $DIR/dont-suggest-impl-as-closure-arg.rs:3:17 + | +LL | let c = |f: dyn Fn()| f(); + | ^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `(dyn Fn() + 'static)` + = help: unsized fn params are gated as an unstable feature +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | let c = |f: &dyn Fn()| f(); + | + + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. From b2aa9d0620bbfa09f67c7bbfae2dd553d39bc90a Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 8 Apr 2025 10:52:16 +0000 Subject: [PATCH 251/606] Remove some dead or leftover code related to rustc-intrinsic abi removal --- .../src/error_codes/E0622.md | 4 ++- compiler/rustc_error_codes/src/lib.rs | 2 +- .../rustc_hir_analysis/src/check/check.rs | 11 ------- .../rustc_hir_analysis/src/check/intrinsic.rs | 33 +++++-------------- tests/ui/error-codes/E0622.rs | 14 -------- tests/ui/error-codes/E0622.stderr | 9 ----- 6 files changed, 13 insertions(+), 60 deletions(-) delete mode 100644 tests/ui/error-codes/E0622.rs delete mode 100644 tests/ui/error-codes/E0622.stderr diff --git a/compiler/rustc_error_codes/src/error_codes/E0622.md b/compiler/rustc_error_codes/src/error_codes/E0622.md index e6ff949d3e9f..9b8131a061e3 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0622.md +++ b/compiler/rustc_error_codes/src/error_codes/E0622.md @@ -1,8 +1,10 @@ +#### Note: this error code is no longer emitted by the compiler. + An intrinsic was declared without being a function. Erroneous code example: -```compile_fail,E0622 +```no_run #![feature(intrinsics)] #![allow(internal_features)] diff --git a/compiler/rustc_error_codes/src/lib.rs b/compiler/rustc_error_codes/src/lib.rs index dfeef5a957d6..2488d870899c 100644 --- a/compiler/rustc_error_codes/src/lib.rs +++ b/compiler/rustc_error_codes/src/lib.rs @@ -397,7 +397,7 @@ E0618: 0618, E0619: 0619, E0620: 0620, E0621: 0621, -E0622: 0622, +E0622: 0622, // REMOVED: rustc-intrinsic ABI was removed E0623: 0623, E0624: 0624, E0625: 0625, diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index e3ed20e1b318..2e0e57ba8879 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -719,7 +719,6 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) { def_id, tcx.def_ident_span(def_id).unwrap(), i.name, - ExternAbi::Rust, ) } } @@ -787,16 +786,6 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) { for item in items { let def_id = item.id.owner_id.def_id; - if tcx.has_attr(def_id, sym::rustc_intrinsic) { - intrinsic::check_intrinsic_type( - tcx, - item.id.owner_id.def_id, - item.span, - item.ident.name, - abi, - ); - } - let generics = tcx.generics_of(def_id); let own_counts = generics.own_counts(); if generics.own_params.len() - own_counts.lifetimes != 0 { diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 0bf9e127989f..d62ca7e19877 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -1,9 +1,8 @@ //! Type-checking for the `#[rustc_intrinsic]` intrinsics that the compiler exposes. use rustc_abi::ExternAbi; -use rustc_errors::codes::*; -use rustc_errors::{DiagMessage, struct_span_code_err}; -use rustc_hir::{self as hir, Safety}; +use rustc_errors::DiagMessage; +use rustc_hir::{self as hir}; use rustc_middle::bug; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::ty::{self, Ty, TyCtxt}; @@ -26,17 +25,10 @@ fn equate_intrinsic_type<'tcx>( sig: ty::PolyFnSig<'tcx>, ) { let (generics, span) = match tcx.hir_node_by_def_id(def_id) { - hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn { generics, .. }, .. }) - | hir::Node::ForeignItem(hir::ForeignItem { - kind: hir::ForeignItemKind::Fn(_, _, generics), - .. - }) => (tcx.generics_of(def_id), generics.span), - _ => { - struct_span_code_err!(tcx.dcx(), span, E0622, "intrinsic must be a function") - .with_span_label(span, "expected a function") - .emit(); - return; + hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn { generics, .. }, .. }) => { + (tcx.generics_of(def_id), generics.span) } + _ => tcx.dcx().span_bug(span, "intrinsic must be a function"), }; let own_counts = generics.own_counts(); @@ -70,13 +62,7 @@ fn equate_intrinsic_type<'tcx>( } /// Returns the unsafety of the given intrinsic. -pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hir::Safety { - let has_safe_attr = if tcx.has_attr(intrinsic_id, sym::rustc_intrinsic) { - tcx.fn_sig(intrinsic_id).skip_binder().safety() - } else { - // Old-style intrinsics are never safe - Safety::Unsafe - }; +fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hir::Safety { let is_in_list = match tcx.item_name(intrinsic_id.into()) { // When adding a new intrinsic to this list, // it's usually worth updating that intrinsic's documentation @@ -148,7 +134,7 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) - _ => hir::Safety::Unsafe, }; - if has_safe_attr != is_in_list { + if tcx.fn_sig(intrinsic_id).skip_binder().safety() != is_in_list { tcx.dcx().struct_span_err( tcx.def_span(intrinsic_id), DiagMessage::from(format!( @@ -163,12 +149,11 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) - /// Remember to add all intrinsics here, in `compiler/rustc_codegen_llvm/src/intrinsic.rs`, /// and in `library/core/src/intrinsics.rs`. -pub fn check_intrinsic_type( +pub(crate) fn check_intrinsic_type( tcx: TyCtxt<'_>, intrinsic_id: LocalDefId, span: Span, intrinsic_name: Symbol, - abi: ExternAbi, ) { let generics = tcx.generics_of(intrinsic_id); let param = |n| { @@ -706,7 +691,7 @@ pub fn check_intrinsic_type( }; (n_tps, 0, n_cts, inputs, output, safety) }; - let sig = tcx.mk_fn_sig(inputs, output, false, safety, abi); + let sig = tcx.mk_fn_sig(inputs, output, false, safety, ExternAbi::Rust); let sig = ty::Binder::bind_with_vars(sig, bound_vars); equate_intrinsic_type(tcx, span, intrinsic_id, n_tps, n_lts, n_cts, sig) } diff --git a/tests/ui/error-codes/E0622.rs b/tests/ui/error-codes/E0622.rs deleted file mode 100644 index 0c2a4f226d80..000000000000 --- a/tests/ui/error-codes/E0622.rs +++ /dev/null @@ -1,14 +0,0 @@ -#![feature(intrinsics)] - -extern "C" { - - #[rustc_intrinsic] - pub static atomic_singlethreadfence_seqcst: unsafe extern "C" fn(); - //~^ ERROR intrinsic must be a function [E0622] -} - -fn main() { - unsafe { - atomic_singlethreadfence_seqcst(); - } -} diff --git a/tests/ui/error-codes/E0622.stderr b/tests/ui/error-codes/E0622.stderr deleted file mode 100644 index c0aea542af04..000000000000 --- a/tests/ui/error-codes/E0622.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0622]: intrinsic must be a function - --> $DIR/E0622.rs:6:5 - | -LL | pub static atomic_singlethreadfence_seqcst: unsafe extern "C" fn(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected a function - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0622`. From 09d5bcf1ad75c0f0a43d32de6bc73533ac83d6d0 Mon Sep 17 00:00:00 2001 From: lincot Date: Mon, 6 May 2024 16:50:17 +0300 Subject: [PATCH 252/606] Speed up `String::push` and `String::insert` Improve performance of `String` methods by avoiding unnecessary memcpy for the character bytes, with added codegen check to ensure compliance. --- library/alloc/src/lib.rs | 1 + library/alloc/src/string.rs | 69 +++++++++++++++++------- library/core/src/char/methods.rs | 90 ++++++++++++++++++++++---------- library/core/src/char/mod.rs | 2 +- tests/codegen/string-push.rs | 11 ++++ 5 files changed, 123 insertions(+), 50 deletions(-) create mode 100644 tests/codegen/string-push.rs diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 04858667230b..e70e6ca0d55d 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -104,6 +104,7 @@ #![feature(async_iterator)] #![feature(bstr)] #![feature(bstr_internals)] +#![feature(char_internals)] #![feature(char_max_len)] #![feature(clone_to_uninit)] #![feature(coerce_unsized)] diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 9236f5cb8d1f..5193a0b2d4b6 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -1401,11 +1401,14 @@ impl String { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn push(&mut self, ch: char) { - match ch.len_utf8() { - 1 => self.vec.push(ch as u8), - _ => { - self.vec.extend_from_slice(ch.encode_utf8(&mut [0; char::MAX_LEN_UTF8]).as_bytes()) - } + let len = self.len(); + let ch_len = ch.len_utf8(); + self.reserve(ch_len); + + // SAFETY: Just reserved capacity for at least the length needed to encode `ch`. + unsafe { + core::char::encode_utf8_raw_unchecked(ch as u32, self.vec.as_mut_ptr().add(self.len())); + self.vec.set_len(len + ch_len); } } @@ -1702,24 +1705,31 @@ impl String { #[rustc_confusables("set")] pub fn insert(&mut self, idx: usize, ch: char) { assert!(self.is_char_boundary(idx)); - let mut bits = [0; char::MAX_LEN_UTF8]; - let bits = ch.encode_utf8(&mut bits).as_bytes(); - unsafe { - self.insert_bytes(idx, bits); - } - } - - #[cfg(not(no_global_oom_handling))] - unsafe fn insert_bytes(&mut self, idx: usize, bytes: &[u8]) { let len = self.len(); - let amt = bytes.len(); - self.vec.reserve(amt); + let ch_len = ch.len_utf8(); + self.reserve(ch_len); + // SAFETY: Move the bytes starting from `idx` to their new location `ch_len` + // bytes ahead. This is safe because sufficient capacity was reserved, and `idx` + // is a char boundary. unsafe { - ptr::copy(self.vec.as_ptr().add(idx), self.vec.as_mut_ptr().add(idx + amt), len - idx); - ptr::copy_nonoverlapping(bytes.as_ptr(), self.vec.as_mut_ptr().add(idx), amt); - self.vec.set_len(len + amt); + ptr::copy( + self.vec.as_ptr().add(idx), + self.vec.as_mut_ptr().add(idx + ch_len), + len - idx, + ); + } + + // SAFETY: Encode the character into the vacated region if `idx != len`, + // or into the uninitialized spare capacity otherwise. + unsafe { + core::char::encode_utf8_raw_unchecked(ch as u32, self.vec.as_mut_ptr().add(idx)); + } + + // SAFETY: Update the length to include the newly added bytes. + unsafe { + self.vec.set_len(len + ch_len); } } @@ -1749,8 +1759,27 @@ impl String { pub fn insert_str(&mut self, idx: usize, string: &str) { assert!(self.is_char_boundary(idx)); + let len = self.len(); + let amt = string.len(); + self.reserve(amt); + + // SAFETY: Move the bytes starting from `idx` to their new location `amt` bytes + // ahead. This is safe because sufficient capacity was just reserved, and `idx` + // is a char boundary. unsafe { - self.insert_bytes(idx, string.as_bytes()); + ptr::copy(self.vec.as_ptr().add(idx), self.vec.as_mut_ptr().add(idx + amt), len - idx); + } + + // SAFETY: Copy the new string slice into the vacated region if `idx != len`, + // or into the uninitialized spare capacity otherwise. The borrow checker + // ensures that the source and destination do not overlap. + unsafe { + ptr::copy_nonoverlapping(string.as_ptr(), self.vec.as_mut_ptr().add(idx), amt); + } + + // SAFETY: Update the length to include the newly added bytes. + unsafe { + self.vec.set_len(len + amt); } } diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index fa584953bed5..367f2b499afe 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -1806,39 +1806,71 @@ const fn len_utf16(code: u32) -> usize { #[inline] pub const fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> &mut [u8] { let len = len_utf8(code); - match (len, &mut *dst) { - (1, [a, ..]) => { - *a = code as u8; - } - (2, [a, b, ..]) => { - *a = (code >> 6 & 0x1F) as u8 | TAG_TWO_B; - *b = (code & 0x3F) as u8 | TAG_CONT; - } - (3, [a, b, c, ..]) => { - *a = (code >> 12 & 0x0F) as u8 | TAG_THREE_B; - *b = (code >> 6 & 0x3F) as u8 | TAG_CONT; - *c = (code & 0x3F) as u8 | TAG_CONT; - } - (4, [a, b, c, d, ..]) => { - *a = (code >> 18 & 0x07) as u8 | TAG_FOUR_B; - *b = (code >> 12 & 0x3F) as u8 | TAG_CONT; - *c = (code >> 6 & 0x3F) as u8 | TAG_CONT; - *d = (code & 0x3F) as u8 | TAG_CONT; - } - _ => { - const_panic!( - "encode_utf8: buffer does not have enough bytes to encode code point", - "encode_utf8: need {len} bytes to encode U+{code:04X} but buffer has just {dst_len}", - code: u32 = code, - len: usize = len, - dst_len: usize = dst.len(), - ) - } - }; + if dst.len() < len { + const_panic!( + "encode_utf8: buffer does not have enough bytes to encode code point", + "encode_utf8: need {len} bytes to encode U+{code:04X} but buffer has just {dst_len}", + code: u32 = code, + len: usize = len, + dst_len: usize = dst.len(), + ); + } + + // SAFETY: `dst` is checked to be at least the length needed to encode the codepoint. + unsafe { encode_utf8_raw_unchecked(code, dst.as_mut_ptr()) }; + // SAFETY: `<&mut [u8]>::as_mut_ptr` is guaranteed to return a valid pointer and `len` has been tested to be within bounds. unsafe { slice::from_raw_parts_mut(dst.as_mut_ptr(), len) } } +/// Encodes a raw `u32` value as UTF-8 into the byte buffer pointed to by `dst`. +/// +/// Unlike `char::encode_utf8`, this method also handles codepoints in the surrogate range. +/// (Creating a `char` in the surrogate range is UB.) +/// The result is valid [generalized UTF-8] but not valid UTF-8. +/// +/// [generalized UTF-8]: https://simonsapin.github.io/wtf-8/#generalized-utf8 +/// +/// # Safety +/// +/// The behavior is undefined if the buffer pointed to by `dst` is not +/// large enough to hold the encoded codepoint. A buffer of length four +/// is large enough to encode any `char`. +/// +/// For a safe version of this function, see the [`encode_utf8_raw`] function. +#[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")] +#[doc(hidden)] +#[inline] +pub const unsafe fn encode_utf8_raw_unchecked(code: u32, dst: *mut u8) { + let len = len_utf8(code); + // SAFETY: The caller must guarantee that the buffer pointed to by `dst` + // is at least `len` bytes long. + unsafe { + match len { + 1 => { + *dst = code as u8; + } + 2 => { + *dst = (code >> 6 & 0x1F) as u8 | TAG_TWO_B; + *dst.add(1) = (code & 0x3F) as u8 | TAG_CONT; + } + 3 => { + *dst = (code >> 12 & 0x0F) as u8 | TAG_THREE_B; + *dst.add(1) = (code >> 6 & 0x3F) as u8 | TAG_CONT; + *dst.add(2) = (code & 0x3F) as u8 | TAG_CONT; + } + 4 => { + *dst = (code >> 18 & 0x07) as u8 | TAG_FOUR_B; + *dst.add(1) = (code >> 12 & 0x3F) as u8 | TAG_CONT; + *dst.add(2) = (code >> 6 & 0x3F) as u8 | TAG_CONT; + *dst.add(3) = (code & 0x3F) as u8 | TAG_CONT; + } + // SAFETY: `char` always takes between 1 and 4 bytes to encode in UTF-8. + _ => crate::hint::unreachable_unchecked(), + } + } +} + /// Encodes a raw `u32` value as native endian UTF-16 into the provided `u16` buffer, /// and then returns the subslice of the buffer that contains the encoded character. /// diff --git a/library/core/src/char/mod.rs b/library/core/src/char/mod.rs index 088c709f1a2a..5b9f0e2143f5 100644 --- a/library/core/src/char/mod.rs +++ b/library/core/src/char/mod.rs @@ -38,7 +38,7 @@ pub use self::decode::{DecodeUtf16, DecodeUtf16Error}; #[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")] pub use self::methods::encode_utf16_raw; // perma-unstable #[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")] -pub use self::methods::encode_utf8_raw; // perma-unstable +pub use self::methods::{encode_utf8_raw, encode_utf8_raw_unchecked}; // perma-unstable #[rustfmt::skip] use crate::ascii; diff --git a/tests/codegen/string-push.rs b/tests/codegen/string-push.rs new file mode 100644 index 000000000000..cf5f6bb1aa39 --- /dev/null +++ b/tests/codegen/string-push.rs @@ -0,0 +1,11 @@ +//! Check that `String::push` is optimized enough not to call `memcpy`. + +//@ compile-flags: -O +#![crate_type = "lib"] + +// CHECK-LABEL: @string_push_does_not_call_memcpy +#[no_mangle] +pub fn string_push_does_not_call_memcpy(s: &mut String, ch: char) { + // CHECK-NOT: call void @llvm.memcpy + s.push(ch); +} From ff248de852c46fc0fccd31e466b1f2137381d1d6 Mon Sep 17 00:00:00 2001 From: lincot Date: Tue, 8 Apr 2025 17:20:00 +0300 Subject: [PATCH 253/606] Add missing `black_box` in `String` benchmarks --- library/alloctests/benches/string.rs | 48 +++++++++++++--------------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/library/alloctests/benches/string.rs b/library/alloctests/benches/string.rs index 3d79ab78c695..0bbec12e4fdc 100644 --- a/library/alloctests/benches/string.rs +++ b/library/alloctests/benches/string.rs @@ -4,7 +4,7 @@ use test::{Bencher, black_box}; #[bench] fn bench_with_capacity(b: &mut Bencher) { - b.iter(|| String::with_capacity(100)); + b.iter(|| String::with_capacity(black_box(100))); } #[bench] @@ -12,7 +12,8 @@ fn bench_push_str(b: &mut Bencher) { let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb"; b.iter(|| { let mut r = String::new(); - r.push_str(s); + black_box(&mut r).push_str(black_box(s)); + r }); } @@ -24,8 +25,9 @@ fn bench_push_str_one_byte(b: &mut Bencher) { b.iter(|| { let mut r = String::new(); for _ in 0..REPETITIONS { - r.push_str("a") + black_box(&mut r).push_str(black_box("a")); } + r }); } @@ -35,8 +37,9 @@ fn bench_push_char_one_byte(b: &mut Bencher) { b.iter(|| { let mut r = String::new(); for _ in 0..REPETITIONS { - r.push('a') + black_box(&mut r).push(black_box('a')); } + r }); } @@ -46,8 +49,9 @@ fn bench_push_char_two_bytes(b: &mut Bencher) { b.iter(|| { let mut r = String::new(); for _ in 0..REPETITIONS { - r.push('â') + black_box(&mut r).push(black_box('â')); } + r }); } @@ -57,34 +61,26 @@ fn from_utf8_lossy_100_ascii(b: &mut Bencher) { Lorem ipsum dolor sit amet, consectetur. "; assert_eq!(100, s.len()); - b.iter(|| { - let _ = String::from_utf8_lossy(s); - }); + b.iter(|| String::from_utf8_lossy(black_box(s))); } #[bench] fn from_utf8_lossy_100_multibyte(b: &mut Bencher) { let s = "𐌀𐌖𐌋𐌄𐌑𐌉ปรدولة الكويتทศไทย中华𐍅𐌿𐌻𐍆𐌹𐌻𐌰".as_bytes(); assert_eq!(100, s.len()); - b.iter(|| { - let _ = String::from_utf8_lossy(s); - }); + b.iter(|| String::from_utf8_lossy(black_box(s))); } #[bench] fn from_utf8_lossy_invalid(b: &mut Bencher) { let s = b"Hello\xC0\x80 There\xE6\x83 Goodbye"; - b.iter(|| { - let _ = String::from_utf8_lossy(s); - }); + b.iter(|| String::from_utf8_lossy(black_box(s))); } #[bench] fn from_utf8_lossy_100_invalid(b: &mut Bencher) { let s = repeat(0xf5).take(100).collect::>(); - b.iter(|| { - let _ = String::from_utf8_lossy(&s); - }); + b.iter(|| String::from_utf8_lossy(black_box(&s))); } #[bench] @@ -96,8 +92,8 @@ fn bench_exact_size_shrink_to_fit(b: &mut Bencher) { r.push_str(s); assert_eq!(r.len(), r.capacity()); b.iter(|| { - let mut r = String::with_capacity(s.len()); - r.push_str(s); + let mut r = String::with_capacity(black_box(s.len())); + r.push_str(black_box(s)); r.shrink_to_fit(); r }); @@ -107,21 +103,21 @@ fn bench_exact_size_shrink_to_fit(b: &mut Bencher) { fn bench_from_str(b: &mut Bencher) { let s = "Hello there, the quick brown fox jumped over the lazy dog! \ Lorem ipsum dolor sit amet, consectetur. "; - b.iter(|| String::from(s)) + b.iter(|| String::from(black_box(s))) } #[bench] fn bench_from(b: &mut Bencher) { let s = "Hello there, the quick brown fox jumped over the lazy dog! \ Lorem ipsum dolor sit amet, consectetur. "; - b.iter(|| String::from(s)) + b.iter(|| String::from(black_box(s))) } #[bench] fn bench_to_string(b: &mut Bencher) { let s = "Hello there, the quick brown fox jumped over the lazy dog! \ Lorem ipsum dolor sit amet, consectetur. "; - b.iter(|| s.to_string()) + b.iter(|| black_box(s).to_string()) } #[bench] @@ -129,7 +125,7 @@ fn bench_insert_char_short(b: &mut Bencher) { let s = "Hello, World!"; b.iter(|| { let mut x = String::from(s); - black_box(&mut x).insert(6, black_box(' ')); + black_box(&mut x).insert(black_box(6), black_box(' ')); x }) } @@ -139,7 +135,7 @@ fn bench_insert_char_long(b: &mut Bencher) { let s = "Hello, World!"; b.iter(|| { let mut x = String::from(s); - black_box(&mut x).insert(6, black_box('❤')); + black_box(&mut x).insert(black_box(6), black_box('❤')); x }) } @@ -149,7 +145,7 @@ fn bench_insert_str_short(b: &mut Bencher) { let s = "Hello, World!"; b.iter(|| { let mut x = String::from(s); - black_box(&mut x).insert_str(6, black_box(" ")); + black_box(&mut x).insert_str(black_box(6), black_box(" ")); x }) } @@ -159,7 +155,7 @@ fn bench_insert_str_long(b: &mut Bencher) { let s = "Hello, World!"; b.iter(|| { let mut x = String::from(s); - black_box(&mut x).insert_str(6, black_box(" rustic ")); + black_box(&mut x).insert_str(black_box(6), black_box(" rustic ")); x }) } From 72d17bfebbf5463dac1a7eb71c513b151b523e1f Mon Sep 17 00:00:00 2001 From: David Wood Date: Tue, 18 Mar 2025 03:06:17 +0000 Subject: [PATCH 254/606] re-use sized fast path There's an existing fast path for the `type_op_prove_predicate` predicate, checking for trivially `Sized` types, which can be re-used when evaluating obligations within queries. This should improve performance, particularly in anticipation of new sizedness traits being added which can take advantage of this. --- compiler/rustc_middle/src/ty/sty.rs | 14 +++++++------- .../src/traits/fulfill.rs | 6 +++++- .../rustc_trait_selection/src/traits/mod.rs | 4 ++-- .../traits/query/type_op/prove_predicate.rs | 13 ++----------- .../src/traits/select/mod.rs | 8 +++++++- .../rustc_trait_selection/src/traits/util.rs | 19 +++++++++++++++++++ compiler/rustc_traits/src/codegen.rs | 11 +++++++++-- .../rustc_traits/src/evaluate_obligation.rs | 5 +++++ tests/ui/closures/issue-78720.rs | 1 + tests/ui/closures/issue-78720.stderr | 16 +++++++++++----- tests/ui/codegen/overflow-during-mono.rs | 2 +- tests/ui/codegen/overflow-during-mono.stderr | 2 +- 12 files changed, 70 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 27ee363f1c14..e17088799465 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1872,14 +1872,14 @@ impl<'tcx> Ty<'tcx> { /// Fast path helper for testing if a type is `Sized`. /// - /// Returning true means the type is known to be sized. Returning - /// `false` means nothing -- could be sized, might not be. + /// Returning true means the type is known to implement `Sized`. Returning `false` means + /// nothing -- could be sized, might not be. /// - /// Note that we could never rely on the fact that a type such as `[_]` is - /// trivially `!Sized` because we could be in a type environment with a - /// bound such as `[_]: Copy`. A function with such a bound obviously never - /// can be called, but that doesn't mean it shouldn't typecheck. This is why - /// this method doesn't return `Option`. + /// Note that we could never rely on the fact that a type such as `[_]` is trivially `!Sized` + /// because we could be in a type environment with a bound such as `[_]: Copy`. A function with + /// such a bound obviously never can be called, but that doesn't mean it shouldn't typecheck. + /// This is why this method doesn't return `Option`. + #[instrument(skip(tcx), level = "debug")] pub fn is_trivially_sized(self, tcx: TyCtxt<'tcx>) -> bool { match self.kind() { ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index e98a240a53f5..1b76d48e4310 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -24,10 +24,10 @@ use super::{ }; use crate::error_reporting::InferCtxtErrorExt; use crate::infer::{InferCtxt, TyOrConstInferVar}; -use crate::traits::EvaluateConstErr; use crate::traits::normalize::normalize_with_depth_to; use crate::traits::project::{PolyProjectionObligation, ProjectionCacheKeyExt as _}; use crate::traits::query::evaluate_obligation::InferCtxtExt; +use crate::traits::{EvaluateConstErr, sizedness_fast_path}; pub(crate) type PendingPredicateObligations<'tcx> = ThinVec>; @@ -335,6 +335,10 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { let infcx = self.selcx.infcx; + if sizedness_fast_path(infcx.tcx, obligation.predicate) { + return ProcessResult::Changed(thin_vec::thin_vec![]); + } + if obligation.predicate.has_aliases() { let mut obligations = PredicateObligations::new(); let predicate = normalize_with_depth_to( diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index de337710b5ef..f2713b98f0a2 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -65,8 +65,8 @@ pub use self::specialize::{ pub use self::structural_normalize::StructurallyNormalizeExt; pub use self::util::{ BoundVarReplacer, PlaceholderReplacer, elaborate, expand_trait_aliases, impl_item_is_final, - supertrait_def_ids, supertraits, transitive_bounds_that_define_assoc_item, upcast_choices, - with_replaced_escaping_bound_vars, + sizedness_fast_path, supertrait_def_ids, supertraits, transitive_bounds_that_define_assoc_item, + upcast_choices, with_replaced_escaping_bound_vars, }; use crate::error_reporting::InferCtxtErrorExt; use crate::infer::outlives::env::OutlivesEnvironment; diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs index 4f9e2e79d624..87fc532adaf6 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs @@ -1,4 +1,3 @@ -use rustc_hir::LangItem; use rustc_infer::traits::Obligation; use rustc_middle::traits::ObligationCause; use rustc_middle::traits::query::NoSolution; @@ -7,7 +6,7 @@ use rustc_middle::ty::{self, ParamEnvAnd, TyCtxt}; use rustc_span::Span; use crate::infer::canonical::{CanonicalQueryInput, CanonicalQueryResponse}; -use crate::traits::ObligationCtxt; +use crate::traits::{ObligationCtxt, sizedness_fast_path}; impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> { type QueryResponse = (); @@ -16,15 +15,7 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> { tcx: TyCtxt<'tcx>, key: &ParamEnvAnd<'tcx, Self>, ) -> Option { - // Proving Sized, very often on "obviously sized" types like - // `&T`, accounts for about 60% percentage of the predicates - // we have to prove. No need to canonicalize and all that for - // such cases. - if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_ref)) = - key.value.predicate.kind().skip_binder() - && tcx.is_lang_item(trait_ref.def_id(), LangItem::Sized) - && trait_ref.self_ty().is_trivially_sized(tcx) - { + if sizedness_fast_path(tcx, key.value.predicate) { return Some(()); } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 56ff46e89e70..4d88a23250a7 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -49,7 +49,9 @@ use crate::infer::{InferCtxt, InferOk, TypeFreshener}; use crate::solve::InferCtxtSelectExt as _; use crate::traits::normalize::{normalize_with_depth, normalize_with_depth_to}; use crate::traits::project::{ProjectAndUnifyResult, ProjectionCacheKeyExt}; -use crate::traits::{EvaluateConstErr, ProjectionCacheKey, Unimplemented, effects}; +use crate::traits::{ + EvaluateConstErr, ProjectionCacheKey, Unimplemented, effects, sizedness_fast_path, +}; mod _match; mod candidate_assembly; @@ -603,6 +605,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { None => self.check_recursion_limit(&obligation, &obligation)?, } + if sizedness_fast_path(self.tcx(), obligation.predicate) { + return Ok(EvaluatedToOk); + } + ensure_sufficient_stack(|| { let bound_predicate = obligation.predicate.kind(); match bound_predicate.skip_binder() { diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index 9f20cd7eacb4..035fd38c48aa 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -1,6 +1,7 @@ use std::collections::{BTreeMap, VecDeque}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; +use rustc_hir::LangItem; use rustc_hir::def_id::DefId; use rustc_infer::infer::InferCtxt; pub use rustc_infer::traits::util::*; @@ -504,3 +505,21 @@ impl<'tcx> TypeFolder> for PlaceholderReplacer<'_, 'tcx> { } } } + +pub fn sizedness_fast_path<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tcx>) -> bool { + // Proving `Sized` very often on "obviously sized" types like `&T`, accounts for about 60% + // percentage of the predicates we have to prove. No need to canonicalize and all that for + // such cases. + if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_ref)) = + predicate.kind().skip_binder() + { + if tcx.is_lang_item(trait_ref.def_id(), LangItem::Sized) + && trait_ref.self_ty().is_trivially_sized(tcx) + { + debug!("fast path -- trivial sizedness"); + return true; + } + } + + false +} diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs index 4a889abfc28f..88f02d16c7d5 100644 --- a/compiler/rustc_traits/src/codegen.rs +++ b/compiler/rustc_traits/src/codegen.rs @@ -6,11 +6,11 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::bug; use rustc_middle::traits::CodegenObligationError; -use rustc_middle::ty::{self, PseudoCanonicalInput, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, PseudoCanonicalInput, TyCtxt, TypeVisitableExt, Upcast}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::traits::{ ImplSource, Obligation, ObligationCause, ObligationCtxt, ScrubbedTraitError, SelectionContext, - Unimplemented, + Unimplemented, sizedness_fast_path, }; use tracing::debug; @@ -34,6 +34,13 @@ pub(crate) fn codegen_select_candidate<'tcx>( let (infcx, param_env) = tcx.infer_ctxt().ignoring_regions().build_with_typing_env(typing_env); let mut selcx = SelectionContext::new(&infcx); + if sizedness_fast_path(tcx, trait_ref.upcast(tcx)) { + return Ok(&*tcx.arena.alloc(ImplSource::Builtin( + ty::solve::BuiltinImplSource::Trivial, + Default::default(), + ))); + } + let obligation_cause = ObligationCause::dummy(); let obligation = Obligation::new(tcx, obligation_cause, param_env, trait_ref); diff --git a/compiler/rustc_traits/src/evaluate_obligation.rs b/compiler/rustc_traits/src/evaluate_obligation.rs index c9ad096c6e9d..7771db855d70 100644 --- a/compiler/rustc_traits/src/evaluate_obligation.rs +++ b/compiler/rustc_traits/src/evaluate_obligation.rs @@ -5,6 +5,7 @@ use rustc_span::DUMMY_SP; use rustc_trait_selection::traits::query::CanonicalPredicateGoal; use rustc_trait_selection::traits::{ EvaluationResult, Obligation, ObligationCause, OverflowError, SelectionContext, TraitQueryMode, + sizedness_fast_path, }; use tracing::debug; @@ -23,6 +24,10 @@ fn evaluate_obligation<'tcx>( debug!("evaluate_obligation: goal={:#?}", goal); let ParamEnvAnd { param_env, value: predicate } = goal; + if sizedness_fast_path(tcx, predicate) { + return Ok(EvaluationResult::EvaluatedToOk); + } + let mut selcx = SelectionContext::with_query_mode(infcx, TraitQueryMode::Canonical); let obligation = Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate); diff --git a/tests/ui/closures/issue-78720.rs b/tests/ui/closures/issue-78720.rs index 81af030fe556..a615cdf26902 100644 --- a/tests/ui/closures/issue-78720.rs +++ b/tests/ui/closures/issue-78720.rs @@ -1,5 +1,6 @@ fn server() -> impl { //~^ ERROR at least one trait must be specified + //~^^ ERROR type annotations needed ().map2(|| "") } diff --git a/tests/ui/closures/issue-78720.stderr b/tests/ui/closures/issue-78720.stderr index 90672cd83d7c..3e95fab441ad 100644 --- a/tests/ui/closures/issue-78720.stderr +++ b/tests/ui/closures/issue-78720.stderr @@ -5,7 +5,7 @@ LL | fn server() -> impl { | ^^^^ error[E0412]: cannot find type `F` in this scope - --> $DIR/issue-78720.rs:13:12 + --> $DIR/issue-78720.rs:14:12 | LL | _func: F, | ^ @@ -22,8 +22,14 @@ help: you might be missing a type parameter LL | struct Map2 { | +++ +error[E0282]: type annotations needed + --> $DIR/issue-78720.rs:1:16 + | +LL | fn server() -> impl { + | ^^^^ cannot infer type + error[E0308]: mismatched types - --> $DIR/issue-78720.rs:7:39 + --> $DIR/issue-78720.rs:8:39 | LL | fn map2(self, f: F) -> Map2 {} | ^^ expected `Map2`, found `()` @@ -32,7 +38,7 @@ LL | fn map2(self, f: F) -> Map2 {} found unit type `()` error[E0277]: the size for values of type `Self` cannot be known at compilation time - --> $DIR/issue-78720.rs:7:16 + --> $DIR/issue-78720.rs:8:16 | LL | fn map2(self, f: F) -> Map2 {} | ^^^^ doesn't have a size known at compile-time @@ -47,7 +53,7 @@ help: function arguments must have a statically known size, borrowed types alway LL | fn map2(&self, f: F) -> Map2 {} | + -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors -Some errors have detailed explanations: E0277, E0308, E0412. +Some errors have detailed explanations: E0277, E0282, E0308, E0412. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/codegen/overflow-during-mono.rs b/tests/ui/codegen/overflow-during-mono.rs index 83a8b6b3ef6a..a9045840173e 100644 --- a/tests/ui/codegen/overflow-during-mono.rs +++ b/tests/ui/codegen/overflow-during-mono.rs @@ -1,4 +1,4 @@ -//~ ERROR overflow evaluating the requirement `{closure@$DIR/overflow-during-mono.rs:13:41: 13:44}: Sized` +//~ ERROR overflow evaluating the requirement `for<'a> {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}: FnMut(&'a _)` //@ build-fail #![recursion_limit = "32"] diff --git a/tests/ui/codegen/overflow-during-mono.stderr b/tests/ui/codegen/overflow-during-mono.stderr index f7a3e2df3dba..74d98fde285b 100644 --- a/tests/ui/codegen/overflow-during-mono.stderr +++ b/tests/ui/codegen/overflow-during-mono.stderr @@ -1,4 +1,4 @@ -error[E0275]: overflow evaluating the requirement `{closure@$DIR/overflow-during-mono.rs:13:41: 13:44}: Sized` +error[E0275]: overflow evaluating the requirement `for<'a> {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}: FnMut(&'a _)` | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "64"]` attribute to your crate (`overflow_during_mono`) = note: required for `Filter, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>` to implement `Iterator` From 069fd0258853a0511bfa202a7983abffbae16115 Mon Sep 17 00:00:00 2001 From: timesince Date: Wed, 9 Apr 2025 18:46:50 +0800 Subject: [PATCH 255/606] Remove redundant words --- compiler/rustc_abi/src/lib.rs | 2 +- library/core/src/clone.rs | 2 +- src/doc/rustc-dev-guide/src/solve/opaque-types.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 843d5ca61ddd..59b74d292214 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1829,7 +1829,7 @@ pub struct PointeeInfo { pub safe: Option, /// If `safe` is `Some`, then the pointer is either null or dereferenceable for this many bytes. /// On a function argument, "dereferenceable" here means "dereferenceable for the entire duration - /// of this function call", i.e. it is UB for the memory that this pointer points to to be freed + /// of this function call", i.e. it is UB for the memory that this pointer points to be freed /// while this function is still running. /// The size can be zero if the pointer is not dereferenceable. pub size: Size, diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs index e0ac0bfc5289..647463098610 100644 --- a/library/core/src/clone.rs +++ b/library/core/src/clone.rs @@ -427,7 +427,7 @@ pub unsafe trait CloneToUninit { /// read or dropped, because even if it was previously valid, it may have been partially /// overwritten. /// - /// The caller may wish to to take care to deallocate the allocation pointed to by `dest`, + /// The caller may wish to take care to deallocate the allocation pointed to by `dest`, /// if applicable, to avoid a memory leak (but this is not a requirement). /// /// Implementors should avoid leaking values by, upon unwinding, dropping all component values diff --git a/src/doc/rustc-dev-guide/src/solve/opaque-types.md b/src/doc/rustc-dev-guide/src/solve/opaque-types.md index 672aab770801..509c34a4d3a7 100644 --- a/src/doc/rustc-dev-guide/src/solve/opaque-types.md +++ b/src/doc/rustc-dev-guide/src/solve/opaque-types.md @@ -33,7 +33,7 @@ For opaque types in the defining scope and in the implicit-negative coherence mo always done in two steps. Outside of the defining scope `normalizes-to` for opaques always returns `Err(NoSolution)`. -We start by trying to to assign the expected type as a hidden type. +We start by trying to assign the expected type as a hidden type. In the implicit-negative coherence mode, this currently always results in ambiguity without interacting with the opaque types storage. We could instead add allow 'defining' all opaque types, From a6c2ec04b456d600b42b0c7286af38044f19a9a6 Mon Sep 17 00:00:00 2001 From: Boxy Date: Mon, 31 Mar 2025 18:09:32 +0100 Subject: [PATCH 256/606] replace version placeholder --- compiler/rustc_feature/src/accepted.rs | 4 ++-- compiler/rustc_feature/src/removed.rs | 2 +- compiler/rustc_feature/src/unstable.rs | 10 +++++----- library/alloc/src/boxed.rs | 2 +- library/alloc/src/collections/linked_list.rs | 8 ++++---- library/alloc/src/string.rs | 20 ++++++++++---------- library/alloc/src/vec/extract_if.rs | 6 +++--- library/alloc/src/vec/mod.rs | 18 +++++++++--------- library/core/src/char/methods.rs | 4 ++-- library/core/src/net/socket_addr.rs | 16 ++++++++-------- library/core/src/num/int_macros.rs | 12 ++++++------ library/core/src/num/mod.rs | 8 ++++---- library/core/src/num/nonzero.rs | 8 ++++---- library/core/src/num/uint_macros.rs | 16 ++++++++-------- library/core/src/ptr/const_ptr.rs | 8 ++++---- library/core/src/ptr/mut_ptr.rs | 8 ++++---- library/core/src/ptr/non_null.rs | 8 ++++---- library/core/src/slice/mod.rs | 18 +++++++++--------- library/core/src/str/converts.rs | 2 +- library/core/src/str/mod.rs | 16 ++++++++-------- library/std/src/collections/hash/map.rs | 10 +++++----- library/std/src/collections/hash/set.rs | 10 +++++----- library/std/src/ffi/mod.rs | 2 +- library/std/src/ffi/os_str.rs | 8 ++++---- library/std/src/io/error.rs | 2 +- library/std/src/io/mod.rs | 2 +- library/std/src/io/pipe.rs | 18 +++++++++--------- library/std/src/os/fd/owned.rs | 12 ++++++------ library/std/src/os/fd/raw.rs | 12 ++++++------ library/std/src/os/windows/io/handle.rs | 12 ++++++------ library/std/src/os/windows/io/raw.rs | 12 ++++++------ library/std/src/process.rs | 4 ++-- 32 files changed, 149 insertions(+), 149 deletions(-) diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 88e6593572bc..8968c1771e4c 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -63,7 +63,7 @@ declare_features! ( /// Allows using `const` operands in inline assembly. (accepted, asm_const, "1.82.0", Some(93332)), /// Allows using `label` operands in inline assembly. - (accepted, asm_goto, "CURRENT_RUSTC_VERSION", Some(119364)), + (accepted, asm_goto, "1.87.0", Some(119364)), /// Allows using `sym` operands in inline assembly. (accepted, asm_sym, "1.66.0", Some(93333)), /// Allows the definition of associated constants in `trait` or `impl` blocks. @@ -332,7 +332,7 @@ declare_features! ( /// Allows `use<'a, 'b, A, B>` in `impl Trait + use<...>` for precise capture of generic args. (accepted, precise_capturing, "1.82.0", Some(123432)), /// Allows `use<..>` precise capturign on impl Trait in traits. - (accepted, precise_capturing_in_traits, "CURRENT_RUSTC_VERSION", Some(130044)), + (accepted, precise_capturing_in_traits, "1.87.0", Some(130044)), /// Allows procedural macros in `proc-macro` crates. (accepted, proc_macro, "1.29.0", Some(38356)), /// Allows multi-segment paths in attributes and derives. diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index 6ba7b22a0dff..402e18c5d148 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -247,7 +247,7 @@ declare_features! ( /// Allows unnamed fields of struct and union type (removed, unnamed_fields, "1.83.0", Some(49804), Some("feature needs redesign")), (removed, unsafe_no_drop_flag, "1.0.0", None, None), - (removed, unsized_tuple_coercion, "CURRENT_RUSTC_VERSION", Some(42877), + (removed, unsized_tuple_coercion, "1.87.0", Some(42877), Some("The feature restricts possible layouts for tuples, and this restriction is not worth it.")), /// Allows `union` fields that don't implement `Copy` as long as they don't have any drop glue. (removed, untagged_unions, "1.13.0", Some(55149), diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 7edb05c7307b..98213affc5bf 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -474,7 +474,7 @@ declare_features! ( /// Allows `dyn* Trait` objects. (incomplete, dyn_star, "1.65.0", Some(102425)), /// Allows the .use postfix syntax `x.use` and use closures `use |x| { ... }` - (incomplete, ergonomic_clones, "CURRENT_RUSTC_VERSION", Some(132290)), + (incomplete, ergonomic_clones, "1.87.0", Some(132290)), /// Allows exhaustive pattern matching on types that contain uninhabited types. (unstable, exhaustive_patterns, "1.13.0", Some(51085)), /// Allows explicit tail calls via `become` expression. @@ -511,7 +511,7 @@ declare_features! ( /// Allows generic parameters and where-clauses on free & associated const items. (incomplete, generic_const_items, "1.73.0", Some(113521)), /// Allows the type of const generics to depend on generic parameters - (incomplete, generic_const_parameter_types, "CURRENT_RUSTC_VERSION", Some(137626)), + (incomplete, generic_const_parameter_types, "1.87.0", Some(137626)), /// Allows any generic constants being used as pattern type range ends (incomplete, generic_pattern_types, "1.86.0", Some(136574)), /// Allows registering static items globally, possibly across crates, to iterate over at runtime. @@ -602,7 +602,7 @@ declare_features! ( /// Allows macro attributes on expressions, statements and non-inline modules. (unstable, proc_macro_hygiene, "1.30.0", Some(54727)), /// Allows the use of raw-dylibs on ELF platforms - (incomplete, raw_dylib_elf, "CURRENT_RUSTC_VERSION", Some(135694)), + (incomplete, raw_dylib_elf, "1.87.0", Some(135694)), /// Makes `&` and `&mut` patterns eat only one layer of references in Rust 2024. (incomplete, ref_pat_eat_one_layer_2024, "1.79.0", Some(123076)), /// Makes `&` and `&mut` patterns eat only one layer of references in Rust 2024—structural variant @@ -664,14 +664,14 @@ declare_features! ( /// Allows using the `#[used(linker)]` (or `#[used(compiler)]`) attribute. (unstable, used_with_arg, "1.60.0", Some(93798)), /// Allows use of attributes in `where` clauses. - (unstable, where_clause_attrs, "CURRENT_RUSTC_VERSION", Some(115590)), + (unstable, where_clause_attrs, "1.87.0", Some(115590)), /// Allows use of x86 `AMX` target-feature attributes and intrinsics (unstable, x86_amx_intrinsics, "1.81.0", Some(126622)), /// Allows use of the `xop` target-feature (unstable, xop_target_feature, "1.81.0", Some(127208)), /// Allows `do yeet` expressions (unstable, yeet_expr, "1.62.0", Some(96373)), - (unstable, yield_expr, "CURRENT_RUSTC_VERSION", Some(43122)), + (unstable, yield_expr, "1.87.0", Some(43122)), // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! // Features are listed in alphabetical order. Tidy will fail if you don't keep it this way. // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 4644e37f809c..4536f5554435 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -952,7 +952,7 @@ impl Box, A> { /// assert_eq!(*x, i); /// } /// ``` - #[stable(feature = "box_uninit_write", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "box_uninit_write", since = "1.87.0")] #[inline] pub fn write(mut boxed: Self, value: T) -> Box { unsafe { diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs index 3183268b4b32..cc42a120e4fa 100644 --- a/library/alloc/src/collections/linked_list.rs +++ b/library/alloc/src/collections/linked_list.rs @@ -1151,7 +1151,7 @@ impl LinkedList { /// assert_eq!(evens.into_iter().collect::>(), vec![2, 4, 6, 8, 14]); /// assert_eq!(odds.into_iter().collect::>(), vec![1, 3, 5, 9, 11, 13, 15]); /// ``` - #[stable(feature = "extract_if", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "extract_if", since = "1.87.0")] pub fn extract_if(&mut self, filter: F) -> ExtractIf<'_, T, F, A> where F: FnMut(&mut T) -> bool, @@ -1931,7 +1931,7 @@ impl<'a, T, A: Allocator> CursorMut<'a, T, A> { } /// An iterator produced by calling `extract_if` on LinkedList. -#[stable(feature = "extract_if", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "extract_if", since = "1.87.0")] #[must_use = "iterators are lazy and do nothing unless consumed"] pub struct ExtractIf< 'a, @@ -1946,7 +1946,7 @@ pub struct ExtractIf< old_len: usize, } -#[stable(feature = "extract_if", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "extract_if", since = "1.87.0")] impl Iterator for ExtractIf<'_, T, F, A> where F: FnMut(&mut T) -> bool, @@ -1975,7 +1975,7 @@ where } } -#[stable(feature = "extract_if", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "extract_if", since = "1.87.0")] impl fmt::Debug for ExtractIf<'_, T, F> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("ExtractIf").field(&self.list).finish() diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 9236f5cb8d1f..32f1d0fde809 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -1043,7 +1043,7 @@ impl String { #[inline] #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_vec_string_slice", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_vec_string_slice", since = "1.87.0")] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] pub const fn into_bytes(self) -> Vec { self.vec @@ -1062,7 +1062,7 @@ impl String { #[must_use] #[stable(feature = "string_as_str", since = "1.7.0")] #[rustc_diagnostic_item = "string_as_str"] - #[rustc_const_stable(feature = "const_vec_string_slice", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_vec_string_slice", since = "1.87.0")] pub const fn as_str(&self) -> &str { // SAFETY: String contents are stipulated to be valid UTF-8, invalid contents are an error // at construction. @@ -1085,7 +1085,7 @@ impl String { #[must_use] #[stable(feature = "string_as_str", since = "1.7.0")] #[rustc_diagnostic_item = "string_as_mut_str"] - #[rustc_const_stable(feature = "const_vec_string_slice", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_vec_string_slice", since = "1.87.0")] pub const fn as_mut_str(&mut self) -> &mut str { // SAFETY: String contents are stipulated to be valid UTF-8, invalid contents are an error // at construction. @@ -1134,7 +1134,7 @@ impl String { /// assert_eq!(string, "abcdecdeabecde"); /// ``` #[cfg(not(no_global_oom_handling))] - #[stable(feature = "string_extend_from_within", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "string_extend_from_within", since = "1.87.0")] pub fn extend_from_within(&mut self, src: R) where R: RangeBounds, @@ -1159,7 +1159,7 @@ impl String { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_vec_string_slice", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_vec_string_slice", since = "1.87.0")] pub const fn capacity(&self) -> usize { self.vec.capacity() } @@ -1425,7 +1425,7 @@ impl String { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_vec_string_slice", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_vec_string_slice", since = "1.87.0")] pub const fn as_bytes(&self) -> &[u8] { self.vec.as_slice() } @@ -1779,7 +1779,7 @@ impl String { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_vec_string_slice", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_vec_string_slice", since = "1.87.0")] pub const unsafe fn as_mut_vec(&mut self) -> &mut Vec { &mut self.vec } @@ -1801,7 +1801,7 @@ impl String { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_vec_string_slice", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_vec_string_slice", since = "1.87.0")] #[rustc_confusables("length", "size")] pub const fn len(&self) -> usize { self.vec.len() @@ -1821,7 +1821,7 @@ impl String { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_vec_string_slice", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_vec_string_slice", since = "1.87.0")] pub const fn is_empty(&self) -> bool { self.len() == 0 } @@ -3140,7 +3140,7 @@ impl From for Vec { } } -#[stable(feature = "try_from_vec_u8_for_string", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "try_from_vec_u8_for_string", since = "1.87.0")] impl TryFrom> for String { type Error = FromUtf8Error; /// Converts the given [`Vec`] into a [`String`] if it contains valid UTF-8 data. diff --git a/library/alloc/src/vec/extract_if.rs b/library/alloc/src/vec/extract_if.rs index be869553ef4e..8a591a877964 100644 --- a/library/alloc/src/vec/extract_if.rs +++ b/library/alloc/src/vec/extract_if.rs @@ -15,7 +15,7 @@ use crate::alloc::{Allocator, Global}; /// let mut v = vec![0, 1, 2]; /// let iter: std::vec::ExtractIf<'_, _, _> = v.extract_if(.., |x| *x % 2 == 0); /// ``` -#[stable(feature = "extract_if", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "extract_if", since = "1.87.0")] #[derive(Debug)] #[must_use = "iterators are lazy and do nothing unless consumed"] pub struct ExtractIf< @@ -57,7 +57,7 @@ impl<'a, T, F, A: Allocator> ExtractIf<'a, T, F, A> { } } -#[stable(feature = "extract_if", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "extract_if", since = "1.87.0")] impl Iterator for ExtractIf<'_, T, F, A> where F: FnMut(&mut T) -> bool, @@ -93,7 +93,7 @@ where } } -#[stable(feature = "extract_if", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "extract_if", since = "1.87.0")] impl Drop for ExtractIf<'_, T, F, A> { fn drop(&mut self) { unsafe { diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index e6867febf6c6..68e4add30e5d 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -66,7 +66,7 @@ use core::ptr::{self, NonNull}; use core::slice::{self, SliceIndex}; use core::{fmt, intrinsics}; -#[stable(feature = "extract_if", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "extract_if", since = "1.87.0")] pub use self::extract_if::ExtractIf; use crate::alloc::{Allocator, Global}; use crate::borrow::{Cow, ToOwned}; @@ -1267,7 +1267,7 @@ impl Vec { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_vec_string_slice", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_vec_string_slice", since = "1.87.0")] pub const fn capacity(&self) -> usize { self.buf.capacity() } @@ -1582,7 +1582,7 @@ impl Vec { #[inline] #[stable(feature = "vec_as_slice", since = "1.7.0")] #[rustc_diagnostic_item = "vec_as_slice"] - #[rustc_const_stable(feature = "const_vec_string_slice", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_vec_string_slice", since = "1.87.0")] pub const fn as_slice(&self) -> &[T] { // SAFETY: `slice::from_raw_parts` requires pointee is a contiguous, aligned buffer of size // `len` containing properly-initialized `T`s. Data must not be mutated for the returned @@ -1614,7 +1614,7 @@ impl Vec { #[inline] #[stable(feature = "vec_as_slice", since = "1.7.0")] #[rustc_diagnostic_item = "vec_as_mut_slice"] - #[rustc_const_stable(feature = "const_vec_string_slice", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_vec_string_slice", since = "1.87.0")] pub const fn as_mut_slice(&mut self) -> &mut [T] { // SAFETY: `slice::from_raw_parts_mut` requires pointee is a contiguous, aligned buffer of // size `len` containing properly-initialized `T`s. Data must not be accessed through any @@ -1686,7 +1686,7 @@ impl Vec { /// [`as_ptr`]: Vec::as_ptr /// [`as_non_null`]: Vec::as_non_null #[stable(feature = "vec_as_ptr", since = "1.37.0")] - #[rustc_const_stable(feature = "const_vec_string_slice", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_vec_string_slice", since = "1.87.0")] #[rustc_never_returns_null_ptr] #[rustc_as_ptr] #[inline] @@ -1749,7 +1749,7 @@ impl Vec { /// [`as_ptr`]: Vec::as_ptr /// [`as_non_null`]: Vec::as_non_null #[stable(feature = "vec_as_ptr", since = "1.37.0")] - #[rustc_const_stable(feature = "const_vec_string_slice", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_vec_string_slice", since = "1.87.0")] #[rustc_never_returns_null_ptr] #[rustc_as_ptr] #[inline] @@ -2700,7 +2700,7 @@ impl Vec { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_vec_string_slice", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_vec_string_slice", since = "1.87.0")] #[rustc_confusables("length", "size")] pub const fn len(&self) -> usize { let len = self.len; @@ -2726,7 +2726,7 @@ impl Vec { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "vec_is_empty"] - #[rustc_const_stable(feature = "const_vec_string_slice", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_vec_string_slice", since = "1.87.0")] pub const fn is_empty(&self) -> bool { self.len() == 0 } @@ -3715,7 +3715,7 @@ impl Vec { /// assert_eq!(items, vec![0, 0, 0, 0, 0, 0, 0, 2, 2, 2]); /// assert_eq!(ones.len(), 3); /// ``` - #[stable(feature = "extract_if", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "extract_if", since = "1.87.0")] pub fn extract_if(&mut self, range: R, filter: F) -> ExtractIf<'_, T, F, A> where F: FnMut(&mut T) -> bool, diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index fa584953bed5..c575e08c54ad 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -337,7 +337,7 @@ impl char { /// '1'.is_digit(1); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_char_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_char_classify", since = "1.87.0")] #[inline] pub const fn is_digit(self, radix: u32) -> bool { self.to_digit(radix).is_some() @@ -886,7 +886,7 @@ impl char { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_char_classify", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_char_classify", since = "1.87.0")] #[inline] pub const fn is_whitespace(self) -> bool { match self { diff --git a/library/core/src/net/socket_addr.rs b/library/core/src/net/socket_addr.rs index 21753d009249..936f9f64930d 100644 --- a/library/core/src/net/socket_addr.rs +++ b/library/core/src/net/socket_addr.rs @@ -210,7 +210,7 @@ impl SocketAddr { /// ``` #[inline] #[stable(feature = "sockaddr_setters", since = "1.9.0")] - #[rustc_const_stable(feature = "const_sockaddr_setters", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_sockaddr_setters", since = "1.87.0")] pub const fn set_ip(&mut self, new_ip: IpAddr) { // `match (*self, new_ip)` would have us mutate a copy of self only to throw it away. match (self, new_ip) { @@ -254,7 +254,7 @@ impl SocketAddr { /// ``` #[inline] #[stable(feature = "sockaddr_setters", since = "1.9.0")] - #[rustc_const_stable(feature = "const_sockaddr_setters", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_sockaddr_setters", since = "1.87.0")] pub const fn set_port(&mut self, new_port: u16) { match *self { SocketAddr::V4(ref mut a) => a.set_port(new_port), @@ -360,7 +360,7 @@ impl SocketAddrV4 { /// ``` #[inline] #[stable(feature = "sockaddr_setters", since = "1.9.0")] - #[rustc_const_stable(feature = "const_sockaddr_setters", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_sockaddr_setters", since = "1.87.0")] pub const fn set_ip(&mut self, new_ip: Ipv4Addr) { self.ip = new_ip; } @@ -396,7 +396,7 @@ impl SocketAddrV4 { /// ``` #[inline] #[stable(feature = "sockaddr_setters", since = "1.9.0")] - #[rustc_const_stable(feature = "const_sockaddr_setters", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_sockaddr_setters", since = "1.87.0")] pub const fn set_port(&mut self, new_port: u16) { self.port = new_port; } @@ -458,7 +458,7 @@ impl SocketAddrV6 { /// ``` #[inline] #[stable(feature = "sockaddr_setters", since = "1.9.0")] - #[rustc_const_stable(feature = "const_sockaddr_setters", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_sockaddr_setters", since = "1.87.0")] pub const fn set_ip(&mut self, new_ip: Ipv6Addr) { self.ip = new_ip; } @@ -494,7 +494,7 @@ impl SocketAddrV6 { /// ``` #[inline] #[stable(feature = "sockaddr_setters", since = "1.9.0")] - #[rustc_const_stable(feature = "const_sockaddr_setters", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_sockaddr_setters", since = "1.87.0")] pub const fn set_port(&mut self, new_port: u16) { self.port = new_port; } @@ -542,7 +542,7 @@ impl SocketAddrV6 { /// ``` #[inline] #[stable(feature = "sockaddr_setters", since = "1.9.0")] - #[rustc_const_stable(feature = "const_sockaddr_setters", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_sockaddr_setters", since = "1.87.0")] pub const fn set_flowinfo(&mut self, new_flowinfo: u32) { self.flowinfo = new_flowinfo; } @@ -585,7 +585,7 @@ impl SocketAddrV6 { /// ``` #[inline] #[stable(feature = "sockaddr_setters", since = "1.9.0")] - #[rustc_const_stable(feature = "const_sockaddr_setters", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_sockaddr_setters", since = "1.87.0")] pub const fn set_scope_id(&mut self, new_scope_id: u32) { self.scope_id = new_scope_id; } diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index a72ca4bcb059..de0d55e2185e 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -244,8 +244,8 @@ macro_rules! int_impl { /// #[doc = concat!("assert_eq!(n.cast_unsigned(), ", stringify!($UnsignedT), "::MAX);")] /// ``` - #[stable(feature = "integer_sign_cast", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "integer_sign_cast", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "integer_sign_cast", since = "1.87.0")] + #[rustc_const_stable(feature = "integer_sign_cast", since = "1.87.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] @@ -1355,8 +1355,8 @@ macro_rules! int_impl { #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".unbounded_shl(4), 0x10);")] #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".unbounded_shl(129), 0);")] /// ``` - #[stable(feature = "unbounded_shifts", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "unbounded_shifts", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "unbounded_shifts", since = "1.87.0")] + #[rustc_const_stable(feature = "unbounded_shifts", since = "1.87.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1478,8 +1478,8 @@ macro_rules! int_impl { #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".unbounded_shr(129), 0);")] #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.unbounded_shr(129), -1);")] /// ``` - #[stable(feature = "unbounded_shifts", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "unbounded_shifts", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "unbounded_shifts", since = "1.87.0")] + #[rustc_const_stable(feature = "unbounded_shifts", since = "1.87.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 151e128cd78a..9c67c37a3dda 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -169,8 +169,8 @@ macro_rules! midpoint_impl { #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(-7), -3);")] #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(7), 3);")] /// ``` - #[stable(feature = "num_midpoint_signed", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "num_midpoint_signed", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "num_midpoint_signed", since = "1.87.0")] + #[rustc_const_stable(feature = "num_midpoint_signed", since = "1.87.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -221,8 +221,8 @@ macro_rules! midpoint_impl { #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(-7), -3);")] #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".midpoint(7), 3);")] /// ``` - #[stable(feature = "num_midpoint_signed", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "num_midpoint_signed", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "num_midpoint_signed", since = "1.87.0")] + #[rustc_const_stable(feature = "num_midpoint_signed", since = "1.87.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 7585ec140e31..1b79112aec1f 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -1704,8 +1704,8 @@ macro_rules! nonzero_integer_signedness_dependent_methods { /// #[doc = concat!("assert_eq!(n.cast_signed(), NonZero::new(-1", stringify!($Sint), ").unwrap());")] /// ``` - #[stable(feature = "integer_sign_cast", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "integer_sign_cast", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "integer_sign_cast", since = "1.87.0")] + #[rustc_const_stable(feature = "integer_sign_cast", since = "1.87.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] @@ -2143,8 +2143,8 @@ macro_rules! nonzero_integer_signedness_dependent_methods { /// #[doc = concat!("assert_eq!(n.cast_unsigned(), NonZero::<", stringify!($Uint), ">::MAX);")] /// ``` - #[stable(feature = "integer_sign_cast", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "integer_sign_cast", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "integer_sign_cast", since = "1.87.0")] + #[rustc_const_stable(feature = "integer_sign_cast", since = "1.87.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 586892758398..1b2acdc5a0df 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -273,8 +273,8 @@ macro_rules! uint_impl { /// #[doc = concat!("assert_eq!(n.cast_signed(), -1", stringify!($SignedT), ");")] /// ``` - #[stable(feature = "integer_sign_cast", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "integer_sign_cast", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "integer_sign_cast", since = "1.87.0")] + #[rustc_const_stable(feature = "integer_sign_cast", since = "1.87.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] @@ -1616,8 +1616,8 @@ macro_rules! uint_impl { #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".unbounded_shl(4), 0x10);")] #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".unbounded_shl(129), 0);")] /// ``` - #[stable(feature = "unbounded_shifts", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "unbounded_shifts", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "unbounded_shifts", since = "1.87.0")] + #[rustc_const_stable(feature = "unbounded_shifts", since = "1.87.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1737,8 +1737,8 @@ macro_rules! uint_impl { #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".unbounded_shr(4), 0x1);")] #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".unbounded_shr(129), 0);")] /// ``` - #[stable(feature = "unbounded_shifts", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "unbounded_shifts", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "unbounded_shifts", since = "1.87.0")] + #[rustc_const_stable(feature = "unbounded_shifts", since = "1.87.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -3331,8 +3331,8 @@ macro_rules! uint_impl { #[doc = concat!("assert!(0_", stringify!($SelfT), ".is_multiple_of(0));")] #[doc = concat!("assert!(!6_", stringify!($SelfT), ".is_multiple_of(0));")] /// ``` - #[stable(feature = "unsigned_is_multiple_of", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "unsigned_is_multiple_of", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "unsigned_is_multiple_of", since = "1.87.0")] + #[rustc_const_stable(feature = "unsigned_is_multiple_of", since = "1.87.0")] #[must_use] #[inline] #[rustc_inherit_overflow_checks] diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 71a84aff2460..0854e31c1997 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -764,8 +764,8 @@ impl *const T { /// // This would be incorrect, as the pointers are not correctly ordered: /// // ptr1.offset_from_unsigned(ptr2) /// ``` - #[stable(feature = "ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "ptr_sub_ptr", since = "1.87.0")] + #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "1.87.0")] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn offset_from_unsigned(self, origin: *const T) -> usize @@ -809,8 +809,8 @@ impl *const T { /// /// For non-`Sized` pointees this operation considers only the data pointers, /// ignoring the metadata. - #[stable(feature = "ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "ptr_sub_ptr", since = "1.87.0")] + #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "1.87.0")] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn byte_offset_from_unsigned(self, origin: *const U) -> usize { diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 9e62beb80492..e29774963db0 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -937,8 +937,8 @@ impl *mut T { /// /// // This would be incorrect, as the pointers are not correctly ordered: /// // ptr1.offset_from(ptr2) - #[stable(feature = "ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "ptr_sub_ptr", since = "1.87.0")] + #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "1.87.0")] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn offset_from_unsigned(self, origin: *const T) -> usize @@ -959,8 +959,8 @@ impl *mut T { /// /// For non-`Sized` pointees this operation considers only the data pointers, /// ignoring the metadata. - #[stable(feature = "ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "ptr_sub_ptr", since = "1.87.0")] + #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "1.87.0")] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn byte_offset_from_unsigned(self, origin: *mut U) -> usize { diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index e019aafad393..68b8f0c3e4e1 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -900,8 +900,8 @@ impl NonNull { /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces - #[stable(feature = "ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "ptr_sub_ptr", since = "1.87.0")] + #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "1.87.0")] pub const unsafe fn offset_from_unsigned(self, subtracted: NonNull) -> usize where T: Sized, @@ -922,8 +922,8 @@ impl NonNull { /// ignoring the metadata. #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces - #[stable(feature = "ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "ptr_sub_ptr", since = "1.87.0")] + #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "1.87.0")] pub const unsafe fn byte_offset_from_unsigned(self, origin: NonNull) -> usize { // SAFETY: the caller must uphold the safety contract for `byte_sub_ptr`. unsafe { self.as_ptr().byte_offset_from_unsigned(origin.as_ptr()) } diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index c7e8d5f989dd..b906899a30b3 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -3721,7 +3721,7 @@ impl [T] { #[doc(alias = "memcpy")] #[inline] #[stable(feature = "copy_from_slice", since = "1.9.0")] - #[rustc_const_stable(feature = "const_copy_from_slice", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_copy_from_slice", since = "1.87.0")] #[track_caller] pub const fn copy_from_slice(&mut self, src: &[T]) where @@ -4331,7 +4331,7 @@ impl [T] { /// ``` #[inline] #[must_use = "method does not modify the slice if the range is out of bounds"] - #[stable(feature = "slice_take", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "slice_take", since = "1.87.0")] pub fn split_off<'a, R: OneSidedRange>( self: &mut &'a Self, range: R, @@ -4397,7 +4397,7 @@ impl [T] { /// ``` #[inline] #[must_use = "method does not modify the slice if the range is out of bounds"] - #[stable(feature = "slice_take", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "slice_take", since = "1.87.0")] pub fn split_off_mut<'a, R: OneSidedRange>( self: &mut &'a mut Self, range: R, @@ -4434,7 +4434,7 @@ impl [T] { /// assert_eq!(first, &'a'); /// ``` #[inline] - #[stable(feature = "slice_take", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "slice_take", since = "1.87.0")] #[rustc_const_unstable(feature = "const_split_off_first_last", issue = "138539")] pub const fn split_off_first<'a>(self: &mut &'a Self) -> Option<&'a T> { // FIXME(const-hack): Use `?` when available in const instead of `let-else`. @@ -4459,7 +4459,7 @@ impl [T] { /// assert_eq!(first, &'d'); /// ``` #[inline] - #[stable(feature = "slice_take", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "slice_take", since = "1.87.0")] #[rustc_const_unstable(feature = "const_split_off_first_last", issue = "138539")] pub const fn split_off_first_mut<'a>(self: &mut &'a mut Self) -> Option<&'a mut T> { // FIXME(const-hack): Use `mem::take` and `?` when available in const. @@ -4484,7 +4484,7 @@ impl [T] { /// assert_eq!(last, &'c'); /// ``` #[inline] - #[stable(feature = "slice_take", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "slice_take", since = "1.87.0")] #[rustc_const_unstable(feature = "const_split_off_first_last", issue = "138539")] pub const fn split_off_last<'a>(self: &mut &'a Self) -> Option<&'a T> { // FIXME(const-hack): Use `?` when available in const instead of `let-else`. @@ -4509,7 +4509,7 @@ impl [T] { /// assert_eq!(last, &'d'); /// ``` #[inline] - #[stable(feature = "slice_take", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "slice_take", since = "1.87.0")] #[rustc_const_unstable(feature = "const_split_off_first_last", issue = "138539")] pub const fn split_off_last_mut<'a>(self: &mut &'a mut Self) -> Option<&'a mut T> { // FIXME(const-hack): Use `mem::take` and `?` when available in const. @@ -4841,7 +4841,7 @@ impl [[T; N]] { /// assert!(empty_slice_of_arrays.as_flattened().is_empty()); /// ``` #[stable(feature = "slice_flatten", since = "1.80.0")] - #[rustc_const_stable(feature = "const_slice_flatten", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_slice_flatten", since = "1.87.0")] pub const fn as_flattened(&self) -> &[T] { let len = if T::IS_ZST { self.len().checked_mul(N).expect("slice len overflow") @@ -4878,7 +4878,7 @@ impl [[T; N]] { /// assert_eq!(array, [[6, 7, 8], [9, 10, 11], [12, 13, 14]]); /// ``` #[stable(feature = "slice_flatten", since = "1.80.0")] - #[rustc_const_stable(feature = "const_slice_flatten", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_slice_flatten", since = "1.87.0")] pub const fn as_flattened_mut(&mut self) -> &mut [T] { let len = if T::IS_ZST { self.len().checked_mul(N).expect("slice len overflow") diff --git a/library/core/src/str/converts.rs b/library/core/src/str/converts.rs index 1276d9014f0e..37854a4da64c 100644 --- a/library/core/src/str/converts.rs +++ b/library/core/src/str/converts.rs @@ -126,7 +126,7 @@ pub const fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> { /// See the docs for [`Utf8Error`] for more details on the kinds of /// errors that can be returned. #[stable(feature = "str_mut_extras", since = "1.20.0")] -#[rustc_const_stable(feature = "const_str_from_utf8", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_str_from_utf8", since = "1.87.0")] #[rustc_diagnostic_item = "str_from_utf8_mut"] pub const fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> { // FIXME(const-hack): This should use `?` again, once it's `const` diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 5cc08f8a71af..79b4953fcc11 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -230,8 +230,8 @@ impl str { /// /// assert_eq!("💖", sparkle_heart); /// ``` - #[stable(feature = "inherent_str_constructors", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "inherent_str_constructors", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "inherent_str_constructors", since = "1.87.0")] + #[rustc_const_stable(feature = "inherent_str_constructors", since = "1.87.0")] #[rustc_diagnostic_item = "str_inherent_from_utf8"] pub const fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> { converts::from_utf8(v) @@ -263,8 +263,8 @@ impl str { /// ``` /// See the docs for [`Utf8Error`] for more details on the kinds of /// errors that can be returned. - #[stable(feature = "inherent_str_constructors", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "const_str_from_utf8", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "inherent_str_constructors", since = "1.87.0")] + #[rustc_const_stable(feature = "const_str_from_utf8", since = "1.87.0")] #[rustc_diagnostic_item = "str_inherent_from_utf8_mut"] pub const fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> { converts::from_utf8_mut(v) @@ -295,8 +295,8 @@ impl str { /// ``` #[inline] #[must_use] - #[stable(feature = "inherent_str_constructors", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "inherent_str_constructors", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "inherent_str_constructors", since = "1.87.0")] + #[rustc_const_stable(feature = "inherent_str_constructors", since = "1.87.0")] #[rustc_diagnostic_item = "str_inherent_from_utf8_unchecked"] pub const unsafe fn from_utf8_unchecked(v: &[u8]) -> &str { // SAFETY: converts::from_utf8_unchecked has the same safety requirements as this function. @@ -320,8 +320,8 @@ impl str { /// ``` #[inline] #[must_use] - #[stable(feature = "inherent_str_constructors", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "inherent_str_constructors", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "inherent_str_constructors", since = "1.87.0")] + #[rustc_const_stable(feature = "inherent_str_constructors", since = "1.87.0")] #[rustc_diagnostic_item = "str_inherent_from_utf8_unchecked_mut"] pub const unsafe fn from_utf8_unchecked_mut(v: &mut [u8]) -> &mut str { // SAFETY: converts::from_utf8_unchecked_mut has the same safety requirements as this function. diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 2487f5a2a503..0eef2bd225c0 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -683,7 +683,7 @@ impl HashMap { /// ``` #[inline] #[rustc_lint_query_instability] - #[stable(feature = "hash_extract_if", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "hash_extract_if", since = "1.87.0")] pub fn extract_if(&mut self, pred: F) -> ExtractIf<'_, K, V, F> where F: FnMut(&K, &mut V) -> bool, @@ -1677,7 +1677,7 @@ impl<'a, K, V> Drain<'a, K, V> { /// ]); /// let iter = map.extract_if(|_k, v| *v % 2 == 0); /// ``` -#[stable(feature = "hash_extract_if", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "hash_extract_if", since = "1.87.0")] #[must_use = "iterators are lazy and do nothing unless consumed"] pub struct ExtractIf<'a, K, V, F> where @@ -2294,7 +2294,7 @@ where } } -#[stable(feature = "hash_extract_if", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "hash_extract_if", since = "1.87.0")] impl Iterator for ExtractIf<'_, K, V, F> where F: FnMut(&K, &mut V) -> bool, @@ -2311,10 +2311,10 @@ where } } -#[stable(feature = "hash_extract_if", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "hash_extract_if", since = "1.87.0")] impl FusedIterator for ExtractIf<'_, K, V, F> where F: FnMut(&K, &mut V) -> bool {} -#[stable(feature = "hash_extract_if", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "hash_extract_if", since = "1.87.0")] impl<'a, K, V, F> fmt::Debug for ExtractIf<'a, K, V, F> where F: FnMut(&K, &mut V) -> bool, diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index a547a9943c1a..7be000594bc5 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -308,7 +308,7 @@ impl HashSet { /// ``` #[inline] #[rustc_lint_query_instability] - #[stable(feature = "hash_extract_if", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "hash_extract_if", since = "1.87.0")] pub fn extract_if(&mut self, pred: F) -> ExtractIf<'_, T, F> where F: FnMut(&T) -> bool, @@ -1390,7 +1390,7 @@ pub struct Drain<'a, K: 'a> { /// /// let mut extract_ifed = a.extract_if(|v| v % 2 == 0); /// ``` -#[stable(feature = "hash_extract_if", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "hash_extract_if", since = "1.87.0")] pub struct ExtractIf<'a, K, F> where F: FnMut(&K) -> bool, @@ -1673,7 +1673,7 @@ impl fmt::Debug for Drain<'_, K> { } } -#[stable(feature = "hash_extract_if", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "hash_extract_if", since = "1.87.0")] impl Iterator for ExtractIf<'_, K, F> where F: FnMut(&K) -> bool, @@ -1690,10 +1690,10 @@ where } } -#[stable(feature = "hash_extract_if", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "hash_extract_if", since = "1.87.0")] impl FusedIterator for ExtractIf<'_, K, F> where F: FnMut(&K) -> bool {} -#[stable(feature = "hash_extract_if", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "hash_extract_if", since = "1.87.0")] impl<'a, K, F> fmt::Debug for ExtractIf<'a, K, F> where F: FnMut(&K) -> bool, diff --git a/library/std/src/ffi/mod.rs b/library/std/src/ffi/mod.rs index 860ec3a6be16..d34e3ca00b9f 100644 --- a/library/std/src/ffi/mod.rs +++ b/library/std/src/ffi/mod.rs @@ -201,5 +201,5 @@ pub use self::c_str::{CStr, CString}; #[doc(inline)] pub use self::os_str::{OsStr, OsString}; -#[stable(feature = "os_str_display", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "os_str_display", since = "1.87.0")] pub mod os_str; diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index aa25ff5293c7..ce01175309a7 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -1255,7 +1255,7 @@ impl OsStr { /// let s = OsStr::new("Hello, world!"); /// println!("{}", s.display()); /// ``` - #[stable(feature = "os_str_display", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "os_str_display", since = "1.87.0")] #[must_use = "this does not display the `OsStr`; \ it returns an object that can be displayed"] #[inline] @@ -1612,19 +1612,19 @@ impl fmt::Debug for OsStr { /// /// [`Display`]: fmt::Display /// [`format!`]: crate::format -#[stable(feature = "os_str_display", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "os_str_display", since = "1.87.0")] pub struct Display<'a> { os_str: &'a OsStr, } -#[stable(feature = "os_str_display", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "os_str_display", since = "1.87.0")] impl fmt::Debug for Display<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(&self.os_str, f) } } -#[stable(feature = "os_str_display", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "os_str_display", since = "1.87.0")] impl fmt::Display for Display<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(&self.os_str.inner, f) diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index 8472f9030500..2498fb8d24fb 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -374,7 +374,7 @@ pub enum ErrorKind { /// A filename was invalid. /// /// This error can also occur if a length limit for a name was exceeded. - #[stable(feature = "io_error_invalid_filename", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "io_error_invalid_filename", since = "1.87.0")] InvalidFilename, /// Program argument list too long. /// diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 314cbb45d49e..b6545eada86a 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -310,7 +310,7 @@ pub use self::error::RawOsError; pub use self::error::SimpleMessage; #[unstable(feature = "io_const_error", issue = "133448")] pub use self::error::const_error; -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] pub use self::pipe::{PipeReader, PipeWriter, pipe}; #[stable(feature = "is_terminal", since = "1.70.0")] pub use self::stdio::IsTerminal; diff --git a/library/std/src/io/pipe.rs b/library/std/src/io/pipe.rs index cfed9b05cc0c..c6b7b49a351e 100644 --- a/library/std/src/io/pipe.rs +++ b/library/std/src/io/pipe.rs @@ -67,19 +67,19 @@ use crate::sys_common::{FromInner, IntoInner}; /// ``` /// [changes]: io#platform-specific-behavior /// [man page]: https://man7.org/linux/man-pages/man7/pipe.7.html -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] #[inline] pub fn pipe() -> io::Result<(PipeReader, PipeWriter)> { pipe_inner().map(|(reader, writer)| (PipeReader(reader), PipeWriter(writer))) } /// Read end of an anonymous pipe. -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] #[derive(Debug)] pub struct PipeReader(pub(crate) AnonPipe); /// Write end of an anonymous pipe. -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] #[derive(Debug)] pub struct PipeWriter(pub(crate) AnonPipe); @@ -160,7 +160,7 @@ impl PipeReader { /// # Ok(()) /// # } /// ``` - #[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "anonymous_pipe", since = "1.87.0")] pub fn try_clone(&self) -> io::Result { self.0.try_clone().map(Self) } @@ -199,13 +199,13 @@ impl PipeWriter { /// # Ok(()) /// # } /// ``` - #[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "anonymous_pipe", since = "1.87.0")] pub fn try_clone(&self) -> io::Result { self.0.try_clone().map(Self) } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] impl io::Read for &PipeReader { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.0.read(buf) @@ -225,7 +225,7 @@ impl io::Read for &PipeReader { } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] impl io::Read for PipeReader { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.0.read(buf) @@ -245,7 +245,7 @@ impl io::Read for PipeReader { } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] impl io::Write for &PipeWriter { fn write(&mut self, buf: &[u8]) -> io::Result { self.0.write(buf) @@ -263,7 +263,7 @@ impl io::Write for &PipeWriter { } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] impl io::Write for PipeWriter { fn write(&mut self, buf: &[u8]) -> io::Result { self.0.write(buf) diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs index be73e7dee9c7..10e1e73a115b 100644 --- a/library/std/src/os/fd/owned.rs +++ b/library/std/src/os/fd/owned.rs @@ -505,7 +505,7 @@ impl<'a> AsFd for io::StderrLock<'a> { } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] #[cfg(not(target_os = "trusty"))] impl AsFd for io::PipeReader { fn as_fd(&self) -> BorrowedFd<'_> { @@ -513,7 +513,7 @@ impl AsFd for io::PipeReader { } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] #[cfg(not(target_os = "trusty"))] impl From for OwnedFd { fn from(pipe: io::PipeReader) -> Self { @@ -521,7 +521,7 @@ impl From for OwnedFd { } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] #[cfg(not(target_os = "trusty"))] impl AsFd for io::PipeWriter { fn as_fd(&self) -> BorrowedFd<'_> { @@ -529,7 +529,7 @@ impl AsFd for io::PipeWriter { } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] #[cfg(not(target_os = "trusty"))] impl From for OwnedFd { fn from(pipe: io::PipeWriter) -> Self { @@ -537,7 +537,7 @@ impl From for OwnedFd { } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] #[cfg(not(target_os = "trusty"))] impl From for io::PipeReader { fn from(owned_fd: OwnedFd) -> Self { @@ -545,7 +545,7 @@ impl From for io::PipeReader { } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] #[cfg(not(target_os = "trusty"))] impl From for io::PipeWriter { fn from(owned_fd: OwnedFd) -> Self { diff --git a/library/std/src/os/fd/raw.rs b/library/std/src/os/fd/raw.rs index c800c1489ad2..34a6cf1a8b84 100644 --- a/library/std/src/os/fd/raw.rs +++ b/library/std/src/os/fd/raw.rs @@ -285,7 +285,7 @@ impl AsRawFd for Box { } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] #[cfg(not(target_os = "trusty"))] impl AsRawFd for io::PipeReader { fn as_raw_fd(&self) -> RawFd { @@ -293,7 +293,7 @@ impl AsRawFd for io::PipeReader { } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] #[cfg(not(target_os = "trusty"))] impl FromRawFd for io::PipeReader { unsafe fn from_raw_fd(raw_fd: RawFd) -> Self { @@ -301,7 +301,7 @@ impl FromRawFd for io::PipeReader { } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] #[cfg(not(target_os = "trusty"))] impl IntoRawFd for io::PipeReader { fn into_raw_fd(self) -> RawFd { @@ -309,7 +309,7 @@ impl IntoRawFd for io::PipeReader { } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] #[cfg(not(target_os = "trusty"))] impl AsRawFd for io::PipeWriter { fn as_raw_fd(&self) -> RawFd { @@ -317,7 +317,7 @@ impl AsRawFd for io::PipeWriter { } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] #[cfg(not(target_os = "trusty"))] impl FromRawFd for io::PipeWriter { unsafe fn from_raw_fd(raw_fd: RawFd) -> Self { @@ -325,7 +325,7 @@ impl FromRawFd for io::PipeWriter { } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] #[cfg(not(target_os = "trusty"))] impl IntoRawFd for io::PipeWriter { fn into_raw_fd(self) -> RawFd { diff --git a/library/std/src/os/windows/io/handle.rs b/library/std/src/os/windows/io/handle.rs index 7f21929b85f9..4fc04b79315f 100644 --- a/library/std/src/os/windows/io/handle.rs +++ b/library/std/src/os/windows/io/handle.rs @@ -661,42 +661,42 @@ impl From> for OwnedHandle { } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] impl AsHandle for io::PipeReader { fn as_handle(&self) -> BorrowedHandle<'_> { self.0.as_handle() } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] impl From for OwnedHandle { fn from(pipe: io::PipeReader) -> Self { pipe.into_inner().into_inner() } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] impl AsHandle for io::PipeWriter { fn as_handle(&self) -> BorrowedHandle<'_> { self.0.as_handle() } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] impl From for OwnedHandle { fn from(pipe: io::PipeWriter) -> Self { pipe.into_inner().into_inner() } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] impl From for io::PipeReader { fn from(owned_handle: OwnedHandle) -> Self { Self::from_inner(FromInner::from_inner(owned_handle)) } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] impl From for io::PipeWriter { fn from(owned_handle: OwnedHandle) -> Self { Self::from_inner(FromInner::from_inner(owned_handle)) diff --git a/library/std/src/os/windows/io/raw.rs b/library/std/src/os/windows/io/raw.rs index bc3e55c86296..a3ec7440338d 100644 --- a/library/std/src/os/windows/io/raw.rs +++ b/library/std/src/os/windows/io/raw.rs @@ -311,42 +311,42 @@ impl IntoRawSocket for net::UdpSocket { } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] impl AsRawHandle for io::PipeReader { fn as_raw_handle(&self) -> RawHandle { self.0.as_raw_handle() } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] impl FromRawHandle for io::PipeReader { unsafe fn from_raw_handle(raw_handle: RawHandle) -> Self { unsafe { Self::from_inner(FromRawHandle::from_raw_handle(raw_handle)) } } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] impl IntoRawHandle for io::PipeReader { fn into_raw_handle(self) -> RawHandle { self.0.into_raw_handle() } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] impl AsRawHandle for io::PipeWriter { fn as_raw_handle(&self) -> RawHandle { self.0.as_raw_handle() } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] impl FromRawHandle for io::PipeWriter { unsafe fn from_raw_handle(raw_handle: RawHandle) -> Self { unsafe { Self::from_inner(FromRawHandle::from_raw_handle(raw_handle)) } } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] impl IntoRawHandle for io::PipeWriter { fn into_raw_handle(self) -> RawHandle { self.0.into_raw_handle() diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 3b765a9537bc..da518011a0e4 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -1659,14 +1659,14 @@ impl From for Stdio { } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] impl From for Stdio { fn from(pipe: io::PipeWriter) -> Self { Stdio::from_inner(pipe.into_inner().into()) } } -#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "anonymous_pipe", since = "1.87.0")] impl From for Stdio { fn from(pipe: io::PipeReader) -> Self { Stdio::from_inner(pipe.into_inner().into()) From 609eacbb22eb9014fdea1618105a294f0dc8a63e Mon Sep 17 00:00:00 2001 From: Boxy Date: Wed, 2 Apr 2025 21:03:17 +0100 Subject: [PATCH 257/606] bump stage0 --- src/stage0 | 922 ++++++++++++++++++++++++++--------------------------- 1 file changed, 460 insertions(+), 462 deletions(-) diff --git a/src/stage0 b/src/stage0 index 9d6a08d378d8..b3841d253f34 100644 --- a/src/stage0 +++ b/src/stage0 @@ -14,468 +14,466 @@ nightly_branch=master # All changes below this comment will be overridden the next time the # tool is executed. -compiler_date=2025-02-18 +compiler_date=2025-04-02 compiler_version=beta -rustfmt_date=2025-02-18 +rustfmt_date=2025-04-02 rustfmt_version=nightly -dist/2025-02-18/rustc-beta-aarch64-apple-darwin.tar.gz=1b51ca064350d8b15c7ab6c8ec996a497e912dc237cafc2c205066fc6416e0ff -dist/2025-02-18/rustc-beta-aarch64-apple-darwin.tar.xz=e4b71f6456d9e62ada6909254606da7f6681f3da0f5bc7d2c3d5c387fea35743 -dist/2025-02-18/rustc-beta-aarch64-pc-windows-msvc.tar.gz=1ff70a5bd238d959d806c3b471a5b03c6cde784944a96a585e0ae0837d2a9c92 -dist/2025-02-18/rustc-beta-aarch64-pc-windows-msvc.tar.xz=5017b351bb90a08041757eae61386b224ec0161c5734293184a87d8903f30098 -dist/2025-02-18/rustc-beta-aarch64-unknown-linux-gnu.tar.gz=8a58b6cc4577615efc76bb9472229098d6f938c1f051ea540409e9dc812dbd8f -dist/2025-02-18/rustc-beta-aarch64-unknown-linux-gnu.tar.xz=330e217dbd1c507c8706aef5fbd0baf9584495445743f38668cdc962adfb125e -dist/2025-02-18/rustc-beta-aarch64-unknown-linux-musl.tar.gz=4060ec54281975880a9819b815120d6a450e4c31ddf1136ecce348e28875d50d -dist/2025-02-18/rustc-beta-aarch64-unknown-linux-musl.tar.xz=0f92b9267a55ac0c764cde63b8cbc8a0a317f7e0817185d380fc2aa35a933687 -dist/2025-02-18/rustc-beta-arm-unknown-linux-gnueabi.tar.gz=4e989e00725e7cfb08ea834c74ec6dd352eda74c13218f7da423ed598af9f9df -dist/2025-02-18/rustc-beta-arm-unknown-linux-gnueabi.tar.xz=b06181daf8842c2e544e5d54169f9bbfc70ee76115495de033ac4e341617a588 -dist/2025-02-18/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz=93fe2efcde1032ad636ef509a73168f0ab7fadbca699a27e2882b3832539e8fa -dist/2025-02-18/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz=b49d0256381c928785035578e5b7624c37ba732ea7aefca37dbb66b5162c8090 -dist/2025-02-18/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz=56fd36c20d78085f39f0df40f15f7694e8744714104539865b9c3d7b06d47e2f -dist/2025-02-18/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz=86587bea60c2b8a114ab33fe65a7152fcf8e1dcca14550712dca72af9fd65674 -dist/2025-02-18/rustc-beta-i686-pc-windows-gnu.tar.gz=32c95c78b223efea2ee8e02fbe3a58ac753ce9284e792bc87feaa051fcff5687 -dist/2025-02-18/rustc-beta-i686-pc-windows-gnu.tar.xz=d2e623f11aee7e81eceb6947e3f7150bfd727eb2f527e4abc6b10d3322959802 -dist/2025-02-18/rustc-beta-i686-pc-windows-msvc.tar.gz=f7ffd07eb2b5e83df513c6a313e28003e3ce923778583e78da9efbb5e62405dc -dist/2025-02-18/rustc-beta-i686-pc-windows-msvc.tar.xz=cd2e61b548a6849b17183fcacb2ac8f94955d893be439793580c39080feb28be -dist/2025-02-18/rustc-beta-i686-unknown-linux-gnu.tar.gz=fedeca202c1651fe4b15cfc411365ecf016376b3cc7c772d2e0d739e0ec02dc6 -dist/2025-02-18/rustc-beta-i686-unknown-linux-gnu.tar.xz=6389f10e2328bdfa81ef1f34406bb4ec8bcb6dcf64d39c95946d32c9fee7f0b7 -dist/2025-02-18/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz=21b565bbaacc2be5d066c5d0c49b7c0f5b0bd24690ca35e9c88e6ec91846f744 -dist/2025-02-18/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz=4a728e3ec41834775f0b288cdca5ae152314edcaf20d7ea46ea62fab1b9ef327 -dist/2025-02-18/rustc-beta-loongarch64-unknown-linux-musl.tar.gz=0a72f650aa70708f9a72886ea33b7a2e3ffe2a6e2cbcb1d2248f3d9eca74a9d4 -dist/2025-02-18/rustc-beta-loongarch64-unknown-linux-musl.tar.xz=877c3c447f4c25068f70bd7d6dd5078d75b0c194777b2f8a9311a66fc6eda701 -dist/2025-02-18/rustc-beta-powerpc-unknown-linux-gnu.tar.gz=67af5e05ab0a367d3f76c0656823b530a23fb26d9c86db2b433684b9191b8881 -dist/2025-02-18/rustc-beta-powerpc-unknown-linux-gnu.tar.xz=2da086d39eaa000ba629ee15bec740db57039ca3e5c7c55feb9cb9ca6d39c785 -dist/2025-02-18/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz=b079df9a3e5be95a755d22f5ecf3ddeb43f94d96eaa3985770ae98ad0e7e15bb -dist/2025-02-18/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz=916fe3b67094bb351320371de9587f01bb65f9b9aed2c7aff7930e499822b660 -dist/2025-02-18/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz=356e3173c960aadfb91dcb607a26647895fb1ae11a7cb596b019c71c6dd808e7 -dist/2025-02-18/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz=9115c4c85d8c4b5254df41a5d3f55733648ba282711e18a692ee100ed13fb550 -dist/2025-02-18/rustc-beta-powerpc64le-unknown-linux-musl.tar.gz=b8a267f9ca2d23385c529924782f633b6b9f66b50cda5986eff91c223d715307 -dist/2025-02-18/rustc-beta-powerpc64le-unknown-linux-musl.tar.xz=84e65fc1d4282d737b6d0b1aaa1c2abd395af215983eb5b3700e925ca6ba3bc3 -dist/2025-02-18/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz=19b1d8618edb5d3a6cf620c814f6b76a462bc965f4aac2cde7aca5849b92cac9 -dist/2025-02-18/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz=9914408b5590fe7c43b2aa10c261bb5162b024e396c625b06546564a5eaddb89 -dist/2025-02-18/rustc-beta-s390x-unknown-linux-gnu.tar.gz=37ac73ea85f43a4859d8c4526cb9480e69bcaa778e842128852c8b21c6db6b45 -dist/2025-02-18/rustc-beta-s390x-unknown-linux-gnu.tar.xz=af1cab661b26cab1ade53f12ec08d13d60a74c2f370d9d3617154e0f01cb3719 -dist/2025-02-18/rustc-beta-x86_64-apple-darwin.tar.gz=aa9999ad56f8968e3e0f5417661ff42fbd1bd482a649d1a8c01d6ba5a6e78a72 -dist/2025-02-18/rustc-beta-x86_64-apple-darwin.tar.xz=bfd09bf8db9bbd7557df3f206207631cc4b10d59d0cf6b072e610646b5c7fa4a -dist/2025-02-18/rustc-beta-x86_64-pc-windows-gnu.tar.gz=dabab346a003a5b13265da6bab96fc703c34f728c852092bec4cf08d13daeadc -dist/2025-02-18/rustc-beta-x86_64-pc-windows-gnu.tar.xz=c2252dea69c8dcf6ba0213da8b05b8d9173676fb7448cde684da7b56d2c52577 -dist/2025-02-18/rustc-beta-x86_64-pc-windows-msvc.tar.gz=9ae9c3cb963872b2ef02650bcec15906e0b5e89cc6d3bee0aadfffcec7a1e6df -dist/2025-02-18/rustc-beta-x86_64-pc-windows-msvc.tar.xz=bcbf75c92e9afe6b25bbde275bd38c3cdeda6324baf5b8c99173ca5738760a7f -dist/2025-02-18/rustc-beta-x86_64-unknown-freebsd.tar.gz=5313d0780f6a9587e809da0f1ffc973721afad88a0ef8fb83005c383d79229d8 -dist/2025-02-18/rustc-beta-x86_64-unknown-freebsd.tar.xz=52ab3212d64b56a8da207fe976cbc8d266e962a61c742e6069137b10ff25c3c1 -dist/2025-02-18/rustc-beta-x86_64-unknown-illumos.tar.gz=527f839ddedc7bdff48527a276d3d7f64d475dd815b81c6664f1ce25668e0ce4 -dist/2025-02-18/rustc-beta-x86_64-unknown-illumos.tar.xz=3861d9928983a415cd44e5dc50a99af948fac392adfb6c2147b14fb98dd08890 -dist/2025-02-18/rustc-beta-x86_64-unknown-linux-gnu.tar.gz=0054d14cf00b25cfbcb2a1560887c825f703223312ca9cdd0ad51076bf54a3cc -dist/2025-02-18/rustc-beta-x86_64-unknown-linux-gnu.tar.xz=75a9d69d13e50bb22ec721f9c64d08282d76f285482b285bb61bacabeecd710c -dist/2025-02-18/rustc-beta-x86_64-unknown-linux-musl.tar.gz=305765ca6a413ea86360b970bd062a19f6bc52756551af43d74920fc2a021d95 -dist/2025-02-18/rustc-beta-x86_64-unknown-linux-musl.tar.xz=c7230b578a97fb234ac106c7333615074b9a7a8abc1422f149ad613c2af28134 -dist/2025-02-18/rustc-beta-x86_64-unknown-netbsd.tar.gz=881bd9b260b2c7838ea1b4de2cd6baf2ff4d317e0c159faba1a683c4c32ba267 -dist/2025-02-18/rustc-beta-x86_64-unknown-netbsd.tar.xz=0c4f2cc0bafbf8b41b257e851870b64d3b5fc112f02227f561c645dc439c96db -dist/2025-02-18/rust-std-beta-aarch64-apple-darwin.tar.gz=958434edfc07bf6d10da3d41f01d1511b28d1178423a78bff2f60cd10046dbca -dist/2025-02-18/rust-std-beta-aarch64-apple-darwin.tar.xz=80043af05fb96c497bce55063f2733e37f243f85084f9aa60ab504d7c15c5cce -dist/2025-02-18/rust-std-beta-aarch64-apple-ios.tar.gz=509aa8803b29ccbb97a1a8c12e2ca6b27310d5af313650c7afff45ab1843106a -dist/2025-02-18/rust-std-beta-aarch64-apple-ios.tar.xz=f0f05dafc9a3277b075023bb449675946706307f769590c065cb53ae615708d9 -dist/2025-02-18/rust-std-beta-aarch64-apple-ios-macabi.tar.gz=c37c0aee56c5858f91fb5aa60df28cc92649d4884d5edde57eb6690f494ba5f5 -dist/2025-02-18/rust-std-beta-aarch64-apple-ios-macabi.tar.xz=e5120697e4a118824fdebf6d2a644f8f338bb83e209303fc684095b8f6b4ab1c -dist/2025-02-18/rust-std-beta-aarch64-apple-ios-sim.tar.gz=d5b851917a3f57703378596828e92068c28e00fe0b02331891737c2fc697b5ff -dist/2025-02-18/rust-std-beta-aarch64-apple-ios-sim.tar.xz=ef33164320931007db65f4915b533e5078a7279a7a134fc80045751a5198834a -dist/2025-02-18/rust-std-beta-aarch64-linux-android.tar.gz=4b94607d7c09b4f0f85236fb2237f1859150e12745ee2020cb134db904c1e05b -dist/2025-02-18/rust-std-beta-aarch64-linux-android.tar.xz=3aa7807ef9da83e1a4deebe4a7085e4df1b60edd4e9f237870f827073100d09c -dist/2025-02-18/rust-std-beta-aarch64-pc-windows-gnullvm.tar.gz=2d4c8a5a400c35443228087f8203f320253299a5018c1b92526f99023581c3e9 -dist/2025-02-18/rust-std-beta-aarch64-pc-windows-gnullvm.tar.xz=df8741055b3d4f7eeedec9e0101a1c184a37ffb75b2d4474bfbca577300355f2 -dist/2025-02-18/rust-std-beta-aarch64-pc-windows-msvc.tar.gz=8db9c07d4b68018cd3c67be1e7bc496078dfa8a6852a35c449db5ba19f6bf0df -dist/2025-02-18/rust-std-beta-aarch64-pc-windows-msvc.tar.xz=f112e3d51013ceff37e8c05d80c3605b76ddec8e55474d55815b4860f96febc8 -dist/2025-02-18/rust-std-beta-aarch64-unknown-fuchsia.tar.gz=2bb6d934225823c2dcdb86dca91dd8e488f69b238b283607f75abe9b5de46486 -dist/2025-02-18/rust-std-beta-aarch64-unknown-fuchsia.tar.xz=99036fde94fe0cb3ab2d2f48cd9f9bbb4d2fa784f1bd21afaa71b032cd95b069 -dist/2025-02-18/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz=c49fee34a02f5d3fe4e03ed7da90e045f7967c3e2e8f7a30804f4da5d535225c -dist/2025-02-18/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz=88170a13f9448b9671d252f0315aed94b6324716230db7307061d4890cfda70a -dist/2025-02-18/rust-std-beta-aarch64-unknown-linux-musl.tar.gz=a5e7442d722f6742fd0436d3c7d75738bc6cbd936f3399190086a88ef311e34e -dist/2025-02-18/rust-std-beta-aarch64-unknown-linux-musl.tar.xz=5d07a95e3203ebe98eed1b271a2e6ae44bead53e7bda019a8d256c8553c21bd1 -dist/2025-02-18/rust-std-beta-aarch64-unknown-linux-ohos.tar.gz=0af6b8fc7f46641d4de61ada9bc9ff01af7775d727121267177fa4c43cc9ed7b -dist/2025-02-18/rust-std-beta-aarch64-unknown-linux-ohos.tar.xz=fd68b34e7aba25d8a834c018febbde6c3de7d967e014a738681642f41ec61603 -dist/2025-02-18/rust-std-beta-aarch64-unknown-none.tar.gz=46025b0892498de8e311be7bd6df261065f80a70720cb9285062161a30af5d76 -dist/2025-02-18/rust-std-beta-aarch64-unknown-none.tar.xz=b4cbf42364270c158d801ac7d4b6cfd7bf1f5f9e74a3044e6d959f1971f5bc34 -dist/2025-02-18/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz=ae2a5c63cce6ce237c81ae78cabc6e1e0634c956789c2e2f39e3a6c0d864636f -dist/2025-02-18/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz=6bba5069c89d9a0d9a2013715814fb55ebcd77b342ed0dfc72115a18367c5e8c -dist/2025-02-18/rust-std-beta-aarch64-unknown-uefi.tar.gz=0bef07ceece7523d6f41f1d640569c52ebe8a6b97b35da84240d873fd68250da -dist/2025-02-18/rust-std-beta-aarch64-unknown-uefi.tar.xz=cff8b58e158786cee1a719552fb97cb2cd3a12b541641437809428a65eed42fa -dist/2025-02-18/rust-std-beta-arm-linux-androideabi.tar.gz=a34fbf0d01cea60876a6d0aa4ee96587a5e31b6d4f84aa7c1ba5b7fed261b639 -dist/2025-02-18/rust-std-beta-arm-linux-androideabi.tar.xz=7d72d638f5984726fb4a61e81671d9557d0a9a876bf5bbf39b2df3c9983d2962 -dist/2025-02-18/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz=9ef3aa1bcbe1a18658bd16359cbf3e94ae1b07f65bd5c69ffbfa964ad845baf5 -dist/2025-02-18/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz=93020195c2ce07204179e2d2f900953707e341a71d9371551c4a727afc58378e -dist/2025-02-18/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz=5b0a4c4831534de85a5ba5b0149bbd824ca83648bf66babe5dbf13291b06e03d -dist/2025-02-18/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz=60f1ff95cc88330b6c9741520c02ec845e7b14943f2927091a9110b7fb1c4305 -dist/2025-02-18/rust-std-beta-arm-unknown-linux-musleabi.tar.gz=0f254a943b6e56873d2ab84e8a93fa7a3ab723df5a7926faeadae4696ed06121 -dist/2025-02-18/rust-std-beta-arm-unknown-linux-musleabi.tar.xz=0c682e7cbba8463682a0a20785ff7fd331d2bc7a32c0cf86b8159897fc5c5ee7 -dist/2025-02-18/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz=6c5be45f79035f57ac41fd209f6e7d4439cab5acaa766f7bf001b24196411b1e -dist/2025-02-18/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz=bf25eb6650ad27377414d53af6857133a539530c841cf96e3cae4406bf4ad485 -dist/2025-02-18/rust-std-beta-arm64ec-pc-windows-msvc.tar.gz=39ec7fd0ecf47b36c6badc1fc71f1290e99d2edfa9d7cfa72446fbb32ba9c8b0 -dist/2025-02-18/rust-std-beta-arm64ec-pc-windows-msvc.tar.xz=f1d578e9251d95c94c20e3ee7888993ec7ea3d967a880f89963df7bea0bbe93b -dist/2025-02-18/rust-std-beta-armebv7r-none-eabi.tar.gz=3990bce70402da79a27fd0f4adb169e4e9faf617bdbca2676bc41d9f85845dd7 -dist/2025-02-18/rust-std-beta-armebv7r-none-eabi.tar.xz=ac944400a3da94e32d7010e10b30879bbb5da456d3d54dfd0efc792884b035de -dist/2025-02-18/rust-std-beta-armebv7r-none-eabihf.tar.gz=1196e2ae338b325ceb89edaab8b165478ec481270a7ce4c65f47f45d76e7b33b -dist/2025-02-18/rust-std-beta-armebv7r-none-eabihf.tar.xz=fead57620d21252c958020e340fc793102d177f76fd90b3936eaf3a22a3b87c9 -dist/2025-02-18/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz=e5e81e1501554c2b28745c4d905bbe50f909dce3b7806f6010a9d48cc528304e -dist/2025-02-18/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz=d3c9513cdb058685848de3d7864a7fa5a9b1e45f779a7ecf447ac7faae652772 -dist/2025-02-18/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz=6ca5598fbdbf77bcf971e62d5b3f486e25d01e95773670bdc600448f29b68a09 -dist/2025-02-18/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz=7e0a8798586538c4b322b58b9e1ac90e27dea4a0b5b750873f90b8ec9dcdbe2e -dist/2025-02-18/rust-std-beta-armv7-linux-androideabi.tar.gz=cbd81d4f949248c0c48a60545648a384aa321ee5f590f52d50e8d3639a649745 -dist/2025-02-18/rust-std-beta-armv7-linux-androideabi.tar.xz=75216a970ba5a023717dbbd45b5a1a90ff9533f25deca241c11ebce80dc6229e -dist/2025-02-18/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz=5acf37dc6035d3d83d003d70d3db3c196b20d461a70385e8e5d545be1f4392b4 -dist/2025-02-18/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz=8c75b0c815465126d6c7516883c478c78fc83cfb294bd5b9387d5bad65c9810f -dist/2025-02-18/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz=733fca96e3d6dd232c746a6034bd7cc864f06bfce3d5da3bfd72c5ca4cea221d -dist/2025-02-18/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz=e9ef142105d0073bf070a6de74e7173fbc09f3f22fd50eef0fea8ab6cf0ab4d7 -dist/2025-02-18/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz=13f2b55f297628bea201f3caaae0178f0d898c67a696d4b60a37c3ba5af0582b -dist/2025-02-18/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz=455605ff7e88d69052a4b3798ba27a673807ac1be197a8ac9e57497b5bac1661 -dist/2025-02-18/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz=5b4b8eae2d86baeb470ad2a143f5d91f0dedeb225607189d9d0f8c8115e5251f -dist/2025-02-18/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz=fd36a0f0a001436195eacdb52baee2462c43a1f9899b2e01ed60019f8285a95d -dist/2025-02-18/rust-std-beta-armv7-unknown-linux-ohos.tar.gz=093900dfc07c4c4f59bd84aa8e9b505890cd8736a994798da8cfd7fb6210ab5b -dist/2025-02-18/rust-std-beta-armv7-unknown-linux-ohos.tar.xz=e5cef28308348a378835ced449affa965f49d9b7382d28cbf32337ae94ebc9cd -dist/2025-02-18/rust-std-beta-armv7a-none-eabi.tar.gz=210229d27f6d574670e9406b98748869212e66713a8ad37f2e5b67ebf27e43ab -dist/2025-02-18/rust-std-beta-armv7a-none-eabi.tar.xz=323197f1dc3fe70e0a540df8a5f5d9475dcb390f1685bef54ba355ad3b48f316 -dist/2025-02-18/rust-std-beta-armv7r-none-eabi.tar.gz=f66d3a794ea7ea0df73b5df389738e6b3e1790b27c06187de2ed1888743ecb57 -dist/2025-02-18/rust-std-beta-armv7r-none-eabi.tar.xz=ae1465d82ea49e5ed33ac95dc0ece4c8fd0ce3df20b21a6a44ed93f33d131aca -dist/2025-02-18/rust-std-beta-armv7r-none-eabihf.tar.gz=fa0d84655bfb7488c9c378ecf833edbde08c652d25fbc9092ed2707b320f657a -dist/2025-02-18/rust-std-beta-armv7r-none-eabihf.tar.xz=251ba3b71c4a0bbdc327a84ee1b3c3deeeed3917fe55aadff9a52a44063f6270 -dist/2025-02-18/rust-std-beta-i586-pc-windows-msvc.tar.gz=9d9d89b206dc85323a7ee765447d1cafc2fab9189be88e1558709d94c51f2298 -dist/2025-02-18/rust-std-beta-i586-pc-windows-msvc.tar.xz=b124483bdffbb41b5c806f6bcc1003ba15d031cf5fe02eaead555abe15da20a6 -dist/2025-02-18/rust-std-beta-i586-unknown-linux-gnu.tar.gz=914925fb75c45cd9939c8692b02efd337b814040ca9bce369d812b97698a4c3e -dist/2025-02-18/rust-std-beta-i586-unknown-linux-gnu.tar.xz=eefceae8f0d42a5e3524ac134afa9a13e938f1680edf605cca2e2d9dfbd33682 -dist/2025-02-18/rust-std-beta-i586-unknown-linux-musl.tar.gz=4baafd6924c5ab59c0c4dfd30272c08328ea1f31b70e8a9a3dababb94c1dee03 -dist/2025-02-18/rust-std-beta-i586-unknown-linux-musl.tar.xz=c75b6e4b50cd731d7f955956ce0afc02f04e2adc4268a1bec8b076eb1733ad28 -dist/2025-02-18/rust-std-beta-i686-linux-android.tar.gz=e067c5483336195763c2f1e9625644075fd93cc86180e6d24bee63aa26b22e99 -dist/2025-02-18/rust-std-beta-i686-linux-android.tar.xz=d4892feae881cc914b94b8bfd66b5e75cc4d62cbb697b8faa3f29d1d70d15f5f -dist/2025-02-18/rust-std-beta-i686-pc-windows-gnu.tar.gz=ff6f43c40e2f8edc9ca21df771c3c28ab77bcb0e254adaa09d8c9433bd56fa97 -dist/2025-02-18/rust-std-beta-i686-pc-windows-gnu.tar.xz=8d6088d7ef7f13bbf576fe238e8a032091359a773845f35e3329b5d8273d1fcc -dist/2025-02-18/rust-std-beta-i686-pc-windows-gnullvm.tar.gz=cc62a0e5c529bb041455ed15f646e5c9c918f20a644ed7306ad8beb1abf07c1d -dist/2025-02-18/rust-std-beta-i686-pc-windows-gnullvm.tar.xz=9cdcd32f73d9839c5e6322f8b1e18e3abf825ddbbe9bb498616f0c058c5fb061 -dist/2025-02-18/rust-std-beta-i686-pc-windows-msvc.tar.gz=fecfb22d75b38e9c92c64790833c8ed8b4ea70c40d3d9c67a23277216c1246bb -dist/2025-02-18/rust-std-beta-i686-pc-windows-msvc.tar.xz=a592d638118b0b95e8ef0e174b94c1825d0e3a3aab87d03737eb7415d1b32076 -dist/2025-02-18/rust-std-beta-i686-unknown-freebsd.tar.gz=e8546b2f4fe5746706d2b0d56fe174ee5993bd61a9fe451fd233236d7af0feee -dist/2025-02-18/rust-std-beta-i686-unknown-freebsd.tar.xz=09efaf8f4f26ce6d466c1e20758901dc64348cdf390f4b878b4ee9542f50dbae -dist/2025-02-18/rust-std-beta-i686-unknown-linux-gnu.tar.gz=e173f1ac1662deba8c719965d5d4c77e711cc0eac732d933b6c8ac021a44de5c -dist/2025-02-18/rust-std-beta-i686-unknown-linux-gnu.tar.xz=600aa6b6ed1b49afdcc4978c897cd1e1f801193b804b0d1723319464c8378c88 -dist/2025-02-18/rust-std-beta-i686-unknown-linux-musl.tar.gz=38f7ee73e7067df2b98064b9f0ed00b8aa7c7eeae5955719fa0e2cf1f126ed19 -dist/2025-02-18/rust-std-beta-i686-unknown-linux-musl.tar.xz=6e639d9c45eda6b43ce0ce52e3213172df1875adfa0c13e52385b5aa9fa05da1 -dist/2025-02-18/rust-std-beta-i686-unknown-uefi.tar.gz=2ae2a44ad2610bbe3a97d176bbfd3e43efa22b5713c9591b9f3bcd7609f3a30b -dist/2025-02-18/rust-std-beta-i686-unknown-uefi.tar.xz=d8fcf03e16ce9ada0253a2f8899ee9193083e1638d9e0da6cc76886b6ee14c91 -dist/2025-02-18/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz=cb0f09f7d81b1e49a761a94396dcb4e999dbbea7d70e044785992da9a2aa38e2 -dist/2025-02-18/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz=1cecfc8d91f5f3cb7bc67f49795d5e2c74638df0f7d66a3051a851522dae2860 -dist/2025-02-18/rust-std-beta-loongarch64-unknown-linux-musl.tar.gz=0369af7a8b56dac39448a22f1ad27df42c72ccdcb43cb96e7eaecf0c0d8b94e2 -dist/2025-02-18/rust-std-beta-loongarch64-unknown-linux-musl.tar.xz=a395fd16ea741c72b39db5d398a46a90cae8531be620a3468d0dc13f8a9979f0 -dist/2025-02-18/rust-std-beta-loongarch64-unknown-none.tar.gz=e2ce2c57ad140b9088052009efae96ed04ce14c258cd954ee049dfc9146242a7 -dist/2025-02-18/rust-std-beta-loongarch64-unknown-none.tar.xz=a055dd6cc47dad744fe9343d100750ea013cbe3a5bf4fcdac54e80809352a6d3 -dist/2025-02-18/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz=26f8ba1c9594f7336ad530eef0076f2d30752d2edcf96d944cc962dde3d3caff -dist/2025-02-18/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz=32c80782a30c7bf300510e4fa29dad76d9a40bed2d5746c4d55b17fb261d788c -dist/2025-02-18/rust-std-beta-nvptx64-nvidia-cuda.tar.gz=2cd25291aa0c7610f10ab04cdf4ba4d214e0c684bed73d2ef31ae84af2da0eaf -dist/2025-02-18/rust-std-beta-nvptx64-nvidia-cuda.tar.xz=a7f02677a5c35388593142ef95cf56ffe1632df7fd42ff35bff89dafb34a0bdf -dist/2025-02-18/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz=64ee7c6fb36ea45490911ae5557f6a051728a05a7c88b1476489be87456be4bb -dist/2025-02-18/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz=250993b5a1915a8970d91f7a10f3f50c907cc9508d71d3b2c8e20914f90254a6 -dist/2025-02-18/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz=deb267998a725fb0288432a51aeac3004d6430fce8683c91d102b6708e5b99ea -dist/2025-02-18/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz=49ba80f0a2970948699b78fc60ac09f77dda94e56931399c57c2c81fce8df9e4 -dist/2025-02-18/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz=06ff5073e946ed2a5f80f9a5befd7b0c27e9a959cebf26b6cefc5762a0fcdb03 -dist/2025-02-18/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz=27f12f5835f564b03f55d85121c9474b9fc93d3084c5b5d0fc63d33c8c9dcc64 -dist/2025-02-18/rust-std-beta-powerpc64le-unknown-linux-musl.tar.gz=78aff087bbef054b5a6a8d2a1649dd59f69b7f98635eb0c130c4ba87b3018850 -dist/2025-02-18/rust-std-beta-powerpc64le-unknown-linux-musl.tar.xz=e82b6bdfed001c91f8f88f6c37e31ef35f2f25cdca6fe8adfd90d024cc068e15 -dist/2025-02-18/rust-std-beta-riscv32i-unknown-none-elf.tar.gz=8dd6fdb684882ce4087bb96ec2d982c0d808c93c053c774b49cfc705959b4309 -dist/2025-02-18/rust-std-beta-riscv32i-unknown-none-elf.tar.xz=4d6db36241c3d8735e7c2ee84a37ae0cfbc2fc79c6fd259ca4b74e7edb68b8f0 -dist/2025-02-18/rust-std-beta-riscv32im-unknown-none-elf.tar.gz=32e8a2eb316b2a82f80e7268a318df89f732d7cbaba779debe10664aec7d40de -dist/2025-02-18/rust-std-beta-riscv32im-unknown-none-elf.tar.xz=562030f1bdc1307bc0261a2e66c12a6f21fed0ed21fdb2140b1b1d55664aab00 -dist/2025-02-18/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz=52e8c7ab87f5d2cbb712fb54ad8394b50a7f95961e1a7e5ffce981a962899a2c -dist/2025-02-18/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz=74f13bf5f0ff428c323c3041771b653d3ccf5a999105869378bf09a6ce6ca040 -dist/2025-02-18/rust-std-beta-riscv32imafc-unknown-none-elf.tar.gz=e2b8a784b4c6826d00a69de8e1891a40619f4b17c6e54c5cbed349fedefbd8f1 -dist/2025-02-18/rust-std-beta-riscv32imafc-unknown-none-elf.tar.xz=a231848519003a9ea1306a7da2139675516c0d94e5cbd8af140bb1a37515d7fa -dist/2025-02-18/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz=82d33d6527db7adaff8bec04c6edb4f3f7a1609fb5e5a91011a3b48dd47af93e -dist/2025-02-18/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz=bfe440ce80c4547afef2c6b8379bccde9f7206a5406c5a7ed5c06ab460ad8ba1 -dist/2025-02-18/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz=728c559f432bf8487c345967a2ebc9e4eada676a6d56a68ec32d26ee9775857e -dist/2025-02-18/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz=51e7990ff209c27a15d40a684d634e5cad26d55913b897c2be6d92fcb849b7d8 -dist/2025-02-18/rust-std-beta-riscv64gc-unknown-linux-musl.tar.gz=ea66ba0e6af1fc7ce741c0838bc005abc04c6ad85c6831d2e05d04f30066281b -dist/2025-02-18/rust-std-beta-riscv64gc-unknown-linux-musl.tar.xz=7429a295ccda168e41e9717647ba4639eceb81a73d66ad7ba01c9e7f1ca19c03 -dist/2025-02-18/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz=01824c3ca49cfb433de4508282f0395bae8053866691869fb804a3058a403b02 -dist/2025-02-18/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz=67e324c82c6a5c9fd279b9bf5ebabaecf35374c741e5728c2db3fbbb6eab1fd9 -dist/2025-02-18/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz=466d4e5c1912937481fbd22d739987d663f3c771ff0efd676b34fc34e9266f87 -dist/2025-02-18/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz=409c2870098222c09abcb1c89c7394633222bef2cba9756638e8cad058e3c524 -dist/2025-02-18/rust-std-beta-s390x-unknown-linux-gnu.tar.gz=b31e3389756f78bf680982d6c6415c3712567e5050beddae10d2df52de560e61 -dist/2025-02-18/rust-std-beta-s390x-unknown-linux-gnu.tar.xz=729b7433746947b88b8d4f488e2831bff1a92911b8c25f16a1208542e38d5834 -dist/2025-02-18/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz=56caed9608e88e9ed6dec56ec3265d6464633ed57b14a455c626983defc87411 -dist/2025-02-18/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz=9c9d16cac691185cf055117d6888a25f14c72cd110e3bc699c6e78b5d0dc70d8 -dist/2025-02-18/rust-std-beta-sparcv9-sun-solaris.tar.gz=6963215ffa1d2cf9650db8bc36f1eb5c97fb4d824a010c2a65f842fa00b4b4c0 -dist/2025-02-18/rust-std-beta-sparcv9-sun-solaris.tar.xz=9077823bd323a251347336f3c656c6847d5fefb90efed0cacadd510f42afbb74 -dist/2025-02-18/rust-std-beta-thumbv6m-none-eabi.tar.gz=f6d1b17e822403428a6ddf254caf78c75c2d91c208e035590779b51d45b7e081 -dist/2025-02-18/rust-std-beta-thumbv6m-none-eabi.tar.xz=1eb4e8ca0d8a52ddf754aec64b70e7a1f91d2746eef7e3c6d4580a0794cbfae3 -dist/2025-02-18/rust-std-beta-thumbv7em-none-eabi.tar.gz=7793950c2a0016ae90ee8fb70e881047a1f85c82f087fb02532009d6419ba6a8 -dist/2025-02-18/rust-std-beta-thumbv7em-none-eabi.tar.xz=14464141719b2b2c5d4a4b29685f3a2e336c2542ea33af01cfaec2ed7511baba -dist/2025-02-18/rust-std-beta-thumbv7em-none-eabihf.tar.gz=62612b4da1872950af31bf3d9f0a595f019e6c4074874f4cdfa9166c5ff39434 -dist/2025-02-18/rust-std-beta-thumbv7em-none-eabihf.tar.xz=07ab29714f76693f69273a5567408307186b272061501a9ac83eebe944f66d31 -dist/2025-02-18/rust-std-beta-thumbv7m-none-eabi.tar.gz=b2da60ea5d746b607c505279b84aa2a8f3bac3e258ca867f6aeca958e50691c8 -dist/2025-02-18/rust-std-beta-thumbv7m-none-eabi.tar.xz=3eee9280fdd35f30ee9b4a2e5d8614ee916f36cd08629a574f6450721a1fe05b -dist/2025-02-18/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz=c5be169574de4fcd550b67d19834e064b81084e673764390b9f177631f3fb0ed -dist/2025-02-18/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz=bcd6ddf6493cbe17236a74c26da7e16a9a752fd39ab453866ae3301cff0c8375 -dist/2025-02-18/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz=e52c2e8272a9ff9442ae6bafb7526cac424d15d4d6d1d8d210fe981b42da9b73 -dist/2025-02-18/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz=81adef669c6f8f08b941b0befc6af30eb78b2717c3aacd52a1526d9545548c53 -dist/2025-02-18/rust-std-beta-thumbv8m.base-none-eabi.tar.gz=1036f47867b7d29ae468a040c50da016e20a6a3a291714df4193895234591c00 -dist/2025-02-18/rust-std-beta-thumbv8m.base-none-eabi.tar.xz=508b4f1e307d0b033eab345ab5106eb83ad8dad212f491f1ba92b9680f699bc6 -dist/2025-02-18/rust-std-beta-thumbv8m.main-none-eabi.tar.gz=41c806851db8e59dc9ad8a756c8efde7dc14e8ef5dc4feb81be9351d267b6157 -dist/2025-02-18/rust-std-beta-thumbv8m.main-none-eabi.tar.xz=f3bb9c783f4350e491fd683d057521f497314e85576b26808f4edc7d1d8612c6 -dist/2025-02-18/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz=36a3e0675cc972fe6f4f860da47c9d4e0ac175191622c651fbb002207506b627 -dist/2025-02-18/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz=c3287e3ebd4583a576f4bbdcfaa77fc21f6165b18573cbfdeb28593494ec14dc -dist/2025-02-18/rust-std-beta-wasm32-unknown-emscripten.tar.gz=4a7128b50478a05d4fdad69715a0a7c9dcc745aab33cbc2e137cb670c6265001 -dist/2025-02-18/rust-std-beta-wasm32-unknown-emscripten.tar.xz=6e3b5981cca095c2414ad4d23f3e69a942a12c1d51dc9e055ad8409c5edbdcf9 -dist/2025-02-18/rust-std-beta-wasm32-unknown-unknown.tar.gz=3b0cbbb35daf13711e8f211da8e2ed4ade96f728be5e5ad3ca02e4d3e32b7262 -dist/2025-02-18/rust-std-beta-wasm32-unknown-unknown.tar.xz=4e50db69d0917f205a16fa3c4ee5e4012c000194ff75641ddeb49bbec9a2ec49 -dist/2025-02-18/rust-std-beta-wasm32-wasip1.tar.gz=d382d7f9787018480329518035fc4ce3247775633423e0f2940c3670cbdd4705 -dist/2025-02-18/rust-std-beta-wasm32-wasip1.tar.xz=e1d9c800db62bf606d9be9a75dd00ac7190acf3fd3592cbdeba67170ddb092aa -dist/2025-02-18/rust-std-beta-wasm32-wasip1-threads.tar.gz=cc7cd664a483eace96710d341132de4f9cf2113f358722425ddcf84cfe821116 -dist/2025-02-18/rust-std-beta-wasm32-wasip1-threads.tar.xz=17156e3e57e304ab3ab10f8191a9952400182d2a46ebcd39d1cfde97b94c0756 -dist/2025-02-18/rust-std-beta-wasm32-wasip2.tar.gz=7ab89b39693bd1bc3f344dce6ad1c127ef38f64591c7be769d07603b2422800d -dist/2025-02-18/rust-std-beta-wasm32-wasip2.tar.xz=2f53c60d0c0388ff644c17e341368e8b15d4c41b2827b03507d4efee100a1841 -dist/2025-02-18/rust-std-beta-wasm32v1-none.tar.gz=3277ec65149e708925ca7fc062cde92953d01569d2700d2831e6ff68768e5b30 -dist/2025-02-18/rust-std-beta-wasm32v1-none.tar.xz=24df037c2c4bcb3d593033d93b6e26aa1dc38161452220d7a73a23a696dc93bc -dist/2025-02-18/rust-std-beta-x86_64-apple-darwin.tar.gz=3878e1506ee4642fdd1bd5e10025c9c289f8d03b7cea876d2348fabc2675b721 -dist/2025-02-18/rust-std-beta-x86_64-apple-darwin.tar.xz=46bdd522559b61848cfcbc8c55d95b190a134f2a0ac19e3c7ebfaea867f9780b -dist/2025-02-18/rust-std-beta-x86_64-apple-ios.tar.gz=e914a0a4a2824f12764b0b91b0dd97a25416686839f35dea2aabde41c011f850 -dist/2025-02-18/rust-std-beta-x86_64-apple-ios.tar.xz=b44ac0cc8cab86ba9d000d2164786b5bdc115ace7990ead57aaba2b0e02750aa -dist/2025-02-18/rust-std-beta-x86_64-apple-ios-macabi.tar.gz=497c75ec8b5f99a625d898b406d437b8902b8ad42ee1d629a0efd27cfee96e44 -dist/2025-02-18/rust-std-beta-x86_64-apple-ios-macabi.tar.xz=a53ed7bfd16d62a7f51509d32fb6cc6b1f3af331f4c4867cbc1eb57da5c3d521 -dist/2025-02-18/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz=3cec5b6714f156e43c85b4b15377475bc38f65325f61de020bddfc2708b25a7b -dist/2025-02-18/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz=ea2cc73a03644647dec905100154a3238dd819fd0421f770dbc433cd6dc49f33 -dist/2025-02-18/rust-std-beta-x86_64-linux-android.tar.gz=2eaebfe572503b69e34674ed414357c514bcfbf013e6a2a7bb3fb14f501872e8 -dist/2025-02-18/rust-std-beta-x86_64-linux-android.tar.xz=66c4f03b907515831f9a48c8f5036d4c3115e814507a27abe1e423ef4a7e7c0b -dist/2025-02-18/rust-std-beta-x86_64-pc-solaris.tar.gz=4c8f54f1709908a9edabd9e60d8492cda771db4b51fe766f2a2323a10f184e1e -dist/2025-02-18/rust-std-beta-x86_64-pc-solaris.tar.xz=60d74169e80b3e1297b010501fa5a46a29a7541c84ceeff304b4c2ace7631540 -dist/2025-02-18/rust-std-beta-x86_64-pc-windows-gnu.tar.gz=9d043fbcd7e180052b903180114d50c71a2ccbeb22fff7020514b4b0a11a8123 -dist/2025-02-18/rust-std-beta-x86_64-pc-windows-gnu.tar.xz=f08905c0b8192f23f214465d757d93e30aee0250dda279d648e948961e0745ca -dist/2025-02-18/rust-std-beta-x86_64-pc-windows-gnullvm.tar.gz=e35a42a9a6eccc4b738b389fdff24ba01ef23ff8d00fbd34100acafffb9c3763 -dist/2025-02-18/rust-std-beta-x86_64-pc-windows-gnullvm.tar.xz=a1fd2d1b1bb1fe9593df7835b5fb81e5c9453c0bbbc17b9ee5deb0512ad12550 -dist/2025-02-18/rust-std-beta-x86_64-pc-windows-msvc.tar.gz=feada263ce77cd0ec635ae78c8ce34099385a1f89d1eb680576a85a8adf0d75e -dist/2025-02-18/rust-std-beta-x86_64-pc-windows-msvc.tar.xz=ee8def01984eba376773f7a055a18a4096750d26f96ab9150326dc60ece9fbe5 -dist/2025-02-18/rust-std-beta-x86_64-unknown-freebsd.tar.gz=7791a0155a0a3464d07b176383a4b61dcfaef4bf0247c58d447402fac3123186 -dist/2025-02-18/rust-std-beta-x86_64-unknown-freebsd.tar.xz=11bae401884cce0306b415bb1202c2c63f81395677057fbbe12e9302951a9d3d -dist/2025-02-18/rust-std-beta-x86_64-unknown-fuchsia.tar.gz=4d05cd943f4e4250d50a5f732a64f32431a6cfef59b38bc087b1dbe1aa4b9561 -dist/2025-02-18/rust-std-beta-x86_64-unknown-fuchsia.tar.xz=7bdc7161d66b6c330f027f53b15f164c9ad4d55debe77b7c34971a877bf82caa -dist/2025-02-18/rust-std-beta-x86_64-unknown-illumos.tar.gz=01edf8fdab00df25cfea2ade367dc4f66a1d08d11bfd9a7e56b65a723e14b517 -dist/2025-02-18/rust-std-beta-x86_64-unknown-illumos.tar.xz=9efccf8ba6fc68997123924cddd7008b15f1a57170d03597a370346fdc6c83d6 -dist/2025-02-18/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz=9dbfabe77853e672d576e70332e07727882cd6af14dee9a00d5186b43763ce82 -dist/2025-02-18/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz=04e31482a3ff18d8fdff40c4e95b22bc667bc0dd1ba06fadbe2479bae5d97288 -dist/2025-02-18/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz=ebb6e0c56d905ef064fa15449a72746daa9e3998f5aba5c6a3c132bc676228cd -dist/2025-02-18/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz=818fc179c8380f0fb70c46e04086926a69b026591ab62cfbc1051abc5c80012a -dist/2025-02-18/rust-std-beta-x86_64-unknown-linux-musl.tar.gz=c0a1c692a334821d61a9b92cd1332f047175d4335336db3e2129687ba96ce5bc -dist/2025-02-18/rust-std-beta-x86_64-unknown-linux-musl.tar.xz=2c71b87db4cec49e3c620e6b4e0e07f1aaaffe69020b07c87546232ed1ad3b20 -dist/2025-02-18/rust-std-beta-x86_64-unknown-linux-ohos.tar.gz=c1bbf445dd0b187904af5871bf48a720151ef75fdd3dd13161dad01ef5e87bbc -dist/2025-02-18/rust-std-beta-x86_64-unknown-linux-ohos.tar.xz=19963165ec2c35c15024869c16a707bdc90e72032ebf6e203cc67411ec8ba7c7 -dist/2025-02-18/rust-std-beta-x86_64-unknown-netbsd.tar.gz=63fbbd51047125fe30f1954ea19a05d6f051d2a77929952bab326c8ded6db8d3 -dist/2025-02-18/rust-std-beta-x86_64-unknown-netbsd.tar.xz=1c255d1de9c2629210575b862600bf369499a0eb8873178ceff4a337ba9dccfe -dist/2025-02-18/rust-std-beta-x86_64-unknown-none.tar.gz=781f14a54c5e68acde1e68042905a48f687294e2bc61450f422a6e15bf6ab509 -dist/2025-02-18/rust-std-beta-x86_64-unknown-none.tar.xz=d45921b98740f3cce5833bc4fb1e36816f34b81e96c3ca2c76deff4744134c6c -dist/2025-02-18/rust-std-beta-x86_64-unknown-redox.tar.gz=0cd76d3c5b051b0b2015cb08079ea3b5ecbb9b0b68779eb35946721b24c07008 -dist/2025-02-18/rust-std-beta-x86_64-unknown-redox.tar.xz=6dec719cdb7f35f6eafd901414525b40f030566bdf3fb55e3b05de162dbf0741 -dist/2025-02-18/rust-std-beta-x86_64-unknown-uefi.tar.gz=aad1e2cfd4f428acb67d9dac1fab4450eccfe9212f52f99f06c09899285b6b1e -dist/2025-02-18/rust-std-beta-x86_64-unknown-uefi.tar.xz=4252b618ffc906949756ad28a5437d11b0353fe1d755ee1d23502a208bdee74c -dist/2025-02-18/cargo-beta-aarch64-apple-darwin.tar.gz=2f7f459d2595d3f60bcef4ccbd3c72095a3ec54fa3f2221a647ae892c308d5b2 -dist/2025-02-18/cargo-beta-aarch64-apple-darwin.tar.xz=501feb9138f3c11a13fd649d6573924ead10f5e6fb1e759d880684bff11c12be -dist/2025-02-18/cargo-beta-aarch64-pc-windows-msvc.tar.gz=b589177b0287a42ce17939dbbee92d883dfec88ebad33bf9a719a3cb2f446533 -dist/2025-02-18/cargo-beta-aarch64-pc-windows-msvc.tar.xz=d795082d304ecdde233a4b6bb3aa558392b2c5a1553fab213ee99648c49f7a51 -dist/2025-02-18/cargo-beta-aarch64-unknown-linux-gnu.tar.gz=8444d938514ad2d55769cf614774dfb4e5a27c34f8ba8b49329a2bcf0b000162 -dist/2025-02-18/cargo-beta-aarch64-unknown-linux-gnu.tar.xz=02e52fc13ae52066031ac40dad039ad752b83582e5f9e74ecef206aa9206ac16 -dist/2025-02-18/cargo-beta-aarch64-unknown-linux-musl.tar.gz=e89709bb552e7ee73de02b08c6d8820b07bccdc09777eff9716efabb2bdd50cd -dist/2025-02-18/cargo-beta-aarch64-unknown-linux-musl.tar.xz=50944f0e51190f9db065764afc7a41a3a1e39767bd1ef5ec659c98fe9243cc98 -dist/2025-02-18/cargo-beta-arm-unknown-linux-gnueabi.tar.gz=0343dfc2f015d476b3aca59b33dd75f907f595bc24715e6c518194ab1a5dfec1 -dist/2025-02-18/cargo-beta-arm-unknown-linux-gnueabi.tar.xz=3dd6c378c10172b1abfdd1db2fa764d1b48153ac1b5065cf124399941d036e56 -dist/2025-02-18/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz=6eac5ffb9adaf2591d3b1872249f4a959c04afdf6694e62dc850936aa8d35972 -dist/2025-02-18/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz=484510e6b9519c2b047864584253c8c1f725ce843e8dd3117349032314737462 -dist/2025-02-18/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz=fcf4d4b2d401ea689ee32f38b4a61c77b52ff4d3d114b23d0262bd02c3d1ab5d -dist/2025-02-18/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz=1a75296c42d6cf93a5e51ecb2b2bfbf0cdea350668d610e8b0c90937163b4f33 -dist/2025-02-18/cargo-beta-i686-pc-windows-gnu.tar.gz=d1b5147ec79466ab9441825b4761e89cebe57ad21a3199b0eca0779683c45ed6 -dist/2025-02-18/cargo-beta-i686-pc-windows-gnu.tar.xz=980850e06ccd90512baebbfe3baaa65b5c089edbae8146fd940c708fd7556abc -dist/2025-02-18/cargo-beta-i686-pc-windows-msvc.tar.gz=78c67ba481cc7b855b54a2edc0297bfb5eadcd83d5a028b05291415417bc6947 -dist/2025-02-18/cargo-beta-i686-pc-windows-msvc.tar.xz=6ea74c750e6e0a794965c6616e5b1a82dee295815b0c24a3898952b1a5a02c8a -dist/2025-02-18/cargo-beta-i686-unknown-linux-gnu.tar.gz=a0c8f67fe77b94674698b4816c081e2ef08500990c0f9eb069d0190df9c4f129 -dist/2025-02-18/cargo-beta-i686-unknown-linux-gnu.tar.xz=9b13f958ec4edff194858e90c54866a129e88769a76fe22582b07e17540708c3 -dist/2025-02-18/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz=f4d2f1c8a7bec6d2b8378aa87a324c42f0f414962174b40b6f0d1dc21d0cacf4 -dist/2025-02-18/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz=f25659ef3be1a28da8821eb178e02108f41cd5c0b87aa01a052a3a90e7a9da50 -dist/2025-02-18/cargo-beta-loongarch64-unknown-linux-musl.tar.gz=b687a7c3fac08680818804e034af6689f1bbcf8fc0e406c99b2a49ddae1e900d -dist/2025-02-18/cargo-beta-loongarch64-unknown-linux-musl.tar.xz=e33818d2f94e8ba148dbf8cd53d6396e370157acba6d0865a5ac71d292939a0a -dist/2025-02-18/cargo-beta-powerpc-unknown-linux-gnu.tar.gz=9cdc2115bd2022cb0b0ac4f1c71142c064957137decc028dde7585acabb8b780 -dist/2025-02-18/cargo-beta-powerpc-unknown-linux-gnu.tar.xz=f722447494f0a7af9c31b71364aa4a2fde79a9887440d8281e4561f7d71620d3 -dist/2025-02-18/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz=d8a30f9e48e89cb1d18532fd7fbef8eeceef6bc602ffaf9e730c635e2fdbb156 -dist/2025-02-18/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz=ec6b3b1595c5761b8092a04a412e79534c28910ed78ed792c9af7ddc4d92a389 -dist/2025-02-18/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz=4bf9c73173199fd3ca952d33702288deb483c7fd392179352135b64e7e8fadb4 -dist/2025-02-18/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz=12aa06644e07344a77d0c16dc1ed96bfba63de02df1f432d57b82f8a1e2282b6 -dist/2025-02-18/cargo-beta-powerpc64le-unknown-linux-musl.tar.gz=eab362146d449dcdd10740c8e6f9dec6e640ffcca162eb51febbc835e34acdfd -dist/2025-02-18/cargo-beta-powerpc64le-unknown-linux-musl.tar.xz=867b716eae9225c66c0ab4642e4e497055ad2effd24343bdf80354ce2845d6f9 -dist/2025-02-18/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz=0503ba2e4b1d668fa3a3174f96ec3fcc12ff767574a7af8ef5fc824ca86dc965 -dist/2025-02-18/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz=478b9f1d4f517f93f15530d27a7d55ea29cdd06eccf01176ffd08c0ee3204c1f -dist/2025-02-18/cargo-beta-s390x-unknown-linux-gnu.tar.gz=419a679aaf6e164649538916daf28081a063bd56c7b86ff0e2df58072f334fdc -dist/2025-02-18/cargo-beta-s390x-unknown-linux-gnu.tar.xz=31b39e242035036c1101412b7c86387e1183063ff5f6ce67d311d0764435a588 -dist/2025-02-18/cargo-beta-x86_64-apple-darwin.tar.gz=d6d5224228dd54b6d16be30271111620c02fd88e656b8bbd22452b66b0d5cb56 -dist/2025-02-18/cargo-beta-x86_64-apple-darwin.tar.xz=cbeff7c031b4ab4732207b90ee8849b27f03cb28d3e085bf4d70444347dbfc99 -dist/2025-02-18/cargo-beta-x86_64-pc-windows-gnu.tar.gz=ae5922955ec579732aacd8112bc53bf5333438eb81d0f81dc5f387888ac979a3 -dist/2025-02-18/cargo-beta-x86_64-pc-windows-gnu.tar.xz=553c55a2bc8eae2c8ba831823a97f2232808af1f753642ec4cdd09c33dd3f6ae -dist/2025-02-18/cargo-beta-x86_64-pc-windows-msvc.tar.gz=d9b2cf14565478429fba6266f0c86a58f3bbd1ce11a63268828b33ccb55759cf -dist/2025-02-18/cargo-beta-x86_64-pc-windows-msvc.tar.xz=2e8c0560355d11a038219072d2503860f5c5b3cd137b89ad931f54d9bba60499 -dist/2025-02-18/cargo-beta-x86_64-unknown-freebsd.tar.gz=4b528361607845e6f8ece403bbdb8d77c6159ec137396319562ea2772502792f -dist/2025-02-18/cargo-beta-x86_64-unknown-freebsd.tar.xz=c244ec4f97420c29c690e32bd6d8f14994bf1d990747f31a3dc0f2b37644493e -dist/2025-02-18/cargo-beta-x86_64-unknown-illumos.tar.gz=7d3b49df93e87322a9e99e36c6df020d3311c5538ad2298d8b5d8f2d9ad3e0d3 -dist/2025-02-18/cargo-beta-x86_64-unknown-illumos.tar.xz=136ce90487448ee770472d4bd2c0d9c96200f0ec762419feb42fefa26ba36b58 -dist/2025-02-18/cargo-beta-x86_64-unknown-linux-gnu.tar.gz=510538965ea142405925d3f4f03a87783516407989b8aa7be07fb84c0680e9fa -dist/2025-02-18/cargo-beta-x86_64-unknown-linux-gnu.tar.xz=a8c569398d71cab0b90c809b1d869a2e3c5037407b5af804df08c205775981c2 -dist/2025-02-18/cargo-beta-x86_64-unknown-linux-musl.tar.gz=1493f66e5cb12e8b955841804e7df745e26daea2278144aa57670192c4c62cef -dist/2025-02-18/cargo-beta-x86_64-unknown-linux-musl.tar.xz=472bbe49415557b75b572879d0c33750731c1fe9e56cc6ef3b0fd5532e56446c -dist/2025-02-18/cargo-beta-x86_64-unknown-netbsd.tar.gz=d3baa6019e13449c01fbeebebce42027ce4ba70841cf28733f6849e7c6ce5d89 -dist/2025-02-18/cargo-beta-x86_64-unknown-netbsd.tar.xz=0db9af42e9ad914a99db4924721c895cdf490bc5351bc8c2d8993e3569e952e4 -dist/2025-02-18/clippy-beta-aarch64-apple-darwin.tar.gz=6ce3b464744082131c99a213454225e5702564c83032e11dd0f3d95530a4e0af -dist/2025-02-18/clippy-beta-aarch64-apple-darwin.tar.xz=925baff0d91b959a99c989a4ada70973baf3da03e1d7e7e8be1fa334c3acbc50 -dist/2025-02-18/clippy-beta-aarch64-pc-windows-msvc.tar.gz=76d265c2fb6280eb8ed399501964f301a50e09e548cee708ebacc978d8db538c -dist/2025-02-18/clippy-beta-aarch64-pc-windows-msvc.tar.xz=e3d1d69cbc838ab639b2e41537b10266f1b6998a228882d4041f35cbb8984909 -dist/2025-02-18/clippy-beta-aarch64-unknown-linux-gnu.tar.gz=918191cad727d795b51f892abb6e4fc87ed735bfcb51433cfb4371cb8be8690c -dist/2025-02-18/clippy-beta-aarch64-unknown-linux-gnu.tar.xz=157d6eb9e7dd80dda7daae5584d095a5e68d13ba8b1d1229e90b5b51f6670e8d -dist/2025-02-18/clippy-beta-aarch64-unknown-linux-musl.tar.gz=fd4de290450e3d3c9188263d9506167e298f4c2d4c781fb3573806694b5ca1ba -dist/2025-02-18/clippy-beta-aarch64-unknown-linux-musl.tar.xz=335c5fd24d1c118e4d1d8abc43d3529dafc9b30af39f6b009924cd0fea676182 -dist/2025-02-18/clippy-beta-arm-unknown-linux-gnueabi.tar.gz=209cdd2042e293d1061b149d97333515821dda0ffeb9b30f24dd2dbb4c1ad548 -dist/2025-02-18/clippy-beta-arm-unknown-linux-gnueabi.tar.xz=57dbfdc34ff4e74aaa8776b80d35aaf0317fdc314ee4b0f3bf58fc672963cf38 -dist/2025-02-18/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz=a89a2562fe9ac6492a5de220c395f433b0e53a8b29c72b3a8d4843f996649ca6 -dist/2025-02-18/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz=0e6ff6453df1397e7b12e7e356e7c7300cfb1f85bc3a6705735067128d2a8135 -dist/2025-02-18/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz=7764c2dbaf217f4b1d8ca4ed2ceaacbb91e8010d26ae1bb10b808afd5dc6a798 -dist/2025-02-18/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz=b7a042eb6830653a623c6299ef57492ae6c9b51a9cd8480f0a6fc2fb6d378bbb -dist/2025-02-18/clippy-beta-i686-pc-windows-gnu.tar.gz=ff41e5b666b3531ccdc0ee836dceb270179d6a849e47024eedc6ea309d36791a -dist/2025-02-18/clippy-beta-i686-pc-windows-gnu.tar.xz=98c6386b63ed89dd96beea223f4c720320b6ca460f11b77c46427e128034cbbb -dist/2025-02-18/clippy-beta-i686-pc-windows-msvc.tar.gz=12bd371402e4d3251f60fa29b3b3aca88b4480229088b68791dffbb4ae1554ce -dist/2025-02-18/clippy-beta-i686-pc-windows-msvc.tar.xz=62a22d1e9b4fdba254e549f5edb276bef5252754ba67a76526d5aeca85515646 -dist/2025-02-18/clippy-beta-i686-unknown-linux-gnu.tar.gz=04179b3a20a68ae2fd8444832ea4edd8155dc9296c7a1edf101053e3ff934891 -dist/2025-02-18/clippy-beta-i686-unknown-linux-gnu.tar.xz=c955e464e99097025fc7d0e42bf90342f74f475c5148526df2f51ca46ce8db4d -dist/2025-02-18/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz=6f58d326a1f2a35246384640b999f95a961a9fe1e5a3c4a3e67d7f96e1ef43fb -dist/2025-02-18/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz=583b1d55a38fdd473a3f3f3cc0fbeac808fbeb593b8b45c7a6b8a09dec0d68cf -dist/2025-02-18/clippy-beta-loongarch64-unknown-linux-musl.tar.gz=80d73fe94ecbbcdb14b35e1616d52e0bb9b1f04dcdd4fc384e7103cc36325014 -dist/2025-02-18/clippy-beta-loongarch64-unknown-linux-musl.tar.xz=1bae908e4d3931eb4dc71ac1524f990bbccaadd9d30897bf516899baebd4c5d5 -dist/2025-02-18/clippy-beta-powerpc-unknown-linux-gnu.tar.gz=b882e7ea97e0d36b289a46ef84b14b2b44ccea93ebdc77b2ab3430361ad15b1f -dist/2025-02-18/clippy-beta-powerpc-unknown-linux-gnu.tar.xz=91e52dc398dccbafd040e401f155c204f2a14d5f62aecfc24912910d5e45008d -dist/2025-02-18/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz=c81497f2b2d2670b9dea2e35804e10780c1631a8761d4bc3331767c1ccaad6b9 -dist/2025-02-18/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz=6236e129f3e551a3126fa07662cc8ad512ad5fcf436a8da9e27a915ad4c234cf -dist/2025-02-18/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz=1b031f055ea4ab4a9da0c8bfb0037e92b493caf7879351f8b404a96c447ec92c -dist/2025-02-18/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz=2f07224e49f7cab10d673116d9dee9f964b4c44ac3db336e7ddbab9e0b1bc698 -dist/2025-02-18/clippy-beta-powerpc64le-unknown-linux-musl.tar.gz=84a8295a7066d258404c87d2269a01d89cc7efd0f143ab53689597f3fb351417 -dist/2025-02-18/clippy-beta-powerpc64le-unknown-linux-musl.tar.xz=019460a6b0e1c5c1331d5a54f3e45306ba0d1b1c2206e2e69f38c1c3501cf741 -dist/2025-02-18/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz=aba8f7bd0a89205961f9803418cdf9bb63a7d72bab4a1ff937f4a142921f4833 -dist/2025-02-18/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz=4607503ba131ca655dab86ad48c1737f216f8ec25ba6dfddbf1f0807e5a6dd2a -dist/2025-02-18/clippy-beta-s390x-unknown-linux-gnu.tar.gz=b0170f9b9e13d4f6e016124fd40c858e00155479fb4f96c1edc896130bb76dcd -dist/2025-02-18/clippy-beta-s390x-unknown-linux-gnu.tar.xz=397f0a8944beffb87c74717bd0f422836b3daccfa848d91c0a65875031bf12fa -dist/2025-02-18/clippy-beta-x86_64-apple-darwin.tar.gz=11be90b9b09f4e24e56df2a602ed8161023314514121d9f76e424fb628df468c -dist/2025-02-18/clippy-beta-x86_64-apple-darwin.tar.xz=16d313798f12d0e74f888b627e079606958de58eb2ca4c70d5f7de8cce72620c -dist/2025-02-18/clippy-beta-x86_64-pc-windows-gnu.tar.gz=41ed081e4a7b205cde3fe958db18ffe1c1ac5a9c336f965a03fe89499a3eddbd -dist/2025-02-18/clippy-beta-x86_64-pc-windows-gnu.tar.xz=daaa3267dcbb3daa0cae47861683f29da5b7419214ec5949e242aa93e3f87148 -dist/2025-02-18/clippy-beta-x86_64-pc-windows-msvc.tar.gz=6d9b8f549e34d8fb65987b39c01c27fbb0e18e8950a07ec6fd1888d01e253971 -dist/2025-02-18/clippy-beta-x86_64-pc-windows-msvc.tar.xz=1c26b51c484f5b10ee693212e258fb86c63a2b59e631542918799d480a3587d4 -dist/2025-02-18/clippy-beta-x86_64-unknown-freebsd.tar.gz=a42777c542773a4262ac9fcb07ed13f769957f58a795160441241ad4e4f5258a -dist/2025-02-18/clippy-beta-x86_64-unknown-freebsd.tar.xz=9e809fa141ac68557f203aec2a6cc02a4ddd22169595c40ed4a964801ccadb1d -dist/2025-02-18/clippy-beta-x86_64-unknown-illumos.tar.gz=4e65b5db249a18e73247029506f619393be7042f2c91a00301962effb76a18ea -dist/2025-02-18/clippy-beta-x86_64-unknown-illumos.tar.xz=6714018d069fbce271c177f1941a6b77f18b67af462596aff273f7db1970ef4a -dist/2025-02-18/clippy-beta-x86_64-unknown-linux-gnu.tar.gz=72a8ee3bad3d638af0cc3ba6c0c0ed1594abe609573de71d9c7a884a8ac7645c -dist/2025-02-18/clippy-beta-x86_64-unknown-linux-gnu.tar.xz=f622befd60c3695d3d62642b953deabc3e3f04b32cae8a7cc228cb534244adbc -dist/2025-02-18/clippy-beta-x86_64-unknown-linux-musl.tar.gz=8946e02ab98281b6949c4d725a5fe3fb1bfc86651a675e451f126fec8d053762 -dist/2025-02-18/clippy-beta-x86_64-unknown-linux-musl.tar.xz=425907bd4320c516647e5dd6df6154746d64854fe2e78f27283b7fcb27164de7 -dist/2025-02-18/clippy-beta-x86_64-unknown-netbsd.tar.gz=505208d2d73ed7278e5b29d8450c382a89e4c0992d6199243e07c8640c611b85 -dist/2025-02-18/clippy-beta-x86_64-unknown-netbsd.tar.xz=d4b0306e7d7db5cb7da977a7ca72fff2070f102ac385c3b35286da25033582af -dist/2025-02-18/rustfmt-nightly-aarch64-apple-darwin.tar.gz=13854358645915af29d9337bb87301aa1a5e76ecc86a934dd640d02af3255ea2 -dist/2025-02-18/rustfmt-nightly-aarch64-apple-darwin.tar.xz=0cd190bd5a064235f9cd6f6e7eae4725b3b53ae36493b3ea54b8f190372ba3ee -dist/2025-02-18/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz=20b3f8c4c7b02158181970804d419b16f85a1083943e1c384e0bcef441f32aff -dist/2025-02-18/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz=1ace0f10060d2fc35a1f05a1d61adebf95212e8b46a2234c2e78030481c1b3e9 -dist/2025-02-18/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz=e5ad64d67931df49f6b7d3448e9860699d6549c2b4a96abda1a03069b45f339b -dist/2025-02-18/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz=e8112ae80c8fd43452612b79dabf471be561b7e828c9a2141c698429d761a49b -dist/2025-02-18/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz=8ad36bbe888e61b6d7e540ba4a2478652f14c1b28dbbcaab732003293b7c985b -dist/2025-02-18/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz=1794af320a273f4a951942ff0cd73a359fd82a971c572af1ab7ff2961340791c -dist/2025-02-18/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz=67b9d1d3c46bcce0aa94d6cb4155cdf7376677caf2e19685553266f781eb7cc1 -dist/2025-02-18/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz=9d7b97a85b1368cfc78f1df42afb08aa04eb17fbb91ceb3c379d59fab4294890 -dist/2025-02-18/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz=42396c7bd206d0fa07f3b44fcb894ac074e2af07eb158c1ef630bb5467151c8f -dist/2025-02-18/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz=6881c9681342f1430fd9cc8c9786cee40522be3dcd0fc4dcf2b3957d9d53f03e -dist/2025-02-18/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz=6cb8973ac4215d67aad9bb56521024626d7883a6e00748623a728dd9107698db -dist/2025-02-18/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz=920d877e04260be6ccf9963bea12220e886df673cbc48b55925650f8f5b21d9f -dist/2025-02-18/rustfmt-nightly-i686-pc-windows-gnu.tar.gz=ec5c7105f2c2a2055f704435fff9edbbee0a234e63050676c034f983d4e341ee -dist/2025-02-18/rustfmt-nightly-i686-pc-windows-gnu.tar.xz=ab408b64db4bd47abf8e24c0f611f2c67a3c9ce7e2138a92772e0510c6dce5f9 -dist/2025-02-18/rustfmt-nightly-i686-pc-windows-msvc.tar.gz=d04250bc2e57fcb03f1d80722f2ac1117f797d768262d7630c9b53af808a8c9d -dist/2025-02-18/rustfmt-nightly-i686-pc-windows-msvc.tar.xz=6d7be9f04a46040f068544e32eb84c98afc1f81b750beb229def84a7513150fb -dist/2025-02-18/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz=94f585a7c666dc9c95c3ae14744e614a3fbe37b3e31b476b48bc4ef3289bdd46 -dist/2025-02-18/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz=83e82932245b3c1d3c275126184f942b9cb8bf20f0d40c7cb1efb6f918327b9d -dist/2025-02-18/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz=9c8cb5a14294c48f8ee972d5f460751a8bae5b541bff3d872c85812b621c39d8 -dist/2025-02-18/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz=4f616740bef30599e6950ae2d8ae694513003e14122f6002a9d60bdc64f77cfc -dist/2025-02-18/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.gz=a668e7be7946f6a9099486a40256f17832288322c9237d931f172ed76caf678d -dist/2025-02-18/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.xz=b02c57c217f358ff4344ee2afcbb8353cffc0a012f970d9520ad233d188d59e2 -dist/2025-02-18/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz=9baf04e268999020372b21484ecc4f5aa001b3bcee05619ae5b0a11571a3a45f -dist/2025-02-18/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz=b2c2c3a0eecca7b4c35eabf09e215158c48eb426899e365db1c91c1c560ad255 -dist/2025-02-18/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz=c42df8e575a24a5edbc58b5b46a89a226188d2aafc59da89d568acbb6e9cceb6 -dist/2025-02-18/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz=fee7c373bb8fee5c7d4e43d7a7046d3bb156d3e496ed21cddf20c21ffdef3e69 -dist/2025-02-18/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz=a0ae21a3b56e20e667c72d92ad4bacd4abb77d1fea32949d7dd62a56d6b531d3 -dist/2025-02-18/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz=fc7e21cbd61169b37e81c73d4d5353d7e54ca322fd01491d9f37ff3666557e7e -dist/2025-02-18/rustfmt-nightly-powerpc64le-unknown-linux-musl.tar.gz=e08ceaa9241c2e53041b107af09674ca4fbc4e12b1371254869e3d80d5c907ab -dist/2025-02-18/rustfmt-nightly-powerpc64le-unknown-linux-musl.tar.xz=9f208dc6e5938a128174263349345e9fe7f587689f6a53fe5d026ae3c6fbed2c -dist/2025-02-18/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz=44abe49dfc0492cb3ab28f0aae0d784c982063399a38f8f13016f3dde123948a -dist/2025-02-18/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz=72fa294f92ab244608c384d6ad6eea0e540e6fc58181fd65a4fce0c5029c39fd -dist/2025-02-18/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz=556dcf393856c6d9c9c6731b02e34146f9f956f588025b6a614b8802032d125a -dist/2025-02-18/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz=93906364910891f71e13e0ecb07f02b707e42e11a0f1b117c590804dfa16a9d1 -dist/2025-02-18/rustfmt-nightly-x86_64-apple-darwin.tar.gz=7022c760f457075fb353e59984dcb551600581a315fd17ea1320b892b1d99a55 -dist/2025-02-18/rustfmt-nightly-x86_64-apple-darwin.tar.xz=e085ee261acbaa41361a0263dd8f13644f8a4e3679eca6bb0851b03c647b80e8 -dist/2025-02-18/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz=2436e18fefae02554e620a1131455d923c1b67e00e878c75a941a6eedb4eae28 -dist/2025-02-18/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz=9f6e37b5973925d07115e517e6a3e490a221218f48fd101a20670da2c3d01add -dist/2025-02-18/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz=78f492a26981e7a6f9f3e8bbd1e880682e55cede081f3cfb13a2ec5f736edbb2 -dist/2025-02-18/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz=d4d788fa3e3b9a598aa7baec47af3b56362224533be85dd68a411f35f8800b2d -dist/2025-02-18/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz=8922186dedf0b12e9aa2bb041b76be8fccd43b9322c3496c688355f34bbd7a59 -dist/2025-02-18/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz=6325e43f2c28118a9525f5c5fc09de9fb9a09ffb4aaad31f28d394c233ee8398 -dist/2025-02-18/rustfmt-nightly-x86_64-unknown-illumos.tar.gz=7f317107f8319c650973cef52f745c2a8e57ea6a087910b6979404f2cb2f1cff -dist/2025-02-18/rustfmt-nightly-x86_64-unknown-illumos.tar.xz=b273be4897e83f786020bce1dc5dd1caf01e2ea43f085391c0031277718feba0 -dist/2025-02-18/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz=0373011266a9ab62f45fa137a4bfdb970ccad8bbbb74bf776466d203f28d226b -dist/2025-02-18/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz=62748525678370dbda7f1cbd12a384e95d4af76103de998785278f6d1f076177 -dist/2025-02-18/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz=30eeb980720d8c22bc45c012c4fd212e118195206b8b993630f074e526e6693a -dist/2025-02-18/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz=2f3843d9544fa56dc87f1d13ef79c68c1e68d84bec007f0345159a7448368dfe -dist/2025-02-18/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz=a86eaeab8f5f45d16eaf355a46d8b19afcd8c46db732432091156e381aa79cb6 -dist/2025-02-18/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz=144cd28da601c331f6501c634ad89286be213a69cf521435e35657c5f6fe2afd -dist/2025-02-18/rustc-nightly-aarch64-apple-darwin.tar.gz=21101db859a550ab39de1ecdec75f4f058934ed8e0ab7dfadbb2efab57bc5e0a -dist/2025-02-18/rustc-nightly-aarch64-apple-darwin.tar.xz=a40da26e908810701112b9d3f9ab83515c8e2f4b33219f8f773c5459366d37e1 -dist/2025-02-18/rustc-nightly-aarch64-pc-windows-msvc.tar.gz=5391bc993b7208c10a6f4256417c9f76a4a33d167b2fd547b57af614d3fc8458 -dist/2025-02-18/rustc-nightly-aarch64-pc-windows-msvc.tar.xz=d72a205f52173b1726d8341a9436e62439b1987fe0cd4d2bbff740e38f629b41 -dist/2025-02-18/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz=185e052bf2ba1cda4b6ad1c49a9f65b906899ad1ca09cd864d6041941ad344dc -dist/2025-02-18/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz=640f7af3fef5f0abacdaa292ce17255433ee16f12bfc2d2e81d70afcf9fcdd8f -dist/2025-02-18/rustc-nightly-aarch64-unknown-linux-musl.tar.gz=8cdee468a90606b21a8cc3305f2b6b3eb7e3d687263f4ca8319c709cda2a324f -dist/2025-02-18/rustc-nightly-aarch64-unknown-linux-musl.tar.xz=358bbfb24816c781e07d5480a5606dce27068f856c0a606873ceba05c9540c3c -dist/2025-02-18/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz=b220757cc8ed39c429c49b55e293ded3e07239d2e2bab8a9054ce55581393c47 -dist/2025-02-18/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz=18d3cbc49e44b7810b498517d21390e39bee7ca8351c8b321592e83301ad79e9 -dist/2025-02-18/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz=77ac127bae48859f57d9bd8337ac4a0bda95b1190e451abeaf7e77f1a240a647 -dist/2025-02-18/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz=79009bbf0325f9db0c905d74cb0f139c92478a0b2fb5edaf383366b0e654a172 -dist/2025-02-18/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz=8264c7ed7bc47953ae76cf87236655562a55846abb195bc9281833a0da168db6 -dist/2025-02-18/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz=c6a85e7f2a469fb05f0a84ceaea25dc0d95b57bd4d68dcee447918162cb36b2a -dist/2025-02-18/rustc-nightly-i686-pc-windows-gnu.tar.gz=0f31c9ed4ba7e942806fc2927d305f9d3ad676cf81e53e0f7c4123aef375fedc -dist/2025-02-18/rustc-nightly-i686-pc-windows-gnu.tar.xz=350f4b46dee2aa6ebfc31912cfae5c7c1db99b298c52834308e95c504cadbe7d -dist/2025-02-18/rustc-nightly-i686-pc-windows-msvc.tar.gz=e12a40b7178995ac223eb7fa317e1114a988256d99fe615f70d64cf3f2891fa7 -dist/2025-02-18/rustc-nightly-i686-pc-windows-msvc.tar.xz=09fb4a4744a55bf8fd6371e5496f6a9c00b119ddf20b19855653d66d9a618214 -dist/2025-02-18/rustc-nightly-i686-unknown-linux-gnu.tar.gz=52361a34730f8bf14eefad7e51f66fc3ba3be405a364d4520103208fe8fdc056 -dist/2025-02-18/rustc-nightly-i686-unknown-linux-gnu.tar.xz=ea81964fc8bcb8b43968acb6a4f7fdec2ddea9f75a8be5446fb01b4267d0d75f -dist/2025-02-18/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz=11e7a143112b6abf818652e425b6f092464cc9d8f5286e90180c7af8d5939643 -dist/2025-02-18/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz=86f5d40eecccb623ff744bbc1fb40458949db9b2f8501cadc6be9bca95f6c693 -dist/2025-02-18/rustc-nightly-loongarch64-unknown-linux-musl.tar.gz=1be7ecdf609958fb0ef945203b22a600f1e343ee7fc581f6451eecd39f1e0b7e -dist/2025-02-18/rustc-nightly-loongarch64-unknown-linux-musl.tar.xz=03d3b67092da64f7b7be7ba4e115cfad4071c0bea3abb5e60ac166127713b169 -dist/2025-02-18/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz=4e33311490c2dcf79a16307e1141ce37574ec3829a1e93d0f5b06ff68ad5c861 -dist/2025-02-18/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz=504c102fa1c8dc5042cb354a60b87c0f6d47f9adab341f496af723f3ea8bd548 -dist/2025-02-18/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz=c559971ae42a5e0e999e2fe119033bffbfe8c64b767e697e0b95f5dfc271d13e -dist/2025-02-18/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz=51159ab0ade5a62e128b6c794da5c9815324470c468e5808b50663c3a0df6d39 -dist/2025-02-18/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz=a8134f8f7ea4531d54ab5c0a0894f140ce5182a384c57395edbe06ed551970ab -dist/2025-02-18/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz=8f2f5d88ba9f4ee946db5f00d56c4852213dcb0b46ce2793966af6c96d934dc6 -dist/2025-02-18/rustc-nightly-powerpc64le-unknown-linux-musl.tar.gz=7bfc6666757b57fa6160d076a9eb52852dcb5bf788bd12c0f014bbd552b8a7ef -dist/2025-02-18/rustc-nightly-powerpc64le-unknown-linux-musl.tar.xz=e2c3293e2a90012ad48bbc2b6f285adf20f356ff1f4146b3f11543511bbb3c44 -dist/2025-02-18/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz=f582a59b5a6cbe6d58400c69f1cad4f34d0f1541c1ffb9df3ce71846edd828fe -dist/2025-02-18/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz=244384bd94f7c3606a086abc8be9d36a855faf09d9bb6b121f42e168c526e717 -dist/2025-02-18/rustc-nightly-s390x-unknown-linux-gnu.tar.gz=327e29662140cb76b1ff362fe51f9a12fb4ec304929317ed8de7295fdb9c5b9f -dist/2025-02-18/rustc-nightly-s390x-unknown-linux-gnu.tar.xz=a2c4e19b3a8dabd5c8fe72edd60d1925947cad5971c77c62f12fca764c6e4e7a -dist/2025-02-18/rustc-nightly-x86_64-apple-darwin.tar.gz=b6812f92e08cff1b706380637fdd553b04b9cea746ffb69e6488fbec70680136 -dist/2025-02-18/rustc-nightly-x86_64-apple-darwin.tar.xz=f2502b2a810938c41e2302a9112c97d04998ada16583373e6488bcca00595761 -dist/2025-02-18/rustc-nightly-x86_64-pc-windows-gnu.tar.gz=9159f7323718c6a8b98f7de5186ed507b3dca1bfcce9bdfa6437313bd630a989 -dist/2025-02-18/rustc-nightly-x86_64-pc-windows-gnu.tar.xz=10d54c9b80570b6729d0e68f017d862c5126f09b42f150d004aa8fd5382b165c -dist/2025-02-18/rustc-nightly-x86_64-pc-windows-msvc.tar.gz=1f29c1aef1dcc3ff9f2e3013b7ea0521829e6e474f9058cb70fea65180230b41 -dist/2025-02-18/rustc-nightly-x86_64-pc-windows-msvc.tar.xz=18cddaf7653f146dcc8a44ca0cc33c6dd3c24f28fff87aedca01fe3beaaa9915 -dist/2025-02-18/rustc-nightly-x86_64-unknown-freebsd.tar.gz=e57c1477cf9b75e727db48b8b75435d65aa0a6ef0eb566ac1890b576c330f64f -dist/2025-02-18/rustc-nightly-x86_64-unknown-freebsd.tar.xz=725f9e9d25b7ad6f60d5596684964b0c3a63d98a62a2aeda6a134b9f02fdb681 -dist/2025-02-18/rustc-nightly-x86_64-unknown-illumos.tar.gz=86a9034fa275c0fc73d639fe6437fc4d2621bf12897c9f83a81ab6056173a95f -dist/2025-02-18/rustc-nightly-x86_64-unknown-illumos.tar.xz=4aeef66ad8a908589ddf0d89581a6ca809b7c2a57f06bbda6fd3927b531fe07b -dist/2025-02-18/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz=907aa282fb9f3d96c9fb03dadd62f4ea766e1242fe19106ae331a4f49a9b20f0 -dist/2025-02-18/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz=e63d13a6acd596ebfd7bf65b292eedd2a5e260b536ca11517a3fe1d8e6a6241f -dist/2025-02-18/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=b7bee098c32b321551f68e96e002f85e3a0323c864aa7f65641a58ae24f4238e -dist/2025-02-18/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=e5c22c2fab89c7ba548b11104c54e8f82cafb1979ba73a318682bb10ed9e4fb9 -dist/2025-02-18/rustc-nightly-x86_64-unknown-netbsd.tar.gz=7bf40bffe95437244f6f8a5fde69499f42d2b716e166115530fbcdbdcd837887 -dist/2025-02-18/rustc-nightly-x86_64-unknown-netbsd.tar.xz=0adeaa382f289233ffc9229e116a340ac03a861f0fdbb5bd35aaf5d0d7370877 \ No newline at end of file +dist/2025-04-02/rustc-beta-aarch64-apple-darwin.tar.gz=42fbc48c6f9034c1d47029491e0adc7aaa1adecf429e22ea9eb6d36225ed13e7 +dist/2025-04-02/rustc-beta-aarch64-apple-darwin.tar.xz=08f88363fd42d66d537c0a296502f94c3a3fecf59a004613c9acff33eb0b0207 +dist/2025-04-02/rustc-beta-aarch64-pc-windows-msvc.tar.gz=ea47adaa63abd18bf0c11cdb381eefb2874994527005cbccc0dcace33191f9c6 +dist/2025-04-02/rustc-beta-aarch64-pc-windows-msvc.tar.xz=cefea68c789907a45f0bd4233da2e3406287ac55d1c33f8612ec1aa006b853f0 +dist/2025-04-02/rustc-beta-aarch64-unknown-linux-gnu.tar.gz=38fa4ce395641a988247ee58c334389eda62fc1d3c0fb45157f24578319925d8 +dist/2025-04-02/rustc-beta-aarch64-unknown-linux-gnu.tar.xz=d8d0b459acdff2a32f8c40707bf5a17b71ce86fb5ee9ad61690cba8f8227bbfc +dist/2025-04-02/rustc-beta-aarch64-unknown-linux-musl.tar.gz=41f01647a80a7f21b85fe660af9e7964ad34f0e909d1e58c9e28e102a796791f +dist/2025-04-02/rustc-beta-aarch64-unknown-linux-musl.tar.xz=8436eddf40ad5bf61153f24c887fb0f0e878bcc403095719b35f3147328d6406 +dist/2025-04-02/rustc-beta-arm-unknown-linux-gnueabi.tar.gz=07ee5588005a18477a7de89321e6527ee5f10af00e9c4eeb2a8c666f79d3d606 +dist/2025-04-02/rustc-beta-arm-unknown-linux-gnueabi.tar.xz=8a95664cef49c1e45b2ae61ec464a5be976e4cecd2b502a050f95b9eb25dd4c7 +dist/2025-04-02/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz=b9b186ea9bee58a646ce8c4c384fc4cb528c73c1fee3ea3f5028fd4b3fddab3a +dist/2025-04-02/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz=9f62c2ea5b67c14ab804267d449ded07c8b551536886099b02b942ce2d641790 +dist/2025-04-02/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz=f07363ad0dff8b965dc10543f27cfd923266dea6284ebbb1d1b59b77f5ae2b61 +dist/2025-04-02/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz=a31afc234645a7dc5dc47f05bb5321fea12931278433df834def303cdea9f52d +dist/2025-04-02/rustc-beta-i686-pc-windows-gnu.tar.gz=f396061e8faaf66edea34b0855e2d3760fc0fd5c75e99696b50b2d4f310e11e0 +dist/2025-04-02/rustc-beta-i686-pc-windows-gnu.tar.xz=0f95f9170c5b211db29c3baac9341ef61de83511fe0000b8aae65aaf90041ae6 +dist/2025-04-02/rustc-beta-i686-pc-windows-msvc.tar.gz=82b7d1136d1b6f3d229fc77eac19d2cbfb3a46de472345b0ec3ebc152872164f +dist/2025-04-02/rustc-beta-i686-pc-windows-msvc.tar.xz=565bde72132e77617059da66edf9262f728336a2cc2c3c7cf4d61e0a4b5e681a +dist/2025-04-02/rustc-beta-i686-unknown-linux-gnu.tar.gz=8a3abc2a8aee8fa30699f51a216b29b41b2242143646d0f560f89bf72a0e285c +dist/2025-04-02/rustc-beta-i686-unknown-linux-gnu.tar.xz=7d47cf99aa5fd3b5bc2caa918b4eaba793b6d38252a72fa7be631c8db27c8525 +dist/2025-04-02/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz=0654cf14bd3302d001fa00fe73cb7c597206c6897978b3aeefd00e9325a8bdad +dist/2025-04-02/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz=6cd5c3ccb643a912d738239c0ad7464ee755cd81f45a26a9d3aa5ceeff569ba3 +dist/2025-04-02/rustc-beta-loongarch64-unknown-linux-musl.tar.gz=e3c0c5c52b04dd060f3a70b0c936dfb5c70ac29256361a491df9c898259dd551 +dist/2025-04-02/rustc-beta-loongarch64-unknown-linux-musl.tar.xz=83a9bc8f9a61b2a7fedddbdfb253aa078bc9896f179ec9b1d1bd918e7de34663 +dist/2025-04-02/rustc-beta-powerpc-unknown-linux-gnu.tar.gz=21efa7a67647df8aa99e40317c798895321d09c48b8453e51eef1635c20e9c47 +dist/2025-04-02/rustc-beta-powerpc-unknown-linux-gnu.tar.xz=56203ed9d3bbbab33e2825db7c72cfbe4f857f68dc98072cc98280cc4f1110d6 +dist/2025-04-02/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz=76c343aa3f5c74e1419e3f2f79dd3a2091fad8f6db644cf14f7aef036c8369d0 +dist/2025-04-02/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz=e9c7b97a407127e51fa49ca94c5f22c59f2f325848d55e6160d6dcf7ff690f91 +dist/2025-04-02/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz=27935ff4136141519b4e7b37b55253960b7fa16f5cd751d731ed85019432247b +dist/2025-04-02/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz=fd37c12a55055bc4a2f0e002b3126e6396df8d49254b2a8a7a45354aac46bb2c +dist/2025-04-02/rustc-beta-powerpc64le-unknown-linux-musl.tar.gz=cbeba9993d03c6c0c2c508414bee04665abb9c084c736b39c5b8d38c8f63402d +dist/2025-04-02/rustc-beta-powerpc64le-unknown-linux-musl.tar.xz=e92f69d85929c81e3c91b2ab45eec418afc65edf6f8bf9383148a98b052353df +dist/2025-04-02/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz=31a8ae1e64fb86a499518d7711595d653db56527aaedea06bc2bbcb912568844 +dist/2025-04-02/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz=7d001ad6c4825d5323813ed19747cc3e3d2dcbbe76317329a52127b3de37ee88 +dist/2025-04-02/rustc-beta-s390x-unknown-linux-gnu.tar.gz=c69d15e75d51caa0cf77fbe149d43b62c327896bdeb0c6c73fa7240404289862 +dist/2025-04-02/rustc-beta-s390x-unknown-linux-gnu.tar.xz=cf80772ba9eed4885a28aab38323f0ed24ab220339a3b8a148b7c27860c48c19 +dist/2025-04-02/rustc-beta-x86_64-apple-darwin.tar.gz=be22d207f8fd4722d69f6fdc56c57618ec01c54c5b6f3a8506c62583259d433a +dist/2025-04-02/rustc-beta-x86_64-apple-darwin.tar.xz=04feea9824748ae01b4f4f85d15adc5baee23c996c22de86041888466ae69512 +dist/2025-04-02/rustc-beta-x86_64-pc-windows-gnu.tar.gz=8c75005f0309d30e7c272adce173adb253874ce881b347946b6ffe5a07067439 +dist/2025-04-02/rustc-beta-x86_64-pc-windows-gnu.tar.xz=7b87c4ab5291d9ad3670f4e9ee98fe9f6f877ab8d4952109d7e5e9d20181a700 +dist/2025-04-02/rustc-beta-x86_64-pc-windows-msvc.tar.gz=a96d89ba655db5317dd51ffa2ebb81b7bdb76b19cf12de36e9d0aba2c5877ae2 +dist/2025-04-02/rustc-beta-x86_64-pc-windows-msvc.tar.xz=84bcfd763eba610c78223697393ea97f1f70e567a44b8cfe22db79f1cade4201 +dist/2025-04-02/rustc-beta-x86_64-unknown-freebsd.tar.gz=95ff7349cf12e49028256c06c8517719cada2720d4db80bfe7531289bbcdbde9 +dist/2025-04-02/rustc-beta-x86_64-unknown-freebsd.tar.xz=c8d0147c625faa5ce0e75c2509827bc4b190ad286e41411bce92023e00eb7a1d +dist/2025-04-02/rustc-beta-x86_64-unknown-illumos.tar.gz=4be80235a110028d64404e532eb20af37e46db72a7ac3a0cf7c94ddf463c461f +dist/2025-04-02/rustc-beta-x86_64-unknown-illumos.tar.xz=b18ea9a5c262c2f7505305110473cc15bd2c4ed9d583f07c15635406c050be08 +dist/2025-04-02/rustc-beta-x86_64-unknown-linux-gnu.tar.gz=234027a0075224ea157efaf39173ece43f9ca7d69d86e4790a2a038f7e6d98a6 +dist/2025-04-02/rustc-beta-x86_64-unknown-linux-gnu.tar.xz=308a8ee2855a6471db3b3b64cb06e355e31d0d617ebc9f30757bb7db5f6fc7c0 +dist/2025-04-02/rustc-beta-x86_64-unknown-linux-musl.tar.gz=10f39cc94f39bcf17d0fa3b8efeb4db72408fba694e5eb0f175e7465f6d2de49 +dist/2025-04-02/rustc-beta-x86_64-unknown-linux-musl.tar.xz=6b0d16b46347fdbcddfafad8209df19515059eddce1e048ecf1585341fa1e586 +dist/2025-04-02/rustc-beta-x86_64-unknown-netbsd.tar.gz=09f482425c92396f7e4ae3baf625dbcad1d886d82ecfb605b50393abdc23ce15 +dist/2025-04-02/rustc-beta-x86_64-unknown-netbsd.tar.xz=bac2f1a493bc2c5fa6cab1f58ff536cbeba55f77141b34636bfded9e3ff167b5 +dist/2025-04-02/rust-std-beta-aarch64-apple-darwin.tar.gz=8875ade1dd8ba0bca0c12860a076df1f089195a52adc546679025c405bef4dd1 +dist/2025-04-02/rust-std-beta-aarch64-apple-darwin.tar.xz=0a0593ab4c95802b0ed810c0442e13ad9304712c2f7c30a30c734523a7448d8a +dist/2025-04-02/rust-std-beta-aarch64-apple-ios.tar.gz=839086e20098c305adcdf9103cdf3f29a14c4140b4c1b728723e7aedad966883 +dist/2025-04-02/rust-std-beta-aarch64-apple-ios.tar.xz=70f1832193e77a2018088943b531bdbacbe5404d5d7a34393e03f40329e742ce +dist/2025-04-02/rust-std-beta-aarch64-apple-ios-macabi.tar.gz=94adeb2e63a91c09001facbc554678227a3717748104424e4fea71db3d5a16be +dist/2025-04-02/rust-std-beta-aarch64-apple-ios-macabi.tar.xz=73c9bb75eb6fa4cf613c7a2b0e237472e144a1469cb043194ad7802052149fee +dist/2025-04-02/rust-std-beta-aarch64-apple-ios-sim.tar.gz=0e01ed2620887b893687758d62422f661429e3c4566ff52d967463eca89f54c5 +dist/2025-04-02/rust-std-beta-aarch64-apple-ios-sim.tar.xz=c26beb8ea9f11845ce79d4f0ec2616ce82dfbc4fefadfc7f94a1df17f4d5bec2 +dist/2025-04-02/rust-std-beta-aarch64-linux-android.tar.gz=64047673efa9d9bad660e2a44f82e6f929c881fe205523bff10a549505d12b72 +dist/2025-04-02/rust-std-beta-aarch64-linux-android.tar.xz=0e4c6b76e8d92023533aef6fe377c9bd45ef9c1da517eda7bfefec85b966780b +dist/2025-04-02/rust-std-beta-aarch64-pc-windows-gnullvm.tar.gz=a25c50a86e5d674600cec5bd9e7939bf36b0afa766445b0d71673431388d285c +dist/2025-04-02/rust-std-beta-aarch64-pc-windows-gnullvm.tar.xz=8060a4c5337fa6c34b3f08ddb8886beeb5bafd2b02544b08a7cfcb466a27a972 +dist/2025-04-02/rust-std-beta-aarch64-pc-windows-msvc.tar.gz=efd76703934ae0187308eec9b3439abea0dd4437ac353d5dc07d92f9440ab9ee +dist/2025-04-02/rust-std-beta-aarch64-pc-windows-msvc.tar.xz=007462f554b0c6d2b165d727bf72b1ad4347a53869d672fcbf48db2c1dcf128d +dist/2025-04-02/rust-std-beta-aarch64-unknown-fuchsia.tar.gz=e0dc54be7890edef123d2dc31f0dcddd1c807cc060a34f475093cab79100d9fd +dist/2025-04-02/rust-std-beta-aarch64-unknown-fuchsia.tar.xz=01c06c1d61c512a034a109f50f957e4496639549837b63464acb4fb24ff65e09 +dist/2025-04-02/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz=2042d37b09618379dd91125d20803e2d97d5f3f3794e01ed27597a0f3b27c102 +dist/2025-04-02/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz=568f0b8da190daf78cd8573b0408db2ecc2c07b1cb1fa463239581963738e9de +dist/2025-04-02/rust-std-beta-aarch64-unknown-linux-musl.tar.gz=386b1e4786dbfe342626cde4c3708abd04d9862d69717c7acd5dfe82427e38f9 +dist/2025-04-02/rust-std-beta-aarch64-unknown-linux-musl.tar.xz=781d0f9417e1b3d33d95e3c5b82ba7e481a610dc468345119e09a52b1d170045 +dist/2025-04-02/rust-std-beta-aarch64-unknown-linux-ohos.tar.gz=8673d059524ac141a8907decfda36c8afac81fd36dd75f78df750a6d52ada221 +dist/2025-04-02/rust-std-beta-aarch64-unknown-linux-ohos.tar.xz=8e8afe45e9bb84ebc3e02f0b4b71dbcec7c844128329d31067303b86113c3439 +dist/2025-04-02/rust-std-beta-aarch64-unknown-none.tar.gz=72e1dce3c1f821b6018ec155bff250b941afcfcf1697b440a69822b10e929b94 +dist/2025-04-02/rust-std-beta-aarch64-unknown-none.tar.xz=7030883ad3ca170a061972707c488fc25d4dc8ab0f60a1b9b54240e42ca713ba +dist/2025-04-02/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz=28f87a505ca4e2c33015338d73cfdf5c2fdb1f5775f82ec432d033a36880351d +dist/2025-04-02/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz=45669a09671c183d702a31b6ecf095e8f422797c4e242063c7864180c6f657a4 +dist/2025-04-02/rust-std-beta-aarch64-unknown-uefi.tar.gz=1ad54cabda8bfabfd93e16c564c0950c26e1502662d5f4ce3b33b4ee265b9a2d +dist/2025-04-02/rust-std-beta-aarch64-unknown-uefi.tar.xz=a79f9d7eb4297994b2e87d48106a959c82bc4387433e5e86dc8caddde29a8a4e +dist/2025-04-02/rust-std-beta-arm-linux-androideabi.tar.gz=75192092fa7a40051a70a843cf75513de2c50d66927f16b122f7417c1d4f25e7 +dist/2025-04-02/rust-std-beta-arm-linux-androideabi.tar.xz=843dde45dfa49b5cc97266c61d8e58dfb22dbf2288e6e8baaef769eaf59675cc +dist/2025-04-02/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz=03ccaa5e246502fc61fea1e0b33f5c60b5895cd0b5b932bf640d62e97164b457 +dist/2025-04-02/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz=a73525dcab3a0f3bc7064c8a6cdeb9b0e5b359501cb7e8fe20075a0e97b2a5ba +dist/2025-04-02/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz=8c851fc122d14beee962e15fdb95c2873769805180be30723f418d84cbc0a8b8 +dist/2025-04-02/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz=8524ad1b7723a4a5898837d5b526fb11ffcd039b2c4835a2e139071f6cfd4e9f +dist/2025-04-02/rust-std-beta-arm-unknown-linux-musleabi.tar.gz=b108ec4460d4f6ca79813e6d2d4cb7061fa522a990333fb9f4f927b0fc659624 +dist/2025-04-02/rust-std-beta-arm-unknown-linux-musleabi.tar.xz=0bdb617dfa833c62c03f5bfd2f06ed3ca1479908d860f888d661794188bd57d6 +dist/2025-04-02/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz=19f9fff71344f7a42f958c3efec720e4b2e0d67ba36a5fd66946e74811259f2b +dist/2025-04-02/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz=0cdfe9b4a8bc4b63637cfd9766c3e0e1d3dcd6d2e82fe35f57973a0081e630ec +dist/2025-04-02/rust-std-beta-arm64ec-pc-windows-msvc.tar.gz=a8490374598bbfa42931bbfba51ecc0186c476217eb79408ae6b80a4ba6de9f2 +dist/2025-04-02/rust-std-beta-arm64ec-pc-windows-msvc.tar.xz=2bc2838320667f060c140345d1c26aedf90bf5efb1f72e6722b74d32f876901c +dist/2025-04-02/rust-std-beta-armebv7r-none-eabi.tar.gz=9a237e1dbd2e3b555aa3932351d1c20a0f9f2f06e810abd254b5ca152aace687 +dist/2025-04-02/rust-std-beta-armebv7r-none-eabi.tar.xz=f4978bf9af719f0b6e8300ea862fe617e983e5443a46c769d60d5e8c4d556ba8 +dist/2025-04-02/rust-std-beta-armebv7r-none-eabihf.tar.gz=c1476718625d5d5d42b60faa9ade845272b0b71e91d77a9cdd271c4682c900d2 +dist/2025-04-02/rust-std-beta-armebv7r-none-eabihf.tar.xz=f8ab07e99983fc7395841cc9ed7ce7cfaedd87bfb91214bd83508ad96aef0c0b +dist/2025-04-02/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz=649071a7de4792ff75da59ca421ea1cb364c011db97e73c480982a5f9f06b8aa +dist/2025-04-02/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz=529aac0b0a385fa5ddb76a88eb6923bcc981679caab2d1c374d443383c99f52a +dist/2025-04-02/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz=8bdf3412b0b557485099db86afcdf58293bfd4c09c4b360c2d9733788b612122 +dist/2025-04-02/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz=5d5a4ebed984a0930b214ec0b11e20fd9a7b8d5dc2d00985b75a77c8febcf441 +dist/2025-04-02/rust-std-beta-armv7-linux-androideabi.tar.gz=2c03cbb393641876bebad9b76465ac7f96adb82c14dcc9b5bc01a82e5110b892 +dist/2025-04-02/rust-std-beta-armv7-linux-androideabi.tar.xz=67d86fa728178c30cd7a33e0c488c32f58ae0caeb9a982370e080ea38853830b +dist/2025-04-02/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz=3737dd5f80f35f3fecf5cd8324c9226f45bb0bfd040998d91509a2c6fd8967f1 +dist/2025-04-02/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz=8f9f710c92af058d5a07c93b4cfd45b7d30e63ab79bea7f79530537aae2dd836 +dist/2025-04-02/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz=6ecb3e238e125e88851dba9711b2b32f4de1da55de36a62373bfcc42d001fa0b +dist/2025-04-02/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz=7d6807d24afe4825b77c1cb74c1412b814cf2508f5b40debb55b3f264e02eb6a +dist/2025-04-02/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz=a15fccced78065f748a5c4f66763b8940ae3e52b5048b5ee1fab6b0b7b40c701 +dist/2025-04-02/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz=20bc43c1b5742a9c7a97ade055441ca1ca153dab9602db3ffaf1ac518713568e +dist/2025-04-02/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz=b01929a0f18b1a41b65307a04d1273d2197df83b3c124f80659ef8fa4f8c4577 +dist/2025-04-02/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz=2a13350da7c632d3878ca8da8a7d0bda60c850df8e5d824956082b524eb136fe +dist/2025-04-02/rust-std-beta-armv7-unknown-linux-ohos.tar.gz=11bc9fd437be07cb454182b0d7b287ec030f7d8904f096b73beda6480ba33285 +dist/2025-04-02/rust-std-beta-armv7-unknown-linux-ohos.tar.xz=31e06feb45173fec8e58cf92216e44d556587fe2ed866102206e23514c73d3f0 +dist/2025-04-02/rust-std-beta-armv7a-none-eabi.tar.gz=aebbae792c070adea3f10135c02b2cf5d623b84e765ec3a72c89275f53a85384 +dist/2025-04-02/rust-std-beta-armv7a-none-eabi.tar.xz=e80dcb152e7a8337fbbff6a5c8dfcd9c6da4b753da6b14e63fe7c15cc0836359 +dist/2025-04-02/rust-std-beta-armv7r-none-eabi.tar.gz=e79846c1203d5d375c7c1cff1c843cb6fcd4e33bbc71b2363e12fc900bbd72bd +dist/2025-04-02/rust-std-beta-armv7r-none-eabi.tar.xz=0e24e48461cc46edef0237e38480ac806d0521c73ea366668e731f29b638d7c9 +dist/2025-04-02/rust-std-beta-armv7r-none-eabihf.tar.gz=fd2a9b48ea203b44567cfdcfcfb21d5d803896fdfdc5f3aa191e3fa7472b98db +dist/2025-04-02/rust-std-beta-armv7r-none-eabihf.tar.xz=2b85d461bed34a97cf832a7c0e1d4179d7800ef47523a8e31d635b8de5dd44a7 +dist/2025-04-02/rust-std-beta-i586-unknown-linux-gnu.tar.gz=cab412c30b27060cdcb29adb947dc070875813726707dff121c4a1aa8615646d +dist/2025-04-02/rust-std-beta-i586-unknown-linux-gnu.tar.xz=1b8d469fbb8903a5f4f5eb6ccee7bdf28cc56137b6b212fdfa1aed647f4c347b +dist/2025-04-02/rust-std-beta-i586-unknown-linux-musl.tar.gz=93fa0383e32f18567c3c156f3cddde1fa4296003f98cdd22b0b5628d69d5208a +dist/2025-04-02/rust-std-beta-i586-unknown-linux-musl.tar.xz=71ae00b01ffbfdc6654d0fd14df204adb7d499ac71e59c93affff91d58833d88 +dist/2025-04-02/rust-std-beta-i686-linux-android.tar.gz=4c6f4764e284ff29958417295ddc5d3316072fc9eac87dfed8b694c237aa4f88 +dist/2025-04-02/rust-std-beta-i686-linux-android.tar.xz=f471a7abb2d447f668f01973be4712e20c6dd29b210a96517b277e62c6d7de07 +dist/2025-04-02/rust-std-beta-i686-pc-windows-gnu.tar.gz=0c5efb9792502fc08174b2556f5c91f3edbad6e02de5e230f39c5fa011fc935c +dist/2025-04-02/rust-std-beta-i686-pc-windows-gnu.tar.xz=b6a87360e7be832288e59239d41e809db01710ccae5ef37bcbe7b0eb1d311e66 +dist/2025-04-02/rust-std-beta-i686-pc-windows-gnullvm.tar.gz=0429745cd95a198a7a42a1ce0c7ab2d502f3ff3eee81104fe6d5d4d5dab9447e +dist/2025-04-02/rust-std-beta-i686-pc-windows-gnullvm.tar.xz=bcb43c9e2d4a49c18d39e041d28021f2302707ae9ac20ef37f4d467fd2cd3975 +dist/2025-04-02/rust-std-beta-i686-pc-windows-msvc.tar.gz=e1d8c40e61701c6bfd519125169cc1ab1d60e9a58238351bbeda0ccc5522cc49 +dist/2025-04-02/rust-std-beta-i686-pc-windows-msvc.tar.xz=1f87f343a90f6e88cb3173d52f4f88d8abdb0c1a613681c92675c1acc340aa54 +dist/2025-04-02/rust-std-beta-i686-unknown-freebsd.tar.gz=5862f33548bef1aa21b3d63caefa12ee34775cb378f89c4dc161e081a773d11e +dist/2025-04-02/rust-std-beta-i686-unknown-freebsd.tar.xz=ed3460948031d0c4e97f7b1b77062f388d133db2b2212518eabd3198e72c031c +dist/2025-04-02/rust-std-beta-i686-unknown-linux-gnu.tar.gz=3a6edd9f412a274e372c9555b6758d540d06ac08efd21ce95df1ed4d30418afd +dist/2025-04-02/rust-std-beta-i686-unknown-linux-gnu.tar.xz=8338baaa50b9cb08a28f7bb21a22deef849f8809282c661e48c486a168b6249e +dist/2025-04-02/rust-std-beta-i686-unknown-linux-musl.tar.gz=56ab80fc6cb75a0d66c477e76f87918645bc3b616cf704306820832681022768 +dist/2025-04-02/rust-std-beta-i686-unknown-linux-musl.tar.xz=94efb810dbee977ecb3ff5a42a5a620d720c237da58d974ba1f376c99947baf5 +dist/2025-04-02/rust-std-beta-i686-unknown-uefi.tar.gz=64cb107065bde9b30c78b9b342211c4e6cd2c3ed726155dacfcf5958ba869a82 +dist/2025-04-02/rust-std-beta-i686-unknown-uefi.tar.xz=ff1bc215b4aba25f59eeee8285967e24b78f6965473ea8bb30186ab55804f88a +dist/2025-04-02/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz=da1d33b266e1dd277f97f63228843765706f26c9f75c4b5171f49c2762fed870 +dist/2025-04-02/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz=8309c9c4a03df90eb53116b5c5c4870d103911227848919580a48e5e85954709 +dist/2025-04-02/rust-std-beta-loongarch64-unknown-linux-musl.tar.gz=26a3115d5354f878f80bef1c83a44af185e2780882e17143ca57aff078d123a0 +dist/2025-04-02/rust-std-beta-loongarch64-unknown-linux-musl.tar.xz=12431c3b50276f352a3ea71c74db279cd03c2edfb3edf743f81774d4274f7ef9 +dist/2025-04-02/rust-std-beta-loongarch64-unknown-none.tar.gz=ac67b23f84d09ab17d26f30deb38a128ccf812a561738327effe48ecd0caa319 +dist/2025-04-02/rust-std-beta-loongarch64-unknown-none.tar.xz=5508b02465d3dbb40512a142eabb27817807d2af153089f7d05a0af355fdb245 +dist/2025-04-02/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz=a79a59139e13166cb1121d703cee113bf92821f937d433cb9a2c00567280a4e2 +dist/2025-04-02/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz=8c3b5501050f57125cc89e6525b780ca0e18d2d5318f779894ab97efef761fb3 +dist/2025-04-02/rust-std-beta-nvptx64-nvidia-cuda.tar.gz=84a48148eb313f236f85a4907af615b7af4c3ce3d9065ffe0db54458852690ab +dist/2025-04-02/rust-std-beta-nvptx64-nvidia-cuda.tar.xz=26281622332b438bc43b8f46921153a45c6236a4c0939c76fdb4d9fb3d29cbbb +dist/2025-04-02/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz=0eef233c871404b913c6458d8005d362e3c24fcb0670ac49a7e67b1a503b4b29 +dist/2025-04-02/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz=b96422b0f33446abee203160a22e9bac8861e1c7988b2cef463276743001fc7c +dist/2025-04-02/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz=18db97406a6e644734c7890991cb3006fabe1e1a185f89d108d28a992ed7c17c +dist/2025-04-02/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz=eea42655b5335643905acaa3d8ff1774e2c1a39ffde363c2073a8636c153087a +dist/2025-04-02/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz=5feaf6f3859204979fb4dab03fc93428abd103d61822d6e4e9a2f5d6d155213a +dist/2025-04-02/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz=98f8e695253c9dad3d82638bd69c084a3e7a96d17eb1dba0f90a42df993de864 +dist/2025-04-02/rust-std-beta-powerpc64le-unknown-linux-musl.tar.gz=e028f2ec967ecee5d9e7b48058209428ed220c5da2c00f2753f8d4e98951e168 +dist/2025-04-02/rust-std-beta-powerpc64le-unknown-linux-musl.tar.xz=69f508ffcb55347dbb773cfa22a1f7a6362f3aff6a48296b50945422ea82c7b5 +dist/2025-04-02/rust-std-beta-riscv32i-unknown-none-elf.tar.gz=ea30bf48fcb3873db4019ae3d248e1db868e1f7fc49e4549737aae58b3b49b22 +dist/2025-04-02/rust-std-beta-riscv32i-unknown-none-elf.tar.xz=c3724aaa58f812dc8283622f27e215546d8522b6ecdf1d191010dde3a1ba3344 +dist/2025-04-02/rust-std-beta-riscv32im-unknown-none-elf.tar.gz=9d24eb785b66796309c2f03944719fb6b6980ae8fb7ca97084fcfdea0094bcce +dist/2025-04-02/rust-std-beta-riscv32im-unknown-none-elf.tar.xz=f6b2233474eb64d041e6bd8f1b6dee3eaf775b6b5a7ddec703689352cf88f6a2 +dist/2025-04-02/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz=8a5c94055180b9a1226a23c5992a622062ac52cddf91651a91a5d236be46d0c8 +dist/2025-04-02/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz=7ea826d6c58fe1ef1c9374aef0cbfec5495daddcda581b231d18397330d9e248 +dist/2025-04-02/rust-std-beta-riscv32imafc-unknown-none-elf.tar.gz=811881bd5b514c89c316453ea1214fbeccf5388f18468cc83676a879d58f53ab +dist/2025-04-02/rust-std-beta-riscv32imafc-unknown-none-elf.tar.xz=9448b7bad586237faa4f090ce8c3de83b62d19fbe37104ae32032d9df709d2e6 +dist/2025-04-02/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz=dd9252a03b0a888ee7598a84c20aac721739c2caf9c5b585274d2a30d7fcbcb6 +dist/2025-04-02/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz=d1f134647fe0c3efcce80351cf9e4786ca8e3e336c0316b7c28ff07b78907c73 +dist/2025-04-02/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz=4f688c40457ba71542438fbc100b62b5f081435567f965512481ccf3d002826d +dist/2025-04-02/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz=a474fddf29c6979e0870c397c19f64de00650893a781eb51d9e136802bfabbfd +dist/2025-04-02/rust-std-beta-riscv64gc-unknown-linux-musl.tar.gz=7071209fdf0d2605b623ef96c934ed039d1dd95a68c438a8c563530ed48fb4e2 +dist/2025-04-02/rust-std-beta-riscv64gc-unknown-linux-musl.tar.xz=1328504e895dc9bbc36ac697bd5031e0034b2468fc66a91e42b39a4d35d4ea8b +dist/2025-04-02/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz=e7878c1137279790205e62f9c363a6f45e2a8cd9c30702a53478a8104dc87a6b +dist/2025-04-02/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz=f373b1d79547c385a01c2b36951eb3750a4cf3bcaaa213587af9a6b4274dc924 +dist/2025-04-02/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz=4832338ebc25d088e30952605b3f6491d96003790df5b10c5c56e29ec69ac646 +dist/2025-04-02/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz=d782dac690b3da2b96206809512f1ae82fb4a73ee387d91128ae0d98bf51ef3a +dist/2025-04-02/rust-std-beta-s390x-unknown-linux-gnu.tar.gz=faccf22845e31101a420796d9065b350092cbee29d755c2369ee36cc7172866f +dist/2025-04-02/rust-std-beta-s390x-unknown-linux-gnu.tar.xz=f296c5726380b1f2b8603a079e8dfdfa7e4a97a499b1e86874753c312768ab15 +dist/2025-04-02/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz=b8a8fd8fda8b99d96d6f890bcd0c9073393441e85a4cda169b6fc7dbb7296984 +dist/2025-04-02/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz=923a0530224f0631162f7b86bef79be85f45071f62ca4f5de0588fb5ca6affa8 +dist/2025-04-02/rust-std-beta-sparcv9-sun-solaris.tar.gz=944a83365d3c46313e28b1d3a5b0e52e57ce88b3eaaf0f7f53234d4423ce9ca7 +dist/2025-04-02/rust-std-beta-sparcv9-sun-solaris.tar.xz=be0c983c443f05feb4614d97336755894b3ffc5083d852bd84ee7cd9e5edfa03 +dist/2025-04-02/rust-std-beta-thumbv6m-none-eabi.tar.gz=08905a766352dd259be919aeb366e965dbbd4066c398dc4d26efa333b0ac46b8 +dist/2025-04-02/rust-std-beta-thumbv6m-none-eabi.tar.xz=4fa005107c3d1addb242179c03a804a27d34ca68bd76c092a41a197da56abce1 +dist/2025-04-02/rust-std-beta-thumbv7em-none-eabi.tar.gz=e6ccc1004004ed759b1814daae0b50a3a0adca9786688ef9cc601a0a19edc72a +dist/2025-04-02/rust-std-beta-thumbv7em-none-eabi.tar.xz=fc23abf9c086a34264bfcfe7c4876ec65ce54f8ca73a98020bb8eab6d2c51d57 +dist/2025-04-02/rust-std-beta-thumbv7em-none-eabihf.tar.gz=e8121551c0529f73796bc157bf916e3608685454a02a81d170a258a7465b5b7c +dist/2025-04-02/rust-std-beta-thumbv7em-none-eabihf.tar.xz=2695f76447ff5d70aa3cc6b6690267b31b9aa4ddc7c45205e529f92d234483a0 +dist/2025-04-02/rust-std-beta-thumbv7m-none-eabi.tar.gz=36d7fb4edd572c7d73501aab7c89737ee0036d606700c728f430142e91649eb0 +dist/2025-04-02/rust-std-beta-thumbv7m-none-eabi.tar.xz=a6e59eaed0ab3e310852d9a75fc43600c7c2eee0c808224b87bcb8c18df4ada6 +dist/2025-04-02/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz=6bc70be43929b77f3508b1872e5b09227aebce1c7c9c943995b5df92cf6d9181 +dist/2025-04-02/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz=37b956924534aed1ae7ef9908d38bf724c6903591269136d23e293e17a0d333f +dist/2025-04-02/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz=041562edada0caeea67fe7f3ffb5b9f8c1b506c0d5ee7b657c5ee2afbefba7fa +dist/2025-04-02/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz=8980372a7e9a072b1e0b954569e59df260583a3371daf005c5a83576688562d1 +dist/2025-04-02/rust-std-beta-thumbv8m.base-none-eabi.tar.gz=83f461ac0ebcc05d5cbf67a6585b49dc7b245c8788dc3a75e08a93be41e2615f +dist/2025-04-02/rust-std-beta-thumbv8m.base-none-eabi.tar.xz=6ac8847ce601c8dfeffff07915de06a605b3c685f81b90f87b092897c2afb973 +dist/2025-04-02/rust-std-beta-thumbv8m.main-none-eabi.tar.gz=bfcd9ff7dc9bb5e95bd563d750240efcbc3bfa1a21a9f9a2786ef37f665b7e43 +dist/2025-04-02/rust-std-beta-thumbv8m.main-none-eabi.tar.xz=4507383395a26d41abd71041b162dfc5e9471a4c624d9fd6ad310e184ef15d01 +dist/2025-04-02/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz=b4d1940ea5e24cd6a0ba3906c98d2b03e4a18927619152b43e91832733316258 +dist/2025-04-02/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz=45eec7770344beb84cf418cf7818216d123136465785f4742127f6f5a8c5ce27 +dist/2025-04-02/rust-std-beta-wasm32-unknown-emscripten.tar.gz=19bf2f4bf64f874ccfd84b820b7200e83e896c96a396edd7bd10301d2bc89d98 +dist/2025-04-02/rust-std-beta-wasm32-unknown-emscripten.tar.xz=4c616b7bd972c09461f0bccf5009bc574dcfa8bdce2dd97d17fcffd64542e496 +dist/2025-04-02/rust-std-beta-wasm32-unknown-unknown.tar.gz=69bcb61fd0f8bd7d2da225a4525a877cce003afd7fc3d789c385f164959cd41a +dist/2025-04-02/rust-std-beta-wasm32-unknown-unknown.tar.xz=0372a64eda0c7249ce5fbcbbbf29e145e969b383a73b7c470f0b583720fcdbe2 +dist/2025-04-02/rust-std-beta-wasm32-wasip1.tar.gz=f76a2a3f4702eb781a680ebd4346afb4c26ca2235e62bad144b057860c09b8a8 +dist/2025-04-02/rust-std-beta-wasm32-wasip1.tar.xz=173bc3317b59a01036a9c8e0bccc570fd6f5174d15f94634f53d81dec3d2cd68 +dist/2025-04-02/rust-std-beta-wasm32-wasip1-threads.tar.gz=18e05380478ed0b3f76d9062fade2be2e66c039dcc470ffb01be3c8dffc79995 +dist/2025-04-02/rust-std-beta-wasm32-wasip1-threads.tar.xz=3d477eb85308f73d1081d6dd3e54577be4bd84f291a50af0e3be15fa8aa36db6 +dist/2025-04-02/rust-std-beta-wasm32-wasip2.tar.gz=3444883960a9f8b831d1f26ee17ef082a2029cdc2e9b45ce5af4d6565d3a526e +dist/2025-04-02/rust-std-beta-wasm32-wasip2.tar.xz=867361c7ba912b404c426807a60625a1f830707a172f7da139c1a892aa85bf35 +dist/2025-04-02/rust-std-beta-wasm32v1-none.tar.gz=d15017a323c662a1e8c65f51e66151138c2255cd8842a67e990000606dac839f +dist/2025-04-02/rust-std-beta-wasm32v1-none.tar.xz=f3b32484ef287317187ca0bd5245b1793ae40d50290a2882419da8503b8243f3 +dist/2025-04-02/rust-std-beta-x86_64-apple-darwin.tar.gz=179be6a29fcf16b4c18775208569a051f2f5a38558e751d2dda0a42027868843 +dist/2025-04-02/rust-std-beta-x86_64-apple-darwin.tar.xz=912f7f8d7117a5cac85dffee5ffd9f2c1cf237477bb0f9e1127afff1f0cd4757 +dist/2025-04-02/rust-std-beta-x86_64-apple-ios.tar.gz=9d2f3230bd82ba9d45e572b45ec63c63cfb592dba6311b6a16de075f18c86999 +dist/2025-04-02/rust-std-beta-x86_64-apple-ios.tar.xz=c8ff77db2d081444ab5167764465beb33046cc81cf2e8dbbd8e9a7328306762c +dist/2025-04-02/rust-std-beta-x86_64-apple-ios-macabi.tar.gz=76c9b2ae710fed611a2294a5e4bb6597b07d78f0bbd3a5a0d15c3320f38a0017 +dist/2025-04-02/rust-std-beta-x86_64-apple-ios-macabi.tar.xz=b9c485a3824c971a42c10af26cf06c539c34fa429e92601a1978280867029e62 +dist/2025-04-02/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz=a223c08b88c768d97bf9f071c74d9548acf00bbb097b8c8427c2ec87ca205597 +dist/2025-04-02/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz=34ddb3db8a71edabb4d0fd8d52a164dbca5a5cd96d6ba131e7d439c333726f78 +dist/2025-04-02/rust-std-beta-x86_64-linux-android.tar.gz=9ba28bf95c75ca0d69461d1c044902443053b64678b540967a97c7cd2eb7cc4c +dist/2025-04-02/rust-std-beta-x86_64-linux-android.tar.xz=09e35188a801371a55abeb9e2ee455ebd26d41b8eb561b8016ecacfc7ba20c90 +dist/2025-04-02/rust-std-beta-x86_64-pc-solaris.tar.gz=c1f2fb4b90cf258dfa1a52167ba925b583dc889ec1c3c48958560ff3b7b79b13 +dist/2025-04-02/rust-std-beta-x86_64-pc-solaris.tar.xz=d71f2bade21f751d9592e865ce3722b5d3b9abc49e55ca9d04c02d658360b6ad +dist/2025-04-02/rust-std-beta-x86_64-pc-windows-gnu.tar.gz=691c23504582e6db1cf883f52b5378aad3c42da7e2d2237e54601be9c8d16cac +dist/2025-04-02/rust-std-beta-x86_64-pc-windows-gnu.tar.xz=22e7327c5ba22863cb62cc5331862b8c2b4b10a732637729b5e1504034aa2cf1 +dist/2025-04-02/rust-std-beta-x86_64-pc-windows-gnullvm.tar.gz=81b7dda817a7dbc8b33542c356e0c5e5605b7c60a2fee13f4a266c8d970a3f54 +dist/2025-04-02/rust-std-beta-x86_64-pc-windows-gnullvm.tar.xz=09e4c9804f7489b337ccf66426e18e7522dcba24234b289a39eb63c8242353d0 +dist/2025-04-02/rust-std-beta-x86_64-pc-windows-msvc.tar.gz=a8188567321462309fb63af38f652c6a7448ebaae1425b9ec20d2fe2a12e8896 +dist/2025-04-02/rust-std-beta-x86_64-pc-windows-msvc.tar.xz=5284f85dce61b2b021888b6b82995aa7b4a14a979b42b83499a810c261fc183e +dist/2025-04-02/rust-std-beta-x86_64-unknown-freebsd.tar.gz=eb57c8ca7f515386d60a88e56443e377aae70e185ac52a62869e115c636a2bcc +dist/2025-04-02/rust-std-beta-x86_64-unknown-freebsd.tar.xz=8bef59b74196fa9f7839bb491f6b32d0761a45c8d7178980ee3afd80231b836e +dist/2025-04-02/rust-std-beta-x86_64-unknown-fuchsia.tar.gz=f43f402881f4558e3df4a7ace68ba80caa9354cfa5a8b1efac89f95e38386253 +dist/2025-04-02/rust-std-beta-x86_64-unknown-fuchsia.tar.xz=ea7d09c015c057591ff51b808cca9c8c1d973de3a9033fe42c1bf34d748d03a6 +dist/2025-04-02/rust-std-beta-x86_64-unknown-illumos.tar.gz=a4835455348bc5b154b1bba63aa03d2294713589214b50d3babae3e0f9918a3c +dist/2025-04-02/rust-std-beta-x86_64-unknown-illumos.tar.xz=711920e7491332251fb672abdc7685fa940f863d8e182e2ae9d9347d7fa6a725 +dist/2025-04-02/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz=1b8324839c0e10e410f29bd471f6c49eb4710adbe172d6bef3e619ae95d47d02 +dist/2025-04-02/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz=223b41f16a80b9c404f5af9a194b7414ef354681f911839353f24b44eed91494 +dist/2025-04-02/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz=6d8d8d9fd6336de0ebcb58fa85aa0d11e62a60d6c6ca01d71da0bdf668d216c1 +dist/2025-04-02/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz=033df93011b4461cde64c4230c495bad1523b9b38f5b0de56dd928c1da85b577 +dist/2025-04-02/rust-std-beta-x86_64-unknown-linux-musl.tar.gz=70a441c0cf8ca25abc1f722c1db5dde8b5fd3b90c767895b7518fc58c2678390 +dist/2025-04-02/rust-std-beta-x86_64-unknown-linux-musl.tar.xz=b5584d6d0031f8230a40f5ed76570ab1396c8997c3e957ca159d72a5dc201a2d +dist/2025-04-02/rust-std-beta-x86_64-unknown-linux-ohos.tar.gz=2596cdc3708d82aa93a8a1f595238fe9fd7b5b05a4886e7e390ca3b86d352e7e +dist/2025-04-02/rust-std-beta-x86_64-unknown-linux-ohos.tar.xz=c03901c0c8434b5db244c22145870e7d933b9060af3b23f24a765c755098a3a1 +dist/2025-04-02/rust-std-beta-x86_64-unknown-netbsd.tar.gz=82bc22594dc602b27edf8233bd9c4fbf0323999ce99ff2a7ddd0ce9268647eb1 +dist/2025-04-02/rust-std-beta-x86_64-unknown-netbsd.tar.xz=86f674f5e19a1b1780f06a6d5add06fd4240430233b7c3f5203a4daa5f444673 +dist/2025-04-02/rust-std-beta-x86_64-unknown-none.tar.gz=ca7882354f4274dc405034aa6edbda685b9d76bc6e5905074d2aaf8c35b35a95 +dist/2025-04-02/rust-std-beta-x86_64-unknown-none.tar.xz=ed6c828fdafcf87a68f522379f11c44eff1a4be1bf027d9888d1f17f22e9ca61 +dist/2025-04-02/rust-std-beta-x86_64-unknown-redox.tar.gz=6f8ab182274e2f5b0fa82fdc5c6e3776ba969e6ee6f6098ce6d170f6685f55c2 +dist/2025-04-02/rust-std-beta-x86_64-unknown-redox.tar.xz=ee061d725f657a2e52114f282be0cab1a6e542a0270b11782c36e8737ed84f32 +dist/2025-04-02/rust-std-beta-x86_64-unknown-uefi.tar.gz=0324f537f463738bbdbf40b92423df6c6068f76c583872d6070d6a41c5169dac +dist/2025-04-02/rust-std-beta-x86_64-unknown-uefi.tar.xz=2cd2727f71b14c06eb0a14fa532e5b3bc66f8b983c021f3201c327606b04511e +dist/2025-04-02/cargo-beta-aarch64-apple-darwin.tar.gz=76010b5a9f8dff0102a18de75e818c51b915a3bcff428fc48973728577c2ecd3 +dist/2025-04-02/cargo-beta-aarch64-apple-darwin.tar.xz=f0f03ece675cfaa9dd0f00204d7ddd4086a45357f09cac9d800d37bef8d0db33 +dist/2025-04-02/cargo-beta-aarch64-pc-windows-msvc.tar.gz=bf4ab12afcea7911ab973177de83b7bbdfd0000e3090331f31a595d57819ed6d +dist/2025-04-02/cargo-beta-aarch64-pc-windows-msvc.tar.xz=156fc94166e5f2af91fd9a36c67b545c0eff63dad51fcd81571cce01447c1c1b +dist/2025-04-02/cargo-beta-aarch64-unknown-linux-gnu.tar.gz=c86bbf8091188ab9f7d41e566ef628a657d66683884333c3851e99edaea6e279 +dist/2025-04-02/cargo-beta-aarch64-unknown-linux-gnu.tar.xz=610383a4efb93ab53cc747ba038888742346499407c982b7bc8c0c41689cf453 +dist/2025-04-02/cargo-beta-aarch64-unknown-linux-musl.tar.gz=7d427779360c9cba5903c2a0183be1c1759cb2c2f2b77bd2f64b409821fabb64 +dist/2025-04-02/cargo-beta-aarch64-unknown-linux-musl.tar.xz=29bda8bd7dcee65315b8c14a527f4e4b4dd678b35dd430591f7c71712ecbd2f9 +dist/2025-04-02/cargo-beta-arm-unknown-linux-gnueabi.tar.gz=ef6d6a810eecb3a38940634b653257070dcfcff52c2d8321fa3a933d41c7ed73 +dist/2025-04-02/cargo-beta-arm-unknown-linux-gnueabi.tar.xz=79796d83949811776aaedc7e6db6d32374c07b8f8d256d9b871de335bf5e7074 +dist/2025-04-02/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz=fa93a1285a97453e2aaaf9cf392abb4ff9a419451e925959470166522e54b1dc +dist/2025-04-02/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz=acb69df00475904faccf18729030a70e8ce21543189d48c7102330a98a12edf1 +dist/2025-04-02/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz=7141bf32c173d26f34571b2dfb890187d866f113e28b63908841377e48dbc6ab +dist/2025-04-02/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz=249f3c535805fb2510d13338401e9ae96f16e6996e58551025b35676a1147ab5 +dist/2025-04-02/cargo-beta-i686-pc-windows-gnu.tar.gz=fe4f5f35ecac25bc3726ffecbe3e650d51adb9ea13dc5153a0699ea8d8776d13 +dist/2025-04-02/cargo-beta-i686-pc-windows-gnu.tar.xz=b7b8432464eb793e9a651c4c38ee8abe76421a9be7f75e96237a4ef938f927f9 +dist/2025-04-02/cargo-beta-i686-pc-windows-msvc.tar.gz=a283da65d3a75435ff3d05441fd0337472fd16325531086e90b01cc5d5bd221a +dist/2025-04-02/cargo-beta-i686-pc-windows-msvc.tar.xz=ae19f98c901228ae5c7573cebde4816517bdb8d03dbdc7b92d95518d27d93531 +dist/2025-04-02/cargo-beta-i686-unknown-linux-gnu.tar.gz=e3c5b2560f64c8056ef82ed0cd659d35fda5181f19fa670b962228142398efbc +dist/2025-04-02/cargo-beta-i686-unknown-linux-gnu.tar.xz=3fc435b8a186f6ec1b7ebc38c92c2e23e1bd786415fc33e7743ef95c37c69b45 +dist/2025-04-02/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz=bcab46663be61e979b7a89792d164e182d5482ad9b444a969dbb304c5dad8c8c +dist/2025-04-02/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz=9e2ecb90d85a4aca95211892a6a41fde09ce1e4f44a60caab9aeb61833191d36 +dist/2025-04-02/cargo-beta-loongarch64-unknown-linux-musl.tar.gz=3c5c40f61e85663d03fe51f63d505d8dca73f94bfb3eed29f6e1396b31e0a554 +dist/2025-04-02/cargo-beta-loongarch64-unknown-linux-musl.tar.xz=775c56ce638e0923758ab5f82a87c15b7a1500d10e0be2433af40364a0455d58 +dist/2025-04-02/cargo-beta-powerpc-unknown-linux-gnu.tar.gz=c1a144dc83b673e0375e8f718cde6672ca276dbab9161d7f3e002c6273352c1b +dist/2025-04-02/cargo-beta-powerpc-unknown-linux-gnu.tar.xz=1b41b3396340c97c122661c95fe54265036e721f1750bad3a8fe4920f6f52b34 +dist/2025-04-02/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz=2a43a7682ea3da8b911b09a7bb4a3a75fc3facb64fc952e51ff35c63e6630b75 +dist/2025-04-02/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz=73a3383196527e63716de1b1cab233226519873556a755a7e47279f799936116 +dist/2025-04-02/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz=d5f521839bd4b258454097cf97b056508e6f9103f7312c93b632ae44ac9f7dc0 +dist/2025-04-02/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz=c4fc5ff91bc1054e8497efa53ee6a9a9eb7f06927cd314a681e16b6d46b08440 +dist/2025-04-02/cargo-beta-powerpc64le-unknown-linux-musl.tar.gz=5b0d569fe4ec84d6e7526af9d9794b440e8f1b5fc1b09e951678b09fd3ff97fb +dist/2025-04-02/cargo-beta-powerpc64le-unknown-linux-musl.tar.xz=e9c68eee5763c624cbe312bc1b50b6c3172eb7997e209371692e7f897d13b03b +dist/2025-04-02/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz=96962461e7f6744a46f18a557a4701d35d6fa3b6d960d854f4c3effe6f2636f8 +dist/2025-04-02/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz=4d6029204f930543afeeaf44d9e635692c86c9daaaac6301cccbe076c7facbe5 +dist/2025-04-02/cargo-beta-s390x-unknown-linux-gnu.tar.gz=f40421ea02804c3089420e5ca13838f94fb89c114de9a9e596e9a1207d2166d7 +dist/2025-04-02/cargo-beta-s390x-unknown-linux-gnu.tar.xz=77521eb215cded6886267644661b3357590f20368383f314da8f310197e9679e +dist/2025-04-02/cargo-beta-x86_64-apple-darwin.tar.gz=0357ed5c9c8ccbe71f89695bffe1604dbd2f451472fc6ea8d8d2dfc93a703b30 +dist/2025-04-02/cargo-beta-x86_64-apple-darwin.tar.xz=6ce4f66b60609f58046138831ae3828ad1d58f8d0b2f515f153c96b690a0134f +dist/2025-04-02/cargo-beta-x86_64-pc-windows-gnu.tar.gz=8fbf8506fc0c47bb30043c026107c51d6b548fa91320b5bbd2c608e191bdc007 +dist/2025-04-02/cargo-beta-x86_64-pc-windows-gnu.tar.xz=bb57df35e6d73b0b0bba58801d66febfed03f0b3f74085eb50ef8b5ea3fdbb40 +dist/2025-04-02/cargo-beta-x86_64-pc-windows-msvc.tar.gz=0bec5e9059c4b3035f636017c1586653d372f03969bcd4d80c0eaee52f01a2ac +dist/2025-04-02/cargo-beta-x86_64-pc-windows-msvc.tar.xz=3f836d3027d7ed25655f43262b126311bf014629dadc4a860f00302bc468e752 +dist/2025-04-02/cargo-beta-x86_64-unknown-freebsd.tar.gz=0f60566416471c38350c12f066bb512eca65a66319f5ee7fdbb60464d70661fa +dist/2025-04-02/cargo-beta-x86_64-unknown-freebsd.tar.xz=eae168df54ddfe95db669c205ae97baa902056722856fa174758ebd058168a95 +dist/2025-04-02/cargo-beta-x86_64-unknown-illumos.tar.gz=816eb91ac3858043f58075fc48fc2e90d0427c58b6283be589d337a7f0ddc9df +dist/2025-04-02/cargo-beta-x86_64-unknown-illumos.tar.xz=faba548d376309b71bcdae49f7089705be951f72a84ef68362aa6d865d40ebf9 +dist/2025-04-02/cargo-beta-x86_64-unknown-linux-gnu.tar.gz=1fe7e9d2c5a733acdaed418011c1fc31c3036e5299e8f9288ddeac43780fa35e +dist/2025-04-02/cargo-beta-x86_64-unknown-linux-gnu.tar.xz=7a39bd08e46d3e19da81c02ea3bb46bd1750a3ac1d1db8fb5db852cde14cdd72 +dist/2025-04-02/cargo-beta-x86_64-unknown-linux-musl.tar.gz=00df62b75e1811fd4fcc827b531e7ad94a73fcc37318d0aed28796d902b33568 +dist/2025-04-02/cargo-beta-x86_64-unknown-linux-musl.tar.xz=874084ab37814ddf50ef423e22f0721e5c24acd953ed02cf83432d2372606a5f +dist/2025-04-02/cargo-beta-x86_64-unknown-netbsd.tar.gz=7b4467e398bd34f94912c56863ae83b45415bbf612b3be15624a6a410c27ff2a +dist/2025-04-02/cargo-beta-x86_64-unknown-netbsd.tar.xz=75e7ac498a8e617bb907c26f2a3bba9a1e9a22af1c0946f88c7bd53c28790ffb +dist/2025-04-02/clippy-beta-aarch64-apple-darwin.tar.gz=0f5a8a6a96b8785beae1fc9476374d060632dcc4c17a4335031425ee8e2dec48 +dist/2025-04-02/clippy-beta-aarch64-apple-darwin.tar.xz=aed266be1799ae3e95099d491c3b20b731b2094bc8388c6ac3e782667b58ca6f +dist/2025-04-02/clippy-beta-aarch64-pc-windows-msvc.tar.gz=0ca97501432918d43aa9bed9b58cd4f1d0d738970e09d6c037ce967519b2b13f +dist/2025-04-02/clippy-beta-aarch64-pc-windows-msvc.tar.xz=c64edd87358c1ecb9e01b204977edaf0307cc939a3dd3ae62f151c153ac2019b +dist/2025-04-02/clippy-beta-aarch64-unknown-linux-gnu.tar.gz=7bfdd371ed44a32e50ecd6baf107796d5a77ca3cce0bd58bc5882afd98ca0edf +dist/2025-04-02/clippy-beta-aarch64-unknown-linux-gnu.tar.xz=cf49acab8153fb65867a9c44eabb7f156f85e9818b6f49453067ce0764036919 +dist/2025-04-02/clippy-beta-aarch64-unknown-linux-musl.tar.gz=bfb20f832ba30a4840f0d4898d27cf69b5717a78bd71b20270f8ddd66c48bc69 +dist/2025-04-02/clippy-beta-aarch64-unknown-linux-musl.tar.xz=54081690d35c39267a49d991e5e0c16043261b6969c49f23c2be44e46c3bfcdf +dist/2025-04-02/clippy-beta-arm-unknown-linux-gnueabi.tar.gz=3d88b69d6c67c58b09be9d679cfbe8ee449b9de419e950edcffd4637ded46cac +dist/2025-04-02/clippy-beta-arm-unknown-linux-gnueabi.tar.xz=67843ea0aeaab167029818669074e8bdc46a7e1c269a15580cdfe44a7d2ba96b +dist/2025-04-02/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz=46e9efe50418a035ddabf9a6467b6b0ef20453816c4b6dfd46fa1342bdc42167 +dist/2025-04-02/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz=3b27dc434e88280bbc89f5c5ba6eb68ec5332b549b73f7f8d79feda9cbb49628 +dist/2025-04-02/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz=670a6ce01ee6e5225b152a1357eba9a41cb47f04d08cdc8a0828eded4132aba1 +dist/2025-04-02/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz=cf92bed8c784e9579c09305fd227df3992950c227bc844a9b09995828d62e2cc +dist/2025-04-02/clippy-beta-i686-pc-windows-gnu.tar.gz=58238b6f4f8ad957a39c0eb63b45007d1c3f8c79e98307c7e5a531b7309a30f4 +dist/2025-04-02/clippy-beta-i686-pc-windows-gnu.tar.xz=e77c5215b3e96c59fa150330cb5144db66dac377fdad3be9c28f9fa07d9fb7cc +dist/2025-04-02/clippy-beta-i686-pc-windows-msvc.tar.gz=7c65df8af1f6f4102ffbd7fdaec50c24f89f2631edd06642732f1b5c74558ab4 +dist/2025-04-02/clippy-beta-i686-pc-windows-msvc.tar.xz=eeb119d26e1e2ddd3ef72741158d75d0db254f6420fd729d34abe5d172c7d765 +dist/2025-04-02/clippy-beta-i686-unknown-linux-gnu.tar.gz=c43518b27adce17f06f89c70ab52ae4c94f1f7129a182c16f9bb28fbc8a5f40b +dist/2025-04-02/clippy-beta-i686-unknown-linux-gnu.tar.xz=1d972c55d89cc01b7e408b4e24e8975bca29ff28578f224024a00f00d17c28b8 +dist/2025-04-02/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz=0d779bd9fcc5ed8e1db81a3a385bc0158c3903e5b0f0e4c99d172eee106a4f3e +dist/2025-04-02/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz=5515e0678c081ddae45f3f0c3c7ae58cc2f7b1141e1557a39826bf1aa58a2480 +dist/2025-04-02/clippy-beta-loongarch64-unknown-linux-musl.tar.gz=e99599c1fd0cab2eb0e89dd8e37e90ee2106d602a3edb3473fd65768bb8f7b27 +dist/2025-04-02/clippy-beta-loongarch64-unknown-linux-musl.tar.xz=f346a801dee3734461eab4303469d31faaf3e8f0d733b854470722ed48c66276 +dist/2025-04-02/clippy-beta-powerpc-unknown-linux-gnu.tar.gz=cd7b58e507d6695ada446ef9fa113a9588501832f4627b3e7cc0000a77c9265f +dist/2025-04-02/clippy-beta-powerpc-unknown-linux-gnu.tar.xz=0a7073874663b4ce8eb47a0257ac0cf8049acb34703241466f1208489c4dbee0 +dist/2025-04-02/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz=78d0b9581a7d79549bbb6a7e8984bf923a7b80bf6bb3979a90e90ceed8e66d33 +dist/2025-04-02/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz=79069a26ed617a2a07eef7cf098d028cb0c172fc4a6dc99115a51862b1b8bea8 +dist/2025-04-02/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz=23c58421839105c88937ad90a92603b7fcd6d9e21f291ab8c419fce1663a20a5 +dist/2025-04-02/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz=b546706d28c46f5bd3799d6b42201962ec2e9d6baf8df2b66cfcf1bc42789036 +dist/2025-04-02/clippy-beta-powerpc64le-unknown-linux-musl.tar.gz=31cf0d973eb3f0ca341a8d64c26b8b3b045b44b3c00d2497893dac6e44ebdeb4 +dist/2025-04-02/clippy-beta-powerpc64le-unknown-linux-musl.tar.xz=8afd89866c41631d4f4ac4d8a06d943473af7a96b043f6112216a04863817820 +dist/2025-04-02/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz=f08bf4ed1519e7c47f354a0d0b750933342314bacd4be761746666cf455cf74b +dist/2025-04-02/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz=e502f83f811c35e43df0a5e158d9eb61f60c9e1aacc75b588b2ba85022ca4b3e +dist/2025-04-02/clippy-beta-s390x-unknown-linux-gnu.tar.gz=21bede57083544028238ef6c9d24cbf9194a35c88500f2d0c5d50e6f0ae79616 +dist/2025-04-02/clippy-beta-s390x-unknown-linux-gnu.tar.xz=670c0a293e1b01f331c2645b648c1df087da4c1b5d689f608279b1ba524cbaef +dist/2025-04-02/clippy-beta-x86_64-apple-darwin.tar.gz=a6552e032c047203d5a9f5b767945c7a556be35468c42631c0c84cd049e24a8a +dist/2025-04-02/clippy-beta-x86_64-apple-darwin.tar.xz=17a9e9ea8e0d6140080b7fa4e3c77ad1a7fde3c3179f26b0aabe34c3af73b58a +dist/2025-04-02/clippy-beta-x86_64-pc-windows-gnu.tar.gz=2ffa8663502f4c6bba049318c70e79c174fd717d45ab4427103fc11563be678f +dist/2025-04-02/clippy-beta-x86_64-pc-windows-gnu.tar.xz=8c0a71f226b229f30a9acfbc1ab7c6bbedf692ef7b26737721a0518d3f1972ab +dist/2025-04-02/clippy-beta-x86_64-pc-windows-msvc.tar.gz=463c7a5d2a11beaeb1e63bc769db89fb9996a0558da15b4e091befe982893711 +dist/2025-04-02/clippy-beta-x86_64-pc-windows-msvc.tar.xz=40241fa6e463df734096e0e910b414c83d8a4dc8706b7c712cc170844e59e3c6 +dist/2025-04-02/clippy-beta-x86_64-unknown-freebsd.tar.gz=6464044b05b326d8ea594a963e38a52a1e27e0f028704427c41ec5e93e3772d9 +dist/2025-04-02/clippy-beta-x86_64-unknown-freebsd.tar.xz=77cdeb1e838c3da1d01252481f7c06149b0b8e7df48c2a2ee5961f4550d7b662 +dist/2025-04-02/clippy-beta-x86_64-unknown-illumos.tar.gz=d51238e1ad2329b9309e94b40f3374788e2fda9bf47466841a841392835e8a5e +dist/2025-04-02/clippy-beta-x86_64-unknown-illumos.tar.xz=6ad33945045790946fae843f63a805e60c09157e106ff342d3b99a201cd221e1 +dist/2025-04-02/clippy-beta-x86_64-unknown-linux-gnu.tar.gz=64b4f85d9eb75172928b46540090128ce9eec00e275d9027f74d0d5d4106bd76 +dist/2025-04-02/clippy-beta-x86_64-unknown-linux-gnu.tar.xz=b090383b4ebeae96fb340f0a363ee0276eb1f17a4f2a0f2ed81aff039f21bf78 +dist/2025-04-02/clippy-beta-x86_64-unknown-linux-musl.tar.gz=8d8025922c563bb1c872111722a4de298a8f85cd5be3e4cf753d44d6b8304de6 +dist/2025-04-02/clippy-beta-x86_64-unknown-linux-musl.tar.xz=ecf15ae9eb7dafe97afd69133f13364dac09d5e6edc35ddab91fb4ac32e17d42 +dist/2025-04-02/clippy-beta-x86_64-unknown-netbsd.tar.gz=c802af6a6f454b771046bd4a5207bdbe538cb6827becc9174dc229de5f874426 +dist/2025-04-02/clippy-beta-x86_64-unknown-netbsd.tar.xz=03d1e16eaf6f83f80e4cef8c7beebee97498135dd3138b97f97186b545edfb86 +dist/2025-04-02/rustfmt-nightly-aarch64-apple-darwin.tar.gz=c02047132bc7b48bbe930dfddb3afd31349eb042cb101a19d6e4360ea6e586ad +dist/2025-04-02/rustfmt-nightly-aarch64-apple-darwin.tar.xz=cf825dfaeb4d97eb2819ff8e46360192f480960f6b516e328ef8a9493d413a9f +dist/2025-04-02/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz=588551cbfb62eb4ed4e5755fe6eb3e1499a79e24a8a75f448b10d9a2237c63db +dist/2025-04-02/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz=df666f179fcfccb316aeb1a5eb4c17710b23198176edb34ba8b98c88cb369098 +dist/2025-04-02/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz=b06f4aefa01300ef1827a29c9fcd2e4da0c13f3aad92b4c929f6e8811d53ab71 +dist/2025-04-02/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz=059a888b8db76f5a3054a9a78a131d79c49060deaf70b2e2f03a4fcab44ab536 +dist/2025-04-02/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz=f0117a7be9eefe70fbd2f0d3fc05c51f3a97d069dc99500520a5d0973178fc6a +dist/2025-04-02/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz=f2fa87f1e814d0fb163146cf6a47d9375fec2c3778f76c33988acaa1665dacf7 +dist/2025-04-02/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz=fa53d4a6fb2ee3e1607d825afcc05063c0fa0dda1a3ede9a57e1ccc72cece8c4 +dist/2025-04-02/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz=3d785d982878f9bda4778cca0f9365947665849d5f7d2ee4794d8c28df3ab8c8 +dist/2025-04-02/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz=affb343357cd4c677cdeaf3b24698f20cfa15062cb63257aaa9bca3bd7baeeae +dist/2025-04-02/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz=6eb95c2021571a0c1ad3e3edf58fa4daa7711a9085e2ab61bc75799252183358 +dist/2025-04-02/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz=1dffc39afb9210c77e6d45b68cb801247f00afdf33107963c82a83bd94d2225e +dist/2025-04-02/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz=2da28dd8ec76744a7629619f527196689eb35e9bc60f3a5965ed69486e44235d +dist/2025-04-02/rustfmt-nightly-i686-pc-windows-gnu.tar.gz=5b1b39125106cdcbf12be9d5786900852f54eaa1429cabf28eeb68f96a008f90 +dist/2025-04-02/rustfmt-nightly-i686-pc-windows-gnu.tar.xz=3f2ecb3787c82a8dae89929aca4f2f3af790f1ab3c698adf21dde21c919a4052 +dist/2025-04-02/rustfmt-nightly-i686-pc-windows-msvc.tar.gz=eeb8b3f10f1cd75fac4e9e13dd1aee5941f38f1ff7fcfcaa69fcc3a42ea7c49a +dist/2025-04-02/rustfmt-nightly-i686-pc-windows-msvc.tar.xz=afd81cfd8d5fb37427c7eb2a1429c3b06d8daa1f42002c7230718fc56e132c47 +dist/2025-04-02/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz=5eb0f065a5403645ebb6c01d7f27a763f9446b8a48db5b6ff962b6f7c0f3ea3b +dist/2025-04-02/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz=3576e2e8ecc563cfbc4b3f464d80f8e27f412b5eb267656dc5f0316a11a2d299 +dist/2025-04-02/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz=5e69db53a1161ad7616f9e50d1a7fef785840bdf0ba81757d0b6811078692921 +dist/2025-04-02/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz=ba9d18dd2d63bad1e2863c9e14bbc4bd282d03cb806d03011d2d61ce701d934f +dist/2025-04-02/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.gz=b112f8c2e6ec011382c02a40ca07f30e1885a1396a7f2c30f099e56d756f2f54 +dist/2025-04-02/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.xz=42af68aa0b77306187d13ef881ee4327856f505a8a518f46244ffb17037f7e4e +dist/2025-04-02/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz=ed4277c9c8a27fdb97911bb9fbb46385b5fd807ac9338d31eecc3240bb0bc5c2 +dist/2025-04-02/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz=4cf3a7a64edd09b5d8ad72af545c15013842072e70789d1741f845f27c60566d +dist/2025-04-02/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz=65d49556ac1abd1da9cb7c41e518f85213ee2b1f05559c917614937d4c0cada9 +dist/2025-04-02/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz=535ea938d888ea12c139740e5d25ac4b82135b3274b8d86c3c59e36928922ec6 +dist/2025-04-02/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz=9776e0c641ae8a229453fe1fbdaaae05ea0caf37bb4893a00fe86e5d63d1241a +dist/2025-04-02/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz=bf73cfd35802b2706d0db96c854e8a4c45398297a59aef92226ac28d8bb69417 +dist/2025-04-02/rustfmt-nightly-powerpc64le-unknown-linux-musl.tar.gz=307012d0741898b3a2840ba3535832943ab6127f27323e587e1918b2023b37a2 +dist/2025-04-02/rustfmt-nightly-powerpc64le-unknown-linux-musl.tar.xz=79912529a393cb77c604f5a16d5b22611e938971656efd57fc5ef1980ffad35a +dist/2025-04-02/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz=854280cb3eeac146196ba30c8f3a010d568bf5bf9613d1870bd052a2aa3a03c0 +dist/2025-04-02/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz=36e6cfc2b333cf077e3e1bf651acab4e6845330fa151848926d7b33fafa016f3 +dist/2025-04-02/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz=19409bf4daa2e4d76c99659d7348f9a7dd4eb640c8bc81d93dc9170a1e51b7ba +dist/2025-04-02/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz=999346ff469e15507ec43c0b265a94b98ee99a0096d68ea0307a2280d138838f +dist/2025-04-02/rustfmt-nightly-x86_64-apple-darwin.tar.gz=6a52a943d59edb9e6ed97643b01a2ca2f51abb6fba1b4c9b73f59646372aac01 +dist/2025-04-02/rustfmt-nightly-x86_64-apple-darwin.tar.xz=3701a72b39a31e31c9fe65afa660a507088dfe6039867a2019bfb69970872bad +dist/2025-04-02/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz=c0dbe39a6dc72d96446312584055cfd75a4304c4859016ec7590d52813f0736c +dist/2025-04-02/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz=f9e8814cf2e0241bbe40bfafc62bb961d87060dd94c84fba8ea00b2992eafe2a +dist/2025-04-02/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz=b9a2c923b6794b3462882a9f5b1579e2463024a72ff34cdf4bdfd8b0f51ee528 +dist/2025-04-02/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz=c5e8272c451a3d685842e07a996e8bdc305ccb02a02d39f7f4cc764be4b2adce +dist/2025-04-02/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz=d47cb1e290f09795a04652f33afba39f80f3b6dcc4b570c14c75b1d945c78f0a +dist/2025-04-02/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz=389ea9f755623dd3d887bbff71189f86d7397c82e2f8fe660c27784cf7c68a94 +dist/2025-04-02/rustfmt-nightly-x86_64-unknown-illumos.tar.gz=b49f6c211c51a50309ddd2bcb4c886ebeef47e5413e6399778157bc90a37ed0e +dist/2025-04-02/rustfmt-nightly-x86_64-unknown-illumos.tar.xz=d53f55b6dba14bb2e2f90510c3e432781a8aad1f871d8f38795edf866ed4a4f3 +dist/2025-04-02/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz=2b8d77937298b23522ab9bd2f64a829f6faf1dccb87033f6006aa8c324474b47 +dist/2025-04-02/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz=0579d2a7c17cd585c49a42efe062466db777c1e7890f21b319234ee81c86ea39 +dist/2025-04-02/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz=65bc50db8fbe283e876b9ae7d6c15ff0461c1db8b3327f2992a99d21bcc3266c +dist/2025-04-02/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz=120505da1a8cddfb3f549438a52b2c73c76a9f1c2f25709db13d61efd214d732 +dist/2025-04-02/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz=d19004b3f6b9fa446e23f540b21a8f314d3bbcca11f753c9a6fdaf4c7ae7a2de +dist/2025-04-02/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz=e7facb66daed07789015c2d5b092afde5dbb1349d06cd0f80ae8319437587723 +dist/2025-04-02/rustc-nightly-aarch64-apple-darwin.tar.gz=3783e0aa4450a6bb913fc9a9799950892e65c7af9a2c895419090072999a2305 +dist/2025-04-02/rustc-nightly-aarch64-apple-darwin.tar.xz=4d3a72db4cfcd7663803f1a0b193326e37c7faecc0c97c3903a17fbc0f7c8848 +dist/2025-04-02/rustc-nightly-aarch64-pc-windows-msvc.tar.gz=c253308683fd394b1287a4eb9ca00cb8557bd7f7f91af8b087adccf9153a94eb +dist/2025-04-02/rustc-nightly-aarch64-pc-windows-msvc.tar.xz=63c30a1e523266dd6f8d6bb1525484f51fc6462bd7946900e0590b219f2a8b47 +dist/2025-04-02/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz=74d2313a732fc8401d62b9a8610bd9a25502f0372921c0e99d9d20f0cf8e3b19 +dist/2025-04-02/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz=a96db92f8c7cebe6e0d140a1853ecaa038e04975d62f17950e141d8ac2452536 +dist/2025-04-02/rustc-nightly-aarch64-unknown-linux-musl.tar.gz=250e2c21af9d4b284c7455668ebcc3d1e408c20cda1abf0ee69acac4c873e5ed +dist/2025-04-02/rustc-nightly-aarch64-unknown-linux-musl.tar.xz=931714cf51d93fee5cc9465e9a0e9d34c771fe2aaae46994f3b00da4c95a8f54 +dist/2025-04-02/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz=28f993889175ba3feb78b458be5282b2564a7c9b96117fed071835ff7b47f43f +dist/2025-04-02/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz=8645d1a7510cc13e2cd9abeffa71cbfb5f3a99990d27da2b05c336801a51c7f0 +dist/2025-04-02/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz=a86525223d8c5d67b0a92382b6ebce65761cdb83629e11bf29d625d688908d38 +dist/2025-04-02/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz=06a57a2c6298bb6e477d1e04922c626142bf96b2072684aecbbbf876bb4296f1 +dist/2025-04-02/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz=a7fb3babdc244ea1f025f3033d13088c50696db8d6db29efcc6a78474a06769e +dist/2025-04-02/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz=b130a7efa1c2bdfa5ef51237d5233ab6bd8feade7dc596d120b6501b4766a569 +dist/2025-04-02/rustc-nightly-i686-pc-windows-gnu.tar.gz=ebb4dda0d1ced3ec5aa14b1ef38227628db92a87f45b817d4ce41ff026a687ec +dist/2025-04-02/rustc-nightly-i686-pc-windows-gnu.tar.xz=43a69c9382b20249495824c149ffb5b5dae2ff7407c0c431859bc3e1f1ca4a7c +dist/2025-04-02/rustc-nightly-i686-pc-windows-msvc.tar.gz=bf3eb550e148e89e7ff17be5e72ad0462d57f3c452bfdc46b80a1812ec2fe457 +dist/2025-04-02/rustc-nightly-i686-pc-windows-msvc.tar.xz=b2dde774c1ef573c6a889c2d78bbb98f535f22be4b20896797be2f10781f0eb4 +dist/2025-04-02/rustc-nightly-i686-unknown-linux-gnu.tar.gz=96d130960b0dc1d8fa54f53d22a8fa8cf5aa35d0b213071404122e4e714feab0 +dist/2025-04-02/rustc-nightly-i686-unknown-linux-gnu.tar.xz=d743c6126151dd18624382a4228bf90af1239fc7fd97e763009b31666fb860fb +dist/2025-04-02/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz=090ec673f24758b8a4d0ce7b8c58fc6015585bd8392e37760283ffbe6045298c +dist/2025-04-02/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz=c71ad975a15c440890a7358b5459b7ca6b9d5e1842dd353071467c2a3f841605 +dist/2025-04-02/rustc-nightly-loongarch64-unknown-linux-musl.tar.gz=8806875cee039409632e8baf5433227af04bd07d015329d9512cc4f4879f687c +dist/2025-04-02/rustc-nightly-loongarch64-unknown-linux-musl.tar.xz=cebc3a4f1eb71e86e4e63f78e1c2f86fc98f7d23db1a3cb7e4c4d385e5591d51 +dist/2025-04-02/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz=643dc0fe347a78a82321b5f47b41b09025856b6383ef67274ba3324879aae75e +dist/2025-04-02/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz=955018b90daf3797497dfc423aec731e8d0320b96dcf42db1705b761e1e0dd58 +dist/2025-04-02/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz=aed278e57ffe0eb54328a9536607bc179806e0c2de9fccb9779a4517752899e5 +dist/2025-04-02/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz=0b6e0305b13d867c677243b16613f62b07352038f5e7ad7e1865cc2d00168283 +dist/2025-04-02/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz=e10d8eee30be690aa2e6ff58ca554d47173086d5df8f0ea8581b3fd10d4cee0a +dist/2025-04-02/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz=3ca3c258404dd8718321ed8a50aa6512fea9d810120db225a3fcfe56d7b83064 +dist/2025-04-02/rustc-nightly-powerpc64le-unknown-linux-musl.tar.gz=ddfc329b8932ad796c0eb7618632f9ae0c5ffb7a6093ea7d5cc4185fc0537f22 +dist/2025-04-02/rustc-nightly-powerpc64le-unknown-linux-musl.tar.xz=b4e82b64f2e934e17fc9b270295554a8bf0bd3d38ffffc66b367aad5bee3ad6f +dist/2025-04-02/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz=116d290065bd9e8ff2ca57440e94f773f68adf79aedba767159dfb92fe1a42b0 +dist/2025-04-02/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz=6e1deb0c47bba4b56bbf1d04344e45f0490938455aee421629f2fcfd309eff64 +dist/2025-04-02/rustc-nightly-s390x-unknown-linux-gnu.tar.gz=445f8a0ca579153b449fa0d36460227af68399c4227be76e4cbb3d65cef9055c +dist/2025-04-02/rustc-nightly-s390x-unknown-linux-gnu.tar.xz=d87bcac173e9800dc1c1b28e668a1b4c3616029d0ca53adfa4ac382733610193 +dist/2025-04-02/rustc-nightly-x86_64-apple-darwin.tar.gz=4342b89aed19f409df56bfac3d6ac071a02cb6839a52d19fdff9d10cc1d9f540 +dist/2025-04-02/rustc-nightly-x86_64-apple-darwin.tar.xz=cb787327895f275e6f9025bb38c6337492c839310931b8c7ba39743813621701 +dist/2025-04-02/rustc-nightly-x86_64-pc-windows-gnu.tar.gz=6cddd0d3cf18780b36776fd0324643a36b3294923531a741cc763516c8238caf +dist/2025-04-02/rustc-nightly-x86_64-pc-windows-gnu.tar.xz=cefc15752bd84b290f50b958b96feb0134d420a10c6f36791424c762cda08abc +dist/2025-04-02/rustc-nightly-x86_64-pc-windows-msvc.tar.gz=731e968787044081453a559a95579435654b47f91a9b7f94579ac007ed3e4cf9 +dist/2025-04-02/rustc-nightly-x86_64-pc-windows-msvc.tar.xz=3d9b173043aed73aa3ab1fa0b14d0ce2149a4943f4bb10aa1e31af619afe0eed +dist/2025-04-02/rustc-nightly-x86_64-unknown-freebsd.tar.gz=c0df2f0a354d2d657d8ec8091bc094060321b343c8e7bb8e4315cfe042dacfc3 +dist/2025-04-02/rustc-nightly-x86_64-unknown-freebsd.tar.xz=8933bc0361484ac7c6b226defaea73eda5c4e10462e7ea54052c7e1d370e48c0 +dist/2025-04-02/rustc-nightly-x86_64-unknown-illumos.tar.gz=5887f913ac80dfe9826619227c66eb234a2b4848e6bc4f41c6fdd8102bf981e9 +dist/2025-04-02/rustc-nightly-x86_64-unknown-illumos.tar.xz=4a54b8b09eba43df0d99fb6e03177cf8ba2214a5810be52ac33ee3d9d33e98bc +dist/2025-04-02/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz=1c0bb76acd7944804d52c3139f4dcf154d3221cdeb300bb6b9bca726cd6ad30f +dist/2025-04-02/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz=e67a33440c3e021ff2dd41add0fb05db6c0e8ae68bd30d33e8b3185b0bb7191b +dist/2025-04-02/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=0ea7e17d7bb67d6a6c4b2f864aaffcd96512f15f17f0acc63751eb1df6c486a7 +dist/2025-04-02/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=b73d37b704ab58921172cc561f5598db6a504dcd4d7980966f7c26caaf6d3594 +dist/2025-04-02/rustc-nightly-x86_64-unknown-netbsd.tar.gz=986f6c594d37bcbd3833e053640ba8775f68d26a65c5618386654ef55d7b3542 +dist/2025-04-02/rustc-nightly-x86_64-unknown-netbsd.tar.xz=c0d9a88c30d2ab38ec3a11fabb5515ed9bc3ac1a8e35a438d68bf7ff82f6b843 \ No newline at end of file From c93005ee651422f1920ef2a68e5ab9ff772b4b06 Mon Sep 17 00:00:00 2001 From: Boxy Date: Wed, 2 Apr 2025 21:28:54 +0100 Subject: [PATCH 258/606] update cfgs --- .../src/obligation_forest/mod.rs | 2 +- compiler/rustc_error_messages/src/lib.rs | 2 +- compiler/rustc_middle/src/mir/terminator.rs | 6 +-- compiler/rustc_middle/src/query/erase.rs | 4 +- compiler/rustc_next_trait_solver/src/lib.rs | 2 +- compiler/rustc_type_ir/src/lib.rs | 2 +- library/alloc/src/alloc.rs | 14 +++--- library/core/Cargo.toml | 2 - library/core/src/clone.rs | 2 +- library/core/src/fmt/mod.rs | 28 ----------- library/core/src/fmt/rt.rs | 29 +---------- library/core/src/intrinsics/mod.rs | 48 ------------------- library/core/src/macros/mod.rs | 1 - library/core/src/pat.rs | 6 +-- library/core/src/pin.rs | 2 +- library/core/src/prelude/v1.rs | 1 - library/coretests/tests/pin_macro.rs | 1 - library/panic_unwind/src/lib.rs | 4 +- library/proc_macro/src/bridge/mod.rs | 1 - library/std/src/alloc.rs | 2 +- library/std/src/backtrace.rs | 2 +- library/std/src/panicking.rs | 4 +- library/std/src/prelude/v1.rs | 1 - src/tools/compiletest/src/header/tests.rs | 3 -- 24 files changed, 29 insertions(+), 140 deletions(-) diff --git a/compiler/rustc_data_structures/src/obligation_forest/mod.rs b/compiler/rustc_data_structures/src/obligation_forest/mod.rs index f63b201742d9..2c62034c6e87 100644 --- a/compiler/rustc_data_structures/src/obligation_forest/mod.rs +++ b/compiler/rustc_data_structures/src/obligation_forest/mod.rs @@ -315,7 +315,7 @@ mod helper { use super::*; pub(super) type ObligationTreeIdGenerator = impl Iterator; impl ObligationForest { - #[cfg_attr(not(bootstrap), define_opaque(ObligationTreeIdGenerator))] + #[define_opaque(ObligationTreeIdGenerator)] pub fn new() -> ObligationForest { ObligationForest { nodes: vec![], diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 39e78ae88416..3c6df147b1ba 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -208,7 +208,7 @@ pub type LazyFallbackBundle = Arc Fluent /// Return the default `FluentBundle` with standard "en-US" diagnostic messages. #[instrument(level = "trace", skip(resources))] -#[cfg_attr(not(bootstrap), define_opaque(LazyFallbackBundle))] +#[define_opaque(LazyFallbackBundle)] pub fn fallback_fluent_bundle( resources: Vec<&'static str>, with_directionality_markers: bool, diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index b2c51ad88645..82e8422c52dc 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -454,7 +454,7 @@ mod helper { /// Like [`SwitchTargets::target_for_value`], but returning the same type as /// [`Terminator::successors`]. #[inline] - #[cfg_attr(not(bootstrap), define_opaque(Successors))] + #[define_opaque(Successors)] pub fn successors_for_value(&self, value: u128) -> Successors<'_> { let target = self.target_for_value(value); (&[]).into_iter().copied().chain(Some(target)) @@ -463,7 +463,7 @@ mod helper { impl<'tcx> TerminatorKind<'tcx> { #[inline] - #[cfg_attr(not(bootstrap), define_opaque(Successors))] + #[define_opaque(Successors)] pub fn successors(&self) -> Successors<'_> { use self::TerminatorKind::*; match *self { @@ -502,7 +502,7 @@ mod helper { } #[inline] - #[cfg_attr(not(bootstrap), define_opaque(SuccessorsMut))] + #[define_opaque(SuccessorsMut)] pub fn successors_mut(&mut self) -> SuccessorsMut<'_> { use self::TerminatorKind::*; match *self { diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 6c6b9a5510c6..5bd111fa2f22 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -25,7 +25,7 @@ pub trait EraseType: Copy { pub type Erase = Erased; #[inline(always)] -#[cfg_attr(not(bootstrap), define_opaque(Erase))] +#[define_opaque(Erase)] pub fn erase(src: T) -> Erase { // Ensure the sizes match const { @@ -49,7 +49,7 @@ pub fn erase(src: T) -> Erase { /// Restores an erased value. #[inline(always)] -#[cfg_attr(not(bootstrap), define_opaque(Erase))] +#[define_opaque(Erase)] pub fn restore(value: Erase) -> T { let value: Erased<::Result> = value; // See comment in `erase` for why we use `transmute_unchecked`. diff --git a/compiler/rustc_next_trait_solver/src/lib.rs b/compiler/rustc_next_trait_solver/src/lib.rs index f575fe03019e..92cdc28a37b4 100644 --- a/compiler/rustc_next_trait_solver/src/lib.rs +++ b/compiler/rustc_next_trait_solver/src/lib.rs @@ -6,7 +6,7 @@ // tidy-alphabetical-start #![allow(rustc::usage_of_type_ir_inherent)] -#![cfg_attr(not(bootstrap), allow(rustc::usage_of_type_ir_traits))] +#![allow(rustc::usage_of_type_ir_traits)] // tidy-alphabetical-end pub mod canonicalizer; diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 4e2baca27854..bdc61e956f8c 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -1,12 +1,12 @@ // tidy-alphabetical-start #![allow(rustc::usage_of_ty_tykind)] #![allow(rustc::usage_of_type_ir_inherent)] +#![allow(rustc::usage_of_type_ir_traits)] #![cfg_attr( feature = "nightly", feature(associated_type_defaults, never_type, rustc_attrs, negative_impls) )] #![cfg_attr(feature = "nightly", allow(internal_features))] -#![cfg_attr(not(bootstrap), allow(rustc::usage_of_type_ir_traits))] // tidy-alphabetical-end extern crate self as rustc_type_ir; diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index 1e03a191276c..e1cc4ba25c4e 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -16,22 +16,22 @@ unsafe extern "Rust" { // otherwise. #[rustc_allocator] #[rustc_nounwind] - #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)] + #[rustc_std_internal_symbol] fn __rust_alloc(size: usize, align: usize) -> *mut u8; #[rustc_deallocator] #[rustc_nounwind] - #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)] + #[rustc_std_internal_symbol] fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize); #[rustc_reallocator] #[rustc_nounwind] - #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)] + #[rustc_std_internal_symbol] fn __rust_realloc(ptr: *mut u8, old_size: usize, align: usize, new_size: usize) -> *mut u8; #[rustc_allocator_zeroed] #[rustc_nounwind] - #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)] + #[rustc_std_internal_symbol] fn __rust_alloc_zeroed(size: usize, align: usize) -> *mut u8; - #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)] + #[rustc_std_internal_symbol] static __rust_no_alloc_shim_is_unstable: u8; } @@ -360,7 +360,7 @@ unsafe extern "Rust" { // This is the magic symbol to call the global alloc error handler. rustc generates // it to call `__rg_oom` if there is a `#[alloc_error_handler]`, or to call the // default implementations below (`__rdl_oom`) otherwise. - #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)] + #[rustc_std_internal_symbol] fn __rust_alloc_error_handler(size: usize, align: usize) -> !; } @@ -427,7 +427,7 @@ pub mod __alloc_error_handler { unsafe extern "Rust" { // This symbol is emitted by rustc next to __rust_alloc_error_handler. // Its value depends on the -Zoom={panic,abort} compiler option. - #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)] + #[rustc_std_internal_symbol] static __rust_alloc_error_handler_should_panic: u8; } diff --git a/library/core/Cargo.toml b/library/core/Cargo.toml index b60826ee4e6c..fe61f552a49d 100644 --- a/library/core/Cargo.toml +++ b/library/core/Cargo.toml @@ -32,8 +32,6 @@ check-cfg = [ 'cfg(bootstrap)', 'cfg(no_fp_fmt_parse)', 'cfg(stdarch_intel_sde)', - # #[cfg(bootstrap)] - 'cfg(target_feature, values("vector-enhancements-1"))', # core use #[path] imports to portable-simd `core_simd` crate # and to stdarch `core_arch` crate which messes-up with Cargo list # of declared features, we therefor expect any feature cfg diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs index e0ac0bfc5289..374a56f1252f 100644 --- a/library/core/src/clone.rs +++ b/library/core/src/clone.rs @@ -216,7 +216,7 @@ pub macro Clone($item:item) { /// Use closures allow captured values to be automatically used. /// This is similar to have a closure that you would call `.use` over each captured value. #[unstable(feature = "ergonomic_clones", issue = "132290")] -#[cfg_attr(not(bootstrap), lang = "use_cloned")] +#[lang = "use_cloned"] pub trait UseCloned: Clone { // Empty. } diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index ec7c1705fb86..7ca390941bcd 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -1515,19 +1515,6 @@ unsafe fn run(fmt: &mut Formatter<'_>, arg: &rt::Placeholder, args: &[rt::Argume // which guarantees the indexes are always within bounds. unsafe { (getcount(args, &arg.width), getcount(args, &arg.precision)) }; - #[cfg(bootstrap)] - let options = - *FormattingOptions { flags: flags::ALWAYS_SET | arg.flags << 21, width: 0, precision: 0 } - .align(match arg.align { - rt::Alignment::Left => Some(Alignment::Left), - rt::Alignment::Right => Some(Alignment::Right), - rt::Alignment::Center => Some(Alignment::Center), - rt::Alignment::Unknown => None, - }) - .fill(arg.fill) - .width(width) - .precision(precision); - #[cfg(not(bootstrap))] let options = FormattingOptions { flags: arg.flags, width, precision }; // Extract the correct argument @@ -1544,21 +1531,6 @@ unsafe fn run(fmt: &mut Formatter<'_>, arg: &rt::Placeholder, args: &[rt::Argume unsafe { value.fmt(fmt) } } -#[cfg(bootstrap)] -unsafe fn getcount(args: &[rt::Argument<'_>], cnt: &rt::Count) -> Option { - match *cnt { - rt::Count::Is(n) => Some(n as u16), - rt::Count::Implied => None, - rt::Count::Param(i) => { - debug_assert!(i < args.len()); - // SAFETY: cnt and args come from the same Arguments, - // which guarantees this index is always within bounds. - unsafe { args.get_unchecked(i).as_u16() } - } - } -} - -#[cfg(not(bootstrap))] unsafe fn getcount(args: &[rt::Argument<'_>], cnt: &rt::Count) -> u16 { match *cnt { rt::Count::Is(n) => n, diff --git a/library/core/src/fmt/rt.rs b/library/core/src/fmt/rt.rs index 0b04ebccae2b..0459674303d1 100644 --- a/library/core/src/fmt/rt.rs +++ b/library/core/src/fmt/rt.rs @@ -11,10 +11,6 @@ use crate::ptr::NonNull; #[derive(Copy, Clone)] pub struct Placeholder { pub position: usize, - #[cfg(bootstrap)] - pub fill: char, - #[cfg(bootstrap)] - pub align: Alignment, pub flags: u32, pub precision: Count, pub width: Count, @@ -23,38 +19,17 @@ pub struct Placeholder { #[cfg(bootstrap)] impl Placeholder { #[inline] - pub const fn new( - position: usize, - fill: char, - align: Alignment, - flags: u32, - precision: Count, - width: Count, - ) -> Self { - Self { position, fill, align, flags, precision, width } + pub const fn new(position: usize, flags: u32, precision: Count, width: Count) -> Self { + Self { position, flags, precision, width } } } -#[cfg(bootstrap)] -#[lang = "format_alignment"] -#[derive(Copy, Clone, PartialEq, Eq)] -pub enum Alignment { - Left, - Right, - Center, - Unknown, -} - /// Used by [width](https://doc.rust-lang.org/std/fmt/#width) /// and [precision](https://doc.rust-lang.org/std/fmt/#precision) specifiers. #[lang = "format_count"] #[derive(Copy, Clone)] pub enum Count { /// Specified with a literal number, stores the value - #[cfg(bootstrap)] - Is(usize), - /// Specified with a literal number, stores the value - #[cfg(not(bootstrap))] Is(u16), /// Specified using `$` and `*` syntaxes, stores the index into `args` Param(usize), diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index f81a6ca69ada..ad33e2e5fe94 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -2304,20 +2304,8 @@ pub unsafe fn truncf128(x: f128) -> f128; /// [`f16::round_ties_even`](../../std/primitive.f16.html#method.round_ties_even) #[rustc_intrinsic] #[rustc_nounwind] -#[cfg(not(bootstrap))] pub fn round_ties_even_f16(x: f16) -> f16; -/// To be removed on next bootstrap bump. -#[cfg(bootstrap)] -pub fn round_ties_even_f16(x: f16) -> f16 { - #[rustc_intrinsic] - #[rustc_nounwind] - unsafe fn rintf16(x: f16) -> f16; - - // SAFETY: this intrinsic isn't actually unsafe - unsafe { rintf16(x) } -} - /// Returns the nearest integer to an `f32`. Rounds half-way cases to the number with an even /// least significant digit. /// @@ -2325,20 +2313,8 @@ pub fn round_ties_even_f16(x: f16) -> f16 { /// [`f32::round_ties_even`](../../std/primitive.f32.html#method.round_ties_even) #[rustc_intrinsic] #[rustc_nounwind] -#[cfg(not(bootstrap))] pub fn round_ties_even_f32(x: f32) -> f32; -/// To be removed on next bootstrap bump. -#[cfg(bootstrap)] -pub fn round_ties_even_f32(x: f32) -> f32 { - #[rustc_intrinsic] - #[rustc_nounwind] - unsafe fn rintf32(x: f32) -> f32; - - // SAFETY: this intrinsic isn't actually unsafe - unsafe { rintf32(x) } -} - /// Provided for compatibility with stdarch. DO NOT USE. #[inline(always)] pub unsafe fn rintf32(x: f32) -> f32 { @@ -2352,20 +2328,8 @@ pub unsafe fn rintf32(x: f32) -> f32 { /// [`f64::round_ties_even`](../../std/primitive.f64.html#method.round_ties_even) #[rustc_intrinsic] #[rustc_nounwind] -#[cfg(not(bootstrap))] pub fn round_ties_even_f64(x: f64) -> f64; -/// To be removed on next bootstrap bump. -#[cfg(bootstrap)] -pub fn round_ties_even_f64(x: f64) -> f64 { - #[rustc_intrinsic] - #[rustc_nounwind] - unsafe fn rintf64(x: f64) -> f64; - - // SAFETY: this intrinsic isn't actually unsafe - unsafe { rintf64(x) } -} - /// Provided for compatibility with stdarch. DO NOT USE. #[inline(always)] pub unsafe fn rintf64(x: f64) -> f64 { @@ -2379,20 +2343,8 @@ pub unsafe fn rintf64(x: f64) -> f64 { /// [`f128::round_ties_even`](../../std/primitive.f128.html#method.round_ties_even) #[rustc_intrinsic] #[rustc_nounwind] -#[cfg(not(bootstrap))] pub fn round_ties_even_f128(x: f128) -> f128; -/// To be removed on next bootstrap bump. -#[cfg(bootstrap)] -pub fn round_ties_even_f128(x: f128) -> f128 { - #[rustc_intrinsic] - #[rustc_nounwind] - unsafe fn rintf128(x: f128) -> f128; - - // SAFETY: this intrinsic isn't actually unsafe - unsafe { rintf128(x) } -} - /// Returns the nearest integer to an `f16`. Rounds half-way cases away from zero. /// /// The stabilized version of this intrinsic is diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 5f200b31d1ae..7f0949f3ad82 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1753,7 +1753,6 @@ pub(crate) mod builtin { reason = "`type_alias_impl_trait` has open design concerns" )] #[rustc_builtin_macro] - #[cfg(not(bootstrap))] pub macro define_opaque($($tt:tt)*) { /* compiler built-in */ } diff --git a/library/core/src/pat.rs b/library/core/src/pat.rs index f8826096df3e..91d015b1bc53 100644 --- a/library/core/src/pat.rs +++ b/library/core/src/pat.rs @@ -25,15 +25,15 @@ macro_rules! pattern_type { )] pub trait RangePattern { /// Trait version of the inherent `MIN` assoc const. - #[cfg_attr(not(bootstrap), lang = "RangeMin")] + #[lang = "RangeMin"] const MIN: Self; /// Trait version of the inherent `MIN` assoc const. - #[cfg_attr(not(bootstrap), lang = "RangeMax")] + #[lang = "RangeMax"] const MAX: Self; /// A compile-time helper to subtract 1 for exclusive ranges. - #[cfg_attr(not(bootstrap), lang = "RangeSub")] + #[lang = "RangeSub"] #[track_caller] fn sub_one(self) -> Self; } diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index bc097bf198d0..2ef1bbfd1fa7 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -1943,7 +1943,7 @@ unsafe impl PinCoerceUnsized for *mut T {} #[stable(feature = "pin_macro", since = "1.68.0")] #[rustc_macro_transparency = "semitransparent"] #[allow_internal_unstable(unsafe_pin_internals)] -#[cfg_attr(not(bootstrap), rustc_macro_edition_2021)] +#[rustc_macro_edition_2021] pub macro pin($value:expr $(,)?) { // This is `Pin::new_unchecked(&mut { $value })`, so, for starters, let's // review such a hypothetical macro (that any user-code could define): diff --git a/library/core/src/prelude/v1.rs b/library/core/src/prelude/v1.rs index c5975c030503..8f1b5275871e 100644 --- a/library/core/src/prelude/v1.rs +++ b/library/core/src/prelude/v1.rs @@ -117,5 +117,4 @@ pub use crate::macros::builtin::deref; issue = "63063", reason = "`type_alias_impl_trait` has open design concerns" )] -#[cfg(not(bootstrap))] pub use crate::macros::builtin::define_opaque; diff --git a/library/coretests/tests/pin_macro.rs b/library/coretests/tests/pin_macro.rs index 3174c91a6498..bfbfa8d280fa 100644 --- a/library/coretests/tests/pin_macro.rs +++ b/library/coretests/tests/pin_macro.rs @@ -38,7 +38,6 @@ fn rust_2024_expr() { } #[test] -#[cfg(not(bootstrap))] fn temp_lifetime() { // Check that temporary lifetimes work as in Rust 2021. // Regression test for https://github.com/rust-lang/rust/issues/138596 diff --git a/library/panic_unwind/src/lib.rs b/library/panic_unwind/src/lib.rs index e5c1d6bdb3b0..50bd933aca20 100644 --- a/library/panic_unwind/src/lib.rs +++ b/library/panic_unwind/src/lib.rs @@ -79,11 +79,11 @@ cfg_if::cfg_if! { unsafe extern "C" { /// Handler in std called when a panic object is dropped outside of /// `catch_unwind`. - #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)] + #[rustc_std_internal_symbol] fn __rust_drop_panic() -> !; /// Handler in std called when a foreign exception is caught. - #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)] + #[rustc_std_internal_symbol] fn __rust_foreign_exception() -> !; } diff --git a/library/proc_macro/src/bridge/mod.rs b/library/proc_macro/src/bridge/mod.rs index 52cc8fba0438..1b5c221425ec 100644 --- a/library/proc_macro/src/bridge/mod.rs +++ b/library/proc_macro/src/bridge/mod.rs @@ -9,7 +9,6 @@ #![deny(unsafe_code)] // proc_macros anyway don't work on wasm hosts so while both sides of this bridge can // be built with different versions of rustc, the wasm ABI changes don't really matter. -#![cfg_attr(bootstrap, allow(unknown_lints))] #![allow(wasm_c_abi)] use std::hash::Hash; diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs index 5d2a304b41c5..75971ac90e78 100644 --- a/library/std/src/alloc.rs +++ b/library/std/src/alloc.rs @@ -348,7 +348,7 @@ fn default_alloc_error_hook(layout: Layout) { unsafe extern "Rust" { // This symbol is emitted by rustc next to __rust_alloc_error_handler. // Its value depends on the -Zoom={panic,abort} compiler option. - #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)] + #[rustc_std_internal_symbol] static __rust_alloc_error_handler_should_panic: u8; } diff --git a/library/std/src/backtrace.rs b/library/std/src/backtrace.rs index 3e641ac5d904..3683485640c2 100644 --- a/library/std/src/backtrace.rs +++ b/library/std/src/backtrace.rs @@ -432,7 +432,7 @@ mod helper { use super::*; pub(super) type LazyResolve = impl (FnOnce() -> Capture) + Send + Sync + UnwindSafe; - #[cfg_attr(not(bootstrap), define_opaque(LazyResolve))] + #[define_opaque(LazyResolve)] pub(super) fn lazy_resolve(mut capture: Capture) -> LazyResolve { move || { // Use the global backtrace lock to synchronize this as it's a diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index b35549c92ada..a3950980b5e3 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -55,14 +55,14 @@ pub static EMPTY_PANIC: fn(&'static str) -> ! = // hook up these functions, but it is not this day! #[allow(improper_ctypes)] unsafe extern "C" { - #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)] + #[rustc_std_internal_symbol] fn __rust_panic_cleanup(payload: *mut u8) -> *mut (dyn Any + Send + 'static); } unsafe extern "Rust" { /// `PanicPayload` lazily performs allocation only when needed (this avoids /// allocations when using the "abort" panic runtime). - #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)] + #[rustc_std_internal_symbol] fn __rust_start_panic(payload: &mut dyn PanicPayload) -> u32; } diff --git a/library/std/src/prelude/v1.rs b/library/std/src/prelude/v1.rs index 4217f6586407..c15d8c40085a 100644 --- a/library/std/src/prelude/v1.rs +++ b/library/std/src/prelude/v1.rs @@ -109,7 +109,6 @@ pub use core::prelude::v1::deref; issue = "63063", reason = "`type_alias_impl_trait` has open design concerns" )] -#[cfg(not(bootstrap))] pub use core::prelude::v1::define_opaque; // The file so far is equivalent to core/src/prelude/v1.rs. It is duplicated diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index ff6bc49b72a1..1a796cdd7cd8 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -459,9 +459,6 @@ fn profiler_runtime() { #[test] fn asm_support() { let asms = [ - #[cfg(bootstrap)] - ("avr-unknown-gnu-atmega328", false), - #[cfg(not(bootstrap))] ("avr-none", false), ("i686-unknown-netbsd", true), ("riscv32gc-unknown-linux-gnu", true), From 2b684f39e4c768526ff6ec35c7f5a5abd306d086 Mon Sep 17 00:00:00 2001 From: Boxy Date: Wed, 2 Apr 2025 21:29:39 +0100 Subject: [PATCH 259/606] update missing targets list --- src/bootstrap/src/core/sanity.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index dbfebd11f828..891340add908 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -34,7 +34,6 @@ pub struct Finder { // Targets can be removed from this list once they are present in the stage0 compiler (usually by updating the beta compiler of the bootstrap). const STAGE0_MISSING_TARGETS: &[&str] = &[ // just a dummy comment so the list doesn't get onelined - "wasm32-wali-linux-musl", ]; /// Minimum version threshold for libstdc++ required when using prebuilt LLVM From c274459b63a7b89e852afd6562890d255bea850e Mon Sep 17 00:00:00 2001 From: Boxy Date: Wed, 2 Apr 2025 21:33:51 +0100 Subject: [PATCH 260/606] clippy lints --- src/bootstrap/src/core/build_steps/tool.rs | 1 - src/bootstrap/src/core/builder/mod.rs | 1 - src/bootstrap/src/lib.rs | 2 +- src/bootstrap/src/utils/helpers.rs | 4 +--- 4 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index b58d279359e3..7cc7093e23b3 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -817,7 +817,6 @@ impl Step for LldWrapper { fields(build_compiler = ?self.build_compiler, target_compiler = ?self.target_compiler), ), )] - fn run(self, builder: &Builder<'_>) -> ToolBuildResult { if builder.config.dry_run() { return ToolBuildResult { diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index f002903996b2..8aae5255d7e1 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -1276,7 +1276,6 @@ impl<'a> Builder<'a> { ), ), )] - /// FIXME: This function is unnecessary (and dangerous, see ). /// We already have uplifting logic for the compiler, so remove this. pub fn compiler_for( diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 7c60e0421421..1a513a240e17 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -1557,7 +1557,7 @@ Executed at: {executed_at}"#, !self.config.full_bootstrap && !self.config.download_rustc() && stage >= 2 - && (self.hosts.iter().any(|h| *h == target) || target == self.build) + && (self.hosts.contains(&target) || target == self.build) } /// Checks whether the `compiler` compiling for `target` should be forced to diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs index 78dcdcbd1874..ee8fe7aa9d21 100644 --- a/src/bootstrap/src/utils/helpers.rs +++ b/src/bootstrap/src/utils/helpers.rs @@ -432,9 +432,7 @@ pub fn dir_is_empty(dir: &Path) -> bool { /// the "y" part from the string. pub fn extract_beta_rev(version: &str) -> Option { let parts = version.splitn(2, "-beta.").collect::>(); - let count = parts.get(1).and_then(|s| s.find(' ').map(|p| s[..p].to_string())); - - count + parts.get(1).and_then(|s| s.find(' ').map(|p| s[..p].to_string())) } pub enum LldThreads { From acf678bd4c796bcc220fea8f9702777fd11b1827 Mon Sep 17 00:00:00 2001 From: Boxy Date: Thu, 3 Apr 2025 23:10:20 +0100 Subject: [PATCH 261/606] intra-doc link --- library/alloc/src/collections/btree/set_val.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/alloc/src/collections/btree/set_val.rs b/library/alloc/src/collections/btree/set_val.rs index cf30160bfbbc..5037b6578e80 100644 --- a/library/alloc/src/collections/btree/set_val.rs +++ b/library/alloc/src/collections/btree/set_val.rs @@ -9,7 +9,7 @@ pub(super) struct SetValZST; /// Returns `true` only for type `SetValZST`, `false` for all other types (blanket implementation). /// `TypeId` requires a `'static` lifetime, use of this trait avoids that restriction. /// -/// [`TypeId`]: std::any::TypeId +/// [`TypeId`]: core::any::TypeId pub(super) trait IsSetVal { fn is_set_val() -> bool; } From 5a5bda52f09214c5771cf0b2be5f4579a0d888c7 Mon Sep 17 00:00:00 2001 From: Boxy Date: Wed, 9 Apr 2025 12:04:03 +0100 Subject: [PATCH 262/606] Update boostrap --- src/bootstrap/src/core/build_steps/test.rs | 20 ++++---------------- src/bootstrap/src/core/builder/cargo.rs | 6 +++--- src/bootstrap/src/core/builder/mod.rs | 2 +- src/bootstrap/src/utils/helpers.rs | 14 +++----------- 4 files changed, 11 insertions(+), 31 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 8e42e845a8cb..e23c1ab5a238 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -261,13 +261,7 @@ impl Step for Cargotest { .args(builder.config.test_args()) .env("RUSTC", builder.rustc(compiler)) .env("RUSTDOC", builder.rustdoc(compiler)); - add_rustdoc_cargo_linker_args( - &mut cmd, - builder, - compiler.host, - LldThreads::No, - compiler.stage, - ); + add_rustdoc_cargo_linker_args(&mut cmd, builder, compiler.host, LldThreads::No); cmd.delay_failure().run(builder); } } @@ -845,7 +839,7 @@ impl Step for RustdocTheme { .env("CFG_RELEASE_CHANNEL", &builder.config.channel) .env("RUSTDOC_REAL", builder.rustdoc(self.compiler)) .env("RUSTC_BOOTSTRAP", "1"); - cmd.args(linker_args(builder, self.compiler.host, LldThreads::No, self.compiler.stage)); + cmd.args(linker_args(builder, self.compiler.host, LldThreads::No)); cmd.delay_failure().run(builder); } @@ -1021,13 +1015,7 @@ impl Step for RustdocGUI { cmd.env("RUSTDOC", builder.rustdoc(self.compiler)) .env("RUSTC", builder.rustc(self.compiler)); - add_rustdoc_cargo_linker_args( - &mut cmd, - builder, - self.compiler.host, - LldThreads::No, - self.compiler.stage, - ); + add_rustdoc_cargo_linker_args(&mut cmd, builder, self.compiler.host, LldThreads::No); for path in &builder.paths { if let Some(p) = helpers::is_valid_test_suite_arg(path, "tests/rustdoc-gui", builder) { @@ -1796,7 +1784,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the } let mut hostflags = flags.clone(); - hostflags.extend(linker_flags(builder, compiler.host, LldThreads::No, compiler.stage)); + hostflags.extend(linker_flags(builder, compiler.host, LldThreads::No)); let mut targetflags = flags; diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs index a96ccdd12c2c..e4503b264562 100644 --- a/src/bootstrap/src/core/builder/cargo.rs +++ b/src/bootstrap/src/core/builder/cargo.rs @@ -260,7 +260,7 @@ impl Cargo { } } - for arg in linker_args(builder, compiler.host, LldThreads::Yes, 0) { + for arg in linker_args(builder, compiler.host, LldThreads::Yes) { self.hostflags.arg(&arg); } @@ -270,10 +270,10 @@ impl Cargo { } // We want to set -Clinker using Cargo, therefore we only call `linker_flags` and not // `linker_args` here. - for flag in linker_flags(builder, target, LldThreads::Yes, compiler.stage) { + for flag in linker_flags(builder, target, LldThreads::Yes) { self.rustflags.arg(&flag); } - for arg in linker_args(builder, target, LldThreads::Yes, compiler.stage) { + for arg in linker_args(builder, target, LldThreads::Yes) { self.rustdocflags.arg(&arg); } diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index 8aae5255d7e1..c32d9c2870cf 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -1479,7 +1479,7 @@ impl<'a> Builder<'a> { cmd.arg("-Dwarnings"); } cmd.arg("-Znormalize-docs"); - cmd.args(linker_args(self, compiler.host, LldThreads::Yes, compiler.stage)); + cmd.args(linker_args(self, compiler.host, LldThreads::Yes)); cmd } diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs index ee8fe7aa9d21..1299fbb7d629 100644 --- a/src/bootstrap/src/utils/helpers.rs +++ b/src/bootstrap/src/utils/helpers.rs @@ -445,9 +445,8 @@ pub fn linker_args( builder: &Builder<'_>, target: TargetSelection, lld_threads: LldThreads, - stage: u32, ) -> Vec { - let mut args = linker_flags(builder, target, lld_threads, stage); + let mut args = linker_flags(builder, target, lld_threads); if let Some(linker) = builder.linker(target) { args.push(format!("-Clinker={}", linker.display())); @@ -462,18 +461,12 @@ pub fn linker_flags( builder: &Builder<'_>, target: TargetSelection, lld_threads: LldThreads, - stage: u32, ) -> Vec { let mut args = vec![]; if !builder.is_lld_direct_linker(target) && builder.config.lld_mode.is_used() { match builder.config.lld_mode { LldMode::External => { - // cfg(bootstrap) - remove after updating bootstrap compiler (#137498) - if stage == 0 && target.is_windows() { - args.push("-Clink-arg=-fuse-ld=lld".to_string()); - } else { - args.push("-Zlinker-features=+lld".to_string()); - } + args.push("-Zlinker-features=+lld".to_string()); // FIXME(kobzol): remove this flag once MCP510 gets stabilized args.push("-Zunstable-options".to_string()); } @@ -501,9 +494,8 @@ pub fn add_rustdoc_cargo_linker_args( builder: &Builder<'_>, target: TargetSelection, lld_threads: LldThreads, - stage: u32, ) { - let args = linker_args(builder, target, lld_threads, stage); + let args = linker_args(builder, target, lld_threads); let mut flags = cmd .get_envs() .find_map(|(k, v)| if k == OsStr::new("RUSTDOCFLAGS") { v } else { None }) From cf685653131bf76a88457eb8a88ee91c0d9fa821 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Wed, 9 Apr 2025 13:48:39 +0200 Subject: [PATCH 263/606] Temporarily leave the review rotation --- triagebot.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/triagebot.toml b/triagebot.toml index 756536dc2e7b..64c85bbb3811 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1123,6 +1123,7 @@ cc = ["@ZuseZ4"] warn_non_default_branch.enable = true contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html" users_on_vacation = [ + "fmease", "jyn514", "saethlin", "Noratrieb", From f20efc4c61a0d5deaf86988565a0214733ff0e6b Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 9 Apr 2025 09:49:24 +0000 Subject: [PATCH 264/606] Handle `UnsafePointer` coercions in one place --- compiler/rustc_hir_typeck/src/coercion.rs | 58 +++++++++-------------- 1 file changed, 22 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index f1571cf4c831..c19e0a057401 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -247,7 +247,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { ty::FnPtr(a_sig_tys, a_hdr) => { // We permit coercion of fn pointers to drop the // unsafe qualifier. - self.coerce_from_fn_pointer(a, a_sig_tys.with(a_hdr), b) + self.coerce_from_fn_pointer(a_sig_tys.with(a_hdr), b) } ty::Closure(closure_def_id_a, args_a) => { // Non-capturing closures are coercible to @@ -813,18 +813,12 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { }) } - fn coerce_from_safe_fn( + fn coerce_from_safe_fn( &self, - a: Ty<'tcx>, fn_ty_a: ty::PolyFnSig<'tcx>, b: Ty<'tcx>, - to_unsafe: F, - normal: G, - ) -> CoerceResult<'tcx> - where - F: FnOnce(Ty<'tcx>) -> Vec>, - G: FnOnce(Ty<'tcx>) -> Vec>, - { + adjustment: Option, + ) -> CoerceResult<'tcx> { self.commit_if_ok(|snapshot| { let outer_universe = self.infcx.universe(); @@ -833,9 +827,22 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { && hdr_b.safety.is_unsafe() { let unsafe_a = self.tcx.safe_to_unsafe_fn_ty(fn_ty_a); - self.unify_and(unsafe_a, b, to_unsafe) + self.unify_and(unsafe_a, b, |target| match adjustment { + Some(kind) => vec![ + Adjustment { kind, target: Ty::new_fn_ptr(self.tcx, fn_ty_a) }, + Adjustment { + kind: Adjust::Pointer(PointerCoercion::UnsafeFnPointer), + target, + }, + ], + None => simple(Adjust::Pointer(PointerCoercion::UnsafeFnPointer))(target), + }) } else { - self.unify_and(a, b, normal) + let a = Ty::new_fn_ptr(self.tcx, fn_ty_a); + self.unify_and(a, b, |target| match adjustment { + None => vec![], + Some(kind) => vec![Adjustment { kind, target }], + }) }; // FIXME(#73154): This is a hack. Currently LUB can generate @@ -852,7 +859,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { fn coerce_from_fn_pointer( &self, - a: Ty<'tcx>, fn_ty_a: ty::PolyFnSig<'tcx>, b: Ty<'tcx>, ) -> CoerceResult<'tcx> { @@ -861,15 +867,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { //! let b = self.shallow_resolve(b); - debug!("coerce_from_fn_pointer(a={:?}, b={:?})", a, b); + debug!(?fn_ty_a, ?b, "coerce_from_fn_pointer"); - self.coerce_from_safe_fn( - a, - fn_ty_a, - b, - simple(Adjust::Pointer(PointerCoercion::UnsafeFnPointer)), - identity, - ) + self.coerce_from_safe_fn(fn_ty_a, b, None) } fn coerce_from_fn_item(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> { @@ -916,24 +916,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { self.at(&self.cause, self.param_env).normalize(a_sig); obligations.extend(o1); - let a_fn_pointer = Ty::new_fn_ptr(self.tcx, a_sig); let InferOk { value, obligations: o2 } = self.coerce_from_safe_fn( - a_fn_pointer, a_sig, b, - |unsafe_ty| { - vec![ - Adjustment { - kind: Adjust::Pointer(PointerCoercion::ReifyFnPointer), - target: a_fn_pointer, - }, - Adjustment { - kind: Adjust::Pointer(PointerCoercion::UnsafeFnPointer), - target: unsafe_ty, - }, - ] - }, - simple(Adjust::Pointer(PointerCoercion::ReifyFnPointer)), + Some(Adjust::Pointer(PointerCoercion::ReifyFnPointer)), )?; obligations.extend(o2); From 32c8f7dbcf17e8a97a3a99e112e86a604d12f0a2 Mon Sep 17 00:00:00 2001 From: xizheyin Date: Wed, 9 Apr 2025 20:51:52 +0800 Subject: [PATCH 265/606] librustdoc: remove IndexItem::new, use previous fields constructor Signed-off-by: xizheyin --- src/librustdoc/formats/cache.rs | 14 ++++---- src/librustdoc/html/render/mod.rs | 56 +++++++------------------------ 2 files changed, 19 insertions(+), 51 deletions(-) diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 2a612fa9b8cd..2648641e53e7 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -574,20 +574,20 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It ); let aliases = item.attrs.get_doc_aliases(); let deprecation = item.deprecation(tcx); - let index_item = IndexItem::new( - item.type_(), - Some(defid), + let index_item = IndexItem { + ty: item.type_(), + defid: Some(defid), name, path, desc, - parent_did, - None, - None, + parent: parent_did, + parent_idx: None, + exact_path: None, impl_id, search_type, aliases, deprecation, - ); + }; cache.search_index.push(index_item); } diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index b9a2e65b0907..ad6fa110ae88 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -113,50 +113,18 @@ enum RenderMode { /// by hand to a large JS file at the end of cache-creation. #[derive(Debug)] pub(crate) struct IndexItem { - ty: ItemType, - defid: Option, - name: Symbol, - path: String, - desc: String, - parent: Option, - parent_idx: Option, - exact_path: Option, - impl_id: Option, - search_type: Option, - aliases: Box<[Symbol]>, - deprecation: Option, -} - -impl IndexItem { - pub fn new( - ty: ItemType, - defid: Option, - name: Symbol, - path: String, - desc: String, - parent: Option, - parent_idx: Option, - exact_path: Option, - impl_id: Option, - search_type: Option, - aliases: Box<[Symbol]>, - deprecation: Option, - ) -> Self { - Self { - ty, - defid, - name, - path, - desc, - parent, - parent_idx, - exact_path, - impl_id, - search_type, - aliases, - deprecation, - } - } + pub(crate) ty: ItemType, + pub(crate) defid: Option, + pub(crate) name: Symbol, + pub(crate) path: String, + pub(crate) desc: String, + pub(crate) parent: Option, + pub(crate) parent_idx: Option, + pub(crate) exact_path: Option, + pub(crate) impl_id: Option, + pub(crate) search_type: Option, + pub(crate) aliases: Box<[Symbol]>, + pub(crate) deprecation: Option, } /// A type used for the search index. From 697768a6645468e2a67a2df3c022b32d450a7f06 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 9 Apr 2025 12:46:08 +0000 Subject: [PATCH 266/606] Simplify some `unify_and` calls --- compiler/rustc_hir_typeck/src/coercion.rs | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index c19e0a057401..9e1a4703b995 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -191,7 +191,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // we have no information about the source type. This will always // ultimately fall back to some form of subtyping. if a.is_ty_var() { - return self.coerce_from_inference_variable(a, b, identity); + return self.coerce_from_inference_variable(a, b); } // Consider coercing the subtype to a DST @@ -265,12 +265,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { /// Coercing *from* an inference variable. In this case, we have no information /// about the source type, so we can't really do a true coercion and we always /// fall back to subtyping (`unify_and`). - fn coerce_from_inference_variable( - &self, - a: Ty<'tcx>, - b: Ty<'tcx>, - make_adjustments: impl FnOnce(Ty<'tcx>) -> Vec>, - ) -> CoerceResult<'tcx> { + fn coerce_from_inference_variable(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> { debug!("coerce_from_inference_variable(a={:?}, b={:?})", a, b); assert!(a.is_ty_var() && self.shallow_resolve(a) == a); assert!(self.shallow_resolve(b) == b); @@ -298,12 +293,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { "coerce_from_inference_variable: two inference variables, target_ty={:?}, obligations={:?}", target_ty, obligations ); - let adjustments = make_adjustments(target_ty); - InferResult::Ok(InferOk { value: (adjustments, target_ty), obligations }) + success(vec![], target_ty, obligations) } else { // One unresolved type variable: just apply subtyping, we may be able // to do something useful. - self.unify_and(a, b, make_adjustments) + self.unify_and(a, b, identity) } } @@ -708,7 +702,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { && let ty::Dynamic(b_data, _, ty::DynStar) = b.kind() && a_data.principal_def_id() == b_data.principal_def_id() { - return self.unify_and(a, b, |_| vec![]); + return self.unify_and(a, b, identity); } // Check the obligations of the cast -- for example, when casting @@ -808,9 +802,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // To complete the reborrow, we need to make sure we can unify the inner types, and if so we // add the adjustments. - self.unify_and(a, b, |_inner_ty| { - vec![Adjustment { kind: Adjust::ReborrowPin(mut_b), target: b }] - }) + self.unify_and(a, b, simple(Adjust::ReborrowPin(mut_b))) } fn coerce_from_safe_fn( From 804b6c963688a78f041bab93247c3cf0c78d7f2b Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 9 Apr 2025 12:57:43 +0000 Subject: [PATCH 267/606] Rename `unify` to `unify_raw` --- compiler/rustc_hir_typeck/src/coercion.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 9e1a4703b995..44b966e610ed 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -131,7 +131,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { Coerce { fcx, cause, allow_two_phase, use_lub: false, coerce_never } } - fn unify(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> InferResult<'tcx, Ty<'tcx>> { + fn unify_raw(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> InferResult<'tcx, Ty<'tcx>> { debug!("unify(a: {:?}, b: {:?}, use_lub: {})", a, b, self.use_lub); self.commit_if_ok(|_| { let at = self.at(&self.cause, self.fcx.param_env); @@ -166,7 +166,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { where F: FnOnce(Ty<'tcx>) -> Vec>, { - self.unify(a, b) + self.unify_raw(a, b) .and_then(|InferOk { value: ty, obligations }| success(f(ty), ty, obligations)) } @@ -431,7 +431,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { referent_ty, mutbl_b, // [1] above ); - match self.unify(derefd_ty_a, b) { + match self.unify_raw(derefd_ty_a, b) { Ok(ok) => { found = Some(ok); break; @@ -1096,9 +1096,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let cause = self.cause(DUMMY_SP, ObligationCauseCode::ExprAssignable); // We don't ever need two-phase here since we throw out the result of the coercion. let coerce = Coerce::new(self, cause, AllowTwoPhase::No, true); - coerce - .autoderef(DUMMY_SP, expr_ty) - .find_map(|(ty, steps)| self.probe(|_| coerce.unify(ty, target)).ok().map(|_| steps)) + coerce.autoderef(DUMMY_SP, expr_ty).find_map(|(ty, steps)| { + self.probe(|_| coerce.unify_raw(ty, target)).ok().map(|_| steps) + }) } /// Given a type, this function will calculate and return the type given From 34258d62cd61c7cca7d1b957724717cd7df6c2ec Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 9 Apr 2025 12:58:33 +0000 Subject: [PATCH 268/606] Add a dedicated function for the common `unify_and(identity)` case --- compiler/rustc_hir_typeck/src/coercion.rs | 29 ++++++++++++----------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 44b966e610ed..80592ea53d98 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -103,11 +103,6 @@ fn coerce_mutbls<'tcx>( if from_mutbl >= to_mutbl { Ok(()) } else { Err(TypeError::Mutability) } } -/// Do not require any adjustments, i.e. coerce `x -> x`. -fn identity(_: Ty<'_>) -> Vec> { - vec![] -} - fn simple<'tcx>(kind: Adjust) -> impl FnOnce(Ty<'tcx>) -> Vec> { move |target| vec![Adjustment { kind, target }] } @@ -161,6 +156,12 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { }) } + /// Unify two types (using sub or lub). + fn unify(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> { + self.unify_raw(a, b) + .and_then(|InferOk { value: ty, obligations }| success(vec![], ty, obligations)) + } + /// Unify two types (using sub or lub) and produce a specific coercion. fn unify_and(&self, a: Ty<'tcx>, b: Ty<'tcx>, f: F) -> CoerceResult<'tcx> where @@ -183,7 +184,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { return success(simple(Adjust::NeverToAny)(b), b, PredicateObligations::new()); } else { // Otherwise the only coercion we can do is unification. - return self.unify_and(a, b, identity); + return self.unify(a, b); } } @@ -257,7 +258,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { } _ => { // Otherwise, just use unification rules. - self.unify_and(a, b, identity) + self.unify(a, b) } } } @@ -297,7 +298,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { } else { // One unresolved type variable: just apply subtyping, we may be able // to do something useful. - self.unify_and(a, b, identity) + self.unify(a, b) } } @@ -325,7 +326,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { coerce_mutbls(mt_a.mutbl, mutbl_b)?; (r_a, mt_a) } - _ => return self.unify_and(a, b, identity), + _ => return self.unify(a, b), }; let span = self.cause.span; @@ -702,7 +703,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { && let ty::Dynamic(b_data, _, ty::DynStar) = b.kind() && a_data.principal_def_id() == b_data.principal_def_id() { - return self.unify_and(a, b, identity); + return self.unify(a, b); } // Check the obligations of the cast -- for example, when casting @@ -917,7 +918,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { obligations.extend(o2); Ok(InferOk { value, obligations }) } - _ => self.unify_and(a, b, identity), + _ => self.unify(a, b), } } @@ -964,7 +965,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { simple(Adjust::Pointer(PointerCoercion::ClosureFnPointer(safety))), ) } - _ => self.unify_and(a, b, identity), + _ => self.unify(a, b), } } @@ -979,7 +980,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { let (is_ref, mt_a) = match *a.kind() { ty::Ref(_, ty, mutbl) => (true, ty::TypeAndMut { ty, mutbl }), ty::RawPtr(ty, mutbl) => (false, ty::TypeAndMut { ty, mutbl }), - _ => return self.unify_and(a, b, identity), + _ => return self.unify(a, b), }; coerce_mutbls(mt_a.mutbl, mutbl_b)?; @@ -998,7 +999,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { } else if mt_a.mutbl != mutbl_b { self.unify_and(a_raw, b, simple(Adjust::Pointer(PointerCoercion::MutToConstPointer))) } else { - self.unify_and(a_raw, b, identity) + self.unify(a_raw, b) } } } From 3528a65dd75c9f0ace6aa8dd8ce75e2ce97027b0 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 9 Apr 2025 13:03:45 +0000 Subject: [PATCH 269/606] Deduplicate `target` type setting in `unify_and` callbacks --- compiler/rustc_hir_typeck/src/coercion.rs | 90 +++++++++++++---------- 1 file changed, 50 insertions(+), 40 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 80592ea53d98..4f95d20251f2 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -103,10 +103,6 @@ fn coerce_mutbls<'tcx>( if from_mutbl >= to_mutbl { Ok(()) } else { Err(TypeError::Mutability) } } -fn simple<'tcx>(kind: Adjust) -> impl FnOnce(Ty<'tcx>) -> Vec> { - move |target| vec![Adjustment { kind, target }] -} - /// This always returns `Ok(...)`. fn success<'tcx>( adj: Vec>, @@ -163,12 +159,17 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { } /// Unify two types (using sub or lub) and produce a specific coercion. - fn unify_and(&self, a: Ty<'tcx>, b: Ty<'tcx>, f: F) -> CoerceResult<'tcx> - where - F: FnOnce(Ty<'tcx>) -> Vec>, - { - self.unify_raw(a, b) - .and_then(|InferOk { value: ty, obligations }| success(f(ty), ty, obligations)) + fn unify_and( + &self, + a: Ty<'tcx>, + b: Ty<'tcx>, + mut adjustments: Vec>, + final_adjustment: Adjust, + ) -> CoerceResult<'tcx> { + self.unify_raw(a, b).and_then(|InferOk { value: ty, obligations }| { + adjustments.push(Adjustment { target: ty, kind: final_adjustment }); + success(adjustments, ty, obligations) + }) } #[instrument(skip(self))] @@ -181,7 +182,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // Coercing from `!` to any type is allowed: if a.is_never() { if self.coerce_never { - return success(simple(Adjust::NeverToAny)(b), b, PredicateObligations::new()); + return success( + vec![Adjustment { kind: Adjust::NeverToAny, target: b }], + b, + PredicateObligations::new(), + ); } else { // Otherwise the only coercion we can do is unification. return self.unify(a, b); @@ -574,13 +579,15 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // We only have the latter, so we use an inference variable // for the former and let type inference do the rest. let coerce_target = self.next_ty_var(self.cause.span); - let mut coercion = self.unify_and(coerce_target, target, |target| { - let unsize = Adjustment { kind: Adjust::Pointer(PointerCoercion::Unsize), target }; + let mut coercion = self.unify_and( + coerce_target, + target, match reborrow { - None => vec![unsize], - Some((ref deref, ref autoref)) => vec![deref.clone(), autoref.clone(), unsize], - } - })?; + None => vec![], + Some((ref deref, ref autoref)) => vec![deref.clone(), autoref.clone()], + }, + Adjust::Pointer(PointerCoercion::Unsize), + )?; let mut selcx = traits::SelectionContext::new(self); @@ -803,7 +810,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // To complete the reborrow, we need to make sure we can unify the inner types, and if so we // add the adjustments. - self.unify_and(a, b, simple(Adjust::ReborrowPin(mut_b))) + self.unify_and(a, b, vec![], Adjust::ReborrowPin(mut_b)) } fn coerce_from_safe_fn( @@ -820,22 +827,24 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { && hdr_b.safety.is_unsafe() { let unsafe_a = self.tcx.safe_to_unsafe_fn_ty(fn_ty_a); - self.unify_and(unsafe_a, b, |target| match adjustment { - Some(kind) => vec![ - Adjustment { kind, target: Ty::new_fn_ptr(self.tcx, fn_ty_a) }, - Adjustment { - kind: Adjust::Pointer(PointerCoercion::UnsafeFnPointer), - target, - }, - ], - None => simple(Adjust::Pointer(PointerCoercion::UnsafeFnPointer))(target), - }) + let adjustments = match adjustment { + Some(kind) => { + vec![Adjustment { kind, target: Ty::new_fn_ptr(self.tcx, fn_ty_a) }] + } + None => vec![], + }; + self.unify_and( + unsafe_a, + b, + adjustments, + Adjust::Pointer(PointerCoercion::UnsafeFnPointer), + ) } else { let a = Ty::new_fn_ptr(self.tcx, fn_ty_a); - self.unify_and(a, b, |target| match adjustment { - None => vec![], - Some(kind) => vec![Adjustment { kind, target }], - }) + match adjustment { + Some(adjust) => self.unify_and(a, b, vec![], adjust), + None => self.unify(a, b), + } }; // FIXME(#73154): This is a hack. Currently LUB can generate @@ -962,7 +971,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { self.unify_and( pointer_ty, b, - simple(Adjust::Pointer(PointerCoercion::ClosureFnPointer(safety))), + vec![], + Adjust::Pointer(PointerCoercion::ClosureFnPointer(safety)), ) } _ => self.unify(a, b), @@ -990,14 +1000,14 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // representation, we still register an Adjust::DerefRef so that // regionck knows that the region for `a` must be valid here. if is_ref { - self.unify_and(a_raw, b, |target| { - vec![ - Adjustment { kind: Adjust::Deref(None), target: mt_a.ty }, - Adjustment { kind: Adjust::Borrow(AutoBorrow::RawPtr(mutbl_b)), target }, - ] - }) + self.unify_and( + a_raw, + b, + vec![Adjustment { kind: Adjust::Deref(None), target: mt_a.ty }], + Adjust::Borrow(AutoBorrow::RawPtr(mutbl_b)), + ) } else if mt_a.mutbl != mutbl_b { - self.unify_and(a_raw, b, simple(Adjust::Pointer(PointerCoercion::MutToConstPointer))) + self.unify_and(a_raw, b, vec![], Adjust::Pointer(PointerCoercion::MutToConstPointer)) } else { self.unify(a_raw, b) } From 67ff33666f3f59578c2ca7e337fd55129439edb2 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Wed, 9 Apr 2025 12:03:28 -0400 Subject: [PATCH 270/606] saethlin is back from vacation --- triagebot.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index 756536dc2e7b..8573e62a567e 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1124,7 +1124,6 @@ warn_non_default_branch.enable = true contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html" users_on_vacation = [ "jyn514", - "saethlin", "Noratrieb", ] From 50d0ce1b42d67ce98b2ccac55d22a2ff8abe3273 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Fri, 21 Feb 2025 21:00:43 -0800 Subject: [PATCH 271/606] Ensure `swap_nonoverlapping` is really always untyped --- library/core/src/ptr/mod.rs | 136 +++++++++++------- library/coretests/tests/ptr.rs | 36 +++++ tests/assembly/x86_64-typed-swap.rs | 28 ++++ tests/codegen/simd/swap-simd-types.rs | 8 +- tests/codegen/swap-large-types.rs | 76 ++++++---- tests/codegen/swap-small-types.rs | 76 ++++++++-- .../consts/missing_span_in_backtrace.stderr | 6 +- 7 files changed, 271 insertions(+), 95 deletions(-) diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index ea53da78d3bd..2357ba23aa0d 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -398,6 +398,7 @@ use crate::cmp::Ordering; use crate::intrinsics::const_eval_select; use crate::marker::FnPtr; use crate::mem::{self, MaybeUninit, SizedTypeProperties}; +use crate::num::NonZero; use crate::{fmt, hash, intrinsics, ub_checks}; mod alignment; @@ -1094,51 +1095,25 @@ pub const unsafe fn swap_nonoverlapping(x: *mut T, y: *mut T, count: usize) { // are pointers inside `T` we will copy them in one go rather than trying to copy a part // of a pointer (which would not work). // SAFETY: Same preconditions as this function - unsafe { swap_nonoverlapping_simple_untyped(x, y, count) } + unsafe { swap_nonoverlapping_const(x, y, count) } } else { - macro_rules! attempt_swap_as_chunks { - ($ChunkTy:ty) => { - if align_of::() >= align_of::<$ChunkTy>() - && size_of::() % size_of::<$ChunkTy>() == 0 - { - let x: *mut $ChunkTy = x.cast(); - let y: *mut $ChunkTy = y.cast(); - let count = count * (size_of::() / size_of::<$ChunkTy>()); - // SAFETY: these are the same bytes that the caller promised were - // ok, just typed as `MaybeUninit`s instead of as `T`s. - // The `if` condition above ensures that we're not violating - // alignment requirements, and that the division is exact so - // that we don't lose any bytes off the end. - return unsafe { swap_nonoverlapping_simple_untyped(x, y, count) }; - } - }; + // Going though a slice here helps codegen know the size fits in `isize` + let slice = slice_from_raw_parts_mut(x, count); + // SAFETY: This is all readable from the pointer, meaning it's one + // allocated object, and thus cannot be more than isize::MAX bytes. + let bytes = unsafe { mem::size_of_val_raw::<[T]>(slice) }; + if let Some(bytes) = NonZero::new(bytes) { + // SAFETY: These are the same ranges, just expressed in a different + // type, so they're still non-overlapping. + unsafe { swap_nonoverlapping_bytes(x.cast(), y.cast(), bytes) }; } - - // Split up the slice into small power-of-two-sized chunks that LLVM is able - // to vectorize (unless it's a special type with more-than-pointer alignment, - // because we don't want to pessimize things like slices of SIMD vectors.) - if align_of::() <= size_of::() - && (!size_of::().is_power_of_two() - || size_of::() > size_of::() * 2) - { - attempt_swap_as_chunks!(usize); - attempt_swap_as_chunks!(u8); - } - - // SAFETY: Same preconditions as this function - unsafe { swap_nonoverlapping_simple_untyped(x, y, count) } } ) } /// Same behavior and safety conditions as [`swap_nonoverlapping`] -/// -/// LLVM can vectorize this (at least it can for the power-of-two-sized types -/// `swap_nonoverlapping` tries to use) so no need to manually SIMD it. #[inline] -const unsafe fn swap_nonoverlapping_simple_untyped(x: *mut T, y: *mut T, count: usize) { - let x = x.cast::>(); - let y = y.cast::>(); +const unsafe fn swap_nonoverlapping_const(x: *mut T, y: *mut T, count: usize) { let mut i = 0; while i < count { // SAFETY: By precondition, `i` is in-bounds because it's below `n` @@ -1147,26 +1122,91 @@ const unsafe fn swap_nonoverlapping_simple_untyped(x: *mut T, y: *mut T, coun // and it's distinct from `x` since the ranges are non-overlapping let y = unsafe { y.add(i) }; - // If we end up here, it's because we're using a simple type -- like - // a small power-of-two-sized thing -- or a special type with particularly - // large alignment, particularly SIMD types. - // Thus, we're fine just reading-and-writing it, as either it's small - // and that works well anyway or it's special and the type's author - // presumably wanted things to be done in the larger chunk. - // SAFETY: we're only ever given pointers that are valid to read/write, // including being aligned, and nothing here panics so it's drop-safe. unsafe { - let a: MaybeUninit = read(x); - let b: MaybeUninit = read(y); - write(x, b); - write(y, a); + // Note that it's critical that these use `copy_nonoverlapping`, + // rather than `read`/`write`, to avoid #134713 if T has padding. + let mut temp = MaybeUninit::::uninit(); + copy_nonoverlapping(x, temp.as_mut_ptr(), 1); + copy_nonoverlapping(y, x, 1); + copy_nonoverlapping(temp.as_ptr(), y, 1); } i += 1; } } +// Don't let MIR inline this, because we really want it to keep its noalias metadata +#[rustc_no_mir_inline] +#[inline] +fn swap_chunk(x: &mut MaybeUninit<[u8; N]>, y: &mut MaybeUninit<[u8; N]>) { + let a = *x; + let b = *y; + *x = b; + *y = a; +} + +#[inline] +unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, bytes: NonZero) { + // Same as `swap_nonoverlapping::<[u8; N]>`. + unsafe fn swap_nonoverlapping_chunks( + x: *mut MaybeUninit<[u8; N]>, + y: *mut MaybeUninit<[u8; N]>, + chunks: NonZero, + ) { + let chunks = chunks.get(); + for i in 0..chunks { + // SAFETY: i is in [0, chunks) so the adds and dereferences are in-bounds. + unsafe { swap_chunk(&mut *x.add(i), &mut *y.add(i)) }; + } + } + + // Same as `swap_nonoverlapping_bytes`, but accepts at most 1+2+4=7 bytes + #[inline] + unsafe fn swap_nonoverlapping_short(x: *mut u8, y: *mut u8, bytes: NonZero) { + // Tail handling for auto-vectorized code sometimes has element-at-a-time behaviour, + // see . + // By swapping as different sizes, rather than as a loop over bytes, + // we make sure not to end up with, say, seven byte-at-a-time copies. + + let bytes = bytes.get(); + let mut i = 0; + macro_rules! swap_prefix { + ($($n:literal)+) => {$( + if (bytes & $n) != 0 { + // SAFETY: `i` can only have the same bits set as those in bytes, + // so these `add`s are in-bounds of `bytes`. But the bit for + // `$n` hasn't been set yet, so the `$n` bytes that `swap_chunk` + // will read and write are within the usable range. + unsafe { swap_chunk::<$n>(&mut*x.add(i).cast(), &mut*y.add(i).cast()) }; + i |= $n; + } + )+}; + } + swap_prefix!(4 2 1); + debug_assert_eq!(i, bytes); + } + + const CHUNK_SIZE: usize = size_of::<*const ()>(); + let bytes = bytes.get(); + + let chunks = bytes / CHUNK_SIZE; + let tail = bytes % CHUNK_SIZE; + if let Some(chunks) = NonZero::new(chunks) { + // SAFETY: this is bytes/CHUNK_SIZE*CHUNK_SIZE bytes, which is <= bytes, + // so it's within the range of our non-overlapping bytes. + unsafe { swap_nonoverlapping_chunks::(x.cast(), y.cast(), chunks) }; + } + if let Some(tail) = NonZero::new(tail) { + const { assert!(CHUNK_SIZE <= 8) }; + let delta = chunks * CHUNK_SIZE; + // SAFETY: the tail length is below CHUNK SIZE because of the remainder, + // and CHUNK_SIZE is at most 8 by the const assert, so tail <= 7 + unsafe { swap_nonoverlapping_short(x.add(delta), y.add(delta), tail) }; + } +} + /// Moves `src` into the pointed `dst`, returning the previous `dst` value. /// /// Neither value is dropped. diff --git a/library/coretests/tests/ptr.rs b/library/coretests/tests/ptr.rs index 6091926084a3..cc5f7946863a 100644 --- a/library/coretests/tests/ptr.rs +++ b/library/coretests/tests/ptr.rs @@ -984,3 +984,39 @@ fn test_ptr_metadata_in_const() { assert_eq!(SLICE_META, 3); assert_eq!(DYN_META.size_of(), 42); } + +// See +const fn ptr_swap_nonoverlapping_is_untyped_inner() { + #[repr(C)] + struct HasPadding(usize, u8); + + let buf1: [usize; 2] = [1000, 2000]; + let buf2: [usize; 2] = [3000, 4000]; + + // HasPadding and [usize; 2] have the same size and alignment, + // so swap_nonoverlapping should treat them the same + assert!(size_of::() == size_of::<[usize; 2]>()); + assert!(align_of::() == align_of::<[usize; 2]>()); + + let mut b1 = buf1; + let mut b2 = buf2; + // Safety: b1 and b2 are distinct local variables, + // with the same size and alignment as HasPadding. + unsafe { + std::ptr::swap_nonoverlapping( + b1.as_mut_ptr().cast::(), + b2.as_mut_ptr().cast::(), + 1, + ); + } + assert!(b1[0] == buf2[0]); + assert!(b1[1] == buf2[1]); + assert!(b2[0] == buf1[0]); + assert!(b2[1] == buf1[1]); +} + +#[test] +fn test_ptr_swap_nonoverlapping_is_untyped() { + ptr_swap_nonoverlapping_is_untyped_inner(); + const { ptr_swap_nonoverlapping_is_untyped_inner() }; +} diff --git a/tests/assembly/x86_64-typed-swap.rs b/tests/assembly/x86_64-typed-swap.rs index dfd6ee565bcc..a6753011d362 100644 --- a/tests/assembly/x86_64-typed-swap.rs +++ b/tests/assembly/x86_64-typed-swap.rs @@ -51,3 +51,31 @@ pub fn swap_simd(x: &mut __m128, y: &mut __m128) { // CHECK-NEXT: retq swap(x, y) } + +// CHECK-LABEL: swap_string: +#[no_mangle] +pub fn swap_string(x: &mut String, y: &mut String) { + // CHECK-NOT: mov + // CHECK-COUNT-4: movups + // CHECK-NOT: mov + // CHECK-COUNT-4: movq + // CHECK-NOT: mov + swap(x, y) +} + +// CHECK-LABEL: swap_44_bytes: +#[no_mangle] +pub fn swap_44_bytes(x: &mut [u8; 44], y: &mut [u8; 44]) { + // Ensure we do better than a long run of byte copies, + // see + + // CHECK-NOT: movb + // CHECK-COUNT-8: movups{{.+}}xmm + // CHECK-NOT: movb + // CHECK-COUNT-4: movq + // CHECK-NOT: movb + // CHECK-COUNT-4: movl + // CHECK-NOT: movb + // CHECK: retq + swap(x, y) +} diff --git a/tests/codegen/simd/swap-simd-types.rs b/tests/codegen/simd/swap-simd-types.rs index 69767d0a7558..c063cc683a61 100644 --- a/tests/codegen/simd/swap-simd-types.rs +++ b/tests/codegen/simd/swap-simd-types.rs @@ -23,8 +23,8 @@ pub fn swap_single_m256(x: &mut __m256, y: &mut __m256) { #[no_mangle] pub fn swap_m256_slice(x: &mut [__m256], y: &mut [__m256]) { // CHECK-NOT: alloca - // CHECK: load <8 x float>{{.+}}align 32 - // CHECK: store <8 x float>{{.+}}align 32 + // CHECK-COUNT-2: load <4 x i64>{{.+}}align 32 + // CHECK-COUNT-2: store <4 x i64>{{.+}}align 32 if x.len() == y.len() { x.swap_with_slice(y); } @@ -34,7 +34,7 @@ pub fn swap_m256_slice(x: &mut [__m256], y: &mut [__m256]) { #[no_mangle] pub fn swap_bytes32(x: &mut [u8; 32], y: &mut [u8; 32]) { // CHECK-NOT: alloca - // CHECK: load <32 x i8>{{.+}}align 1 - // CHECK: store <32 x i8>{{.+}}align 1 + // CHECK-COUNT-2: load <4 x i64>{{.+}}align 1 + // CHECK-COUNT-2: store <4 x i64>{{.+}}align 1 swap(x, y) } diff --git a/tests/codegen/swap-large-types.rs b/tests/codegen/swap-large-types.rs index 49a41bb14692..08c486affd94 100644 --- a/tests/codegen/swap-large-types.rs +++ b/tests/codegen/swap-large-types.rs @@ -12,6 +12,16 @@ type KeccakBuffer = [[u64; 5]; 5]; // to stack for large types, which is completely unnecessary as the lack of // overlap means we can just do whatever fits in registers at a time. +// The tests here (after the first one showing that the problem still exists) +// are less about testing *exactly* what the codegen is, and more about testing +// 1) That things are swapped directly from one argument to the other, +// never going through stack along the way, and +// 2) That we're doing the swapping for big things using large vector types, +// rather then `i64` or `<8 x i8>` (or, even worse, `i8`) at a time. +// +// (There are separate tests for intrinsics::typed_swap_nonoverlapping that +// check that it, as an intrinsic, are emitting exactly what it should.) + // CHECK-LABEL: @swap_basic #[no_mangle] pub fn swap_basic(x: &mut KeccakBuffer, y: &mut KeccakBuffer) { @@ -26,55 +36,55 @@ pub fn swap_basic(x: &mut KeccakBuffer, y: &mut KeccakBuffer) { } } -// This test verifies that the library does something smarter, and thus -// doesn't need any scratch space on the stack. - // CHECK-LABEL: @swap_std #[no_mangle] pub fn swap_std(x: &mut KeccakBuffer, y: &mut KeccakBuffer) { // CHECK-NOT: alloca - // CHECK: load <{{[0-9]+}} x i64> - // CHECK: store <{{[0-9]+}} x i64> + // CHECK: load <{{2|4}} x i64> + // CHECK: store <{{2|4}} x i64> swap(x, y) } -// Verify that types with usize alignment are swapped via vectored usizes, -// not falling back to byte-level code. - // CHECK-LABEL: @swap_slice #[no_mangle] pub fn swap_slice(x: &mut [KeccakBuffer], y: &mut [KeccakBuffer]) { // CHECK-NOT: alloca - // CHECK: load <{{[0-9]+}} x i64> - // CHECK: store <{{[0-9]+}} x i64> + // CHECK: load <{{2|4}} x i64> + // CHECK: store <{{2|4}} x i64> if x.len() == y.len() { x.swap_with_slice(y); } } -// But for a large align-1 type, vectorized byte copying is what we want. - type OneKilobyteBuffer = [u8; 1024]; // CHECK-LABEL: @swap_1kb_slices #[no_mangle] pub fn swap_1kb_slices(x: &mut [OneKilobyteBuffer], y: &mut [OneKilobyteBuffer]) { // CHECK-NOT: alloca - // CHECK: load <{{[0-9]+}} x i8> - // CHECK: store <{{[0-9]+}} x i8> + + // CHECK-NOT: load i32 + // CHECK-NOT: store i32 + // CHECK-NOT: load i16 + // CHECK-NOT: store i16 + // CHECK-NOT: load i8 + // CHECK-NOT: store i8 + + // CHECK: load <{{2|4}} x i64>{{.+}}align 1, + // CHECK: store <{{2|4}} x i64>{{.+}}align 1, + + // CHECK-NOT: load i32 + // CHECK-NOT: store i32 + // CHECK-NOT: load i16 + // CHECK-NOT: store i16 + // CHECK-NOT: load i8 + // CHECK-NOT: store i8 + if x.len() == y.len() { x.swap_with_slice(y); } } -// This verifies that the 2×read + 2×write optimizes to just 3 memcpys -// for an unusual type like this. It's not clear whether we should do anything -// smarter in Rust for these, so for now it's fine to leave these up to the backend. -// That's not as bad as it might seem, as for example, LLVM will lower the -// memcpys below to VMOVAPS on YMMs if one enables the AVX target feature. -// Eventually we'll be able to pass `align_of::` to a const generic and -// thus pick a smarter chunk size ourselves without huge code duplication. - #[repr(align(64))] pub struct BigButHighlyAligned([u8; 64 * 3]); @@ -82,9 +92,25 @@ pub struct BigButHighlyAligned([u8; 64 * 3]); #[no_mangle] pub fn swap_big_aligned(x: &mut BigButHighlyAligned, y: &mut BigButHighlyAligned) { // CHECK-NOT: call void @llvm.memcpy - // CHECK: call void @llvm.memcpy.{{.+}}(ptr noundef nonnull align 64 dereferenceable(192) - // CHECK: call void @llvm.memcpy.{{.+}}(ptr noundef nonnull align 64 dereferenceable(192) - // CHECK: call void @llvm.memcpy.{{.+}}(ptr noundef nonnull align 64 dereferenceable(192) + // CHECK-NOT: load i32 + // CHECK-NOT: store i32 + // CHECK-NOT: load i16 + // CHECK-NOT: store i16 + // CHECK-NOT: load i8 + // CHECK-NOT: store i8 + + // CHECK-COUNT-2: load <{{2|4}} x i64>{{.+}}align 64, + // CHECK-COUNT-2: store <{{2|4}} x i64>{{.+}}align 64, + + // CHECK-COUNT-2: load <{{2|4}} x i64>{{.+}}align 32, + // CHECK-COUNT-2: store <{{2|4}} x i64>{{.+}}align 32, + + // CHECK-NOT: load i32 + // CHECK-NOT: store i32 + // CHECK-NOT: load i16 + // CHECK-NOT: store i16 + // CHECK-NOT: load i8 + // CHECK-NOT: store i8 // CHECK-NOT: call void @llvm.memcpy swap(x, y) } diff --git a/tests/codegen/swap-small-types.rs b/tests/codegen/swap-small-types.rs index 76bb853e6423..ffa573c9a43a 100644 --- a/tests/codegen/swap-small-types.rs +++ b/tests/codegen/swap-small-types.rs @@ -1,5 +1,6 @@ //@ compile-flags: -Copt-level=3 -Z merge-functions=disabled //@ only-x86_64 +//@ min-llvm-version: 20 #![crate_type = "lib"] @@ -27,13 +28,19 @@ pub fn swap_rgb48_manually(x: &mut RGB48, y: &mut RGB48) { pub fn swap_rgb48(x: &mut RGB48, y: &mut RGB48) { // CHECK-NOT: alloca - // Whether `i8` is the best for this is unclear, but - // might as well record what's actually happening right now. + // Swapping `i48` might be cleaner in LLVM-IR here, but `i32`+`i16` isn't bad, + // and is closer to the assembly it generates anyway. - // CHECK: load i8 - // CHECK: load i8 - // CHECK: store i8 - // CHECK: store i8 + // CHECK-NOT: load{{ }} + // CHECK: load i32{{.+}}align 2 + // CHECK-NEXT: load i32{{.+}}align 2 + // CHECK-NEXT: store i32{{.+}}align 2 + // CHECK-NEXT: store i32{{.+}}align 2 + // CHECK: load i16{{.+}}align 2 + // CHECK-NEXT: load i16{{.+}}align 2 + // CHECK-NEXT: store i16{{.+}}align 2 + // CHECK-NEXT: store i16{{.+}}align 2 + // CHECK-NOT: store{{ }} swap(x, y) } @@ -76,30 +83,49 @@ pub fn swap_slices<'a>(x: &mut &'a [u32], y: &mut &'a [u32]) { swap(x, y) } -// LLVM doesn't vectorize a loop over 3-byte elements, -// so we chunk it down to bytes and loop over those instead. type RGB24 = [u8; 3]; // CHECK-LABEL: @swap_rgb24_slices #[no_mangle] pub fn swap_rgb24_slices(x: &mut [RGB24], y: &mut [RGB24]) { // CHECK-NOT: alloca - // CHECK: load <{{[0-9]+}} x i8> - // CHECK: store <{{[0-9]+}} x i8> + + // CHECK: mul nuw nsw i64 %{{x|y}}.1, 3 + + // CHECK: load <{{[0-9]+}} x i64> + // CHECK: store <{{[0-9]+}} x i64> + + // CHECK-COUNT-2: load i32 + // CHECK-COUNT-2: store i32 + // CHECK-COUNT-2: load i16 + // CHECK-COUNT-2: store i16 + // CHECK-COUNT-2: load i8 + // CHECK-COUNT-2: store i8 if x.len() == y.len() { x.swap_with_slice(y); } } -// This one has a power-of-two size, so we iterate over it directly type RGBA32 = [u8; 4]; // CHECK-LABEL: @swap_rgba32_slices #[no_mangle] pub fn swap_rgba32_slices(x: &mut [RGBA32], y: &mut [RGBA32]) { // CHECK-NOT: alloca - // CHECK: load <{{[0-9]+}} x i32> - // CHECK: store <{{[0-9]+}} x i32> + + // Because the size in bytes in a multiple of 4, we can skip the smallest sizes. + + // CHECK: load <{{[0-9]+}} x i64> + // CHECK: store <{{[0-9]+}} x i64> + + // CHECK-COUNT-2: load i32 + // CHECK-COUNT-2: store i32 + + // CHECK-NOT: load i16 + // CHECK-NOT: store i16 + // CHECK-NOT: load i8 + // CHECK-NOT: store i8 + if x.len() == y.len() { x.swap_with_slice(y); } @@ -113,8 +139,8 @@ const _: () = assert!(!std::mem::size_of::().is_power_of_two()); #[no_mangle] pub fn swap_string_slices(x: &mut [String], y: &mut [String]) { // CHECK-NOT: alloca - // CHECK: load <{{[0-9]+}} x i64> - // CHECK: store <{{[0-9]+}} x i64> + // CHECK: load <{{[0-9]+}} x i64>{{.+}}, align 8, + // CHECK: store <{{[0-9]+}} x i64>{{.+}}, align 8, if x.len() == y.len() { x.swap_with_slice(y); } @@ -130,6 +156,26 @@ pub struct Packed { #[no_mangle] pub fn swap_packed_structs(x: &mut Packed, y: &mut Packed) { // CHECK-NOT: alloca + + // CHECK-NOT: load + // CHECK-NOT: store + + // CHECK: %[[A:.+]] = load i64, ptr %x, align 1, + // CHECK-NEXT: %[[B:.+]] = load i64, ptr %y, align 1, + // CHECK-NEXT: store i64 %[[B]], ptr %x, align 1, + // CHECK-NEXT: store i64 %[[A]], ptr %y, align 1, + + // CHECK-NOT: load + // CHECK-NOT: store + + // CHECK: %[[C:.+]] = load i8, ptr %[[X8:.+]], align 1, + // CHECK-NEXT: %[[D:.+]] = load i8, ptr %[[Y8:.+]], align 1, + // CHECK-NEXT: store i8 %[[D]], ptr %[[X8]], align 1, + // CHECK-NEXT: store i8 %[[C]], ptr %[[Y8]], align 1, + + // CHECK-NOT: load + // CHECK-NOT: store + // CHECK: ret void swap(x, y) } diff --git a/tests/ui/consts/missing_span_in_backtrace.stderr b/tests/ui/consts/missing_span_in_backtrace.stderr index 2f3a65302bd5..aad3d76dd269 100644 --- a/tests/ui/consts/missing_span_in_backtrace.stderr +++ b/tests/ui/consts/missing_span_in_backtrace.stderr @@ -12,10 +12,10 @@ note: inside `swap_nonoverlapping::>` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL note: inside `swap_nonoverlapping::compiletime::>` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL -note: inside `std::ptr::swap_nonoverlapping_simple_untyped::>` - --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL -note: inside `std::ptr::read::>>` +note: inside `std::ptr::swap_nonoverlapping_const::>` --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL +note: inside `copy_nonoverlapping::>` + --> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL = help: this code performed an operation that depends on the underlying bytes representing a pointer = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported = note: this error originates in the macro `$crate::intrinsics::const_eval_select` which comes from the expansion of the macro `const_eval_select` (in Nightly builds, run with -Z macro-backtrace for more info) From b06a88ff61acb08dd4f7502908485a3eaa74d0a6 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 22 Feb 2025 13:12:38 -0800 Subject: [PATCH 272/606] Add a Miri test for 134713 --- ...ssue-134713-swap_nonoverlapping_untyped.rs | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 src/tools/miri/tests/pass/issues/issue-134713-swap_nonoverlapping_untyped.rs diff --git a/src/tools/miri/tests/pass/issues/issue-134713-swap_nonoverlapping_untyped.rs b/src/tools/miri/tests/pass/issues/issue-134713-swap_nonoverlapping_untyped.rs new file mode 100644 index 000000000000..a1da60ce65c4 --- /dev/null +++ b/src/tools/miri/tests/pass/issues/issue-134713-swap_nonoverlapping_untyped.rs @@ -0,0 +1,30 @@ +use std::mem::{size_of, align_of}; + +// See + +#[repr(C)] +struct Foo(usize, u8); + +fn main() { + let buf1: [usize; 2] = [1000, 2000]; + let buf2: [usize; 2] = [3000, 4000]; + + // Foo and [usize; 2] have the same size and alignment, + // so swap_nonoverlapping should treat them the same + assert_eq!(size_of::(), size_of::<[usize; 2]>()); + assert_eq!(align_of::(), align_of::<[usize; 2]>()); + + let mut b1 = buf1; + let mut b2 = buf2; + // Safety: b1 and b2 are distinct local variables, + // with the same size and alignment as Foo. + unsafe { + std::ptr::swap_nonoverlapping( + b1.as_mut_ptr().cast::(), + b2.as_mut_ptr().cast::(), + 1, + ); + } + assert_eq!(b1, buf2); + assert_eq!(b2, buf1); +} From 8b227a42fa2833581cd70cdc186ccc34e251a74e Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Wed, 9 Apr 2025 12:51:31 -0400 Subject: [PATCH 273/606] rustdoc: Enable Markdown extensions when looking for doctests We should enable these to avoid misinterpreting uses of the extended syntax as code blocks. This happens in practice with multi-paragraph footnotes, as discovered in #139064. --- src/librustdoc/html/markdown.rs | 2 +- tests/rustdoc-ui/multi-par-footnote.rs | 18 ++++++++++++++++++ tests/rustdoc-ui/multi-par-footnote.stdout | 5 +++++ 3 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 tests/rustdoc-ui/multi-par-footnote.rs create mode 100644 tests/rustdoc-ui/multi-par-footnote.stdout diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 334a7a86989a..44134bda5ea3 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -721,7 +721,7 @@ pub(crate) fn find_codes( extra_info: Option<&ExtraInfo<'_>>, include_non_rust: bool, ) { - let mut parser = Parser::new(doc).into_offset_iter(); + let mut parser = Parser::new_ext(doc, main_body_opts()).into_offset_iter(); let mut prev_offset = 0; let mut nb_lines = 0; let mut register_header = None; diff --git a/tests/rustdoc-ui/multi-par-footnote.rs b/tests/rustdoc-ui/multi-par-footnote.rs new file mode 100644 index 000000000000..bb6a85db0dba --- /dev/null +++ b/tests/rustdoc-ui/multi-par-footnote.rs @@ -0,0 +1,18 @@ +//@ check-pass +//@ compile-flags:--test +//@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" +// Regression test for #139064. + +/// Example +/// +/// Footnote with multiple paragraphs[^multiple] +/// +/// [^multiple]: +/// One +/// +/// Two +/// +/// Three +pub fn add(left: u64, right: u64) -> u64 { + left + right +} diff --git a/tests/rustdoc-ui/multi-par-footnote.stdout b/tests/rustdoc-ui/multi-par-footnote.stdout new file mode 100644 index 000000000000..7326c0a25a06 --- /dev/null +++ b/tests/rustdoc-ui/multi-par-footnote.stdout @@ -0,0 +1,5 @@ + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + From 63dcac8423750369ee251e2bad0945ad765eaf5c Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Wed, 9 Apr 2025 10:44:49 -0700 Subject: [PATCH 274/606] skip `tests/codegen/swap-small-types` when debug assertions are on In `swap_nonoverlapping_short` there's a new `debug_assert!`, and if that's enabled then the `alloca`s don't optimize out. --- tests/codegen/swap-small-types.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/codegen/swap-small-types.rs b/tests/codegen/swap-small-types.rs index ffa573c9a43a..7aa613ae9c22 100644 --- a/tests/codegen/swap-small-types.rs +++ b/tests/codegen/swap-small-types.rs @@ -1,6 +1,7 @@ //@ compile-flags: -Copt-level=3 -Z merge-functions=disabled //@ only-x86_64 //@ min-llvm-version: 20 +//@ ignore-std-debug-assertions (`ptr::swap_nonoverlapping` has one which blocks some optimizations) #![crate_type = "lib"] From f6faaee372c1f7fcf2b9ab49310ed07a94620722 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 8 Apr 2025 05:18:17 +0000 Subject: [PATCH 275/606] Report higher-ranked trait error when higher-ranked projection goal fails in new solver --- .../src/solve/fulfill/derive_errors.rs | 36 +++++++++- ...om-env-universe-err-project.current.stderr | 4 +- ...-from-env-universe-err-project.next.stderr | 26 ++----- ...candidate-from-env-universe-err-project.rs | 5 +- ...stderr => closure-mismatch.current.stderr} | 8 +-- .../closure-mismatch.next.stderr | 67 +++++++++++++++++++ tests/ui/mismatched_types/closure-mismatch.rs | 14 ++-- 7 files changed, 122 insertions(+), 38 deletions(-) rename tests/ui/mismatched_types/{closure-mismatch.stderr => closure-mismatch.current.stderr} (90%) create mode 100644 tests/ui/mismatched_types/closure-mismatch.next.stderr diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs index 3a939df25e07..9cbe4147fb4a 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs @@ -291,6 +291,34 @@ impl<'tcx> BestObligation<'tcx> { } } + /// When a higher-ranked projection goal fails, check that the corresponding + /// higher-ranked trait goal holds or not. This is because the process of + /// instantiating and then re-canonicalizing the binder of the projection goal + /// forces us to be unable to see that the leak check failed in the nested + /// `NormalizesTo` goal, so we don't fall back to the rigid projection check + /// that should catch when a projection goal fails due to an unsatisfied trait + /// goal. + fn detect_error_in_higher_ranked_projection( + &mut self, + goal: &inspect::InspectGoal<'_, 'tcx>, + ) -> ControlFlow> { + let tcx = goal.infcx().tcx; + if let Some(projection_clause) = goal.goal().predicate.as_projection_clause() + && !projection_clause.bound_vars().is_empty() + { + let pred = projection_clause.map_bound(|proj| proj.projection_term.trait_ref(tcx)); + self.with_derived_obligation(self.obligation.with(tcx, pred), |this| { + goal.infcx().visit_proof_tree_at_depth( + goal.goal().with(tcx, pred), + goal.depth() + 1, + this, + ) + }) + } else { + ControlFlow::Continue(()) + } + } + /// It is likely that `NormalizesTo` failed without any applicable candidates /// because the alias is not well-formed. /// @@ -374,7 +402,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { source: CandidateSource::Impl(impl_def_id), result: _, } = candidate.kind() - && goal.infcx().tcx.do_not_recommend_impl(impl_def_id) + && tcx.do_not_recommend_impl(impl_def_id) { trace!("#[do_not_recommend] -> exit"); return ControlFlow::Break(self.obligation.clone()); @@ -486,7 +514,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { if let Some(obligation) = goal .infcx() .visit_proof_tree_at_depth( - goal.goal().with(goal.infcx().tcx, ty::ClauseKind::WellFormed(lhs.into())), + goal.goal().with(tcx, ty::ClauseKind::WellFormed(lhs.into())), goal.depth() + 1, self, ) @@ -496,7 +524,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { } else if let Some(obligation) = goal .infcx() .visit_proof_tree_at_depth( - goal.goal().with(goal.infcx().tcx, ty::ClauseKind::WellFormed(rhs.into())), + goal.goal().with(tcx, ty::ClauseKind::WellFormed(rhs.into())), goal.depth() + 1, self, ) @@ -506,6 +534,8 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { } } + self.detect_error_in_higher_ranked_projection(goal)?; + ControlFlow::Break(self.obligation.clone()) } } diff --git a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.current.stderr b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.current.stderr index 7b9fd6bb4c57..c8394575e71d 100644 --- a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.current.stderr +++ b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.current.stderr @@ -13,7 +13,7 @@ LL | fn projection_bound Trait<'a, Assoc = usize>>() {} | ^^^^^^^^^^^^^ error[E0308]: mismatched types - --> $DIR/candidate-from-env-universe-err-project.rs:53:30 + --> $DIR/candidate-from-env-universe-err-project.rs:52:30 | LL | let _higher_ranked_norm: for<'a> fn(>::Assoc) = |_| (); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other @@ -22,7 +22,7 @@ LL | let _higher_ranked_norm: for<'a> fn(>::Assoc) = |_| (); found associated type `>::Assoc` error[E0308]: mismatched types - --> $DIR/candidate-from-env-universe-err-project.rs:53:30 + --> $DIR/candidate-from-env-universe-err-project.rs:52:30 | LL | let _higher_ranked_norm: for<'a> fn(>::Assoc) = |_| (); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other diff --git a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.next.stderr b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.next.stderr index 6e0ec5620da0..468dc3b082e5 100644 --- a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.next.stderr +++ b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.next.stderr @@ -22,38 +22,20 @@ note: required by a bound in `projection_bound` LL | fn projection_bound Trait<'a, Assoc = usize>>() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `projection_bound` -error[E0271]: type mismatch resolving `>::Assoc == usize` - --> $DIR/candidate-from-env-universe-err-project.rs:38:24 - | -LL | projection_bound::(); - | ^ type mismatch resolving `>::Assoc == usize` - | -note: types differ - --> $DIR/candidate-from-env-universe-err-project.rs:14:18 - | -LL | type Assoc = usize; - | ^^^^^ -note: required by a bound in `projection_bound` - --> $DIR/candidate-from-env-universe-err-project.rs:18:42 - | -LL | fn projection_bound Trait<'a, Assoc = usize>>() {} - | ^^^^^^^^^^^^^ required by this bound in `projection_bound` - error: higher-ranked subtype error - --> $DIR/candidate-from-env-universe-err-project.rs:53:30 + --> $DIR/candidate-from-env-universe-err-project.rs:52:30 | LL | let _higher_ranked_norm: for<'a> fn(>::Assoc) = |_| (); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: higher-ranked subtype error - --> $DIR/candidate-from-env-universe-err-project.rs:53:30 + --> $DIR/candidate-from-env-universe-err-project.rs:52:30 | LL | let _higher_ranked_norm: for<'a> fn(>::Assoc) = |_| (); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0271, E0277. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.rs b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.rs index a77d87f6fa78..d70e39223821 100644 --- a/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.rs +++ b/tests/ui/higher-ranked/leak-check/candidate-from-env-universe-err-project.rs @@ -36,9 +36,8 @@ fn function2>() { // does not use the leak check when trying the where-bound, causing us // to prefer it over the impl, resulting in a placeholder error. projection_bound::(); - //[next]~^ ERROR type mismatch resolving `>::Assoc == usize` - //[next]~| ERROR the trait bound `for<'a> T: Trait<'a>` is not satisfied - //[current]~^^^ ERROR mismatched types + //[next]~^ ERROR the trait bound `for<'a> T: Trait<'a>` is not satisfied + //[current]~^^ ERROR mismatched types } fn function3>() { diff --git a/tests/ui/mismatched_types/closure-mismatch.stderr b/tests/ui/mismatched_types/closure-mismatch.current.stderr similarity index 90% rename from tests/ui/mismatched_types/closure-mismatch.stderr rename to tests/ui/mismatched_types/closure-mismatch.current.stderr index 802110c6511d..378fe83ea89b 100644 --- a/tests/ui/mismatched_types/closure-mismatch.stderr +++ b/tests/ui/mismatched_types/closure-mismatch.current.stderr @@ -1,5 +1,5 @@ error: implementation of `FnOnce` is not general enough - --> $DIR/closure-mismatch.rs:8:5 + --> $DIR/closure-mismatch.rs:12:5 | LL | baz(|_| ()); | ^^^^^^^^^^^ implementation of `FnOnce` is not general enough @@ -8,7 +8,7 @@ LL | baz(|_| ()); = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` error: implementation of `Fn` is not general enough - --> $DIR/closure-mismatch.rs:8:5 + --> $DIR/closure-mismatch.rs:12:5 | LL | baz(|_| ()); | ^^^^^^^^^^^ implementation of `Fn` is not general enough @@ -17,7 +17,7 @@ LL | baz(|_| ()); = note: ...but it actually implements `Fn<(&'2 (),)>`, for some specific lifetime `'2` error: implementation of `FnOnce` is not general enough - --> $DIR/closure-mismatch.rs:11:5 + --> $DIR/closure-mismatch.rs:16:5 | LL | baz(|x| ()); | ^^^^^^^^^^^ implementation of `FnOnce` is not general enough @@ -26,7 +26,7 @@ LL | baz(|x| ()); = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` error: implementation of `Fn` is not general enough - --> $DIR/closure-mismatch.rs:11:5 + --> $DIR/closure-mismatch.rs:16:5 | LL | baz(|x| ()); | ^^^^^^^^^^^ implementation of `Fn` is not general enough diff --git a/tests/ui/mismatched_types/closure-mismatch.next.stderr b/tests/ui/mismatched_types/closure-mismatch.next.stderr new file mode 100644 index 000000000000..6b4620aa8d1b --- /dev/null +++ b/tests/ui/mismatched_types/closure-mismatch.next.stderr @@ -0,0 +1,67 @@ +error[E0277]: the trait bound `{closure@$DIR/closure-mismatch.rs:12:9: 12:12}: Foo` is not satisfied + --> $DIR/closure-mismatch.rs:12:9 + | +LL | baz(|_| ()); + | --- ^^^^^^ unsatisfied trait bound + | | + | required by a bound introduced by this call + | + = help: the trait `for<'a> FnOnce(&'a ())` is not implemented for closure `{closure@$DIR/closure-mismatch.rs:12:9: 12:12}` + = note: expected a closure with signature `for<'a> fn(&'a ())` + found a closure with signature `fn(&())` +note: this is a known limitation of the trait solver that will be lifted in the future + --> $DIR/closure-mismatch.rs:12:9 + | +LL | baz(|_| ()); + | ----^^^---- + | | | + | | the trait solver is unable to infer the generic types that should be inferred from this argument + | add turbofish arguments to this call to specify the types manually, even if it's redundant +note: required for `{closure@$DIR/closure-mismatch.rs:12:9: 12:12}` to implement `Foo` + --> $DIR/closure-mismatch.rs:7:18 + | +LL | impl Foo for T {} + | ------- ^^^ ^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `baz` + --> $DIR/closure-mismatch.rs:9:11 + | +LL | fn baz(_: T) {} + | ^^^ required by this bound in `baz` + +error[E0277]: the trait bound `{closure@$DIR/closure-mismatch.rs:16:9: 16:12}: Foo` is not satisfied + --> $DIR/closure-mismatch.rs:16:9 + | +LL | baz(|x| ()); + | --- ^^^^^^ unsatisfied trait bound + | | + | required by a bound introduced by this call + | + = help: the trait `for<'a> FnOnce(&'a ())` is not implemented for closure `{closure@$DIR/closure-mismatch.rs:16:9: 16:12}` + = note: expected a closure with signature `for<'a> fn(&'a ())` + found a closure with signature `fn(&())` +note: this is a known limitation of the trait solver that will be lifted in the future + --> $DIR/closure-mismatch.rs:16:9 + | +LL | baz(|x| ()); + | ----^^^---- + | | | + | | the trait solver is unable to infer the generic types that should be inferred from this argument + | add turbofish arguments to this call to specify the types manually, even if it's redundant +note: required for `{closure@$DIR/closure-mismatch.rs:16:9: 16:12}` to implement `Foo` + --> $DIR/closure-mismatch.rs:7:18 + | +LL | impl Foo for T {} + | ------- ^^^ ^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in `baz` + --> $DIR/closure-mismatch.rs:9:11 + | +LL | fn baz(_: T) {} + | ^^^ required by this bound in `baz` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/mismatched_types/closure-mismatch.rs b/tests/ui/mismatched_types/closure-mismatch.rs index efaed4dc1b99..1a24c760a6af 100644 --- a/tests/ui/mismatched_types/closure-mismatch.rs +++ b/tests/ui/mismatched_types/closure-mismatch.rs @@ -1,3 +1,7 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + trait Foo {} impl Foo for T {} @@ -6,9 +10,11 @@ fn baz(_: T) {} fn main() { baz(|_| ()); - //~^ ERROR implementation of `FnOnce` is not general enough - //~| ERROR implementation of `Fn` is not general enough + //[current]~^ ERROR implementation of `FnOnce` is not general enough + //[current]~| ERROR implementation of `Fn` is not general enough + //[next]~^^^ ERROR Foo` is not satisfied baz(|x| ()); - //~^ ERROR implementation of `FnOnce` is not general enough - //~| ERROR implementation of `Fn` is not general enough + //[current]~^ ERROR implementation of `FnOnce` is not general enough + //[current]~| ERROR implementation of `Fn` is not general enough + //[next]~^^^ ERROR Foo` is not satisfied } From 57c2a021a43bcbd8fe19490c540c3d2cffc0fb89 Mon Sep 17 00:00:00 2001 From: Urgau <3616612+Urgau@users.noreply.github.com> Date: Wed, 9 Apr 2025 20:29:19 +0200 Subject: [PATCH 276/606] triagebot: enable `[canonicalize-issue-links]` and `[no-mentions]` --- src/tools/miri/triagebot.toml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/tools/miri/triagebot.toml b/src/tools/miri/triagebot.toml index 4e013764d871..60e80c3f6733 100644 --- a/src/tools/miri/triagebot.toml +++ b/src/tools/miri/triagebot.toml @@ -40,3 +40,9 @@ unless = ["S-blocked", "S-waiting-on-team", "S-waiting-on-review"] # Automatically close and reopen PRs made by bots to run CI on them [bot-pull-requests] + +# Canonicalize issue numbers to avoid closing the wrong issue when upstreaming this subtree +[canonicalize-issue-links] + +# Prevents mentions in commits to avoid users being spammed +[no-mentions] From 9847c738930b329f70e34d97048a35cd795654b8 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Wed, 9 Apr 2025 09:54:45 +0300 Subject: [PATCH 277/606] set `rust.channel` to "auto-detect" for `dist` profile Signed-off-by: onur-ozkan --- src/bootstrap/defaults/bootstrap.dist.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/defaults/bootstrap.dist.toml b/src/bootstrap/defaults/bootstrap.dist.toml index 7b381b416ca8..6221e2e01e4c 100644 --- a/src/bootstrap/defaults/bootstrap.dist.toml +++ b/src/bootstrap/defaults/bootstrap.dist.toml @@ -15,7 +15,7 @@ download-ci-llvm = false [rust] # We have several defaults in bootstrap that depend on whether the channel is `dev` (e.g. `omit-git-hash` and `download-ci-llvm`). # Make sure they don't get set when installing from source. -channel = "nightly" +channel = "auto-detect" # Never download a rustc, distributions must build a fresh compiler. download-rustc = false lld = true From 7103aea39ab4a73f074a035eb4416e223bf4cde3 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Wed, 9 Apr 2025 12:59:37 -0700 Subject: [PATCH 278/606] Tracking issue template: fine-grained information on style update status Inspired by some of the communication issues around the stabilization of `let`-chains, give more fine-grained information about the status of updating style for any new syntax. This does not change the process or blockers in any way; it only *documents* the current state in the tracking issue. For instance, in the case of `let`-chains, we would have checked the boxes for "Style team decision" and "(non-blocking) Formatting has been implemented", and not checked the box for the style guide. That would have then provided better supporting information for any decisions. --- .github/ISSUE_TEMPLATE/tracking_issue.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/tracking_issue.md b/.github/ISSUE_TEMPLATE/tracking_issue.md index 3a9d8408b3c9..aedc15a54c27 100644 --- a/.github/ISSUE_TEMPLATE/tracking_issue.md +++ b/.github/ISSUE_TEMPLATE/tracking_issue.md @@ -41,7 +41,10 @@ for larger features an implementation could be broken up into multiple PRs. - [ ] Implement the RFC (cc @rust-lang/XXX -- can anyone write up mentoring instructions?) - [ ] Adjust documentation ([see instructions on rustc-dev-guide][doc-guide]) -- [ ] Formatting for new syntax has been added to the [Style Guide] ([nightly-style-procedure]) +- [ ] Style updates for any new syntax ([nightly-style-procedure]) + - [ ] Style team decision on new formatting + - [ ] Formatting for new syntax has been added to the [Style Guide] + - [ ] (non-blocking) Formatting has been implemented in `rustfmt` - [ ] Stabilization PR ([see instructions on rustc-dev-guide][stabilization-guide]) [stabilization-guide]: https://rustc-dev-guide.rust-lang.org/stabilization_guide.html#stabilization-pr From 27836e1e5794dfa8db8565adaf7aed05d8bfff92 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 26 Mar 2025 18:57:13 +0000 Subject: [PATCH 279/606] Rigidly project missing item due to guaranteed impossible sized predicate --- .../rustc_hir_analysis/src/check/check.rs | 8 +- compiler/rustc_middle/src/ty/sty.rs | 37 +++++++ .../src/solve/normalizes_to/mod.rs | 12 +- .../src/traits/project.rs | 104 ++++++++++-------- compiler/rustc_type_ir/src/inherent.rs | 33 ++++++ .../trivial-unsized-projection.bad.stderr | 44 ++++++++ .../trivial-unsized-projection.bad_new.stderr | 61 ++++++++++ tests/ui/traits/trivial-unsized-projection.rs | 34 ++++++ 8 files changed, 281 insertions(+), 52 deletions(-) create mode 100644 tests/ui/traits/trivial-unsized-projection.bad.stderr create mode 100644 tests/ui/traits/trivial-unsized-projection.bad_new.stderr create mode 100644 tests/ui/traits/trivial-unsized-projection.rs diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 18ef00dc8b18..5b89dcf7dd82 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -943,7 +943,7 @@ fn check_impl_items_against_trait<'tcx>( let cause = ObligationCause::misc(tcx.def_span(impl_id), impl_id); let param_env = tcx.param_env(impl_id); - let self_is_guaranteed_unsized = match tcx + let self_is_guaranteed_unsized = tcx .struct_tail_raw( trait_ref.self_ty(), |ty| { @@ -957,11 +957,7 @@ fn check_impl_items_against_trait<'tcx>( }, || (), ) - .kind() - { - ty::Dynamic(_, _, ty::DynKind::Dyn) | ty::Slice(_) | ty::Str => true, - _ => false, - }; + .is_guaranteed_unsized_raw(); for &impl_item in impl_item_refs { let ty_impl_item = tcx.associated_item(impl_item); diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 27ee363f1c14..fb15ab8d8481 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -2029,6 +2029,43 @@ impl<'tcx> Ty<'tcx> { pub fn is_known_rigid(self) -> bool { self.kind().is_known_rigid() } + + /// Returns true if the type is guaranteed to be one of the three built-in unsized types: + /// `dyn Trait`/`[T]`/`str`. This function is *raw* because it does not compute the struct + /// tail of the type, so you are responsible for doing that yourself. + // NOTE: Keep this in sync with `rustc_type_ir`'s copy. + pub fn is_guaranteed_unsized_raw(self) -> bool { + match self.kind() { + Dynamic(_, _, ty::Dyn) | ty::Slice(_) | ty::Str => true, + Bool + | Char + | Int(_) + | Uint(_) + | Float(_) + | Adt(_, _) + | Foreign(_) + | Array(_, _) + | Pat(_, _) + | RawPtr(_, _) + | Ref(_, _, _) + | FnDef(_, _) + | FnPtr(_, _) + | UnsafeBinder(_) + | Closure(_, _) + | CoroutineClosure(_, _) + | Coroutine(_, _) + | CoroutineWitness(_, _) + | Never + | Tuple(_) + | Alias(_, _) + | Param(_) + | Bound(_, _) + | Placeholder(_) + | Infer(_) + | Error(_) + | Dynamic(_, _, ty::DynStar) => false, + } + } } impl<'tcx> rustc_type_ir::inherent::Tys> for &'tcx ty::List> { diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index de6d21da0f59..4cfc727d6b79 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -232,7 +232,17 @@ where }; if !cx.has_item_definition(target_item_def_id) { - return error_response(ecx, cx.delay_bug("missing item")); + // If the impl is missing an item, it's either because the user forgot to + // provide it, or the user is not *obligated* to provide it (because it + // has a trivially false `Sized` predicate). If it's the latter, we cannot + // delay a bug because we can have trivially false where clauses, so we + // treat it as rigid. + if goal_trait_ref.self_ty().is_guaranteed_unsized_raw() { + ecx.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias); + return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes); + } else { + return error_response(ecx, cx.delay_bug("missing item")); + } } let target_container_def_id = cx.parent(target_item_def_id); diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 349569d750e0..8c5f1809a492 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -669,30 +669,11 @@ fn project<'cx, 'tcx>( match candidates { ProjectionCandidateSet::Single(candidate) => { - Ok(Projected::Progress(confirm_candidate(selcx, obligation, candidate))) + confirm_candidate(selcx, obligation, candidate) } ProjectionCandidateSet::None => { let tcx = selcx.tcx(); - let term = match tcx.def_kind(obligation.predicate.def_id) { - DefKind::AssocTy => Ty::new_projection_from_args( - tcx, - obligation.predicate.def_id, - obligation.predicate.args, - ) - .into(), - DefKind::AssocConst => ty::Const::new_unevaluated( - tcx, - ty::UnevaluatedConst::new( - obligation.predicate.def_id, - obligation.predicate.args, - ), - ) - .into(), - kind => { - bug!("unknown projection def-id: {}", kind.descr(obligation.predicate.def_id)) - } - }; - + let term = obligation.predicate.to_term(tcx); Ok(Projected::NoProgress(term)) } // Error occurred while trying to processing impls. @@ -1244,18 +1225,16 @@ fn confirm_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTermObligation<'tcx>, candidate: ProjectionCandidate<'tcx>, -) -> Progress<'tcx> { +) -> Result, ProjectionError<'tcx>> { debug!(?obligation, ?candidate, "confirm_candidate"); - let mut progress = match candidate { + let mut result = match candidate { ProjectionCandidate::ParamEnv(poly_projection) - | ProjectionCandidate::Object(poly_projection) => { - confirm_param_env_candidate(selcx, obligation, poly_projection, false) - } - - ProjectionCandidate::TraitDef(poly_projection) => { - confirm_param_env_candidate(selcx, obligation, poly_projection, true) - } - + | ProjectionCandidate::Object(poly_projection) => Ok(Projected::Progress( + confirm_param_env_candidate(selcx, obligation, poly_projection, false), + )), + ProjectionCandidate::TraitDef(poly_projection) => Ok(Projected::Progress( + confirm_param_env_candidate(selcx, obligation, poly_projection, true), + )), ProjectionCandidate::Select(impl_source) => { confirm_select_candidate(selcx, obligation, impl_source) } @@ -1266,23 +1245,26 @@ fn confirm_candidate<'cx, 'tcx>( // with new region variables, we need to resolve them to existing variables // when possible for this to work. See `auto-trait-projection-recursion.rs` // for a case where this matters. - if progress.term.has_infer_regions() { + if let Ok(Projected::Progress(progress)) = &mut result + && progress.term.has_infer_regions() + { progress.term = progress.term.fold_with(&mut OpportunisticRegionResolver::new(selcx.infcx)); } - progress + + result } fn confirm_select_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTermObligation<'tcx>, impl_source: Selection<'tcx>, -) -> Progress<'tcx> { +) -> Result, ProjectionError<'tcx>> { match impl_source { ImplSource::UserDefined(data) => confirm_impl_candidate(selcx, obligation, data), ImplSource::Builtin(BuiltinImplSource::Misc | BuiltinImplSource::Trivial, data) => { let tcx = selcx.tcx(); let trait_def_id = obligation.predicate.trait_def_id(tcx); - if tcx.is_lang_item(trait_def_id, LangItem::Coroutine) { + let progress = if tcx.is_lang_item(trait_def_id, LangItem::Coroutine) { confirm_coroutine_candidate(selcx, obligation, data) } else if tcx.is_lang_item(trait_def_id, LangItem::Future) { confirm_future_candidate(selcx, obligation, data) @@ -1304,7 +1286,8 @@ fn confirm_select_candidate<'cx, 'tcx>( confirm_async_fn_kind_helper_candidate(selcx, obligation, data) } else { confirm_builtin_candidate(selcx, obligation, data) - } + }; + Ok(Projected::Progress(progress)) } ImplSource::Builtin(BuiltinImplSource::Object { .. }, _) | ImplSource::Param(..) @@ -2000,7 +1983,7 @@ fn confirm_impl_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTermObligation<'tcx>, impl_impl_source: ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>, -) -> Progress<'tcx> { +) -> Result, ProjectionError<'tcx>> { let tcx = selcx.tcx(); let ImplSourceUserDefinedData { impl_def_id, args, mut nested } = impl_impl_source; @@ -2011,19 +1994,47 @@ fn confirm_impl_candidate<'cx, 'tcx>( let param_env = obligation.param_env; let assoc_ty = match specialization_graph::assoc_def(tcx, impl_def_id, assoc_item_id) { Ok(assoc_ty) => assoc_ty, - Err(guar) => return Progress::error(tcx, guar), + Err(guar) => return Ok(Projected::Progress(Progress::error(tcx, guar))), }; + + // This means that the impl is missing a definition for the + // associated type. This is either because the associate item + // has impossible-to-satisfy predicates (since those were + // allowed in ), + // or because the impl is literally missing the definition. if !assoc_ty.item.defaultness(tcx).has_value() { - // This means that the impl is missing a definition for the - // associated type. This error will be reported by the type - // checker method `check_impl_items_against_trait`, so here we - // just return Error. debug!( "confirm_impl_candidate: no associated type {:?} for {:?}", assoc_ty.item.name, obligation.predicate ); - return Progress { term: Ty::new_misc_error(tcx).into(), obligations: nested }; + let tail = selcx.tcx().struct_tail_raw( + tcx.type_of(impl_def_id).instantiate(tcx, args), + |ty| { + normalize_with_depth_to( + selcx, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + ty, + &mut nested, + ) + }, + || {}, + ); + if tail.is_guaranteed_unsized_raw() { + // We treat this projection as rigid here, which is represented via + // `Projected::NoProgress`. This will ensure that the projection is + // checked for well-formedness, and it's either satisfied by a trivial + // where clause in its env or it results in an error. + return Ok(Projected::NoProgress(obligation.predicate.to_term(tcx))); + } else { + return Ok(Projected::Progress(Progress { + term: Ty::new_misc_error(tcx).into(), + obligations: nested, + })); + } } + // If we're trying to normalize ` as X>::A` using //`impl X for Vec { type A = Box; }`, then: // @@ -2033,6 +2044,7 @@ fn confirm_impl_candidate<'cx, 'tcx>( let args = obligation.predicate.args.rebase_onto(tcx, trait_def_id, args); let args = translate_args(selcx.infcx, param_env, impl_def_id, args, assoc_ty.defining_node); let is_const = matches!(tcx.def_kind(assoc_ty.item.def_id), DefKind::AssocConst); + let term: ty::EarlyBinder<'tcx, ty::Term<'tcx>> = if is_const { let did = assoc_ty.item.def_id; let identity_args = crate::traits::GenericArgs::identity_for_item(tcx, did); @@ -2041,7 +2053,8 @@ fn confirm_impl_candidate<'cx, 'tcx>( } else { tcx.type_of(assoc_ty.item.def_id).map_bound(|ty| ty.into()) }; - if !tcx.check_args_compatible(assoc_ty.item.def_id, args) { + + let progress = if !tcx.check_args_compatible(assoc_ty.item.def_id, args) { let err = Ty::new_error_with_message( tcx, obligation.cause.span, @@ -2051,7 +2064,8 @@ fn confirm_impl_candidate<'cx, 'tcx>( } else { assoc_ty_own_obligations(selcx, obligation, &mut nested); Progress { term: term.instantiate(tcx, args), obligations: nested } - } + }; + Ok(Projected::Progress(progress)) } // Get obligations corresponding to the predicates from the where-clause of the diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index 59c2d3c2fc8d..6e6c40580d83 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -155,6 +155,39 @@ pub trait Ty>: fn is_known_rigid(self) -> bool { self.kind().is_known_rigid() } + + fn is_guaranteed_unsized_raw(self) -> bool { + match self.kind() { + ty::Dynamic(_, _, ty::Dyn) | ty::Slice(_) | ty::Str => true, + ty::Bool + | ty::Char + | ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Adt(_, _) + | ty::Foreign(_) + | ty::Array(_, _) + | ty::Pat(_, _) + | ty::RawPtr(_, _) + | ty::Ref(_, _, _) + | ty::FnDef(_, _) + | ty::FnPtr(_, _) + | ty::UnsafeBinder(_) + | ty::Closure(_, _) + | ty::CoroutineClosure(_, _) + | ty::Coroutine(_, _) + | ty::CoroutineWitness(_, _) + | ty::Never + | ty::Tuple(_) + | ty::Alias(_, _) + | ty::Param(_) + | ty::Bound(_, _) + | ty::Placeholder(_) + | ty::Infer(_) + | ty::Error(_) + | ty::Dynamic(_, _, ty::DynStar) => false, + } + } } pub trait Tys>: diff --git a/tests/ui/traits/trivial-unsized-projection.bad.stderr b/tests/ui/traits/trivial-unsized-projection.bad.stderr new file mode 100644 index 000000000000..4aea63329b36 --- /dev/null +++ b/tests/ui/traits/trivial-unsized-projection.bad.stderr @@ -0,0 +1,44 @@ +error[E0277]: the size for values of type `[()]` cannot be known at compilation time + --> $DIR/trivial-unsized-projection.rs:20:12 + | +LL | const FOO: <[()] as Bad>::Assert = todo!(); + | ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[()]` +note: required by a bound in `Bad::Assert` + --> $DIR/trivial-unsized-projection.rs:14:15 + | +LL | type Assert + | ------ required by a bound in this associated type +LL | where +LL | Self: Sized; + | ^^^^^ required by this bound in `Bad::Assert` +help: consider relaxing the implicit `Sized` restriction + | +LL | type Assert: ?Sized + | ++++++++ + +error[E0277]: the size for values of type `[()]` cannot be known at compilation time + --> $DIR/trivial-unsized-projection.rs:20:12 + | +LL | const FOO: <[()] as Bad>::Assert = todo!(); + | ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[()]` +note: required by a bound in `Bad::Assert` + --> $DIR/trivial-unsized-projection.rs:14:15 + | +LL | type Assert + | ------ required by a bound in this associated type +LL | where +LL | Self: Sized; + | ^^^^^ required by this bound in `Bad::Assert` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: consider relaxing the implicit `Sized` restriction + | +LL | type Assert: ?Sized + | ++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/trivial-unsized-projection.bad_new.stderr b/tests/ui/traits/trivial-unsized-projection.bad_new.stderr new file mode 100644 index 000000000000..9f01d71ef159 --- /dev/null +++ b/tests/ui/traits/trivial-unsized-projection.bad_new.stderr @@ -0,0 +1,61 @@ +error[E0271]: type mismatch resolving `<[()] as Bad>::Assert normalizes-to <[()] as Bad>::Assert` + --> $DIR/trivial-unsized-projection.rs:20:12 + | +LL | const FOO: <[()] as Bad>::Assert = todo!(); + | ^^^^^^^^^^^^^^^^^^^^^ types differ + | + = note: statics and constants must have a statically known size + +error[E0277]: the size for values of type `[()]` cannot be known at compilation time + --> $DIR/trivial-unsized-projection.rs:20:12 + | +LL | const FOO: <[()] as Bad>::Assert = todo!(); + | ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[()]` +note: required by a bound in `Bad::Assert` + --> $DIR/trivial-unsized-projection.rs:14:15 + | +LL | type Assert + | ------ required by a bound in this associated type +LL | where +LL | Self: Sized; + | ^^^^^ required by this bound in `Bad::Assert` +help: consider relaxing the implicit `Sized` restriction + | +LL | type Assert: ?Sized + | ++++++++ + +error[E0277]: the size for values of type `[()]` cannot be known at compilation time + --> $DIR/trivial-unsized-projection.rs:20:12 + | +LL | const FOO: <[()] as Bad>::Assert = todo!(); + | ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[()]` +note: required by a bound in `Bad::Assert` + --> $DIR/trivial-unsized-projection.rs:14:15 + | +LL | type Assert + | ------ required by a bound in this associated type +LL | where +LL | Self: Sized; + | ^^^^^ required by this bound in `Bad::Assert` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: consider relaxing the implicit `Sized` restriction + | +LL | type Assert: ?Sized + | ++++++++ + +error[E0271]: type mismatch resolving `<[()] as Bad>::Assert normalizes-to <[()] as Bad>::Assert` + --> $DIR/trivial-unsized-projection.rs:20:36 + | +LL | const FOO: <[()] as Bad>::Assert = todo!(); + | ^^^^^^^ types differ + | + = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0271, E0277. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/trivial-unsized-projection.rs b/tests/ui/traits/trivial-unsized-projection.rs new file mode 100644 index 000000000000..82a309e9e13c --- /dev/null +++ b/tests/ui/traits/trivial-unsized-projection.rs @@ -0,0 +1,34 @@ +//@ revisions: good bad good_new bad_new +//@[good_new] compile-flags: -Znext-solver +//@[bad_new] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[good] check-pass +//@[good_new] check-pass + +#![feature(trivial_bounds)] +#![allow(trivial_bounds)] + +trait Bad { + type Assert + where + Self: Sized; +} + +impl Bad for [()] {} + +#[cfg(any(bad, bad_new))] +const FOO: <[()] as Bad>::Assert = todo!(); +//[bad]~^ ERROR the size for values of type `[()]` cannot be known at compilation time +//[bad]~| ERROR the size for values of type `[()]` cannot be known at compilation time +//[bad_new]~^^^ ERROR the size for values of type `[()]` cannot be known at compilation time +//[bad_new]~| ERROR the size for values of type `[()]` cannot be known at compilation time +//[bad_new]~| ERROR type mismatch resolving `<[()] as Bad>::Assert normalizes-to <[()] as Bad>::Assert` +//[bad_new]~| ERROR type mismatch resolving `<[()] as Bad>::Assert normalizes-to <[()] as Bad>::Assert` + +#[cfg(any(good, good_new))] +// Well-formed in trivially false param-env +fn foo() where [()]: Sized { + let _: <[()] as Bad>::Assert; +} + +fn main() {} From ccdfd310be12f0c46be8b3266b3ff4e2ce5b3806 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 26 Mar 2025 18:59:44 +0000 Subject: [PATCH 280/606] Mark GAT WC as GoalSource::AliasWellFormed so that we recurse into them in error reporting --- .../src/solve/normalizes_to/mod.rs | 4 ++-- compiler/rustc_type_ir/src/solve/mod.rs | 7 +++++-- .../trivial-unsized-projection.bad_new.stderr | 21 ++----------------- tests/ui/traits/trivial-unsized-projection.rs | 2 -- 4 files changed, 9 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index 4cfc727d6b79..f4f15ff6d462 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -134,7 +134,7 @@ where // Add GAT where clauses from the trait's definition // FIXME: We don't need these, since these are the type's own WF obligations. ecx.add_goals( - GoalSource::Misc, + GoalSource::AliasWellFormed, cx.own_predicates_of(goal.predicate.def_id()) .iter_instantiated(cx, goal.predicate.alias.args) .map(|pred| goal.with(cx, pred)), @@ -199,7 +199,7 @@ where // Add GAT where clauses from the trait's definition. // FIXME: We don't need these, since these are the type's own WF obligations. ecx.add_goals( - GoalSource::Misc, + GoalSource::AliasWellFormed, cx.own_predicates_of(goal.predicate.def_id()) .iter_instantiated(cx, goal.predicate.alias.args) .map(|pred| goal.with(cx, pred)), diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs index 3aec4804b279..4e9b87fdf74d 100644 --- a/compiler/rustc_type_ir/src/solve/mod.rs +++ b/compiler/rustc_type_ir/src/solve/mod.rs @@ -83,8 +83,11 @@ pub enum GoalSource { /// Instantiating a higher-ranked goal and re-proving it. InstantiateHigherRanked, /// Predicate required for an alias projection to be well-formed. - /// This is used in two places: projecting to an opaque whose hidden type - /// is already registered in the opaque type storage, and for rigid projections. + /// This is used in three places: + /// 1. projecting to an opaque whose hidden type is already registered in + /// the opaque type storage, + /// 2. for rigid projections's trait goal, + /// 3. for GAT where clauses. AliasWellFormed, /// In case normalizing aliases in nested goals cycles, eagerly normalizing these /// aliases in the context of the parent may incorrectly change the cycle kind. diff --git a/tests/ui/traits/trivial-unsized-projection.bad_new.stderr b/tests/ui/traits/trivial-unsized-projection.bad_new.stderr index 9f01d71ef159..4aea63329b36 100644 --- a/tests/ui/traits/trivial-unsized-projection.bad_new.stderr +++ b/tests/ui/traits/trivial-unsized-projection.bad_new.stderr @@ -1,11 +1,3 @@ -error[E0271]: type mismatch resolving `<[()] as Bad>::Assert normalizes-to <[()] as Bad>::Assert` - --> $DIR/trivial-unsized-projection.rs:20:12 - | -LL | const FOO: <[()] as Bad>::Assert = todo!(); - | ^^^^^^^^^^^^^^^^^^^^^ types differ - | - = note: statics and constants must have a statically known size - error[E0277]: the size for values of type `[()]` cannot be known at compilation time --> $DIR/trivial-unsized-projection.rs:20:12 | @@ -47,15 +39,6 @@ help: consider relaxing the implicit `Sized` restriction LL | type Assert: ?Sized | ++++++++ -error[E0271]: type mismatch resolving `<[()] as Bad>::Assert normalizes-to <[()] as Bad>::Assert` - --> $DIR/trivial-unsized-projection.rs:20:36 - | -LL | const FOO: <[()] as Bad>::Assert = todo!(); - | ^^^^^^^ types differ - | - = note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info) +error: aborting due to 2 previous errors -error: aborting due to 4 previous errors - -Some errors have detailed explanations: E0271, E0277. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/trivial-unsized-projection.rs b/tests/ui/traits/trivial-unsized-projection.rs index 82a309e9e13c..62ff25fb7ac0 100644 --- a/tests/ui/traits/trivial-unsized-projection.rs +++ b/tests/ui/traits/trivial-unsized-projection.rs @@ -22,8 +22,6 @@ const FOO: <[()] as Bad>::Assert = todo!(); //[bad]~| ERROR the size for values of type `[()]` cannot be known at compilation time //[bad_new]~^^^ ERROR the size for values of type `[()]` cannot be known at compilation time //[bad_new]~| ERROR the size for values of type `[()]` cannot be known at compilation time -//[bad_new]~| ERROR type mismatch resolving `<[()] as Bad>::Assert normalizes-to <[()] as Bad>::Assert` -//[bad_new]~| ERROR type mismatch resolving `<[()] as Bad>::Assert normalizes-to <[()] as Bad>::Assert` #[cfg(any(good, good_new))] // Well-formed in trivially false param-env From 830aeb610289924b5910f409f6751fcf4e497f1e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 30 Mar 2025 03:40:14 +0000 Subject: [PATCH 281/606] Use a query rather than recomputing the tail repeatedly --- .../rustc_hir_analysis/src/check/check.rs | 26 +-------- compiler/rustc_middle/src/query/mod.rs | 7 +++ compiler/rustc_middle/src/ty/context.rs | 4 ++ compiler/rustc_middle/src/ty/sty.rs | 37 ------------ .../src/solve/normalizes_to/mod.rs | 2 +- .../src/traits/project.rs | 16 +----- compiler/rustc_ty_utils/src/ty.rs | 57 +++++++++++++++++++ compiler/rustc_type_ir/src/interner.rs | 2 + tests/ui/associated-types/impl-wf-cycle-4.rs | 2 +- .../associated-types/impl-wf-cycle-4.stderr | 29 +++++----- .../trivial-unsized-projection-2.bad.stderr | 54 ++++++++++++++++++ ...rivial-unsized-projection-2.bad_new.stderr | 54 ++++++++++++++++++ .../ui/traits/trivial-unsized-projection-2.rs | 34 +++++++++++ 13 files changed, 234 insertions(+), 90 deletions(-) create mode 100644 tests/ui/traits/trivial-unsized-projection-2.bad.stderr create mode 100644 tests/ui/traits/trivial-unsized-projection-2.bad_new.stderr create mode 100644 tests/ui/traits/trivial-unsized-projection-2.rs diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 5b89dcf7dd82..bcfbd7b0e978 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -937,27 +937,7 @@ fn check_impl_items_against_trait<'tcx>( let trait_def = tcx.trait_def(trait_ref.def_id); - let infcx = tcx.infer_ctxt().ignoring_regions().build(TypingMode::non_body_analysis()); - - let ocx = ObligationCtxt::new_with_diagnostics(&infcx); - let cause = ObligationCause::misc(tcx.def_span(impl_id), impl_id); - let param_env = tcx.param_env(impl_id); - - let self_is_guaranteed_unsized = tcx - .struct_tail_raw( - trait_ref.self_ty(), - |ty| { - ocx.structurally_normalize_ty(&cause, param_env, ty).unwrap_or_else(|_| { - Ty::new_error_with_message( - tcx, - tcx.def_span(impl_id), - "struct tail should be computable", - ) - }) - }, - || (), - ) - .is_guaranteed_unsized_raw(); + let self_is_guaranteed_unsize_self = tcx.impl_self_is_guaranteed_unsized(impl_id); for &impl_item in impl_item_refs { let ty_impl_item = tcx.associated_item(impl_item); @@ -988,7 +968,7 @@ fn check_impl_items_against_trait<'tcx>( } } - if self_is_guaranteed_unsized && tcx.generics_require_sized_self(ty_trait_item.def_id) { + if self_is_guaranteed_unsize_self && tcx.generics_require_sized_self(ty_trait_item.def_id) { tcx.emit_node_span_lint( rustc_lint_defs::builtin::DEAD_CODE, tcx.local_def_id_to_hir_id(ty_impl_item.def_id.expect_local()), @@ -1023,7 +1003,7 @@ fn check_impl_items_against_trait<'tcx>( if !is_implemented && tcx.defaultness(impl_id).is_final() // unsized types don't need to implement methods that have `Self: Sized` bounds. - && !(self_is_guaranteed_unsized && tcx.generics_require_sized_self(trait_item_id)) + && !(self_is_guaranteed_unsize_self && tcx.generics_require_sized_self(trait_item_id)) { missing_items.push(tcx.associated_item(trait_item_id)); } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index a1df27ac788c..40d0028db86d 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1026,6 +1026,13 @@ rustc_queries! { separate_provide_extern } + /// Given an `impl_def_id`, return true if the self type is guaranteed to be unsized due + /// to either being one of the built-in unsized types (str/slice/dyn) or to be a struct + /// whose tail is one of those types. + query impl_self_is_guaranteed_unsized(impl_def_id: DefId) -> bool { + desc { |tcx| "computing whether `{}` has a guaranteed unsized self type", tcx.def_path_str(impl_def_id) } + } + /// Maps a `DefId` of a type to a list of its inherent impls. /// Contains implementations of methods that are inherent to a type. /// Methods in these implementations don't need to be exported. diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 162ca1f4af85..abf6cbbcd877 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -437,6 +437,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> { ) } + fn impl_self_is_guaranteed_unsized(self, impl_def_id: DefId) -> bool { + self.impl_self_is_guaranteed_unsized(impl_def_id) + } + fn has_target_features(self, def_id: DefId) -> bool { !self.codegen_fn_attrs(def_id).target_features.is_empty() } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index fb15ab8d8481..27ee363f1c14 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -2029,43 +2029,6 @@ impl<'tcx> Ty<'tcx> { pub fn is_known_rigid(self) -> bool { self.kind().is_known_rigid() } - - /// Returns true if the type is guaranteed to be one of the three built-in unsized types: - /// `dyn Trait`/`[T]`/`str`. This function is *raw* because it does not compute the struct - /// tail of the type, so you are responsible for doing that yourself. - // NOTE: Keep this in sync with `rustc_type_ir`'s copy. - pub fn is_guaranteed_unsized_raw(self) -> bool { - match self.kind() { - Dynamic(_, _, ty::Dyn) | ty::Slice(_) | ty::Str => true, - Bool - | Char - | Int(_) - | Uint(_) - | Float(_) - | Adt(_, _) - | Foreign(_) - | Array(_, _) - | Pat(_, _) - | RawPtr(_, _) - | Ref(_, _, _) - | FnDef(_, _) - | FnPtr(_, _) - | UnsafeBinder(_) - | Closure(_, _) - | CoroutineClosure(_, _) - | Coroutine(_, _) - | CoroutineWitness(_, _) - | Never - | Tuple(_) - | Alias(_, _) - | Param(_) - | Bound(_, _) - | Placeholder(_) - | Infer(_) - | Error(_) - | Dynamic(_, _, ty::DynStar) => false, - } - } } impl<'tcx> rustc_type_ir::inherent::Tys> for &'tcx ty::List> { diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index f4f15ff6d462..87fb61623d15 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -237,7 +237,7 @@ where // has a trivially false `Sized` predicate). If it's the latter, we cannot // delay a bug because we can have trivially false where clauses, so we // treat it as rigid. - if goal_trait_ref.self_ty().is_guaranteed_unsized_raw() { + if cx.impl_self_is_guaranteed_unsized(impl_def_id) { ecx.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias); return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes); } else { diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 8c5f1809a492..83591219b14d 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -2007,21 +2007,7 @@ fn confirm_impl_candidate<'cx, 'tcx>( "confirm_impl_candidate: no associated type {:?} for {:?}", assoc_ty.item.name, obligation.predicate ); - let tail = selcx.tcx().struct_tail_raw( - tcx.type_of(impl_def_id).instantiate(tcx, args), - |ty| { - normalize_with_depth_to( - selcx, - obligation.param_env, - obligation.cause.clone(), - obligation.recursion_depth + 1, - ty, - &mut nested, - ) - }, - || {}, - ); - if tail.is_guaranteed_unsized_raw() { + if tcx.impl_self_is_guaranteed_unsized(impl_def_id) { // We treat this projection as rigid here, which is represented via // `Projected::NoProgress`. This will ensure that the projection is // checked for well-formedness, and it's either satisfied by a trivial diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 9dc4f11e456e..31d69eef5ecf 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -3,6 +3,7 @@ use rustc_hir as hir; use rustc_hir::LangItem; use rustc_hir::def::DefKind; use rustc_index::bit_set::DenseBitSet; +use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::bug; use rustc_middle::query::Providers; use rustc_middle::ty::{ @@ -312,6 +313,61 @@ fn unsizing_params_for_adt<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> DenseBitSe unsizing_params } +fn impl_self_is_guaranteed_unsized<'tcx>(tcx: TyCtxt<'tcx>, impl_def_id: DefId) -> bool { + debug_assert_eq!(tcx.def_kind(impl_def_id), DefKind::Impl { of_trait: true }); + + let infcx = tcx.infer_ctxt().ignoring_regions().build(ty::TypingMode::non_body_analysis()); + + let ocx = traits::ObligationCtxt::new_with_diagnostics(&infcx); + let cause = traits::ObligationCause::dummy(); + let param_env = tcx.param_env(impl_def_id); + + let tail = tcx.struct_tail_raw( + tcx.type_of(impl_def_id).instantiate_identity(), + |ty| { + ocx.structurally_normalize_ty(&cause, param_env, ty).unwrap_or_else(|_| { + Ty::new_error_with_message( + tcx, + tcx.def_span(impl_def_id), + "struct tail should be computable", + ) + }) + }, + || (), + ); + + match tail.kind() { + ty::Dynamic(_, _, ty::Dyn) | ty::Slice(_) | ty::Str => true, + ty::Bool + | ty::Char + | ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Adt(_, _) + | ty::Foreign(_) + | ty::Array(_, _) + | ty::Pat(_, _) + | ty::RawPtr(_, _) + | ty::Ref(_, _, _) + | ty::FnDef(_, _) + | ty::FnPtr(_, _) + | ty::UnsafeBinder(_) + | ty::Closure(_, _) + | ty::CoroutineClosure(_, _) + | ty::Coroutine(_, _) + | ty::CoroutineWitness(_, _) + | ty::Never + | ty::Tuple(_) + | ty::Alias(_, _) + | ty::Param(_) + | ty::Bound(_, _) + | ty::Placeholder(_) + | ty::Infer(_) + | ty::Error(_) + | ty::Dynamic(_, _, ty::DynStar) => false, + } +} + pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { asyncness, @@ -320,6 +376,7 @@ pub(crate) fn provide(providers: &mut Providers) { param_env_normalized_for_post_analysis, defaultness, unsizing_params_for_adt, + impl_self_is_guaranteed_unsized, ..*providers }; } diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index fce93b735d79..a9e6764e2182 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -255,6 +255,8 @@ pub trait Interner: def_id: Self::DefId, ) -> ty::EarlyBinder>>>; + fn impl_self_is_guaranteed_unsized(self, def_id: Self::DefId) -> bool; + fn has_target_features(self, def_id: Self::DefId) -> bool; fn require_lang_item(self, lang_item: TraitSolverLangItem) -> Self::DefId; diff --git a/tests/ui/associated-types/impl-wf-cycle-4.rs b/tests/ui/associated-types/impl-wf-cycle-4.rs index bfa8adc71a11..1c1b3991d32a 100644 --- a/tests/ui/associated-types/impl-wf-cycle-4.rs +++ b/tests/ui/associated-types/impl-wf-cycle-4.rs @@ -2,7 +2,7 @@ trait Filter { type ToMatch; } -impl Filter for T //~ ERROR overflow evaluating the requirement +impl Filter for T //~ ERROR cycle detected when where T: Fn(Self::ToMatch), { diff --git a/tests/ui/associated-types/impl-wf-cycle-4.stderr b/tests/ui/associated-types/impl-wf-cycle-4.stderr index cdbac267d34d..c966579aecf1 100644 --- a/tests/ui/associated-types/impl-wf-cycle-4.stderr +++ b/tests/ui/associated-types/impl-wf-cycle-4.stderr @@ -1,4 +1,4 @@ -error[E0275]: overflow evaluating the requirement `::ToMatch == ::ToMatch` +error[E0391]: cycle detected when computing normalized predicates of `` --> $DIR/impl-wf-cycle-4.rs:5:1 | LL | / impl Filter for T @@ -6,20 +6,23 @@ LL | | where LL | | T: Fn(Self::ToMatch), | |_________________________^ | -note: required for `T` to implement `Filter` - --> $DIR/impl-wf-cycle-4.rs:5:9 +note: ...which requires computing whether `` has a guaranteed unsized self type... + --> $DIR/impl-wf-cycle-4.rs:5:1 | -LL | impl Filter for T - | ^^^^^^ ^ -LL | where -LL | T: Fn(Self::ToMatch), - | ----------------- unsatisfied trait bound introduced here -note: associated types for the current `impl` cannot be restricted in `where` clauses - --> $DIR/impl-wf-cycle-4.rs:7:11 +LL | / impl Filter for T +LL | | where +LL | | T: Fn(Self::ToMatch), + | |_________________________^ + = note: ...which again requires computing normalized predicates of ``, completing the cycle +note: cycle used when checking that `` is well-formed + --> $DIR/impl-wf-cycle-4.rs:5:1 | -LL | T: Fn(Self::ToMatch), - | ^^^^^^^^^^^^^ +LL | / impl Filter for T +LL | | where +LL | | T: Fn(Self::ToMatch), + | |_________________________^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0275`. +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/traits/trivial-unsized-projection-2.bad.stderr b/tests/ui/traits/trivial-unsized-projection-2.bad.stderr new file mode 100644 index 000000000000..bf8d3c40cf65 --- /dev/null +++ b/tests/ui/traits/trivial-unsized-projection-2.bad.stderr @@ -0,0 +1,54 @@ +error[E0277]: the size for values of type `[()]` cannot be known at compilation time + --> $DIR/trivial-unsized-projection-2.rs:22:12 + | +LL | const FOO: ::Assert = todo!(); + | ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `Tail`, the trait `Sized` is not implemented for `[()]` +note: required because it appears within the type `Tail` + --> $DIR/trivial-unsized-projection-2.rs:17:8 + | +LL | struct Tail([()]); + | ^^^^ +note: required by a bound in `Bad::Assert` + --> $DIR/trivial-unsized-projection-2.rs:14:15 + | +LL | type Assert + | ------ required by a bound in this associated type +LL | where +LL | Self: Sized; + | ^^^^^ required by this bound in `Bad::Assert` +help: consider relaxing the implicit `Sized` restriction + | +LL | type Assert: ?Sized + | ++++++++ + +error[E0277]: the size for values of type `[()]` cannot be known at compilation time + --> $DIR/trivial-unsized-projection-2.rs:22:12 + | +LL | const FOO: ::Assert = todo!(); + | ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `Tail`, the trait `Sized` is not implemented for `[()]` +note: required because it appears within the type `Tail` + --> $DIR/trivial-unsized-projection-2.rs:17:8 + | +LL | struct Tail([()]); + | ^^^^ +note: required by a bound in `Bad::Assert` + --> $DIR/trivial-unsized-projection-2.rs:14:15 + | +LL | type Assert + | ------ required by a bound in this associated type +LL | where +LL | Self: Sized; + | ^^^^^ required by this bound in `Bad::Assert` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: consider relaxing the implicit `Sized` restriction + | +LL | type Assert: ?Sized + | ++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/trivial-unsized-projection-2.bad_new.stderr b/tests/ui/traits/trivial-unsized-projection-2.bad_new.stderr new file mode 100644 index 000000000000..bf8d3c40cf65 --- /dev/null +++ b/tests/ui/traits/trivial-unsized-projection-2.bad_new.stderr @@ -0,0 +1,54 @@ +error[E0277]: the size for values of type `[()]` cannot be known at compilation time + --> $DIR/trivial-unsized-projection-2.rs:22:12 + | +LL | const FOO: ::Assert = todo!(); + | ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `Tail`, the trait `Sized` is not implemented for `[()]` +note: required because it appears within the type `Tail` + --> $DIR/trivial-unsized-projection-2.rs:17:8 + | +LL | struct Tail([()]); + | ^^^^ +note: required by a bound in `Bad::Assert` + --> $DIR/trivial-unsized-projection-2.rs:14:15 + | +LL | type Assert + | ------ required by a bound in this associated type +LL | where +LL | Self: Sized; + | ^^^^^ required by this bound in `Bad::Assert` +help: consider relaxing the implicit `Sized` restriction + | +LL | type Assert: ?Sized + | ++++++++ + +error[E0277]: the size for values of type `[()]` cannot be known at compilation time + --> $DIR/trivial-unsized-projection-2.rs:22:12 + | +LL | const FOO: ::Assert = todo!(); + | ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `Tail`, the trait `Sized` is not implemented for `[()]` +note: required because it appears within the type `Tail` + --> $DIR/trivial-unsized-projection-2.rs:17:8 + | +LL | struct Tail([()]); + | ^^^^ +note: required by a bound in `Bad::Assert` + --> $DIR/trivial-unsized-projection-2.rs:14:15 + | +LL | type Assert + | ------ required by a bound in this associated type +LL | where +LL | Self: Sized; + | ^^^^^ required by this bound in `Bad::Assert` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: consider relaxing the implicit `Sized` restriction + | +LL | type Assert: ?Sized + | ++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/trivial-unsized-projection-2.rs b/tests/ui/traits/trivial-unsized-projection-2.rs new file mode 100644 index 000000000000..af4e12f6f900 --- /dev/null +++ b/tests/ui/traits/trivial-unsized-projection-2.rs @@ -0,0 +1,34 @@ +//@ revisions: good bad good_new bad_new +//@[good_new] compile-flags: -Znext-solver +//@[bad_new] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[good] check-pass +//@[good_new] check-pass + +#![feature(trivial_bounds)] +#![allow(trivial_bounds)] + +trait Bad { + type Assert + where + Self: Sized; +} + +struct Tail([()]); + +impl Bad for Tail {} + +#[cfg(any(bad, bad_new))] +const FOO: ::Assert = todo!(); +//[bad]~^ ERROR the size for values of type `[()]` cannot be known at compilation time +//[bad]~| ERROR the size for values of type `[()]` cannot be known at compilation time +//[bad_new]~^^^ ERROR the size for values of type `[()]` cannot be known at compilation time +//[bad_new]~| ERROR the size for values of type `[()]` cannot be known at compilation time + +#[cfg(any(good, good_new))] +// Well-formed in trivially false param-env +fn foo() where Tail: Sized { + let _: ::Assert; +} + +fn main() {} From 6cd724bb43b92ae573112c3d39804f227c7ebf02 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 31 Mar 2025 18:56:09 +0000 Subject: [PATCH 282/606] Make unnormalizable item ambiguous in coherence --- .../src/solve/normalizes_to/mod.rs | 20 ++++++++- ...trivial-unsized-projection-in-coherence.rs | 45 +++++++++++++++++++ ...ial-unsized-projection-in-coherence.stderr | 15 +++++++ 3 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 tests/ui/traits/trivial-unsized-projection-in-coherence.rs create mode 100644 tests/ui/traits/trivial-unsized-projection-in-coherence.stderr diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index 87fb61623d15..2d027f16e5d9 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -238,8 +238,24 @@ where // delay a bug because we can have trivially false where clauses, so we // treat it as rigid. if cx.impl_self_is_guaranteed_unsized(impl_def_id) { - ecx.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias); - return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes); + match ecx.typing_mode() { + ty::TypingMode::Coherence => { + return ecx.evaluate_added_goals_and_make_canonical_response( + Certainty::AMBIGUOUS, + ); + } + ty::TypingMode::Analysis { .. } + | ty::TypingMode::Borrowck { .. } + | ty::TypingMode::PostBorrowckAnalysis { .. } + | ty::TypingMode::PostAnalysis => { + ecx.structurally_instantiate_normalizes_to_term( + goal, + goal.predicate.alias, + ); + return ecx + .evaluate_added_goals_and_make_canonical_response(Certainty::Yes); + } + } } else { return error_response(ecx, cx.delay_bug("missing item")); } diff --git a/tests/ui/traits/trivial-unsized-projection-in-coherence.rs b/tests/ui/traits/trivial-unsized-projection-in-coherence.rs new file mode 100644 index 000000000000..4407d544b4ef --- /dev/null +++ b/tests/ui/traits/trivial-unsized-projection-in-coherence.rs @@ -0,0 +1,45 @@ +// Make sure we don't treat missing associated items as rigid +// during coherence, even if we know they've got an impossible +// `Sized`-bound. As we check whether the self type is definitely +// not `Sized` outside of coherence, this check can be incomplete. +// +// In this test we only use `impl Overlap for T` to normalize +// the field of `MaybeUnsized` when checking whether it's +// definitely not `Sized`. However, for `MaybeUnsized` we +// could also use `impl Overlap for u32` for normalization, which +// would result in a `Sized` type. cc #139000 + +struct MaybeUnsized, U>(>::MaybeUnsized); + +trait ReqSized { + type Missing1 + where + Self: Sized; + type Missing2 + where + Self: Sized; +} +impl ReqSized for MaybeUnsized {} + +struct W(T); +trait Eq {} +impl Eq for W {} + +trait RelateReqSized {} +impl RelateReqSized for T where W: Eq {} + +trait Overlap { + type MaybeUnsized: ?Sized; +} +impl Overlap for T { + type MaybeUnsized = str; +} +impl Overlap for u32 +//~^ ERROR conflicting implementations of trait `Overlap` for type `u32` +where + MaybeUnsized: RelateReqSized, +{ + type MaybeUnsized = u32; +} + +fn main() {} diff --git a/tests/ui/traits/trivial-unsized-projection-in-coherence.stderr b/tests/ui/traits/trivial-unsized-projection-in-coherence.stderr new file mode 100644 index 000000000000..52fca9479ca4 --- /dev/null +++ b/tests/ui/traits/trivial-unsized-projection-in-coherence.stderr @@ -0,0 +1,15 @@ +error[E0119]: conflicting implementations of trait `Overlap` for type `u32` + --> $DIR/trivial-unsized-projection-in-coherence.rs:37:1 + | +LL | impl Overlap for T { + | -------------------------- first implementation here +... +LL | / impl Overlap for u32 +LL | | +LL | | where +LL | | MaybeUnsized: RelateReqSized, + | |_________________________________________^ conflicting implementation for `u32` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. From 77116881a857ca49ff11c7c3b35c86305864ab45 Mon Sep 17 00:00:00 2001 From: oyvindln Date: Wed, 9 Apr 2025 23:45:46 +0200 Subject: [PATCH 283/606] update miniz_oxide to 0.8.8 0.8.7 can trigger a panic when debug assertions are enabled when used via flate2 in some cases --- Cargo.lock | 6 +++--- library/Cargo.lock | 4 ++-- src/ci/citool/Cargo.lock | 4 ++-- src/tools/miri/test_dependencies/Cargo.lock | 4 ++-- src/tools/rustbook/Cargo.lock | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bf519e039260..68ad21bbeba7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1221,7 +1221,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece" dependencies = [ "crc32fast", - "miniz_oxide 0.8.7", + "miniz_oxide 0.8.8", ] [[package]] @@ -2291,9 +2291,9 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.8.7" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff70ce3e48ae43fa075863cef62e8b43b71a4f2382229920e0df362592919430" +checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" dependencies = [ "adler2", ] diff --git a/library/Cargo.lock b/library/Cargo.lock index ad634e9f794a..75584d2a77b7 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -176,9 +176,9 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.8.7" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff70ce3e48ae43fa075863cef62e8b43b71a4f2382229920e0df362592919430" +checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" dependencies = [ "adler2", "compiler_builtins", diff --git a/src/ci/citool/Cargo.lock b/src/ci/citool/Cargo.lock index 800eaae07665..2fe219f368b9 100644 --- a/src/ci/citool/Cargo.lock +++ b/src/ci/citool/Cargo.lock @@ -563,9 +563,9 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "miniz_oxide" -version = "0.8.5" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5" +checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" dependencies = [ "adler2", ] diff --git a/src/tools/miri/test_dependencies/Cargo.lock b/src/tools/miri/test_dependencies/Cargo.lock index 24a8efc873d6..276c518e74f3 100644 --- a/src/tools/miri/test_dependencies/Cargo.lock +++ b/src/tools/miri/test_dependencies/Cargo.lock @@ -156,9 +156,9 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "miniz_oxide" -version = "0.8.7" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff70ce3e48ae43fa075863cef62e8b43b71a4f2382229920e0df362592919430" +checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" dependencies = [ "adler2", ] diff --git a/src/tools/rustbook/Cargo.lock b/src/tools/rustbook/Cargo.lock index 09bbbd61de50..e0939afc09bb 100644 --- a/src/tools/rustbook/Cargo.lock +++ b/src/tools/rustbook/Cargo.lock @@ -981,9 +981,9 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "miniz_oxide" -version = "0.8.7" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff70ce3e48ae43fa075863cef62e8b43b71a4f2382229920e0df362592919430" +checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" dependencies = [ "adler2", ] From 1b3fc585cb48c71dbaf1677af6d6698977b436cd Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 8 Apr 2025 12:23:07 +1000 Subject: [PATCH 284/606] Rename some `name` variables as `ident`. It bugs me when variables of type `Ident` are called `name`. It leads to silly things like `name.name`. `Ident` variables should be called `ident`, and `name` should be used for variables of type `Symbol`. This commit improves things by by doing `s/name/ident/` on a bunch of `Ident` variables. Not all of them, but a decent chunk. --- compiler/rustc_ast/src/expand/mod.rs | 4 +- compiler/rustc_ast_lowering/src/item.rs | 6 +- compiler/rustc_ast_lowering/src/lib.rs | 4 +- compiler/rustc_ast_pretty/src/pprust/tests.rs | 4 +- .../src/diagnostics/conflict_errors.rs | 10 +-- .../rustc_borrowck/src/diagnostics/mod.rs | 2 +- .../src/proc_macro_harness.rs | 24 +++---- .../rustc_codegen_cranelift/src/main_shim.rs | 2 +- compiler/rustc_expand/src/base.rs | 2 +- compiler/rustc_expand/src/expand.rs | 10 +-- compiler/rustc_hir/src/hir.rs | 4 +- compiler/rustc_hir/src/intravisit.rs | 8 +-- compiler/rustc_hir_analysis/messages.ftl | 8 +-- .../src/check/compare_impl_item.rs | 8 +-- compiler/rustc_hir_analysis/src/collect.rs | 4 +- .../src/collect/predicates_of.rs | 16 ++--- .../src/collect/resolve_bound_vars.rs | 8 +-- compiler/rustc_hir_analysis/src/errors.rs | 4 +- .../src/hir_ty_lowering/bounds.rs | 4 +- .../src/hir_ty_lowering/cmse.rs | 4 +- .../src/hir_ty_lowering/errors.rs | 44 ++++++------ .../src/hir_ty_lowering/mod.rs | 41 +++++------ compiler/rustc_hir_pretty/src/lib.rs | 30 ++++---- compiler/rustc_hir_typeck/messages.ftl | 2 +- compiler/rustc_hir_typeck/src/errors.rs | 2 +- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 14 ++-- compiler/rustc_hir_typeck/src/method/mod.rs | 6 +- .../rustc_hir_typeck/src/method/suggest.rs | 72 +++++++++---------- compiler/rustc_lint/src/context.rs | 2 +- compiler/rustc_lint/src/nonstandard_style.rs | 8 +-- compiler/rustc_metadata/src/rmeta/decoder.rs | 2 +- .../src/rmeta/decoder/cstore_impl.rs | 2 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 2 +- compiler/rustc_metadata/src/rmeta/mod.rs | 2 +- compiler/rustc_middle/src/hir/map.rs | 2 +- compiler/rustc_middle/src/hir/mod.rs | 6 +- compiler/rustc_middle/src/query/mod.rs | 4 +- compiler/rustc_middle/src/ty/assoc.rs | 14 ++-- compiler/rustc_middle/src/ty/mod.rs | 10 +-- .../src/mono_checks/move_check.rs | 2 +- compiler/rustc_resolve/src/diagnostics.rs | 12 ++-- .../rustc_resolve/src/late/diagnostics.rs | 2 +- compiler/rustc_resolve/src/lib.rs | 2 +- compiler/rustc_resolve/src/macros.rs | 4 +- .../src/error_reporting/traits/suggestions.rs | 4 +- src/librustdoc/clean/inline.rs | 4 +- src/librustdoc/clean/mod.rs | 24 +++---- .../src/bool_assert_comparison.rs | 2 +- .../src/functions/renamed_function_params.rs | 4 +- .../src/methods/needless_collect.rs | 2 +- src/tools/clippy/clippy_utils/src/ty/mod.rs | 2 +- .../dont-compute-arg-names-for-non-fn.rs | 2 +- 52 files changed, 238 insertions(+), 229 deletions(-) diff --git a/compiler/rustc_ast/src/expand/mod.rs b/compiler/rustc_ast/src/expand/mod.rs index 04c816293236..323a8fab6d59 100644 --- a/compiler/rustc_ast/src/expand/mod.rs +++ b/compiler/rustc_ast/src/expand/mod.rs @@ -13,12 +13,12 @@ pub mod typetree; #[derive(Debug, Clone, Encodable, Decodable, HashStable_Generic)] pub struct StrippedCfgItem { pub parent_module: ModId, - pub name: Ident, + pub ident: Ident, pub cfg: MetaItem, } impl StrippedCfgItem { pub fn map_mod_id(self, f: impl FnOnce(ModId) -> New) -> StrippedCfgItem { - StrippedCfgItem { parent_module: f(self.parent_module), name: self.name, cfg: self.cfg } + StrippedCfgItem { parent_module: f(self.parent_module), ident: self.ident, cfg: self.cfg } } } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 958a6917dff8..59099e5a5545 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -645,7 +645,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ( // Disallow `impl Trait` in foreign items. this.lower_fn_decl(fdec, i.id, sig.span, FnDeclKind::ExternFn, None), - this.lower_fn_params_to_names(fdec), + this.lower_fn_params_to_idents(fdec), ) }); @@ -833,7 +833,7 @@ impl<'hir> LoweringContext<'_, 'hir> { }) => { // FIXME(contracts): Deny contract here since it won't apply to // any impl method or callees. - let names = self.lower_fn_params_to_names(&sig.decl); + let idents = self.lower_fn_params_to_idents(&sig.decl); let (generics, sig) = self.lower_method_sig( generics, sig, @@ -851,7 +851,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ( *ident, generics, - hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), + hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(idents)), false, ) } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 6aa6a18ee9a7..446e02e40242 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1247,7 +1247,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { safety: self.lower_safety(f.safety, hir::Safety::Safe), abi: self.lower_extern(f.ext), decl: self.lower_fn_decl(&f.decl, t.id, t.span, FnDeclKind::Pointer, None), - param_names: self.lower_fn_params_to_names(&f.decl), + param_idents: self.lower_fn_params_to_idents(&f.decl), })) } TyKind::UnsafeBinder(f) => { @@ -1494,7 +1494,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { })) } - fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Option] { + fn lower_fn_params_to_idents(&mut self, decl: &FnDecl) -> &'hir [Option] { self.arena.alloc_from_iter(decl.inputs.iter().map(|param| match param.pat.kind { PatKind::Missing => None, PatKind::Ident(_, ident, _) => Some(self.lower_ident(ident)), diff --git a/compiler/rustc_ast_pretty/src/pprust/tests.rs b/compiler/rustc_ast_pretty/src/pprust/tests.rs index 4c42dd1f2023..bc7f22766a5c 100644 --- a/compiler/rustc_ast_pretty/src/pprust/tests.rs +++ b/compiler/rustc_ast_pretty/src/pprust/tests.rs @@ -7,12 +7,12 @@ use super::*; fn fun_to_string( decl: &ast::FnDecl, header: ast::FnHeader, - name: Ident, + ident: Ident, generics: &ast::Generics, ) -> String { to_string(|s| { s.head(""); - s.print_fn(decl, header, Some(name), generics); + s.print_fn(decl, header, Some(ident), generics); s.end(); // Close the head box. s.end(); // Close the outer box. }) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 1f4eb0c449f8..e77d0399b8c9 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -2500,11 +2500,11 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { ); let ty::Tuple(params) = tupled_params.kind() else { return }; - // Find the first argument with a matching type, get its name - let Some(this_name) = params.iter().zip(tcx.hir_body_param_names(closure.body)).find_map( - |(param_ty, name)| { + // Find the first argument with a matching type, get its ident + let Some(this_name) = params.iter().zip(tcx.hir_body_param_idents(closure.body)).find_map( + |(param_ty, ident)| { // FIXME: also support deref for stuff like `Rc` arguments - if param_ty.peel_refs() == local_ty { name } else { None } + if param_ty.peel_refs() == local_ty { ident } else { None } }, ) else { return; @@ -3774,7 +3774,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { method_args, *fn_span, call_source.from_hir_call(), - self.infcx.tcx.fn_arg_names(method_did)[0], + self.infcx.tcx.fn_arg_idents(method_did)[0], ) { err.note(format!("borrow occurs due to deref coercion to `{deref_target_ty}`")); diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 899e145c2c04..80556baa0281 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -1029,7 +1029,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { method_args, *fn_span, call_source.from_hir_call(), - self.infcx.tcx.fn_arg_names(method_did)[0], + self.infcx.tcx.fn_arg_idents(method_did)[0], ); return FnSelfUse { diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs index 8862965c0532..a91f2d38a93a 100644 --- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs +++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs @@ -20,14 +20,14 @@ use crate::errors; struct ProcMacroDerive { id: NodeId, trait_name: Symbol, - function_name: Ident, + function_ident: Ident, span: Span, attrs: Vec, } struct ProcMacroDef { id: NodeId, - function_name: Ident, + function_ident: Ident, span: Span, } @@ -95,7 +95,7 @@ impl<'a> CollectProcMacros<'a> { fn collect_custom_derive( &mut self, item: &'a ast::Item, - function_name: Ident, + function_ident: Ident, attr: &'a ast::Attribute, ) { let Some((trait_name, proc_attrs)) = @@ -109,7 +109,7 @@ impl<'a> CollectProcMacros<'a> { id: item.id, span: item.span, trait_name, - function_name, + function_ident, attrs: proc_attrs, })); } else { @@ -123,12 +123,12 @@ impl<'a> CollectProcMacros<'a> { } } - fn collect_attr_proc_macro(&mut self, item: &'a ast::Item, function_name: Ident) { + fn collect_attr_proc_macro(&mut self, item: &'a ast::Item, function_ident: Ident) { if self.in_root && item.vis.kind.is_pub() { self.macros.push(ProcMacro::Attr(ProcMacroDef { id: item.id, span: item.span, - function_name, + function_ident, })); } else { let msg = if !self.in_root { @@ -141,12 +141,12 @@ impl<'a> CollectProcMacros<'a> { } } - fn collect_bang_proc_macro(&mut self, item: &'a ast::Item, function_name: Ident) { + fn collect_bang_proc_macro(&mut self, item: &'a ast::Item, function_ident: Ident) { if self.in_root && item.vis.kind.is_pub() { self.macros.push(ProcMacro::Bang(ProcMacroDef { id: item.id, span: item.span, - function_name, + function_ident, })); } else { let msg = if !self.in_root { @@ -303,7 +303,7 @@ fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> P { ProcMacro::Derive(m) => m.span, ProcMacro::Attr(m) | ProcMacro::Bang(m) => m.span, }; - let local_path = |cx: &ExtCtxt<'_>, name| cx.expr_path(cx.path(span, vec![name])); + let local_path = |cx: &ExtCtxt<'_>, ident| cx.expr_path(cx.path(span, vec![ident])); let proc_macro_ty_method_path = |cx: &ExtCtxt<'_>, method| { cx.expr_path(cx.path( span.with_ctxt(harness_span.ctxt()), @@ -327,7 +327,7 @@ fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> P { .map(|&s| cx.expr_str(span, s)) .collect::>(), ), - local_path(cx, cd.function_name), + local_path(cx, cd.function_ident), ], ) } @@ -345,8 +345,8 @@ fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> P { harness_span, proc_macro_ty_method_path(cx, ident), thin_vec![ - cx.expr_str(span, ca.function_name.name), - local_path(cx, ca.function_name), + cx.expr_str(span, ca.function_ident.name), + local_path(cx, ca.function_ident), ], ) } diff --git a/compiler/rustc_codegen_cranelift/src/main_shim.rs b/compiler/rustc_codegen_cranelift/src/main_shim.rs index 6d5df2b00437..3b48adb7e918 100644 --- a/compiler/rustc_codegen_cranelift/src/main_shim.rs +++ b/compiler/rustc_codegen_cranelift/src/main_shim.rs @@ -104,7 +104,7 @@ pub(crate) fn maybe_create_entry_wrapper( let termination_trait = tcx.require_lang_item(LangItem::Termination, None); let report = tcx .associated_items(termination_trait) - .find_by_name_and_kind( + .find_by_ident_and_kind( tcx, Ident::from_str("report"), AssocKind::Fn, diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index d14e476ba322..49f6d58172ff 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1102,7 +1102,7 @@ pub trait ResolverExpand { /// HIR proc macros items back to their harness items. fn declare_proc_macro(&mut self, id: NodeId); - fn append_stripped_cfg_item(&mut self, parent_node: NodeId, name: Ident, cfg: ast::MetaItem); + fn append_stripped_cfg_item(&mut self, parent_node: NodeId, ident: Ident, cfg: ast::MetaItem); /// Tools registered with `#![register_tool]` and used by tool attributes and lints. fn registered_tools(&self) -> &RegisteredTools; diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index bca846d2ec42..4a5b7b917064 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -1169,9 +1169,9 @@ trait InvocationCollectorNode: HasAttrs + HasNodeId + Sized { collector.cx.dcx().emit_err(RemoveNodeNotSupported { span, descr: Self::descr() }); } - /// All of the names (items) declared by this node. + /// All of the idents (items) declared by this node. /// This is an approximation and should only be used for diagnostics. - fn declared_names(&self) -> Vec { + fn declared_idents(&self) -> Vec { vec![] } } @@ -1306,7 +1306,7 @@ impl InvocationCollectorNode for P { res } - fn declared_names(&self) -> Vec { + fn declared_idents(&self) -> Vec { if let ItemKind::Use(ut) = &self.kind { fn collect_use_tree_leaves(ut: &ast::UseTree, idents: &mut Vec) { match &ut.kind { @@ -2061,10 +2061,10 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { } if let Some(meta_item) = meta_item { - for name in node.declared_names() { + for ident in node.declared_idents() { self.cx.resolver.append_stripped_cfg_item( self.cx.current_expansion.lint_node_id, - name, + ident, meta_item.clone(), ) } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index c61477951c92..062193130b32 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3399,9 +3399,9 @@ pub struct BareFnTy<'hir> { pub abi: ExternAbi, pub generic_params: &'hir [GenericParam<'hir>], pub decl: &'hir FnDecl<'hir>, - // `Option` because bare fn parameter names are optional. We also end up + // `Option` because bare fn parameter idents are optional. We also end up // with `None` in some error cases, e.g. invalid parameter patterns. - pub param_names: &'hir [Option], + pub param_idents: &'hir [Option], } #[derive(Debug, Clone, Copy, HashStable_Generic)] diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index ea3f396761b1..93d20dfa7996 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -652,10 +652,10 @@ pub fn walk_foreign_item<'v, V: Visitor<'v>>( try_visit!(visitor.visit_ident(foreign_item.ident)); match foreign_item.kind { - ForeignItemKind::Fn(ref sig, param_names, ref generics) => { + ForeignItemKind::Fn(ref sig, param_idents, ref generics) => { try_visit!(visitor.visit_generics(generics)); try_visit!(visitor.visit_fn_decl(sig.decl)); - for ident in param_names.iter().copied() { + for ident in param_idents.iter().copied() { visit_opt!(visitor, visit_ident, ident); } } @@ -1169,9 +1169,9 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>( try_visit!(visitor.visit_ty_unambig(ty)); visit_opt!(visitor, visit_nested_body, default); } - TraitItemKind::Fn(ref sig, TraitFn::Required(param_names)) => { + TraitItemKind::Fn(ref sig, TraitFn::Required(param_idents)) => { try_visit!(visitor.visit_fn_decl(sig.decl)); - for ident in param_names.iter().copied() { + for ident in param_idents.iter().copied() { visit_opt!(visitor, visit_ident, ident); } } diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 2f7c3cb3c7d8..92701e3328e9 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -1,5 +1,5 @@ -hir_analysis_ambiguous_assoc_item = ambiguous associated {$assoc_kind} `{$assoc_name}` in bounds of `{$qself}` - .label = ambiguous associated {$assoc_kind} `{$assoc_name}` +hir_analysis_ambiguous_assoc_item = ambiguous associated {$assoc_kind} `{$assoc_ident}` in bounds of `{$qself}` + .label = ambiguous associated {$assoc_kind} `{$assoc_ident}` hir_analysis_ambiguous_lifetime_bound = ambiguous lifetime bound, explicit lifetime bound required @@ -12,13 +12,13 @@ hir_analysis_assoc_item_is_private = {$kind} `{$name}` is private .label = private {$kind} .defined_here_label = the {$kind} is defined here -hir_analysis_assoc_item_not_found = associated {$assoc_kind} `{$assoc_name}` not found for `{$qself}` +hir_analysis_assoc_item_not_found = associated {$assoc_kind} `{$assoc_ident}` not found for `{$qself}` hir_analysis_assoc_item_not_found_found_in_other_trait_label = there is {$identically_named -> [true] an *[false] a similarly named } associated {$assoc_kind} `{$suggested_name}` in the trait `{$trait_name}` -hir_analysis_assoc_item_not_found_label = associated {$assoc_kind} `{$assoc_name}` not found +hir_analysis_assoc_item_not_found_label = associated {$assoc_kind} `{$assoc_ident}` not found hir_analysis_assoc_item_not_found_other_sugg = `{$qself}` has the following associated {$assoc_kind} hir_analysis_assoc_item_not_found_similar_in_other_trait_qpath_sugg = consider fully qualifying{$identically_named -> diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 5e68bb310015..f878f6d572b8 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -1046,11 +1046,11 @@ fn report_trait_method_mismatch<'tcx>( // argument pattern and type. let (sig, body) = tcx.hir_expect_impl_item(impl_m.def_id.expect_local()).expect_fn(); let span = tcx - .hir_body_param_names(body) + .hir_body_param_idents(body) .zip(sig.decl.inputs.iter()) - .map(|(param_name, ty)| { - if let Some(param_name) = param_name { - param_name.span.to(ty.span) + .map(|(param_ident, ty)| { + if let Some(param_ident) = param_ident { + param_ident.span.to(ty.span) } else { ty.span } diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index e9cd22435d95..eb0ad67f9b61 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -438,9 +438,9 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { &self, span: Span, def_id: LocalDefId, - assoc_name: Ident, + assoc_ident: Ident, ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { - self.tcx.at(span).type_param_predicates((self.item_def_id, def_id, assoc_name)) + self.tcx.at(span).type_param_predicates((self.item_def_id, def_id, assoc_ident)) } fn lower_assoc_shared( diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 320225a7a663..371e2583dbdc 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -584,12 +584,12 @@ pub(super) fn explicit_super_predicates_of<'tcx>( pub(super) fn explicit_supertraits_containing_assoc_item<'tcx>( tcx: TyCtxt<'tcx>, - (trait_def_id, assoc_name): (DefId, Ident), + (trait_def_id, assoc_ident): (DefId, Ident), ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { implied_predicates_with_filter( tcx, trait_def_id, - PredicateFilter::SelfTraitThatDefines(assoc_name), + PredicateFilter::SelfTraitThatDefines(assoc_ident), ) } @@ -617,7 +617,7 @@ pub(super) fn implied_predicates_with_filter<'tcx>( filter: PredicateFilter, ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { let Some(trait_def_id) = trait_def_id.as_local() else { - // if `assoc_name` is None, then the query should've been redirected to an + // if `assoc_ident` is None, then the query should've been redirected to an // external provider assert_matches!(filter, PredicateFilter::SelfTraitThatDefines(_)); return tcx.explicit_super_predicates_of(trait_def_id); @@ -834,11 +834,11 @@ pub(super) fn assert_only_contains_predicates_from<'tcx>( #[instrument(level = "trace", skip(tcx))] pub(super) fn type_param_predicates<'tcx>( tcx: TyCtxt<'tcx>, - (item_def_id, def_id, assoc_name): (LocalDefId, LocalDefId, Ident), + (item_def_id, def_id, assoc_ident): (LocalDefId, LocalDefId, Ident), ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { match tcx.opt_rpitit_info(item_def_id.to_def_id()) { Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => { - return tcx.type_param_predicates((opaque_def_id.expect_local(), def_id, assoc_name)); + return tcx.type_param_predicates((opaque_def_id.expect_local(), def_id, assoc_ident)); } Some(ty::ImplTraitInTraitData::Impl { .. }) => { unreachable!("should not be lowering bounds on RPITIT in impl") @@ -863,7 +863,7 @@ pub(super) fn type_param_predicates<'tcx>( let result = if let Some(parent) = parent { let icx = ItemCtxt::new(tcx, parent); - icx.probe_ty_param_bounds(DUMMY_SP, def_id, assoc_name) + icx.probe_ty_param_bounds(DUMMY_SP, def_id, assoc_ident) } else { ty::EarlyBinder::bind(&[] as &[_]) }; @@ -889,7 +889,7 @@ pub(super) fn type_param_predicates<'tcx>( let extra_predicates = extend.into_iter().chain(icx.probe_ty_param_bounds_in_generics( hir_generics, def_id, - PredicateFilter::SelfTraitThatDefines(assoc_name), + PredicateFilter::SelfTraitThatDefines(assoc_ident), )); let bounds = @@ -908,7 +908,7 @@ pub(super) fn type_param_predicates<'tcx>( _ => unreachable!(), }; assert_only_contains_predicates_from( - PredicateFilter::SelfTraitThatDefines(assoc_name), + PredicateFilter::SelfTraitThatDefines(assoc_ident), bounds, self_ty, ); diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 404753875ee5..9bcda35ee87a 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -1874,13 +1874,13 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { fn supertrait_hrtb_vars( tcx: TyCtxt<'tcx>, def_id: DefId, - assoc_name: Ident, + assoc_ident: Ident, assoc_kind: ty::AssocKind, ) -> Option<(Vec, &'tcx ty::AssocItem)> { let trait_defines_associated_item_named = |trait_def_id: DefId| { - tcx.associated_items(trait_def_id).find_by_name_and_kind( + tcx.associated_items(trait_def_id).find_by_ident_and_kind( tcx, - assoc_name, + assoc_ident, assoc_kind, trait_def_id, ) @@ -1904,7 +1904,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { if let Some(assoc_item) = trait_defines_associated_item_named(def_id) { break Some((bound_vars.into_iter().collect(), assoc_item)); } - let predicates = tcx.explicit_supertraits_containing_assoc_item((def_id, assoc_name)); + let predicates = tcx.explicit_supertraits_containing_assoc_item((def_id, assoc_ident)); let obligations = predicates.iter_identity_copied().filter_map(|(pred, _)| { let bound_predicate = pred.kind(); match bound_predicate.skip_binder() { diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index e6090a128b1c..508970cf2554 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -23,7 +23,7 @@ pub(crate) struct AmbiguousAssocItem<'a> { #[label] pub span: Span, pub assoc_kind: &'static str, - pub assoc_name: Ident, + pub assoc_ident: Ident, pub qself: &'a str, } @@ -75,7 +75,7 @@ pub(crate) struct AssocItemIsPrivate { pub(crate) struct AssocItemNotFound<'a> { #[primary_span] pub span: Span, - pub assoc_name: Ident, + pub assoc_ident: Ident, pub assoc_kind: &'static str, pub qself: &'a str, #[subdiagnostic] diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 55087d1f400f..24d05b49861c 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -363,10 +363,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { for hir_bound in hir_bounds { // In order to avoid cycles, when we're lowering `SelfTraitThatDefines`, // we skip over any traits that don't define the given associated type. - if let PredicateFilter::SelfTraitThatDefines(assoc_name) = predicate_filter { + if let PredicateFilter::SelfTraitThatDefines(assoc_ident) = predicate_filter { if let Some(trait_ref) = hir_bound.trait_ref() && let Some(trait_did) = trait_ref.trait_def_id() - && self.tcx().trait_may_define_assoc_item(trait_did, assoc_name) + && self.tcx().trait_may_define_assoc_item(trait_did, assoc_ident) { // Okay } else { diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs index ecb453bced0a..d1ee5a5494c0 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs @@ -49,13 +49,13 @@ pub(crate) fn validate_cmse_abi<'tcx>( Ok(Err(index)) => { // fn(x: u32, u32, u32, u16, y: u16) -> u32, // ^^^^^^ - let span = if let Some(ident) = bare_fn_ty.param_names[index] { + let span = if let Some(ident) = bare_fn_ty.param_idents[index] { ident.span.to(bare_fn_ty.decl.inputs[index].span) } else { bare_fn_ty.decl.inputs[index].span } .to(bare_fn_ty.decl.inputs.last().unwrap().span); - let plural = bare_fn_ty.param_names.len() - index != 1; + let plural = bare_fn_ty.param_idents.len() - index != 1; dcx.emit_err(errors::CmseInputsStackSpill { span, plural, abi }); } Err(layout_err) => { diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 6e9c178d33a6..5a0524d33fde 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -117,7 +117,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { all_candidates: impl Fn() -> I, qself: AssocItemQSelf, assoc_kind: ty::AssocKind, - assoc_name: Ident, + assoc_ident: Ident, span: Span, constraint: Option<&hir::AssocItemConstraint<'tcx>>, ) -> ErrorGuaranteed @@ -129,11 +129,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // First and foremost, provide a more user-friendly & “intuitive” error on kind mismatches. if let Some(assoc_item) = all_candidates().find_map(|r| { tcx.associated_items(r.def_id()) - .filter_by_name_unhygienic(assoc_name.name) - .find(|item| tcx.hygienic_eq(assoc_name, item.ident(tcx), r.def_id())) + .filter_by_name_unhygienic(assoc_ident.name) + .find(|item| tcx.hygienic_eq(assoc_ident, item.ident(tcx), r.def_id())) }) { return self.complain_about_assoc_kind_mismatch( - assoc_item, assoc_kind, assoc_name, span, constraint, + assoc_item, + assoc_kind, + assoc_ident, + span, + constraint, ); } @@ -142,18 +146,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // The fallback span is needed because `assoc_name` might be an `Fn()`'s `Output` without a // valid span, so we point at the whole path segment instead. - let is_dummy = assoc_name.span == DUMMY_SP; + let is_dummy = assoc_ident.span == DUMMY_SP; let mut err = errors::AssocItemNotFound { - span: if is_dummy { span } else { assoc_name.span }, - assoc_name, + span: if is_dummy { span } else { assoc_ident.span }, + assoc_ident, assoc_kind: assoc_kind_str, qself: &qself_str, label: None, sugg: None, // Try to get the span of the identifier within the path's syntax context // (if that's different). - within_macro_span: assoc_name.span.within_macro(span, tcx.sess.source_map()), + within_macro_span: assoc_ident.span.within_macro(span, tcx.sess.source_map()), }; if is_dummy { @@ -169,10 +173,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .collect(); if let Some(suggested_name) = - find_best_match_for_name(&all_candidate_names, assoc_name.name, None) + find_best_match_for_name(&all_candidate_names, assoc_ident.name, None) { err.sugg = Some(errors::AssocItemNotFoundSugg::Similar { - span: assoc_name.span, + span: assoc_ident.span, assoc_kind: assoc_kind_str, suggested_name, }); @@ -201,7 +205,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .collect(); if let Some(suggested_name) = - find_best_match_for_name(&wider_candidate_names, assoc_name.name, None) + find_best_match_for_name(&wider_candidate_names, assoc_ident.name, None) { if let [best_trait] = visible_traits .iter() @@ -215,11 +219,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { { let trait_name = tcx.def_path_str(best_trait); err.label = Some(errors::AssocItemNotFoundLabel::FoundInOtherTrait { - span: assoc_name.span, + span: assoc_ident.span, assoc_kind: assoc_kind_str, trait_name: &trait_name, suggested_name, - identically_named: suggested_name == assoc_name.name, + identically_named: suggested_name == assoc_ident.name, }); if let AssocItemQSelf::TyParam(ty_param_def_id, ty_param_span) = qself // Not using `self.item_def_id()` here as that would yield the opaque type itself if we're @@ -246,7 +250,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // The type param already has a bound for `trait_name`, we just need to // change the associated item. err.sugg = Some(errors::AssocItemNotFoundSugg::SimilarInOtherTrait { - span: assoc_name.span, + span: assoc_ident.span, assoc_kind: assoc_kind_str, suggested_name, }); @@ -265,7 +269,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { Applicability::MaybeIncorrect }; - let identically_named = suggested_name == assoc_name.name; + let identically_named = suggested_name == assoc_ident.name; if let DefKind::TyAlias = tcx.def_kind(item_def_id) && !tcx.type_alias_is_lazy(item_def_id) @@ -273,7 +277,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { err.sugg = Some(errors::AssocItemNotFoundSugg::SimilarInOtherTraitQPath { lo: ty_param_span.shrink_to_lo(), mi: ty_param_span.shrink_to_hi(), - hi: (!identically_named).then_some(assoc_name.span), + hi: (!identically_named).then_some(assoc_ident.span), trait_ref, identically_named, suggested_name, @@ -294,7 +298,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // We suggested constraining a type parameter, but the associated item on it // was also not an exact match, so we also suggest changing it. err.span_suggestion_verbose( - assoc_name.span, + assoc_ident.span, fluent::hir_analysis_assoc_item_not_found_similar_in_other_trait_with_bound_sugg, suggested_name, Applicability::MaybeIncorrect, @@ -311,13 +315,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // suggest using it. if let [candidate_name] = all_candidate_names.as_slice() { err.sugg = Some(errors::AssocItemNotFoundSugg::Other { - span: assoc_name.span, + span: assoc_ident.span, qself: &qself_str, assoc_kind: assoc_kind_str, suggested_name: *candidate_name, }); } else { - err.label = Some(errors::AssocItemNotFoundLabel::NotFound { span: assoc_name.span }); + err.label = Some(errors::AssocItemNotFoundLabel::NotFound { span: assoc_ident.span }); } self.dcx().emit_err(err) @@ -805,7 +809,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { return None; }; - let assoc_item = tcx.associated_items(trait_def).find_by_name_and_kind( + let assoc_item = tcx.associated_items(trait_def).find_by_ident_and_kind( tcx, ident, ty::AssocKind::Type, 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 b4a71edc118c..83aa0d956201 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -147,7 +147,7 @@ pub trait HirTyLowerer<'tcx> { &self, span: Span, def_id: LocalDefId, - assoc_name: Ident, + assoc_ident: Ident, ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]>; /// Lower an associated type/const (from a trait) to a projection. @@ -933,11 +933,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { &self, trait_def_id: DefId, assoc_kind: ty::AssocKind, - assoc_name: Ident, + assoc_ident: Ident, ) -> bool { self.tcx() .associated_items(trait_def_id) - .find_by_name_and_kind(self.tcx(), assoc_name, assoc_kind, trait_def_id) + .find_by_ident_and_kind(self.tcx(), assoc_ident, assoc_kind, trait_def_id) .is_some() } @@ -964,7 +964,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } /// Search for a trait bound on a type parameter whose trait defines the associated item - /// given by `assoc_name` and `kind`. + /// given by `assoc_ident` and `kind`. /// /// This fails if there is no such bound in the list of candidates or if there are multiple /// candidates in which case it reports ambiguity. @@ -976,13 +976,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ty_param_def_id: LocalDefId, ty_param_span: Span, kind: ty::AssocKind, - assoc_name: Ident, + assoc_ident: Ident, span: Span, ) -> Result, ErrorGuaranteed> { - debug!(?ty_param_def_id, ?assoc_name, ?span); + debug!(?ty_param_def_id, ?assoc_ident, ?span); let tcx = self.tcx(); - let predicates = &self.probe_ty_param_bounds(span, ty_param_def_id, assoc_name); + let predicates = &self.probe_ty_param_bounds(span, ty_param_def_id, assoc_ident); debug!("predicates={:#?}", predicates); self.probe_single_bound_for_assoc_item( @@ -990,17 +990,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let trait_refs = predicates .iter_identity_copied() .filter_map(|(p, _)| Some(p.as_trait_clause()?.map_bound(|t| t.trait_ref))); - traits::transitive_bounds_that_define_assoc_item(tcx, trait_refs, assoc_name) + traits::transitive_bounds_that_define_assoc_item(tcx, trait_refs, assoc_ident) }, AssocItemQSelf::TyParam(ty_param_def_id, ty_param_span), kind, - assoc_name, + assoc_ident, span, None, ) } - /// Search for a single trait bound whose trait defines the associated item given by `assoc_name`. + /// Search for a single trait bound whose trait defines the associated item given by + /// `assoc_ident`. /// /// This fails if there is no such bound in the list of candidates or if there are multiple /// candidates in which case it reports ambiguity. @@ -1010,7 +1011,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { all_candidates: impl Fn() -> I, qself: AssocItemQSelf, assoc_kind: ty::AssocKind, - assoc_name: Ident, + assoc_ident: Ident, span: Span, constraint: Option<&hir::AssocItemConstraint<'tcx>>, ) -> Result, ErrorGuaranteed> @@ -1020,7 +1021,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let tcx = self.tcx(); let mut matching_candidates = all_candidates().filter(|r| { - self.probe_trait_that_defines_assoc_item(r.def_id(), assoc_kind, assoc_name) + self.probe_trait_that_defines_assoc_item(r.def_id(), assoc_kind, assoc_ident) }); let Some(bound) = matching_candidates.next() else { @@ -1028,7 +1029,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { all_candidates, qself, assoc_kind, - assoc_name, + assoc_ident, span, constraint, ); @@ -1044,7 +1045,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let mut err = self.dcx().create_err(crate::errors::AmbiguousAssocItem { span, assoc_kind: assoc_kind_str, - assoc_name, + assoc_ident, qself: &qself_str, }); // Provide a more specific error code index entry for equality bindings. @@ -1065,13 +1066,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let bound_id = bound.def_id(); let bound_span = tcx .associated_items(bound_id) - .find_by_name_and_kind(tcx, assoc_name, assoc_kind, bound_id) + .find_by_ident_and_kind(tcx, assoc_ident, assoc_kind, bound_id) .and_then(|item| tcx.hir_span_if_local(item.def_id)); if let Some(bound_span) = bound_span { err.span_label( bound_span, - format!("ambiguous `{assoc_name}` from `{}`", bound.print_trait_sugared(),), + format!("ambiguous `{assoc_ident}` from `{}`", bound.print_trait_sugared(),), ); if let Some(constraint) = constraint { match constraint.kind { @@ -1087,7 +1088,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } // FIXME(#97583): This isn't syntactically well-formed! where_bounds.push(format!( - " T: {trait}::{assoc_name} = {term}", + " T: {trait}::{assoc_ident} = {term}", trait = bound.print_only_trait_path(), )); } @@ -1096,7 +1097,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } else { err.span_suggestion_verbose( - span.with_hi(assoc_name.span.lo()), + span.with_hi(assoc_ident.span.lo()), "use fully-qualified syntax to disambiguate", format!("<{qself_str} as {}>::", bound.print_only_trait_path()), Applicability::MaybeIncorrect, @@ -1104,7 +1105,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } else { err.note(format!( - "associated {assoc_kind_str} `{assoc_name}` could derive from `{}`", + "associated {assoc_kind_str} `{assoc_ident}` could derive from `{}`", bound.print_only_trait_path(), )); } @@ -2858,7 +2859,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let trait_ref = self.lower_impl_trait_ref(i.of_trait.as_ref()?, self.lower_ty(i.self_ty)); - let assoc = tcx.associated_items(trait_ref.def_id).find_by_name_and_kind( + let assoc = tcx.associated_items(trait_ref.def_id).find_by_ident_and_kind( tcx, *ident, ty::AssocKind::Fn, diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 865209b6a960..e5ab317685f9 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -397,7 +397,7 @@ impl<'a> State<'a> { self.pclose(); } hir::TyKind::BareFn(f) => { - self.print_ty_fn(f.abi, f.safety, f.decl, None, f.generic_params, f.param_names); + self.print_ty_fn(f.abi, f.safety, f.decl, None, f.generic_params, f.param_idents); } hir::TyKind::UnsafeBinder(unsafe_binder) => { self.print_unsafe_binder(unsafe_binder); @@ -473,14 +473,14 @@ impl<'a> State<'a> { self.maybe_print_comment(item.span.lo()); self.print_attrs_as_outer(self.attrs(item.hir_id())); match item.kind { - hir::ForeignItemKind::Fn(sig, arg_names, generics) => { + hir::ForeignItemKind::Fn(sig, arg_idents, generics) => { self.head(""); self.print_fn( sig.decl, sig.header, Some(item.ident.name), generics, - arg_names, + arg_idents, None, ); self.end(); // end head-ibox @@ -899,10 +899,10 @@ impl<'a> State<'a> { ident: Ident, m: &hir::FnSig<'_>, generics: &hir::Generics<'_>, - arg_names: &[Option], + arg_idents: &[Option], body_id: Option, ) { - self.print_fn(m.decl, m.header, Some(ident.name), generics, arg_names, body_id); + self.print_fn(m.decl, m.header, Some(ident.name), generics, arg_idents, body_id); } fn print_trait_item(&mut self, ti: &hir::TraitItem<'_>) { @@ -914,8 +914,8 @@ impl<'a> State<'a> { hir::TraitItemKind::Const(ty, default) => { self.print_associated_const(ti.ident, ti.generics, ty, default); } - hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(arg_names)) => { - self.print_method_sig(ti.ident, sig, ti.generics, arg_names, None); + hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(arg_idents)) => { + self.print_method_sig(ti.ident, sig, ti.generics, arg_idents, None); self.word(";"); } hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => { @@ -2122,7 +2122,7 @@ impl<'a> State<'a> { header: hir::FnHeader, name: Option, generics: &hir::Generics<'_>, - arg_names: &[Option], + arg_idents: &[Option], body_id: Option, ) { self.print_fn_header_info(header); @@ -2134,16 +2134,16 @@ impl<'a> State<'a> { self.print_generic_params(generics.params); self.popen(); - // Make sure we aren't supplied *both* `arg_names` and `body_id`. - assert!(arg_names.is_empty() || body_id.is_none()); + // Make sure we aren't supplied *both* `arg_idents` and `body_id`. + assert!(arg_idents.is_empty() || body_id.is_none()); let mut i = 0; let mut print_arg = |s: &mut Self, ty: Option<&hir::Ty<'_>>| { if i == 0 && decl.implicit_self.has_implicit_self() { s.print_implicit_self(&decl.implicit_self); } else { - if let Some(arg_name) = arg_names.get(i) { - if let Some(arg_name) = arg_name { - s.word(arg_name.to_string()); + if let Some(arg_ident) = arg_idents.get(i) { + if let Some(arg_ident) = arg_ident { + s.word(arg_ident.to_string()); s.word(":"); s.space(); } @@ -2452,7 +2452,7 @@ impl<'a> State<'a> { decl: &hir::FnDecl<'_>, name: Option, generic_params: &[hir::GenericParam<'_>], - arg_names: &[Option], + arg_idents: &[Option], ) { self.ibox(INDENT_UNIT); self.print_formal_generic_params(generic_params); @@ -2467,7 +2467,7 @@ impl<'a> State<'a> { }, name, generics, - arg_names, + arg_idents, None, ); self.end(); diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl index 872861d6289d..9e1b70f5767b 100644 --- a/compiler/rustc_hir_typeck/messages.ftl +++ b/compiler/rustc_hir_typeck/messages.ftl @@ -148,7 +148,7 @@ hir_typeck_never_type_fallback_flowing_into_unsafe_path = never type fallback af hir_typeck_never_type_fallback_flowing_into_unsafe_union_field = never type fallback affects this union access .help = specify the type explicitly -hir_typeck_no_associated_item = no {$item_kind} named `{$item_name}` found for {$ty_prefix} `{$ty_str}`{$trait_missing_method -> +hir_typeck_no_associated_item = no {$item_kind} named `{$item_ident}` found for {$ty_prefix} `{$ty_str}`{$trait_missing_method -> [true] {""} *[other] {" "}in the current scope } diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index b73cd26927a5..dfaa374592bc 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -727,7 +727,7 @@ pub(crate) struct NoAssociatedItem { #[primary_span] pub span: Span, pub item_kind: &'static str, - pub item_name: Ident, + pub item_ident: Ident, pub ty_prefix: Cow<'static, str>, pub ty_str: String, pub trait_missing_method: bool, diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index f4bd7ec701f8..81eb8510785b 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1136,7 +1136,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && let self_implicit = matches!(call_expr.kind, hir::ExprKind::MethodCall(..)) as usize && let Some(Some(arg)) = - self.tcx.fn_arg_names(fn_def_id).get(expected_idx.as_usize() + self_implicit) + self.tcx.fn_arg_idents(fn_def_id).get(expected_idx.as_usize() + self_implicit) && arg.name != kw::SelfLower { format!("/* {} */", arg.name) @@ -2619,7 +2619,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { is_method: bool, ) -> Option<(IndexVec, FnParam<'_>)>, &hir::Generics<'_>)> { - let (sig, generics, body_id, param_names) = match self.tcx.hir_get_if_local(def_id)? { + let (sig, generics, body_id, params) = match self.tcx.hir_get_if_local(def_id)? { hir::Node::TraitItem(&hir::TraitItem { generics, kind: hir::TraitItemKind::Fn(sig, trait_fn), @@ -2661,7 +2661,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None } }); - match (body_id, param_names) { + match (body_id, params) { (Some(_), Some(_)) | (None, None) => unreachable!(), (Some(body), None) => { let params = self.tcx.hir_body(body).params; @@ -2678,7 +2678,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { params.get(is_method as usize..params.len() - sig.decl.c_variadic as usize)?; debug_assert_eq!(params.len(), fn_inputs.len()); Some(( - fn_inputs.zip(params.iter().map(|&ident| FnParam::Name(ident))).collect(), + fn_inputs.zip(params.iter().map(|&ident| FnParam::Ident(ident))).collect(), generics, )) } @@ -2709,14 +2709,14 @@ impl<'tcx> Visitor<'tcx> for FindClosureArg<'tcx> { #[derive(Clone, Copy)] enum FnParam<'hir> { Param(&'hir hir::Param<'hir>), - Name(Option), + Ident(Option), } impl FnParam<'_> { fn span(&self) -> Span { match self { Self::Param(param) => param.span, - Self::Name(ident) => { + Self::Ident(ident) => { if let Some(ident) = ident { ident.span } else { @@ -2738,7 +2738,7 @@ impl FnParam<'_> { { Some(ident.name) } - FnParam::Name(ident) + FnParam::Ident(ident) if let Some(ident) = ident && ident.name != kw::Underscore => { diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index 4008021c3a85..ddfd27ccf6b7 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -534,12 +534,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Ok((def_kind, pick.item.def_id)) } - /// Finds item with name `item_name` defined in impl/trait `def_id` + /// Finds item with name `item_ident` defined in impl/trait `def_id` /// and return it, or `None`, if no such item was defined there. - fn associated_value(&self, def_id: DefId, item_name: Ident) -> Option { + fn associated_value(&self, def_id: DefId, item_ident: Ident) -> Option { self.tcx .associated_items(def_id) - .find_by_name_and_namespace(self.tcx, item_name, Namespace::ValueNS, def_id) + .find_by_ident_and_namespace(self.tcx, item_ident, Namespace::ValueNS, def_id) .copied() } } diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 246b23f11b68..67ffbd06f43c 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -584,7 +584,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, mut span: Span, rcvr_ty: Ty<'tcx>, - item_name: Ident, + item_ident: Ident, expr_id: hir::HirId, source: SelfSource<'tcx>, args: Option<&'tcx [hir::Expr<'tcx>]>, @@ -615,7 +615,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else if rcvr_ty.is_enum() { "variant or associated item" } else { - match (item_name.as_str().chars().next(), rcvr_ty.is_fresh_ty()) { + match (item_ident.as_str().chars().next(), rcvr_ty.is_fresh_ty()) { (Some(name), false) if name.is_lowercase() => "function or associated item", (Some(_), false) => "associated item", (Some(_), true) | (None, false) => "variant or associated item", @@ -630,7 +630,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rcvr_ty, source, span, - item_name, + item_ident, &short_ty_str, &mut ty_file, ) { @@ -642,13 +642,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { source, span, item_kind, - item_name, + item_ident, &short_ty_str, &mut ty_file, ) { return guar; } - span = item_name.span; + span = item_ident.span; // Don't show generic arguments when the method can't be found in any implementation (#81576). let mut ty_str_reported = ty_str.clone(); @@ -660,7 +660,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx .inherent_impls(adt_def.did()) .into_iter() - .any(|def_id| self.associated_value(*def_id, item_name).is_some()) + .any(|def_id| self.associated_value(*def_id, item_ident).is_some()) } else { false } @@ -677,14 +677,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let is_write = sugg_span.ctxt().outer_expn_data().macro_def_id.is_some_and(|def_id| { tcx.is_diagnostic_item(sym::write_macro, def_id) || tcx.is_diagnostic_item(sym::writeln_macro, def_id) - }) && item_name.name == sym::write_fmt; + }) && item_ident.name == sym::write_fmt; let mut err = if is_write && let SelfSource::MethodCall(rcvr_expr) = source { self.suggest_missing_writer(rcvr_ty, rcvr_expr) } else { let mut err = self.dcx().create_err(NoAssociatedItem { span, item_kind, - item_name, + item_ident, ty_prefix: if trait_missing_method { // FIXME(mu001999) E0599 maybe not suitable here because it is for types Cow::from("trait") @@ -698,7 +698,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if is_method { self.suggest_use_shadowed_binding_with_method( source, - item_name, + item_ident, &ty_str_reported, &mut err, ); @@ -709,9 +709,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = ty.kind && let Res::SelfTyAlias { alias_to: impl_def_id, .. } = path.res && let DefKind::Impl { .. } = self.tcx.def_kind(impl_def_id) - && let Some(candidate) = tcx.associated_items(impl_def_id).find_by_name_and_kind( + && let Some(candidate) = tcx.associated_items(impl_def_id).find_by_ident_and_kind( self.tcx, - item_name, + item_ident, ty::AssocKind::Type, impl_def_id, ) @@ -721,7 +721,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { let def_path = tcx.def_path_str(adt_def.did()); err.span_suggestion( - ty.span.to(item_name.span), + ty.span.to(item_ident.span), format!("to construct a value of type `{}`, use the explicit path", def_path), def_path, Applicability::MachineApplicable, @@ -749,7 +749,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.find_builder_fn(&mut err, rcvr_ty, expr_id); } - if tcx.ty_is_opaque_future(rcvr_ty) && item_name.name == sym::poll { + if tcx.ty_is_opaque_future(rcvr_ty) && item_ident.name == sym::poll { err.help(format!( "method `poll` found on `Pin<&mut {ty_str}>`, \ see documentation for `std::pin::Pin`" @@ -764,7 +764,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { self.suggest_await_before_method( &mut err, - item_name, + item_ident, rcvr_ty, cal, span, @@ -786,7 +786,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let SelfSource::MethodCall(rcvr_expr) = source && let ty::RawPtr(ty, ptr_mutbl) = *rcvr_ty.kind() && let Ok(pick) = self.lookup_probe_for_diagnostic( - item_name, + item_ident, Ty::new_ref(tcx, ty::Region::new_error_misc(tcx), ty, ptr_mutbl), self.tcx.hir_expect_expr(self.tcx.parent_hir_id(rcvr_expr.hir_id)), ProbeScope::TraitsInScope, @@ -807,7 +807,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; err.span_note( tcx.def_span(pick.item.def_id), - format!("the method `{item_name}` exists on the type `{ty}`", ty = pick.self_ty), + format!("the method `{item_ident}` exists on the type `{ty}`", ty = pick.self_ty), ); let mut_str = ptr_mutbl.ptr_str(); err.note(format!( @@ -833,7 +833,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.suggest_fn_call(&mut err, rcvr_expr, rcvr_ty, |output_ty| { let call_expr = self.tcx.hir_expect_expr(self.tcx.parent_hir_id(rcvr_expr.hir_id)); let probe = self.lookup_probe_for_diagnostic( - item_name, + item_ident, output_ty, call_expr, ProbeScope::AllTraits, @@ -872,13 +872,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { static_candidates, rcvr_ty, source, - item_name, + item_ident, args, sugg_span, ); self.note_candidates_on_method_error( rcvr_ty, - item_name, + item_ident, source, args, span, @@ -889,7 +889,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else if static_candidates.len() > 1 { self.note_candidates_on_method_error( rcvr_ty, - item_name, + item_ident, source, args, span, @@ -903,7 +903,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut restrict_type_params = false; let mut suggested_derive = false; let mut unsatisfied_bounds = false; - if item_name.name == sym::count && self.is_slice_ty(rcvr_ty, span) { + if item_ident.name == sym::count && self.is_slice_ty(rcvr_ty, span) { let msg = "consider using `len` instead"; if let SelfSource::MethodCall(_expr) = source { err.span_suggestion_short(span, msg, "len", Applicability::MachineApplicable); @@ -1348,7 +1348,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let primary_message = primary_message.unwrap_or_else(|| { format!( - "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, \ + "the {item_kind} `{item_ident}` exists for {actual_prefix} `{ty_str}`, \ but its trait bounds were not satisfied" ) }); @@ -1378,7 +1378,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // `Pin<&Self>`. if targs.len() == 1 { let mut item_segment = hir::PathSegment::invalid(); - item_segment.ident = item_name; + item_segment.ident = item_ident; for t in [Ty::new_mut_ref, Ty::new_imm_ref, |_, _, t| t] { let new_args = tcx.mk_args_from_iter(targs.iter().map(|arg| match arg.as_type() { @@ -1422,9 +1422,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::Adt(adt, _) => self.tcx.is_lang_item(adt.did(), LangItem::String), _ => false, }; - if is_string_or_ref_str && item_name.name == sym::iter { + if is_string_or_ref_str && item_ident.name == sym::iter { err.span_suggestion_verbose( - item_name.span, + item_ident.span, "because of the in-memory representation of `&str`, to obtain \ an `Iterator` over each of its codepoint use method `chars`", "chars", @@ -1438,7 +1438,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .into_iter() .copied() .filter(|def_id| { - if let Some(assoc) = self.associated_value(*def_id, item_name) { + if let Some(assoc) = self.associated_value(*def_id, item_ident) { // Check for both mode is the same so we avoid suggesting // incorrect associated item. match (mode, assoc.fn_has_self_parameter, source) { @@ -1499,7 +1499,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If the method name is the name of a field with a function or closure type, // give a helping note that it has to be called as `(x.f)(...)`. if let SelfSource::MethodCall(expr) = source { - if !self.suggest_calling_field_as_fn(span, rcvr_ty, expr, item_name, &mut err) + if !self.suggest_calling_field_as_fn(span, rcvr_ty, expr, item_ident, &mut err) && similar_candidate.is_none() && !custom_span_label { @@ -1512,7 +1512,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let confusable_suggested = self.confusable_method_name( &mut err, rcvr_ty, - item_name, + item_ident, args.map(|args| { args.iter() .map(|expr| { @@ -1530,12 +1530,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { source, span, rcvr_ty, - item_name, + item_ident, expected.only_has_type(self), ); } - self.suggest_unwrapping_inner_self(&mut err, source, rcvr_ty, item_name); + self.suggest_unwrapping_inner_self(&mut err, source, rcvr_ty, item_ident); for (span, mut bounds) in bound_spans { if !tcx.sess.source_map().is_span_accessible(span) { @@ -1546,7 +1546,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let pre = if Some(span) == ty_span { ty_span.take(); format!( - "{item_kind} `{item_name}` not found for this {} because it ", + "{item_kind} `{item_ident}` not found for this {} because it ", rcvr_ty.prefix_string(self.tcx) ) } else { @@ -1566,7 +1566,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_label( span, format!( - "{item_kind} `{item_name}` not found for this {}", + "{item_kind} `{item_ident}` not found for this {}", rcvr_ty.prefix_string(self.tcx) ), ); @@ -1578,7 +1578,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &mut err, span, rcvr_ty, - item_name, + item_ident, args.map(|args| args.len() + 1), source, no_match_data.out_of_scope_traits.clone(), @@ -1595,7 +1595,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let adt_def = rcvr_ty.ty_adt_def().expect("enum is not an ADT"); if let Some(var_name) = edit_distance::find_best_match_for_name( &adt_def.variants().iter().map(|s| s.name).collect::>(), - item_name.name, + item_ident.name, None, ) && let Some(variant) = adt_def.variants().iter().find(|s| s.name == var_name) { @@ -1736,14 +1736,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if !find_candidate_for_method { self.lookup_segments_chain_for_no_match_method( &mut err, - item_name, + item_ident, item_kind, source, no_match_data, ); } - self.note_derefed_ty_has_method(&mut err, source, rcvr_ty, item_name, expected); + self.note_derefed_ty_has_method(&mut err, source, rcvr_ty, item_ident, expected); err.emit() } diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 885a7308bdc6..16c9e08c78d3 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -859,7 +859,7 @@ impl<'tcx> LateContext<'tcx> { ) -> Option> { let tcx = self.tcx; tcx.associated_items(trait_id) - .find_by_name_and_kind(tcx, Ident::from_str(name), ty::AssocKind::Type, trait_id) + .find_by_ident_and_kind(tcx, Ident::from_str(name), ty::AssocKind::Type, trait_id) .and_then(|assoc| { let proj = Ty::new_projection(tcx, assoc.def_id, [self_ty]); tcx.try_normalize_erasing_regions(self.typing_env(), proj).ok() diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index df567e80e556..a3e7c84584d3 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -423,11 +423,11 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase { } fn check_trait_item(&mut self, cx: &LateContext<'_>, item: &hir::TraitItem<'_>) { - if let hir::TraitItemKind::Fn(_, hir::TraitFn::Required(pnames)) = item.kind { + if let hir::TraitItemKind::Fn(_, hir::TraitFn::Required(param_idents)) = item.kind { self.check_snake_case(cx, "trait method", &item.ident); - for param_name in pnames { - if let Some(param_name) = param_name { - self.check_snake_case(cx, "variable", param_name); + for param_ident in param_idents { + if let Some(param_ident) = param_ident { + self.check_snake_case(cx, "variable", param_ident); } } } diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 4610a571da08..5798c4b38272 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1313,7 +1313,7 @@ impl<'a> CrateMetadataRef<'a> { fn get_fn_has_self_parameter(self, id: DefIndex, sess: &'a Session) -> bool { self.root .tables - .fn_arg_names + .fn_arg_idents .get(self, id) .expect("argument names not encoded for a function") .decode((self, sess)) diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 3dc82ce9d183..ecc2dcc5318d 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -286,7 +286,7 @@ provide! { tcx, def_id, other, cdata, rendered_const => { table } rendered_precise_capturing_args => { table } asyncness => { table_direct } - fn_arg_names => { table } + fn_arg_idents => { table } coroutine_kind => { table_direct } coroutine_for_closure => { table } coroutine_by_move_body_def_id => { table } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 167122a9793a..5741923dad97 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1469,7 +1469,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } if let DefKind::Fn | DefKind::AssocFn = def_kind { self.tables.asyncness.set_some(def_id.index, tcx.asyncness(def_id)); - record_array!(self.tables.fn_arg_names[def_id] <- tcx.fn_arg_names(def_id)); + record_array!(self.tables.fn_arg_idents[def_id] <- tcx.fn_arg_idents(def_id)); } if let Some(name) = tcx.intrinsic(def_id) { record!(self.tables.intrinsic[def_id] <- name); diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 96a1f65eeb0f..93125149fe63 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -451,7 +451,7 @@ define_tables! { rendered_const: Table>, rendered_precise_capturing_args: Table>>, asyncness: Table, - fn_arg_names: Table>>, + fn_arg_idents: Table>>, coroutine_kind: Table, coroutine_for_closure: Table, adt_destructor: Table>, diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs index 21ab06c98a77..7f2b9e9d4ffd 100644 --- a/compiler/rustc_middle/src/hir/map.rs +++ b/compiler/rustc_middle/src/hir/map.rs @@ -281,7 +281,7 @@ impl<'tcx> TyCtxt<'tcx> { }) } - pub fn hir_body_param_names(self, id: BodyId) -> impl Iterator> { + pub fn hir_body_param_idents(self, id: BodyId) -> impl Iterator> { self.hir_body(id).params.iter().map(|param| match param.pat.kind { PatKind::Binding(_, _, ident, _) => Some(ident), PatKind::Wild => Some(Ident::new(kw::Underscore, param.pat.span)), diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index 74369b6636c0..a3177a6416d0 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -215,9 +215,9 @@ pub fn provide(providers: &mut Providers) { let hir_id = tcx.local_def_id_to_hir_id(def_id); tcx.hir_opt_ident_span(hir_id) }; - providers.fn_arg_names = |tcx, def_id| { + providers.fn_arg_idents = |tcx, def_id| { if let Some(body_id) = tcx.hir_node_by_def_id(def_id).body_id() { - tcx.arena.alloc_from_iter(tcx.hir_body_param_names(body_id)) + tcx.arena.alloc_from_iter(tcx.hir_body_param_idents(body_id)) } else if let Node::TraitItem(&TraitItem { kind: TraitItemKind::Fn(_, TraitFn::Required(idents)), .. @@ -231,7 +231,7 @@ pub fn provide(providers: &mut Providers) { } else { span_bug!( tcx.hir_span(tcx.local_def_id_to_hir_id(def_id)), - "fn_arg_names: unexpected item {:?}", + "fn_arg_idents: unexpected item {:?}", def_id ); } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index a1df27ac788c..190a6ada4b88 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1435,8 +1435,8 @@ rustc_queries! { desc { |tcx| "computing target features for inline asm of `{}`", tcx.def_path_str(def_id) } } - query fn_arg_names(def_id: DefId) -> &'tcx [Option] { - desc { |tcx| "looking up function parameter names for `{}`", tcx.def_path_str(def_id) } + query fn_arg_idents(def_id: DefId) -> &'tcx [Option] { + desc { |tcx| "looking up function parameter idents for `{}`", tcx.def_path_str(def_id) } separate_provide_extern } diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs index ce4c08aa485e..4a4b6728cc4f 100644 --- a/compiler/rustc_middle/src/ty/assoc.rs +++ b/compiler/rustc_middle/src/ty/assoc.rs @@ -199,8 +199,8 @@ impl AssocItems { self.items.get_by_key(name) } - /// Returns the associated item with the given name and `AssocKind`, if one exists. - pub fn find_by_name_and_kind( + /// Returns the associated item with the given ident and `AssocKind`, if one exists. + pub fn find_by_ident_and_kind( &self, tcx: TyCtxt<'_>, ident: Ident, @@ -212,8 +212,8 @@ impl AssocItems { .find(|item| tcx.hygienic_eq(ident, item.ident(tcx), parent_def_id)) } - /// Returns the associated item with the given name and any of `AssocKind`, if one exists. - pub fn find_by_name_and_kinds( + /// Returns the associated item with the given ident and any of `AssocKind`, if one exists. + pub fn find_by_ident_and_kinds( &self, tcx: TyCtxt<'_>, ident: Ident, @@ -221,11 +221,11 @@ impl AssocItems { kinds: &[AssocKind], parent_def_id: DefId, ) -> Option<&ty::AssocItem> { - kinds.iter().find_map(|kind| self.find_by_name_and_kind(tcx, ident, *kind, parent_def_id)) + kinds.iter().find_map(|kind| self.find_by_ident_and_kind(tcx, ident, *kind, parent_def_id)) } - /// Returns the associated item with the given name in the given `Namespace`, if one exists. - pub fn find_by_name_and_namespace( + /// Returns the associated item with the given ident in the given `Namespace`, if one exists. + pub fn find_by_ident_and_namespace( &self, tcx: TyCtxt<'_>, ident: Ident, diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 80f1bd7c6f46..6691266ee059 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1939,15 +1939,15 @@ impl<'tcx> TyCtxt<'tcx> { /// Hygienically compares a use-site name (`use_name`) for a field or an associated item with /// its supposed definition name (`def_name`). The method also needs `DefId` of the supposed /// definition's parent/scope to perform comparison. - pub fn hygienic_eq(self, use_name: Ident, def_name: Ident, def_parent_def_id: DefId) -> bool { - // We could use `Ident::eq` here, but we deliberately don't. The name + pub fn hygienic_eq(self, use_ident: Ident, def_ident: Ident, def_parent_def_id: DefId) -> bool { + // We could use `Ident::eq` here, but we deliberately don't. The ident // comparison fails frequently, and we want to avoid the expensive // `normalize_to_macros_2_0()` calls required for the span comparison whenever possible. - use_name.name == def_name.name - && use_name + use_ident.name == def_ident.name + && use_ident .span .ctxt() - .hygienic_eq(def_name.span.ctxt(), self.expn_that_defined(def_parent_def_id)) + .hygienic_eq(def_ident.span.ctxt(), self.expn_that_defined(def_parent_def_id)) } pub fn adjust_ident(self, mut ident: Ident, scope: DefId) -> Ident { diff --git a/compiler/rustc_monomorphize/src/mono_checks/move_check.rs b/compiler/rustc_monomorphize/src/mono_checks/move_check.rs index 838bfdab1ea5..74fdd9bcac16 100644 --- a/compiler/rustc_monomorphize/src/mono_checks/move_check.rs +++ b/compiler/rustc_monomorphize/src/mono_checks/move_check.rs @@ -174,7 +174,7 @@ impl<'tcx> MoveCheckVisitor<'tcx> { fn assoc_fn_of_type<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, fn_ident: Ident) -> Option { for impl_def_id in tcx.inherent_impls(def_id) { - if let Some(new) = tcx.associated_items(impl_def_id).find_by_name_and_kind( + if let Some(new) = tcx.associated_items(impl_def_id).find_by_ident_and_kind( tcx, fn_ident, AssocKind::Fn, diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 6dc854758da5..56bc826c94f7 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -2550,7 +2550,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { .iter() .filter_map(|item| { let parent_module = self.opt_local_def_id(item.parent_module)?.to_def_id(); - Some(StrippedCfgItem { parent_module, name: item.name, cfg: item.cfg.clone() }) + Some(StrippedCfgItem { + parent_module, + ident: item.ident, + cfg: item.cfg.clone(), + }) }) .collect::>(); local_items.as_slice() @@ -2558,12 +2562,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { self.tcx.stripped_cfg_items(module.krate) }; - for &StrippedCfgItem { parent_module, name, ref cfg } in symbols { - if parent_module != module || name.name != *segment { + for &StrippedCfgItem { parent_module, ident, ref cfg } in symbols { + if parent_module != module || ident.name != *segment { continue; } - let note = errors::FoundItemConfigureOut { span: name.span }; + let note = errors::FoundItemConfigureOut { span: ident.span }; err.subdiagnostic(note); if let MetaItemKind::List(nested) = &cfg.kind diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index b62bc6c45e0c..c2761bd2717f 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -2238,7 +2238,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { .get(&def_id) .is_some_and(|sig| sig.has_self), None => { - self.r.tcx.fn_arg_names(def_id).first().is_some_and(|&ident| { + self.r.tcx.fn_arg_idents(def_id).first().is_some_and(|&ident| { matches!(ident, Some(Ident { name: kw::SelfLower, .. })) }) } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 3ac66840d87d..e1476814d5c0 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1648,7 +1648,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { .filter_map(|item| { let parent_module = self.node_id_to_def_id.get(&item.parent_module)?.key().to_def_id(); - Some(StrippedCfgItem { parent_module, name: item.name, cfg: item.cfg }) + Some(StrippedCfgItem { parent_module, ident: item.ident, cfg: item.cfg }) }) .collect(), ); diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 9d6ae0aa9d13..e2f783d887e4 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -469,8 +469,8 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { self.proc_macros.push(id) } - fn append_stripped_cfg_item(&mut self, parent_node: NodeId, name: Ident, cfg: ast::MetaItem) { - self.stripped_cfg_items.push(StrippedCfgItem { parent_module: parent_node, name, cfg }); + fn append_stripped_cfg_item(&mut self, parent_node: NodeId, ident: Ident, cfg: ast::MetaItem) { + self.stripped_cfg_items.push(StrippedCfgItem { parent_module: parent_node, ident, cfg }); } fn registered_tools(&self) -> &RegisteredTools { diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 38fcba4ea625..3583bc8ad8ff 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -1988,7 +1988,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { { let closure: Vec<_> = self .tcx - .fn_arg_names(fn_def_id) + .fn_arg_idents(fn_def_id) .iter() .enumerate() .map(|(i, ident)| { @@ -5397,7 +5397,7 @@ fn point_at_assoc_type_restriction( ); } if let Some(new) = - tcx.associated_items(data.impl_or_alias_def_id).find_by_name_and_kind( + tcx.associated_items(data.impl_or_alias_def_id).find_by_ident_and_kind( tcx, Ident::with_dummy_span(name), ty::AssocKind::Type, diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index e0e09b53fc28..3a2b6974681b 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -497,7 +497,7 @@ pub(crate) fn build_impl( }; let trait_item = tcx .associated_items(associated_trait.def_id) - .find_by_name_and_kind( + .find_by_ident_and_kind( tcx, item.ident, assoc_kind, @@ -524,7 +524,7 @@ pub(crate) fn build_impl( if let Some(associated_trait) = associated_trait { let trait_item = tcx .associated_items(associated_trait.def_id) - .find_by_name_and_kind( + .find_by_ident_and_kind( tcx, item.ident(tcx), item.kind, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index c08ae168d692..5e02c165c258 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1088,7 +1088,7 @@ fn clean_fn_decl_legacy_const_generics(func: &mut Function, attrs: &[hir::Attrib enum FunctionArgs<'tcx> { Body(hir::BodyId), - Names(&'tcx [Option]), + Idents(&'tcx [Option]), } fn clean_function<'tcx>( @@ -1104,8 +1104,8 @@ fn clean_function<'tcx>( FunctionArgs::Body(body_id) => { clean_args_from_types_and_body_id(cx, sig.decl.inputs, body_id) } - FunctionArgs::Names(names) => { - clean_args_from_types_and_names(cx, sig.decl.inputs, names) + FunctionArgs::Idents(idents) => { + clean_args_from_types_and_names(cx, sig.decl.inputs, idents) } }; let decl = clean_fn_decl_with_args(cx, sig.decl, Some(&sig.header), args); @@ -1117,7 +1117,7 @@ fn clean_function<'tcx>( fn clean_args_from_types_and_names<'tcx>( cx: &mut DocContext<'tcx>, types: &[hir::Ty<'tcx>], - names: &[Option], + idents: &[Option], ) -> Arguments { fn nonempty_name(ident: &Option) -> Option { if let Some(ident) = ident @@ -1131,7 +1131,7 @@ fn clean_args_from_types_and_names<'tcx>( // If at least one argument has a name, use `_` as the name of unnamed // arguments. Otherwise omit argument names. - let default_name = if names.iter().any(|ident| nonempty_name(ident).is_some()) { + let default_name = if idents.iter().any(|ident| nonempty_name(ident).is_some()) { kw::Underscore } else { kw::Empty @@ -1143,7 +1143,7 @@ fn clean_args_from_types_and_names<'tcx>( .enumerate() .map(|(i, ty)| Argument { type_: clean_ty(ty, cx), - name: names.get(i).and_then(nonempty_name).unwrap_or(default_name), + name: idents.get(i).and_then(nonempty_name).unwrap_or(default_name), is_const: false, }) .collect(), @@ -1193,7 +1193,7 @@ fn clean_poly_fn_sig<'tcx>( did: Option, sig: ty::PolyFnSig<'tcx>, ) -> FnDecl { - let mut names = did.map_or(&[] as &[_], |did| cx.tcx.fn_arg_names(did)).iter(); + let mut names = did.map_or(&[] as &[_], |did| cx.tcx.fn_arg_idents(did)).iter(); // We assume all empty tuples are default return type. This theoretically can discard `-> ()`, // but shouldn't change any code meaning. @@ -1270,8 +1270,8 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext let m = clean_function(cx, sig, trait_item.generics, FunctionArgs::Body(body)); MethodItem(m, None) } - hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(names)) => { - let m = clean_function(cx, sig, trait_item.generics, FunctionArgs::Names(names)); + hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(idents)) => { + let m = clean_function(cx, sig, trait_item.generics, FunctionArgs::Idents(idents)); RequiredMethodItem(m) } hir::TraitItemKind::Type(bounds, Some(default)) => { @@ -2612,7 +2612,7 @@ fn clean_bare_fn_ty<'tcx>( .filter(|p| !is_elided_lifetime(p)) .map(|x| clean_generic_param(cx, None, x)) .collect(); - let args = clean_args_from_types_and_names(cx, bare_fn.decl.inputs, bare_fn.param_names); + let args = clean_args_from_types_and_names(cx, bare_fn.decl.inputs, bare_fn.param_idents); let decl = clean_fn_decl_with_args(cx, bare_fn.decl, None, args); (generic_params, decl) }); @@ -3148,8 +3148,8 @@ fn clean_maybe_renamed_foreign_item<'tcx>( let def_id = item.owner_id.to_def_id(); cx.with_param_env(def_id, |cx| { let kind = match item.kind { - hir::ForeignItemKind::Fn(sig, names, generics) => ForeignFunctionItem( - clean_function(cx, &sig, generics, FunctionArgs::Names(names)), + hir::ForeignItemKind::Fn(sig, idents, generics) => ForeignFunctionItem( + clean_function(cx, &sig, generics, FunctionArgs::Idents(idents)), sig.header.safety(), ), hir::ForeignItemKind::Static(ty, mutability, safety) => ForeignStaticItem( diff --git a/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs b/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs index adac2f27ea8c..ad18c7039eed 100644 --- a/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs +++ b/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs @@ -53,7 +53,7 @@ fn is_impl_not_trait_with_bool_out<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) - .not_trait() .filter(|trait_id| implements_trait(cx, ty, *trait_id, &[])) .and_then(|trait_id| { - cx.tcx.associated_items(trait_id).find_by_name_and_kind( + cx.tcx.associated_items(trait_id).find_by_ident_and_kind( cx.tcx, Ident::from_str("Output"), ty::AssocKind::Type, diff --git a/src/tools/clippy/clippy_lints/src/functions/renamed_function_params.rs b/src/tools/clippy/clippy_lints/src/functions/renamed_function_params.rs index 041f6228fba2..4495aeb5953e 100644 --- a/src/tools/clippy/clippy_lints/src/functions/renamed_function_params.rs +++ b/src/tools/clippy/clippy_lints/src/functions/renamed_function_params.rs @@ -22,8 +22,8 @@ pub(super) fn check_impl_item(cx: &LateContext<'_>, item: &ImplItem<'_>, ignored && let Some(did) = trait_item_def_id_of_impl(items, item.owner_id) && !is_from_ignored_trait(trait_ref, ignored_traits) { - let mut param_idents_iter = cx.tcx.hir_body_param_names(body_id); - let mut default_param_idents_iter = cx.tcx.fn_arg_names(did).iter().copied(); + let mut param_idents_iter = cx.tcx.hir_body_param_idents(body_id); + let mut default_param_idents_iter = cx.tcx.fn_arg_idents(did).iter().copied(); let renames = RenamedFnArgs::new(&mut default_param_idents_iter, &mut param_idents_iter); if !renames.0.is_empty() { diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs index 56ff7e2c61b2..239ee6c729fb 100644 --- a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs @@ -238,7 +238,7 @@ fn is_contains_sig(cx: &LateContext<'_>, call_id: HirId, iter_expr: &Expr<'_>) - .instantiate_bound_regions_with_erased(sig.rebind(search_ty)) .kind() && let Some(iter_trait) = cx.tcx.get_diagnostic_item(sym::Iterator) - && let Some(iter_item) = cx.tcx.associated_items(iter_trait).find_by_name_and_kind( + && let Some(iter_item) = cx.tcx.associated_items(iter_trait).find_by_ident_and_kind( cx.tcx, Ident::with_dummy_span(sym::Item), AssocKind::Type, diff --git a/src/tools/clippy/clippy_utils/src/ty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/mod.rs index 6fdf4c244f8d..29cbf62c3d4c 100644 --- a/src/tools/clippy/clippy_utils/src/ty/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ty/mod.rs @@ -1109,7 +1109,7 @@ pub fn make_projection<'tcx>( assoc_ty: Symbol, args: GenericArgsRef<'tcx>, ) -> Option> { - let Some(assoc_item) = tcx.associated_items(container_id).find_by_name_and_kind( + let Some(assoc_item) = tcx.associated_items(container_id).find_by_ident_and_kind( tcx, Ident::with_dummy_span(assoc_ty), AssocKind::Type, diff --git a/tests/ui/resolve/dont-compute-arg-names-for-non-fn.rs b/tests/ui/resolve/dont-compute-arg-names-for-non-fn.rs index 20bbbff8fd20..4053ccdfbf14 100644 --- a/tests/ui/resolve/dont-compute-arg-names-for-non-fn.rs +++ b/tests/ui/resolve/dont-compute-arg-names-for-non-fn.rs @@ -3,7 +3,7 @@ extern crate foreign_trait_with_assoc; use foreign_trait_with_assoc::Foo; -// Make sure we don't try to call `fn_arg_names` on a non-fn item. +// Make sure we don't try to call `fn_arg_idents` on a non-fn item. impl Foo for Bar {} //~^ ERROR cannot find type `Bar` in this scope From 663a317c20652b9226350b6dde3aeee32532aaec Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 10 Apr 2025 09:39:21 +1000 Subject: [PATCH 285/606] Address review comments. --- .../rustc_borrowck/src/diagnostics/conflict_errors.rs | 2 +- compiler/rustc_expand/src/expand.rs | 2 +- compiler/rustc_hir/src/hir.rs | 2 +- compiler/rustc_middle/src/query/mod.rs | 2 +- compiler/rustc_middle/src/ty/assoc.rs | 9 ++++++--- compiler/rustc_middle/src/ty/mod.rs | 2 +- 6 files changed, 11 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index e77d0399b8c9..8a8ecc3b96e3 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -2500,7 +2500,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { ); let ty::Tuple(params) = tupled_params.kind() else { return }; - // Find the first argument with a matching type, get its ident + // Find the first argument with a matching type and get its identifier. let Some(this_name) = params.iter().zip(tcx.hir_body_param_idents(closure.body)).find_map( |(param_ty, ident)| { // FIXME: also support deref for stuff like `Rc` arguments diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 4a5b7b917064..1b539477d51e 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -1169,7 +1169,7 @@ trait InvocationCollectorNode: HasAttrs + HasNodeId + Sized { collector.cx.dcx().emit_err(RemoveNodeNotSupported { span, descr: Self::descr() }); } - /// All of the idents (items) declared by this node. + /// All of the identifiers (items) declared by this node. /// This is an approximation and should only be used for diagnostics. fn declared_idents(&self) -> Vec { vec![] diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 062193130b32..c9c4936c1564 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3399,7 +3399,7 @@ pub struct BareFnTy<'hir> { pub abi: ExternAbi, pub generic_params: &'hir [GenericParam<'hir>], pub decl: &'hir FnDecl<'hir>, - // `Option` because bare fn parameter idents are optional. We also end up + // `Option` because bare fn parameter identifiers are optional. We also end up // with `None` in some error cases, e.g. invalid parameter patterns. pub param_idents: &'hir [Option], } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 190a6ada4b88..1f4e024d5147 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1436,7 +1436,7 @@ rustc_queries! { } query fn_arg_idents(def_id: DefId) -> &'tcx [Option] { - desc { |tcx| "looking up function parameter idents for `{}`", tcx.def_path_str(def_id) } + desc { |tcx| "looking up function parameter identifiers for `{}`", tcx.def_path_str(def_id) } separate_provide_extern } diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs index 4a4b6728cc4f..e3d332036f1f 100644 --- a/compiler/rustc_middle/src/ty/assoc.rs +++ b/compiler/rustc_middle/src/ty/assoc.rs @@ -199,7 +199,8 @@ impl AssocItems { self.items.get_by_key(name) } - /// Returns the associated item with the given ident and `AssocKind`, if one exists. + /// Returns the associated item with the given identifier and `AssocKind`, if one exists. + /// The identifier is matched hygienically. pub fn find_by_ident_and_kind( &self, tcx: TyCtxt<'_>, @@ -212,7 +213,8 @@ impl AssocItems { .find(|item| tcx.hygienic_eq(ident, item.ident(tcx), parent_def_id)) } - /// Returns the associated item with the given ident and any of `AssocKind`, if one exists. + /// Returns the associated item with the given identifier and any of `AssocKind`, if one + /// exists. The identifier is matched hygienically. pub fn find_by_ident_and_kinds( &self, tcx: TyCtxt<'_>, @@ -224,7 +226,8 @@ impl AssocItems { kinds.iter().find_map(|kind| self.find_by_ident_and_kind(tcx, ident, *kind, parent_def_id)) } - /// Returns the associated item with the given ident in the given `Namespace`, if one exists. + /// Returns the associated item with the given identifier in the given `Namespace`, if one + /// exists. The identifier is matched hygienically. pub fn find_by_ident_and_namespace( &self, tcx: TyCtxt<'_>, diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 6691266ee059..a2b3acac3f26 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1940,7 +1940,7 @@ impl<'tcx> TyCtxt<'tcx> { /// its supposed definition name (`def_name`). The method also needs `DefId` of the supposed /// definition's parent/scope to perform comparison. pub fn hygienic_eq(self, use_ident: Ident, def_ident: Ident, def_parent_def_id: DefId) -> bool { - // We could use `Ident::eq` here, but we deliberately don't. The ident + // We could use `Ident::eq` here, but we deliberately don't. The identifier // comparison fails frequently, and we want to avoid the expensive // `normalize_to_macros_2_0()` calls required for the span comparison whenever possible. use_ident.name == def_ident.name From 4f7c02dda13492b1ef759048725c5a8bc46bc488 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Thu, 10 Apr 2025 09:38:21 +0800 Subject: [PATCH 286/606] compiletest: don't use stringly paths for `compose_and_run` --- src/tools/compiletest/src/runtest.rs | 38 +++++++++---------- .../compiletest/src/runtest/debuginfo.rs | 7 ++-- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 08fccb7c1de0..133266c15268 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -445,8 +445,8 @@ impl<'test> TestCx<'test> { self.compose_and_run( rustc, - self.config.compile_lib_path.to_str().unwrap(), - Some(aux_dir.to_str().unwrap()), + self.config.compile_lib_path.as_path(), + Some(aux_dir.as_path()), src, ) } @@ -1022,8 +1022,8 @@ impl<'test> TestCx<'test> { self.compose_and_run( test_client, - self.config.run_lib_path.to_str().unwrap(), - Some(aux_dir.to_str().unwrap()), + self.config.run_lib_path.as_path(), + Some(aux_dir.as_path()), None, ) } @@ -1037,8 +1037,8 @@ impl<'test> TestCx<'test> { self.compose_and_run( wr_run, - self.config.run_lib_path.to_str().unwrap(), - Some(aux_dir.to_str().unwrap()), + self.config.run_lib_path.as_path(), + Some(aux_dir.as_path()), None, ) } @@ -1052,8 +1052,8 @@ impl<'test> TestCx<'test> { self.compose_and_run( program, - self.config.run_lib_path.to_str().unwrap(), - Some(aux_dir.to_str().unwrap()), + self.config.run_lib_path.as_path(), + Some(aux_dir.as_path()), None, ) } @@ -1199,8 +1199,8 @@ impl<'test> TestCx<'test> { self.props.unset_rustc_env.iter().fold(&mut rustc, Command::env_remove); self.compose_and_run( rustc, - self.config.compile_lib_path.to_str().unwrap(), - Some(aux_dir.to_str().unwrap()), + self.config.compile_lib_path.as_path(), + Some(aux_dir.as_path()), input, ) } @@ -1221,8 +1221,7 @@ impl<'test> TestCx<'test> { rustc.args(&["--crate-type", "rlib"]); rustc.arg("-Cpanic=abort"); - let res = - self.compose_and_run(rustc, self.config.compile_lib_path.to_str().unwrap(), None, None); + let res = self.compose_and_run(rustc, self.config.compile_lib_path.as_path(), None, None); if !res.status.success() { self.fatal_proc_rec( &format!( @@ -1334,8 +1333,8 @@ impl<'test> TestCx<'test> { let auxres = aux_cx.compose_and_run( aux_rustc, - aux_cx.config.compile_lib_path.to_str().unwrap(), - Some(aux_dir.to_str().unwrap()), + aux_cx.config.compile_lib_path.as_path(), + Some(aux_dir.as_path()), None, ); if !auxres.status.success() { @@ -1375,8 +1374,8 @@ impl<'test> TestCx<'test> { fn compose_and_run( &self, mut command: Command, - lib_path: &str, - aux_path: Option<&str>, + lib_path: &Path, + aux_path: Option<&Path>, input: Option, ) -> ProcRes { let cmdline = { @@ -1808,7 +1807,7 @@ impl<'test> TestCx<'test> { } } - fn make_cmdline(&self, command: &Command, libpath: &str) -> String { + fn make_cmdline(&self, command: &Command, libpath: &Path) -> String { use crate::util; // Linux and mac don't require adjusting the library search path @@ -1821,7 +1820,7 @@ impl<'test> TestCx<'test> { format!("{}=\"{}\"", util::lib_path_env_var(), util::make_new_path(path)) } - format!("{} {:?}", lib_path_cmd_prefix(libpath), command) + format!("{} {:?}", lib_path_cmd_prefix(libpath.to_str().unwrap()), command) } } @@ -1982,7 +1981,8 @@ impl<'test> TestCx<'test> { // Add custom flags supplied by the `filecheck-flags:` test header. filecheck.args(&self.props.filecheck_flags); - self.compose_and_run(filecheck, "", None, None) + // FIXME(jieyouxu): don't pass an empty Path + self.compose_and_run(filecheck, Path::new(""), None, None) } fn charset() -> &'static str { diff --git a/src/tools/compiletest/src/runtest/debuginfo.rs b/src/tools/compiletest/src/runtest/debuginfo.rs index 170b8a809968..50e733cd31b6 100644 --- a/src/tools/compiletest/src/runtest/debuginfo.rs +++ b/src/tools/compiletest/src/runtest/debuginfo.rs @@ -104,7 +104,7 @@ impl TestCx<'_> { let debugger_run_result = self.compose_and_run( cdb, - self.config.run_lib_path.to_str().unwrap(), + self.config.run_lib_path.as_path(), None, // aux_path None, // input ); @@ -241,7 +241,8 @@ impl TestCx<'_> { let cmdline = { let mut gdb = Command::new(&format!("{}-gdb", self.config.target)); gdb.args(debugger_opts); - let cmdline = self.make_cmdline(&gdb, ""); + // FIXME(jieyouxu): don't pass an empty Path + let cmdline = self.make_cmdline(&gdb, Path::new("")); logv(self.config, format!("executing {}", cmdline)); cmdline }; @@ -340,7 +341,7 @@ impl TestCx<'_> { gdb.args(debugger_opts).env("PYTHONPATH", pythonpath); debugger_run_result = - self.compose_and_run(gdb, self.config.run_lib_path.to_str().unwrap(), None, None); + self.compose_and_run(gdb, self.config.run_lib_path.as_path(), None, None); } if !debugger_run_result.status.success() { From 3cb9966235a981cfea1bbf2536ebd5021bcbca5e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 10 Apr 2025 11:49:50 +1000 Subject: [PATCH 287/606] Add a HIR pretty printing test for delegation. Note that some of the output is currently bogus, with missing params and args: ``` fn add(: _, : _) -> _ { m::add(, ) } ``` The next commit will fix this. --- tests/pretty/hir-delegation.pp | 23 +++++++++++++++++++++++ tests/pretty/hir-delegation.rs | 22 ++++++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 tests/pretty/hir-delegation.pp create mode 100644 tests/pretty/hir-delegation.rs diff --git a/tests/pretty/hir-delegation.pp b/tests/pretty/hir-delegation.pp new file mode 100644 index 000000000000..1dc83ed635c4 --- /dev/null +++ b/tests/pretty/hir-delegation.pp @@ -0,0 +1,23 @@ +//@ pretty-compare-only +//@ pretty-mode:hir +//@ pp-exact:hir-delegation.pp + +#![allow(incomplete_features)]#![feature(fn_delegation)] +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; + +fn b(e: C) { } + +trait G { + fn b(: _) -> _ { b({ }) } +} + +mod m { + fn add(a: u32, b: u32) -> u32 { a + b } +} + +fn add(: _, : _) -> _ { m::add(, ) } + +fn main() { { let _ = add(1, 2); }; } diff --git a/tests/pretty/hir-delegation.rs b/tests/pretty/hir-delegation.rs new file mode 100644 index 000000000000..9e351a1e32f3 --- /dev/null +++ b/tests/pretty/hir-delegation.rs @@ -0,0 +1,22 @@ +//@ pretty-compare-only +//@ pretty-mode:hir +//@ pp-exact:hir-delegation.pp + +#![allow(incomplete_features)] +#![feature(fn_delegation)] + +fn b(e: C) {} + +trait G { + reuse b {} +} + +mod m { + pub fn add(a: u32, b: u32) -> u32 { a + b } +} + +reuse m::add; + +fn main() { + _ = add(1, 2); +} From 4207c786e752ed7495782c39b74917bbcaf438cf Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Tue, 8 Apr 2025 23:26:36 -0700 Subject: [PATCH 288/606] PR feedback --- library/core/src/array/iter/iter_inner.rs | 16 ++++++++-------- tests/codegen/issues/issue-101082.rs | 18 ++++++++++++------ 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/library/core/src/array/iter/iter_inner.rs b/library/core/src/array/iter/iter_inner.rs index f43d9e7ddd63..3c2343591f8c 100644 --- a/library/core/src/array/iter/iter_inner.rs +++ b/library/core/src/array/iter/iter_inner.rs @@ -31,9 +31,9 @@ impl PartialDrop for [MaybeUninit; N] { /// The real `array::IntoIter` stores a `PolymorphicIter<[MaybeUninit, N]>` /// which it unsizes to `PolymorphicIter<[MaybeUninit]>` to iterate. #[allow(private_bounds)] -pub(super) struct PolymorphicIter +pub(super) struct PolymorphicIter where - TAIL: PartialDrop, + DATA: PartialDrop, { /// The elements in `data` that have not been yielded yet. /// @@ -55,13 +55,13 @@ where /// - `data[alive]` is alive (i.e. contains valid elements) /// - `data[..alive.start]` and `data[alive.end..]` are dead (i.e. the /// elements were already read and must not be touched anymore!) - data: TAIL, + data: DATA, } #[allow(private_bounds)] -impl PolymorphicIter +impl PolymorphicIter where - TAIL: PartialDrop, + DATA: PartialDrop, { #[inline] pub(super) const fn len(&self) -> usize { @@ -70,9 +70,9 @@ where } #[allow(private_bounds)] -impl Drop for PolymorphicIter +impl Drop for PolymorphicIter where - TAIL: PartialDrop, + DATA: PartialDrop, { #[inline] fn drop(&mut self) { @@ -209,7 +209,7 @@ impl PolymorphicIter<[MaybeUninit]> { R: Try, { // `alive` is an `IndexRange`, not an arbitrary iterator, so we can - // trust that its `try_rfold` isn't going to do something weird like + // trust that its `try_fold` isn't going to do something weird like // call the fold-er multiple times for the same index. let data = &mut self.data; self.alive.try_fold(init, move |accum, idx| { diff --git a/tests/codegen/issues/issue-101082.rs b/tests/codegen/issues/issue-101082.rs index 89295da5bd10..96cdff64dda6 100644 --- a/tests/codegen/issues/issue-101082.rs +++ b/tests/codegen/issues/issue-101082.rs @@ -1,8 +1,16 @@ //@ compile-flags: -Copt-level=3 -//@ revisions: host x86-64-v3 +//@ revisions: host x86-64 x86-64-v3 //@ min-llvm-version: 20 -// This particular CPU regressed in #131563 +//@[host] ignore-x86_64 + +// Set the base cpu explicitly, in case the default has been changed. +//@[x86-64] only-x86_64 +//@[x86-64] compile-flags: -Ctarget-cpu=x86-64 + +// FIXME(cuviper) x86-64-v3 in particular regressed in #131563, and the workaround +// at the time still sometimes fails, so only verify it for the power-of-two size +// - https://github.com/llvm/llvm-project/issues/134735 //@[x86-64-v3] only-x86_64 //@[x86-64-v3] compile-flags: -Ctarget-cpu=x86-64-v3 @@ -12,16 +20,14 @@ pub fn test() -> usize { // CHECK-LABEL: @test( // host: ret {{i64|i32}} 165 + // x86-64: ret {{i64|i32}} 165 // FIXME: Now that this autovectorizes via a masked load, it doesn't actually // const-fold for certain widths. The `test_eight` case below shows that, yes, // what we're emitting *can* be const-folded, except that the way LLVM does it // for certain widths doesn't today. We should be able to put this back to // the same check after - // x86-64-v3: - // x86-64-v3: llvm.masked.load - // x86-64-v3: %[[R:.+]] = {{.+}}llvm.vector.reduce.add.v4i64 - // x86-64-v3: ret i64 %[[R]] + // x86-64-v3: masked.load let values = [23, 16, 54, 3, 60, 9]; let mut acc = 0; From 9bb1008e1d8da55be5e383b552e5e9e3774e37fe Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 10 Apr 2025 13:44:57 +1000 Subject: [PATCH 289/606] Avoid empty identifiers for delegate params and args. Instead use `argN`. The empty identifiers could flow to `Liveness::should_warn`, where they would trigger a bounds error. Fixes #139512. --- compiler/rustc_ast_lowering/src/delegation.rs | 15 ++++++++------- tests/pretty/hir-delegation.pp | 4 ++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs index 9899ee03a513..2296b05f69b4 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -47,7 +47,7 @@ use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::DefId; use rustc_middle::span_bug; use rustc_middle::ty::{Asyncness, ResolverAstLowering}; -use rustc_span::{Ident, Span}; +use rustc_span::{Ident, Span, Symbol}; use {rustc_ast as ast, rustc_hir as hir}; use super::{GenericArgsMode, ImplTraitContext, LoweringContext, ParamMode}; @@ -234,12 +234,13 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::FnSig { decl, header, span } } - fn generate_param(&mut self, span: Span) -> (hir::Param<'hir>, NodeId) { + fn generate_param(&mut self, idx: usize, 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 ident = Ident::with_dummy_span(Symbol::intern(&format!("arg{idx}"))); let pat = self.arena.alloc(hir::Pat { hir_id: pat_id, - kind: hir::PatKind::Binding(hir::BindingMode::NONE, pat_id, Ident::empty(), None), + kind: hir::PatKind::Binding(hir::BindingMode::NONE, pat_id, ident, None), span, default_binding_modes: false, }); @@ -247,9 +248,9 @@ impl<'hir> LoweringContext<'_, 'hir> { (hir::Param { hir_id: self.next_id(), pat, ty_span: span, span }, pat_node_id) } - fn generate_arg(&mut self, param_id: HirId, span: Span) -> hir::Expr<'hir> { + fn generate_arg(&mut self, idx: usize, param_id: HirId, span: Span) -> hir::Expr<'hir> { let segments = self.arena.alloc_from_iter(iter::once(hir::PathSegment { - ident: Ident::empty(), + ident: Ident::with_dummy_span(Symbol::intern(&format!("arg{idx}"))), hir_id: self.next_id(), res: Res::Local(param_id), args: None, @@ -273,7 +274,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let mut args: Vec> = Vec::with_capacity(param_count); for idx in 0..param_count { - let (param, pat_node_id) = this.generate_param(span); + let (param, pat_node_id) = this.generate_param(idx, span); parameters.push(param); let arg = if let Some(block) = block @@ -289,7 +290,7 @@ impl<'hir> LoweringContext<'_, 'hir> { this.ident_and_label_to_local_id.insert(pat_node_id, param.pat.hir_id.local_id); this.lower_target_expr(&block) } else { - this.generate_arg(param.pat.hir_id, span) + this.generate_arg(idx, param.pat.hir_id, span) }; args.push(arg); } diff --git a/tests/pretty/hir-delegation.pp b/tests/pretty/hir-delegation.pp index 1dc83ed635c4..872a6a45aede 100644 --- a/tests/pretty/hir-delegation.pp +++ b/tests/pretty/hir-delegation.pp @@ -11,13 +11,13 @@ extern crate std; fn b(e: C) { } trait G { - fn b(: _) -> _ { b({ }) } + fn b(arg0: _) -> _ { b({ }) } } mod m { fn add(a: u32, b: u32) -> u32 { a + b } } -fn add(: _, : _) -> _ { m::add(, ) } +fn add(arg0: _, arg1: _) -> _ { m::add(arg0, arg1) } fn main() { { let _ = add(1, 2); }; } From 57135c427386b875cb2d84eae49e3f9ba045342c Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Mon, 7 Apr 2025 09:49:53 +0800 Subject: [PATCH 290/606] compiletest: add `needs-crate-type` directive The `//@ needs-crate-type: $crate_types...` directive takes a comma-separated list of crate types that the target platform must support in order for the test to be run. --- src/tools/compiletest/src/common.rs | 31 +++++++++++++ src/tools/compiletest/src/directive-list.rs | 1 + src/tools/compiletest/src/header/needs.rs | 48 ++++++++++++++++++++- src/tools/compiletest/src/header/tests.rs | 38 ++++++++++++++++ src/tools/compiletest/src/lib.rs | 1 + 5 files changed, 117 insertions(+), 2 deletions(-) diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 36218b2f9045..6750b5288f42 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -395,6 +395,7 @@ pub struct Config { pub target_cfgs: OnceLock, pub builtin_cfg_names: OnceLock>, + pub supported_crate_types: OnceLock>, pub nocapture: bool, @@ -472,6 +473,11 @@ impl Config { self.builtin_cfg_names.get_or_init(|| builtin_cfg_names(self)) } + /// Get the list of crate types that the target platform supports. + pub fn supported_crate_types(&self) -> &HashSet { + self.supported_crate_types.get_or_init(|| supported_crate_types(self)) + } + pub fn has_threads(&self) -> bool { // Wasm targets don't have threads unless `-threads` is in the target // name, such as `wasm32-wasip1-threads`. @@ -745,6 +751,31 @@ fn builtin_cfg_names(config: &Config) -> HashSet { .collect() } +pub const KNOWN_CRATE_TYPES: &[&str] = + &["bin", "cdylib", "dylib", "lib", "proc-macro", "rlib", "staticlib"]; + +fn supported_crate_types(config: &Config) -> HashSet { + let crate_types: HashSet<_> = rustc_output( + config, + &["--target", &config.target, "--print=supported-crate-types", "-Zunstable-options"], + Default::default(), + ) + .lines() + .map(|l| l.to_string()) + .collect(); + + for crate_type in crate_types.iter() { + assert!( + KNOWN_CRATE_TYPES.contains(&crate_type.as_str()), + "unexpected crate type `{}`: known crate types are {:?}", + crate_type, + KNOWN_CRATE_TYPES + ); + } + + crate_types +} + fn rustc_output(config: &Config, args: &[&str], envs: HashMap) -> String { let mut command = Command::new(&config.rustc_path); add_dylib_path(&mut command, iter::once(&config.compile_lib_path)); diff --git a/src/tools/compiletest/src/directive-list.rs b/src/tools/compiletest/src/directive-list.rs index 44d9c0330f76..086a8a67456f 100644 --- a/src/tools/compiletest/src/directive-list.rs +++ b/src/tools/compiletest/src/directive-list.rs @@ -133,6 +133,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "min-llvm-version", "min-system-llvm-version", "needs-asm-support", + "needs-crate-type", "needs-deterministic-layouts", "needs-dlltool", "needs-dynamic-linking", diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs index 12f0790fb104..2ace40c490bf 100644 --- a/src/tools/compiletest/src/header/needs.rs +++ b/src/tools/compiletest/src/header/needs.rs @@ -1,4 +1,4 @@ -use crate::common::{Config, KNOWN_TARGET_HAS_ATOMIC_WIDTHS, Sanitizer}; +use crate::common::{Config, KNOWN_CRATE_TYPES, KNOWN_TARGET_HAS_ATOMIC_WIDTHS, Sanitizer}; use crate::header::{IgnoreDecision, llvm_has_libzstd}; pub(super) fn handle_needs( @@ -6,7 +6,7 @@ pub(super) fn handle_needs( config: &Config, ln: &str, ) -> IgnoreDecision { - // Note thet we intentionally still put the needs- prefix here to make the file show up when + // Note that we intentionally still put the needs- prefix here to make the file show up when // grepping for a directive name, even though we could technically strip that. let needs = &[ Need { @@ -224,6 +224,50 @@ pub(super) fn handle_needs( } } + // FIXME(jieyouxu): share multi-value directive logic with `needs-target-has-atomic` above. + if name == "needs-crate-type" { + let Some(rest) = rest else { + return IgnoreDecision::Error { + message: + "expected `needs-crate-type` to have a comma-separated list of crate types" + .to_string(), + }; + }; + + // Expect directive value to be a list of comma-separated crate-types. + let specified_crate_types = rest + .split(',') + .map(|crate_type| crate_type.trim()) + .map(ToString::to_string) + .collect::>(); + + for crate_type in &specified_crate_types { + if !KNOWN_CRATE_TYPES.contains(&crate_type.as_str()) { + return IgnoreDecision::Error { + message: format!( + "unknown crate type specified in `needs-crate-type`: `{crate_type}` is not \ + a known crate type, known values are `{:?}`", + KNOWN_CRATE_TYPES + ), + }; + } + } + + let satisfies_all_crate_types = specified_crate_types + .iter() + .all(|specified| config.supported_crate_types().contains(specified)); + if satisfies_all_crate_types { + return IgnoreDecision::Continue; + } else { + return IgnoreDecision::Ignore { + reason: format!( + "skipping test as target does not support all of the crate types `{:?}`", + specified_crate_types + ), + }; + } + } + if !name.starts_with("needs-") { return IgnoreDecision::Continue; } diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 1a796cdd7cd8..f3461f3c244f 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -902,3 +902,41 @@ fn test_rustc_abi() { assert!(!check_ignore(&config, "//@ ignore-rustc_abi-x86-sse2")); assert!(check_ignore(&config, "//@ only-rustc_abi-x86-sse2")); } + +#[test] +fn test_supported_crate_types() { + // Basic assumptions check on under-test compiler's `--print=supported-crate-types` output based + // on knowledge about the cherry-picked `x86_64-unknown-linux-gnu` and `wasm32-unknown-unknown` + // targets. Also smoke tests the `needs-crate-type` directive itself. + + use std::collections::HashSet; + + let config = cfg().target("x86_64-unknown-linux-gnu").build(); + assert_eq!( + config.supported_crate_types().iter().map(String::as_str).collect::>(), + HashSet::from(["bin", "cdylib", "dylib", "lib", "proc-macro", "rlib", "staticlib"]), + ); + assert!(!check_ignore(&config, "//@ needs-crate-type: rlib")); + assert!(!check_ignore(&config, "//@ needs-crate-type: dylib")); + assert!(!check_ignore( + &config, + "//@ needs-crate-type: bin, cdylib, dylib, lib, proc-macro, rlib, staticlib" + )); + + let config = cfg().target("wasm32-unknown-unknown").build(); + assert_eq!( + config.supported_crate_types().iter().map(String::as_str).collect::>(), + HashSet::from(["bin", "cdylib", "lib", "rlib", "staticlib"]), + ); + + // rlib is supported + assert!(!check_ignore(&config, "//@ needs-crate-type: rlib")); + // dylib is not + assert!(check_ignore(&config, "//@ needs-crate-type: dylib")); + // If multiple crate types are specified, then all specified crate types need to be supported. + assert!(check_ignore(&config, "//@ needs-crate-type: cdylib, dylib")); + assert!(check_ignore( + &config, + "//@ needs-crate-type: bin, cdylib, dylib, lib, proc-macro, rlib, staticlib" + )); +} diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 782f6e0f2d8d..8fa11c81c6ab 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -431,6 +431,7 @@ pub fn parse_config(args: Vec) -> Config { target_cfgs: OnceLock::new(), builtin_cfg_names: OnceLock::new(), + supported_crate_types: OnceLock::new(), nocapture: matches.opt_present("no-capture"), From 5fe7712a109941b205899e9bb929d15b040d9720 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Mon, 7 Apr 2025 13:18:03 +0800 Subject: [PATCH 291/606] rustc-dev-guide: document `needs-crate-type` --- src/doc/rustc-dev-guide/src/tests/directives.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/tests/directives.md b/src/doc/rustc-dev-guide/src/tests/directives.md index 8e4a710178ed..7ed583c1007d 100644 --- a/src/doc/rustc-dev-guide/src/tests/directives.md +++ b/src/doc/rustc-dev-guide/src/tests/directives.md @@ -191,8 +191,13 @@ settings: specified atomic widths, e.g. the test with `//@ needs-target-has-atomic: 8, 16, ptr` will only run if it supports the comma-separated list of atomic widths. -- `needs-dynamic-linking` - ignores if target does not support dynamic linking +- `needs-dynamic-linking` — ignores if target does not support dynamic linking (which is orthogonal to it being unable to create `dylib` and `cdylib` crate types) +- `needs-crate-type` — ignores if target platform does not support one or more + of the comma-delimited list of specified crate types. For example, + `//@ needs-crate-type: cdylib, proc-macro` will cause the test to be ignored + on `wasm32-unknown-unknown` target because the target does not support the + `proc-macro` crate type. The following directives will check LLVM support: From c615d1074300f450c435abbf718969bf4f416f98 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Mon, 7 Apr 2025 13:29:13 +0800 Subject: [PATCH 292/606] tests: use specific-purpose `needs-crate-type` over `ignore-$target` directives Not all existing tests are converted, I only updated ones that I can easily find via directive comments. --- .../invalid-compile-flags/crate-type-flag.rs | 9 ++--- tests/ui/linkage-attr/issue-12133-3.rs | 3 +- .../lint-non-snake-case-crate.cdylib_.stderr | 4 +-- .../lint-non-snake-case-crate.dylib_.stderr | 4 +-- .../lint-non-snake-case-crate.lib_.stderr | 4 +-- ...nt-non-snake-case-crate.proc_macro_.stderr | 4 +-- .../lint-non-snake-case-crate.rlib_.stderr | 4 +-- .../lint-non-snake-case-crate.rs | 33 +++++++++---------- ...int-non-snake-case-crate.staticlib_.stderr | 4 +-- .../abort-link-to-unwind-dylib.rs | 4 +-- 10 files changed, 33 insertions(+), 40 deletions(-) diff --git a/tests/ui/invalid-compile-flags/crate-type-flag.rs b/tests/ui/invalid-compile-flags/crate-type-flag.rs index 8ccce97f7bfa..61b35cf8c64f 100644 --- a/tests/ui/invalid-compile-flags/crate-type-flag.rs +++ b/tests/ui/invalid-compile-flags/crate-type-flag.rs @@ -3,8 +3,6 @@ //! //! This test does not try to check if the output artifacts are valid. -// FIXME(#132309): add a proper `supports-crate-type` directive. - // Single valid crate types should pass //@ revisions: lib rlib staticlib dylib cdylib bin proc_dash_macro @@ -17,19 +15,18 @@ //@[staticlib] compile-flags: --crate-type=staticlib //@[staticlib] check-pass -//@[dylib] ignore-musl (dylib is supported, but musl libc is statically linked by default) -//@[dylib] ignore-wasm (dylib is not supported) +//@[dylib] needs-crate-type: dylib //@[dylib] compile-flags: --crate-type=dylib //@[dylib] check-pass -//@[cdylib] ignore-musl (cdylib is supported, but musl libc is statically linked by default) +//@[cdylib] needs-crate-type: cdylib //@[cdylib] compile-flags: --crate-type=cdylib //@[cdylib] check-pass //@[bin] compile-flags: --crate-type=bin //@[bin] check-pass -//@[proc_dash_macro] ignore-wasm (proc-macro is not supported) +//@[proc_dash_macro] needs-crate-type: proc-macro //@[proc_dash_macro] needs-unwind (panic=abort causes warning to be emitted) //@[proc_dash_macro] compile-flags: --crate-type=proc-macro //@[proc_dash_macro] check-pass diff --git a/tests/ui/linkage-attr/issue-12133-3.rs b/tests/ui/linkage-attr/issue-12133-3.rs index 473d5774c162..df1b0b2f728e 100644 --- a/tests/ui/linkage-attr/issue-12133-3.rs +++ b/tests/ui/linkage-attr/issue-12133-3.rs @@ -2,8 +2,7 @@ //@ aux-build:issue-12133-rlib.rs //@ aux-build:issue-12133-dylib.rs //@ aux-build:issue-12133-dylib2.rs -//@ ignore-wasm32 no dylib support -//@ ignore-musl +//@ needs-crate-type: dylib //@ needs-dynamic-linking diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.cdylib_.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.cdylib_.stderr index 1192b690e29c..a9c018867442 100644 --- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.cdylib_.stderr +++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.cdylib_.stderr @@ -1,11 +1,11 @@ error: crate `NonSnakeCase` should have a snake case name - --> $DIR/lint-non-snake-case-crate.rs:36:18 + --> $DIR/lint-non-snake-case-crate.rs:35:18 | LL | #![crate_name = "NonSnakeCase"] | ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case` | note: the lint level is defined here - --> $DIR/lint-non-snake-case-crate.rs:38:9 + --> $DIR/lint-non-snake-case-crate.rs:37:9 | LL | #![deny(non_snake_case)] | ^^^^^^^^^^^^^^ diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.dylib_.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.dylib_.stderr index 1192b690e29c..a9c018867442 100644 --- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.dylib_.stderr +++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.dylib_.stderr @@ -1,11 +1,11 @@ error: crate `NonSnakeCase` should have a snake case name - --> $DIR/lint-non-snake-case-crate.rs:36:18 + --> $DIR/lint-non-snake-case-crate.rs:35:18 | LL | #![crate_name = "NonSnakeCase"] | ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case` | note: the lint level is defined here - --> $DIR/lint-non-snake-case-crate.rs:38:9 + --> $DIR/lint-non-snake-case-crate.rs:37:9 | LL | #![deny(non_snake_case)] | ^^^^^^^^^^^^^^ diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.lib_.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.lib_.stderr index 1192b690e29c..a9c018867442 100644 --- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.lib_.stderr +++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.lib_.stderr @@ -1,11 +1,11 @@ error: crate `NonSnakeCase` should have a snake case name - --> $DIR/lint-non-snake-case-crate.rs:36:18 + --> $DIR/lint-non-snake-case-crate.rs:35:18 | LL | #![crate_name = "NonSnakeCase"] | ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case` | note: the lint level is defined here - --> $DIR/lint-non-snake-case-crate.rs:38:9 + --> $DIR/lint-non-snake-case-crate.rs:37:9 | LL | #![deny(non_snake_case)] | ^^^^^^^^^^^^^^ diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.proc_macro_.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.proc_macro_.stderr index 1192b690e29c..a9c018867442 100644 --- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.proc_macro_.stderr +++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.proc_macro_.stderr @@ -1,11 +1,11 @@ error: crate `NonSnakeCase` should have a snake case name - --> $DIR/lint-non-snake-case-crate.rs:36:18 + --> $DIR/lint-non-snake-case-crate.rs:35:18 | LL | #![crate_name = "NonSnakeCase"] | ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case` | note: the lint level is defined here - --> $DIR/lint-non-snake-case-crate.rs:38:9 + --> $DIR/lint-non-snake-case-crate.rs:37:9 | LL | #![deny(non_snake_case)] | ^^^^^^^^^^^^^^ diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rlib_.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rlib_.stderr index 1192b690e29c..a9c018867442 100644 --- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rlib_.stderr +++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rlib_.stderr @@ -1,11 +1,11 @@ error: crate `NonSnakeCase` should have a snake case name - --> $DIR/lint-non-snake-case-crate.rs:36:18 + --> $DIR/lint-non-snake-case-crate.rs:35:18 | LL | #![crate_name = "NonSnakeCase"] | ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case` | note: the lint level is defined here - --> $DIR/lint-non-snake-case-crate.rs:38:9 + --> $DIR/lint-non-snake-case-crate.rs:37:9 | LL | #![deny(non_snake_case)] | ^^^^^^^^^^^^^^ diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rs b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rs index 6f701cd27c62..a63e9c5ddf24 100644 --- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rs +++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rs @@ -10,28 +10,27 @@ // But should fire on non-binary crates. -// FIXME(#132309): dylib crate type is not supported on wasm; we need a proper -// supports-crate-type directive. Also, needs-dynamic-linking should rule out -// musl since it supports neither dylibs nor cdylibs. -//@[dylib_] ignore-wasm -//@[dylib_] ignore-musl -//@[cdylib_] ignore-musl - -//@[dylib_] needs-dynamic-linking +//@[cdylib_] compile-flags: --crate-type=cdylib //@[cdylib_] needs-dynamic-linking +//@[cdylib_] needs-crate-type: cdylib + +//@[dylib_] compile-flags: --crate-type=dylib +//@[dylib_] needs-dynamic-linking +//@[dylib_] needs-crate-type: dylib + +//@[lib_] compile-flags: --crate-type=lib + //@[proc_macro_] force-host //@[proc_macro_] no-prefer-dynamic - -//@[cdylib_] compile-flags: --crate-type=cdylib -//@[dylib_] compile-flags: --crate-type=dylib -//@[lib_] compile-flags: --crate-type=lib //@[proc_macro_] compile-flags: --crate-type=proc-macro -//@[rlib_] compile-flags: --crate-type=rlib -//@[staticlib_] compile-flags: --crate-type=staticlib - -// The compiler may emit a warning that causes stderr output -// that contains a warning this test does not wish to check. +// The compiler may emit a warning that causes stderr output that contains a warning this test does +// not wish to check. //@[proc_macro_] needs-unwind +//@[proc_macro_] needs-crate-type: proc-macro + +//@[rlib_] compile-flags: --crate-type=rlib + +//@[staticlib_] compile-flags: --crate-type=staticlib #![crate_name = "NonSnakeCase"] //[cdylib_,dylib_,lib_,proc_macro_,rlib_,staticlib_]~^ ERROR crate `NonSnakeCase` should have a snake case name diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.staticlib_.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.staticlib_.stderr index 1192b690e29c..a9c018867442 100644 --- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.staticlib_.stderr +++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.staticlib_.stderr @@ -1,11 +1,11 @@ error: crate `NonSnakeCase` should have a snake case name - --> $DIR/lint-non-snake-case-crate.rs:36:18 + --> $DIR/lint-non-snake-case-crate.rs:35:18 | LL | #![crate_name = "NonSnakeCase"] | ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case` | note: the lint level is defined here - --> $DIR/lint-non-snake-case-crate.rs:38:9 + --> $DIR/lint-non-snake-case-crate.rs:37:9 | LL | #![deny(non_snake_case)] | ^^^^^^^^^^^^^^ diff --git a/tests/ui/panic-runtime/abort-link-to-unwind-dylib.rs b/tests/ui/panic-runtime/abort-link-to-unwind-dylib.rs index 8b782413f6a4..a691ceb566b0 100644 --- a/tests/ui/panic-runtime/abort-link-to-unwind-dylib.rs +++ b/tests/ui/panic-runtime/abort-link-to-unwind-dylib.rs @@ -1,9 +1,7 @@ //@ build-fail //@ compile-flags:-C panic=abort -C prefer-dynamic //@ needs-unwind -//@ ignore-musl - no dylibs here -//@ ignore-emscripten -//@ ignore-sgx no dynamic lib support +//@ needs-crate-type: dylib // This is a test where the local crate, compiled with `panic=abort`, links to // the standard library **dynamically** which is already linked against From 726e33f0e34b077334f1bd3f06f46dfa04ee65b1 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 10 Apr 2025 08:40:22 +0200 Subject: [PATCH 293/606] path: add more Windows tests --- src/tools/miri/tests/pass/path.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/tools/miri/tests/pass/path.rs b/src/tools/miri/tests/pass/path.rs index 299ee6cfe9dd..dbca0ea611f7 100644 --- a/src/tools/miri/tests/pass/path.rs +++ b/src/tools/miri/tests/pass/path.rs @@ -31,9 +31,14 @@ fn test_absolute() { assert_absolute_eq(r"\\?\PIPE\name", r"\\?\PIPE\name"); // Verbatim paths are always unchanged, no matter what. assert_absolute_eq(r"\\?\path.\to/file..", r"\\?\path.\to/file.."); - + // Trailing dot is removed here. assert_absolute_eq(r"C:\path..\to.\file.", r"C:\path..\to\file"); + // `..` is resolved here. + assert_absolute_eq(r"C:\path\to\..\file", r"C:\path\file"); + assert_absolute_eq(r"\\server\share\to\..\file", r"\\server\share\file"); + // Magic filename. assert_absolute_eq(r"COM1", r"\\.\COM1"); + assert_absolute_eq(r"C:\path\to\COM1", r"\\.\COM1"); } else { panic!("unsupported OS"); } From 9a26863acc2a8fdd6a21834fa418673ee33861e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Wed, 9 Apr 2025 17:47:32 +0200 Subject: [PATCH 294/606] Apply LTO when building rustc tools --- src/bootstrap/src/core/build_steps/tool.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index b58d279359e3..fc8d9d6d57b6 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -148,7 +148,9 @@ impl Step for ToolBuild { &self.extra_features, ); - if path.ends_with("/rustdoc") && + // Rustc tools (miri, clippy, cargo, rustfmt, rust-analyzer) + // could use the additional optimizations. + if self.mode == Mode::ToolRustc && // rustdoc is performance sensitive, so apply LTO to it. is_lto_stage(&self.compiler) { From 59a1f3314c15271154794566d11f55609180a74a Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Thu, 10 Apr 2025 08:18:32 +0800 Subject: [PATCH 295/606] compiletest: update to Edition 2024 --- src/tools/compiletest/Cargo.toml | 2 +- src/tools/compiletest/src/debuggers.rs | 4 ++- src/tools/compiletest/src/lib.rs | 10 +++++--- src/tools/compiletest/src/raise_fd_limit.rs | 13 +++++++--- src/tools/compiletest/src/read2.rs | 28 +++++++++++++++++---- 5 files changed, 43 insertions(+), 14 deletions(-) diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml index 06e618c2d254..3db34ed24cc2 100644 --- a/src/tools/compiletest/Cargo.toml +++ b/src/tools/compiletest/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "compiletest" version = "0.0.0" -edition = "2021" +edition = "2024" [lib] doctest = false diff --git a/src/tools/compiletest/src/debuggers.rs b/src/tools/compiletest/src/debuggers.rs index 20e3c8dfb9ee..5126e55aea12 100644 --- a/src/tools/compiletest/src/debuggers.rs +++ b/src/tools/compiletest/src/debuggers.rs @@ -40,7 +40,9 @@ pub(crate) fn configure_gdb(config: &Config) -> Option> { // // we should figure out how to lift this restriction! (run them all // on different ports allocated dynamically). - env::set_var("RUST_TEST_THREADS", "1"); + // + // SAFETY: at this point we are still single-threaded. + unsafe { env::set_var("RUST_TEST_THREADS", "1") }; } Some(Arc::new(Config { debugger: Some(Debugger::Gdb), ..config.clone() })) diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 782f6e0f2d8d..dfd678a7e2d6 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -529,10 +529,14 @@ pub fn run_tests(config: Arc) { } // Prevent issue #21352 UAC blocking .exe containing 'patch' etc. on Windows // If #11207 is resolved (adding manifest to .exe) this becomes unnecessary - env::set_var("__COMPAT_LAYER", "RunAsInvoker"); + // + // SAFETY: at this point we're still single-threaded. + unsafe { env::set_var("__COMPAT_LAYER", "RunAsInvoker") }; - // Let tests know which target they're running as - env::set_var("TARGET", &config.target); + // Let tests know which target they're running as. + // + // SAFETY: at this point we're still single-threaded. + unsafe { env::set_var("TARGET", &config.target) }; let mut configs = Vec::new(); if let Mode::DebugInfo = config.mode { diff --git a/src/tools/compiletest/src/raise_fd_limit.rs b/src/tools/compiletest/src/raise_fd_limit.rs index 7b12ba946b9e..653b125a6b41 100644 --- a/src/tools/compiletest/src/raise_fd_limit.rs +++ b/src/tools/compiletest/src/raise_fd_limit.rs @@ -6,6 +6,7 @@ /// This fixes issue #7772. #[cfg(target_vendor = "apple")] #[allow(non_camel_case_types)] +// FIXME(#139616): document caller contract. pub unsafe fn raise_fd_limit() { use std::ptr::null_mut; use std::{cmp, io}; @@ -21,8 +22,10 @@ pub unsafe fn raise_fd_limit() { let mut mib: [libc::c_int; 2] = [CTL_KERN, KERN_MAXFILESPERPROC]; let mut maxfiles: libc::c_int = 0; let mut size: libc::size_t = size_of_val(&maxfiles) as libc::size_t; - if libc::sysctl(&mut mib[0], 2, &mut maxfiles as *mut _ as *mut _, &mut size, null_mut(), 0) - != 0 + // FIXME(#139616): justify why this is sound. + if unsafe { + libc::sysctl(&mut mib[0], 2, &mut maxfiles as *mut _ as *mut _, &mut size, null_mut(), 0) + } != 0 { let err = io::Error::last_os_error(); panic!("raise_fd_limit: error calling sysctl: {}", err); @@ -30,7 +33,8 @@ pub unsafe fn raise_fd_limit() { // Fetch the current resource limits let mut rlim = libc::rlimit { rlim_cur: 0, rlim_max: 0 }; - if libc::getrlimit(libc::RLIMIT_NOFILE, &mut rlim) != 0 { + // FIXME(#139616): justify why this is sound. + if unsafe { libc::getrlimit(libc::RLIMIT_NOFILE, &mut rlim) } != 0 { let err = io::Error::last_os_error(); panic!("raise_fd_limit: error calling getrlimit: {}", err); } @@ -41,7 +45,8 @@ pub unsafe fn raise_fd_limit() { rlim.rlim_cur = cmp::min(maxfiles as libc::rlim_t, rlim.rlim_max); // Set our newly-increased resource limit. - if libc::setrlimit(libc::RLIMIT_NOFILE, &rlim) != 0 { + // FIXME(#139616): justify why this is sound. + if unsafe { libc::setrlimit(libc::RLIMIT_NOFILE, &rlim) } != 0 { let err = io::Error::last_os_error(); panic!("raise_fd_limit: error calling setrlimit: {}", err); } diff --git a/src/tools/compiletest/src/read2.rs b/src/tools/compiletest/src/read2.rs index 28ca5589992a..2213dd07160a 100644 --- a/src/tools/compiletest/src/read2.rs +++ b/src/tools/compiletest/src/read2.rs @@ -165,6 +165,7 @@ mod imp { mut err_pipe: ChildStderr, data: &mut dyn FnMut(bool, &mut Vec, bool), ) -> io::Result<()> { + // FIXME(#139616): justify why this is sound. unsafe { libc::fcntl(out_pipe.as_raw_fd(), libc::F_SETFL, libc::O_NONBLOCK); libc::fcntl(err_pipe.as_raw_fd(), libc::F_SETFL, libc::O_NONBLOCK); @@ -175,6 +176,7 @@ mod imp { let mut out = Vec::new(); let mut err = Vec::new(); + // FIXME(#139616): justify why this is sound. let mut fds: [libc::pollfd; 2] = unsafe { mem::zeroed() }; fds[0].fd = out_pipe.as_raw_fd(); fds[0].events = libc::POLLIN; @@ -185,6 +187,7 @@ mod imp { while nfds > 0 { // wait for either pipe to become readable using `select` + // FIXME(#139616): justify why this is sound. let r = unsafe { libc::poll(fds.as_mut_ptr(), nfds, -1) }; if r == -1 { let err = io::Error::last_os_error(); @@ -256,6 +259,7 @@ mod imp { port.add_handle(0, &out_pipe)?; port.add_handle(1, &err_pipe)?; + // FIXME(#139616): justify why this is sound. unsafe { let mut out_pipe = Pipe::new(out_pipe, &mut out); let mut err_pipe = Pipe::new(err_pipe, &mut err); @@ -284,18 +288,23 @@ mod imp { } impl<'a> Pipe<'a> { + // FIXME(#139616): document caller contract. unsafe fn new(p: P, dst: &'a mut Vec) -> Pipe<'a> { Pipe { dst, - pipe: NamedPipe::from_raw_handle(p.into_raw_handle()), + // FIXME(#139616): justify why this is sound. + pipe: unsafe { NamedPipe::from_raw_handle(p.into_raw_handle()) }, overlapped: Overlapped::zero(), done: false, } } + // FIXME(#139616): document caller contract. unsafe fn read(&mut self) -> io::Result<()> { - let dst = slice_to_end(self.dst); - match self.pipe.read_overlapped(dst, self.overlapped.raw()) { + // FIXME(#139616): justify why this is sound. + let dst = unsafe { slice_to_end(self.dst) }; + // FIXME(#139616): justify why this is sound. + match unsafe { self.pipe.read_overlapped(dst, self.overlapped.raw()) } { Ok(_) => Ok(()), Err(e) => { if e.raw_os_error() == Some(ERROR_BROKEN_PIPE.0 as i32) { @@ -308,15 +317,18 @@ mod imp { } } + // FIXME(#139616): document caller contract. unsafe fn complete(&mut self, status: &CompletionStatus) { let prev = self.dst.len(); - self.dst.set_len(prev + status.bytes_transferred() as usize); + // FIXME(#139616): justify why this is sound. + unsafe { self.dst.set_len(prev + status.bytes_transferred() as usize) }; if status.bytes_transferred() == 0 { self.done = true; } } } + // FIXME(#139616): document caller contract. unsafe fn slice_to_end(v: &mut Vec) -> &mut [u8] { if v.capacity() == 0 { v.reserve(16); @@ -324,6 +336,12 @@ mod imp { if v.capacity() == v.len() { v.reserve(1); } - slice::from_raw_parts_mut(v.as_mut_ptr().offset(v.len() as isize), v.capacity() - v.len()) + // FIXME(#139616): justify why this is sound. + unsafe { + slice::from_raw_parts_mut( + v.as_mut_ptr().offset(v.len() as isize), + v.capacity() - v.len(), + ) + } } } From 673012faf7085d426d6598b8e445ad8630921723 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 10 Apr 2025 07:12:12 +0000 Subject: [PATCH 296/606] Some performance shenanigans --- compiler/rustc_hir_typeck/src/coercion.rs | 69 +++++++++++++---------- 1 file changed, 40 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 4f95d20251f2..ec198c252975 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -163,12 +163,18 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { &self, a: Ty<'tcx>, b: Ty<'tcx>, - mut adjustments: Vec>, + adjustments: impl IntoIterator>, final_adjustment: Adjust, ) -> CoerceResult<'tcx> { self.unify_raw(a, b).and_then(|InferOk { value: ty, obligations }| { - adjustments.push(Adjustment { target: ty, kind: final_adjustment }); - success(adjustments, ty, obligations) + success( + adjustments + .into_iter() + .chain(std::iter::once(Adjustment { target: ty, kind: final_adjustment })) + .collect(), + ty, + obligations, + ) }) } @@ -579,15 +585,18 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // We only have the latter, so we use an inference variable // for the former and let type inference do the rest. let coerce_target = self.next_ty_var(self.cause.span); - let mut coercion = self.unify_and( - coerce_target, - target, - match reborrow { - None => vec![], - Some((ref deref, ref autoref)) => vec![deref.clone(), autoref.clone()], - }, - Adjust::Pointer(PointerCoercion::Unsize), - )?; + + let mut coercion = match reborrow { + None => { + self.unify_and(coerce_target, target, [], Adjust::Pointer(PointerCoercion::Unsize))? + } + Some((ref deref, ref autoref)) => self.unify_and( + coerce_target, + target, + [deref.clone(), autoref.clone()], + Adjust::Pointer(PointerCoercion::Unsize), + )?, + }; let mut selcx = traits::SelectionContext::new(self); @@ -810,7 +819,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // To complete the reborrow, we need to make sure we can unify the inner types, and if so we // add the adjustments. - self.unify_and(a, b, vec![], Adjust::ReborrowPin(mut_b)) + self.unify_and(a, b, [], Adjust::ReborrowPin(mut_b)) } fn coerce_from_safe_fn( @@ -827,22 +836,24 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { && hdr_b.safety.is_unsafe() { let unsafe_a = self.tcx.safe_to_unsafe_fn_ty(fn_ty_a); - let adjustments = match adjustment { - Some(kind) => { - vec![Adjustment { kind, target: Ty::new_fn_ptr(self.tcx, fn_ty_a) }] - } - None => vec![], - }; - self.unify_and( - unsafe_a, - b, - adjustments, - Adjust::Pointer(PointerCoercion::UnsafeFnPointer), - ) + match adjustment { + Some(kind) => self.unify_and( + unsafe_a, + b, + [Adjustment { kind, target: Ty::new_fn_ptr(self.tcx, fn_ty_a) }], + Adjust::Pointer(PointerCoercion::UnsafeFnPointer), + ), + None => self.unify_and( + unsafe_a, + b, + [], + Adjust::Pointer(PointerCoercion::UnsafeFnPointer), + ), + } } else { let a = Ty::new_fn_ptr(self.tcx, fn_ty_a); match adjustment { - Some(adjust) => self.unify_and(a, b, vec![], adjust), + Some(adjust) => self.unify_and(a, b, [], adjust), None => self.unify(a, b), } }; @@ -971,7 +982,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { self.unify_and( pointer_ty, b, - vec![], + [], Adjust::Pointer(PointerCoercion::ClosureFnPointer(safety)), ) } @@ -1003,11 +1014,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { self.unify_and( a_raw, b, - vec![Adjustment { kind: Adjust::Deref(None), target: mt_a.ty }], + [Adjustment { kind: Adjust::Deref(None), target: mt_a.ty }], Adjust::Borrow(AutoBorrow::RawPtr(mutbl_b)), ) } else if mt_a.mutbl != mutbl_b { - self.unify_and(a_raw, b, vec![], Adjust::Pointer(PointerCoercion::MutToConstPointer)) + self.unify_and(a_raw, b, [], Adjust::Pointer(PointerCoercion::MutToConstPointer)) } else { self.unify(a_raw, b) } From cd371b90e25a5923f8106cea55b5705061974139 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Tue, 8 Apr 2025 15:17:08 +0200 Subject: [PATCH 297/606] replace `//@ compile-flags: --edition` with `//@ edition` --- tests/assembly/cstring-merging.rs | 3 ++- tests/codegen/async-closure-debug.rs | 3 ++- tests/codegen/async-fn-debug-awaitee-field.rs | 3 ++- tests/codegen/async-fn-debug-msvc.rs | 3 ++- tests/codegen/async-fn-debug.rs | 13 +++++++------ tests/codegen/coroutine-debug.rs | 13 +++++++------ .../codegen/debuginfo-generic-closure-env-names.rs | 3 ++- tests/codegen/infallible-unwrap-in-opt-z.rs | 3 ++- tests/codegen/inline-function-args-debug-info.rs | 7 ++++--- tests/codegen/issues/issue-119422.rs | 3 ++- tests/codegen/simd/simd-wide-sum.rs | 3 ++- tests/codegen/try_question_mark_nop.rs | 3 ++- tests/crashes/119095.rs | 2 +- tests/crashes/120016.rs | 3 ++- tests/crashes/127033.rs | 2 +- tests/crashes/128094.rs | 3 ++- tests/crashes/132103.rs | 3 ++- tests/crashes/132430.rs | 3 ++- tests/crashes/135128.rs | 3 ++- tests/crashes/135470.rs | 3 ++- tests/crashes/135646.rs | 4 +++- tests/crashes/135668.rs | 2 +- tests/crashes/137467-1.rs | 2 +- tests/crashes/137467-2.rs | 2 +- tests/crashes/137467-3.rs | 2 +- tests/crashes/137916.rs | 2 +- tests/debuginfo/coroutine-closure.rs | 3 ++- .../incremental/issue-85360-eval-obligation-ice.rs | 5 +++-- .../doctest/failed-doctest-should-panic-2021.rs | 3 ++- .../doctest/failed-doctest-should-panic-2021.stdout | 6 +++--- .../intra-doc/import-inline-merge-module.rs | 3 ++- tests/rustdoc/auxiliary/primitive-doc.rs | 3 ++- tests/rustdoc/auxiliary/primitive-reexport.rs | 3 ++- .../intra-doc/extern-crate-only-used-in-link.rs | 3 ++- tests/rustdoc/primitive-reexport.rs | 3 ++- tests/rustdoc/primitive-slice-auto-trait.rs | 3 ++- tests/rustdoc/primitive-tuple-auto-trait.rs | 3 ++- tests/rustdoc/primitive-tuple-variadic.rs | 3 ++- tests/rustdoc/primitive-unit-auto-trait.rs | 3 ++- .../async-closures/closure-shim-borrowck-error.rs | 3 ++- .../closure-shim-borrowck-error.stderr | 4 ++-- tests/ui/async-await/issue-60709.rs | 3 ++- tests/ui/async-await/issues/issue-59972.rs | 3 ++- tests/ui/check-cfg/raw-keywords.edition2015.stderr | 8 ++++---- tests/ui/check-cfg/raw-keywords.edition2021.stderr | 8 ++++---- tests/ui/check-cfg/raw-keywords.rs | 3 ++- .../closures/2229_closure_analysis/issue-89606.rs | 4 ++-- .../preserve_field_drop_order2.rs | 4 ++-- .../cfg_accessible-not_sure.rs | 4 ++-- tests/ui/consts/const-suggest-feature.rs | 2 +- .../min_const_fn/min_const_fn_libstd_stability.rs | 2 +- tests/ui/coroutine/async-gen-deduce-yield.rs | 2 +- tests/ui/coroutine/async-gen-yield-ty-is-unit.rs | 2 +- tests/ui/debuginfo/issue-105386-debuginfo-ub.rs | 3 ++- tests/ui/deprecation/try-macro-suggestion.rs | 2 +- tests/ui/feature-gates/feature-gate-try_blocks.rs | 2 +- .../feature-gates/feature-gate-yeet_expr-in-cfg.rs | 2 +- tests/ui/feature-gates/feature-gate-yeet_expr.rs | 2 +- tests/ui/higher-ranked/trait-bounds/issue-95034.rs | 3 ++- tests/ui/impl-trait/auto-trait-contains-err.rs | 2 +- tests/ui/imports/redundant-import-extern-prelude.rs | 3 ++- .../imports/redundant-import-extern-prelude.stderr | 4 ++-- .../imports/redundant-import-issue-121915-2015.rs | 3 ++- .../redundant-import-issue-121915-2015.stderr | 4 ++-- tests/ui/imports/suggest-remove-issue-121315.rs | 2 +- tests/ui/label/label_break_value_desugared_break.rs | 2 +- tests/ui/let-else/issue-102317.rs | 3 ++- .../lifetimes/issue-83737-binders-across-types.rs | 2 +- .../ui/lifetimes/issue-83737-erasing-bound-vars.rs | 2 +- tests/ui/lint/unqualified_local_imports.rs | 2 +- tests/ui/lint/unused/issue-70041.rs | 2 +- tests/ui/macros/expr_2021_cargo_fix_edition.fixed | 2 +- tests/ui/macros/expr_2021_cargo_fix_edition.rs | 2 +- tests/ui/mir/issue-105809.rs | 3 ++- .../parser/keyword-try-as-identifier-edition2018.rs | 2 +- .../sanitizer/cfi/assoc-ty-lifetime-issue-123053.rs | 3 ++- .../sanitizer/issue-111184-cfi-coroutine-witness.rs | 3 ++- tests/ui/suggestions/enum-method-probe.fixed | 2 +- tests/ui/suggestions/enum-method-probe.rs | 2 +- tests/ui/suggestions/inner_type.fixed | 2 +- tests/ui/suggestions/inner_type.rs | 2 +- tests/ui/suggestions/issue-86667.rs | 2 +- tests/ui/traits/issue-85360-eval-obligation-ice.rs | 2 +- .../next-solver/opaques/ambig-in-mir-typeck.rs | 3 ++- .../opaques/revealing-use-in-nested-body.rs | 2 +- .../object/suggestion-trait-object-issue-139174.rs | 2 +- tests/ui/try-block/issue-45124.rs | 2 +- tests/ui/try-block/try-block-bad-lifetime.rs | 2 +- tests/ui/try-block/try-block-bad-type.rs | 2 +- tests/ui/try-block/try-block-catch.rs | 2 +- tests/ui/try-block/try-block-in-edition2015.rs | 2 +- tests/ui/try-block/try-block-in-match-arm.rs | 2 +- tests/ui/try-block/try-block-in-match.rs | 2 +- tests/ui/try-block/try-block-in-return.rs | 2 +- tests/ui/try-block/try-block-in-while.rs | 2 +- tests/ui/try-block/try-block-maybe-bad-lifetime.rs | 2 +- tests/ui/try-block/try-block-opt-init.rs | 2 +- tests/ui/try-block/try-block-type-error.rs | 2 +- .../ui/try-block/try-block-unreachable-code-lint.rs | 2 +- tests/ui/try-block/try-block-unused-delims.fixed | 2 +- tests/ui/try-block/try-block-unused-delims.rs | 2 +- tests/ui/try-block/try-block.rs | 2 +- tests/ui/try-block/try-is-identifier-edition2015.rs | 2 +- .../cross_inference_pattern_bug.rs | 2 +- .../cross_inference_pattern_bug_no_type.rs | 3 ++- tests/ui/type-alias-impl-trait/issue-93411.rs | 2 +- .../issue-96572-unconstrained.rs | 2 +- .../use/auxiliary/extern-use-primitive-type-lib.rs | 2 +- 108 files changed, 181 insertions(+), 135 deletions(-) diff --git a/tests/assembly/cstring-merging.rs b/tests/assembly/cstring-merging.rs index 7436e2418230..07f25d1e1a42 100644 --- a/tests/assembly/cstring-merging.rs +++ b/tests/assembly/cstring-merging.rs @@ -1,6 +1,7 @@ //@ only-linux //@ assembly-output: emit-asm -//@ compile-flags: --crate-type=lib -Copt-level=3 --edition 2024 +//@ compile-flags: --crate-type=lib -Copt-level=3 +//@ edition: 2024 use std::ffi::CStr; diff --git a/tests/codegen/async-closure-debug.rs b/tests/codegen/async-closure-debug.rs index 2d67e02eb9ca..b5b369e6e54b 100644 --- a/tests/codegen/async-closure-debug.rs +++ b/tests/codegen/async-closure-debug.rs @@ -1,6 +1,7 @@ // Just make sure that async closures don't ICE. // -//@ compile-flags: -C debuginfo=2 --edition=2018 +//@ compile-flags: -C debuginfo=2 +//@ edition: 2018 //@ ignore-msvc // CHECK-DAG: [[GEN_FN:!.*]] = !DINamespace(name: "async_closure_test" diff --git a/tests/codegen/async-fn-debug-awaitee-field.rs b/tests/codegen/async-fn-debug-awaitee-field.rs index ab13d4509e2e..50860c90662a 100644 --- a/tests/codegen/async-fn-debug-awaitee-field.rs +++ b/tests/codegen/async-fn-debug-awaitee-field.rs @@ -7,7 +7,8 @@ //@[MSVC] only-msvc //@[NONMSVC] ignore-msvc -//@ compile-flags: -C debuginfo=2 --edition=2018 -Copt-level=0 +//@ compile-flags: -C debuginfo=2 -Copt-level=0 +//@ edition: 2018 #![crate_type = "lib"] diff --git a/tests/codegen/async-fn-debug-msvc.rs b/tests/codegen/async-fn-debug-msvc.rs index 7c695042b425..f0bb9a18bcea 100644 --- a/tests/codegen/async-fn-debug-msvc.rs +++ b/tests/codegen/async-fn-debug-msvc.rs @@ -4,7 +4,8 @@ // - Other fields are not marked artificial // // -//@ compile-flags: -C debuginfo=2 --edition=2018 +//@ compile-flags: -C debuginfo=2 +//@ edition: 2018 //@ only-msvc async fn foo() {} diff --git a/tests/codegen/async-fn-debug.rs b/tests/codegen/async-fn-debug.rs index 7be4ad456657..ed704c7cc8b9 100644 --- a/tests/codegen/async-fn-debug.rs +++ b/tests/codegen/async-fn-debug.rs @@ -4,7 +4,8 @@ // - Other fields are not marked artificial // // -//@ compile-flags: -C debuginfo=2 --edition=2018 +//@ compile-flags: -C debuginfo=2 +//@ edition: 2018 //@ ignore-msvc async fn foo() {} @@ -22,26 +23,26 @@ async fn async_fn_test() { // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: discriminator: [[DISC:![0-9]*]] // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "0", scope: [[VARIANT]], -// CHECK-SAME: file: [[FILE:![0-9]*]], line: 11, +// CHECK-SAME: file: [[FILE:![0-9]*]], line: 12, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DICompositeType(tag: DW_TAG_structure_type, name: "Unresumed", scope: [[GEN]], // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "1", scope: [[VARIANT]], -// CHECK-SAME: file: [[FILE]], line: 15, +// CHECK-SAME: file: [[FILE]], line: 16, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "2", scope: [[VARIANT]], -// CHECK-SAME: file: [[FILE]], line: 15, +// CHECK-SAME: file: [[FILE]], line: 16, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "3", scope: [[VARIANT]], -// CHECK-SAME: file: [[FILE]], line: 12, +// CHECK-SAME: file: [[FILE]], line: 13, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "4", scope: [[VARIANT]], -// CHECK-SAME: file: [[FILE]], line: 14, +// CHECK-SAME: file: [[FILE]], line: 15, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN]], diff --git a/tests/codegen/coroutine-debug.rs b/tests/codegen/coroutine-debug.rs index d00667a37d5e..ff62e9709b4b 100644 --- a/tests/codegen/coroutine-debug.rs +++ b/tests/codegen/coroutine-debug.rs @@ -4,7 +4,8 @@ // - Other fields are not marked artificial // // -//@ compile-flags: -C debuginfo=2 --edition=2018 +//@ compile-flags: -C debuginfo=2 +//@ edition: 2018 //@ ignore-msvc #![feature(coroutines, coroutine_trait)] @@ -27,26 +28,26 @@ fn coroutine_test() -> impl Coroutine { // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: discriminator: [[DISC:![0-9]*]] // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "0", scope: [[VARIANT]], -// CHECK-SAME: file: [[FILE:![0-9]*]], line: 15, +// CHECK-SAME: file: [[FILE:![0-9]*]], line: 16, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DICompositeType(tag: DW_TAG_structure_type, name: "Unresumed", scope: [[GEN]], // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "1", scope: [[VARIANT]], -// CHECK-SAME: file: [[FILE]], line: 19, +// CHECK-SAME: file: [[FILE]], line: 20, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "2", scope: [[VARIANT]], -// CHECK-SAME: file: [[FILE]], line: 19, +// CHECK-SAME: file: [[FILE]], line: 20, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "3", scope: [[VARIANT]], -// CHECK-SAME: file: [[FILE]], line: 16, +// CHECK-SAME: file: [[FILE]], line: 17, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "4", scope: [[VARIANT]], -// CHECK-SAME: file: [[FILE]], line: 18, +// CHECK-SAME: file: [[FILE]], line: 19, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN]], diff --git a/tests/codegen/debuginfo-generic-closure-env-names.rs b/tests/codegen/debuginfo-generic-closure-env-names.rs index 6b314c9abaeb..64bc58e1df7a 100644 --- a/tests/codegen/debuginfo-generic-closure-env-names.rs +++ b/tests/codegen/debuginfo-generic-closure-env-names.rs @@ -18,7 +18,8 @@ // legacy mangling scheme rustc version and generic parameters are both hashed into a single part // of the name, thus randomizing item order with respect to rustc version. -//@ compile-flags: -Cdebuginfo=2 --edition 2021 -Copt-level=0 -Csymbol-mangling-version=v0 +//@ compile-flags: -Cdebuginfo=2 -Copt-level=0 -Csymbol-mangling-version=v0 +//@ edition: 2021 // non_generic_closure() // NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{closure_env#0}", scope: ![[non_generic_closure_NAMESPACE:[0-9]+]], diff --git a/tests/codegen/infallible-unwrap-in-opt-z.rs b/tests/codegen/infallible-unwrap-in-opt-z.rs index 3756fafe3840..c2297c58e778 100644 --- a/tests/codegen/infallible-unwrap-in-opt-z.rs +++ b/tests/codegen/infallible-unwrap-in-opt-z.rs @@ -1,4 +1,5 @@ -//@ compile-flags: -C opt-level=z --edition=2021 +//@ compile-flags: -C opt-level=z +//@ edition: 2021 #![crate_type = "lib"] diff --git a/tests/codegen/inline-function-args-debug-info.rs b/tests/codegen/inline-function-args-debug-info.rs index 53a179160dc3..c31419cb9140 100644 --- a/tests/codegen/inline-function-args-debug-info.rs +++ b/tests/codegen/inline-function-args-debug-info.rs @@ -2,7 +2,8 @@ // gets inlined by MIR inlining. Without function argument indexes, `info args` in gdb won't show // arguments and their values for the current function. -//@ compile-flags: -Zinline-mir=yes -Cdebuginfo=2 --edition=2021 +//@ compile-flags: -Zinline-mir=yes -Cdebuginfo=2 +//@ edition: 2021 #![crate_type = "lib"] @@ -14,9 +15,9 @@ pub fn outer_function(x: usize, y: usize) -> usize { #[inline] fn inner_function(aaaa: usize, bbbb: usize) -> usize { // CHECK: !DILocalVariable(name: "aaaa", arg: 1 - // CHECK-SAME: line: 15 + // CHECK-SAME: line: 16 // CHECK-NOT: !DILexicalBlock( // CHECK: !DILocalVariable(name: "bbbb", arg: 2 - // CHECK-SAME: line: 15 + // CHECK-SAME: line: 16 aaaa + bbbb } diff --git a/tests/codegen/issues/issue-119422.rs b/tests/codegen/issues/issue-119422.rs index e1a082c377f8..17ae71605b58 100644 --- a/tests/codegen/issues/issue-119422.rs +++ b/tests/codegen/issues/issue-119422.rs @@ -1,7 +1,8 @@ //! This test checks that compiler don't generate useless compares to zeros //! for `NonZero` integer types. //! -//@ compile-flags: -Copt-level=3 --edition=2021 -Zmerge-functions=disabled +//@ compile-flags: -Copt-level=3 -Zmerge-functions=disabled +//@ edition: 2021 //@ only-64bit (because the LLVM type of i64 for usize shows up) #![crate_type = "lib"] diff --git a/tests/codegen/simd/simd-wide-sum.rs b/tests/codegen/simd/simd-wide-sum.rs index fb9b61884e7a..95117b2c7488 100644 --- a/tests/codegen/simd/simd-wide-sum.rs +++ b/tests/codegen/simd/simd-wide-sum.rs @@ -1,5 +1,6 @@ //@ revisions: llvm mir-opt3 -//@ compile-flags: -C opt-level=3 -Z merge-functions=disabled --edition=2021 +//@ compile-flags: -C opt-level=3 -Z merge-functions=disabled +//@ edition: 2021 //@ only-x86_64 //@ [mir-opt3]compile-flags: -Zmir-opt-level=3 //@ [mir-opt3]build-pass diff --git a/tests/codegen/try_question_mark_nop.rs b/tests/codegen/try_question_mark_nop.rs index 9f68d742a75e..398c9a580bc3 100644 --- a/tests/codegen/try_question_mark_nop.rs +++ b/tests/codegen/try_question_mark_nop.rs @@ -1,4 +1,5 @@ -//@ compile-flags: -Copt-level=3 -Z merge-functions=disabled --edition=2021 +//@ compile-flags: -Copt-level=3 -Z merge-functions=disabled +//@ edition: 2021 //@ only-x86_64 //@ revisions: NINETEEN TWENTY //@[NINETEEN] exact-llvm-major-version: 19 diff --git a/tests/crashes/119095.rs b/tests/crashes/119095.rs index 28742e0d5dae..9b6c976d3e5d 100644 --- a/tests/crashes/119095.rs +++ b/tests/crashes/119095.rs @@ -1,5 +1,5 @@ //@ known-bug: #119095 -//@ compile-flags: --edition=2021 +//@ edition: 2021 fn any() -> T { loop {} diff --git a/tests/crashes/120016.rs b/tests/crashes/120016.rs index faba1af91b4b..7eda330e7ade 100644 --- a/tests/crashes/120016.rs +++ b/tests/crashes/120016.rs @@ -1,5 +1,6 @@ //@ known-bug: #120016 -//@ compile-flags: -Zcrate-attr=feature(const_async_blocks) --edition=2021 +//@ compile-flags: -Zcrate-attr=feature(const_async_blocks) +//@ edition: 2021 #![feature(type_alias_impl_trait, const_async_blocks)] diff --git a/tests/crashes/127033.rs b/tests/crashes/127033.rs index 919c9dfd30e8..52b880e4859b 100644 --- a/tests/crashes/127033.rs +++ b/tests/crashes/127033.rs @@ -1,5 +1,5 @@ //@ known-bug: #127033 -//@ compile-flags: --edition=2021 +//@ edition: 2021 pub trait RaftLogStorage { fn save_vote(vote: ()) -> impl std::future::Future + Send; diff --git a/tests/crashes/128094.rs b/tests/crashes/128094.rs index 5f0ae108f8f6..56d09d78bed9 100644 --- a/tests/crashes/128094.rs +++ b/tests/crashes/128094.rs @@ -1,5 +1,6 @@ //@ known-bug: rust-lang/rust#128094 -//@ compile-flags: -Zmir-enable-passes=+GVN --edition=2018 +//@ compile-flags: -Zmir-enable-passes=+GVN +//@ edition: 2018 pub enum Request { TestSome(T), diff --git a/tests/crashes/132103.rs b/tests/crashes/132103.rs index 5bf4792c44c9..e2d8378efe6a 100644 --- a/tests/crashes/132103.rs +++ b/tests/crashes/132103.rs @@ -1,5 +1,6 @@ //@ known-bug: #132103 -//@compile-flags: -Zvalidate-mir --edition=2018 -Zinline-mir=yes +//@ compile-flags: -Zvalidate-mir -Zinline-mir=yes +//@ edition: 2018 use core::future::{async_drop_in_place, Future}; use core::mem::{self}; use core::pin::pin; diff --git a/tests/crashes/132430.rs b/tests/crashes/132430.rs index 995bdf06224e..81c8c6d6f7d3 100644 --- a/tests/crashes/132430.rs +++ b/tests/crashes/132430.rs @@ -1,6 +1,7 @@ //@ known-bug: #132430 -//@compile-flags: --edition=2018 --crate-type=lib +//@ compile-flags: --crate-type=lib +//@ edition: 2018 #![feature(cmse_nonsecure_entry)] struct Test; diff --git a/tests/crashes/135128.rs b/tests/crashes/135128.rs index a8fd1ae1ff56..c718b758dc69 100644 --- a/tests/crashes/135128.rs +++ b/tests/crashes/135128.rs @@ -1,5 +1,6 @@ //@ known-bug: #135128 -//@ compile-flags: -Copt-level=1 --edition=2021 +//@ compile-flags: -Copt-level=1 +//@ edition: 2021 #![feature(trivial_bounds)] diff --git a/tests/crashes/135470.rs b/tests/crashes/135470.rs index 7d357a9317f3..efa017b5457c 100644 --- a/tests/crashes/135470.rs +++ b/tests/crashes/135470.rs @@ -1,5 +1,6 @@ //@ known-bug: #135470 -//@ compile-flags: --edition=2021 -Copt-level=0 +//@ compile-flags: -Copt-level=0 +//@ edition: 2021 use std::future::Future; trait Access { diff --git a/tests/crashes/135646.rs b/tests/crashes/135646.rs index 67b0ad93db4c..841ea5b81b41 100644 --- a/tests/crashes/135646.rs +++ b/tests/crashes/135646.rs @@ -1,5 +1,7 @@ //@ known-bug: #135646 -//@ compile-flags: --edition=2024 -Zpolonius=next +//@ compile-flags: -Zpolonius=next +//@ edition: 2024 + fn main() { &{ [1, 2, 3][4] }; } diff --git a/tests/crashes/135668.rs b/tests/crashes/135668.rs index 8126a65606b2..00d7b5db0c67 100644 --- a/tests/crashes/135668.rs +++ b/tests/crashes/135668.rs @@ -1,5 +1,5 @@ //@ known-bug: #135668 -//@ compile-flags: --edition=2021 +//@ edition: 2021 use std::future::Future; pub async fn foo() { diff --git a/tests/crashes/137467-1.rs b/tests/crashes/137467-1.rs index 1d62cba59a79..b6bff2bdc4e8 100644 --- a/tests/crashes/137467-1.rs +++ b/tests/crashes/137467-1.rs @@ -1,5 +1,5 @@ //@ known-bug: #137467 -//@ compile-flags: --edition=2021 +//@ edition: 2021 enum Camera { Normal { base_transform: i32 }, Volume { transform: i32 }, diff --git a/tests/crashes/137467-2.rs b/tests/crashes/137467-2.rs index 151d6a0767f0..a70ea92b22dc 100644 --- a/tests/crashes/137467-2.rs +++ b/tests/crashes/137467-2.rs @@ -1,5 +1,5 @@ //@ known-bug: #137467 -//@ compile-flags: --edition=2021 +//@ edition: 2021 enum Camera { Normal { base_transform: i32 }, diff --git a/tests/crashes/137467-3.rs b/tests/crashes/137467-3.rs index 2140fe044a77..cb81a9a912e7 100644 --- a/tests/crashes/137467-3.rs +++ b/tests/crashes/137467-3.rs @@ -1,5 +1,5 @@ //@ known-bug: #137467 -//@ compile-flags: --edition=2021 +//@ edition: 2021 fn meow(x: (u32, u32, u32)) { let f = || { diff --git a/tests/crashes/137916.rs b/tests/crashes/137916.rs index 3d6b0e0fbab4..b25e7b200d95 100644 --- a/tests/crashes/137916.rs +++ b/tests/crashes/137916.rs @@ -1,5 +1,5 @@ //@ known-bug: #137916 -//@ compile-flags: --edition=2021 +//@ edition: 2021 use std::ptr::null; async fn a() -> Box { diff --git a/tests/debuginfo/coroutine-closure.rs b/tests/debuginfo/coroutine-closure.rs index ffb6ae68a2b8..002531084fb9 100644 --- a/tests/debuginfo/coroutine-closure.rs +++ b/tests/debuginfo/coroutine-closure.rs @@ -1,6 +1,7 @@ #![feature(async_closure)] //@ only-cdb -//@ compile-flags:-g --edition=2021 +//@ compile-flags: -g +//@ edition: 2021 // === CDB TESTS ================================================================================== diff --git a/tests/incremental/issue-85360-eval-obligation-ice.rs b/tests/incremental/issue-85360-eval-obligation-ice.rs index 6efae1aa12d7..70bb43f39ecf 100644 --- a/tests/incremental/issue-85360-eval-obligation-ice.rs +++ b/tests/incremental/issue-85360-eval-obligation-ice.rs @@ -1,6 +1,7 @@ //@ revisions:cfail1 cfail2 -//@[cfail1] compile-flags: --crate-type=lib --edition=2021 -Zassert-incr-state=not-loaded -//@[cfail2] compile-flags: --crate-type=lib --edition=2021 -Zassert-incr-state=loaded +//@[cfail1] compile-flags: --crate-type=lib -Zassert-incr-state=not-loaded +//@[cfail2] compile-flags: --crate-type=lib -Zassert-incr-state=loaded +//@ edition: 2021 //@ build-pass use core::any::Any; diff --git a/tests/rustdoc-ui/doctest/failed-doctest-should-panic-2021.rs b/tests/rustdoc-ui/doctest/failed-doctest-should-panic-2021.rs index d8c43100d2fc..1ed67694a903 100644 --- a/tests/rustdoc-ui/doctest/failed-doctest-should-panic-2021.rs +++ b/tests/rustdoc-ui/doctest/failed-doctest-should-panic-2021.rs @@ -1,7 +1,8 @@ // FIXME: if/when the output of the test harness can be tested on its own, this test should be // adapted to use that, and that normalize line can go away -//@ compile-flags:--test --edition 2021 +//@ compile-flags: --test +//@ edition: 2021 //@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR" //@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" //@ failure-status: 101 diff --git a/tests/rustdoc-ui/doctest/failed-doctest-should-panic-2021.stdout b/tests/rustdoc-ui/doctest/failed-doctest-should-panic-2021.stdout index 63d987de8a9f..9f4d60e6f4de 100644 --- a/tests/rustdoc-ui/doctest/failed-doctest-should-panic-2021.stdout +++ b/tests/rustdoc-ui/doctest/failed-doctest-should-panic-2021.stdout @@ -1,14 +1,14 @@ running 1 test -test $DIR/failed-doctest-should-panic-2021.rs - Foo (line 9) ... FAILED +test $DIR/failed-doctest-should-panic-2021.rs - Foo (line 10) ... FAILED failures: ----- $DIR/failed-doctest-should-panic-2021.rs - Foo (line 9) stdout ---- +---- $DIR/failed-doctest-should-panic-2021.rs - Foo (line 10) stdout ---- Test executable succeeded, but it's marked `should_panic`. failures: - $DIR/failed-doctest-should-panic-2021.rs - Foo (line 9) + $DIR/failed-doctest-should-panic-2021.rs - Foo (line 10) test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME diff --git a/tests/rustdoc-ui/intra-doc/import-inline-merge-module.rs b/tests/rustdoc-ui/intra-doc/import-inline-merge-module.rs index 636c3c8de42c..bcfb790e55f6 100644 --- a/tests/rustdoc-ui/intra-doc/import-inline-merge-module.rs +++ b/tests/rustdoc-ui/intra-doc/import-inline-merge-module.rs @@ -3,7 +3,8 @@ //@ check-pass //@ aux-build: inner-crate-doc.rs -//@ compile-flags: --extern inner_crate_doc --edition 2018 +//@ compile-flags: --extern inner_crate_doc +//@ edition: 2018 /// Import doc comment [inner_crate_doc] #[doc(inline)] diff --git a/tests/rustdoc/auxiliary/primitive-doc.rs b/tests/rustdoc/auxiliary/primitive-doc.rs index a7253ed2450b..859716c38e46 100644 --- a/tests/rustdoc/auxiliary/primitive-doc.rs +++ b/tests/rustdoc/auxiliary/primitive-doc.rs @@ -1,4 +1,5 @@ -//@ compile-flags: --crate-type lib --edition 2018 +//@ compile-flags: --crate-type lib +//@ edition: 2018 #![feature(rustc_attrs)] #![feature(no_core)] diff --git a/tests/rustdoc/auxiliary/primitive-reexport.rs b/tests/rustdoc/auxiliary/primitive-reexport.rs index 18b57037634d..7c85038674b6 100644 --- a/tests/rustdoc/auxiliary/primitive-reexport.rs +++ b/tests/rustdoc/auxiliary/primitive-reexport.rs @@ -1,4 +1,5 @@ -//@ compile-flags: --emit metadata --crate-type lib --edition 2018 +//@ compile-flags: --emit metadata --crate-type lib +//@ edition: 2018 #![crate_name = "foo"] diff --git a/tests/rustdoc/intra-doc/extern-crate-only-used-in-link.rs b/tests/rustdoc/intra-doc/extern-crate-only-used-in-link.rs index 7cec30c8b746..30834bd72104 100644 --- a/tests/rustdoc/intra-doc/extern-crate-only-used-in-link.rs +++ b/tests/rustdoc/intra-doc/extern-crate-only-used-in-link.rs @@ -6,7 +6,8 @@ //@ aux-build:empty2.rs //@ aux-crate:priv:empty2=empty2.rs //@ build-aux-docs -//@ compile-flags:-Z unstable-options --edition 2018 +//@ compile-flags:-Z unstable-options +//@ edition: 2018 //@ has extern_crate_only_used_in_link/index.html //@ has - '//a[@href="../issue_66159_1/struct.Something.html"]' 'issue_66159_1::Something' diff --git a/tests/rustdoc/primitive-reexport.rs b/tests/rustdoc/primitive-reexport.rs index eb255745392a..9b23b24fc93a 100644 --- a/tests/rustdoc/primitive-reexport.rs +++ b/tests/rustdoc/primitive-reexport.rs @@ -1,5 +1,6 @@ //@ aux-build: primitive-reexport.rs -//@ compile-flags:--extern foo --edition 2018 +//@ compile-flags: --extern foo +//@ edition: 2018 #![crate_name = "bar"] diff --git a/tests/rustdoc/primitive-slice-auto-trait.rs b/tests/rustdoc/primitive-slice-auto-trait.rs index e78d1d946142..647c1cca9481 100644 --- a/tests/rustdoc/primitive-slice-auto-trait.rs +++ b/tests/rustdoc/primitive-slice-auto-trait.rs @@ -1,4 +1,5 @@ -//@ compile-flags: --crate-type lib --edition 2018 +//@ compile-flags: --crate-type lib +//@ edition: 2018 #![crate_name = "foo"] #![feature(rustc_attrs)] diff --git a/tests/rustdoc/primitive-tuple-auto-trait.rs b/tests/rustdoc/primitive-tuple-auto-trait.rs index 045478e6b4f8..51300bd6b2fc 100644 --- a/tests/rustdoc/primitive-tuple-auto-trait.rs +++ b/tests/rustdoc/primitive-tuple-auto-trait.rs @@ -1,4 +1,5 @@ -//@ compile-flags: --crate-type lib --edition 2018 +//@ compile-flags: --crate-type lib +//@ edition: 2018 #![crate_name = "foo"] #![feature(rustc_attrs)] diff --git a/tests/rustdoc/primitive-tuple-variadic.rs b/tests/rustdoc/primitive-tuple-variadic.rs index d142729d2a8b..bab5eaae9a23 100644 --- a/tests/rustdoc/primitive-tuple-variadic.rs +++ b/tests/rustdoc/primitive-tuple-variadic.rs @@ -1,4 +1,5 @@ -//@ compile-flags: --crate-type lib --edition 2018 +//@ compile-flags: --crate-type lib +//@ edition: 2018 #![crate_name = "foo"] #![feature(rustdoc_internals)] diff --git a/tests/rustdoc/primitive-unit-auto-trait.rs b/tests/rustdoc/primitive-unit-auto-trait.rs index 6cae094c21c8..7dada1f9832e 100644 --- a/tests/rustdoc/primitive-unit-auto-trait.rs +++ b/tests/rustdoc/primitive-unit-auto-trait.rs @@ -1,4 +1,5 @@ -//@ compile-flags: --crate-type lib --edition 2018 +//@ compile-flags: --crate-type lib +//@ edition: 2018 #![crate_name = "foo"] #![feature(rustc_attrs)] diff --git a/tests/ui/async-await/async-closures/closure-shim-borrowck-error.rs b/tests/ui/async-await/async-closures/closure-shim-borrowck-error.rs index 069744a3282d..12dca587e07d 100644 --- a/tests/ui/async-await/async-closures/closure-shim-borrowck-error.rs +++ b/tests/ui/async-await/async-closures/closure-shim-borrowck-error.rs @@ -1,4 +1,5 @@ -//@ compile-flags: -Zvalidate-mir --edition=2018 --crate-type=lib -Copt-level=3 +//@ compile-flags: -Zvalidate-mir --crate-type=lib -Copt-level=3 +//@ edition: 2018 fn main() {} diff --git a/tests/ui/async-await/async-closures/closure-shim-borrowck-error.stderr b/tests/ui/async-await/async-closures/closure-shim-borrowck-error.stderr index 52697bac5098..03fa220b0bfa 100644 --- a/tests/ui/async-await/async-closures/closure-shim-borrowck-error.stderr +++ b/tests/ui/async-await/async-closures/closure-shim-borrowck-error.stderr @@ -1,5 +1,5 @@ error[E0507]: cannot move out of `x` which is behind a mutable reference - --> $DIR/closure-shim-borrowck-error.rs:10:18 + --> $DIR/closure-shim-borrowck-error.rs:11:18 | LL | needs_fn_mut(async || { | ^^^^^^^^ `x` is moved here @@ -11,7 +11,7 @@ LL | x.hello(); | move occurs because `x` has type `Ty`, which does not implement the `Copy` trait | note: if `Ty` implemented `Clone`, you could clone the value - --> $DIR/closure-shim-borrowck-error.rs:16:1 + --> $DIR/closure-shim-borrowck-error.rs:17:1 | LL | x.hello(); | - you could clone this value diff --git a/tests/ui/async-await/issue-60709.rs b/tests/ui/async-await/issue-60709.rs index 8634d6f7768b..a3f54d70316c 100644 --- a/tests/ui/async-await/issue-60709.rs +++ b/tests/ui/async-await/issue-60709.rs @@ -1,6 +1,7 @@ // This used to compile the future down to ud2, due to uninhabited types being // handled incorrectly in coroutines. -//@ compile-flags: -Copt-level=z -Cdebuginfo=2 --edition=2018 +//@ compile-flags: -Copt-level=z -Cdebuginfo=2 +//@ edition: 2018 //@ run-pass diff --git a/tests/ui/async-await/issues/issue-59972.rs b/tests/ui/async-await/issues/issue-59972.rs index c30477fcd30c..e64a856fab30 100644 --- a/tests/ui/async-await/issues/issue-59972.rs +++ b/tests/ui/async-await/issues/issue-59972.rs @@ -4,7 +4,8 @@ //@ run-pass -//@ compile-flags: --edition=2018 -Aunused +//@ compile-flags: -Aunused +//@ edition: 2018 pub enum Uninhabited { } diff --git a/tests/ui/check-cfg/raw-keywords.edition2015.stderr b/tests/ui/check-cfg/raw-keywords.edition2015.stderr index 8ca33e088fc9..29c1a71c0b7a 100644 --- a/tests/ui/check-cfg/raw-keywords.edition2015.stderr +++ b/tests/ui/check-cfg/raw-keywords.edition2015.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition name: `tru` - --> $DIR/raw-keywords.rs:14:7 + --> $DIR/raw-keywords.rs:15:7 | LL | #[cfg(tru)] | ^^^ help: there is a config with a similar name: `r#true` @@ -9,7 +9,7 @@ LL | #[cfg(tru)] = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition name: `r#false` - --> $DIR/raw-keywords.rs:19:7 + --> $DIR/raw-keywords.rs:20:7 | LL | #[cfg(r#false)] | ^^^^^^^ @@ -19,7 +19,7 @@ LL | #[cfg(r#false)] = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition name: `await` - --> $DIR/raw-keywords.rs:27:29 + --> $DIR/raw-keywords.rs:28:29 | LL | #[cfg_attr(edition2015, cfg(await))] | ^^^^^ @@ -28,7 +28,7 @@ LL | #[cfg_attr(edition2015, cfg(await))] = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition name: `raw` - --> $DIR/raw-keywords.rs:33:7 + --> $DIR/raw-keywords.rs:34:7 | LL | #[cfg(r#raw)] | ^^^^^ diff --git a/tests/ui/check-cfg/raw-keywords.edition2021.stderr b/tests/ui/check-cfg/raw-keywords.edition2021.stderr index cce55720bdd1..cc3702685fd2 100644 --- a/tests/ui/check-cfg/raw-keywords.edition2021.stderr +++ b/tests/ui/check-cfg/raw-keywords.edition2021.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition name: `tru` - --> $DIR/raw-keywords.rs:14:7 + --> $DIR/raw-keywords.rs:15:7 | LL | #[cfg(tru)] | ^^^ help: there is a config with a similar name: `r#true` @@ -9,7 +9,7 @@ LL | #[cfg(tru)] = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition name: `r#false` - --> $DIR/raw-keywords.rs:19:7 + --> $DIR/raw-keywords.rs:20:7 | LL | #[cfg(r#false)] | ^^^^^^^ @@ -19,7 +19,7 @@ LL | #[cfg(r#false)] = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition name: `r#await` - --> $DIR/raw-keywords.rs:28:29 + --> $DIR/raw-keywords.rs:29:29 | LL | #[cfg_attr(edition2021, cfg(r#await))] | ^^^^^^^ @@ -28,7 +28,7 @@ LL | #[cfg_attr(edition2021, cfg(r#await))] = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition name: `raw` - --> $DIR/raw-keywords.rs:33:7 + --> $DIR/raw-keywords.rs:34:7 | LL | #[cfg(r#raw)] | ^^^^^ diff --git a/tests/ui/check-cfg/raw-keywords.rs b/tests/ui/check-cfg/raw-keywords.rs index 5de13240d7ed..b82eb5a64e9a 100644 --- a/tests/ui/check-cfg/raw-keywords.rs +++ b/tests/ui/check-cfg/raw-keywords.rs @@ -6,7 +6,8 @@ //@ compile-flags: --cfg=true --cfg=async --check-cfg=cfg(r#true,r#async,edition2015,edition2021) // //@ revisions: edition2015 edition2021 -//@ [edition2021] compile-flags: --edition 2021 +//@ [edition2015] edition: 2015 +//@ [edition2021] edition: 2021 #[cfg(r#true)] fn foo() {} diff --git a/tests/ui/closures/2229_closure_analysis/issue-89606.rs b/tests/ui/closures/2229_closure_analysis/issue-89606.rs index 8c88a4b82261..5494686356d5 100644 --- a/tests/ui/closures/2229_closure_analysis/issue-89606.rs +++ b/tests/ui/closures/2229_closure_analysis/issue-89606.rs @@ -2,8 +2,8 @@ // //@ check-pass //@ revisions: twenty_eighteen twenty_twentyone -//@ [twenty_eighteen]compile-flags: --edition 2018 -//@ [twenty_twentyone]compile-flags: --edition 2021 +//@ [twenty_eighteen] edition: 2018 +//@ [twenty_twentyone] edition: 2021 struct S<'a>(Option<&'a mut i32>); diff --git a/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order2.rs b/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order2.rs index 4fc2e6c903a9..a771b815702a 100644 --- a/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order2.rs +++ b/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order2.rs @@ -1,8 +1,8 @@ //@ run-pass //@ check-run-results //@ revisions: twenty_eighteen twenty_twentyone -//@ [twenty_eighteen]compile-flags: --edition 2018 -//@ [twenty_twentyone]compile-flags: --edition 2021 +//@ [twenty_eighteen] edition: 2018 +//@ [twenty_twentyone] edition: 2021 #[derive(Debug)] struct Dropable(&'static str); diff --git a/tests/ui/conditional-compilation/cfg_accessible-not_sure.rs b/tests/ui/conditional-compilation/cfg_accessible-not_sure.rs index 2ac57f356740..7753b7d64fb3 100644 --- a/tests/ui/conditional-compilation/cfg_accessible-not_sure.rs +++ b/tests/ui/conditional-compilation/cfg_accessible-not_sure.rs @@ -1,6 +1,6 @@ //@ revisions: edition2015 edition2021 -//@ [edition2015]compile-flags: --edition=2015 -//@ [edition2021]compile-flags: --edition=2021 +//@ [edition2015] edition: 2015 +//@ [edition2021] edition: 2021 #![feature(extern_types)] #![feature(cfg_accessible)] diff --git a/tests/ui/consts/const-suggest-feature.rs b/tests/ui/consts/const-suggest-feature.rs index 0c9403689761..dbb166dd6c5d 100644 --- a/tests/ui/consts/const-suggest-feature.rs +++ b/tests/ui/consts/const-suggest-feature.rs @@ -1,4 +1,4 @@ -//@compile-flags: --edition 2018 +//@ edition: 2018 use std::cell::Cell; const WRITE: () = unsafe { diff --git a/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs b/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs index d6f07994e820..8f2bcd82c73f 100644 --- a/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs +++ b/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition 2018 +//@ edition: 2018 #![unstable(feature = "humans", reason = "who ever let humans program computers, we're apparently really bad at it", diff --git a/tests/ui/coroutine/async-gen-deduce-yield.rs b/tests/ui/coroutine/async-gen-deduce-yield.rs index f85e4a52e9b9..a9572ee9b0dd 100644 --- a/tests/ui/coroutine/async-gen-deduce-yield.rs +++ b/tests/ui/coroutine/async-gen-deduce-yield.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition 2024 +//@ edition: 2024 //@ check-pass #![feature(async_iterator, gen_blocks)] diff --git a/tests/ui/coroutine/async-gen-yield-ty-is-unit.rs b/tests/ui/coroutine/async-gen-yield-ty-is-unit.rs index 583820c7aa39..53e3ce77f8a8 100644 --- a/tests/ui/coroutine/async-gen-yield-ty-is-unit.rs +++ b/tests/ui/coroutine/async-gen-yield-ty-is-unit.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition 2024 +//@ edition: 2024 //@ check-pass #![feature(async_iterator, gen_blocks)] diff --git a/tests/ui/debuginfo/issue-105386-debuginfo-ub.rs b/tests/ui/debuginfo/issue-105386-debuginfo-ub.rs index 7b850f32b4b6..e926a337659c 100644 --- a/tests/ui/debuginfo/issue-105386-debuginfo-ub.rs +++ b/tests/ui/debuginfo/issue-105386-debuginfo-ub.rs @@ -1,5 +1,6 @@ //@ run-pass -//@ compile-flags: --edition 2021 -Copt-level=3 -Cdebuginfo=2 -Zmir-opt-level=3 +//@ compile-flags: -Copt-level=3 -Cdebuginfo=2 -Zmir-opt-level=3 +//@ edition: 2021 fn main() { TranslatorI.visit_pre(); diff --git a/tests/ui/deprecation/try-macro-suggestion.rs b/tests/ui/deprecation/try-macro-suggestion.rs index 1e477ab9c88f..0775f0011001 100644 --- a/tests/ui/deprecation/try-macro-suggestion.rs +++ b/tests/ui/deprecation/try-macro-suggestion.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition 2018 +//@ edition: 2018 fn foo() -> Result<(), ()> { Ok(try!()); //~ ERROR use of deprecated `try` macro Ok(try!(Ok(()))) //~ ERROR use of deprecated `try` macro diff --git a/tests/ui/feature-gates/feature-gate-try_blocks.rs b/tests/ui/feature-gates/feature-gate-try_blocks.rs index f565dd014de8..90816293624a 100644 --- a/tests/ui/feature-gates/feature-gate-try_blocks.rs +++ b/tests/ui/feature-gates/feature-gate-try_blocks.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition 2018 +//@ edition: 2018 pub fn main() { let try_result: Option<_> = try { //~ ERROR `try` expression is experimental diff --git a/tests/ui/feature-gates/feature-gate-yeet_expr-in-cfg.rs b/tests/ui/feature-gates/feature-gate-yeet_expr-in-cfg.rs index 33fda822baad..a32ebed8dde5 100644 --- a/tests/ui/feature-gates/feature-gate-yeet_expr-in-cfg.rs +++ b/tests/ui/feature-gates/feature-gate-yeet_expr-in-cfg.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition 2021 +//@ edition: 2021 pub fn demo() -> Option { #[cfg(FALSE)] diff --git a/tests/ui/feature-gates/feature-gate-yeet_expr.rs b/tests/ui/feature-gates/feature-gate-yeet_expr.rs index 12cc17e1cc89..6604f496917f 100644 --- a/tests/ui/feature-gates/feature-gate-yeet_expr.rs +++ b/tests/ui/feature-gates/feature-gate-yeet_expr.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition 2018 +//@ edition: 2018 pub fn demo() -> Option { do yeet //~ ERROR `do yeet` expression is experimental diff --git a/tests/ui/higher-ranked/trait-bounds/issue-95034.rs b/tests/ui/higher-ranked/trait-bounds/issue-95034.rs index 53b28c2bea45..f33469796c2f 100644 --- a/tests/ui/higher-ranked/trait-bounds/issue-95034.rs +++ b/tests/ui/higher-ranked/trait-bounds/issue-95034.rs @@ -1,5 +1,6 @@ //@ check-pass -//@ compile-flags: --edition=2021 --crate-type=lib +//@ compile-flags: --crate-type=lib +//@ edition: 2021 use std::{ future::Future, diff --git a/tests/ui/impl-trait/auto-trait-contains-err.rs b/tests/ui/impl-trait/auto-trait-contains-err.rs index d7f094211d7d..8a2ebe301f11 100644 --- a/tests/ui/impl-trait/auto-trait-contains-err.rs +++ b/tests/ui/impl-trait/auto-trait-contains-err.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition=2021 +//@ edition: 2021 use std::future::Future; diff --git a/tests/ui/imports/redundant-import-extern-prelude.rs b/tests/ui/imports/redundant-import-extern-prelude.rs index 0064eaa93188..b573b8fc6109 100644 --- a/tests/ui/imports/redundant-import-extern-prelude.rs +++ b/tests/ui/imports/redundant-import-extern-prelude.rs @@ -5,7 +5,8 @@ // See also the discussion in . -//@ compile-flags: --extern aux_issue_121915 --edition 2018 +//@ compile-flags: --extern aux_issue_121915 +//@ edition: 2018 //@ aux-build: aux-issue-121915.rs #[deny(redundant_imports)] diff --git a/tests/ui/imports/redundant-import-extern-prelude.stderr b/tests/ui/imports/redundant-import-extern-prelude.stderr index 6d2518c1284b..06cce7e17256 100644 --- a/tests/ui/imports/redundant-import-extern-prelude.stderr +++ b/tests/ui/imports/redundant-import-extern-prelude.stderr @@ -1,11 +1,11 @@ error: the item `aux_issue_121915` is imported redundantly - --> $DIR/redundant-import-extern-prelude.rs:14:9 + --> $DIR/redundant-import-extern-prelude.rs:15:9 | LL | use aux_issue_121915; | ^^^^^^^^^^^^^^^^ the item `aux_issue_121915` is already defined by the extern prelude | note: the lint level is defined here - --> $DIR/redundant-import-extern-prelude.rs:11:8 + --> $DIR/redundant-import-extern-prelude.rs:12:8 | LL | #[deny(redundant_imports)] | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/imports/redundant-import-issue-121915-2015.rs b/tests/ui/imports/redundant-import-issue-121915-2015.rs index dc499bc40b61..7108776757e9 100644 --- a/tests/ui/imports/redundant-import-issue-121915-2015.rs +++ b/tests/ui/imports/redundant-import-issue-121915-2015.rs @@ -1,4 +1,5 @@ -//@ compile-flags: --extern aux_issue_121915 --edition 2015 +//@ compile-flags: --extern aux_issue_121915 +//@ edition: 2015 //@ aux-build: aux-issue-121915.rs extern crate aux_issue_121915; diff --git a/tests/ui/imports/redundant-import-issue-121915-2015.stderr b/tests/ui/imports/redundant-import-issue-121915-2015.stderr index f4e9f604896a..367a4f1cd15a 100644 --- a/tests/ui/imports/redundant-import-issue-121915-2015.stderr +++ b/tests/ui/imports/redundant-import-issue-121915-2015.stderr @@ -1,5 +1,5 @@ error: the item `aux_issue_121915` is imported redundantly - --> $DIR/redundant-import-issue-121915-2015.rs:8:9 + --> $DIR/redundant-import-issue-121915-2015.rs:9:9 | LL | extern crate aux_issue_121915; | ------------------------------ the item `aux_issue_121915` is already imported here @@ -8,7 +8,7 @@ LL | use aux_issue_121915; | ^^^^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/redundant-import-issue-121915-2015.rs:6:8 + --> $DIR/redundant-import-issue-121915-2015.rs:7:8 | LL | #[deny(redundant_imports)] | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/imports/suggest-remove-issue-121315.rs b/tests/ui/imports/suggest-remove-issue-121315.rs index ee3ceb6e3a38..3c036b843fd4 100644 --- a/tests/ui/imports/suggest-remove-issue-121315.rs +++ b/tests/ui/imports/suggest-remove-issue-121315.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition 2021 +//@ edition: 2021 #![deny(unused_imports, redundant_imports)] #![allow(dead_code)] diff --git a/tests/ui/label/label_break_value_desugared_break.rs b/tests/ui/label/label_break_value_desugared_break.rs index b7e7fd47c27f..17ef1ba6d24b 100644 --- a/tests/ui/label/label_break_value_desugared_break.rs +++ b/tests/ui/label/label_break_value_desugared_break.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition 2018 +//@ edition: 2018 #![feature(try_blocks)] //@ run-pass diff --git a/tests/ui/let-else/issue-102317.rs b/tests/ui/let-else/issue-102317.rs index d94410e10a8d..5afcacfc3aad 100644 --- a/tests/ui/let-else/issue-102317.rs +++ b/tests/ui/let-else/issue-102317.rs @@ -1,6 +1,7 @@ // issue #102317 //@ build-pass -//@ compile-flags: --edition 2021 -C opt-level=3 -Zvalidate-mir +//@ compile-flags: -C opt-level=3 -Zvalidate-mir +//@ edition: 2021 struct SegmentJob; diff --git a/tests/ui/lifetimes/issue-83737-binders-across-types.rs b/tests/ui/lifetimes/issue-83737-binders-across-types.rs index d20c84dae3f7..6f3993812944 100644 --- a/tests/ui/lifetimes/issue-83737-binders-across-types.rs +++ b/tests/ui/lifetimes/issue-83737-binders-across-types.rs @@ -1,5 +1,5 @@ //@ build-pass -//@ compile-flags: --edition 2018 +//@ edition: 2018 //@ compile-flags: --crate-type rlib use std::future::Future; diff --git a/tests/ui/lifetimes/issue-83737-erasing-bound-vars.rs b/tests/ui/lifetimes/issue-83737-erasing-bound-vars.rs index 466bcdc6be0f..dcc8c7e94ba6 100644 --- a/tests/ui/lifetimes/issue-83737-erasing-bound-vars.rs +++ b/tests/ui/lifetimes/issue-83737-erasing-bound-vars.rs @@ -1,5 +1,5 @@ //@ build-pass -//@ compile-flags: --edition 2018 +//@ edition: 2018 //@ compile-flags: --crate-type rlib use std::future::Future; diff --git a/tests/ui/lint/unqualified_local_imports.rs b/tests/ui/lint/unqualified_local_imports.rs index 9de71471342d..b7036f9c68ea 100644 --- a/tests/ui/lint/unqualified_local_imports.rs +++ b/tests/ui/lint/unqualified_local_imports.rs @@ -1,4 +1,4 @@ -//@compile-flags: --edition 2018 +//@ edition: 2018 #![feature(unqualified_local_imports)] #![deny(unqualified_local_imports)] diff --git a/tests/ui/lint/unused/issue-70041.rs b/tests/ui/lint/unused/issue-70041.rs index 817dfe821149..890ba378263b 100644 --- a/tests/ui/lint/unused/issue-70041.rs +++ b/tests/ui/lint/unused/issue-70041.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition=2018 +//@ edition: 2018 //@ run-pass macro_rules! regex { diff --git a/tests/ui/macros/expr_2021_cargo_fix_edition.fixed b/tests/ui/macros/expr_2021_cargo_fix_edition.fixed index 061a4b98033c..c0d276093589 100644 --- a/tests/ui/macros/expr_2021_cargo_fix_edition.fixed +++ b/tests/ui/macros/expr_2021_cargo_fix_edition.fixed @@ -1,6 +1,6 @@ //@ run-rustfix //@ check-pass -//@ compile-flags: --edition=2021 +//@ edition: 2021 #![warn(edition_2024_expr_fragment_specifier)] macro_rules! m { diff --git a/tests/ui/macros/expr_2021_cargo_fix_edition.rs b/tests/ui/macros/expr_2021_cargo_fix_edition.rs index cd9cd965fad2..b2c16fc7041c 100644 --- a/tests/ui/macros/expr_2021_cargo_fix_edition.rs +++ b/tests/ui/macros/expr_2021_cargo_fix_edition.rs @@ -1,6 +1,6 @@ //@ run-rustfix //@ check-pass -//@ compile-flags: --edition=2021 +//@ edition: 2021 #![warn(edition_2024_expr_fragment_specifier)] macro_rules! m { diff --git a/tests/ui/mir/issue-105809.rs b/tests/ui/mir/issue-105809.rs index e7a8fb652689..a46dcf350adf 100644 --- a/tests/ui/mir/issue-105809.rs +++ b/tests/ui/mir/issue-105809.rs @@ -1,7 +1,8 @@ // Non-regression test ICE from issue #105809 and duplicates. //@ build-pass: the ICE is during codegen -//@ compile-flags: --edition 2018 -Zmir-opt-level=1 +//@ compile-flags: -Zmir-opt-level=1 +//@ edition: 2018 use std::{future::Future, pin::Pin}; diff --git a/tests/ui/parser/keyword-try-as-identifier-edition2018.rs b/tests/ui/parser/keyword-try-as-identifier-edition2018.rs index 27452f4d45e8..795f32059f22 100644 --- a/tests/ui/parser/keyword-try-as-identifier-edition2018.rs +++ b/tests/ui/parser/keyword-try-as-identifier-edition2018.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition 2018 +//@ edition: 2018 fn main() { let try = "foo"; //~ error: expected identifier, found reserved keyword `try` diff --git a/tests/ui/sanitizer/cfi/assoc-ty-lifetime-issue-123053.rs b/tests/ui/sanitizer/cfi/assoc-ty-lifetime-issue-123053.rs index dd604b6bf7dc..f4f383e008a0 100644 --- a/tests/ui/sanitizer/cfi/assoc-ty-lifetime-issue-123053.rs +++ b/tests/ui/sanitizer/cfi/assoc-ty-lifetime-issue-123053.rs @@ -2,7 +2,8 @@ // trait object type to fail, causing an ICE. // //@ needs-sanitizer-cfi -//@ compile-flags: -Ccodegen-units=1 -Clto -Ctarget-feature=-crt-static -Zsanitizer=cfi --edition=2021 +//@ compile-flags: -Ccodegen-units=1 -Clto -Ctarget-feature=-crt-static -Zsanitizer=cfi +//@ edition: 2021 //@ no-prefer-dynamic //@ only-x86_64-unknown-linux-gnu //@ build-pass diff --git a/tests/ui/sanitizer/issue-111184-cfi-coroutine-witness.rs b/tests/ui/sanitizer/issue-111184-cfi-coroutine-witness.rs index e5b1e0322575..7d0c73c2841e 100644 --- a/tests/ui/sanitizer/issue-111184-cfi-coroutine-witness.rs +++ b/tests/ui/sanitizer/issue-111184-cfi-coroutine-witness.rs @@ -2,7 +2,8 @@ // encode_ty and caused the compiler to ICE. // //@ needs-sanitizer-cfi -//@ compile-flags: -Ccodegen-units=1 -Clto -Ctarget-feature=-crt-static -Zsanitizer=cfi --edition=2021 +//@ compile-flags: -Ccodegen-units=1 -Clto -Ctarget-feature=-crt-static -Zsanitizer=cfi +//@ edition: 2021 //@ no-prefer-dynamic //@ only-x86_64-unknown-linux-gnu //@ build-pass diff --git a/tests/ui/suggestions/enum-method-probe.fixed b/tests/ui/suggestions/enum-method-probe.fixed index 611be9911d97..e097fa8cc1d8 100644 --- a/tests/ui/suggestions/enum-method-probe.fixed +++ b/tests/ui/suggestions/enum-method-probe.fixed @@ -1,4 +1,4 @@ -//@ compile-flags: --edition=2021 +//@ edition: 2021 //@ run-rustfix #![allow(unused)] diff --git a/tests/ui/suggestions/enum-method-probe.rs b/tests/ui/suggestions/enum-method-probe.rs index e183ebd25f2a..665ee7d0aaad 100644 --- a/tests/ui/suggestions/enum-method-probe.rs +++ b/tests/ui/suggestions/enum-method-probe.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition=2021 +//@ edition: 2021 //@ run-rustfix #![allow(unused)] diff --git a/tests/ui/suggestions/inner_type.fixed b/tests/ui/suggestions/inner_type.fixed index cfea66b57ec1..3dc939d6b5c4 100644 --- a/tests/ui/suggestions/inner_type.fixed +++ b/tests/ui/suggestions/inner_type.fixed @@ -1,4 +1,4 @@ -//@ compile-flags: --edition=2021 +//@ edition: 2021 //@ run-rustfix pub struct Struct { diff --git a/tests/ui/suggestions/inner_type.rs b/tests/ui/suggestions/inner_type.rs index 5fedf3f256e3..81a05c253119 100644 --- a/tests/ui/suggestions/inner_type.rs +++ b/tests/ui/suggestions/inner_type.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition=2021 +//@ edition: 2021 //@ run-rustfix pub struct Struct { diff --git a/tests/ui/suggestions/issue-86667.rs b/tests/ui/suggestions/issue-86667.rs index 1f37e9a5f6de..cc5b878b6321 100644 --- a/tests/ui/suggestions/issue-86667.rs +++ b/tests/ui/suggestions/issue-86667.rs @@ -1,7 +1,7 @@ // Regression test for #86667, where a garbled suggestion was issued for // a missing named lifetime parameter. -//@ compile-flags: --edition 2018 +//@ edition: 2018 async fn a(s1: &str, s2: &str) -> &str { //~^ ERROR: missing lifetime specifier [E0106] diff --git a/tests/ui/traits/issue-85360-eval-obligation-ice.rs b/tests/ui/traits/issue-85360-eval-obligation-ice.rs index 931879a67226..f7c49049e2d3 100644 --- a/tests/ui/traits/issue-85360-eval-obligation-ice.rs +++ b/tests/ui/traits/issue-85360-eval-obligation-ice.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition=2021 +//@ edition: 2021 #![feature(rustc_attrs)] diff --git a/tests/ui/traits/next-solver/opaques/ambig-in-mir-typeck.rs b/tests/ui/traits/next-solver/opaques/ambig-in-mir-typeck.rs index e5208e3e47d0..198e6199e92c 100644 --- a/tests/ui/traits/next-solver/opaques/ambig-in-mir-typeck.rs +++ b/tests/ui/traits/next-solver/opaques/ambig-in-mir-typeck.rs @@ -1,7 +1,8 @@ // Regression test for #132335. This previously ICE'd due to ambiguity // in MIR typeck. -//@ compile-flags: -Znext-solver=globally --crate-type lib --edition=2018 +//@ compile-flags: -Znext-solver=globally --crate-type lib +//@ edition: 2018 //@ check-pass use core::future::Future; use core::pin::Pin; diff --git a/tests/ui/traits/next-solver/opaques/revealing-use-in-nested-body.rs b/tests/ui/traits/next-solver/opaques/revealing-use-in-nested-body.rs index 8388751fea64..b79926eebda3 100644 --- a/tests/ui/traits/next-solver/opaques/revealing-use-in-nested-body.rs +++ b/tests/ui/traits/next-solver/opaques/revealing-use-in-nested-body.rs @@ -3,7 +3,7 @@ // of the async block. This caused borrowck of the recursive // call to ICE. -//@ compile-flags: --edition=2021 +//@ edition: 2021 //@ check-pass async fn test() { Box::pin(test()).await; diff --git a/tests/ui/traits/object/suggestion-trait-object-issue-139174.rs b/tests/ui/traits/object/suggestion-trait-object-issue-139174.rs index f8fa410b7d49..50851a5b0f84 100644 --- a/tests/ui/traits/object/suggestion-trait-object-issue-139174.rs +++ b/tests/ui/traits/object/suggestion-trait-object-issue-139174.rs @@ -1,4 +1,4 @@ -//@compile-flags: --edition 2021 +//@ edition: 2021 fn f<'a>(x: Box Option>) -> usize { //~^ ERROR expected trait, found builtin type `usize` diff --git a/tests/ui/try-block/issue-45124.rs b/tests/ui/try-block/issue-45124.rs index e9e0e767efa2..26e1736faaca 100644 --- a/tests/ui/try-block/issue-45124.rs +++ b/tests/ui/try-block/issue-45124.rs @@ -1,6 +1,6 @@ //@ run-pass #![allow(unreachable_code)] -//@ compile-flags: --edition 2018 +//@ edition: 2018 #![feature(try_blocks)] diff --git a/tests/ui/try-block/try-block-bad-lifetime.rs b/tests/ui/try-block/try-block-bad-lifetime.rs index bfff757a2df6..9b45b0d95594 100644 --- a/tests/ui/try-block/try-block-bad-lifetime.rs +++ b/tests/ui/try-block/try-block-bad-lifetime.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition 2018 +//@ edition: 2018 #![feature(try_blocks)] diff --git a/tests/ui/try-block/try-block-bad-type.rs b/tests/ui/try-block/try-block-bad-type.rs index 71eb832dd4eb..00cd0af127c8 100644 --- a/tests/ui/try-block/try-block-bad-type.rs +++ b/tests/ui/try-block/try-block-bad-type.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition 2018 +//@ edition: 2018 #![feature(try_blocks)] diff --git a/tests/ui/try-block/try-block-catch.rs b/tests/ui/try-block/try-block-catch.rs index c3aa442ba663..170d5bab3e50 100644 --- a/tests/ui/try-block/try-block-catch.rs +++ b/tests/ui/try-block/try-block-catch.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition 2018 +//@ edition: 2018 #![feature(try_blocks)] diff --git a/tests/ui/try-block/try-block-in-edition2015.rs b/tests/ui/try-block/try-block-in-edition2015.rs index 423269df12d6..4ebe2d31b81d 100644 --- a/tests/ui/try-block/try-block-in-edition2015.rs +++ b/tests/ui/try-block/try-block-in-edition2015.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition 2015 +//@ edition: 2015 pub fn main() { let try_result: Option<_> = try { diff --git a/tests/ui/try-block/try-block-in-match-arm.rs b/tests/ui/try-block/try-block-in-match-arm.rs index cecbf724916c..703b1c54bbb1 100644 --- a/tests/ui/try-block/try-block-in-match-arm.rs +++ b/tests/ui/try-block/try-block-in-match-arm.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ compile-flags: --edition 2018 +//@ edition: 2018 #![feature(try_blocks)] diff --git a/tests/ui/try-block/try-block-in-match.rs b/tests/ui/try-block/try-block-in-match.rs index 5c62f41efdba..63a32000f625 100644 --- a/tests/ui/try-block/try-block-in-match.rs +++ b/tests/ui/try-block/try-block-in-match.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ compile-flags: --edition 2018 +//@ edition: 2018 #![feature(try_blocks)] diff --git a/tests/ui/try-block/try-block-in-return.rs b/tests/ui/try-block/try-block-in-return.rs index ee5ca696b6d6..7dc023b90dbc 100644 --- a/tests/ui/try-block/try-block-in-return.rs +++ b/tests/ui/try-block/try-block-in-return.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ compile-flags: --edition 2018 +//@ edition: 2018 #![feature(try_blocks)] diff --git a/tests/ui/try-block/try-block-in-while.rs b/tests/ui/try-block/try-block-in-while.rs index 88a97136c594..d6232546cea0 100644 --- a/tests/ui/try-block/try-block-in-while.rs +++ b/tests/ui/try-block/try-block-in-while.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition 2018 +//@ edition: 2018 #![feature(try_blocks)] diff --git a/tests/ui/try-block/try-block-maybe-bad-lifetime.rs b/tests/ui/try-block/try-block-maybe-bad-lifetime.rs index 52ec0c44a059..14adee8944fa 100644 --- a/tests/ui/try-block/try-block-maybe-bad-lifetime.rs +++ b/tests/ui/try-block/try-block-maybe-bad-lifetime.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition 2018 +//@ edition: 2018 #![feature(try_blocks)] diff --git a/tests/ui/try-block/try-block-opt-init.rs b/tests/ui/try-block/try-block-opt-init.rs index fbe7f90d0303..55ac5b4a37cc 100644 --- a/tests/ui/try-block/try-block-opt-init.rs +++ b/tests/ui/try-block/try-block-opt-init.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition 2018 +//@ edition: 2018 #![feature(try_blocks)] diff --git a/tests/ui/try-block/try-block-type-error.rs b/tests/ui/try-block/try-block-type-error.rs index 79cdb7a2e48d..4e482b40140d 100644 --- a/tests/ui/try-block/try-block-type-error.rs +++ b/tests/ui/try-block/try-block-type-error.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition 2018 +//@ edition: 2018 #![feature(try_blocks)] diff --git a/tests/ui/try-block/try-block-unreachable-code-lint.rs b/tests/ui/try-block/try-block-unreachable-code-lint.rs index 62c74b76d59c..9135882a57b2 100644 --- a/tests/ui/try-block/try-block-unreachable-code-lint.rs +++ b/tests/ui/try-block/try-block-unreachable-code-lint.rs @@ -1,6 +1,6 @@ // Test unreachable_code lint for `try {}` block ok-wrapping. See issues #54165, #63324. -//@ compile-flags: --edition 2018 +//@ edition: 2018 //@ check-pass #![feature(try_blocks)] #![warn(unreachable_code)] diff --git a/tests/ui/try-block/try-block-unused-delims.fixed b/tests/ui/try-block/try-block-unused-delims.fixed index 348eb8f79656..4769c45d38cc 100644 --- a/tests/ui/try-block/try-block-unused-delims.fixed +++ b/tests/ui/try-block/try-block-unused-delims.fixed @@ -1,5 +1,5 @@ //@ check-pass -//@ compile-flags: --edition 2018 +//@ edition: 2018 //@ run-rustfix #![feature(try_blocks)] diff --git a/tests/ui/try-block/try-block-unused-delims.rs b/tests/ui/try-block/try-block-unused-delims.rs index f119e1074f6e..0520d1d620f5 100644 --- a/tests/ui/try-block/try-block-unused-delims.rs +++ b/tests/ui/try-block/try-block-unused-delims.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ compile-flags: --edition 2018 +//@ edition: 2018 //@ run-rustfix #![feature(try_blocks)] diff --git a/tests/ui/try-block/try-block.rs b/tests/ui/try-block/try-block.rs index 7520cbaad378..3fa0d2ba0f24 100644 --- a/tests/ui/try-block/try-block.rs +++ b/tests/ui/try-block/try-block.rs @@ -2,7 +2,7 @@ #![allow(non_camel_case_types)] #![allow(dead_code)] -//@ compile-flags: --edition 2018 +//@ edition: 2018 #![feature(try_blocks)] diff --git a/tests/ui/try-block/try-is-identifier-edition2015.rs b/tests/ui/try-block/try-is-identifier-edition2015.rs index 54bd049442fc..99f4d2068599 100644 --- a/tests/ui/try-block/try-is-identifier-edition2015.rs +++ b/tests/ui/try-block/try-is-identifier-edition2015.rs @@ -1,7 +1,7 @@ //@ run-pass #![allow(non_camel_case_types)] -//@ compile-flags: --edition 2015 +//@ edition: 2015 fn main() { let try = 2; diff --git a/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug.rs b/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug.rs index 4f3f6d37eff4..f69fd5747b65 100644 --- a/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug.rs +++ b/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug.rs @@ -1,4 +1,4 @@ -//@ compile-flags: --edition=2021 +//@ edition: 2021 //@ build-pass #![feature(type_alias_impl_trait)] diff --git a/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs b/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs index cad1cbf61a29..736a9dfb4903 100644 --- a/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs +++ b/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs @@ -1,4 +1,5 @@ -//@ compile-flags: --edition=2021 --crate-type=lib +//@ compile-flags: --crate-type=lib +//@ edition: 2021 //@ rustc-env:RUST_BACKTRACE=0 //@ check-pass diff --git a/tests/ui/type-alias-impl-trait/issue-93411.rs b/tests/ui/type-alias-impl-trait/issue-93411.rs index 11cbb8766315..614d2d0471b9 100644 --- a/tests/ui/type-alias-impl-trait/issue-93411.rs +++ b/tests/ui/type-alias-impl-trait/issue-93411.rs @@ -2,7 +2,7 @@ // this test used to stack overflow due to infinite recursion. //@ check-pass -//@ compile-flags: --edition=2018 +//@ edition: 2018 use std::future::Future; diff --git a/tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs b/tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs index 08f3c404bed6..7f0f6a214aae 100644 --- a/tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs +++ b/tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs @@ -1,7 +1,7 @@ #![feature(type_alias_impl_trait)] //@ check-pass //@ revisions: default edition2021 -//@[edition2021] compile-flags: --edition 2021 +//@[edition2021]edition: 2021 fn main() { type T = impl Copy; diff --git a/tests/ui/use/auxiliary/extern-use-primitive-type-lib.rs b/tests/ui/use/auxiliary/extern-use-primitive-type-lib.rs index 18aa329ae36b..c21eea743e92 100644 --- a/tests/ui/use/auxiliary/extern-use-primitive-type-lib.rs +++ b/tests/ui/use/auxiliary/extern-use-primitive-type-lib.rs @@ -1,3 +1,3 @@ -//@ compile-flags: --edition=2018 +//@ edition: 2018 pub use u32; From cd3a7bb9616959f34028bd4530387d9406964cec Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Tue, 8 Apr 2025 15:33:06 +0200 Subject: [PATCH 298/606] ensure //@compile-flags are last even when passing --edition --- src/tools/compiletest/src/header.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index a0178f4bcc57..21bd69d59b0e 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -385,7 +385,9 @@ impl TestProps { } if let Some(edition) = config.parse_edition(ln) { - self.compile_flags.push(format!("--edition={}", edition.trim())); + // The edition is added at the start, since flags from //@compile-flags must + // be passed to rustc last. + self.compile_flags.insert(0, format!("--edition={}", edition.trim())); has_edition = true; } @@ -606,7 +608,9 @@ impl TestProps { } if let (Some(edition), false) = (&config.edition, has_edition) { - self.compile_flags.push(format!("--edition={}", edition)); + // The edition is added at the start, since flags from //@compile-flags must be passed + // to rustc last. + self.compile_flags.insert(0, format!("--edition={}", edition)); } } From 2638e4e8b226ea1a51247f3660691ed5543cbf7d Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Tue, 8 Apr 2025 15:36:12 +0200 Subject: [PATCH 299/606] prevent configuring the edition with //@compile-flags --- src/tools/compiletest/src/header.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 21bd69d59b0e..80274613768c 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -378,7 +378,13 @@ impl TestProps { } if let Some(flags) = config.parse_name_value_directive(ln, COMPILE_FLAGS) { - self.compile_flags.extend(split_flags(&flags)); + let flags = split_flags(&flags); + for flag in &flags { + if flag == "--edition" || flag.starts_with("--edition=") { + panic!("you must use `//@ edition` to configure the edition"); + } + } + self.compile_flags.extend(flags); } if config.parse_name_value_directive(ln, INCORRECT_COMPILER_FLAGS).is_some() { panic!("`compiler-flags` directive should be spelled `compile-flags`"); From 9cf6e8cbf6c2d50b9eae23fb1ce25cd087778068 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Tue, 8 Apr 2025 15:41:26 +0200 Subject: [PATCH 300/606] include --edition in the compiletest stamp --- src/tools/compiletest/src/runtest.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 08fccb7c1de0..48e8c7d2db59 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -177,6 +177,7 @@ pub fn compute_stamp_hash(config: &Config) -> String { let mut hash = DefaultHasher::new(); config.stage_id.hash(&mut hash); config.run.hash(&mut hash); + config.edition.hash(&mut hash); match config.debugger { Some(Debugger::Cdb) => { From b1053fdb76cca8b2006558207b3b1c939c3df333 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Wed, 9 Apr 2025 09:45:56 +0300 Subject: [PATCH 301/606] handle `config.channel` default for tarballs Signed-off-by: onur-ozkan --- src/bootstrap/src/core/config/config.rs | 33 ++++++++++++++----------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 1712be7f947f..9532cfa711f4 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -1540,9 +1540,6 @@ impl Config { } } - let file_content = t!(fs::read_to_string(config.src.join("src/ci/channel"))); - let ci_channel = file_content.trim_end(); - // Give a hard error if `--config` or `RUST_BOOTSTRAP_CONFIG` are set to a missing path, // but not if `bootstrap.toml` hasn't been created. let mut toml = if !using_default_path || toml_path.exists() { @@ -1847,17 +1844,21 @@ impl Config { let mut lld_enabled = None; let mut std_features = None; - let is_user_configured_rust_channel = - if let Some(channel) = toml.rust.as_ref().and_then(|r| r.channel.clone()) { - if channel == "auto-detect" { - config.channel = ci_channel.into(); - } else { - config.channel = channel; - } + let file_content = t!(fs::read_to_string(config.src.join("src/ci/channel"))); + let ci_channel = file_content.trim_end(); + + let toml_channel = toml.rust.as_ref().and_then(|r| r.channel.clone()); + let is_user_configured_rust_channel = match toml_channel { + Some(channel) if channel == "auto-detect" => { + config.channel = ci_channel.into(); true - } else { - false - }; + } + Some(channel) => { + config.channel = channel; + true + } + None => false, + }; let default = config.channel == "dev"; config.omit_git_hash = toml.rust.as_ref().and_then(|r| r.omit_git_hash).unwrap_or(default); @@ -1882,6 +1883,10 @@ impl Config { && config.src.join(".cargo/config.toml").exists(), ); + if !is_user_configured_rust_channel && config.rust_info.is_from_tarball() { + config.channel = ci_channel.into(); + } + if let Some(rust) = toml.rust { let Rust { optimize: optimize_toml, @@ -2085,8 +2090,6 @@ impl Config { config.channel = channel; } - } else if config.rust_info.is_from_tarball() && !is_user_configured_rust_channel { - ci_channel.clone_into(&mut config.channel); } if let Some(llvm) = toml.llvm { From f80b12129ea8a58464a685abefd1f36819d3dd7b Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 10 Apr 2025 08:15:03 +0000 Subject: [PATCH 302/606] Avoid some more duplication --- compiler/rustc_hir_typeck/src/coercion.rs | 38 ++++++++--------------- 1 file changed, 13 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index ec198c252975..fd899425f62d 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -586,17 +586,12 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // for the former and let type inference do the rest. let coerce_target = self.next_ty_var(self.cause.span); - let mut coercion = match reborrow { - None => { - self.unify_and(coerce_target, target, [], Adjust::Pointer(PointerCoercion::Unsize))? - } - Some((ref deref, ref autoref)) => self.unify_and( - coerce_target, - target, - [deref.clone(), autoref.clone()], - Adjust::Pointer(PointerCoercion::Unsize), - )?, - }; + let mut coercion = self.unify_and( + coerce_target, + target, + reborrow.into_iter().flat_map(|(deref, autoref)| [deref, autoref]), + Adjust::Pointer(PointerCoercion::Unsize), + )?; let mut selcx = traits::SelectionContext::new(self); @@ -836,20 +831,13 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { && hdr_b.safety.is_unsafe() { let unsafe_a = self.tcx.safe_to_unsafe_fn_ty(fn_ty_a); - match adjustment { - Some(kind) => self.unify_and( - unsafe_a, - b, - [Adjustment { kind, target: Ty::new_fn_ptr(self.tcx, fn_ty_a) }], - Adjust::Pointer(PointerCoercion::UnsafeFnPointer), - ), - None => self.unify_and( - unsafe_a, - b, - [], - Adjust::Pointer(PointerCoercion::UnsafeFnPointer), - ), - } + self.unify_and( + unsafe_a, + b, + adjustment + .map(|kind| Adjustment { kind, target: Ty::new_fn_ptr(self.tcx, fn_ty_a) }), + Adjust::Pointer(PointerCoercion::UnsafeFnPointer), + ) } else { let a = Ty::new_fn_ptr(self.tcx, fn_ty_a); match adjustment { From 88a82be263e40093d176ca1dd8f544eee2a88084 Mon Sep 17 00:00:00 2001 From: LorrensP-2158466 Date: Tue, 25 Feb 2025 20:50:12 +0100 Subject: [PATCH 303/606] feature: implement WAIT & WAKE operations of FreeBSD _umtx_op syscall for Futex support --- src/tools/miri/ci/ci.sh | 2 +- .../src/shims/unix/freebsd/foreign_items.rs | 8 + src/tools/miri/src/shims/unix/freebsd/mod.rs | 1 + src/tools/miri/src/shims/unix/freebsd/sync.rs | 251 +++++++++++++++++ .../pass-dep/concurrency/freebsd-futex.rs | 260 ++++++++++++++++++ 5 files changed, 521 insertions(+), 1 deletion(-) create mode 100644 src/tools/miri/src/shims/unix/freebsd/sync.rs create mode 100644 src/tools/miri/tests/pass-dep/concurrency/freebsd-futex.rs diff --git a/src/tools/miri/ci/ci.sh b/src/tools/miri/ci/ci.sh index 7155d692ee5c..b690bd9cd2b9 100755 --- a/src/tools/miri/ci/ci.sh +++ b/src/tools/miri/ci/ci.sh @@ -164,7 +164,7 @@ case $HOST_TARGET in # Partially supported targets (tier 2) BASIC="empty_main integer heap_alloc libc-mem vec string btreemap" # ensures we have the basics: pre-main code, system allocator UNIX="hello panic/panic panic/unwind concurrency/simple atomic libc-mem libc-misc libc-random env num_cpus" # the things that are very similar across all Unixes, and hence easily supported there - TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal $BASIC $UNIX time hashmap random threadname pthread fs libc-pipe + TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal $BASIC $UNIX time hashmap random threadname pthread fs libc-pipe concurrency sync TEST_TARGET=i686-unknown-freebsd run_tests_minimal $BASIC $UNIX time hashmap random threadname pthread fs libc-pipe TEST_TARGET=aarch64-linux-android run_tests_minimal $BASIC $UNIX time hashmap random sync concurrency thread epoll eventfd TEST_TARGET=wasm32-wasip2 run_tests_minimal $BASIC wasm diff --git a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs index 08d06fe5d4c6..21a386b29272 100644 --- a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs @@ -2,6 +2,7 @@ use rustc_middle::ty::Ty; use rustc_span::Symbol; use rustc_target::callconv::{Conv, FnAbi}; +use super::sync::EvalContextExt as _; use crate::shims::unix::*; use crate::*; @@ -55,6 +56,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(res, dest)?; } + // Synchronization primitives + "_umtx_op" => { + let [obj, op, val, uaddr, uaddr2] = + this.check_shim(abi, Conv::C, link_name, args)?; + this._umtx_op(obj, op, val, uaddr, uaddr2, dest)?; + } + // File related shims // For those, we both intercept `func` and `call@FBSD_1.0` symbols cases // since freebsd 12 the former form can be expected. diff --git a/src/tools/miri/src/shims/unix/freebsd/mod.rs b/src/tools/miri/src/shims/unix/freebsd/mod.rs index 09c6507b24f8..50fb2b9d3287 100644 --- a/src/tools/miri/src/shims/unix/freebsd/mod.rs +++ b/src/tools/miri/src/shims/unix/freebsd/mod.rs @@ -1 +1,2 @@ pub mod foreign_items; +pub mod sync; diff --git a/src/tools/miri/src/shims/unix/freebsd/sync.rs b/src/tools/miri/src/shims/unix/freebsd/sync.rs new file mode 100644 index 000000000000..54650f35b2cb --- /dev/null +++ b/src/tools/miri/src/shims/unix/freebsd/sync.rs @@ -0,0 +1,251 @@ +//! Contains FreeBSD-specific synchronization functions + +use core::time::Duration; + +use crate::concurrency::sync::FutexRef; +use crate::*; + +pub struct FreeBsdFutex { + futex: FutexRef, +} + +/// Extended variant of the `timespec` struct. +pub struct UmtxTime { + timeout: Duration, + abs_time: bool, + timeout_clock: TimeoutClock, +} + +impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} +pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { + /// Implementation of the FreeBSD [`_umtx_op`](https://man.freebsd.org/cgi/man.cgi?query=_umtx_op&sektion=2&manpath=FreeBSD+14.2-RELEASE+and+Ports) syscall. + /// This is used for futex operations on FreeBSD. + /// + /// `obj`: a pointer to the futex object (can be a lot of things, mostly *AtomicU32) + /// `op`: the futex operation to run + /// `val`: the current value of the object as a `c_long` (for wait/wake) + /// `uaddr`: `op`-specific optional parameter, pointer-sized integer or pointer to an `op`-specific struct + /// `uaddr2`: `op`-specific optional parameter, pointer-sized integer or pointer to an `op`-specific struct + /// `dest`: the place this syscall returns to, 0 for success, -1 for failure + /// + /// # Note + /// Curently only the WAIT and WAKE operations are implemented. + fn _umtx_op( + &mut self, + obj: &OpTy<'tcx>, + op: &OpTy<'tcx>, + val: &OpTy<'tcx>, + uaddr: &OpTy<'tcx>, + uaddr2: &OpTy<'tcx>, + dest: &MPlaceTy<'tcx>, + ) -> InterpResult<'tcx> { + let this = self.eval_context_mut(); + + let obj = this.read_pointer(obj)?; + let op = this.read_scalar(op)?.to_i32()?; + let val = this.read_target_usize(val)?; + let uaddr = this.read_target_usize(uaddr)?; + let uaddr2 = this.read_pointer(uaddr2)?; + + let wait = this.eval_libc_i32("UMTX_OP_WAIT"); + let wait_uint = this.eval_libc_i32("UMTX_OP_WAIT_UINT"); + let wait_uint_private = this.eval_libc_i32("UMTX_OP_WAIT_UINT_PRIVATE"); + + let wake = this.eval_libc_i32("UMTX_OP_WAKE"); + let wake_private = this.eval_libc_i32("UMTX_OP_WAKE_PRIVATE"); + + let timespec_layout = this.libc_ty_layout("timespec"); + let umtx_time_layout = this.libc_ty_layout("_umtx_time"); + assert!( + timespec_layout.size != umtx_time_layout.size, + "`struct timespec` and `struct _umtx_time` should have different sizes." + ); + + match op { + // UMTX_OP_WAIT_UINT and UMTX_OP_WAIT_UINT_PRIVATE only differ in whether they work across + // processes or not. For Miri, we can treat them the same. + op if op == wait || op == wait_uint || op == wait_uint_private => { + let obj_layout = + if op == wait { this.machine.layouts.isize } else { this.machine.layouts.u32 }; + let obj = this.ptr_to_mplace(obj, obj_layout); + + // Read the Linux futex wait implementation in Miri to understand why this fence is needed. + this.atomic_fence(AtomicFenceOrd::SeqCst)?; + let obj_val = this + .read_scalar_atomic(&obj, AtomicReadOrd::Acquire)? + .to_bits(obj_layout.size)?; // isize and u32 can have different sizes + + if obj_val == u128::from(val) { + // This cannot fail since we already did an atomic acquire read on that pointer. + // Acquire reads are only allowed on mutable memory. + let futex_ref = this + .get_sync_or_init(obj.ptr(), |_| FreeBsdFutex { futex: Default::default() }) + .unwrap() + .futex + .clone(); + + // From the manual: + // The timeout is specified by passing either the address of `struct timespec`, or its + // extended variant, `struct _umtx_time`, as the `uaddr2` argument of _umtx_op(). + // They are distinguished by the `uaddr` value, which must be equal + // to the size of the structure pointed to by `uaddr2`, casted to uintptr_t. + let timeout = if this.ptr_is_null(uaddr2)? { + // no timeout parameter + None + } else { + if uaddr == umtx_time_layout.size.bytes() { + // `uaddr2` points to a `struct _umtx_time`. + let umtx_time_place = this.ptr_to_mplace(uaddr2, umtx_time_layout); + + let umtx_time = match this.read_umtx_time(&umtx_time_place)? { + Some(ut) => ut, + None => { + return this + .set_last_error_and_return(LibcError("EINVAL"), dest); + } + }; + + let anchor = if umtx_time.abs_time { + TimeoutAnchor::Absolute + } else { + TimeoutAnchor::Relative + }; + + Some((umtx_time.timeout_clock, anchor, umtx_time.timeout)) + } else if uaddr == timespec_layout.size.bytes() { + // RealTime clock can't be used in isolation mode. + this.check_no_isolation("`_umtx_op` with `timespec` timeout")?; + + // `uaddr2` points to a `struct timespec`. + let timespec = this.ptr_to_mplace(uaddr2, timespec_layout); + let duration = match this.read_timespec(×pec)? { + Some(duration) => duration, + None => { + return this + .set_last_error_and_return(LibcError("EINVAL"), dest); + } + }; + + // FreeBSD does not seem to document which clock is used when the timeout + // is passed as a `struct timespec*`. Based on discussions online and the source + // code (umtx_copyin_umtx_time() in kern_umtx.c), it seems to default to CLOCK_REALTIME, + // so that's what we also do. + // Discussion in golang: https://github.com/golang/go/issues/17168#issuecomment-250235271 + Some((TimeoutClock::RealTime, TimeoutAnchor::Relative, duration)) + } else { + return this.set_last_error_and_return(LibcError("EINVAL"), dest); + } + }; + + let dest = dest.clone(); + this.futex_wait( + futex_ref, + u32::MAX, // we set the bitset to include all bits + timeout, + callback!( + @capture<'tcx> { + dest: MPlaceTy<'tcx>, + } + |ecx, unblock: UnblockKind| match unblock { + UnblockKind::Ready => { + // From the manual: + // If successful, all requests, except UMTX_SHM_CREAT and UMTX_SHM_LOOKUP + // sub-requests of the UMTX_OP_SHM request, will return zero. + ecx.write_int(0, &dest) + } + UnblockKind::TimedOut => { + ecx.set_last_error_and_return(LibcError("ETIMEDOUT"), &dest) + } + } + ), + ); + interp_ok(()) + } else { + // The manual doesn’t specify what should happen if the futex value doesn’t match the expected one. + // On FreeBSD 14.2, testing shows that WAIT operations return 0 even when the value is incorrect. + this.write_int(0, dest)?; + interp_ok(()) + } + } + // UMTX_OP_WAKE and UMTX_OP_WAKE_PRIVATE only differ in whether they work across + // processes or not. For Miri, we can treat them the same. + op if op == wake || op == wake_private => { + let Some(futex_ref) = + this.get_sync_or_init(obj, |_| FreeBsdFutex { futex: Default::default() }) + else { + // From Linux implemenation: + // No AllocId, or no live allocation at that AllocId. + // Return an error code. (That seems nicer than silently doing something non-intuitive.) + // This means that if an address gets reused by a new allocation, + // we'll use an independent futex queue for this... that seems acceptable. + return this.set_last_error_and_return(LibcError("EFAULT"), dest); + }; + let futex_ref = futex_ref.futex.clone(); + + // Saturating cast for when usize is smaller than u64. + let count = usize::try_from(val).unwrap_or(usize::MAX); + + // Read the Linux futex wake implementation in Miri to understand why this fence is needed. + this.atomic_fence(AtomicFenceOrd::SeqCst)?; + + // `_umtx_op` doesn't return the amount of woken threads. + let _woken = this.futex_wake( + &futex_ref, + u32::MAX, // we set the bitset to include all bits + count, + )?; + + // From the manual: + // If successful, all requests, except UMTX_SHM_CREAT and UMTX_SHM_LOOKUP + // sub-requests of the UMTX_OP_SHM request, will return zero. + this.write_int(0, dest)?; + interp_ok(()) + } + op => { + throw_unsup_format!("Miri does not support `_umtx_op` syscall with op={}", op) + } + } + } + + /// Parses a `_umtx_time` struct. + /// Returns `None` if the underlying `timespec` struct is invalid. + fn read_umtx_time(&mut self, ut: &MPlaceTy<'tcx>) -> InterpResult<'tcx, Option> { + let this = self.eval_context_mut(); + // Only flag allowed is UMTX_ABSTIME. + let abs_time = this.eval_libc_u32("UMTX_ABSTIME"); + + let timespec_place = this.project_field(ut, 0)?; + // Inner `timespec` must still be valid. + let duration = match this.read_timespec(×pec_place)? { + Some(dur) => dur, + None => return interp_ok(None), + }; + + let flags_place = this.project_field(ut, 1)?; + let flags = this.read_scalar(&flags_place)?.to_u32()?; + let abs_time_flag = flags == abs_time; + + let clock_id_place = this.project_field(ut, 2)?; + let clock_id = this.read_scalar(&clock_id_place)?.to_i32()?; + let timeout_clock = this.translate_umtx_time_clock_id(clock_id)?; + + interp_ok(Some(UmtxTime { timeout: duration, abs_time: abs_time_flag, timeout_clock })) + } + + /// Translate raw FreeBSD clockid to a Miri TimeoutClock. + /// FIXME: share this code with the pthread and clock_gettime shims. + fn translate_umtx_time_clock_id(&mut self, raw_id: i32) -> InterpResult<'tcx, TimeoutClock> { + let this = self.eval_context_mut(); + + let timeout = if raw_id == this.eval_libc_i32("CLOCK_REALTIME") { + // RealTime clock can't be used in isolation mode. + this.check_no_isolation("`_umtx_op` with `CLOCK_REALTIME` timeout")?; + TimeoutClock::RealTime + } else if raw_id == this.eval_libc_i32("CLOCK_MONOTONIC") { + TimeoutClock::Monotonic + } else { + throw_unsup_format!("unsupported clock id {raw_id}"); + }; + interp_ok(timeout) + } +} diff --git a/src/tools/miri/tests/pass-dep/concurrency/freebsd-futex.rs b/src/tools/miri/tests/pass-dep/concurrency/freebsd-futex.rs new file mode 100644 index 000000000000..38a0bf58148e --- /dev/null +++ b/src/tools/miri/tests/pass-dep/concurrency/freebsd-futex.rs @@ -0,0 +1,260 @@ +//@only-target: freebsd +//@compile-flags: -Zmiri-preemption-rate=0 -Zmiri-disable-isolation + +use std::mem::{self, MaybeUninit}; +use std::ptr::{self, addr_of}; +use std::sync::atomic::AtomicU32; +use std::time::Instant; +use std::{io, thread}; + +fn wait_wake() { + fn wake_nobody() { + // Current thread waits on futex. + // New thread wakes up 0 threads waiting on that futex. + // Current thread should time out. + static mut FUTEX: u32 = 0; + + let waker = thread::spawn(|| { + unsafe { + assert_eq!( + libc::_umtx_op( + addr_of!(FUTEX) as *mut _, + libc::UMTX_OP_WAKE_PRIVATE, + 0, // wake up 0 waiters + ptr::null_mut::(), + ptr::null_mut::(), + ), + 0 + ); + } + }); + + // 10ms should be enough. + let mut timeout = libc::timespec { tv_sec: 0, tv_nsec: 10_000_000 }; + let timeout_size_arg = + ptr::without_provenance_mut::(mem::size_of::()); + unsafe { + assert_eq!( + libc::_umtx_op( + addr_of!(FUTEX) as *mut _, + libc::UMTX_OP_WAIT_UINT_PRIVATE, + 0, + timeout_size_arg, + &mut timeout as *mut _ as _, + ), + -1 + ); + // Main thread did not get woken up, so it timed out. + assert_eq!(io::Error::last_os_error().raw_os_error().unwrap(), libc::ETIMEDOUT); + } + + waker.join().unwrap(); + } + + fn wake_two_of_three() { + // We create 2 threads that wait on a futex with a 100ms timeout. + // The main thread wakes up 2 threads waiting on this futex and after this + // checks that only those threads woke up and the other one timed out. + static mut FUTEX: u32 = 0; + + fn waiter() -> bool { + let mut timeout = libc::timespec { tv_sec: 0, tv_nsec: 100_000_000 }; + let timeout_size_arg = + ptr::without_provenance_mut::(mem::size_of::()); + unsafe { + libc::_umtx_op( + addr_of!(FUTEX) as *mut _, + libc::UMTX_OP_WAIT_UINT_PRIVATE, + 0, // FUTEX is 0 + timeout_size_arg, + &mut timeout as *mut _ as _, + ); + // Return true if this thread woke up. + io::Error::last_os_error().raw_os_error().unwrap() != libc::ETIMEDOUT + } + } + + let t1 = thread::spawn(waiter); + let t2 = thread::spawn(waiter); + let t3 = thread::spawn(waiter); + + // Run all the waiters, so they can go to sleep. + thread::yield_now(); + + // Wake up 2 thread and make sure 1 is still waiting. + unsafe { + assert_eq!( + libc::_umtx_op( + addr_of!(FUTEX) as *mut _, + libc::UMTX_OP_WAKE_PRIVATE, + 2, + ptr::null_mut::(), + ptr::null_mut::(), + ), + 0 + ); + } + + // Treat the booleans as numbers to simplify checking how many threads were woken up. + let t1 = t1.join().unwrap() as usize; + let t2 = t2.join().unwrap() as usize; + let t3 = t3.join().unwrap() as usize; + let woken_up_count = t1 + t2 + t3; + assert!(woken_up_count == 2, "Expected 2 threads to wake up got: {woken_up_count}"); + } + + wake_nobody(); + wake_two_of_three(); +} + +fn wake_dangling() { + let futex = Box::new(0); + let ptr: *const u32 = &*futex; + drop(futex); + + // Expect error since this is now "unmapped" memory. + unsafe { + assert_eq!( + libc::_umtx_op( + ptr as *const AtomicU32 as *mut _, + libc::UMTX_OP_WAKE_PRIVATE, + 0, + ptr::null_mut::(), + ptr::null_mut::(), + ), + -1 + ); + assert_eq!(io::Error::last_os_error().raw_os_error().unwrap(), libc::EFAULT); + } +} + +fn wait_wrong_val() { + let futex: u32 = 123; + + // Wait with a wrong value just returns 0 + unsafe { + assert_eq!( + libc::_umtx_op( + ptr::from_ref(&futex).cast_mut().cast(), + libc::UMTX_OP_WAIT_UINT_PRIVATE, + 456, + ptr::null_mut::(), + ptr::null_mut::(), + ), + 0 + ); + } +} + +fn wait_relative_timeout() { + fn without_timespec() { + let start = Instant::now(); + + let futex: u32 = 123; + + let mut timeout = libc::timespec { tv_sec: 0, tv_nsec: 200_000_000 }; + let timeout_size_arg = + ptr::without_provenance_mut::(mem::size_of::()); + // Wait for 200ms, with nobody waking us up early + unsafe { + assert_eq!( + libc::_umtx_op( + ptr::from_ref(&futex).cast_mut().cast(), + libc::UMTX_OP_WAIT_UINT_PRIVATE, + 123, + timeout_size_arg, + &mut timeout as *mut _ as _, + ), + -1 + ); + assert_eq!(io::Error::last_os_error().raw_os_error().unwrap(), libc::ETIMEDOUT); + } + + assert!((200..1000).contains(&start.elapsed().as_millis())); + } + + fn with_timespec() { + let futex: u32 = 123; + let mut timeout = libc::_umtx_time { + _timeout: libc::timespec { tv_sec: 0, tv_nsec: 200_000_000 }, + _flags: 0, + _clockid: libc::CLOCK_MONOTONIC as u32, + }; + let timeout_size_arg = + ptr::without_provenance_mut::(mem::size_of::()); + + let start = Instant::now(); + + // Wait for 200ms, with nobody waking us up early + unsafe { + assert_eq!( + libc::_umtx_op( + ptr::from_ref(&futex).cast_mut().cast(), + libc::UMTX_OP_WAIT_UINT_PRIVATE, + 123, + timeout_size_arg, + &mut timeout as *mut _ as _, + ), + -1 + ); + assert_eq!(io::Error::last_os_error().raw_os_error().unwrap(), libc::ETIMEDOUT); + } + assert!((200..1000).contains(&start.elapsed().as_millis())); + } + + without_timespec(); + with_timespec(); +} + +fn wait_absolute_timeout() { + let start = Instant::now(); + + // Get the current monotonic timestamp as timespec. + let mut timeout = unsafe { + let mut now: MaybeUninit = MaybeUninit::uninit(); + assert_eq!(libc::clock_gettime(libc::CLOCK_MONOTONIC, now.as_mut_ptr()), 0); + now.assume_init() + }; + + // Add 200ms. + timeout.tv_nsec += 200_000_000; + if timeout.tv_nsec > 1_000_000_000 { + timeout.tv_nsec -= 1_000_000_000; + timeout.tv_sec += 1; + } + + // Create umtx_timeout struct with that absolute timeout. + let umtx_timeout = libc::_umtx_time { + _timeout: timeout, + _flags: libc::UMTX_ABSTIME, + _clockid: libc::CLOCK_MONOTONIC as u32, + }; + let umtx_timeout_ptr = &umtx_timeout as *const _; + let umtx_timeout_size = ptr::without_provenance_mut(mem::size_of_val(&umtx_timeout)); + + let futex: u32 = 123; + + // Wait for 200ms from now, with nobody waking us up early. + unsafe { + assert_eq!( + libc::_umtx_op( + ptr::from_ref(&futex).cast_mut().cast(), + libc::UMTX_OP_WAIT_UINT_PRIVATE, + 123, + umtx_timeout_size, + umtx_timeout_ptr as *mut _, + ), + -1 + ); + assert_eq!(io::Error::last_os_error().raw_os_error().unwrap(), libc::ETIMEDOUT); + } + assert!((200..1000).contains(&start.elapsed().as_millis())); +} + +fn main() { + wait_wake(); + wake_dangling(); + wait_wrong_val(); + wait_relative_timeout(); + wait_absolute_timeout(); +} From 33794fd1963b917eb691cad0349d1e203040594f Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Thu, 10 Apr 2025 12:34:57 +0200 Subject: [PATCH 304/606] mention --edition restrictions in rustc-dev-guide --- src/doc/rustc-dev-guide/src/tests/directives.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/directives.md b/src/doc/rustc-dev-guide/src/tests/directives.md index 8e4a710178ed..f97f08e33542 100644 --- a/src/doc/rustc-dev-guide/src/tests/directives.md +++ b/src/doc/rustc-dev-guide/src/tests/directives.md @@ -229,14 +229,14 @@ ignoring debuggers. ### Affecting how tests are built -| Directive | Explanation | Supported test suites | Possible values | -|---------------------|----------------------------------------------------------------------------------------------|---------------------------|------------------------------------------------------------------------------| -| `compile-flags` | Flags passed to `rustc` when building the test or aux file | All except for `run-make` | Any valid `rustc` flags, e.g. `-Awarnings -Dfoo`. Cannot be `-Cincremental`. | -| `edition` | Alias for `compile-flags: --edition=xxx` | All except for `run-make` | Any valid `--edition` value | -| `rustc-env` | Env var to set when running `rustc` | All except for `run-make` | `=` | -| `unset-rustc-env` | Env var to unset when running `rustc` | All except for `run-make` | Any env var name | -| `incremental` | Proper incremental support for tests outside of incremental test suite | `ui`, `crashes` | N/A | -| `no-prefer-dynamic` | Don't use `-C prefer-dynamic`, don't build as a dylib via a `--crate-type=dylib` preset flag | `ui`, `crashes` | N/A | +| Directive | Explanation | Supported test suites | Possible values | +|---------------------|----------------------------------------------------------------------------------------------|---------------------------|--------------------------------------------------------------------------------------------| +| `compile-flags` | Flags passed to `rustc` when building the test or aux file | All except for `run-make` | Any valid `rustc` flags, e.g. `-Awarnings -Dfoo`. Cannot be `-Cincremental` or `--edition` | +| `edition` | The edition used to build the test | All except for `run-make` | Any valid `--edition` value | +| `rustc-env` | Env var to set when running `rustc` | All except for `run-make` | `=` | +| `unset-rustc-env` | Env var to unset when running `rustc` | All except for `run-make` | Any env var name | +| `incremental` | Proper incremental support for tests outside of incremental test suite | `ui`, `crashes` | N/A | +| `no-prefer-dynamic` | Don't use `-C prefer-dynamic`, don't build as a dylib via a `--crate-type=dylib` preset flag | `ui`, `crashes` | N/A |
Tests (outside of `run-make`) that want to use incremental tests not in the From 95613e3dbccd4d5a6ecd0a6906ac8fe609d14d03 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Thu, 10 Apr 2025 12:40:27 +0200 Subject: [PATCH 305/606] Remove unnecessary `mut`. The value is moved in pin!(). --- tests/ui/sanitizer/cfi/coroutine.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/sanitizer/cfi/coroutine.rs b/tests/ui/sanitizer/cfi/coroutine.rs index 3ad896afd00b..39a754f10363 100644 --- a/tests/ui/sanitizer/cfi/coroutine.rs +++ b/tests/ui/sanitizer/cfi/coroutine.rs @@ -26,7 +26,7 @@ use std::async_iter::AsyncIterator; #[test] fn general_coroutine() { - let mut coro = #[coroutine] |x: i32| { + let coro = #[coroutine] |x: i32| { yield x; "done" }; From dc3843b70ee1f1beee889f2f1c0000919a012db5 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 10 Apr 2025 10:34:11 +0200 Subject: [PATCH 306/606] make GetFullPathNameW more correct on non-Windows hosts --- .../miri/src/shims/windows/foreign_items.rs | 118 +++++++++++++----- src/tools/miri/tests/pass/path.rs | 24 +++- 2 files changed, 104 insertions(+), 38 deletions(-) diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs index fae6170a9e72..31ff34768506 100644 --- a/src/tools/miri/src/shims/windows/foreign_items.rs +++ b/src/tools/miri/src/shims/windows/foreign_items.rs @@ -26,57 +26,107 @@ pub fn is_dyn_sym(name: &str) -> bool { } #[cfg(windows)] -fn win_absolute<'tcx>(path: &Path) -> InterpResult<'tcx, io::Result> { +fn win_get_full_path_name<'tcx>(path: &Path) -> InterpResult<'tcx, io::Result> { // We are on Windows so we can simply let the host do this. interp_ok(path::absolute(path)) } #[cfg(unix)] #[expect(clippy::get_first, clippy::arithmetic_side_effects)] -fn win_absolute<'tcx>(path: &Path) -> InterpResult<'tcx, io::Result> { - // We are on Unix, so we need to implement parts of the logic ourselves. +fn win_get_full_path_name<'tcx>(path: &Path) -> InterpResult<'tcx, io::Result> { + use std::sync::LazyLock; + + use rustc_data_structures::fx::FxHashSet; + + // We are on Unix, so we need to implement parts of the logic ourselves. `path` will use `/` + // separators, and the result should also use `/`. + // See for more + // information about Windows paths. + // This does not handle all corner cases correctly, see + // for more cursed + // examples. let bytes = path.as_os_str().as_encoded_bytes(); - // If it starts with `//` (these were backslashes but are already converted) - // then this is a magic special path, we just leave it unchanged. - if bytes.get(0).copied() == Some(b'/') && bytes.get(1).copied() == Some(b'/') { + // If it starts with `//./` or `//?/` then this is a magic special path, we just leave it + // unchanged. + if bytes.get(0).copied() == Some(b'/') + && bytes.get(1).copied() == Some(b'/') + && matches!(bytes.get(2), Some(b'.' | b'?')) + && bytes.get(3).copied() == Some(b'/') + { return interp_ok(Ok(path.into())); }; - // Special treatment for Windows' magic filenames: they are treated as being relative to `\\.\`. - let magic_filenames = &[ - "CON", "PRN", "AUX", "NUL", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", - "COM9", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9", - ]; - if magic_filenames.iter().any(|m| m.as_bytes() == bytes) { - let mut result: Vec = br"//./".into(); + let is_unc = bytes.starts_with(b"//"); + // Special treatment for Windows' magic filenames: they are treated as being relative to `//./`. + static MAGIC_FILENAMES: LazyLock> = LazyLock::new(|| { + FxHashSet::from_iter([ + "CON", "PRN", "AUX", "NUL", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", + "COM8", "COM9", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9", + ]) + }); + if str::from_utf8(bytes).is_ok_and(|s| MAGIC_FILENAMES.contains(&*s.to_ascii_uppercase())) { + let mut result: Vec = b"//./".into(); result.extend(bytes); return interp_ok(Ok(bytes_to_os_str(&result)?.into())); } // Otherwise we try to do something kind of close to what Windows does, but this is probably not - // right in all cases. We iterate over the components between `/`, and remove trailing `.`, - // except that trailing `..` remain unchanged. - let mut result = vec![]; + // right in all cases. + let mut result: Vec<&[u8]> = vec![]; // will be a vecot of components, joined by `/`. let mut bytes = bytes; // the remaining bytes to process - loop { - let len = bytes.iter().position(|&b| b == b'/').unwrap_or(bytes.len()); - let mut component = &bytes[..len]; - if len >= 2 && component[len - 1] == b'.' && component[len - 2] != b'.' { - // Strip trailing `.` + let mut stop = false; + while !stop { + // Find next component, and advance `bytes`. + let mut component = match bytes.iter().position(|&b| b == b'/') { + Some(pos) => { + let (component, tail) = bytes.split_at(pos); + bytes = &tail[1..]; // remove the `/`. + component + } + None => { + // There's no more `/`. + stop = true; + let component = bytes; + bytes = &[]; + component + } + }; + // `NUL` and only `NUL` also gets changed to be relative to `//./` later in the path. + // (This changed with Windows 11; previously, all magic filenames behaved like this.) + // Also, this does not apply to UNC paths. + if !is_unc && component.eq_ignore_ascii_case(b"NUL") { + let mut result: Vec = b"//./".into(); + result.extend(component); + return interp_ok(Ok(bytes_to_os_str(&result)?.into())); + } + // Deal with `..` -- Windows handles this entirely syntactically. + if component == b".." { + // Remove previous component, unless we are at the "root" already, then just ignore the `..`. + let is_root = { + // Paths like `/C:`. + result.len() == 2 && matches!(result[0], []) && matches!(result[1], [_, b':']) + } || { + // Paths like `//server/share` + result.len() == 4 && matches!(result[0], []) && matches!(result[1], []) + }; + if !is_root { + result.pop(); + } + continue; + } + // Preserve this component. + // Strip trailing `.`, but preserve trailing `..`. But not for UNC paths! + let len = component.len(); + if !is_unc && len >= 2 && component[len - 1] == b'.' && component[len - 2] != b'.' { component = &component[..len - 1]; } // Add this component to output. - result.extend(component); - // Prepare next iteration. - if len < bytes.len() { - // There's a component after this; add `/` and process remaining bytes. - result.push(b'/'); - bytes = &bytes[len + 1..]; - continue; - } else { - // This was the last component and it did not have a trailing `/`. - break; - } + result.push(component); } - // Let the host `absolute` function do working-dir handling + // Drive letters must be followed by a `/`. + if result.len() == 2 && matches!(result[0], []) && matches!(result[1], [_, b':']) { + result.push(&[]); + } + // Let the host `absolute` function do working-dir handling. + let result = result.join(&b'/'); interp_ok(path::absolute(bytes_to_os_str(&result)?)) } @@ -231,7 +281,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } let filename = this.read_path_from_wide_str(filename)?; - let result = match win_absolute(&filename)? { + let result = match win_get_full_path_name(&filename)? { Err(err) => { this.set_last_error(err)?; Scalar::from_u32(0) // return zero upon failure diff --git a/src/tools/miri/tests/pass/path.rs b/src/tools/miri/tests/pass/path.rs index dbca0ea611f7..7428d0afcc67 100644 --- a/src/tools/miri/tests/pass/path.rs +++ b/src/tools/miri/tests/pass/path.rs @@ -6,7 +6,11 @@ mod utils; #[track_caller] fn assert_absolute_eq(in_: &str, out: &str) { - assert_eq!(absolute(in_).unwrap().as_os_str(), Path::new(out).as_os_str()); + assert_eq!( + absolute(in_).unwrap().as_os_str(), + Path::new(out).as_os_str(), + "incorrect absolute path for {in_:?}" + ); } fn test_absolute() { @@ -29,16 +33,28 @@ fn test_absolute() { assert_absolute_eq(r"\\?\C:\path\to\file", r"\\?\C:\path\to\file"); assert_absolute_eq(r"\\?\UNC\server\share\to\file", r"\\?\UNC\server\share\to\file"); assert_absolute_eq(r"\\?\PIPE\name", r"\\?\PIPE\name"); + assert_absolute_eq(r"\\server\share\NUL", r"\\server\share\NUL"); + // This fails on Windows 10 hosts. FIXME: enable this once GHA runners are on Windows 11. + //assert_absolute_eq(r"C:\path\to\COM1", r"C:\path\to\COM1"); // Verbatim paths are always unchanged, no matter what. assert_absolute_eq(r"\\?\path.\to/file..", r"\\?\path.\to/file.."); // Trailing dot is removed here. assert_absolute_eq(r"C:\path..\to.\file.", r"C:\path..\to\file"); // `..` is resolved here. assert_absolute_eq(r"C:\path\to\..\file", r"C:\path\file"); - assert_absolute_eq(r"\\server\share\to\..\file", r"\\server\share\file"); - // Magic filename. + assert_absolute_eq(r"C:\path\to\..\..\file", r"C:\file"); + assert_absolute_eq(r"C:\path\to\..\..\..\..\..\..\file", r"C:\file"); + assert_absolute_eq(r"C:\..", r"C:\"); + assert_absolute_eq(r"\\server\share\to\path\with\..\file", r"\\server\share\to\path\file"); + assert_absolute_eq(r"\\server\share\to\..\..\..\..\file", r"\\server\share\file"); + assert_absolute_eq(r"\\server\share\..", r"\\server\share"); + // Magic filenames. + assert_absolute_eq(r"NUL", r"\\.\NUL"); + assert_absolute_eq(r"nul", r"\\.\nul"); assert_absolute_eq(r"COM1", r"\\.\COM1"); - assert_absolute_eq(r"C:\path\to\COM1", r"\\.\COM1"); + assert_absolute_eq(r"com1", r"\\.\com1"); + assert_absolute_eq(r"C:\path\to\NUL", r"\\.\NUL"); + assert_absolute_eq(r"C:\path\to\nul", r"\\.\nul"); } else { panic!("unsupported OS"); } From ac4014bd2004811851caea3e81c22cbed7b92aa5 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Wed, 22 Jan 2025 16:05:26 -0800 Subject: [PATCH 307/606] Add minimal x86_64-lynx-lynxos178 support. It's possible to build no_std programs with this compiler. > A tier 3 target must have a designated developer or developers (the "target maintainers") on record to be CCed when issues arise regarding the target. (The mechanism to track and CC such developers may evolve over time.) Tim Newsome (@tnewsome-lynx) will be the designated developer for x86_64-lynx-lynxos178 support. > Targets must use naming consistent with any existing targets; for instance, a target for the same CPU or OS as an existing Rust target should use the same name for that CPU or OS. Targets should normally use the same names and naming conventions as used elsewhere in the broader ecosystem beyond Rust (such as in other toolchains), unless they have a very good reason to diverge. Changing the name of a target can be highly disruptive, especially once the target reaches a higher tier, so getting the name right is important even for a tier 3 target. I believe the target is named appropriately. > Target names should not introduce undue confusion or ambiguity unless absolutely necessary to maintain ecosystem compatibility. For example, if the name of the target makes people extremely likely to form incorrect beliefs about what it targets, the name should be changed or augmented to disambiguate it. The target name is not confusing. > If possible, use only letters, numbers, dashes and underscores for the name. Periods (.) are known to cause issues in Cargo. Done. > Tier 3 targets may have unusual requirements to build or use, but must not create legal issues or impose onerous legal terms for the Rust project or for Rust developers or users. > The target must not introduce license incompatibilities. > Anything added to the Rust repository must be under the standard Rust license (MIT OR Apache-2.0). All this new code is licensed under the Apache-2.0 license. > The target must not cause the Rust tools or libraries built for any other host (even when supporting cross-compilation to the target) to depend on any new dependency less permissive than the Rust licensing policy. This applies whether the dependency is a Rust crate that would require adding new license exceptions (as specified by the tidy tool in the rust-lang/rust repository), or whether the dependency is a native library or binary. In other words, the introduction of the target must not cause a user installing or running a version of Rust or the Rust tools to be subject to any new license requirements. Done. > Compiling, linking, and emitting functional binaries, libraries, or other code for the target (whether hosted on the target itself or cross-compiling from another target) must not depend on proprietary (non-FOSS) libraries. Host tools built for the target itself may depend on the ordinary runtime libraries supplied by the platform and commonly used by other applications built for the target, but those libraries must not be required for code generation for the target; cross-compilation to the target must not require such libraries at all. For instance, rustc built for the target may depend on a common proprietary C runtime library or console output library, but must not depend on a proprietary code generation library or code optimization library. Rust's license permits such combinations, but the Rust project has no interest in maintaining such combinations within the scope of Rust itself, even at tier 3. I think we're in the clear here. We do link against some static libraries that are proprietary (like libm and libc), but those are not used to generate code. E.g. the VxWorks target requires `wr-c++` to be installed, which is not publically available. > "onerous" here is an intentionally subjective term. At a minimum, "onerous" legal/licensing terms include but are not limited to: non-disclosure requirements, non-compete requirements, contributor license agreements (CLAs) or equivalent, "non-commercial"/"research-only"/etc terms, requirements conditional on the employer or employment of any particular Rust developers, revocable terms, any requirements that create liability for the Rust project or its developers or users, or any requirements that adversely affect the livelihood or prospects of the Rust project or its developers or users. Our intention is to allow anyone with access to LynxOS CDK to use Rust for it. > Neither this policy nor any decisions made regarding targets shall create any binding agreement or estoppel by any party. If any member of an approving Rust team serves as one of the maintainers of a target, or has any legal or employment requirement (explicit or implicit) that might affect their decisions regarding a target, they must recuse themselves from any approval decisions regarding the target's tier status, though they may otherwise participate in discussions. > This requirement does not prevent part or all of this policy from being cited in an explicit contract or work agreement (e.g. to implement or maintain support for a target). This requirement exists to ensure that a developer or team responsible for reviewing and approving a target does not face any legal threats or obligations that would prevent them from freely exercising their judgment in such approval, even if such judgment involves subjective matters or goes beyond the letter of these requirements. No problem. > Tier 3 targets should attempt to implement as much of the standard libraries as possible and appropriate (core for most targets, alloc for targets that can support dynamic memory allocation, std for targets with an operating system or equivalent layer of system-provided functionality), but may leave some code unimplemented (either unavailable or stubbed out as appropriate), whether because the target makes it impossible to implement or challenging to implement. The authors of pull requests are not obligated to avoid calling any portions of the standard library on the basis of a tier 3 target not implementing those portions. With this first PR, only core is supported. I am working on support for the std library and intend to submit that once all the tests are passing. > The target must provide documentation for the Rust community explaining how to build for the target, using cross-compilation if possible. If the target supports running binaries, or running tests (even if they do not pass), the documentation must explain how to run such binaries or tests for the target, using emulation if possible or dedicated hardware if necessary. This is documented in `src/doc/rustc/src/platform-support/lynxos_178.md`. > Tier 3 targets must not impose burden on the authors of pull requests, or other developers in the community, to maintain the target. In particular, do not post comments (automated or manual) on a PR that derail or suggest a block on the PR based on a tier 3 target. Do not send automated messages or notifications (via any medium, including via @) to a PR author or others involved with a PR regarding a tier 3 target, unless they have opted into such messages. > Backlinks such as those generated by the issue/PR tracker when linking to an issue or PR are not considered a violation of this policy, within reason. However, such messages (even on a separate repository) must not generate notifications to anyone involved with a PR who has not requested such notifications. Understood. > Patches adding or updating tier 3 targets must not break any existing tier 2 or tier 1 target, and must not knowingly break another tier 3 target without approval of either the compiler team or the maintainers of the other tier 3 target. > In particular, this may come up when working on closely related targets, such as variations of the same architecture with different features. Avoid introducing unconditional uses of features that another variation of the target may not have; use conditional compilation or runtime detection, as appropriate, to let each target run code supported by that target. As far as I know this change does not affect any other targets. > Tier 3 targets must be able to produce assembly using at least one of rustc's supported backends from any host target. (Having support in a fork of the backend is not sufficient, it must be upstream.) Many targets produce assembly for x86_64 so that also works for LynxOS-178. --- .../rustc_target/src/spec/base/lynxos178.rs | 31 ++++++++ compiler/rustc_target/src/spec/base/mod.rs | 1 + compiler/rustc_target/src/spec/mod.rs | 1 + .../src/spec/targets/x86_64_lynx_lynxos178.rs | 34 ++++++++ src/bootstrap/src/core/sanity.rs | 1 + src/doc/rustc/src/SUMMARY.md | 1 + src/doc/rustc/src/platform-support.md | 1 + .../rustc/src/platform-support/lynxos178.md | 77 +++++++++++++++++++ tests/assembly/targets/targets-elf.rs | 3 + tests/ui/check-cfg/well-known-values.stderr | 4 +- 10 files changed, 152 insertions(+), 2 deletions(-) create mode 100644 compiler/rustc_target/src/spec/base/lynxos178.rs create mode 100644 compiler/rustc_target/src/spec/targets/x86_64_lynx_lynxos178.rs create mode 100644 src/doc/rustc/src/platform-support/lynxos178.md diff --git a/compiler/rustc_target/src/spec/base/lynxos178.rs b/compiler/rustc_target/src/spec/base/lynxos178.rs new file mode 100644 index 000000000000..b9434ff5faaf --- /dev/null +++ b/compiler/rustc_target/src/spec/base/lynxos178.rs @@ -0,0 +1,31 @@ +use std::borrow::Cow; + +use crate::spec::{ + PanicStrategy, RelocModel, RelroLevel, SplitDebuginfo, StackProbeType, TargetOptions, cvs, +}; + +pub(crate) fn opts() -> TargetOptions { + TargetOptions { + os: "lynxos178".into(), + dynamic_linking: false, + families: cvs!["unix"], + position_independent_executables: false, + static_position_independent_executables: false, + relro_level: RelroLevel::Full, + has_thread_local: false, + crt_static_respected: true, + panic_strategy: PanicStrategy::Abort, + linker: Some(Cow::Borrowed("x86_64-lynx-lynxos178-gcc")), + no_default_libraries: false, + eh_frame_header: false, // GNU ld (GNU Binutils) 2.37.50 does not support --eh-frame-hdr + max_atomic_width: Some(64), + supported_split_debuginfo: Cow::Borrowed(&[ + SplitDebuginfo::Packed, + SplitDebuginfo::Unpacked, + SplitDebuginfo::Off, + ]), + relocation_model: RelocModel::Static, + stack_probes: StackProbeType::Inline, + ..Default::default() + } +} diff --git a/compiler/rustc_target/src/spec/base/mod.rs b/compiler/rustc_target/src/spec/base/mod.rs index 71b6528c2dd1..b368d93f0072 100644 --- a/compiler/rustc_target/src/spec/base/mod.rs +++ b/compiler/rustc_target/src/spec/base/mod.rs @@ -19,6 +19,7 @@ pub(crate) mod linux_musl; pub(crate) mod linux_ohos; pub(crate) mod linux_uclibc; pub(crate) mod linux_wasm; +pub(crate) mod lynxos178; pub(crate) mod msvc; pub(crate) mod netbsd; pub(crate) mod nto_qnx; diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 64171fcc7ab3..3c769dad630a 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -2078,6 +2078,7 @@ supported_targets! { ("riscv32imafc-unknown-nuttx-elf", riscv32imafc_unknown_nuttx_elf), ("riscv64imac-unknown-nuttx-elf", riscv64imac_unknown_nuttx_elf), ("riscv64gc-unknown-nuttx-elf", riscv64gc_unknown_nuttx_elf), + ("x86_64-lynx-lynxos178", x86_64_lynx_lynxos178), ("x86_64-pc-cygwin", x86_64_pc_cygwin), } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_lynx_lynxos178.rs b/compiler/rustc_target/src/spec/targets/x86_64_lynx_lynxos178.rs new file mode 100644 index 000000000000..654ae7c9c5be --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/x86_64_lynx_lynxos178.rs @@ -0,0 +1,34 @@ +use crate::spec::{SanitizerSet, StackProbeType, Target, base}; + +pub(crate) fn target() -> Target { + let mut base = base::lynxos178::opts(); + base.cpu = "x86-64".into(); + base.plt_by_default = false; + base.max_atomic_width = Some(64); + base.stack_probes = StackProbeType::Inline; + base.static_position_independent_executables = false; + base.supported_sanitizers = SanitizerSet::ADDRESS + | SanitizerSet::CFI + | SanitizerSet::KCFI + | SanitizerSet::DATAFLOW + | SanitizerSet::LEAK + | SanitizerSet::MEMORY + | SanitizerSet::SAFESTACK + | SanitizerSet::THREAD; + base.supports_xray = true; + + Target { + llvm_target: "x86_64-unknown-unknown-gnu".into(), + metadata: crate::spec::TargetMetadata { + description: Some("LynxOS-178".into()), + tier: Some(3), + host_tools: Some(false), + std: Some(false), + }, + pointer_width: 64, + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), + arch: "x86_64".into(), + options: base, + } +} diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index 891340add908..9e4a72bc9c37 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -34,6 +34,7 @@ pub struct Finder { // Targets can be removed from this list once they are present in the stage0 compiler (usually by updating the beta compiler of the bootstrap). const STAGE0_MISSING_TARGETS: &[&str] = &[ // just a dummy comment so the list doesn't get onelined + "x86_64-lynx-lynxos178", ]; /// Minimum version threshold for libstdc++ required when using prebuilt LLVM diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 9bb64adfa786..cf41f5b86a85 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -78,6 +78,7 @@ - [illumos](platform-support/illumos.md) - [loongarch\*-unknown-linux-\*](platform-support/loongarch-linux.md) - [loongarch\*-unknown-none\*](platform-support/loongarch-none.md) + - [\*-lynxos178-\*](platform-support/lynxos178.md) - [m68k-unknown-linux-gnu](platform-support/m68k-unknown-linux-gnu.md) - [m68k-unknown-none-elf](platform-support/m68k-unknown-none-elf.md) - [mips64-openwrt-linux-musl](platform-support/mips64-openwrt-linux-musl.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 4149b4cb9202..9870e5011ebf 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -407,6 +407,7 @@ target | std | host | notes [`wasm32-wali-linux-musl`](platform-support/wasm32-wali-linux.md) | ? | | WebAssembly with [WALI](https://github.com/arjunr2/WALI) [`x86_64-apple-tvos`](platform-support/apple-tvos.md) | ✓ | | x86 64-bit tvOS [`x86_64-apple-watchos-sim`](platform-support/apple-watchos.md) | ✓ | | x86 64-bit Apple WatchOS simulator +[`x86_64-lynx-lynxos178`](platform-support/lynxos178.md) | | | x86_64 LynxOS-178 [`x86_64-pc-cygwin`](platform-support/x86_64-pc-cygwin.md) | ✓ | | 64-bit x86 Cygwin | [`x86_64-pc-nto-qnx710`](platform-support/nto-qnx.md) | ✓ | | x86 64-bit QNX Neutrino 7.1 RTOS with default network stack (io-pkt) | [`x86_64-pc-nto-qnx710_iosock`](platform-support/nto-qnx.md) | ✓ | | x86 64-bit QNX Neutrino 7.1 RTOS with new network stack (io-sock) | diff --git a/src/doc/rustc/src/platform-support/lynxos178.md b/src/doc/rustc/src/platform-support/lynxos178.md new file mode 100644 index 000000000000..6463f95a0b8e --- /dev/null +++ b/src/doc/rustc/src/platform-support/lynxos178.md @@ -0,0 +1,77 @@ +# `*-lynxos178-*` + +**Tier: 3** + +Targets for the LynxOS-178 operating system. + +[LynxOS-178](https://www.lynx.com/products/lynxos-178-do-178c-certified-posix-rtos) +is a commercial RTOS designed for safety-critical real-time systems. It is +developed by Lynx Software Technologies as part of the +[MOSA.ic](https://www.lynx.com/solutions/safe-and-secure-operating-environment) +product suite. + +Target triples available: +- `x86_64-lynx-lynxos178` + +## Target maintainers + +- Renat Fatykhov, https://github.com/rfatykhov-lynx + +## Requirements + +To build Rust programs for LynxOS-178, you must first have LYNX MOSA.ic +installed on the build machine. + +This target supports only cross-compilation, from the same hosts supported by +the Lynx CDK. + +Currently only `no_std` programs are supported. Work to support `std` is in +progress. + +## Building the target + +You can build Rust with support for x86_64-lynx-lynxos178 by adding that +to the `target` list in `config.toml`, and then running `./x build --target +x86_64-lynx-lynxos178 compiler`. + +## Building Rust programs + +Rust does not yet ship pre-compiled artifacts for this target. To compile for +this target, you will need to build Rust with the target enabled (see "Building +the target" above). + +Before executing `cargo`, you must configure the environment to build LynxOS-178 +binaries by running `source setup.sh` from the los178 directory. + +If your program/crates contain procedural macros, Rust must be able to build +binaries for the host as well. The host gcc is hidden by sourcing setup.sh. To +deal with this, add the following to your project's `.cargo/config.toml`: +```toml +[target.x86_64-unknown-linux-gnu] +linker = "lynx-host-gcc" +``` +(If necessary substitute your host target triple for x86_64-unknown-linux-gnu.) + +To point `cargo` at the correct rustc binary, set the RUSTC environment +variable. + +The core library should be usable. You can try by building it as part of your +project: +```bash +cargo +nightly build -Z build-std=core --target x86_64-lynx-lynxos178 +``` + +## Testing + +Binaries built with rust can be provided to a LynxOS-178 instance on its file +system, where they can be executed. Rust binaries tend to be large, so it may +be necessary to strip them first. + +It is possible to run the Rust testsuite by providing a test runner that takes +the test binary and executes it under LynxOS-178. Most (all?) tests won't run +without std support though, which is not yet supported. + +## Cross-compilation toolchains and C code + +LYNX MOSA.ic comes with all the tools required to cross-compile C code for +LynxOS-178. diff --git a/tests/assembly/targets/targets-elf.rs b/tests/assembly/targets/targets-elf.rs index 8f2fef0e9c91..325559111949 100644 --- a/tests/assembly/targets/targets-elf.rs +++ b/tests/assembly/targets/targets-elf.rs @@ -571,6 +571,9 @@ //@ revisions: x86_64_linux_android //@ [x86_64_linux_android] compile-flags: --target x86_64-linux-android //@ [x86_64_linux_android] needs-llvm-components: x86 +//@ revisions: x86_64_lynx_lynxos178 +//@ [x86_64_lynx_lynxos178] compile-flags: --target x86_64-lynx-lynxos178 +//@ [x86_64_lynx_lynxos178] needs-llvm-components: x86 //@ revisions: x86_64_pc_nto_qnx710 //@ [x86_64_pc_nto_qnx710] compile-flags: --target x86_64-pc-nto-qnx710 //@ [x86_64_pc_nto_qnx710] needs-llvm-components: x86 diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index 4636b6945d06..7cda6c2eaa52 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -201,7 +201,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_os = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` + = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` @@ -274,7 +274,7 @@ LL | #[cfg(target_os = "linuz")] // testing that we suggest `linux` | | | help: there is a expected value with a similar name: `"linux"` | - = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` + = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` = note: see for more information about checking conditional configuration warning: 28 warnings emitted From 95ad6dfeab798a612908f768ea6df0ddb000f643 Mon Sep 17 00:00:00 2001 From: Makai Date: Thu, 10 Apr 2025 20:12:26 +0800 Subject: [PATCH 308/606] add `span_extend_to_prev_char_before()` to `SourceMap` --- compiler/rustc_span/src/source_map.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index 6fdf8e46fec6..0273bb040f43 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -633,6 +633,24 @@ impl SourceMap { sp } + /// Extends the given `Span` to just before the previous occurrence of `c`. Return the same span + /// if an error occurred while retrieving the code snippet. + pub fn span_extend_to_prev_char_before( + &self, + sp: Span, + c: char, + accept_newlines: bool, + ) -> Span { + if let Ok(prev_source) = self.span_to_prev_source(sp) { + let prev_source = prev_source.rsplit(c).next().unwrap_or(""); + if accept_newlines || !prev_source.contains('\n') { + return sp.with_lo(BytePos(sp.lo().0 - prev_source.len() as u32 - 1_u32)); + } + } + + sp + } + /// Extends the given `Span` to just after the previous occurrence of `pat` when surrounded by /// whitespace. Returns None if the pattern could not be found or if an error occurred while /// retrieving the code snippet. From 830c58be89e4717ca2c1e08f17d1e027707334e9 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 10 Apr 2025 14:24:14 +0200 Subject: [PATCH 309/606] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index a6f295108797..d2b8b5147306 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -25a615bf829b9f6d6f22da537e3851043f92e5f2 +7d7de5bf3c3cbf9c2c5bbc5cbfb9197a8a427d35 From 955d92fb1b87b1b6e672cd57fc81403c3c164d8d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 10 Apr 2025 15:19:59 +0200 Subject: [PATCH 310/606] update lockfile --- Cargo.lock | 1 + 1 file changed, 1 insertion(+) diff --git a/Cargo.lock b/Cargo.lock index bf519e039260..901113bbff56 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2312,6 +2312,7 @@ name = "miri" version = "0.1.0" dependencies = [ "aes", + "bitflags", "chrono", "chrono-tz", "colored", From f74032621621d32cf59739b00ecc8f7f9510fc28 Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Wed, 19 Mar 2025 02:19:33 +0000 Subject: [PATCH 311/606] Allow drivers to supply a list of extra symbols to intern --- compiler/rustc_driver_impl/src/lib.rs | 1 + compiler/rustc_hir/src/tests.rs | 2 +- compiler/rustc_interface/src/interface.rs | 5 ++++ compiler/rustc_interface/src/tests.rs | 2 +- compiler/rustc_interface/src/util.rs | 29 +++++++++++++------ compiler/rustc_macros/src/symbols.rs | 25 ++++++++++------ compiler/rustc_metadata/src/rmeta/decoder.rs | 4 +-- compiler/rustc_metadata/src/rmeta/encoder.rs | 6 ++-- compiler/rustc_metadata/src/rmeta/mod.rs | 2 +- .../rustc_middle/src/query/on_disk_cache.rs | 12 ++++---- compiler/rustc_span/src/lib.rs | 15 ++++++---- compiler/rustc_span/src/symbol.rs | 26 ++++++++--------- compiler/rustc_span/src/symbol/tests.rs | 2 +- src/librustdoc/core.rs | 1 + src/librustdoc/doctest.rs | 1 + src/tools/clippy/Cargo.toml | 1 + .../src/attrs/deprecated_cfg_attr.rs | 4 +-- .../src/attrs/useless_attribute.rs | 4 +-- .../src/doc/needless_doctest_main.rs | 2 +- src/tools/clippy/clippy_utils/src/lib.rs | 4 ++- src/tools/clippy/clippy_utils/src/sym.rs | 23 +++++++++++++++ src/tools/clippy/src/driver.rs | 1 + tests/ui-fulldeps/run-compiler-twice.rs | 1 + 23 files changed, 115 insertions(+), 58 deletions(-) create mode 100644 src/tools/clippy/clippy_utils/src/sym.rs diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 8ede6e413368..3aa9a75d8934 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -259,6 +259,7 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send)) hash_untracked_state: None, register_lints: None, override_queries: None, + extra_symbols: Vec::new(), make_codegen_backend: None, registry: diagnostics_registry(), using_internal_features: &USING_INTERNAL_FEATURES, diff --git a/compiler/rustc_hir/src/tests.rs b/compiler/rustc_hir/src/tests.rs index 0837444ffdbe..18c2bfdac8ce 100644 --- a/compiler/rustc_hir/src/tests.rs +++ b/compiler/rustc_hir/src/tests.rs @@ -17,7 +17,7 @@ fn def_path_hash_depends_on_crate_id() { // the crate by changing the crate disambiguator (e.g. via bumping the // crate's version number). - create_session_globals_then(Edition::Edition2024, None, || { + create_session_globals_then(Edition::Edition2024, &[], None, || { let id0 = StableCrateId::new(Symbol::intern("foo"), false, vec!["1".to_string()], ""); let id1 = StableCrateId::new(Symbol::intern("foo"), false, vec!["2".to_string()], ""); diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 3f87b1a547be..5717a2b8743a 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -340,6 +340,10 @@ pub struct Config { /// the list of queries. pub override_queries: Option, + /// An extra set of symbols to add to the symbol interner, the symbol indices + /// will start at [`PREDEFINED_SYMBOLS_COUNT`](rustc_span::symbol::PREDEFINED_SYMBOLS_COUNT) + pub extra_symbols: Vec<&'static str>, + /// This is a callback from the driver that is called to create a codegen backend. /// /// Has no uses within this repository, but is used by bjorn3 for "the @@ -401,6 +405,7 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se &early_dcx, config.opts.edition, config.opts.unstable_opts.threads, + &config.extra_symbols, SourceMapInputs { file_loader, path_mapping, hash_kind, checksum_hash_kind }, |current_gcx| { // The previous `early_dcx` can't be reused here because it doesn't diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index b44be1710edf..903cda3cb5b5 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -53,7 +53,7 @@ where checksum_hash_kind, }); - rustc_span::create_session_globals_then(DEFAULT_EDITION, sm_inputs, || { + rustc_span::create_session_globals_then(DEFAULT_EDITION, &[], sm_inputs, || { let temps_dir = sessopts.unstable_opts.temps_dir.as_deref().map(PathBuf::from); let io = CompilerIO { input: Input::Str { name: FileName::Custom(String::new()), input: String::new() }, diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 5cccab893bb3..fceaa6577ab1 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -117,6 +117,7 @@ fn run_in_thread_with_globals R + Send, R: Send>( thread_stack_size: usize, edition: Edition, sm_inputs: SourceMapInputs, + extra_symbols: &[&'static str], f: F, ) -> R { // The "thread pool" is a single spawned thread in the non-parallel @@ -134,9 +135,12 @@ fn run_in_thread_with_globals R + Send, R: Send>( // name contains null bytes. let r = builder .spawn_scoped(s, move || { - rustc_span::create_session_globals_then(edition, Some(sm_inputs), || { - f(CurrentGcx::new()) - }) + rustc_span::create_session_globals_then( + edition, + extra_symbols, + Some(sm_inputs), + || f(CurrentGcx::new()), + ) }) .unwrap() .join(); @@ -152,6 +156,7 @@ pub(crate) fn run_in_thread_pool_with_globals R + Send, thread_builder_diag: &EarlyDiagCtxt, edition: Edition, threads: usize, + extra_symbols: &[&'static str], sm_inputs: SourceMapInputs, f: F, ) -> R { @@ -168,12 +173,18 @@ pub(crate) fn run_in_thread_pool_with_globals R + Send, let registry = sync::Registry::new(std::num::NonZero::new(threads).unwrap()); if !sync::is_dyn_thread_safe() { - return run_in_thread_with_globals(thread_stack_size, edition, sm_inputs, |current_gcx| { - // Register the thread for use with the `WorkerLocal` type. - registry.register(); + return run_in_thread_with_globals( + thread_stack_size, + edition, + sm_inputs, + extra_symbols, + |current_gcx| { + // Register the thread for use with the `WorkerLocal` type. + registry.register(); - f(current_gcx) - }); + f(current_gcx) + }, + ); } let current_gcx = FromDyn::from(CurrentGcx::new()); @@ -217,7 +228,7 @@ pub(crate) fn run_in_thread_pool_with_globals R + Send, // pool. Upon creation, each worker thread created gets a copy of the // session globals in TLS. This is possible because `SessionGlobals` impls // `Send` in the parallel compiler. - rustc_span::create_session_globals_then(edition, Some(sm_inputs), || { + rustc_span::create_session_globals_then(edition, extra_symbols, Some(sm_inputs), || { rustc_span::with_session_globals(|session_globals| { let session_globals = FromDyn::from(session_globals); builder diff --git a/compiler/rustc_macros/src/symbols.rs b/compiler/rustc_macros/src/symbols.rs index 37200f62eb5a..0400de622740 100644 --- a/compiler/rustc_macros/src/symbols.rs +++ b/compiler/rustc_macros/src/symbols.rs @@ -142,13 +142,13 @@ pub(super) fn symbols(input: TokenStream) -> TokenStream { output } -struct Preinterned { +struct Predefined { idx: u32, span_of_name: Span, } struct Entries { - map: HashMap, + map: HashMap, } impl Entries { @@ -163,7 +163,7 @@ impl Entries { prev.idx } else { let idx = self.len(); - self.map.insert(s.to_string(), Preinterned { idx, span_of_name: span }); + self.map.insert(s.to_string(), Predefined { idx, span_of_name: span }); idx } } @@ -295,10 +295,14 @@ fn symbols_with_errors(input: TokenStream) -> (TokenStream, Vec) { } let symbol_digits_base = entries.map["0"].idx; - let preinterned_symbols_count = entries.len(); + let predefined_symbols_count = entries.len(); let output = quote! { const SYMBOL_DIGITS_BASE: u32 = #symbol_digits_base; - const PREINTERNED_SYMBOLS_COUNT: u32 = #preinterned_symbols_count; + + /// The number of predefined symbols; this is the the first index for + /// extra pre-interned symbols in an Interner created via + /// [`Interner::with_extra_symbols`]. + pub const PREDEFINED_SYMBOLS_COUNT: u32 = #predefined_symbols_count; #[doc(hidden)] #[allow(non_upper_case_globals)] @@ -315,10 +319,13 @@ fn symbols_with_errors(input: TokenStream) -> (TokenStream, Vec) { } impl Interner { - pub(crate) fn fresh() -> Self { - Interner::prefill(&[ - #prefill_stream - ]) + /// Creates an `Interner` with the predefined symbols from the `symbols!` macro and + /// any extra symbols provided by external drivers such as Clippy + pub(crate) fn with_extra_symbols(extra_symbols: &[&'static str]) -> Self { + Interner::prefill( + &[#prefill_stream], + extra_symbols, + ) } } }; diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index f6cf218db9d0..151cc064a966 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -562,9 +562,9 @@ impl<'a, 'tcx> SpanDecoder for DecodeContext<'a, 'tcx> { Symbol::intern(s) }) } - SYMBOL_PREINTERNED => { + SYMBOL_PREDEFINED => { let symbol_index = self.read_u32(); - Symbol::new_from_decoded(symbol_index) + Symbol::new(symbol_index) } _ => unreachable!(), } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 7ab3d432bdf8..8b7b3bba8876 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -201,9 +201,9 @@ impl<'a, 'tcx> SpanEncoder for EncodeContext<'a, 'tcx> { } fn encode_symbol(&mut self, symbol: Symbol) { - // if symbol preinterned, emit tag and symbol index - if symbol.is_preinterned() { - self.opaque.emit_u8(SYMBOL_PREINTERNED); + // if symbol predefined, emit tag and symbol index + if symbol.is_predefined() { + self.opaque.emit_u8(SYMBOL_PREDEFINED); self.opaque.emit_u32(symbol.as_u32()); } else { // otherwise write it as string or as offset to it diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 5536c93f84a4..3eff5dfd5afe 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -576,7 +576,7 @@ impl SpanTag { // Tags for encoding Symbol's const SYMBOL_STR: u8 = 0; const SYMBOL_OFFSET: u8 = 1; -const SYMBOL_PREINTERNED: u8 = 2; +const SYMBOL_PREDEFINED: u8 = 2; pub fn provide(providers: &mut Providers) { encoder::provide(providers); diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index 14e3ce8bef6b..3b935842af4f 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -45,7 +45,7 @@ const TAG_EXPN_DATA: u8 = 1; // Tags for encoding Symbol's const SYMBOL_STR: u8 = 0; const SYMBOL_OFFSET: u8 = 1; -const SYMBOL_PREINTERNED: u8 = 2; +const SYMBOL_PREDEFINED: u8 = 2; /// Provides an interface to incremental compilation data cached from the /// previous compilation session. This data will eventually include the results @@ -673,9 +673,9 @@ impl<'a, 'tcx> SpanDecoder for CacheDecoder<'a, 'tcx> { Symbol::intern(s) }) } - SYMBOL_PREINTERNED => { + SYMBOL_PREDEFINED => { let symbol_index = self.read_u32(); - Symbol::new_from_decoded(symbol_index) + Symbol::new(symbol_index) } _ => unreachable!(), } @@ -891,9 +891,9 @@ impl<'a, 'tcx> SpanEncoder for CacheEncoder<'a, 'tcx> { // copy&paste impl from rustc_metadata fn encode_symbol(&mut self, symbol: Symbol) { - // if symbol preinterned, emit tag and symbol index - if symbol.is_preinterned() { - self.encoder.emit_u8(SYMBOL_PREINTERNED); + // if symbol predefined, emit tag and symbol index + if symbol.is_predefined() { + self.encoder.emit_u8(SYMBOL_PREDEFINED); self.encoder.emit_u32(symbol.as_u32()); } else { // otherwise write it as string or as offset to it diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index f19d4d9f3624..432b1b86142b 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -116,9 +116,13 @@ pub struct SessionGlobals { } impl SessionGlobals { - pub fn new(edition: Edition, sm_inputs: Option) -> SessionGlobals { + pub fn new( + edition: Edition, + extra_symbols: &[&'static str], + sm_inputs: Option, + ) -> SessionGlobals { SessionGlobals { - symbol_interner: symbol::Interner::fresh(), + symbol_interner: symbol::Interner::with_extra_symbols(extra_symbols), span_interner: Lock::new(span_encoding::SpanInterner::default()), metavar_spans: Default::default(), hygiene_data: Lock::new(hygiene::HygieneData::new(edition)), @@ -129,6 +133,7 @@ impl SessionGlobals { pub fn create_session_globals_then( edition: Edition, + extra_symbols: &[&'static str], sm_inputs: Option, f: impl FnOnce() -> R, ) -> R { @@ -137,7 +142,7 @@ pub fn create_session_globals_then( "SESSION_GLOBALS should never be overwritten! \ Use another thread if you need another SessionGlobals" ); - let session_globals = SessionGlobals::new(edition, sm_inputs); + let session_globals = SessionGlobals::new(edition, extra_symbols, sm_inputs); SESSION_GLOBALS.set(&session_globals, f) } @@ -156,7 +161,7 @@ where F: FnOnce(&SessionGlobals) -> R, { if !SESSION_GLOBALS.is_set() { - let session_globals = SessionGlobals::new(edition, None); + let session_globals = SessionGlobals::new(edition, &[], None); SESSION_GLOBALS.set(&session_globals, || SESSION_GLOBALS.with(f)) } else { SESSION_GLOBALS.with(f) @@ -172,7 +177,7 @@ where /// Default edition, no source map. pub fn create_default_session_globals_then(f: impl FnOnce() -> R) -> R { - create_session_globals_then(edition::DEFAULT_EDITION, None, f) + create_session_globals_then(edition::DEFAULT_EDITION, &[], None, f) } // If this ever becomes non thread-local, `decode_syntax_context` diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 8a8bec35d819..616e9390ffe7 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -2506,15 +2506,10 @@ rustc_index::newtype_index! { } impl Symbol { - const fn new(n: u32) -> Self { + pub const fn new(n: u32) -> Self { Symbol(SymbolIndex::from_u32(n)) } - /// for use in Decoder only - pub fn new_from_decoded(n: u32) -> Self { - Self::new(n) - } - /// Maps a string to its interned representation. #[rustc_diagnostic_item = "SymbolIntern"] pub fn intern(string: &str) -> Self { @@ -2600,11 +2595,14 @@ struct InternerInner { } impl Interner { - fn prefill(init: &[&'static str]) -> Self { - Interner(Lock::new(InternerInner { - arena: Default::default(), - strings: init.iter().copied().collect(), - })) + fn prefill(init: &[&'static str], extra: &[&'static str]) -> Self { + let strings = FxIndexSet::from_iter(init.iter().copied().chain(extra.iter().copied())); + assert_eq!( + strings.len(), + init.len() + extra.len(), + "`init` or `extra` contain duplicate symbols", + ); + Interner(Lock::new(InternerInner { arena: Default::default(), strings })) } #[inline] @@ -2729,9 +2727,9 @@ impl Symbol { self != kw::Empty && self != kw::Underscore && !self.is_path_segment_keyword() } - /// Is this symbol was interned in compiler's `symbols!` macro - pub fn is_preinterned(self) -> bool { - self.as_u32() < PREINTERNED_SYMBOLS_COUNT + /// Was this symbol predefined in the compiler's `symbols!` macro + pub fn is_predefined(self) -> bool { + self.as_u32() < PREDEFINED_SYMBOLS_COUNT } } diff --git a/compiler/rustc_span/src/symbol/tests.rs b/compiler/rustc_span/src/symbol/tests.rs index c6aa7627b2b5..660d0d7179af 100644 --- a/compiler/rustc_span/src/symbol/tests.rs +++ b/compiler/rustc_span/src/symbol/tests.rs @@ -3,7 +3,7 @@ use crate::create_default_session_globals_then; #[test] fn interner_tests() { - let i = Interner::prefill(&[]); + let i = Interner::prefill(&[], &[]); // first one is zero: assert_eq!(i.intern("dog"), Symbol::new(0)); // re-use gets the same entry: diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index c47e42670c90..c4dea79370d1 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -321,6 +321,7 @@ pub(crate) fn create_config( (rustc_interface::DEFAULT_QUERY_PROVIDERS.typeck)(tcx, def_id) }; }), + extra_symbols: Vec::new(), make_codegen_backend: None, registry: rustc_driver::diagnostics_registry(), ice_file: None, diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index a2808bddb3ac..88eaa52c6deb 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -191,6 +191,7 @@ pub(crate) fn run(dcx: DiagCtxtHandle<'_>, input: Input, options: RustdocOptions hash_untracked_state: None, register_lints: Some(Box::new(crate::lint::register_lints)), override_queries: None, + extra_symbols: Vec::new(), make_codegen_backend: None, registry: rustc_driver::diagnostics_registry(), ice_file: None, diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml index c4588002dc99..6c0b3af573db 100644 --- a/src/tools/clippy/Cargo.toml +++ b/src/tools/clippy/Cargo.toml @@ -25,6 +25,7 @@ path = "src/driver.rs" [dependencies] clippy_config = { path = "clippy_config" } clippy_lints = { path = "clippy_lints" } +clippy_utils = { path = "clippy_utils" } rustc_tools_util = { path = "rustc_tools_util", version = "0.4.2" } tempfile = { version = "3.3", optional = true } termize = "0.1" diff --git a/src/tools/clippy/clippy_lints/src/attrs/deprecated_cfg_attr.rs b/src/tools/clippy/clippy_lints/src/attrs/deprecated_cfg_attr.rs index cd38aed26a3e..7fab97d3ea14 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/deprecated_cfg_attr.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/deprecated_cfg_attr.rs @@ -1,10 +1,10 @@ use super::{Attribute, DEPRECATED_CFG_ATTR, DEPRECATED_CLIPPY_CFG_ATTR, unnecessary_clippy_cfg}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::msrvs::{self, MsrvStack}; +use clippy_utils::sym; use rustc_ast::AttrStyle; use rustc_errors::Applicability; use rustc_lint::EarlyContext; -use rustc_span::sym; pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute, msrv: &MsrvStack) { // check cfg_attr @@ -18,7 +18,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute, msrv: &MsrvStack) { && msrv.meets(msrvs::TOOL_ATTRIBUTES) // check for `rustfmt_skip` and `rustfmt::skip` && let Some(skip_item) = &items[1].meta_item() - && (skip_item.has_name(sym!(rustfmt_skip)) + && (skip_item.has_name(sym::rustfmt_skip) || skip_item .path .segments diff --git a/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs b/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs index e3e081ce08e9..1cb43ab02a30 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs @@ -2,10 +2,10 @@ use super::USELESS_ATTRIBUTE; use super::utils::{is_lint_level, is_word, namespace_and_lint}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::{SpanRangeExt, first_line_of_span}; +use clippy_utils::sym; use rustc_ast::{Attribute, Item, ItemKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, LintContext}; -use rustc_span::sym; pub(super) fn check(cx: &EarlyContext<'_>, item: &Item, attrs: &[Attribute]) { let skip_unused_imports = attrs.iter().any(|attr| attr.has_name(sym::macro_use)); @@ -61,7 +61,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, item: &Item, attrs: &[Attribute]) { if is_word(lint, sym::unused_imports) && skip_unused_imports { return; } - if is_word(lint, sym!(unused_extern_crates)) { + if is_word(lint, sym::unused_extern_crates) { return; } }, diff --git a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs index 3008082c2329..bf98b1337bc0 100644 --- a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs +++ b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs @@ -38,7 +38,7 @@ pub fn check( // of all `#[test]` attributes in not ignored code examples fn check_code_sample(code: String, edition: Edition, ignore: bool) -> (bool, Vec>) { rustc_driver::catch_fatal_errors(|| { - rustc_span::create_session_globals_then(edition, None, || { + rustc_span::create_session_globals_then(edition, &[], None, || { let mut test_attr_spans = vec![]; let filename = FileName::anon_source_code(&code); diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index eb4e1a7722f3..12f7d6416e3e 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -3,6 +3,7 @@ #![feature(f128)] #![feature(f16)] #![feature(if_let_guard)] +#![feature(macro_metavar_expr)] #![feature(macro_metavar_expr_concat)] #![feature(let_chains)] #![feature(never_type)] @@ -74,6 +75,7 @@ pub mod qualify_min_const_fn; pub mod source; pub mod str_utils; pub mod sugg; +pub mod sym; pub mod ty; pub mod usage; pub mod visitors; @@ -125,7 +127,7 @@ use rustc_middle::ty::{ use rustc_span::hygiene::{ExpnKind, MacroKind}; use rustc_span::source_map::SourceMap; use rustc_span::symbol::{Ident, Symbol, kw}; -use rustc_span::{InnerSpan, Span, sym}; +use rustc_span::{InnerSpan, Span}; use visitors::{Visitable, for_each_unconsumed_temporary}; use crate::consts::{ConstEvalCtxt, Constant, mir_to_const}; diff --git a/src/tools/clippy/clippy_utils/src/sym.rs b/src/tools/clippy/clippy_utils/src/sym.rs new file mode 100644 index 000000000000..9cc72a5b3aaa --- /dev/null +++ b/src/tools/clippy/clippy_utils/src/sym.rs @@ -0,0 +1,23 @@ +#![allow(non_upper_case_globals)] + +use rustc_span::symbol::{Symbol, PREDEFINED_SYMBOLS_COUNT}; + +pub use rustc_span::sym::*; + +macro_rules! generate { + ($($sym:ident,)*) => { + /// To be supplied to `rustc_interface::Config` + pub const EXTRA_SYMBOLS: &[&str] = &[ + $(stringify!($sym),)* + ]; + + $( + pub const $sym: Symbol = Symbol::new(PREDEFINED_SYMBOLS_COUNT + ${index()}); + )* + }; +} + +generate! { + rustfmt_skip, + unused_extern_crates, +} diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs index e4092bcd1056..df9c4e8e6ae9 100644 --- a/src/tools/clippy/src/driver.rs +++ b/src/tools/clippy/src/driver.rs @@ -160,6 +160,7 @@ impl rustc_driver::Callbacks for ClippyCallbacks { clippy_lints::register_lints(lint_store, conf); clippy_lints::register_pre_expansion_lints(lint_store, conf); })); + config.extra_symbols = clippy_utils::sym::EXTRA_SYMBOLS.into(); // FIXME: #4825; This is required, because Clippy lints that are based on MIR have to be // run on the unoptimized MIR. On the other hand this results in some false negatives. If diff --git a/tests/ui-fulldeps/run-compiler-twice.rs b/tests/ui-fulldeps/run-compiler-twice.rs index ffc19b138a57..fa651baa7bc8 100644 --- a/tests/ui-fulldeps/run-compiler-twice.rs +++ b/tests/ui-fulldeps/run-compiler-twice.rs @@ -70,6 +70,7 @@ fn compile(code: String, output: PathBuf, sysroot: PathBuf, linker: Option<&Path hash_untracked_state: None, register_lints: None, override_queries: None, + extra_symbols: Vec::new(), make_codegen_backend: None, registry: rustc_driver::diagnostics_registry(), using_internal_features: &rustc_driver::USING_INTERNAL_FEATURES, From 5cda2a9b4bc537acea44576bc3cc3e6b9ff42bdc Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 10 Apr 2025 15:45:32 +0200 Subject: [PATCH 312/606] run all 'thread' tests on FreeBSD, and also on 32bit --- src/tools/miri/ci/ci.sh | 6 +++--- src/tools/miri/src/shims/windows/foreign_items.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tools/miri/ci/ci.sh b/src/tools/miri/ci/ci.sh index b690bd9cd2b9..755e02d02eca 100755 --- a/src/tools/miri/ci/ci.sh +++ b/src/tools/miri/ci/ci.sh @@ -164,9 +164,9 @@ case $HOST_TARGET in # Partially supported targets (tier 2) BASIC="empty_main integer heap_alloc libc-mem vec string btreemap" # ensures we have the basics: pre-main code, system allocator UNIX="hello panic/panic panic/unwind concurrency/simple atomic libc-mem libc-misc libc-random env num_cpus" # the things that are very similar across all Unixes, and hence easily supported there - TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal $BASIC $UNIX time hashmap random threadname pthread fs libc-pipe concurrency sync - TEST_TARGET=i686-unknown-freebsd run_tests_minimal $BASIC $UNIX time hashmap random threadname pthread fs libc-pipe - TEST_TARGET=aarch64-linux-android run_tests_minimal $BASIC $UNIX time hashmap random sync concurrency thread epoll eventfd + TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal $BASIC $UNIX time hashmap random thread sync concurrency fs libc-pipe + TEST_TARGET=i686-unknown-freebsd run_tests_minimal $BASIC $UNIX time hashmap random thread sync concurrency fs libc-pipe + TEST_TARGET=aarch64-linux-android run_tests_minimal $BASIC $UNIX time hashmap random thread sync concurrency epoll eventfd TEST_TARGET=wasm32-wasip2 run_tests_minimal $BASIC wasm TEST_TARGET=wasm32-unknown-unknown run_tests_minimal no_std empty_main wasm # this target doesn't really have std TEST_TARGET=thumbv7em-none-eabihf run_tests_minimal no_std diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs index 7d97e333cd9b..ba4da155fc4d 100644 --- a/src/tools/miri/src/shims/windows/foreign_items.rs +++ b/src/tools/miri/src/shims/windows/foreign_items.rs @@ -65,7 +65,7 @@ fn win_get_full_path_name<'tcx>(path: &Path) -> InterpResult<'tcx, io::Result = vec![]; // will be a vecot of components, joined by `/`. + let mut result: Vec<&[u8]> = vec![]; // will be a vector of components, joined by `/`. let mut bytes = bytes; // the remaining bytes to process let mut stop = false; while !stop { From f9f2acac1f7335ccb5129f97c963ac937b121b49 Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Thu, 10 Apr 2025 13:55:52 +0000 Subject: [PATCH 313/606] cfi: do not transmute function pointers in formatting code --- library/core/src/fmt/mod.rs | 2 +- library/core/src/fmt/rt.rs | 45 +++++++++++++++++++------------------ 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 7ca390941bcd..580f95eddce7 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -7,7 +7,7 @@ use crate::char::{EscapeDebugExtArgs, MAX_LEN_UTF8}; use crate::marker::PhantomData; use crate::num::fmt as numfmt; use crate::ops::Deref; -use crate::{iter, mem, result, str}; +use crate::{iter, result, str}; mod builders; #[cfg(not(no_fp_fmt_parse))] diff --git a/library/core/src/fmt/rt.rs b/library/core/src/fmt/rt.rs index 0459674303d1..05e024b134d1 100644 --- a/library/core/src/fmt/rt.rs +++ b/library/core/src/fmt/rt.rs @@ -65,61 +65,67 @@ pub struct Argument<'a> { ty: ArgumentType<'a>, } -#[rustc_diagnostic_item = "ArgumentMethods"] -impl Argument<'_> { - #[inline] - const fn new<'a, T>(x: &'a T, f: fn(&T, &mut Formatter<'_>) -> Result) -> Argument<'a> { +macro_rules! argument_new { + ($t:ty, $x:expr, $f:expr) => { Argument { // INVARIANT: this creates an `ArgumentType<'a>` from a `&'a T` and // a `fn(&T, ...)`, so the invariant is maintained. ty: ArgumentType::Placeholder { - value: NonNull::from_ref(x).cast(), + value: NonNull::<$t>::from_ref($x).cast(), // SAFETY: function pointers always have the same layout. - formatter: unsafe { mem::transmute(f) }, + formatter: |ptr: NonNull<()>, fmt: &mut Formatter<'_>| { + let func = $f; + // SAFETY: This is the same type as the `value` field. + let r = unsafe { ptr.cast::<$t>().as_ref() }; + (func)(r, fmt) + }, _lifetime: PhantomData, }, } - } + }; +} +#[rustc_diagnostic_item = "ArgumentMethods"] +impl Argument<'_> { #[inline] pub fn new_display(x: &T) -> Argument<'_> { - Self::new(x, Display::fmt) + argument_new!(T, x, ::fmt) } #[inline] pub fn new_debug(x: &T) -> Argument<'_> { - Self::new(x, Debug::fmt) + argument_new!(T, x, ::fmt) } #[inline] pub fn new_debug_noop(x: &T) -> Argument<'_> { - Self::new(x, |_, _| Ok(())) + argument_new!(T, x, |_: &T, _| Ok(())) } #[inline] pub fn new_octal(x: &T) -> Argument<'_> { - Self::new(x, Octal::fmt) + argument_new!(T, x, ::fmt) } #[inline] pub fn new_lower_hex(x: &T) -> Argument<'_> { - Self::new(x, LowerHex::fmt) + argument_new!(T, x, ::fmt) } #[inline] pub fn new_upper_hex(x: &T) -> Argument<'_> { - Self::new(x, UpperHex::fmt) + argument_new!(T, x, ::fmt) } #[inline] pub fn new_pointer(x: &T) -> Argument<'_> { - Self::new(x, Pointer::fmt) + argument_new!(T, x, ::fmt) } #[inline] pub fn new_binary(x: &T) -> Argument<'_> { - Self::new(x, Binary::fmt) + argument_new!(T, x, ::fmt) } #[inline] pub fn new_lower_exp(x: &T) -> Argument<'_> { - Self::new(x, LowerExp::fmt) + argument_new!(T, x, ::fmt) } #[inline] pub fn new_upper_exp(x: &T) -> Argument<'_> { - Self::new(x, UpperExp::fmt) + argument_new!(T, x, ::fmt) } #[inline] #[track_caller] @@ -135,11 +141,6 @@ impl Argument<'_> { /// # Safety /// /// This argument must actually be a placeholder argument. - /// - // FIXME: Transmuting formatter in new and indirectly branching to/calling - // it here is an explicit CFI violation. - #[allow(inline_no_sanitize)] - #[no_sanitize(cfi, kcfi)] #[inline] pub(super) unsafe fn fmt(&self, f: &mut Formatter<'_>) -> Result { match self.ty { From 997ec4982b6be6c4d2bffe7dcb0df420d78482de Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Thu, 10 Apr 2025 14:32:59 +0000 Subject: [PATCH 314/606] Update code coverage map --- tests/coverage/closure.cov-map | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/tests/coverage/closure.cov-map b/tests/coverage/closure.cov-map index 2d784ba09b60..640f98956840 100644 --- a/tests/coverage/closure.cov-map +++ b/tests/coverage/closure.cov-map @@ -140,19 +140,17 @@ Number of file 0 mappings: 6 - Code(Counter(0)) at (prev + 2, 9) to (start + 0, 10) Highest counter ID seen: c1 -Function name: closure::main::{closure#18} -Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 19, 0d, 02, 1c, 05, 02, 1d, 02, 12, 02, 02, 11, 00, 12, 01, 01, 11, 01, 0e] +Function name: closure::main::{closure#18} (unused) +Raw bytes (24): 0x[01, 01, 00, 04, 00, 19, 0d, 02, 1c, 00, 02, 1d, 02, 12, 00, 02, 11, 00, 12, 00, 01, 11, 01, 0e] Number of files: 1 - file 0 => global file 1 -Number of expressions: 1 -- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +Number of expressions: 0 Number of file 0 mappings: 4 -- Code(Counter(0)) at (prev + 25, 13) to (start + 2, 28) -- Code(Counter(1)) at (prev + 2, 29) to (start + 2, 18) -- Code(Expression(0, Sub)) at (prev + 2, 17) to (start + 0, 18) - = (c0 - c1) -- Code(Counter(0)) at (prev + 1, 17) to (start + 1, 14) -Highest counter ID seen: c1 +- Code(Zero) at (prev + 25, 13) to (start + 2, 28) +- Code(Zero) at (prev + 2, 29) to (start + 2, 18) +- Code(Zero) at (prev + 2, 17) to (start + 0, 18) +- Code(Zero) at (prev + 1, 17) to (start + 1, 14) +Highest counter ID seen: (none) Function name: closure::main::{closure#19} Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 43, 0d, 02, 1c, 05, 02, 1d, 02, 12, 02, 02, 11, 00, 12, 01, 01, 11, 01, 0e] From 2d37173c237f9b5cdc7f8971879a2162265cba61 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 10 Apr 2025 14:46:39 +0000 Subject: [PATCH 315/606] Bump crossbeam-channel from 0.5.14 to 0.5.15 Bumps [crossbeam-channel](https://github.com/crossbeam-rs/crossbeam) from 0.5.14 to 0.5.15. - [Release notes](https://github.com/crossbeam-rs/crossbeam/releases) - [Changelog](https://github.com/crossbeam-rs/crossbeam/blob/master/CHANGELOG.md) - [Commits](https://github.com/crossbeam-rs/crossbeam/compare/crossbeam-channel-0.5.14...crossbeam-channel-0.5.15) --- updated-dependencies: - dependency-name: crossbeam-channel dependency-version: 0.5.15 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- src/tools/miri/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/miri/Cargo.lock b/src/tools/miri/Cargo.lock index 0c6f4a3dd06e..bbdcccdc17f2 100644 --- a/src/tools/miri/Cargo.lock +++ b/src/tools/miri/Cargo.lock @@ -257,9 +257,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.14" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" dependencies = [ "crossbeam-utils", ] From 250a1aa7a6d583db8882333c1875f3ececdccc3b Mon Sep 17 00:00:00 2001 From: Yotam Ofek Date: Wed, 5 Mar 2025 09:24:09 +0000 Subject: [PATCH 316/606] make `AllTypes::print` return `impl fmt::Display` --- src/librustdoc/html/render/context.rs | 10 +--- src/librustdoc/html/render/mod.rs | 73 ++++++++++++++------------- src/librustdoc/html/render/tests.rs | 3 +- 3 files changed, 41 insertions(+), 45 deletions(-) diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index e2d1f58a37ec..596ac665fc31 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -650,15 +650,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { bar.render_into(&mut sidebar).unwrap(); - let v = layout::render( - &shared.layout, - &page, - sidebar, - BufDisplay(|buf: &mut String| { - all.print(buf); - }), - &shared.style_files, - ); + let v = layout::render(&shared.layout, &page, sidebar, all.print(), &shared.style_files); shared.fs.write(final_file, v)?; // if to avoid writing help, settings files to doc root unless we're on the final invocation diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 21c823f49d15..aacb854d5da1 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -439,44 +439,49 @@ impl AllTypes { sections } - fn print(&self, f: &mut String) { - fn print_entries(f: &mut String, e: &FxIndexSet, kind: ItemSection) { - if !e.is_empty() { - let mut e: Vec<&ItemEntry> = e.iter().collect(); - e.sort(); - write_str( - f, - format_args!( - "

{title}

    ", - id = kind.id(), - title = kind.name(), - ), - ); - - for s in e.iter() { - write_str(f, format_args!("
  • {}
  • ", s.print())); + fn print(&self) -> impl fmt::Display { + fn print_entries(e: &FxIndexSet, kind: ItemSection) -> impl fmt::Display { + fmt::from_fn(move |f| { + if e.is_empty() { + return Ok(()); } - f.push_str("
"); - } + let mut e: Vec<&ItemEntry> = e.iter().collect(); + e.sort(); + write!( + f, + "

{title}

    ", + id = kind.id(), + title = kind.name(), + )?; + + for s in e.iter() { + write!(f, "
  • {}
  • ", s.print())?; + } + + f.write_str("
") + }) } - f.push_str("

List of all items

"); - // Note: print_entries does not escape the title, because we know the current set of titles - // doesn't require escaping. - print_entries(f, &self.structs, ItemSection::Structs); - print_entries(f, &self.enums, ItemSection::Enums); - print_entries(f, &self.unions, ItemSection::Unions); - print_entries(f, &self.primitives, ItemSection::PrimitiveTypes); - print_entries(f, &self.traits, ItemSection::Traits); - print_entries(f, &self.macros, ItemSection::Macros); - print_entries(f, &self.attribute_macros, ItemSection::AttributeMacros); - print_entries(f, &self.derive_macros, ItemSection::DeriveMacros); - print_entries(f, &self.functions, ItemSection::Functions); - print_entries(f, &self.type_aliases, ItemSection::TypeAliases); - print_entries(f, &self.trait_aliases, ItemSection::TraitAliases); - print_entries(f, &self.statics, ItemSection::Statics); - print_entries(f, &self.constants, ItemSection::Constants); + fmt::from_fn(|f| { + f.write_str("

List of all items

")?; + // Note: print_entries does not escape the title, because we know the current set of titles + // doesn't require escaping. + print_entries(&self.structs, ItemSection::Structs).fmt(f)?; + print_entries(&self.enums, ItemSection::Enums).fmt(f)?; + print_entries(&self.unions, ItemSection::Unions).fmt(f)?; + print_entries(&self.primitives, ItemSection::PrimitiveTypes).fmt(f)?; + print_entries(&self.traits, ItemSection::Traits).fmt(f)?; + print_entries(&self.macros, ItemSection::Macros).fmt(f)?; + print_entries(&self.attribute_macros, ItemSection::AttributeMacros).fmt(f)?; + print_entries(&self.derive_macros, ItemSection::DeriveMacros).fmt(f)?; + print_entries(&self.functions, ItemSection::Functions).fmt(f)?; + print_entries(&self.type_aliases, ItemSection::TypeAliases).fmt(f)?; + print_entries(&self.trait_aliases, ItemSection::TraitAliases).fmt(f)?; + print_entries(&self.statics, ItemSection::Statics).fmt(f)?; + print_entries(&self.constants, ItemSection::Constants).fmt(f)?; + Ok(()) + }) } } diff --git a/src/librustdoc/html/render/tests.rs b/src/librustdoc/html/render/tests.rs index 657cd3c82aae..327a30887b1d 100644 --- a/src/librustdoc/html/render/tests.rs +++ b/src/librustdoc/html/render/tests.rs @@ -47,8 +47,7 @@ fn test_all_types_prints_header_once() { // Regression test for #82477 let all_types = AllTypes::new(); - let mut buffer = String::new(); - all_types.print(&mut buffer); + let buffer = all_types.print().to_string(); assert_eq!(1, buffer.matches("List of all items").count()); } From 642995cf1c25d13b7857f1a36cf609654c29c6dc Mon Sep 17 00:00:00 2001 From: Yotam Ofek Date: Thu, 13 Mar 2025 06:20:23 +0000 Subject: [PATCH 317/606] make `link_tooltip` return `impl fmt::Display` --- src/librustdoc/clean/types.rs | 2 +- src/librustdoc/html/format.rs | 55 ++++++++++++++++++----------------- 2 files changed, 30 insertions(+), 27 deletions(-) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 06e75fe1764e..c67f81c77f3c 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -517,7 +517,7 @@ impl Item { Some(RenderedLink { original_text: s.clone(), new_text: link_text.clone(), - tooltip: link_tooltip(*id, fragment, cx), + tooltip: link_tooltip(*id, fragment, cx).to_string(), href, }) } else { diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 41e9a5a66516..4998c671b61e 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -11,6 +11,7 @@ use std::borrow::Cow; use std::cmp::Ordering; use std::fmt::{self, Display, Write}; use std::iter::{self, once}; +use std::slice; use itertools::Either; use rustc_abi::ExternAbi; @@ -650,33 +651,35 @@ pub(crate) fn href_relative_parts<'fqp>( } } -pub(crate) fn link_tooltip(did: DefId, fragment: &Option, cx: &Context<'_>) -> String { - let cache = cx.cache(); - let Some((fqp, shortty)) = cache.paths.get(&did).or_else(|| cache.external_paths.get(&did)) - else { - return String::new(); - }; - let mut buf = String::new(); - let fqp = if *shortty == ItemType::Primitive { - // primitives are documented in a crate, but not actually part of it - &fqp[fqp.len() - 1..] - } else { - fqp - }; - if let &Some(UrlFragment::Item(id)) = fragment { - write_str(&mut buf, format_args!("{} ", cx.tcx().def_descr(id))); - for component in fqp { - write_str(&mut buf, format_args!("{component}::")); +pub(crate) fn link_tooltip( + did: DefId, + fragment: &Option, + cx: &Context<'_>, +) -> impl fmt::Display { + fmt::from_fn(move |f| { + let cache = cx.cache(); + let Some((fqp, shortty)) = cache.paths.get(&did).or_else(|| cache.external_paths.get(&did)) + else { + return Ok(()); + }; + let fqp = if *shortty == ItemType::Primitive { + // primitives are documented in a crate, but not actually part of it + slice::from_ref(fqp.last().unwrap()) + } else { + fqp + }; + if let &Some(UrlFragment::Item(id)) = fragment { + write!(f, "{} ", cx.tcx().def_descr(id))?; + for component in fqp { + write!(f, "{component}::")?; + } + write!(f, "{}", cx.tcx().item_name(id))?; + } else if !fqp.is_empty() { + write!(f, "{shortty} ")?; + fqp.iter().joined("::", f)?; } - write_str(&mut buf, format_args!("{}", cx.tcx().item_name(id))); - } else if !fqp.is_empty() { - let mut fqp_it = fqp.iter(); - write_str(&mut buf, format_args!("{shortty} {}", fqp_it.next().unwrap())); - for component in fqp_it { - write_str(&mut buf, format_args!("::{component}")); - } - } - buf + Ok(()) + }) } /// Used to render a [`clean::Path`]. From f7640d5468208b1e58913b58e164718c628d51cc Mon Sep 17 00:00:00 2001 From: Yotam Ofek Date: Thu, 13 Mar 2025 12:41:47 +0000 Subject: [PATCH 318/606] make `doc_impl_item` and `render_default_items` receive `impl fmt::Write` --- src/librustdoc/html/render/mod.rs | 234 ++++++++++++++---------------- 1 file changed, 108 insertions(+), 126 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index aacb854d5da1..511a9316aff3 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -47,6 +47,7 @@ use std::path::PathBuf; use std::{fs, str}; use askama::Template; +use itertools::Either; use rustc_attr_parsing::{ ConstStability, DeprecatedSince, Deprecation, RustcVersion, StabilityLevel, StableSince, }; @@ -1644,8 +1645,8 @@ fn render_impl( // `containing_item` is used for rendering stability info. If the parent is a trait impl, // `containing_item` will the grandparent, since trait impls can't have stability attached. fn doc_impl_item( - boring: &mut String, - interesting: &mut String, + boring: impl fmt::Write, + interesting: impl fmt::Write, cx: &Context<'_>, item: &clean::Item, parent: &clean::Item, @@ -1654,7 +1655,7 @@ fn render_impl( is_default_item: bool, trait_: Option<&clean::Trait>, rendering_params: ImplRenderingParameters, - ) { + ) -> fmt::Result { let item_type = item.type_(); let name = item.name.as_ref().unwrap(); @@ -1729,15 +1730,16 @@ fn render_impl( ); } } - let w = if short_documented && trait_.is_some() { interesting } else { boring }; + let mut w = if short_documented && trait_.is_some() { + Either::Left(interesting) + } else { + Either::Right(boring) + }; let toggled = !doc_buffer.is_empty(); if toggled { let method_toggle_class = if item_type.is_method() { " method-toggle" } else { "" }; - write_str( - w, - format_args!("
"), - ); + write!(w, "
")?; } match &item.kind { clean::MethodItem(..) | clean::RequiredMethodItem(_) => { @@ -1752,172 +1754,151 @@ fn render_impl( .find(|item| item.name.map(|n| n == *name).unwrap_or(false)) }) .map(|item| format!("{}.{name}", item.type_())); - write_str( + write!( w, - format_args!( - "
\ + "
\ {}", - render_rightside(cx, item, render_mode) - ), - ); + render_rightside(cx, item, render_mode) + )?; if trait_.is_some() { // Anchors are only used on trait impls. - write_str(w, format_args!("§")); + write!(w, "§")?; } - write_str( + write!( w, - format_args!( - "

{}

", - render_assoc_item( - item, - link.anchor(source_id.as_ref().unwrap_or(&id)), - ItemType::Impl, - cx, - render_mode, - ), + "

{}

", + render_assoc_item( + item, + link.anchor(source_id.as_ref().unwrap_or(&id)), + ItemType::Impl, + cx, + render_mode, ), - ); + )?; } } clean::RequiredAssocConstItem(generics, ty) => { let source_id = format!("{item_type}.{name}"); let id = cx.derive_id(&source_id); - write_str( + write!( w, - format_args!( - "
\ + "
\ {}", - render_rightside(cx, item, render_mode) - ), - ); + render_rightside(cx, item, render_mode) + )?; if trait_.is_some() { // Anchors are only used on trait impls. - write_str(w, format_args!("§")); + write!(w, "§")?; } - write_str( + write!( w, - format_args!( - "

{}

", - assoc_const( - item, - generics, - ty, - AssocConstValue::None, - link.anchor(if trait_.is_some() { &source_id } else { &id }), - 0, - cx, - ) + "

{}

", + assoc_const( + item, + generics, + ty, + AssocConstValue::None, + link.anchor(if trait_.is_some() { &source_id } else { &id }), + 0, + cx, ), - ); + )?; } clean::ProvidedAssocConstItem(ci) | clean::ImplAssocConstItem(ci) => { let source_id = format!("{item_type}.{name}"); let id = cx.derive_id(&source_id); - write_str( + write!( w, - format_args!( - "
\ + "
\ {}", - render_rightside(cx, item, render_mode) - ), - ); + render_rightside(cx, item, render_mode), + )?; if trait_.is_some() { // Anchors are only used on trait impls. - write_str(w, format_args!("§")); + write!(w, "§")?; } - write_str( + write!( w, - format_args!( - "

{}

", - assoc_const( - item, - &ci.generics, - &ci.type_, - match item.kind { - clean::ProvidedAssocConstItem(_) => - AssocConstValue::TraitDefault(&ci.kind), - clean::ImplAssocConstItem(_) => AssocConstValue::Impl(&ci.kind), - _ => unreachable!(), - }, - link.anchor(if trait_.is_some() { &source_id } else { &id }), - 0, - cx, - ) + "

{}

", + assoc_const( + item, + &ci.generics, + &ci.type_, + match item.kind { + clean::ProvidedAssocConstItem(_) => + AssocConstValue::TraitDefault(&ci.kind), + clean::ImplAssocConstItem(_) => AssocConstValue::Impl(&ci.kind), + _ => unreachable!(), + }, + link.anchor(if trait_.is_some() { &source_id } else { &id }), + 0, + cx, ), - ); + )?; } clean::RequiredAssocTypeItem(generics, bounds) => { let source_id = format!("{item_type}.{name}"); let id = cx.derive_id(&source_id); - write_str( + write!( w, - format_args!( - "
\ + "
\ {}", - render_rightside(cx, item, render_mode) - ), - ); + render_rightside(cx, item, render_mode), + )?; if trait_.is_some() { // Anchors are only used on trait impls. - write_str(w, format_args!("§")); + write!(w, "§")?; } - write_str( + write!( w, - format_args!( - "

{}

", - assoc_type( - item, - generics, - bounds, - None, - link.anchor(if trait_.is_some() { &source_id } else { &id }), - 0, - cx, - ) + "

{}

", + assoc_type( + item, + generics, + bounds, + None, + link.anchor(if trait_.is_some() { &source_id } else { &id }), + 0, + cx, ), - ); + )?; } clean::AssocTypeItem(tydef, _bounds) => { let source_id = format!("{item_type}.{name}"); let id = cx.derive_id(&source_id); - write_str( + write!( w, - format_args!( - "
\ + "
\ {}", - render_rightside(cx, item, render_mode) - ), - ); + render_rightside(cx, item, render_mode), + )?; if trait_.is_some() { // Anchors are only used on trait impls. - write_str(w, format_args!("§")); + write!(w, "§")?; } - write_str( + write!( w, - format_args!( - "

{}

", - assoc_type( - item, - &tydef.generics, - &[], // intentionally leaving out bounds - Some(tydef.item_type.as_ref().unwrap_or(&tydef.type_)), - link.anchor(if trait_.is_some() { &source_id } else { &id }), - 0, - cx, - ) + "

{}

", + assoc_type( + item, + &tydef.generics, + &[], // intentionally leaving out bounds + Some(tydef.item_type.as_ref().unwrap_or(&tydef.type_)), + link.anchor(if trait_.is_some() { &source_id } else { &id }), + 0, + cx, ), - ); + )?; } - clean::StrippedItem(..) => return, + clean::StrippedItem(..) => return Ok(()), _ => panic!("can't make docs for trait item with name {:?}", item.name), } - w.push_str(&info_buffer); + w.write_str(&info_buffer)?; if toggled { - w.push_str("
"); - w.push_str(&doc_buffer); - w.push_str("
"); + write!(w, "
{doc_buffer}
")?; } + Ok(()) } let mut impl_items = String::new(); @@ -1960,7 +1941,7 @@ fn render_impl( false, trait_, rendering_params, - ); + )?; } _ => {} } @@ -1978,7 +1959,7 @@ fn render_impl( false, trait_, rendering_params, - ); + )?; } for method in methods { doc_impl_item( @@ -1992,20 +1973,20 @@ fn render_impl( false, trait_, rendering_params, - ); + )?; } } fn render_default_items( - boring: &mut String, - interesting: &mut String, + mut boring: impl fmt::Write, + mut interesting: impl fmt::Write, cx: &Context<'_>, t: &clean::Trait, i: &clean::Impl, parent: &clean::Item, render_mode: RenderMode, rendering_params: ImplRenderingParameters, - ) { + ) -> fmt::Result { for trait_item in &t.items { // Skip over any default trait items that are impossible to reference // (e.g. if it has a `Self: Sized` bound on an unsized type). @@ -2025,8 +2006,8 @@ fn render_impl( let assoc_link = AssocItemLink::GotoSource(did.into(), &provided_methods); doc_impl_item( - boring, - interesting, + &mut boring, + &mut interesting, cx, trait_item, parent, @@ -2035,8 +2016,9 @@ fn render_impl( true, Some(t), rendering_params, - ); + )?; } + Ok(()) } // If we've implemented a trait, then also emit documentation for all @@ -2056,7 +2038,7 @@ fn render_impl( &i.impl_item, render_mode, rendering_params, - ); + )?; } } if render_mode == RenderMode::Normal { From 8dd1cbbdad2ba128c8237714665ef25b86e9945d Mon Sep 17 00:00:00 2001 From: Yotam Ofek Date: Thu, 13 Mar 2025 13:34:00 +0000 Subject: [PATCH 319/606] lazify `render_assoc_items_inner` --- src/librustdoc/html/render/mod.rs | 91 ++++++++++++++++++------------- 1 file changed, 54 insertions(+), 37 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 511a9316aff3..94171ad6de80 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -40,6 +40,7 @@ mod span_map; mod type_layout; mod write_shared; +use std::borrow::Cow; use std::collections::VecDeque; use std::fmt::{self, Display as _, Write}; use std::iter::Peekable; @@ -99,6 +100,19 @@ enum AssocItemRender<'a> { DerefFor { trait_: &'a clean::Path, type_: &'a clean::Type, deref_mut_: bool }, } +impl AssocItemRender<'_> { + fn render_mode(&self) -> RenderMode { + match self { + Self::All => RenderMode::Normal, + &Self::DerefFor { deref_mut_, .. } => RenderMode::ForDeref { mut_: deref_mut_ }, + } + } + + fn class(&self) -> Option<&'static str> { + if let Self::DerefFor { .. } = self { Some("impl-items") } else { None } + } +} + /// For different handling of associated items from the Deref target of a type rather than the type /// itself. #[derive(Copy, Clone, PartialEq)] @@ -1211,7 +1225,7 @@ impl<'a> AssocItemLink<'a> { } fn write_section_heading( - title: &str, + title: impl fmt::Display, id: &str, extra_class: Option<&str>, extra: impl fmt::Display, @@ -1231,7 +1245,7 @@ fn write_section_heading( }) } -fn write_impl_section_heading(title: &str, id: &str) -> impl fmt::Display { +fn write_impl_section_heading(title: impl fmt::Display, id: &str) -> impl fmt::Display { write_section_heading(title, id, None, "") } @@ -1308,20 +1322,17 @@ fn render_assoc_items_inner( let (mut non_trait, traits): (Vec<_>, _) = v.iter().partition(|i| i.inner_impl().trait_.is_none()); if !non_trait.is_empty() { - let mut close_tags = >::with_capacity(1); - let mut tmp_buf = String::new(); - let (render_mode, id, class_html) = match what { - AssocItemRender::All => { - write_str( - &mut tmp_buf, - format_args!( - "{}", - write_impl_section_heading("Implementations", "implementations") - ), - ); - (RenderMode::Normal, "implementations-list".to_owned(), "") - } - AssocItemRender::DerefFor { trait_, type_, deref_mut_ } => { + let render_mode = what.render_mode(); + let class_html = what + .class() + .map(|class| fmt::from_fn(move |f| write!(f, r#" class="{class}""#))) + .maybe_display(); + let (section_heading, id) = match what { + AssocItemRender::All => ( + Either::Left(write_impl_section_heading("Implementations", "implementations")), + Cow::Borrowed("implementations-list"), + ), + AssocItemRender::DerefFor { trait_, type_, .. } => { let id = cx.derive_id(small_url_encode(format!("deref-methods-{:#}", type_.print(cx)))); // the `impls.get` above only looks at the outermost type, @@ -1335,25 +1346,27 @@ fn render_assoc_items_inner( type_.is_doc_subtype_of(&impl_.inner_impl().for_, &cx.shared.cache) }); let derived_id = cx.derive_id(&id); - close_tags.push(""); - write_str( - &mut tmp_buf, - format_args!( - "
{}", - write_impl_section_heading( - &format!( - "Methods from {trait_}<Target = {type_}>", - trait_ = trait_.print(cx), - type_ = type_.print(cx), - ), - &id, - ) - ), - ); if let Some(def_id) = type_.def_id(cx.cache()) { - cx.deref_id_map.borrow_mut().insert(def_id, id); + cx.deref_id_map.borrow_mut().insert(def_id, id.clone()); } - (RenderMode::ForDeref { mut_: deref_mut_ }, derived_id, r#" class="impl-items""#) + ( + Either::Right(fmt::from_fn(move |f| { + write!( + f, + "
{}", + write_impl_section_heading( + fmt::from_fn(|f| write!( + f, + "Methods from {trait_}<Target = {type_}>", + trait_ = trait_.print(cx), + type_ = type_.print(cx), + )), + &id, + ) + ) + })), + Cow::Owned(derived_id), + ) } }; let mut impls_buf = String::new(); @@ -1381,10 +1394,14 @@ fn render_assoc_items_inner( ); } if !impls_buf.is_empty() { - write!(w, "{tmp_buf}
{impls_buf}
").unwrap(); - for tag in close_tags.into_iter().rev() { - w.write_str(tag).unwrap(); - } + write!( + w, + "{section_heading}
{impls_buf}
{}", + matches!(what, AssocItemRender::DerefFor { .. }) + .then_some("
") + .maybe_display(), + ) + .unwrap(); } } From 74ca12951ce22dfea4f11131f8f244038d4b5f18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Thu, 10 Apr 2025 17:40:48 +0200 Subject: [PATCH 320/606] Bump `FileEncoder` buffer size to 64 kB --- compiler/rustc_serialize/src/opaque.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_serialize/src/opaque.rs b/compiler/rustc_serialize/src/opaque.rs index 81f6266f8d1f..0a55504a556d 100644 --- a/compiler/rustc_serialize/src/opaque.rs +++ b/compiler/rustc_serialize/src/opaque.rs @@ -19,7 +19,7 @@ pub type FileEncodeResult = Result; pub const MAGIC_END_BYTES: &[u8] = b"rust-end-file"; /// The size of the buffer in `FileEncoder`. -const BUF_SIZE: usize = 8192; +const BUF_SIZE: usize = 64 * 1024; /// `FileEncoder` encodes data to file via fixed-size buffer. /// From b435def33c0955712d811efc41c3ec71609196ab Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Wed, 9 Apr 2025 20:32:31 +0000 Subject: [PATCH 321/606] Update `compiler-builtins` to 0.1.153 Includes the following changes: * Avoid OOB access in `memcpy` and `memmove` [1] * Enable intrinsics on AVR [2] * `libm` updates to avoid using `core::arch` vector intrinsics [3] * Re-enable `f16` on aarch64 without Neon [4] [1]: https://github.com/rust-lang/compiler-builtins/pull/799 [2]: https://github.com/rust-lang/compiler-builtins/pull/791 [3]: https://github.com/rust-lang/compiler-builtins/pull/814 [4]: https://github.com/rust-lang/compiler-builtins/pull/809 --- library/Cargo.lock | 4 ++-- library/alloc/Cargo.toml | 2 +- library/std/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/library/Cargo.lock b/library/Cargo.lock index ad634e9f794a..d035ca6c91f5 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -67,9 +67,9 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.152" +version = "0.1.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2153cf213eb259361567720ce55f6446f17acd0ccca87fb6dc05360578228a58" +checksum = "926ef6a360c15a911023352fd6969c51605d70495406f735beb1ca0257448e59" dependencies = [ "cc", "rustc-std-workspace-core", diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml index 1d2dd1e60819..ee8cb9d25a39 100644 --- a/library/alloc/Cargo.toml +++ b/library/alloc/Cargo.toml @@ -16,7 +16,7 @@ bench = false [dependencies] core = { path = "../core", public = true } -compiler_builtins = { version = "=0.1.152", features = ['rustc-dep-of-std'] } +compiler_builtins = { version = "=0.1.153", features = ['rustc-dep-of-std'] } [features] compiler-builtins-mem = ['compiler_builtins/mem'] diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 176da603d58d..6b70ff764d7a 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -18,7 +18,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] } panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core", public = true } -compiler_builtins = { version = "=0.1.152" } +compiler_builtins = { version = "=0.1.153" } unwind = { path = "../unwind" } hashbrown = { version = "0.15", default-features = false, features = [ 'rustc-dep-of-std', From 62d5fb85ac64f034f031423cb747cf57ee14a048 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 8 Apr 2025 21:41:02 +0000 Subject: [PATCH 322/606] Simplify --- .../src/solve/fulfill/derive_errors.rs | 52 ++++++++----------- 1 file changed, 22 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs index 9cbe4147fb4a..73d3f81296fa 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs @@ -388,7 +388,8 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { (true, Ok(Certainty::Maybe(MaybeCause::Ambiguity))) | (false, Err(_)) => {} _ => return ControlFlow::Continue(()), } - let pred_kind = goal.goal().predicate.kind(); + + let pred = goal.goal().predicate; let candidates = self.non_trivial_candidates(goal); let candidate = match candidates.as_slice() { @@ -410,12 +411,12 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { // FIXME: Also, what about considering >1 layer up the stack? May be necessary // for normalizes-to. - let child_mode = match pred_kind.skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => { - ChildMode::Trait(pred_kind.rebind(pred)) + let child_mode = match pred.kind().skip_binder() { + ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) => { + ChildMode::Trait(pred.kind().rebind(trait_pred)) } - ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(pred)) => { - ChildMode::Host(pred_kind.rebind(pred)) + ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(host_pred)) => { + ChildMode::Host(pred.kind().rebind(host_pred)) } ty::PredicateKind::NormalizesTo(normalizes_to) if matches!( @@ -423,7 +424,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst ) => { - ChildMode::Trait(pred_kind.rebind(ty::TraitPredicate { + ChildMode::Trait(pred.kind().rebind(ty::TraitPredicate { trait_ref: normalizes_to.alias.trait_ref(tcx), polarity: ty::PredicatePolarity::Positive, })) @@ -457,10 +458,12 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { for nested_goal in nested_goals { trace!(nested_goal = ?(nested_goal.goal(), nested_goal.source(), nested_goal.result())); + let nested_pred = nested_goal.goal().predicate; + let make_obligation = |cause| Obligation { cause, param_env: nested_goal.goal().param_env, - predicate: nested_goal.goal().predicate, + predicate: nested_pred, recursion_depth: self.obligation.recursion_depth + 1, }; @@ -510,28 +513,17 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { // alias-relate may fail because the lhs or rhs can't be normalized, // and therefore is treated as rigid. - if let Some(ty::PredicateKind::AliasRelate(lhs, rhs, _)) = pred_kind.no_bound_vars() { - if let Some(obligation) = goal - .infcx() - .visit_proof_tree_at_depth( - goal.goal().with(tcx, ty::ClauseKind::WellFormed(lhs.into())), - goal.depth() + 1, - self, - ) - .break_value() - { - return ControlFlow::Break(obligation); - } else if let Some(obligation) = goal - .infcx() - .visit_proof_tree_at_depth( - goal.goal().with(tcx, ty::ClauseKind::WellFormed(rhs.into())), - goal.depth() + 1, - self, - ) - .break_value() - { - return ControlFlow::Break(obligation); - } + if let Some(ty::PredicateKind::AliasRelate(lhs, rhs, _)) = pred.kind().no_bound_vars() { + goal.infcx().visit_proof_tree_at_depth( + goal.goal().with(tcx, ty::ClauseKind::WellFormed(lhs.into())), + goal.depth() + 1, + self, + )?; + goal.infcx().visit_proof_tree_at_depth( + goal.goal().with(tcx, ty::ClauseKind::WellFormed(rhs.into())), + goal.depth() + 1, + self, + )?; } self.detect_error_in_higher_ranked_projection(goal)?; From 8f00b1fdad0c60220625bace86510db125ecf31a Mon Sep 17 00:00:00 2001 From: Boxy Date: Thu, 10 Apr 2025 17:48:33 +0100 Subject: [PATCH 323/606] Allow parenthesis around inferred array lengths --- compiler/rustc_ast_lowering/src/lib.rs | 4 +- .../parend_infer.nogate.stderr | 53 +++++++++++++++++++ .../generic_arg_infer/parend_infer.rs | 20 ++++++- 3 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 tests/ui/const-generics/generic_arg_infer/parend_infer.nogate.stderr diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 6aa6a18ee9a7..f62d250fcbea 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2034,7 +2034,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } fn lower_array_length_to_const_arg(&mut self, c: &AnonConst) -> &'hir hir::ConstArg<'hir> { - match c.value.kind { + // We cannot just match on `ExprKind::Underscore` as `(_)` is represented as + // `ExprKind::Paren(ExprKind::Underscore)` and should also be lowered to `GenericArg::Infer` + match c.value.peel_parens().kind { ExprKind::Underscore => { if !self.tcx.features().generic_arg_infer() { feature_err( diff --git a/tests/ui/const-generics/generic_arg_infer/parend_infer.nogate.stderr b/tests/ui/const-generics/generic_arg_infer/parend_infer.nogate.stderr new file mode 100644 index 000000000000..d0a5da9676df --- /dev/null +++ b/tests/ui/const-generics/generic_arg_infer/parend_infer.nogate.stderr @@ -0,0 +1,53 @@ +error[E0658]: const arguments cannot yet be inferred with `_` + --> $DIR/parend_infer.rs:24:16 + | +LL | let c: Foo<_> = Foo::<1>; + | ^ + | + = note: see issue #85077 for more information + = help: add `#![feature(generic_arg_infer)]` 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]: const arguments cannot yet be inferred with `_` + --> $DIR/parend_infer.rs:26:16 + | +LL | let c: Foo<(_)> = Foo::<1>; + | ^^^ + | + = note: see issue #85077 for more information + = help: add `#![feature(generic_arg_infer)]` 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]: const arguments cannot yet be inferred with `_` + --> $DIR/parend_infer.rs:28:16 + | +LL | let c: Foo<(((_)))> = Foo::<1>; + | ^^^^^^^ + | + = note: see issue #85077 for more information + = help: add `#![feature(generic_arg_infer)]` 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]: using `_` for array lengths is unstable + --> $DIR/parend_infer.rs:17:17 + | +LL | let b: [u8; (_)] = [1; (((((_)))))]; + | ^^^ + | + = note: see issue #85077 for more information + = help: add `#![feature(generic_arg_infer)]` 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]: using `_` for array lengths is unstable + --> $DIR/parend_infer.rs:17:28 + | +LL | let b: [u8; (_)] = [1; (((((_)))))]; + | ^^^^^^^^^^^ + | + = note: see issue #85077 for more information + = help: add `#![feature(generic_arg_infer)]` 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 5 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/const-generics/generic_arg_infer/parend_infer.rs b/tests/ui/const-generics/generic_arg_infer/parend_infer.rs index 81c42183b383..3dc27a702de4 100644 --- a/tests/ui/const-generics/generic_arg_infer/parend_infer.rs +++ b/tests/ui/const-generics/generic_arg_infer/parend_infer.rs @@ -1,7 +1,9 @@ -//@ check-pass +//@[gate] check-pass //@ revisions: gate nogate #![cfg_attr(gate, feature(generic_arg_infer))] +struct Foo; + fn main() { // AST Types preserve parens for pretty printing reasons. This means // that this is parsed as a `TyKind::Paren(TyKind::Infer)`. Generic @@ -9,4 +11,20 @@ fn main() { // but `TyKind::Infer` wrapped in arbitrarily many `TyKind::Paren`. let a: Vec<(_)> = vec![1_u8]; let a: Vec<(((((_)))))> = vec![1_u8]; + + // AST Exprs similarly preserve parens for pretty printing reasons. + #[rustfmt::skip] + let b: [u8; (_)] = [1; (((((_)))))]; + //[nogate]~^ error: using `_` for array lengths is unstable + //[nogate]~| error: using `_` for array lengths is unstable + let b: [u8; 2] = b; + + // This is the same case as AST types as the parser doesn't distinguish between const + // and type args when they share syntax + let c: Foo<_> = Foo::<1>; + //[nogate]~^ error: const arguments cannot yet be inferred with `_` + let c: Foo<(_)> = Foo::<1>; + //[nogate]~^ error: const arguments cannot yet be inferred with `_` + let c: Foo<(((_)))> = Foo::<1>; + //[nogate]~^ error: const arguments cannot yet be inferred with `_` } From 0069cadb9aa28ebd5dce748b1cc2e194d7e85fe7 Mon Sep 17 00:00:00 2001 From: Yotam Ofek Date: Thu, 10 Apr 2025 18:06:32 +0000 Subject: [PATCH 324/606] Micro-optimize `InstSimplify`'s `simplify_primitive_clone` --- .../rustc_mir_transform/src/instsimplify.rs | 25 ++++++------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index 2eff6b31372f..2ecae196de98 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -10,7 +10,6 @@ use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, layout}; use rustc_span::{DUMMY_SP, Symbol, sym}; use crate::simplify::simplify_duplicate_switch_targets; -use crate::take_array; pub(super) enum InstSimplify { BeforeInline, @@ -229,7 +228,9 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { terminator: &mut Terminator<'tcx>, statements: &mut Vec>, ) { - let TerminatorKind::Call { func, args, destination, target, .. } = &mut terminator.kind + let TerminatorKind::Call { + func, args, destination, target: Some(destination_block), .. + } = &terminator.kind else { return; }; @@ -237,15 +238,8 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { // It's definitely not a clone if there are multiple arguments let [arg] = &args[..] else { return }; - let Some(destination_block) = *target else { return }; - // Only bother looking more if it's easy to know what we're calling - let Some((fn_def_id, fn_args)) = func.const_fn_def() else { return }; - - // Clone needs one arg, so we can cheaply rule out other stuff - if fn_args.len() != 1 { - return; - } + let Some((fn_def_id, ..)) = func.const_fn_def() else { return }; // These types are easily available from locals, so check that before // doing DefId lookups to figure out what we're actually calling. @@ -253,15 +247,12 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { let ty::Ref(_region, inner_ty, Mutability::Not) = *arg_ty.kind() else { return }; - if !inner_ty.is_trivially_pure_clone_copy() { + if !self.tcx.is_lang_item(fn_def_id, LangItem::CloneFn) + || !inner_ty.is_trivially_pure_clone_copy() + { return; } - if !self.tcx.is_lang_item(fn_def_id, LangItem::CloneFn) { - return; - } - - let Ok([arg]) = take_array(args) else { return }; let Some(arg_place) = arg.node.place() else { return }; statements.push(Statement { @@ -273,7 +264,7 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { )), ))), }); - terminator.kind = TerminatorKind::Goto { target: destination_block }; + terminator.kind = TerminatorKind::Goto { target: *destination_block }; } fn simplify_nounwind_call(&self, terminator: &mut Terminator<'tcx>) { From f243cb8861fc2def232e43b6acc2e2cd6867b89c Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Wed, 9 Apr 2025 22:53:57 -0700 Subject: [PATCH 325/606] Implement RtlNtStatusToDosError and shim test for it --- .../miri/src/shims/windows/foreign_items.rs | 19 +++++++++++++++++++ .../miri/tests/pass-dep/shims/windows-fs.rs | 11 ++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs index 33b654042391..0c4afc069e20 100644 --- a/src/tools/miri/src/shims/windows/foreign_items.rs +++ b/src/tools/miri/src/shims/windows/foreign_items.rs @@ -346,6 +346,25 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let last_error = this.get_last_error()?; this.write_scalar(last_error, dest)?; } + "RtlNtStatusToDosError" => { + let [status] = this.check_shim(abi, sys_conv, link_name, args)?; + let status = this.read_scalar(status)?.to_u32()?; + let err = match status { + // STATUS_MEDIA_WRITE_PROTECTED => ERROR_WRITE_PROTECT + 0xC00000A2 => 19, + // STATUS_FILE_INVALID => ERROR_FILE_INVALID + 0xC0000098 => 1006, + // STATUS_DISK_FULL => ERROR_DISK_FULL + 0xC000007F => 112, + // STATUS_IO_DEVICE_ERROR => ERROR_IO_DEVICE + 0xC0000185 => 1117, + // STATUS_ACCESS_DENIED => ERROR_ACCESS_DENIED + 0xC0000022 => 5, + // Anything without an error code => ERROR_MR_MID_NOT_FOUND + _ => 317, + }; + this.write_scalar(Scalar::from_i32(err), dest)?; + } // Querying system information "GetSystemInfo" => { diff --git a/src/tools/miri/tests/pass-dep/shims/windows-fs.rs b/src/tools/miri/tests/pass-dep/shims/windows-fs.rs index 312df9eb115d..a015464dbde3 100644 --- a/src/tools/miri/tests/pass-dep/shims/windows-fs.rs +++ b/src/tools/miri/tests/pass-dep/shims/windows-fs.rs @@ -10,7 +10,9 @@ use std::ptr; mod utils; use windows_sys::Win32::Foundation::{ - CloseHandle, ERROR_ALREADY_EXISTS, GENERIC_READ, GENERIC_WRITE, GetLastError, + CloseHandle, ERROR_ACCESS_DENIED, ERROR_ALREADY_EXISTS, ERROR_IO_DEVICE, GENERIC_READ, + GENERIC_WRITE, GetLastError, RtlNtStatusToDosError, STATUS_ACCESS_DENIED, + STATUS_IO_DEVICE_ERROR, }; use windows_sys::Win32::Storage::FileSystem::{ BY_HANDLE_FILE_INFORMATION, CREATE_ALWAYS, CREATE_NEW, CreateFileW, FILE_ATTRIBUTE_DIRECTORY, @@ -26,6 +28,7 @@ fn main() { test_create_always_twice(); test_open_always_twice(); test_open_dir_reparse(); + test_ntstatus_to_dos(); } } @@ -191,6 +194,12 @@ unsafe fn test_open_dir_reparse() { }; } +unsafe fn test_ntstatus_to_dos() { + // We won't test all combinations, just a couple common ones + assert_eq!(RtlNtStatusToDosError(STATUS_IO_DEVICE_ERROR), ERROR_IO_DEVICE); + assert_eq!(RtlNtStatusToDosError(STATUS_ACCESS_DENIED), ERROR_ACCESS_DENIED); +} + fn to_wide_cstr(path: &Path) -> Vec { let mut raw_path = path.as_os_str().encode_wide().collect::>(); raw_path.extend([0, 0]); From 9491242ff70618571d3b0e102e800c04f8603ba9 Mon Sep 17 00:00:00 2001 From: Yotam Ofek Date: Thu, 10 Apr 2025 15:26:27 +0000 Subject: [PATCH 326/606] Cleanup the `InstSimplify` MIR transformation --- .../rustc_mir_transform/src/instsimplify.rs | 192 ++++++++---------- 1 file changed, 86 insertions(+), 106 deletions(-) diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index 2eff6b31372f..a8d6aaa50a29 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -39,26 +39,26 @@ impl<'tcx> crate::MirPass<'tcx> for InstSimplify { attr::contains_name(tcx.hir_krate_attrs(), sym::rustc_preserve_ub_checks); for block in body.basic_blocks.as_mut() { for statement in block.statements.iter_mut() { - match statement.kind { - StatementKind::Assign(box (_place, ref mut rvalue)) => { - if !preserve_ub_checks { - ctx.simplify_ub_check(rvalue); - } - ctx.simplify_bool_cmp(rvalue); - ctx.simplify_ref_deref(rvalue); - ctx.simplify_ptr_aggregate(rvalue); - ctx.simplify_cast(rvalue); - ctx.simplify_repeated_aggregate(rvalue); - ctx.simplify_repeat_once(rvalue); - } - _ => {} + let StatementKind::Assign(box (.., rvalue)) = &mut statement.kind else { + continue; + }; + + if !preserve_ub_checks { + ctx.simplify_ub_check(rvalue); } + ctx.simplify_bool_cmp(rvalue); + ctx.simplify_ref_deref(rvalue); + ctx.simplify_ptr_aggregate(rvalue); + ctx.simplify_cast(rvalue); + ctx.simplify_repeated_aggregate(rvalue); + ctx.simplify_repeat_once(rvalue); } - ctx.simplify_primitive_clone(block.terminator.as_mut().unwrap(), &mut block.statements); - ctx.simplify_intrinsic_assert(block.terminator.as_mut().unwrap()); - ctx.simplify_nounwind_call(block.terminator.as_mut().unwrap()); - simplify_duplicate_switch_targets(block.terminator.as_mut().unwrap()); + let terminator = block.terminator.as_mut().unwrap(); + ctx.simplify_primitive_clone(terminator, &mut block.statements); + ctx.simplify_intrinsic_assert(terminator); + ctx.simplify_nounwind_call(terminator); + simplify_duplicate_switch_targets(terminator); } } @@ -105,43 +105,34 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { /// Transform boolean comparisons into logical operations. fn simplify_bool_cmp(&self, rvalue: &mut Rvalue<'tcx>) { - match rvalue { - Rvalue::BinaryOp(op @ (BinOp::Eq | BinOp::Ne), box (a, b)) => { - let new = match (op, self.try_eval_bool(a), self.try_eval_bool(b)) { - // Transform "Eq(a, true)" ==> "a" - (BinOp::Eq, _, Some(true)) => Some(Rvalue::Use(a.clone())), + let Rvalue::BinaryOp(op @ (BinOp::Eq | BinOp::Ne), box (a, b)) = &*rvalue else { return }; + *rvalue = match (op, self.try_eval_bool(a), self.try_eval_bool(b)) { + // Transform "Eq(a, true)" ==> "a" + (BinOp::Eq, _, Some(true)) => Rvalue::Use(a.clone()), - // Transform "Ne(a, false)" ==> "a" - (BinOp::Ne, _, Some(false)) => Some(Rvalue::Use(a.clone())), + // Transform "Ne(a, false)" ==> "a" + (BinOp::Ne, _, Some(false)) => Rvalue::Use(a.clone()), - // Transform "Eq(true, b)" ==> "b" - (BinOp::Eq, Some(true), _) => Some(Rvalue::Use(b.clone())), + // Transform "Eq(true, b)" ==> "b" + (BinOp::Eq, Some(true), _) => Rvalue::Use(b.clone()), - // Transform "Ne(false, b)" ==> "b" - (BinOp::Ne, Some(false), _) => Some(Rvalue::Use(b.clone())), + // Transform "Ne(false, b)" ==> "b" + (BinOp::Ne, Some(false), _) => Rvalue::Use(b.clone()), - // Transform "Eq(false, b)" ==> "Not(b)" - (BinOp::Eq, Some(false), _) => Some(Rvalue::UnaryOp(UnOp::Not, b.clone())), + // Transform "Eq(false, b)" ==> "Not(b)" + (BinOp::Eq, Some(false), _) => Rvalue::UnaryOp(UnOp::Not, b.clone()), - // Transform "Ne(true, b)" ==> "Not(b)" - (BinOp::Ne, Some(true), _) => Some(Rvalue::UnaryOp(UnOp::Not, b.clone())), + // Transform "Ne(true, b)" ==> "Not(b)" + (BinOp::Ne, Some(true), _) => Rvalue::UnaryOp(UnOp::Not, b.clone()), - // Transform "Eq(a, false)" ==> "Not(a)" - (BinOp::Eq, _, Some(false)) => Some(Rvalue::UnaryOp(UnOp::Not, a.clone())), + // Transform "Eq(a, false)" ==> "Not(a)" + (BinOp::Eq, _, Some(false)) => Rvalue::UnaryOp(UnOp::Not, a.clone()), - // Transform "Ne(a, true)" ==> "Not(a)" - (BinOp::Ne, _, Some(true)) => Some(Rvalue::UnaryOp(UnOp::Not, a.clone())), + // Transform "Ne(a, true)" ==> "Not(a)" + (BinOp::Ne, _, Some(true)) => Rvalue::UnaryOp(UnOp::Not, a.clone()), - _ => None, - }; - - if let Some(new) = new { - *rvalue = new; - } - } - - _ => {} - } + _ => return, + }; } fn try_eval_bool(&self, a: &Operand<'_>) -> Option { @@ -151,64 +142,58 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { /// Transform `&(*a)` ==> `a`. fn simplify_ref_deref(&self, rvalue: &mut Rvalue<'tcx>) { - if let Rvalue::Ref(_, _, place) | Rvalue::RawPtr(_, place) = rvalue { - if let Some((base, ProjectionElem::Deref)) = place.as_ref().last_projection() { - if rvalue.ty(self.local_decls, self.tcx) != base.ty(self.local_decls, self.tcx).ty { - return; - } - - *rvalue = Rvalue::Use(Operand::Copy(Place { - local: base.local, - projection: self.tcx.mk_place_elems(base.projection), - })); - } + if let Rvalue::Ref(_, _, place) | Rvalue::RawPtr(_, place) = rvalue + && let Some((base, ProjectionElem::Deref)) = place.as_ref().last_projection() + && rvalue.ty(self.local_decls, self.tcx) == base.ty(self.local_decls, self.tcx).ty + { + *rvalue = Rvalue::Use(Operand::Copy(Place { + local: base.local, + projection: self.tcx.mk_place_elems(base.projection), + })); } } /// Transform `Aggregate(RawPtr, [p, ()])` ==> `Cast(PtrToPtr, p)`. fn simplify_ptr_aggregate(&self, rvalue: &mut Rvalue<'tcx>) { if let Rvalue::Aggregate(box AggregateKind::RawPtr(pointee_ty, mutability), fields) = rvalue + && let meta_ty = fields.raw[1].ty(self.local_decls, self.tcx) + && meta_ty.is_unit() { - let meta_ty = fields.raw[1].ty(self.local_decls, self.tcx); - if meta_ty.is_unit() { - // The mutable borrows we're holding prevent printing `rvalue` here - let mut fields = std::mem::take(fields); - let _meta = fields.pop().unwrap(); - let data = fields.pop().unwrap(); - let ptr_ty = Ty::new_ptr(self.tcx, *pointee_ty, *mutability); - *rvalue = Rvalue::Cast(CastKind::PtrToPtr, data, ptr_ty); - } + // The mutable borrows we're holding prevent printing `rvalue` here + let mut fields = std::mem::take(fields); + let _meta = fields.pop().unwrap(); + let data = fields.pop().unwrap(); + let ptr_ty = Ty::new_ptr(self.tcx, *pointee_ty, *mutability); + *rvalue = Rvalue::Cast(CastKind::PtrToPtr, data, ptr_ty); } } fn simplify_ub_check(&self, rvalue: &mut Rvalue<'tcx>) { - if let Rvalue::NullaryOp(NullOp::UbChecks, _) = *rvalue { - let const_ = Const::from_bool(self.tcx, self.tcx.sess.ub_checks()); - let constant = ConstOperand { span: DUMMY_SP, const_, user_ty: None }; - *rvalue = Rvalue::Use(Operand::Constant(Box::new(constant))); - } + let Rvalue::NullaryOp(NullOp::UbChecks, _) = *rvalue else { return }; + + let const_ = Const::from_bool(self.tcx, self.tcx.sess.ub_checks()); + let constant = ConstOperand { span: DUMMY_SP, const_, user_ty: None }; + *rvalue = Rvalue::Use(Operand::Constant(Box::new(constant))); } fn simplify_cast(&self, rvalue: &mut Rvalue<'tcx>) { - if let Rvalue::Cast(kind, operand, cast_ty) = rvalue { - let operand_ty = operand.ty(self.local_decls, self.tcx); - if operand_ty == *cast_ty { - *rvalue = Rvalue::Use(operand.clone()); - } else if *kind == CastKind::Transmute { - // Transmuting an integer to another integer is just a signedness cast - if let (ty::Int(int), ty::Uint(uint)) | (ty::Uint(uint), ty::Int(int)) = - (operand_ty.kind(), cast_ty.kind()) - && int.bit_width() == uint.bit_width() - { - // The width check isn't strictly necessary, as different widths - // are UB and thus we'd be allowed to turn it into a cast anyway. - // But let's keep the UB around for codegen to exploit later. - // (If `CastKind::Transmute` ever becomes *not* UB for mismatched sizes, - // then the width check is necessary for big-endian correctness.) - *kind = CastKind::IntToInt; - return; - } - } + let Rvalue::Cast(kind, operand, cast_ty) = rvalue else { return }; + + let operand_ty = operand.ty(self.local_decls, self.tcx); + if operand_ty == *cast_ty { + *rvalue = Rvalue::Use(operand.clone()); + } else if *kind == CastKind::Transmute + // Transmuting an integer to another integer is just a signedness cast + && let (ty::Int(int), ty::Uint(uint)) | (ty::Uint(uint), ty::Int(int)) = + (operand_ty.kind(), cast_ty.kind()) + && int.bit_width() == uint.bit_width() + { + // The width check isn't strictly necessary, as different widths + // are UB and thus we'd be allowed to turn it into a cast anyway. + // But let's keep the UB around for codegen to exploit later. + // (If `CastKind::Transmute` ever becomes *not* UB for mismatched sizes, + // then the width check is necessary for big-endian correctness.) + *kind = CastKind::IntToInt; } } @@ -277,7 +262,7 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { } fn simplify_nounwind_call(&self, terminator: &mut Terminator<'tcx>) { - let TerminatorKind::Call { func, unwind, .. } = &mut terminator.kind else { + let TerminatorKind::Call { ref func, ref mut unwind, .. } = terminator.kind else { return; }; @@ -290,7 +275,7 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { ty::FnDef(..) => body_ty.fn_sig(self.tcx).abi(), ty::Closure(..) => ExternAbi::RustCall, ty::Coroutine(..) => ExternAbi::Rust, - _ => bug!("unexpected body ty: {:?}", body_ty), + _ => bug!("unexpected body ty: {body_ty:?}"), }; if !layout::fn_can_unwind(self.tcx, Some(def_id), body_abi) { @@ -299,10 +284,9 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { } fn simplify_intrinsic_assert(&self, terminator: &mut Terminator<'tcx>) { - let TerminatorKind::Call { func, target, .. } = &mut terminator.kind else { - return; - }; - let Some(target_block) = target else { + let TerminatorKind::Call { ref func, target: ref mut target @ Some(target_block), .. } = + terminator.kind + else { return; }; let func_ty = func.ty(self.local_decls, self.tcx); @@ -310,12 +294,10 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { return; }; // The intrinsics we are interested in have one generic parameter - if args.is_empty() { - return; - } + let [arg, ..] = args[..] else { return }; let known_is_valid = - intrinsic_assert_panics(self.tcx, self.typing_env, args[0], intrinsic_name); + intrinsic_assert_panics(self.tcx, self.typing_env, arg, intrinsic_name); match known_is_valid { // We don't know the layout or it's not validity assertion at all, don't touch it None => {} @@ -325,7 +307,7 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { } Some(false) => { // If we know the assert does not panic, turn the call into a Goto - terminator.kind = TerminatorKind::Goto { target: *target_block }; + terminator.kind = TerminatorKind::Goto { target: target_block }; } } } @@ -346,9 +328,7 @@ fn resolve_rust_intrinsic<'tcx>( tcx: TyCtxt<'tcx>, func_ty: Ty<'tcx>, ) -> Option<(Symbol, GenericArgsRef<'tcx>)> { - if let ty::FnDef(def_id, args) = *func_ty.kind() { - let intrinsic = tcx.intrinsic(def_id)?; - return Some((intrinsic.name, args)); - } - None + let ty::FnDef(def_id, args) = *func_ty.kind() else { return None }; + let intrinsic = tcx.intrinsic(def_id)?; + Some((intrinsic.name, args)) } From decd7ecd1e3640c4bada4f4a3de411a8d507d40c Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 9 Apr 2025 17:25:46 +0000 Subject: [PATCH 327/606] Deeply normalize obligations in BestObligation --- .../src/solve/fulfill/derive_errors.rs | 19 ++- .../src/solve/normalize.rs | 32 ++-- .../as_expression.next.stderr | 12 +- .../do_not_recommend/as_expression.rs | 3 +- .../unsatisfied-const-trait-bound.stderr | 138 +++++++++++++++--- tests/ui/traits/next-solver/async.fail.stderr | 4 +- tests/ui/traits/next-solver/async.rs | 2 +- .../traits/next-solver/more-object-bound.rs | 2 +- .../next-solver/more-object-bound.stderr | 12 +- .../recursive-self-normalization-2.rs | 2 +- .../recursive-self-normalization-2.stderr | 6 +- 11 files changed, 172 insertions(+), 60 deletions(-) diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs index 73d3f81296fa..d8dcd12aecb9 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs @@ -13,9 +13,9 @@ use rustc_next_trait_solver::solve::{GenerateProofTree, SolverDelegateEvalExt as use rustc_type_ir::solve::NoSolution; use tracing::{instrument, trace}; -use crate::solve::Certainty; use crate::solve::delegate::SolverDelegate; use crate::solve::inspect::{self, ProofTreeInferCtxtExt, ProofTreeVisitor}; +use crate::solve::{Certainty, deeply_normalize_for_diagnostics}; use crate::traits::{FulfillmentError, FulfillmentErrorCode, wf}; pub(super) fn fulfillment_error_for_no_solution<'tcx>( @@ -151,7 +151,7 @@ fn find_best_leaf_obligation<'tcx>( // // We should probably fix the visitor to not do so instead, as this also // means the leaf obligation may be incorrect. - infcx + let obligation = infcx .fudge_inference_if_ok(|| { infcx .visit_proof_tree( @@ -161,7 +161,8 @@ fn find_best_leaf_obligation<'tcx>( .break_value() .ok_or(()) }) - .unwrap_or(obligation) + .unwrap_or(obligation); + deeply_normalize_for_diagnostics(infcx, obligation.param_env, obligation) } struct BestObligation<'tcx> { @@ -298,7 +299,7 @@ impl<'tcx> BestObligation<'tcx> { /// `NormalizesTo` goal, so we don't fall back to the rigid projection check /// that should catch when a projection goal fails due to an unsatisfied trait /// goal. - fn detect_error_in_higher_ranked_projection( + fn detect_trait_error_in_higher_ranked_projection( &mut self, goal: &inspect::InspectGoal<'_, 'tcx>, ) -> ControlFlow> { @@ -307,7 +308,13 @@ impl<'tcx> BestObligation<'tcx> { && !projection_clause.bound_vars().is_empty() { let pred = projection_clause.map_bound(|proj| proj.projection_term.trait_ref(tcx)); - self.with_derived_obligation(self.obligation.with(tcx, pred), |this| { + let obligation = Obligation::new( + tcx, + self.obligation.cause.clone(), + goal.goal().param_env, + deeply_normalize_for_diagnostics(goal.infcx(), goal.goal().param_env, pred), + ); + self.with_derived_obligation(obligation, |this| { goal.infcx().visit_proof_tree_at_depth( goal.goal().with(tcx, pred), goal.depth() + 1, @@ -526,7 +533,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { )?; } - self.detect_error_in_higher_ranked_projection(goal)?; + self.detect_trait_error_in_higher_ranked_projection(goal)?; ControlFlow::Break(self.obligation.clone()) } diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs index 232357dc71a0..79fb044a67f8 100644 --- a/compiler/rustc_trait_selection/src/solve/normalize.rs +++ b/compiler/rustc_trait_selection/src/solve/normalize.rs @@ -253,20 +253,28 @@ impl<'tcx> TypeFolder> for DeeplyNormalizeForDiagnosticsFolder<'_, } fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - deeply_normalize_with_skipped_universes( - self.at, - ty, - vec![None; ty.outer_exclusive_binder().as_usize()], - ) - .unwrap_or_else(|_: Vec>| ty.super_fold_with(self)) + let infcx = self.at.infcx; + infcx + .commit_if_ok(|_| { + deeply_normalize_with_skipped_universes( + self.at, + ty, + vec![None; ty.outer_exclusive_binder().as_usize()], + ) + }) + .unwrap_or_else(|_: Vec>| ty.super_fold_with(self)) } fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { - deeply_normalize_with_skipped_universes( - self.at, - ct, - vec![None; ct.outer_exclusive_binder().as_usize()], - ) - .unwrap_or_else(|_: Vec>| ct.super_fold_with(self)) + let infcx = self.at.infcx; + infcx + .commit_if_ok(|_| { + deeply_normalize_with_skipped_universes( + self.at, + ct, + vec![None; ct.outer_exclusive_binder().as_usize()], + ) + }) + .unwrap_or_else(|_: Vec>| ct.super_fold_with(self)) } } diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr index 90bb715a0522..6170250992ce 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr @@ -1,12 +1,14 @@ -error[E0277]: the trait bound `&str: AsExpression<::SqlType>` is not satisfied +error[E0277]: the trait bound `&str: AsExpression` is not satisfied --> $DIR/as_expression.rs:56:21 | LL | SelectInt.check("bar"); - | ----- ^^^^^ the trait `AsExpression<::SqlType>` is not implemented for `&str` + | ----- ^^^^^ the trait `AsExpression` is not implemented for `&str` | | | required by a bound introduced by this call | - = help: the trait `AsExpression` is implemented for `&str` + = help: the trait `AsExpression` is not implemented for `&str` + but trait `AsExpression` is implemented for it + = help: for that trait implementation, expected `Text`, found `Integer` note: required by a bound in `Foo::check` --> $DIR/as_expression.rs:47:12 | @@ -16,11 +18,11 @@ LL | where LL | T: AsExpression, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::check` -error[E0271]: type mismatch resolving `::SqlType == Text` +error[E0271]: type mismatch resolving `Integer == Text` --> $DIR/as_expression.rs:56:5 | LL | SelectInt.check("bar"); - | ^^^^^^^^^^^^^^^^^^^^^^ expected `Text`, found `Integer` + | ^^^^^^^^^^^^^^^^^^^^^^ types differ error: aborting due to 2 previous errors diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs index b5ff76809a2c..673adb82870d 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs +++ b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs @@ -54,7 +54,6 @@ impl Foo for T where T: Expression {} fn main() { SelectInt.check("bar"); - //[current]~^ ERROR the trait bound `&str: AsExpression` is not satisfied - //[next]~^^ ERROR the trait bound `&str: AsExpression<::SqlType>` is not satisfied + //~^ ERROR the trait bound `&str: AsExpression` is not satisfied //[next]~| ERROR type mismatch } diff --git a/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr b/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr index be761e49ba0c..03e26615d7ed 100644 --- a/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr +++ b/tests/ui/traits/const-traits/unsatisfied-const-trait-bound.stderr @@ -6,30 +6,134 @@ LL | #![feature(const_trait_impl, generic_const_exprs)] | = help: remove one of these features -error[E0277]: the trait bound `T: const Trait` is not satisfied - --> $DIR/unsatisfied-const-trait-bound.rs:29:37 +error[E0391]: cycle detected when evaluating type-level constant + --> $DIR/unsatisfied-const-trait-bound.rs:29:35 | LL | fn accept0(_: Container<{ T::make() }>) {} - | ^ + | ^^^^^^^^^^^^^ + | +note: ...which requires const-evaluating + checking `accept0::{constant#0}`... + --> $DIR/unsatisfied-const-trait-bound.rs:29:35 + | +LL | fn accept0(_: Container<{ T::make() }>) {} + | ^^^^^^^^^^^^^ +note: ...which requires caching mir of `accept0::{constant#0}` for CTFE... + --> $DIR/unsatisfied-const-trait-bound.rs:29:35 + | +LL | fn accept0(_: Container<{ T::make() }>) {} + | ^^^^^^^^^^^^^ +note: ...which requires elaborating drops for `accept0::{constant#0}`... + --> $DIR/unsatisfied-const-trait-bound.rs:29:35 + | +LL | fn accept0(_: Container<{ T::make() }>) {} + | ^^^^^^^^^^^^^ +note: ...which requires borrow-checking `accept0::{constant#0}`... + --> $DIR/unsatisfied-const-trait-bound.rs:29:35 + | +LL | fn accept0(_: Container<{ T::make() }>) {} + | ^^^^^^^^^^^^^ +note: ...which requires promoting constants in MIR for `accept0::{constant#0}`... + --> $DIR/unsatisfied-const-trait-bound.rs:29:35 + | +LL | fn accept0(_: Container<{ T::make() }>) {} + | ^^^^^^^^^^^^^ +note: ...which requires const checking `accept0::{constant#0}`... + --> $DIR/unsatisfied-const-trait-bound.rs:29:35 + | +LL | fn accept0(_: Container<{ T::make() }>) {} + | ^^^^^^^^^^^^^ +note: ...which requires building MIR for `accept0::{constant#0}`... + --> $DIR/unsatisfied-const-trait-bound.rs:29:35 + | +LL | fn accept0(_: Container<{ T::make() }>) {} + | ^^^^^^^^^^^^^ +note: ...which requires building an abstract representation for `accept0::{constant#0}`... + --> $DIR/unsatisfied-const-trait-bound.rs:29:35 + | +LL | fn accept0(_: Container<{ T::make() }>) {} + | ^^^^^^^^^^^^^ +note: ...which requires building THIR for `accept0::{constant#0}`... + --> $DIR/unsatisfied-const-trait-bound.rs:29:35 + | +LL | fn accept0(_: Container<{ T::make() }>) {} + | ^^^^^^^^^^^^^ +note: ...which requires type-checking `accept0::{constant#0}`... + --> $DIR/unsatisfied-const-trait-bound.rs:29:35 + | +LL | fn accept0(_: Container<{ T::make() }>) {} + | ^^^^^^^^^^^^^ + = note: ...which again requires evaluating type-level constant, completing the cycle +note: cycle used when checking that `accept0` is well-formed + --> $DIR/unsatisfied-const-trait-bound.rs:29:1 + | +LL | fn accept0(_: Container<{ T::make() }>) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = 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[E0277]: the trait bound `T: const Trait` is not satisfied - --> $DIR/unsatisfied-const-trait-bound.rs:33:50 +error[E0391]: cycle detected when caching mir of `accept1::{constant#0}` for CTFE + --> $DIR/unsatisfied-const-trait-bound.rs:33:48 | LL | const fn accept1(_: Container<{ T::make() }>) {} - | ^ - -error[E0277]: the trait bound `Ty: const Trait` is not satisfied - --> $DIR/unsatisfied-const-trait-bound.rs:22:15 + | ^^^^^^^^^^^^^ | -LL | require::(); - | ^^ +note: ...which requires elaborating drops for `accept1::{constant#0}`... + --> $DIR/unsatisfied-const-trait-bound.rs:33:48 | -note: required by a bound in `require` - --> $DIR/unsatisfied-const-trait-bound.rs:8:15 +LL | const fn accept1(_: Container<{ T::make() }>) {} + | ^^^^^^^^^^^^^ +note: ...which requires borrow-checking `accept1::{constant#0}`... + --> $DIR/unsatisfied-const-trait-bound.rs:33:48 | -LL | fn require() {} - | ^^^^^^^^^^^ required by this bound in `require` +LL | const fn accept1(_: Container<{ T::make() }>) {} + | ^^^^^^^^^^^^^ +note: ...which requires promoting constants in MIR for `accept1::{constant#0}`... + --> $DIR/unsatisfied-const-trait-bound.rs:33:48 + | +LL | const fn accept1(_: Container<{ T::make() }>) {} + | ^^^^^^^^^^^^^ +note: ...which requires const checking `accept1::{constant#0}`... + --> $DIR/unsatisfied-const-trait-bound.rs:33:48 + | +LL | const fn accept1(_: Container<{ T::make() }>) {} + | ^^^^^^^^^^^^^ +note: ...which requires building MIR for `accept1::{constant#0}`... + --> $DIR/unsatisfied-const-trait-bound.rs:33:48 + | +LL | const fn accept1(_: Container<{ T::make() }>) {} + | ^^^^^^^^^^^^^ +note: ...which requires building an abstract representation for `accept1::{constant#0}`... + --> $DIR/unsatisfied-const-trait-bound.rs:33:48 + | +LL | const fn accept1(_: Container<{ T::make() }>) {} + | ^^^^^^^^^^^^^ +note: ...which requires building THIR for `accept1::{constant#0}`... + --> $DIR/unsatisfied-const-trait-bound.rs:33:48 + | +LL | const fn accept1(_: Container<{ T::make() }>) {} + | ^^^^^^^^^^^^^ +note: ...which requires type-checking `accept1::{constant#0}`... + --> $DIR/unsatisfied-const-trait-bound.rs:33:48 + | +LL | const fn accept1(_: Container<{ T::make() }>) {} + | ^^^^^^^^^^^^^ +note: ...which requires evaluating type-level constant... + --> $DIR/unsatisfied-const-trait-bound.rs:33:48 + | +LL | const fn accept1(_: Container<{ T::make() }>) {} + | ^^^^^^^^^^^^^ +note: ...which requires const-evaluating + checking `accept1::{constant#0}`... + --> $DIR/unsatisfied-const-trait-bound.rs:33:48 + | +LL | const fn accept1(_: Container<{ T::make() }>) {} + | ^^^^^^^^^^^^^ + = note: ...which again requires caching mir of `accept1::{constant#0}` for CTFE, completing the cycle +note: cycle used when const-evaluating + checking `accept1::{constant#0}` + --> $DIR/unsatisfied-const-trait-bound.rs:33:48 + | +LL | const fn accept1(_: Container<{ T::make() }>) {} + | ^^^^^^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/traits/next-solver/async.fail.stderr b/tests/ui/traits/next-solver/async.fail.stderr index bc89842d16a1..a76a10d20ee8 100644 --- a/tests/ui/traits/next-solver/async.fail.stderr +++ b/tests/ui/traits/next-solver/async.fail.stderr @@ -1,8 +1,8 @@ -error[E0271]: expected `{async block@$DIR/async.rs:12:17: 12:22}` to be a future that resolves to `i32`, but it resolves to `()` +error[E0271]: type mismatch resolving `() == i32` --> $DIR/async.rs:12:17 | LL | needs_async(async {}); - | ----------- ^^^^^^^^ expected `i32`, found `()` + | ----------- ^^^^^^^^ types differ | | | required by a bound introduced by this call | diff --git a/tests/ui/traits/next-solver/async.rs b/tests/ui/traits/next-solver/async.rs index fded77435475..34c0ed02eeb1 100644 --- a/tests/ui/traits/next-solver/async.rs +++ b/tests/ui/traits/next-solver/async.rs @@ -10,7 +10,7 @@ fn needs_async(_: impl Future) {} #[cfg(fail)] fn main() { needs_async(async {}); - //[fail]~^ ERROR expected `{async block@$DIR/async.rs:12:17: 12:22}` to be a future that resolves to `i32`, but it resolves to `()` + //[fail]~^ ERROR type mismatch resolving `() == i32` } #[cfg(pass)] diff --git a/tests/ui/traits/next-solver/more-object-bound.rs b/tests/ui/traits/next-solver/more-object-bound.rs index 3d3fdc926f65..1dad1903a649 100644 --- a/tests/ui/traits/next-solver/more-object-bound.rs +++ b/tests/ui/traits/next-solver/more-object-bound.rs @@ -10,7 +10,7 @@ trait Trait: SuperTrait::B> {} fn transmute(x: A) -> B { foo::>(x) - //~^ ERROR type mismatch resolving ` as SuperTrait>::A == B` + //~^ ERROR type mismatch resolving `A == B` } fn foo(x: T::A) -> B diff --git a/tests/ui/traits/next-solver/more-object-bound.stderr b/tests/ui/traits/next-solver/more-object-bound.stderr index 39849d4c865e..d04376cc9c64 100644 --- a/tests/ui/traits/next-solver/more-object-bound.stderr +++ b/tests/ui/traits/next-solver/more-object-bound.stderr @@ -1,17 +1,9 @@ -error[E0271]: type mismatch resolving ` as SuperTrait>::A == B` +error[E0271]: type mismatch resolving `A == B` --> $DIR/more-object-bound.rs:12:5 | -LL | fn transmute(x: A) -> B { - | - - expected type parameter - | | - | found type parameter LL | foo::>(x) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `B`, found type parameter `A` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ | - = note: expected type parameter `B` - found type parameter `A` - = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound - = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters = note: required because it appears within the type `dyn Trait` note: required by a bound in `foo` --> $DIR/more-object-bound.rs:18:8 diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs index 94a9484ecdcf..b2a8c8cb4ae6 100644 --- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs +++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs @@ -13,7 +13,7 @@ fn needs_bar() {} fn test::Assoc2> + Foo2::Assoc1>>() { needs_bar::(); - //~^ ERROR the trait bound `::Assoc1: Bar` is not satisfied + //~^ ERROR the trait bound `::Assoc2: Bar` is not satisfied } fn main() {} diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr index 6f5111a6193c..c4be47e3520d 100644 --- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr +++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr @@ -1,8 +1,8 @@ -error[E0277]: the trait bound `::Assoc1: Bar` is not satisfied +error[E0277]: the trait bound `::Assoc2: Bar` is not satisfied --> $DIR/recursive-self-normalization-2.rs:15:17 | LL | needs_bar::(); - | ^^^^^^^^^ the trait `Bar` is not implemented for `::Assoc1` + | ^^^^^^^^^ the trait `Bar` is not implemented for `::Assoc2` | note: required by a bound in `needs_bar` --> $DIR/recursive-self-normalization-2.rs:12:17 @@ -11,7 +11,7 @@ LL | fn needs_bar() {} | ^^^ required by this bound in `needs_bar` help: consider further restricting the associated type | -LL | fn test::Assoc2> + Foo2::Assoc1>>() where ::Assoc1: Bar { +LL | fn test::Assoc2> + Foo2::Assoc1>>() where ::Assoc2: Bar { | ++++++++++++++++++++++++++++++ error: aborting due to 1 previous error From 22dd86c015da5074037a821c5b99013cd98b9029 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sun, 6 Apr 2025 17:28:08 +0200 Subject: [PATCH 328/606] Encode dep node edge count as u32 instead of usize --- .../src/dep_graph/serialized.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs index 7750d6d1fef4..38100242ebff 100644 --- a/compiler/rustc_query_system/src/dep_graph/serialized.rs +++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs @@ -226,12 +226,12 @@ impl SerializedDepGraph { // If the length of this node's edge list is small, the length is stored in the header. // If it is not, we fall back to another decoder call. - let num_edges = node_header.len().unwrap_or_else(|| d.read_usize()); + let num_edges = node_header.len().unwrap_or_else(|| d.read_u32()); // The edges index list uses the same varint strategy as rmeta tables; we select the // number of byte elements per-array not per-element. This lets us read the whole edge // list for a node with one decoder call and also use the on-disk format in memory. - let edges_len_bytes = node_header.bytes_per_index() * num_edges; + let edges_len_bytes = node_header.bytes_per_index() * (num_edges as usize); // The in-memory structure for the edges list stores the byte width of the edges on // this node with the offset into the global edge data array. let edges_header = node_header.edges_header(&edge_list_data); @@ -296,7 +296,7 @@ struct SerializedNodeHeader { // The fields of a `SerializedNodeHeader`, this struct is an implementation detail and exists only // to make the implementation of `SerializedNodeHeader` simpler. struct Unpacked { - len: Option, + len: Option, bytes_per_index: usize, kind: DepKind, hash: PackedFingerprint, @@ -352,7 +352,7 @@ impl SerializedNodeHeader { assert_eq!(fingerprint, res.fingerprint()); assert_eq!(node, res.node()); if let Some(len) = res.len() { - assert_eq!(edge_count, len); + assert_eq!(edge_count, len as usize); } } Self { bytes, _marker: PhantomData } @@ -366,7 +366,7 @@ impl SerializedNodeHeader { let kind = head & mask(Self::KIND_BITS) as u16; let bytes_per_index = (head >> Self::KIND_BITS) & mask(Self::WIDTH_BITS) as u16; - let len = (head as usize) >> (Self::WIDTH_BITS + Self::KIND_BITS); + let len = (head as u32) >> (Self::WIDTH_BITS + Self::KIND_BITS); Unpacked { len: len.checked_sub(1), @@ -378,7 +378,7 @@ impl SerializedNodeHeader { } #[inline] - fn len(&self) -> Option { + fn len(&self) -> Option { self.unpack().len } @@ -421,7 +421,8 @@ impl NodeInfo { e.write_array(header.bytes); if header.len().is_none() { - e.emit_usize(edges.len()); + // The edges are all unique and the number of unique indices is less than u32::MAX. + e.emit_u32(edges.len().try_into().unwrap()); } let bytes_per_index = header.bytes_per_index(); @@ -456,7 +457,8 @@ impl NodeInfo { e.write_array(header.bytes); if header.len().is_none() { - e.emit_usize(edge_count); + // The edges are all unique and the number of unique indices is less than u32::MAX. + e.emit_u32(edge_count.try_into().unwrap()); } let bytes_per_index = header.bytes_per_index(); From 59c55339af73b5345ec28d7d830c7bd3feee45b3 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sat, 22 Feb 2025 22:01:18 +0100 Subject: [PATCH 329/606] add `simd_insert_dyn` and `simd_extract_dyn` --- compiler/rustc_codegen_llvm/src/intrinsic.rs | 69 +++++++++-------- .../rustc_hir_analysis/src/check/intrinsic.rs | 8 +- compiler/rustc_span/src/symbol.rs | 2 + library/core/src/intrinsics/simd.rs | 39 +++++++++- tests/codegen/simd/extract-insert-dyn.rs | 75 +++++++++++++++++++ .../simd/intrinsic/generic-elements-pass.rs | 41 +++++++++- 6 files changed, 197 insertions(+), 37 deletions(-) create mode 100644 tests/codegen/simd/extract-insert-dyn.rs diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 660fc7ec4c40..a14600f925fb 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -1417,7 +1417,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>( return Ok(bx.shuffle_vector(args[0].immediate(), args[1].immediate(), indices)); } - if name == sym::simd_insert { + if name == sym::simd_insert || name == sym::simd_insert_dyn { require!( in_elem == arg_tys[2], InvalidMonomorphization::InsertedType { @@ -1428,40 +1428,49 @@ fn generic_simd_intrinsic<'ll, 'tcx>( out_ty: arg_tys[2] } ); - let idx = bx - .const_to_opt_u128(args[1].immediate(), false) - .expect("typeck should have ensure that this is a const"); - if idx >= in_len.into() { - return_error!(InvalidMonomorphization::SimdIndexOutOfBounds { - span, - name, - arg_idx: 1, - total_len: in_len.into(), - }); - } - return Ok(bx.insert_element( - args[0].immediate(), - args[2].immediate(), - bx.const_i32(idx as i32), - )); + + let index_imm = if name == sym::simd_insert { + let idx = bx + .const_to_opt_u128(args[1].immediate(), false) + .expect("typeck should have ensure that this is a const"); + if idx >= in_len.into() { + return_error!(InvalidMonomorphization::SimdIndexOutOfBounds { + span, + name, + arg_idx: 1, + total_len: in_len.into(), + }); + } + bx.const_i32(idx as i32) + } else { + args[1].immediate() + }; + + return Ok(bx.insert_element(args[0].immediate(), args[2].immediate(), index_imm)); } - if name == sym::simd_extract { + if name == sym::simd_extract || name == sym::simd_extract_dyn { require!( ret_ty == in_elem, InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty } ); - let idx = bx - .const_to_opt_u128(args[1].immediate(), false) - .expect("typeck should have ensure that this is a const"); - if idx >= in_len.into() { - return_error!(InvalidMonomorphization::SimdIndexOutOfBounds { - span, - name, - arg_idx: 1, - total_len: in_len.into(), - }); - } - return Ok(bx.extract_element(args[0].immediate(), bx.const_i32(idx as i32))); + let index_imm = if name == sym::simd_extract { + let idx = bx + .const_to_opt_u128(args[1].immediate(), false) + .expect("typeck should have ensure that this is a const"); + if idx >= in_len.into() { + return_error!(InvalidMonomorphization::SimdIndexOutOfBounds { + span, + name, + arg_idx: 1, + total_len: in_len.into(), + }); + } + bx.const_i32(idx as i32) + } else { + args[1].immediate() + }; + + return Ok(bx.extract_element(args[0].immediate(), index_imm)); } if name == sym::simd_select { diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 42d785c8dd0f..21d40b01e9a1 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -674,8 +674,12 @@ pub fn check_intrinsic_type( sym::simd_masked_load => (3, 0, vec![param(0), param(1), param(2)], param(2)), sym::simd_masked_store => (3, 0, vec![param(0), param(1), param(2)], tcx.types.unit), sym::simd_scatter => (3, 0, vec![param(0), param(1), param(2)], tcx.types.unit), - sym::simd_insert => (2, 0, vec![param(0), tcx.types.u32, param(1)], param(0)), - sym::simd_extract => (2, 0, vec![param(0), tcx.types.u32], param(1)), + sym::simd_insert | sym::simd_insert_dyn => { + (2, 0, vec![param(0), tcx.types.u32, param(1)], param(0)) + } + sym::simd_extract | sym::simd_extract_dyn => { + (2, 0, vec![param(0), tcx.types.u32], param(1)) + } sym::simd_cast | sym::simd_as | sym::simd_cast_ptr diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 8a8bec35d819..0b6e3f64ad10 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1885,6 +1885,7 @@ symbols! { simd_eq, simd_expose_provenance, simd_extract, + simd_extract_dyn, simd_fabs, simd_fcos, simd_fexp, @@ -1903,6 +1904,7 @@ symbols! { simd_ge, simd_gt, simd_insert, + simd_insert_dyn, simd_le, simd_lt, simd_masked_load, diff --git a/library/core/src/intrinsics/simd.rs b/library/core/src/intrinsics/simd.rs index ae6e1a779ed5..9ac6ee855355 100644 --- a/library/core/src/intrinsics/simd.rs +++ b/library/core/src/intrinsics/simd.rs @@ -4,7 +4,7 @@ /// Inserts an element into a vector, returning the updated vector. /// -/// `T` must be a vector with element type `U`. +/// `T` must be a vector with element type `U`, and `idx` must be `const`. /// /// # Safety /// @@ -15,14 +15,47 @@ pub const unsafe fn simd_insert(x: T, idx: u32, val: U) -> T; /// Extracts an element from a vector. /// +/// `T` must be a vector with element type `U`, and `idx` must be `const`. +/// +/// # Safety +/// +/// `idx` must be const and in-bounds of the vector. +#[rustc_intrinsic] +#[rustc_nounwind] +pub const unsafe fn simd_extract(x: T, idx: u32) -> U; + +/// Inserts an element into a vector, returning the updated vector. +/// /// `T` must be a vector with element type `U`. /// +/// If the index is `const`, [`simd_insert`] may emit better assembly. +/// /// # Safety /// /// `idx` must be in-bounds of the vector. -#[rustc_intrinsic] #[rustc_nounwind] -pub const unsafe fn simd_extract(x: T, idx: u32) -> U; +#[cfg_attr(not(bootstrap), rustc_intrinsic)] +pub unsafe fn simd_insert_dyn(mut x: T, idx: u32, val: U) -> T { + // SAFETY: `idx` must be in-bounds + unsafe { (&raw mut x).cast::().add(idx as usize).write(val) } + x +} + +/// Extracts an element from a vector. +/// +/// `T` must be a vector with element type `U`. +/// +/// If the index is `const`, [`simd_extract`] may emit better assembly. +/// +/// # Safety +/// +/// `idx` must be in-bounds of the vector. +#[rustc_nounwind] +#[cfg_attr(not(bootstrap), rustc_intrinsic)] +pub unsafe fn simd_extract_dyn(x: T, idx: u32) -> U { + // SAFETY: `idx` must be in-bounds + unsafe { (&raw const x).cast::().add(idx as usize).read() } +} /// Adds two simd vectors elementwise. /// diff --git a/tests/codegen/simd/extract-insert-dyn.rs b/tests/codegen/simd/extract-insert-dyn.rs new file mode 100644 index 000000000000..584e2c7887ad --- /dev/null +++ b/tests/codegen/simd/extract-insert-dyn.rs @@ -0,0 +1,75 @@ +//@compile-flags: -C opt-level=3 -C no-prepopulate-passes + +#![feature(core_intrinsics, repr_simd)] +#![no_std] +#![crate_type = "lib"] +#![allow(non_camel_case_types)] + +// Test that `core::intrinsics::simd::{simd_extract_dyn, simd_insert_dyn}` +// lower to an LLVM extractelement or insertelement operation. + +use core::intrinsics::simd::{simd_extract, simd_extract_dyn, simd_insert, simd_insert_dyn}; + +#[repr(simd)] +#[derive(Clone, Copy)] +pub struct u32x16([u32; 16]); + +#[repr(simd)] +#[derive(Clone, Copy)] +pub struct i8x16([i8; 16]); + +// CHECK-LABEL: dyn_simd_extract +// CHECK: extractelement <16 x i8> %x, i32 %idx +#[no_mangle] +unsafe extern "C" fn dyn_simd_extract(x: i8x16, idx: u32) -> i8 { + simd_extract_dyn(x, idx) +} + +// CHECK-LABEL: literal_dyn_simd_extract +// CHECK: extractelement <16 x i8> %x, i32 7 +#[no_mangle] +unsafe extern "C" fn literal_dyn_simd_extract(x: i8x16) -> i8 { + simd_extract_dyn(x, 7) +} + +// CHECK-LABEL: const_dyn_simd_extract +// CHECK: extractelement <16 x i8> %x, i32 7 +#[no_mangle] +unsafe extern "C" fn const_dyn_simd_extract(x: i8x16) -> i8 { + simd_extract_dyn(x, const { 3 + 4 }) +} + +// CHECK-LABEL: const_simd_extract +// CHECK: extractelement <16 x i8> %x, i32 7 +#[no_mangle] +unsafe extern "C" fn const_simd_extract(x: i8x16) -> i8 { + simd_extract(x, const { 3 + 4 }) +} + +// CHECK-LABEL: dyn_simd_insert +// CHECK: insertelement <16 x i8> %x, i8 %e, i32 %idx +#[no_mangle] +unsafe extern "C" fn dyn_simd_insert(x: i8x16, e: i8, idx: u32) -> i8x16 { + simd_insert_dyn(x, idx, e) +} + +// CHECK-LABEL: literal_dyn_simd_insert +// CHECK: insertelement <16 x i8> %x, i8 %e, i32 7 +#[no_mangle] +unsafe extern "C" fn literal_dyn_simd_insert(x: i8x16, e: i8) -> i8x16 { + simd_insert_dyn(x, 7, e) +} + +// CHECK-LABEL: const_dyn_simd_insert +// CHECK: insertelement <16 x i8> %x, i8 %e, i32 7 +#[no_mangle] +unsafe extern "C" fn const_dyn_simd_insert(x: i8x16, e: i8) -> i8x16 { + simd_insert_dyn(x, const { 3 + 4 }, e) +} + +// CHECK-LABEL: const_simd_insert +// CHECK: insertelement <16 x i8> %x, i8 %e, i32 7 +#[no_mangle] +unsafe extern "C" fn const_simd_insert(x: i8x16, e: i8) -> i8x16 { + simd_insert(x, const { 3 + 4 }, e) +} diff --git a/tests/ui/simd/intrinsic/generic-elements-pass.rs b/tests/ui/simd/intrinsic/generic-elements-pass.rs index 4dc2e4d5a80a..e4d47cdb3818 100644 --- a/tests/ui/simd/intrinsic/generic-elements-pass.rs +++ b/tests/ui/simd/intrinsic/generic-elements-pass.rs @@ -1,8 +1,10 @@ //@ run-pass -#![feature(repr_simd, core_intrinsics)] +#![feature(repr_simd, intrinsics, core_intrinsics)] -use std::intrinsics::simd::{simd_extract, simd_insert, simd_shuffle}; +use std::intrinsics::simd::{ + simd_extract, simd_extract_dyn, simd_insert, simd_insert_dyn, simd_shuffle, +}; #[repr(simd)] #[derive(Copy, Clone, Debug, PartialEq)] @@ -70,6 +72,41 @@ fn main() { all_eq!(simd_extract(x8, 6), 86); all_eq!(simd_extract(x8, 7), 87); } + unsafe { + all_eq!(simd_insert_dyn(x2, 0, 100), i32x2([100, 21])); + all_eq!(simd_insert_dyn(x2, 1, 100), i32x2([20, 100])); + + all_eq!(simd_insert_dyn(x4, 0, 100), i32x4([100, 41, 42, 43])); + all_eq!(simd_insert_dyn(x4, 1, 100), i32x4([40, 100, 42, 43])); + all_eq!(simd_insert_dyn(x4, 2, 100), i32x4([40, 41, 100, 43])); + all_eq!(simd_insert_dyn(x4, 3, 100), i32x4([40, 41, 42, 100])); + + all_eq!(simd_insert_dyn(x8, 0, 100), i32x8([100, 81, 82, 83, 84, 85, 86, 87])); + all_eq!(simd_insert_dyn(x8, 1, 100), i32x8([80, 100, 82, 83, 84, 85, 86, 87])); + all_eq!(simd_insert_dyn(x8, 2, 100), i32x8([80, 81, 100, 83, 84, 85, 86, 87])); + all_eq!(simd_insert_dyn(x8, 3, 100), i32x8([80, 81, 82, 100, 84, 85, 86, 87])); + all_eq!(simd_insert_dyn(x8, 4, 100), i32x8([80, 81, 82, 83, 100, 85, 86, 87])); + all_eq!(simd_insert_dyn(x8, 5, 100), i32x8([80, 81, 82, 83, 84, 100, 86, 87])); + all_eq!(simd_insert_dyn(x8, 6, 100), i32x8([80, 81, 82, 83, 84, 85, 100, 87])); + all_eq!(simd_insert_dyn(x8, 7, 100), i32x8([80, 81, 82, 83, 84, 85, 86, 100])); + + all_eq!(simd_extract_dyn(x2, 0), 20); + all_eq!(simd_extract_dyn(x2, 1), 21); + + all_eq!(simd_extract_dyn(x4, 0), 40); + all_eq!(simd_extract_dyn(x4, 1), 41); + all_eq!(simd_extract_dyn(x4, 2), 42); + all_eq!(simd_extract_dyn(x4, 3), 43); + + all_eq!(simd_extract_dyn(x8, 0), 80); + all_eq!(simd_extract_dyn(x8, 1), 81); + all_eq!(simd_extract_dyn(x8, 2), 82); + all_eq!(simd_extract_dyn(x8, 3), 83); + all_eq!(simd_extract_dyn(x8, 4), 84); + all_eq!(simd_extract_dyn(x8, 5), 85); + all_eq!(simd_extract_dyn(x8, 6), 86); + all_eq!(simd_extract_dyn(x8, 7), 87); + } let y2 = i32x2([120, 121]); let y4 = i32x4([140, 141, 142, 143]); From d7e7f8b522c9c2f5d8a509947904cd31956faa27 Mon Sep 17 00:00:00 2001 From: Augie Fackler Date: Fri, 7 Mar 2025 14:25:21 -0500 Subject: [PATCH 330/606] tests: adjust expectation for f128 abi on Windows llvm/llvm-project@5ee1c0b7148571ed9d60e447b66fb0f35de14576 updates llvm to match the documented calling convention to pass f128 indirectly. @rustbot label llvm-main --- tests/assembly/x86_64-windows-float-abi.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/assembly/x86_64-windows-float-abi.rs b/tests/assembly/x86_64-windows-float-abi.rs index e8900be1aaee..cbc809108511 100644 --- a/tests/assembly/x86_64-windows-float-abi.rs +++ b/tests/assembly/x86_64-windows-float-abi.rs @@ -37,7 +37,8 @@ pub extern "C" fn second_f64(_: f64, x: f64) -> f64 { } // CHECK-LABEL: second_f128 -// CHECK: movaps %xmm1, %xmm0 +// FIXME(llvm21): this can be just %rdx instead of the regex once we don't test on LLVM 20 +// CHECK: movaps {{(%xmm1|\(%rdx\))}}, %xmm0 // CHECK-NEXT: retq #[no_mangle] pub extern "C" fn second_f128(_: f128, x: f128) -> f128 { From 02f10d9bfe41c6c6650f72965d74f27e92dc3986 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Thu, 27 Mar 2025 00:19:52 +0100 Subject: [PATCH 331/606] Remove the use of Rayon iterators --- Cargo.lock | 14 +-- .../rustc_codegen_cranelift/src/driver/aot.rs | 29 ++--- compiler/rustc_codegen_ssa/src/base.rs | 6 +- compiler/rustc_data_structures/Cargo.toml | 2 +- compiler/rustc_data_structures/src/marker.rs | 13 +++ .../src/sync/parallel.rs | 104 +++++++++++++----- compiler/rustc_interface/Cargo.toml | 1 - compiler/rustc_interface/src/util.rs | 8 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 2 +- compiler/rustc_middle/src/hir/map.rs | 2 +- compiler/rustc_middle/src/hir/mod.rs | 10 +- compiler/rustc_monomorphize/src/collector.rs | 2 +- src/tools/miri/src/bin/miri.rs | 2 +- src/tools/tidy/src/deps.rs | 1 - 14 files changed, 122 insertions(+), 74 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bf519e039260..380115098873 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3216,17 +3216,6 @@ dependencies = [ "tikv-jemalloc-sys", ] -[[package]] -name = "rustc-rayon" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cd9fb077db982d7ceb42a90471e5a69a990b58f71e06f0d8340bb2cf35eb751" -dependencies = [ - "either", - "indexmap", - "rustc-rayon-core", -] - [[package]] name = "rustc-rayon-core" version = "0.5.0" @@ -3598,7 +3587,7 @@ dependencies = [ "parking_lot", "portable-atomic", "rustc-hash 2.1.1", - "rustc-rayon", + "rustc-rayon-core", "rustc-stable-hash", "rustc_arena", "rustc_graphviz", @@ -3944,7 +3933,6 @@ dependencies = [ name = "rustc_interface" version = "0.0.0" dependencies = [ - "rustc-rayon", "rustc-rayon-core", "rustc_abi", "rustc_ast", diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs index 444dc4412868..b1bc7e1707eb 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs @@ -728,26 +728,27 @@ pub(crate) fn run_aot( let concurrency_limiter = IntoDynSyncSend(ConcurrencyLimiter::new(todo_cgus.len())); - let modules = tcx.sess.time("codegen mono items", || { - let mut modules: Vec<_> = par_map(todo_cgus, |(_, cgu)| { - let dep_node = cgu.codegen_dep_node(tcx); - tcx.dep_graph - .with_task( + let modules: Vec<_> = + tcx.sess.time("codegen mono items", || { + let modules: Vec<_> = par_map(todo_cgus, |(_, cgu)| { + let dep_node = cgu.codegen_dep_node(tcx); + let (module, _) = tcx.dep_graph.with_task( dep_node, tcx, (global_asm_config.clone(), cgu.name(), concurrency_limiter.acquire(tcx.dcx())), module_codegen, Some(rustc_middle::dep_graph::hash_result), - ) - .0 - }); - modules.extend( - done_cgus + ); + IntoDynSyncSend(module) + }); + modules .into_iter() - .map(|(_, cgu)| OngoingModuleCodegen::Sync(reuse_workproduct_for_cgu(tcx, cgu))), - ); - modules - }); + .map(|module| module.0) + .chain(done_cgus.into_iter().map(|(_, cgu)| { + OngoingModuleCodegen::Sync(reuse_workproduct_for_cgu(tcx, cgu)) + })) + .collect() + }); let allocator_module = emit_allocator_module(tcx); diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 1985b3b71706..bf49bac1736c 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -10,7 +10,7 @@ use rustc_ast::expand::allocator::{ALLOCATOR_METHODS, AllocatorKind, global_fn_n use rustc_attr_parsing::OptimizeAttr; use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry}; -use rustc_data_structures::sync::par_map; +use rustc_data_structures::sync::{IntoDynSyncSend, par_map}; use rustc_data_structures::unord::UnordMap; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::lang_items::LangItem; @@ -757,7 +757,7 @@ pub fn codegen_crate( let pre_compiled_cgus = par_map(cgus, |(i, _)| { let module = backend.compile_codegen_unit(tcx, codegen_units[i].name()); - (i, module) + (i, IntoDynSyncSend(module)) }); total_codegen_time += start_time.elapsed(); @@ -777,7 +777,7 @@ pub fn codegen_crate( match cgu_reuse { CguReuse::No => { let (module, cost) = if let Some(cgu) = pre_compiled_cgus.remove(&i) { - cgu + cgu.0 } else { let start_time = Instant::now(); let module = backend.compile_codegen_unit(tcx, cgu.name()); diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml index fcaf2750507d..f48c73b13b96 100644 --- a/compiler/rustc_data_structures/Cargo.toml +++ b/compiler/rustc_data_structures/Cargo.toml @@ -14,7 +14,7 @@ indexmap = "2.4.0" jobserver_crate = { version = "0.1.28", package = "jobserver" } measureme = "12.0.1" rustc-hash = "2.0.0" -rustc-rayon = { version = "0.5.1", features = ["indexmap"] } +rustc-rayon-core = { version = "0.5.0" } rustc-stable-hash = { version = "0.1.0", features = ["nightly"] } rustc_arena = { path = "../rustc_arena" } rustc_graphviz = { path = "../rustc_graphviz" } diff --git a/compiler/rustc_data_structures/src/marker.rs b/compiler/rustc_data_structures/src/marker.rs index 64c64bfa3c29..744ae9b6fe2a 100644 --- a/compiler/rustc_data_structures/src/marker.rs +++ b/compiler/rustc_data_structures/src/marker.rs @@ -179,6 +179,12 @@ impl FromDyn { FromDyn(val) } + #[inline(always)] + pub fn derive(&self, val: O) -> FromDyn { + // We already did the check for `sync::is_dyn_thread_safe()` when creating `Self` + FromDyn(val) + } + #[inline(always)] pub fn into_inner(self) -> T { self.0 @@ -200,6 +206,13 @@ impl std::ops::Deref for FromDyn { } } +impl std::ops::DerefMut for FromDyn { + #[inline(always)] + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + // A wrapper to convert a struct that is already a `Send` or `Sync` into // an instance of `DynSend` and `DynSync`, since the compiler cannot infer // it automatically in some cases. (e.g. Box) diff --git a/compiler/rustc_data_structures/src/sync/parallel.rs b/compiler/rustc_data_structures/src/sync/parallel.rs index 8ef8a3f35856..ba3c85ef5b15 100644 --- a/compiler/rustc_data_structures/src/sync/parallel.rs +++ b/compiler/rustc_data_structures/src/sync/parallel.rs @@ -7,7 +7,6 @@ use std::any::Any; use std::panic::{AssertUnwindSafe, catch_unwind, resume_unwind}; use parking_lot::Mutex; -use rayon::iter::{FromParallelIterator, IntoParallelIterator, ParallelIterator}; use crate::FatalErrorMarker; use crate::sync::{DynSend, DynSync, FromDyn, IntoDynSyncSend, mode}; @@ -97,11 +96,11 @@ macro_rules! parallel { // This function only works when `mode::is_dyn_thread_safe()`. pub fn scope<'scope, OP, R>(op: OP) -> R where - OP: FnOnce(&rayon::Scope<'scope>) -> R + DynSend, + OP: FnOnce(&rayon_core::Scope<'scope>) -> R + DynSend, R: DynSend, { let op = FromDyn::from(op); - rayon::scope(|s| FromDyn::from(op.into_inner()(s))).into_inner() + rayon_core::scope(|s| FromDyn::from(op.into_inner()(s))).into_inner() } #[inline] @@ -114,7 +113,7 @@ where let oper_a = FromDyn::from(oper_a); let oper_b = FromDyn::from(oper_b); let (a, b) = parallel_guard(|guard| { - rayon::join( + rayon_core::join( move || guard.run(move || FromDyn::from(oper_a.into_inner()())), move || guard.run(move || FromDyn::from(oper_b.into_inner()())), ) @@ -125,56 +124,103 @@ where } } -pub fn par_for_each_in + IntoParallelIterator>( +fn par_slice( + items: &mut [I], + guard: &ParallelGuard, + for_each: impl Fn(&mut I) + DynSync + DynSend, +) { + struct State<'a, F> { + for_each: FromDyn, + guard: &'a ParallelGuard, + group: usize, + } + + fn par_rec( + items: &mut [I], + state: &State<'_, F>, + ) { + if items.len() <= state.group { + for item in items { + state.guard.run(|| (state.for_each)(item)); + } + } else { + let (left, right) = items.split_at_mut(items.len() / 2); + let mut left = state.for_each.derive(left); + let mut right = state.for_each.derive(right); + rayon_core::join(move || par_rec(*left, state), move || par_rec(*right, state)); + } + } + + let state = State { + for_each: FromDyn::from(for_each), + guard, + group: std::cmp::max(items.len() / 128, 1), + }; + par_rec(items, &state) +} + +pub fn par_for_each_in>( t: T, - for_each: impl Fn(I) + DynSync + DynSend, + for_each: impl Fn(&I) + DynSync + DynSend, ) { parallel_guard(|guard| { if mode::is_dyn_thread_safe() { - let for_each = FromDyn::from(for_each); - t.into_par_iter().for_each(|i| { - guard.run(|| for_each(i)); - }); + let mut items: Vec<_> = t.into_iter().collect(); + par_slice(&mut items, guard, |i| for_each(&*i)) } else { t.into_iter().for_each(|i| { - guard.run(|| for_each(i)); + guard.run(|| for_each(&i)); }); } }); } -pub fn try_par_for_each_in< - T: IntoIterator + IntoParallelIterator::Item>, - E: Send, ->( +/// This runs `for_each` in parallel for each iterator item. If one or more of the +/// `for_each` calls returns `Err`, the function will also return `Err`. The error returned +/// will be non-deterministic, but this is expected to be used with `ErrorGuaranteed` which +/// are all equivalent. +pub fn try_par_for_each_in( t: T, - for_each: impl Fn(::Item) -> Result<(), E> + DynSync + DynSend, -) -> Result<(), E> { + for_each: impl Fn(&::Item) -> Result<(), E> + DynSync + DynSend, +) -> Result<(), E> +where + ::Item: DynSend, +{ parallel_guard(|guard| { if mode::is_dyn_thread_safe() { - let for_each = FromDyn::from(for_each); - t.into_par_iter() - .filter_map(|i| guard.run(|| for_each(i))) - .reduce(|| Ok(()), Result::and) + let mut items: Vec<_> = t.into_iter().collect(); + + let error = Mutex::new(None); + + par_slice(&mut items, guard, |i| { + if let Err(err) = for_each(&*i) { + *error.lock() = Some(err); + } + }); + + if let Some(err) = error.into_inner() { Err(err) } else { Ok(()) } } else { - t.into_iter().filter_map(|i| guard.run(|| for_each(i))).fold(Ok(()), Result::and) + t.into_iter().filter_map(|i| guard.run(|| for_each(&i))).fold(Ok(()), Result::and) } }) } -pub fn par_map< - I, - T: IntoIterator + IntoParallelIterator, - R: std::marker::Send, - C: FromIterator + FromParallelIterator, ->( +pub fn par_map, R: DynSend, C: FromIterator>( t: T, map: impl Fn(I) -> R + DynSync + DynSend, ) -> C { parallel_guard(|guard| { if mode::is_dyn_thread_safe() { let map = FromDyn::from(map); - t.into_par_iter().filter_map(|i| guard.run(|| map(i))).collect() + + let mut items: Vec<(Option, Option)> = + t.into_iter().map(|i| (Some(i), None)).collect(); + + par_slice(&mut items, guard, |i| { + i.1 = Some(map(i.0.take().unwrap())); + }); + + items.into_iter().filter_map(|i| i.1).collect() } else { t.into_iter().filter_map(|i| guard.run(|| map(i))).collect() } diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml index e36739356648..ff28dbeaee69 100644 --- a/compiler/rustc_interface/Cargo.toml +++ b/compiler/rustc_interface/Cargo.toml @@ -5,7 +5,6 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -rustc-rayon = { version = "0.5.0" } rustc-rayon-core = { version = "0.5.0" } rustc_ast = { path = "../rustc_ast" } rustc_ast_lowering = { path = "../rustc_ast_lowering" } diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 83d80938b4e3..15eec6054acb 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -179,7 +179,7 @@ pub(crate) fn run_in_thread_pool_with_globals R + Send, let current_gcx = FromDyn::from(CurrentGcx::new()); let current_gcx2 = current_gcx.clone(); - let builder = rayon::ThreadPoolBuilder::new() + let builder = rayon_core::ThreadPoolBuilder::new() .thread_name(|_| "rustc".to_string()) .acquire_thread_handler(jobserver::acquire_thread) .release_thread_handler(jobserver::release_thread) @@ -236,7 +236,7 @@ pub(crate) fn run_in_thread_pool_with_globals R + Send, builder .build_scoped( // Initialize each new worker thread when created. - move |thread: rayon::ThreadBuilder| { + move |thread: rayon_core::ThreadBuilder| { // Register the thread for use with the `WorkerLocal` type. registry.register(); @@ -245,7 +245,9 @@ pub(crate) fn run_in_thread_pool_with_globals R + Send, }) }, // Run `f` on the first thread in the thread pool. - move |pool: &rayon::ThreadPool| pool.install(|| f(current_gcx.into_inner())), + move |pool: &rayon_core::ThreadPool| { + pool.install(|| f(current_gcx.into_inner())) + }, ) .unwrap() }) diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 55bb984c5b69..8a4ab9538eee 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -2199,7 +2199,7 @@ fn prefetch_mir(tcx: TyCtxt<'_>) { } let reachable_set = tcx.reachable_set(()); - par_for_each_in(tcx.mir_keys(()), |&def_id| { + par_for_each_in(tcx.mir_keys(()), |&&def_id| { let (encode_const, encode_opt) = should_encode_mir(tcx, reachable_set, def_id); if encode_const { diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs index 21ab06c98a77..e1fa343e7eba 100644 --- a/compiler/rustc_middle/src/hir/map.rs +++ b/compiler/rustc_middle/src/hir/map.rs @@ -343,7 +343,7 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn par_hir_body_owners(self, f: impl Fn(LocalDefId) + DynSend + DynSync) { - par_for_each_in(&self.hir_crate_items(()).body_owners[..], |&def_id| f(def_id)); + par_for_each_in(&self.hir_crate_items(()).body_owners[..], |&&def_id| f(def_id)); } pub fn hir_ty_param_owner(self, def_id: LocalDefId) -> LocalDefId { diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index 74369b6636c0..cfa445a2fe2d 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -83,35 +83,35 @@ impl ModuleItems { &self, f: impl Fn(ItemId) -> Result<(), ErrorGuaranteed> + DynSend + DynSync, ) -> Result<(), ErrorGuaranteed> { - try_par_for_each_in(&self.free_items[..], |&id| f(id)) + try_par_for_each_in(&self.free_items[..], |&&id| f(id)) } pub fn par_trait_items( &self, f: impl Fn(TraitItemId) -> Result<(), ErrorGuaranteed> + DynSend + DynSync, ) -> Result<(), ErrorGuaranteed> { - try_par_for_each_in(&self.trait_items[..], |&id| f(id)) + try_par_for_each_in(&self.trait_items[..], |&&id| f(id)) } pub fn par_impl_items( &self, f: impl Fn(ImplItemId) -> Result<(), ErrorGuaranteed> + DynSend + DynSync, ) -> Result<(), ErrorGuaranteed> { - try_par_for_each_in(&self.impl_items[..], |&id| f(id)) + try_par_for_each_in(&self.impl_items[..], |&&id| f(id)) } pub fn par_foreign_items( &self, f: impl Fn(ForeignItemId) -> Result<(), ErrorGuaranteed> + DynSend + DynSync, ) -> Result<(), ErrorGuaranteed> { - try_par_for_each_in(&self.foreign_items[..], |&id| f(id)) + try_par_for_each_in(&self.foreign_items[..], |&&id| f(id)) } pub fn par_opaques( &self, f: impl Fn(LocalDefId) -> Result<(), ErrorGuaranteed> + DynSend + DynSync, ) -> Result<(), ErrorGuaranteed> { - try_par_for_each_in(&self.opaques[..], |&id| f(id)) + try_par_for_each_in(&self.opaques[..], |&&id| f(id)) } } diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 6e676ac6b8d5..1dbb35f92c2c 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1689,7 +1689,7 @@ pub(crate) fn collect_crate_mono_items<'tcx>( let mut recursion_depths = DefIdMap::default(); collect_items_rec( tcx, - dummy_spanned(root), + dummy_spanned(*root), &state, &mut recursion_depths, recursion_limit, diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index 56ee96502b3e..4e8fe0ca8adf 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -185,7 +185,7 @@ impl rustc_driver::Callbacks for MiriCompilerCalls { let num_failed = sync::IntoDynSyncSend(AtomicU32::new(0)); sync::par_for_each_in(many_seeds.seeds.clone(), |seed| { let mut config = config.clone(); - config.seed = Some(seed.into()); + config.seed = Some((*seed).into()); eprintln!("Trying seed: {seed}"); let return_code = miri::eval_entry(tcx, entry_def_id, entry_type, config) .unwrap_or(rustc_driver::EXIT_FAILURE); diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 1a57d2b182ac..bf3b4112324a 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -361,7 +361,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "rustc-demangle", "rustc-hash", "rustc-literal-escaper", - "rustc-rayon", "rustc-rayon-core", "rustc-stable-hash", "rustc_apfloat", From 0ca31277f3198a5b4371adafbd9148e3136074d4 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 10 Apr 2025 10:34:55 +0300 Subject: [PATCH 332/606] compiletest: Make `SUGGESTION` annotations viral --- src/tools/compiletest/src/header.rs | 2 +- src/tools/compiletest/src/runtest.rs | 11 ++++++++-- tests/ui/async-await/suggest-missing-await.rs | 1 + .../async-await/suggest-missing-await.stderr | 22 +++++++++---------- tests/ui/cast/cast-as-bool.rs | 2 ++ tests/ui/cast/cast-as-bool.stderr | 22 +++++++++---------- tests/ui/fn/suggest-return-closure.rs | 1 + tests/ui/fn/suggest-return-closure.stderr | 6 ++--- tests/ui/parser/inverted-parameters.rs | 2 ++ tests/ui/parser/inverted-parameters.stderr | 12 +++++----- tests/ui/suggestions/suggest-ref-mut.rs | 2 ++ tests/ui/suggestions/suggest-ref-mut.stderr | 8 +++---- .../issue-90027-async-fn-return-suggestion.rs | 1 + ...ue-90027-async-fn-return-suggestion.stderr | 8 +++---- 14 files changed, 58 insertions(+), 42 deletions(-) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 01a6ae00825d..b64f01169a00 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -306,7 +306,7 @@ impl TestProps { (ErrorKind::Note, true), (ErrorKind::Error, true), (ErrorKind::Warning, true), - (ErrorKind::Suggestion, false), + (ErrorKind::Suggestion, true), ]), } } diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 9c03fa141bd3..3fbc95f5862b 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -711,6 +711,7 @@ impl<'test> TestCx<'test> { let expect_help = expected_errors.iter().any(|ee| ee.kind == Some(ErrorKind::Help)); let expect_note = expected_errors.iter().any(|ee| ee.kind == Some(ErrorKind::Note)); + let expect_sugg = expected_errors.iter().any(|ee| ee.kind == Some(ErrorKind::Suggestion)); // Parse the JSON output from the compiler and extract out the messages. let actual_errors = json::parse_output(&diagnostic_file_name, &proc_res.stderr, proc_res); @@ -737,8 +738,12 @@ impl<'test> TestCx<'test> { None => { // If the test is a known bug, don't require that the error is annotated - if self.is_unexpected_compiler_message(&actual_error, expect_help, expect_note) - { + if self.is_unexpected_compiler_message( + &actual_error, + expect_help, + expect_note, + expect_sugg, + ) { self.error(&format!( "{}:{}: unexpected {}: '{}'", file_name, @@ -802,6 +807,7 @@ impl<'test> TestCx<'test> { actual_error: &Error, expect_help: bool, expect_note: bool, + expect_sugg: bool, ) -> bool { actual_error.require_annotation && actual_error.kind.map_or(false, |err_kind| { @@ -811,6 +817,7 @@ impl<'test> TestCx<'test> { match err_kind { ErrorKind::Help => expect_help && default_require_annotations, ErrorKind::Note => expect_note && default_require_annotations, + ErrorKind::Suggestion => expect_sugg && default_require_annotations, _ => default_require_annotations, } }) diff --git a/tests/ui/async-await/suggest-missing-await.rs b/tests/ui/async-await/suggest-missing-await.rs index 989792825cf8..8a9c7cfe9800 100644 --- a/tests/ui/async-await/suggest-missing-await.rs +++ b/tests/ui/async-await/suggest-missing-await.rs @@ -1,4 +1,5 @@ //@ edition:2018 +//@ dont-require-annotations:SUGGESTION fn take_u32(_x: u32) {} diff --git a/tests/ui/async-await/suggest-missing-await.stderr b/tests/ui/async-await/suggest-missing-await.stderr index f9db86ea40a9..9db7eb980eff 100644 --- a/tests/ui/async-await/suggest-missing-await.stderr +++ b/tests/ui/async-await/suggest-missing-await.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/suggest-missing-await.rs:12:14 + --> $DIR/suggest-missing-await.rs:13:14 | LL | take_u32(x) | -------- ^ expected `u32`, found future @@ -7,12 +7,12 @@ LL | take_u32(x) | arguments to this function are incorrect | note: calling an async function returns a future - --> $DIR/suggest-missing-await.rs:12:14 + --> $DIR/suggest-missing-await.rs:13:14 | LL | take_u32(x) | ^ note: function defined here - --> $DIR/suggest-missing-await.rs:3:4 + --> $DIR/suggest-missing-await.rs:4:4 | LL | fn take_u32(_x: u32) {} | ^^^^^^^^ ------- @@ -22,13 +22,13 @@ LL | take_u32(x.await) | ++++++ error[E0308]: mismatched types - --> $DIR/suggest-missing-await.rs:22:5 + --> $DIR/suggest-missing-await.rs:23:5 | LL | dummy() | ^^^^^^^ expected `()`, found future | note: calling an async function returns a future - --> $DIR/suggest-missing-await.rs:22:5 + --> $DIR/suggest-missing-await.rs:23:5 | LL | dummy() | ^^^^^^^ @@ -42,7 +42,7 @@ LL | dummy(); | + error[E0308]: `if` and `else` have incompatible types - --> $DIR/suggest-missing-await.rs:35:9 + --> $DIR/suggest-missing-await.rs:36:9 | LL | let _x = if true { | ______________- @@ -64,7 +64,7 @@ LL | dummy().await | ++++++ error[E0308]: `match` arms have incompatible types - --> $DIR/suggest-missing-await.rs:45:14 + --> $DIR/suggest-missing-await.rs:46:14 | LL | let _x = match 0usize { | ______________- @@ -87,7 +87,7 @@ LL ~ 1 => dummy().await, | error[E0308]: mismatched types - --> $DIR/suggest-missing-await.rs:53:9 + --> $DIR/suggest-missing-await.rs:54:9 | LL | let _x = match dummy() { | ------- this expression has type `impl Future` @@ -102,7 +102,7 @@ LL | let _x = match dummy().await { | ++++++ error[E0308]: mismatched types - --> $DIR/suggest-missing-await.rs:67:9 + --> $DIR/suggest-missing-await.rs:68:9 | LL | match dummy_result() { | -------------- this expression has type `impl Future>` @@ -118,7 +118,7 @@ LL | match dummy_result().await { | ++++++ error[E0308]: mismatched types - --> $DIR/suggest-missing-await.rs:69:9 + --> $DIR/suggest-missing-await.rs:70:9 | LL | match dummy_result() { | -------------- this expression has type `impl Future>` @@ -134,7 +134,7 @@ LL | match dummy_result().await { | ++++++ error[E0308]: mismatched types - --> $DIR/suggest-missing-await.rs:77:27 + --> $DIR/suggest-missing-await.rs:78:27 | LL | Some(do_async()).map(|()| {}); | ^^ diff --git a/tests/ui/cast/cast-as-bool.rs b/tests/ui/cast/cast-as-bool.rs index 511a02718fe2..8f3555094e0a 100644 --- a/tests/ui/cast/cast-as-bool.rs +++ b/tests/ui/cast/cast-as-bool.rs @@ -1,3 +1,5 @@ +//@ dont-require-annotations:SUGGESTION + fn main() { let u = 5 as bool; //~ ERROR cannot cast `i32` as `bool` //~| HELP compare with zero instead diff --git a/tests/ui/cast/cast-as-bool.stderr b/tests/ui/cast/cast-as-bool.stderr index b2c9ae5c6ad6..25377ebebe2b 100644 --- a/tests/ui/cast/cast-as-bool.stderr +++ b/tests/ui/cast/cast-as-bool.stderr @@ -1,5 +1,5 @@ error[E0054]: cannot cast `i32` as `bool` - --> $DIR/cast-as-bool.rs:2:13 + --> $DIR/cast-as-bool.rs:4:13 | LL | let u = 5 as bool; | ^^^^^^^^^ @@ -11,7 +11,7 @@ LL + let u = 5 != 0; | error[E0054]: cannot cast `i32` as `bool` - --> $DIR/cast-as-bool.rs:6:13 + --> $DIR/cast-as-bool.rs:8:13 | LL | let t = (1 + 2) as bool; | ^^^^^^^^^^^^^^^ @@ -23,7 +23,7 @@ LL + let t = (1 + 2) != 0; | error[E0054]: cannot cast `u32` as `bool` - --> $DIR/cast-as-bool.rs:10:13 + --> $DIR/cast-as-bool.rs:12:13 | LL | let _ = 5_u32 as bool; | ^^^^^^^^^^^^^ @@ -35,7 +35,7 @@ LL + let _ = 5_u32 != 0; | error[E0054]: cannot cast `f64` as `bool` - --> $DIR/cast-as-bool.rs:13:13 + --> $DIR/cast-as-bool.rs:15:13 | LL | let _ = 64.0_f64 as bool; | ^^^^^^^^^^^^^^^^ @@ -47,43 +47,43 @@ LL + let _ = 64.0_f64 != 0; | error[E0054]: cannot cast `IntEnum` as `bool` - --> $DIR/cast-as-bool.rs:24:13 + --> $DIR/cast-as-bool.rs:26:13 | LL | let _ = IntEnum::One as bool; | ^^^^^^^^^^^^^^^^^^^^ unsupported cast error[E0054]: cannot cast `fn(u8) -> String {uwu}` as `bool` - --> $DIR/cast-as-bool.rs:33:13 + --> $DIR/cast-as-bool.rs:35:13 | LL | let _ = uwu as bool; | ^^^^^^^^^^^ unsupported cast error[E0054]: cannot cast `unsafe fn() {owo}` as `bool` - --> $DIR/cast-as-bool.rs:35:13 + --> $DIR/cast-as-bool.rs:37:13 | LL | let _ = owo as bool; | ^^^^^^^^^^^ unsupported cast error[E0054]: cannot cast `fn(u8) -> String` as `bool` - --> $DIR/cast-as-bool.rs:38:13 + --> $DIR/cast-as-bool.rs:40:13 | LL | let _ = uwu as fn(u8) -> String as bool; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsupported cast error[E0054]: cannot cast `char` as `bool` - --> $DIR/cast-as-bool.rs:40:13 + --> $DIR/cast-as-bool.rs:42:13 | LL | let _ = 'x' as bool; | ^^^^^^^^^^^ unsupported cast error[E0054]: cannot cast `*const ()` as `bool` - --> $DIR/cast-as-bool.rs:44:13 + --> $DIR/cast-as-bool.rs:46:13 | LL | let _ = ptr as bool; | ^^^^^^^^^^^ unsupported cast error[E0606]: casting `&'static str` as `bool` is invalid - --> $DIR/cast-as-bool.rs:46:13 + --> $DIR/cast-as-bool.rs:48:13 | LL | let v = "hello" as bool; | ^^^^^^^^^^^^^^^ diff --git a/tests/ui/fn/suggest-return-closure.rs b/tests/ui/fn/suggest-return-closure.rs index 30e25ca8edcc..67be8de92431 100644 --- a/tests/ui/fn/suggest-return-closure.rs +++ b/tests/ui/fn/suggest-return-closure.rs @@ -19,6 +19,7 @@ fn fn_mut() -> _ { let x = String::new(); //~^ HELP: consider changing this to be mutable //~| NOTE binding `x` declared here + //~| SUGGESTION mut |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 45c12b548e67..1860d1ca5d92 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:32:13 + --> $DIR/suggest-return-closure.rs:33: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:23:9 + --> $DIR/suggest-return-closure.rs:24:9 | LL | x.push(c); | ^ cannot borrow as mutable @@ -43,7 +43,7 @@ LL | let mut x = String::new(); | +++ error[E0597]: `x` does not live long enough - --> $DIR/suggest-return-closure.rs:23:9 + --> $DIR/suggest-return-closure.rs:24:9 | LL | let x = String::new(); | - binding `x` declared here diff --git a/tests/ui/parser/inverted-parameters.rs b/tests/ui/parser/inverted-parameters.rs index 5c4272504e06..3bfa8e82d6cb 100644 --- a/tests/ui/parser/inverted-parameters.rs +++ b/tests/ui/parser/inverted-parameters.rs @@ -1,3 +1,5 @@ +//@ dont-require-annotations:SUGGESTION + struct S; impl S { diff --git a/tests/ui/parser/inverted-parameters.stderr b/tests/ui/parser/inverted-parameters.stderr index 866227782039..7b969032d0f9 100644 --- a/tests/ui/parser/inverted-parameters.stderr +++ b/tests/ui/parser/inverted-parameters.stderr @@ -1,5 +1,5 @@ error: expected one of `:`, `@`, or `|`, found `bar` - --> $DIR/inverted-parameters.rs:4:24 + --> $DIR/inverted-parameters.rs:6:24 | LL | fn foo(&self, &str bar) {} | -----^^^ @@ -8,7 +8,7 @@ LL | fn foo(&self, &str bar) {} | help: declare the type after the parameter binding: `: ` error: expected one of `:`, `@`, or `|`, found `quux` - --> $DIR/inverted-parameters.rs:10:10 + --> $DIR/inverted-parameters.rs:12:10 | LL | fn baz(S quux, xyzzy: i32) {} | --^^^^ @@ -17,19 +17,19 @@ LL | fn baz(S quux, xyzzy: i32) {} | help: declare the type after the parameter binding: `: ` error: expected one of `:`, `@`, or `|`, found `a` - --> $DIR/inverted-parameters.rs:15:12 + --> $DIR/inverted-parameters.rs:17:12 | LL | fn one(i32 a b) {} | ^ expected one of `:`, `@`, or `|` error: expected one of `:` or `|`, found `(` - --> $DIR/inverted-parameters.rs:18:23 + --> $DIR/inverted-parameters.rs:20:23 | LL | fn pattern((i32, i32) (a, b)) {} | ^ expected one of `:` or `|` error: expected one of `:`, `@`, or `|`, found `)` - --> $DIR/inverted-parameters.rs:21:12 + --> $DIR/inverted-parameters.rs:23:12 | LL | fn fizz(i32) {} | ^ expected one of `:`, `@`, or `|` @@ -49,7 +49,7 @@ LL | fn fizz(_: i32) {} | ++ error: expected one of `:`, `@`, or `|`, found `S` - --> $DIR/inverted-parameters.rs:27:23 + --> $DIR/inverted-parameters.rs:29:23 | LL | fn missing_colon(quux S) {} | -----^ diff --git a/tests/ui/suggestions/suggest-ref-mut.rs b/tests/ui/suggestions/suggest-ref-mut.rs index 9f5df9303c33..e9baeb8b0ead 100644 --- a/tests/ui/suggestions/suggest-ref-mut.rs +++ b/tests/ui/suggestions/suggest-ref-mut.rs @@ -1,3 +1,5 @@ +//@ dont-require-annotations:SUGGESTION + struct X(usize); impl X { diff --git a/tests/ui/suggestions/suggest-ref-mut.stderr b/tests/ui/suggestions/suggest-ref-mut.stderr index 935a04c052ac..7c0899f0fbc1 100644 --- a/tests/ui/suggestions/suggest-ref-mut.stderr +++ b/tests/ui/suggestions/suggest-ref-mut.stderr @@ -1,5 +1,5 @@ error[E0594]: cannot assign to `self.0`, which is behind a `&` reference - --> $DIR/suggest-ref-mut.rs:7:9 + --> $DIR/suggest-ref-mut.rs:9:9 | LL | self.0 = 32; | ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be written @@ -10,7 +10,7 @@ LL | fn zap(&mut self) { | +++ error[E0594]: cannot assign to `*foo`, which is behind a `&` reference - --> $DIR/suggest-ref-mut.rs:15:5 + --> $DIR/suggest-ref-mut.rs:17:5 | LL | *foo = 32; | ^^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be written @@ -21,7 +21,7 @@ LL | let ref mut foo = 16; | +++ error[E0594]: cannot assign to `*bar`, which is behind a `&` reference - --> $DIR/suggest-ref-mut.rs:19:9 + --> $DIR/suggest-ref-mut.rs:21:9 | LL | *bar = 32; | ^^^^^^^^^ `bar` is a `&` reference, so the data it refers to cannot be written @@ -32,7 +32,7 @@ LL | if let Some(ref mut bar) = Some(16) { | +++ error[E0594]: cannot assign to `*quo`, which is behind a `&` reference - --> $DIR/suggest-ref-mut.rs:23:22 + --> $DIR/suggest-ref-mut.rs:25:22 | LL | ref quo => { *quo = 32; }, | ^^^^^^^^^ `quo` is a `&` reference, so the data it refers to cannot be written diff --git a/tests/ui/typeck/issue-90027-async-fn-return-suggestion.rs b/tests/ui/typeck/issue-90027-async-fn-return-suggestion.rs index 0be1237749fc..b9dbae6b57dc 100644 --- a/tests/ui/typeck/issue-90027-async-fn-return-suggestion.rs +++ b/tests/ui/typeck/issue-90027-async-fn-return-suggestion.rs @@ -1,4 +1,5 @@ //@ edition:2018 +//@ dont-require-annotations:SUGGESTION async fn hello() { //~ HELP try adding a return type 0 diff --git a/tests/ui/typeck/issue-90027-async-fn-return-suggestion.stderr b/tests/ui/typeck/issue-90027-async-fn-return-suggestion.stderr index c46f4ec1ec30..3680df25f0ba 100644 --- a/tests/ui/typeck/issue-90027-async-fn-return-suggestion.stderr +++ b/tests/ui/typeck/issue-90027-async-fn-return-suggestion.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/issue-90027-async-fn-return-suggestion.rs:4:5 + --> $DIR/issue-90027-async-fn-return-suggestion.rs:5:5 | LL | async fn hello() { | - help: try adding a return type: `-> i32` @@ -7,7 +7,7 @@ LL | 0 | ^ expected `()`, found integer error[E0308]: mismatched types - --> $DIR/issue-90027-async-fn-return-suggestion.rs:9:5 + --> $DIR/issue-90027-async-fn-return-suggestion.rs:10:5 | LL | async fn world() -> () { | -- expected `()` because of return type @@ -15,13 +15,13 @@ LL | 0 | ^ expected `()`, found integer error[E0308]: mismatched types - --> $DIR/issue-90027-async-fn-return-suggestion.rs:14:5 + --> $DIR/issue-90027-async-fn-return-suggestion.rs:15:5 | LL | hello() | ^^^^^^^ expected `()`, found future | note: calling an async function returns a future - --> $DIR/issue-90027-async-fn-return-suggestion.rs:14:5 + --> $DIR/issue-90027-async-fn-return-suggestion.rs:15:5 | LL | hello() | ^^^^^^^ From 909b6c9f83748008828b6c52d2d6281c460141e1 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 10 Apr 2025 10:50:01 +0300 Subject: [PATCH 333/606] compiletest: Turn `TestProps::require_annotations` into a set and further simplify its checking in runtest --- src/tools/compiletest/src/header.rs | 16 +++------ src/tools/compiletest/src/runtest.rs | 49 ++++++++-------------------- 2 files changed, 19 insertions(+), 46 deletions(-) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index b64f01169a00..c53978af3f7d 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -1,4 +1,4 @@ -use std::collections::{HashMap, HashSet}; +use std::collections::HashSet; use std::env; use std::fs::File; use std::io::BufReader; @@ -198,7 +198,7 @@ pub struct TestProps { /// that don't otherwise want/need `-Z build-std`. pub add_core_stubs: bool, /// Whether line annotatins are required for the given error kind. - pub require_annotations: HashMap, + pub dont_require_annotations: HashSet, } mod directives { @@ -301,13 +301,7 @@ impl TestProps { no_auto_check_cfg: false, has_enzyme: false, add_core_stubs: false, - require_annotations: HashMap::from([ - (ErrorKind::Help, true), - (ErrorKind::Note, true), - (ErrorKind::Error, true), - (ErrorKind::Warning, true), - (ErrorKind::Suggestion, true), - ]), + dont_require_annotations: Default::default(), } } @@ -585,8 +579,8 @@ impl TestProps { if let Some(err_kind) = config.parse_name_value_directive(ln, DONT_REQUIRE_ANNOTATIONS) { - self.require_annotations - .insert(ErrorKind::expect_from_user_str(&err_kind), false); + self.dont_require_annotations + .insert(ErrorKind::expect_from_user_str(&err_kind)); } }, ); diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 3fbc95f5862b..999552c99dad 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -22,7 +22,7 @@ use crate::common::{ output_base_dir, output_base_name, output_testname_unique, }; use crate::compute_diff::{DiffLine, make_diff, write_diff, write_filtered_diff}; -use crate::errors::{self, Error, ErrorKind}; +use crate::errors::{Error, ErrorKind}; use crate::header::TestProps; use crate::read2::{Truncated, read2_abbreviated}; use crate::util::{PathBufExt, add_dylib_path, logv, static_regex}; @@ -674,7 +674,7 @@ impl<'test> TestCx<'test> { } } - fn check_expected_errors(&self, expected_errors: Vec, proc_res: &ProcRes) { + fn check_expected_errors(&self, expected_errors: Vec, proc_res: &ProcRes) { debug!( "check_expected_errors: expected_errors={:?} proc_res.status={:?}", expected_errors, proc_res.status @@ -709,9 +709,12 @@ impl<'test> TestCx<'test> { self.testpaths.file.display().to_string() }; - let expect_help = expected_errors.iter().any(|ee| ee.kind == Some(ErrorKind::Help)); - let expect_note = expected_errors.iter().any(|ee| ee.kind == Some(ErrorKind::Note)); - let expect_sugg = expected_errors.iter().any(|ee| ee.kind == Some(ErrorKind::Suggestion)); + // Errors and warnings are always expected, other diagnostics are only expected + // if one of them actually occurs in the test. + let expected_kinds: HashSet<_> = [ErrorKind::Error, ErrorKind::Warning] + .into_iter() + .chain(expected_errors.iter().filter_map(|e| e.kind)) + .collect(); // Parse the JSON output from the compiler and extract out the messages. let actual_errors = json::parse_output(&diagnostic_file_name, &proc_res.stderr, proc_res); @@ -737,13 +740,12 @@ impl<'test> TestCx<'test> { } None => { - // If the test is a known bug, don't require that the error is annotated - if self.is_unexpected_compiler_message( - &actual_error, - expect_help, - expect_note, - expect_sugg, - ) { + if actual_error.require_annotation + && actual_error.kind.map_or(false, |kind| { + expected_kinds.contains(&kind) + && !self.props.dont_require_annotations.contains(&kind) + }) + { self.error(&format!( "{}:{}: unexpected {}: '{}'", file_name, @@ -800,29 +802,6 @@ impl<'test> TestCx<'test> { } } - /// Returns `true` if we should report an error about `actual_error`, - /// which did not match any of the expected error. - fn is_unexpected_compiler_message( - &self, - actual_error: &Error, - expect_help: bool, - expect_note: bool, - expect_sugg: bool, - ) -> bool { - actual_error.require_annotation - && actual_error.kind.map_or(false, |err_kind| { - // If the test being checked doesn't contain any "help" or "note" annotations, then - // we don't require annotating "help" or "note" (respecively) diagnostics at all. - let default_require_annotations = self.props.require_annotations[&err_kind]; - match err_kind { - ErrorKind::Help => expect_help && default_require_annotations, - ErrorKind::Note => expect_note && default_require_annotations, - ErrorKind::Suggestion => expect_sugg && default_require_annotations, - _ => default_require_annotations, - } - }) - } - fn should_emit_metadata(&self, pm: Option) -> Emit { match (pm, self.props.fail_mode, self.config.mode) { (Some(PassMode::Check), ..) | (_, Some(FailMode::Check), Ui) => Emit::Metadata, From ad72ba2e2c60322d07c90364e0ff161f422b2e40 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 10 Apr 2025 19:33:04 +0300 Subject: [PATCH 334/606] dev-guide: Document `dont-require-annotations` and its use cases in more detail --- .../rustc-dev-guide/src/tests/directives.md | 1 + src/doc/rustc-dev-guide/src/tests/ui.md | 55 +++++++++++++------ 2 files changed, 39 insertions(+), 17 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/directives.md b/src/doc/rustc-dev-guide/src/tests/directives.md index 8e4a710178ed..2ebd98f68686 100644 --- a/src/doc/rustc-dev-guide/src/tests/directives.md +++ b/src/doc/rustc-dev-guide/src/tests/directives.md @@ -101,6 +101,7 @@ for more details. | `normalize-stdout` | Normalize actual stdout with a rule `"" -> ""` before comparing against snapshot | `ui`, `incremental` | `"" -> ""`, ``/`` is regex capture and replace syntax | | `dont-check-compiler-stderr` | Don't check actual compiler stderr vs stderr snapshot | `ui` | N/A | | `dont-check-compiler-stdout` | Don't check actual compiler stdout vs stdout snapshot | `ui` | N/A | +| `dont-require-annotations` | Don't require line annotations for the given diagnostic kind (`//~ KIND`) to be exhaustive | `ui`, `incremental` | `ERROR`, `WARN`, `NOTE`, `HELP`, `SUGGESTION` | | `run-rustfix` | Apply all suggestions via `rustfix`, snapshot fixed output, and check fixed output builds | `ui` | N/A | | `rustfix-only-machine-applicable` | `run-rustfix` but only machine-applicable suggestions | `ui` | N/A | | `exec-env` | Env var to set when executing a test | `ui`, `crashes` | `=` | diff --git a/src/doc/rustc-dev-guide/src/tests/ui.md b/src/doc/rustc-dev-guide/src/tests/ui.md index e862a07cae0a..3243a3535ac8 100644 --- a/src/doc/rustc-dev-guide/src/tests/ui.md +++ b/src/doc/rustc-dev-guide/src/tests/ui.md @@ -303,8 +303,7 @@ It should be preferred to using `error-pattern`, which is imprecise and non-exha ### `error-pattern` The `error-pattern` [directive](directives.md) can be used for runtime messages, which don't -have a specific span, or for compile time messages if imprecise matching is required due to -multi-line platform specific diagnostics. +have a specific span, or in exceptional cases for compile time messages. Let's think about this test: @@ -318,7 +317,7 @@ fn main() { ``` We want to ensure this shows "index out of bounds" but we cannot use the `ERROR` -annotation since the error doesn't have any span. Then it's time to use the +annotation since the runtime error doesn't have any span. Then it's time to use the `error-pattern` directive: ```rust,ignore @@ -331,29 +330,51 @@ fn main() { } ``` -But for strict testing, try to use the `ERROR` annotation as much as possible, -including `//~?` annotations for diagnostics without span. -For compile time diagnostics `error-pattern` should very rarely be necessary. +Use of `error-pattern` is not recommended in general. -Per-line annotations (`//~`) are still checked in tests using `error-pattern`. -To opt out of these checks, use `//@ compile-flags: --error-format=human`. -Do that only in exceptional cases. +For strict testing of compile time output, try to use the line annotations `//~` as much as +possible, including `//~?` annotations for diagnostics without span. -### Error levels +If the compile time output is target dependent or too verbose, use directive +`//@ dont-require-annotations: ` to make the line annotation checking +non-exhaustive, some of the compiler messages can stay uncovered by annotations in this mode. -The error levels that you can have are: +For checking runtime output `//@ check-run-results` may be preferable. + +Only use `error-pattern` if none of the above works. + +Line annotations `//~` are still checked in tests using `error-pattern`. +In exceptional cases use `//@ compile-flags: --error-format=human` to opt out of these checks. + +### Diagnostic kinds (error levels) + +The diagnostic kinds that you can have are: - `ERROR` -- `WARN` or `WARNING` +- `WARN` (or `WARNING`) - `NOTE` -- `HELP` and `SUGGESTION` +- `HELP` +- `SUGGESTION` -You are allowed to not include a level, but you should include it at least for -the primary message. - -The `SUGGESTION` level is used for specifying what the expected replacement text +The `SUGGESTION` kind is used for specifying what the expected replacement text should be for a diagnostic suggestion. +`ERROR` and `WARN` kinds are required to be exhaustively covered by line annotations +`//~` by default. + +Other kinds only need to be line-annotated if at least one annotation of that kind appears +in the test file. For example, one `//~ NOTE` will also require all other `//~ NOTE`s in the file +to be written out explicitly. + +Use directive `//@ dont-require-annotations` to opt out of exhaustive annotations. +E.g. use `//@ dont-require-annotations: NOTE` to annotate notes selectively. +Avoid using this directive for `ERROR`s and `WARN`ings, unless there's a serious reason, like +target-dependent compiler output. + +Missing diagnostic kinds (`//~ message`) are currently accepted, but are being phased away. +They will match any compiler output kind, but will not force exhaustive annotations for that kind. +Prefer explicit kind and `//@ dont-require-annotations` to achieve the same effect. + UI tests use the `-A unused` flag by default to ignore all unused warnings, as unused warnings are usually not the focus of a test. However, simple code samples often have unused warnings. If the test is specifically testing an From 06dd9e2d20db8ba9b260fa750f09ea969fb57b87 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 10 Apr 2025 23:39:05 +0300 Subject: [PATCH 335/606] compiletest: Trim the value of `dont-require-annotations` --- src/tools/compiletest/src/header.rs | 2 +- tests/ui/async-await/suggest-missing-await.rs | 2 +- tests/ui/cast/cast-as-bool.rs | 2 +- tests/ui/cfg/cfg_false_no_std-2.rs | 2 +- tests/ui/panic-runtime/two-panic-runtimes.rs | 2 +- tests/ui/panic-runtime/want-abort-got-unwind.rs | 2 +- tests/ui/panic-runtime/want-abort-got-unwind2.rs | 2 +- tests/ui/parser/inverted-parameters.rs | 2 +- tests/ui/suggestions/suggest-ref-mut.rs | 2 +- tests/ui/typeck/issue-90027-async-fn-return-suggestion.rs | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index c53978af3f7d..1fd9022ed97e 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -580,7 +580,7 @@ impl TestProps { config.parse_name_value_directive(ln, DONT_REQUIRE_ANNOTATIONS) { self.dont_require_annotations - .insert(ErrorKind::expect_from_user_str(&err_kind)); + .insert(ErrorKind::expect_from_user_str(err_kind.trim())); } }, ); diff --git a/tests/ui/async-await/suggest-missing-await.rs b/tests/ui/async-await/suggest-missing-await.rs index 8a9c7cfe9800..de0b2ce52b69 100644 --- a/tests/ui/async-await/suggest-missing-await.rs +++ b/tests/ui/async-await/suggest-missing-await.rs @@ -1,5 +1,5 @@ //@ edition:2018 -//@ dont-require-annotations:SUGGESTION +//@ dont-require-annotations: SUGGESTION fn take_u32(_x: u32) {} diff --git a/tests/ui/cast/cast-as-bool.rs b/tests/ui/cast/cast-as-bool.rs index 8f3555094e0a..fa9664e572c0 100644 --- a/tests/ui/cast/cast-as-bool.rs +++ b/tests/ui/cast/cast-as-bool.rs @@ -1,4 +1,4 @@ -//@ dont-require-annotations:SUGGESTION +//@ dont-require-annotations: SUGGESTION fn main() { let u = 5 as bool; //~ ERROR cannot cast `i32` as `bool` diff --git a/tests/ui/cfg/cfg_false_no_std-2.rs b/tests/ui/cfg/cfg_false_no_std-2.rs index 349c49412ffa..18b2c699fd7a 100644 --- a/tests/ui/cfg/cfg_false_no_std-2.rs +++ b/tests/ui/cfg/cfg_false_no_std-2.rs @@ -1,6 +1,6 @@ // Error, the linked empty library is `no_std` and doesn't provide a panic handler. -//@ dont-require-annotations:ERROR +//@ dont-require-annotations: ERROR //@ dont-check-compiler-stderr //@ aux-build: cfg_false_lib_no_std_before.rs diff --git a/tests/ui/panic-runtime/two-panic-runtimes.rs b/tests/ui/panic-runtime/two-panic-runtimes.rs index 7add07ef6004..80591edd1077 100644 --- a/tests/ui/panic-runtime/two-panic-runtimes.rs +++ b/tests/ui/panic-runtime/two-panic-runtimes.rs @@ -1,6 +1,6 @@ // ignore-tidy-linelength //@ build-fail -//@ dont-require-annotations:ERROR +//@ dont-require-annotations: ERROR //@ dont-check-compiler-stderr //@ aux-build:panic-runtime-unwind.rs //@ aux-build:panic-runtime-unwind2.rs diff --git a/tests/ui/panic-runtime/want-abort-got-unwind.rs b/tests/ui/panic-runtime/want-abort-got-unwind.rs index 1ae2e623f103..42cdf8bc6626 100644 --- a/tests/ui/panic-runtime/want-abort-got-unwind.rs +++ b/tests/ui/panic-runtime/want-abort-got-unwind.rs @@ -1,6 +1,6 @@ // ignore-tidy-linelength //@ build-fail -//@ dont-require-annotations:ERROR +//@ dont-require-annotations: ERROR //@ dont-check-compiler-stderr //@ aux-build:panic-runtime-unwind.rs //@ compile-flags:-C panic=abort diff --git a/tests/ui/panic-runtime/want-abort-got-unwind2.rs b/tests/ui/panic-runtime/want-abort-got-unwind2.rs index dc4d3ea86d86..ddf12cd2a9a5 100644 --- a/tests/ui/panic-runtime/want-abort-got-unwind2.rs +++ b/tests/ui/panic-runtime/want-abort-got-unwind2.rs @@ -1,6 +1,6 @@ // ignore-tidy-linelength //@ build-fail -//@ dont-require-annotations:ERROR +//@ dont-require-annotations: ERROR //@ dont-check-compiler-stderr //@ aux-build:panic-runtime-unwind.rs //@ aux-build:wants-panic-runtime-unwind.rs diff --git a/tests/ui/parser/inverted-parameters.rs b/tests/ui/parser/inverted-parameters.rs index 3bfa8e82d6cb..bc2f53f0be1b 100644 --- a/tests/ui/parser/inverted-parameters.rs +++ b/tests/ui/parser/inverted-parameters.rs @@ -1,4 +1,4 @@ -//@ dont-require-annotations:SUGGESTION +//@ dont-require-annotations: SUGGESTION struct S; diff --git a/tests/ui/suggestions/suggest-ref-mut.rs b/tests/ui/suggestions/suggest-ref-mut.rs index e9baeb8b0ead..2a933f6305f6 100644 --- a/tests/ui/suggestions/suggest-ref-mut.rs +++ b/tests/ui/suggestions/suggest-ref-mut.rs @@ -1,4 +1,4 @@ -//@ dont-require-annotations:SUGGESTION +//@ dont-require-annotations: SUGGESTION struct X(usize); diff --git a/tests/ui/typeck/issue-90027-async-fn-return-suggestion.rs b/tests/ui/typeck/issue-90027-async-fn-return-suggestion.rs index b9dbae6b57dc..dd833957a70a 100644 --- a/tests/ui/typeck/issue-90027-async-fn-return-suggestion.rs +++ b/tests/ui/typeck/issue-90027-async-fn-return-suggestion.rs @@ -1,5 +1,5 @@ //@ edition:2018 -//@ dont-require-annotations:SUGGESTION +//@ dont-require-annotations: SUGGESTION async fn hello() { //~ HELP try adding a return type 0 From 3375264fa1c6e7fe95b05c7c369f1f884dee1c91 Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Thu, 10 Apr 2025 20:58:15 +0000 Subject: [PATCH 336/606] Fix `register_group_alias` for tools --- compiler/rustc_lint/src/context.rs | 97 ++++++++++++------------------ compiler/rustc_lint/src/levels.rs | 4 +- compiler/rustc_lint/src/lib.rs | 4 +- 3 files changed, 42 insertions(+), 63 deletions(-) diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 885a7308bdc6..9005bc929203 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -83,11 +83,6 @@ enum TargetLint { Ignored, } -pub enum FindLintError { - NotFound, - Removed, -} - struct LintAlias { name: &'static str, /// Whether deprecation warnings should be suppressed for this alias. @@ -231,13 +226,24 @@ impl LintStore { } } - pub fn register_group_alias(&mut self, lint_name: &'static str, alias: &'static str) { - self.lint_groups.insert( + fn insert_group(&mut self, name: &'static str, group: LintGroup) { + let previous = self.lint_groups.insert(name, group); + if previous.is_some() { + bug!("group {name:?} already exists"); + } + } + + pub fn register_group_alias(&mut self, group_name: &'static str, alias: &'static str) { + let Some(LintGroup { lint_ids, .. }) = self.lint_groups.get(group_name) else { + bug!("group alias {alias:?} points to unregistered group {group_name:?}") + }; + + self.insert_group( alias, LintGroup { - lint_ids: vec![], + lint_ids: lint_ids.clone(), is_externally_loaded: false, - depr: Some(LintAlias { name: lint_name, silent: true }), + depr: Some(LintAlias { name: group_name, silent: true }), }, ); } @@ -249,24 +255,17 @@ impl LintStore { deprecated_name: Option<&'static str>, to: Vec, ) { - let new = self - .lint_groups - .insert(name, LintGroup { lint_ids: to, is_externally_loaded, depr: None }) - .is_none(); if let Some(deprecated) = deprecated_name { - self.lint_groups.insert( + self.insert_group( deprecated, LintGroup { - lint_ids: vec![], + lint_ids: to.clone(), is_externally_loaded, depr: Some(LintAlias { name, silent: false }), }, ); } - - if !new { - bug!("duplicate specification of lint group {}", name); - } + self.insert_group(name, LintGroup { lint_ids: to, is_externally_loaded, depr: None }); } /// This lint should give no warning and have no effect. @@ -292,23 +291,15 @@ impl LintStore { self.by_name.insert(name.into(), Removed(reason.into())); } - pub fn find_lints(&self, mut lint_name: &str) -> Result, FindLintError> { + pub fn find_lints(&self, lint_name: &str) -> Option<&[LintId]> { match self.by_name.get(lint_name) { - Some(&Id(lint_id)) => Ok(vec![lint_id]), - Some(&Renamed(_, lint_id)) => Ok(vec![lint_id]), - Some(&Removed(_)) => Err(FindLintError::Removed), - Some(&Ignored) => Ok(vec![]), - None => loop { - return match self.lint_groups.get(lint_name) { - Some(LintGroup { lint_ids, depr, .. }) => { - if let Some(LintAlias { name, .. }) = depr { - lint_name = name; - continue; - } - Ok(lint_ids.clone()) - } - None => Err(FindLintError::Removed), - }; + Some(Id(lint_id)) => Some(slice::from_ref(lint_id)), + Some(Renamed(_, lint_id)) => Some(slice::from_ref(lint_id)), + Some(Removed(_)) => None, + Some(Ignored) => Some(&[]), + None => match self.lint_groups.get(lint_name) { + Some(LintGroup { lint_ids, .. }) => Some(lint_ids), + None => None, }, } } @@ -374,8 +365,12 @@ impl LintStore { CheckLintNameResult::MissingTool }; } - Some(LintGroup { lint_ids, .. }) => { - return CheckLintNameResult::Tool(lint_ids, None); + Some(LintGroup { lint_ids, depr, .. }) => { + return if let &Some(LintAlias { name, silent: false }) = depr { + CheckLintNameResult::Tool(lint_ids, Some(name.to_string())) + } else { + CheckLintNameResult::Tool(lint_ids, None) + }; } }, Some(Id(id)) => return CheckLintNameResult::Tool(slice::from_ref(id), None), @@ -393,15 +388,11 @@ impl LintStore { None => self.check_tool_name_for_backwards_compat(&complete_name, "clippy"), Some(LintGroup { lint_ids, depr, .. }) => { // Check if the lint group name is deprecated - if let Some(LintAlias { name, silent }) = depr { - let LintGroup { lint_ids, .. } = self.lint_groups.get(name).unwrap(); - return if *silent { - CheckLintNameResult::Ok(lint_ids) - } else { - CheckLintNameResult::Tool(lint_ids, Some((*name).to_string())) - }; + if let &Some(LintAlias { name, silent: false }) = depr { + CheckLintNameResult::Tool(lint_ids, Some(name.to_string())) + } else { + CheckLintNameResult::Ok(lint_ids) } - CheckLintNameResult::Ok(lint_ids) } }, Some(Id(id)) => CheckLintNameResult::Ok(slice::from_ref(id)), @@ -412,7 +403,7 @@ impl LintStore { fn no_lint_suggestion(&self, lint_name: &str, tool_name: &str) -> CheckLintNameResult<'_> { let name_lower = lint_name.to_lowercase(); - if lint_name.chars().any(char::is_uppercase) && self.find_lints(&name_lower).is_ok() { + if lint_name.chars().any(char::is_uppercase) && self.find_lints(&name_lower).is_some() { // First check if the lint name is (partly) in upper case instead of lower case... return CheckLintNameResult::NoLint(Some((Symbol::intern(&name_lower), false))); } @@ -455,18 +446,8 @@ impl LintStore { None => match self.lint_groups.get(&*complete_name) { // Now we are sure, that this lint exists nowhere None => self.no_lint_suggestion(lint_name, tool_name), - Some(LintGroup { lint_ids, depr, .. }) => { - // Reaching this would be weird, but let's cover this case anyway - if let Some(LintAlias { name, silent }) = depr { - let LintGroup { lint_ids, .. } = self.lint_groups.get(name).unwrap(); - if *silent { - CheckLintNameResult::Tool(lint_ids, Some(complete_name)) - } else { - CheckLintNameResult::Tool(lint_ids, Some((*name).to_string())) - } - } else { - CheckLintNameResult::Tool(lint_ids, Some(complete_name)) - } + Some(LintGroup { lint_ids, .. }) => { + CheckLintNameResult::Tool(lint_ids, Some(complete_name)) } }, Some(Id(id)) => CheckLintNameResult::Tool(slice::from_ref(id), Some(complete_name)), diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index d0b1e7bf2553..00775647ac61 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -517,11 +517,11 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { let lint_flag_val = Symbol::intern(lint_name); - let Ok(ids) = self.store.find_lints(lint_name) else { + let Some(ids) = self.store.find_lints(lint_name) else { // errors already handled above continue; }; - for id in ids { + for &id in ids { // ForceWarn and Forbid cannot be overridden if let Some(LevelAndSource { level: Level::ForceWarn | Level::Forbid, .. }) = self.current_specs().get(&id) diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 9b5c564d3324..e1afd8bacb09 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -125,9 +125,7 @@ use unused::*; #[rustfmt::skip] pub use builtin::{MissingDoc, SoftLints}; -pub use context::{ - CheckLintNameResult, EarlyContext, FindLintError, LateContext, LintContext, LintStore, -}; +pub use context::{CheckLintNameResult, EarlyContext, LateContext, LintContext, LintStore}; pub use early::{EarlyCheckNode, check_ast_node}; pub use late::{check_crate, late_lint_mod, unerased_lint_store}; pub use levels::LintLevelsBuilder; From 13f1c845840fa40135fbed8798ec42df4d93b5d3 Mon Sep 17 00:00:00 2001 From: "Celina G. Val" Date: Thu, 10 Apr 2025 16:32:56 -0700 Subject: [PATCH 337/606] Apply suggestions from code review Co-authored-by: Ralf Jung --- library/core/src/contracts.rs | 2 +- library/core/src/intrinsics/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/contracts.rs b/library/core/src/contracts.rs index 53f459debabc..495f84bce4bf 100644 --- a/library/core/src/contracts.rs +++ b/library/core/src/contracts.rs @@ -13,7 +13,7 @@ pub use crate::macros::builtin::{contracts_ensures as ensures, contracts_require #[unstable(feature = "contracts_internals", issue = "128044" /* compiler-team#759 */)] // Similar to `contract_check_requires`, we need to use the user-facing // `contracts` feature rather than the perma-unstable `contracts_internals`. -// Const-checking doesn't honor allow internal unstable logic used by contract expansion. +// Const-checking doesn't honor allow_internal_unstable logic used by contract expansion. #[rustc_const_unstable(feature = "contracts", issue = "128044")] #[lang = "contract_build_check_ensures"] pub const fn build_check_ensures(cond: C) -> C diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 90f686a67288..9c9c1e41e717 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -3484,7 +3484,7 @@ pub const fn contract_check_requires bool + Copy>(cond: C) { #[unstable(feature = "contracts_internals", issue = "128044")] // Similar to `contract_check_requires`, we need to use the user-facing // `contracts` feature rather than the perma-unstable `contracts_internals`. -// Const-checking doesn't honor allow internal unstable logic used by contract expansion. +// Const-checking doesn't honor allow_internal_unstable logic used by contract expansion. #[rustc_const_unstable(feature = "contracts", issue = "128044")] #[lang = "contract_check_ensures"] #[rustc_intrinsic] From d25c8a8ade05384e9ca84866be8672a97896826d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 11 Apr 2025 10:45:14 +1000 Subject: [PATCH 338/606] Handle a negated literal in `eat_token_lit`. Fixes #139495. --- compiler/rustc_parse/src/parser/expr.rs | 13 +++++++++---- tests/ui/macros/reparse-expr-issue-139495.rs | 7 +++++++ tests/ui/macros/reparse-expr-issue-139495.stderr | 13 +++++++++++++ 3 files changed, 29 insertions(+), 4 deletions(-) create mode 100644 tests/ui/macros/reparse-expr-issue-139495.rs create mode 100644 tests/ui/macros/reparse-expr-issue-139495.stderr diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 9c457f150a32..d52e36fcfac2 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2166,10 +2166,15 @@ impl<'a> Parser<'a> { let expr = self .eat_metavar_seq(mv_kind, |this| this.parse_expr()) .expect("metavar seq expr"); - let ast::ExprKind::Lit(token_lit) = expr.kind else { - panic!("didn't reparse an expr"); - }; - Some(token_lit) + if let ast::ExprKind::Lit(token_lit) = expr.kind { + Some(token_lit) + } else if let ast::ExprKind::Unary(UnOp::Neg, inner) = &expr.kind + && let ast::Expr { kind: ast::ExprKind::Lit(_), .. } = **inner + { + None + } else { + panic!("unexpected reparsed expr: {:?}", expr.kind); + } } _ => None, } diff --git a/tests/ui/macros/reparse-expr-issue-139495.rs b/tests/ui/macros/reparse-expr-issue-139495.rs new file mode 100644 index 000000000000..38d24573a533 --- /dev/null +++ b/tests/ui/macros/reparse-expr-issue-139495.rs @@ -0,0 +1,7 @@ +macro_rules! m { + ($abi : expr) => { extern $abi } //~ ERROR expected expression, found keyword `extern` +} + +fn main() { + m!(-2) +} diff --git a/tests/ui/macros/reparse-expr-issue-139495.stderr b/tests/ui/macros/reparse-expr-issue-139495.stderr new file mode 100644 index 000000000000..73a8ed87ba05 --- /dev/null +++ b/tests/ui/macros/reparse-expr-issue-139495.stderr @@ -0,0 +1,13 @@ +error: expected expression, found keyword `extern` + --> $DIR/reparse-expr-issue-139495.rs:2:22 + | +LL | ($abi : expr) => { extern $abi } + | ^^^^^^ expected expression +... +LL | m!(-2) + | ------ in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 1 previous error + From 7e8184fa2a712356f1827c8abc01bafcd359b122 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 11 Apr 2025 10:10:06 +1000 Subject: [PATCH 339/606] Improve `AssocItem::descr`. The commit adds "associated" to the description of associated types and associated consts, to match the description of associated functions. This increases error message precision and consistency with `AssocKind::fmt`. The commit also notes an imperfection in `AssocKind::fmt`; fixing this imperfection is possible but beyond the scope of this PR. --- compiler/rustc_middle/src/ty/assoc.rs | 6 +++-- .../elided-lifetime.rs | 2 +- .../elided-lifetime.stderr | 6 ++--- .../static-trait-impl.rs | 2 +- .../static-trait-impl.stderr | 6 ++--- .../const_params_have_right_type.stderr | 2 +- .../issue-102114.current.stderr | 2 +- .../issue-102114.next.stderr | 2 +- .../parameter_number_and_kind_impl.rs | 6 ++--- .../parameter_number_and_kind_impl.stderr | 24 +++++++++---------- .../assoc-const-missing-type.rs | 2 +- .../assoc-const-missing-type.stderr | 6 ++--- .../generic-const-items/compare-impl-item.rs | 2 +- .../compare-impl-item.stderr | 14 +++++------ ...bstituting-in-region-112823.current.stderr | 2 +- ...nsubstituting-in-region-112823.next.stderr | 2 +- .../in-trait/span-bug-issue-121457.rs | 2 +- .../in-trait/span-bug-issue-121457.stderr | 6 ++--- tests/ui/lifetimes/no_lending_iterators.rs | 2 +- .../ui/lifetimes/no_lending_iterators.stderr | 6 ++--- ...trait-in-type-alias-with-bad-substs.stderr | 2 +- 21 files changed, 53 insertions(+), 51 deletions(-) diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs index e3d332036f1f..bbaf735fbdb9 100644 --- a/compiler/rustc_middle/src/ty/assoc.rs +++ b/compiler/rustc_middle/src/ty/assoc.rs @@ -98,10 +98,10 @@ impl AssocItem { pub fn descr(&self) -> &'static str { match self.kind { - ty::AssocKind::Const => "const", + ty::AssocKind::Const => "associated const", ty::AssocKind::Fn if self.fn_has_self_parameter => "method", ty::AssocKind::Fn => "associated function", - ty::AssocKind::Type => "type", + ty::AssocKind::Type => "associated type", } } @@ -155,6 +155,8 @@ impl AssocKind { impl std::fmt::Display for AssocKind { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { + // FIXME: fails to distinguish between "associated function" and + // "method" because `has_self` isn't known here. AssocKind::Fn => write!(f, "method"), AssocKind::Const => write!(f, "associated const"), AssocKind::Type => write!(f, "associated type"), diff --git a/tests/ui/consts/static-default-lifetime/elided-lifetime.rs b/tests/ui/consts/static-default-lifetime/elided-lifetime.rs index ccf63f86fcf3..d60fe7d409af 100644 --- a/tests/ui/consts/static-default-lifetime/elided-lifetime.rs +++ b/tests/ui/consts/static-default-lifetime/elided-lifetime.rs @@ -16,7 +16,7 @@ impl Bar for Foo<'_> { const STATIC: &str = ""; //~^ ERROR `&` without an explicit lifetime name cannot be used here //~| WARN this was previously accepted by the compiler but is being phased out - //~| ERROR lifetime parameters or bounds on const `STATIC` do not match the trait declaration + //~| ERROR lifetime parameters or bounds on associated const `STATIC` do not match the trait declaration } fn main() {} diff --git a/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr b/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr index 33873f5c5a50..bb8365b0ae56 100644 --- a/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr +++ b/tests/ui/consts/static-default-lifetime/elided-lifetime.stderr @@ -39,14 +39,14 @@ help: use the `'static` lifetime LL | const STATIC: &'static str = ""; | +++++++ -error[E0195]: lifetime parameters or bounds on const `STATIC` do not match the trait declaration +error[E0195]: lifetime parameters or bounds on associated const `STATIC` do not match the trait declaration --> $DIR/elided-lifetime.rs:16:17 | LL | const STATIC: &str; - | - lifetimes in impl do not match this const in trait + | - lifetimes in impl do not match this associated const in trait ... LL | const STATIC: &str = ""; - | ^ lifetimes do not match const in trait + | ^ lifetimes do not match associated const in trait error: aborting due to 3 previous errors diff --git a/tests/ui/consts/static-default-lifetime/static-trait-impl.rs b/tests/ui/consts/static-default-lifetime/static-trait-impl.rs index 1e12259e4833..85746df146fc 100644 --- a/tests/ui/consts/static-default-lifetime/static-trait-impl.rs +++ b/tests/ui/consts/static-default-lifetime/static-trait-impl.rs @@ -9,7 +9,7 @@ impl Bar<'_> for A { const STATIC: &str = ""; //~^ ERROR `&` without an explicit lifetime name cannot be used here //~| WARN this was previously accepted by the compiler but is being phased out - //~| ERROR lifetime parameters or bounds on const `STATIC` do not match the trait declaration + //~| ERROR lifetime parameters or bounds on associated const `STATIC` do not match the trait declaration } struct B; diff --git a/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr b/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr index 116f28e84847..38d24db1317f 100644 --- a/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr +++ b/tests/ui/consts/static-default-lifetime/static-trait-impl.stderr @@ -21,14 +21,14 @@ help: use the `'static` lifetime LL | const STATIC: &'static str = ""; | +++++++ -error[E0195]: lifetime parameters or bounds on const `STATIC` do not match the trait declaration +error[E0195]: lifetime parameters or bounds on associated const `STATIC` do not match the trait declaration --> $DIR/static-trait-impl.rs:9:17 | LL | const STATIC: &'a str; - | - lifetimes in impl do not match this const in trait + | - lifetimes in impl do not match this associated const in trait ... LL | const STATIC: &str = ""; - | ^ lifetimes do not match const in trait + | ^ lifetimes do not match associated const in trait error: aborting due to 2 previous errors diff --git a/tests/ui/generic-associated-types/const_params_have_right_type.stderr b/tests/ui/generic-associated-types/const_params_have_right_type.stderr index 78992112a7c5..a3d3a66a05c4 100644 --- a/tests/ui/generic-associated-types/const_params_have_right_type.stderr +++ b/tests/ui/generic-associated-types/const_params_have_right_type.stderr @@ -1,4 +1,4 @@ -error[E0053]: type `Foo` has an incompatible generic parameter for trait `Trait` +error[E0053]: associated type `Foo` has an incompatible generic parameter for trait `Trait` --> $DIR/const_params_have_right_type.rs:6:14 | LL | trait Trait { diff --git a/tests/ui/generic-associated-types/issue-102114.current.stderr b/tests/ui/generic-associated-types/issue-102114.current.stderr index 03471d08d746..5aace1eeaa2f 100644 --- a/tests/ui/generic-associated-types/issue-102114.current.stderr +++ b/tests/ui/generic-associated-types/issue-102114.current.stderr @@ -1,4 +1,4 @@ -error[E0049]: type `B` has 1 type parameter but its trait declaration has 0 type parameters +error[E0049]: associated type `B` has 1 type parameter but its trait declaration has 0 type parameters --> $DIR/issue-102114.rs:15:12 | LL | type B<'b>; diff --git a/tests/ui/generic-associated-types/issue-102114.next.stderr b/tests/ui/generic-associated-types/issue-102114.next.stderr index 03471d08d746..5aace1eeaa2f 100644 --- a/tests/ui/generic-associated-types/issue-102114.next.stderr +++ b/tests/ui/generic-associated-types/issue-102114.next.stderr @@ -1,4 +1,4 @@ -error[E0049]: type `B` has 1 type parameter but its trait declaration has 0 type parameters +error[E0049]: associated type `B` has 1 type parameter but its trait declaration has 0 type parameters --> $DIR/issue-102114.rs:15:12 | LL | type B<'b>; diff --git a/tests/ui/generic-associated-types/parameter_number_and_kind_impl.rs b/tests/ui/generic-associated-types/parameter_number_and_kind_impl.rs index c1381025ac2a..a39a7aacc7b3 100644 --- a/tests/ui/generic-associated-types/parameter_number_and_kind_impl.rs +++ b/tests/ui/generic-associated-types/parameter_number_and_kind_impl.rs @@ -12,11 +12,11 @@ struct Fooy; impl Foo for Fooy { type A = u32; - //~^ ERROR lifetime parameters or bounds on type `A` do not match the trait declaration + //~^ ERROR lifetime parameters or bounds on associated type `A` do not match the trait declaration type B<'a, T> = Vec; //~^ ERROR type `B` has 1 type parameter but its trait declaration has 0 type parameters type C<'a> = u32; - //~^ ERROR lifetime parameters or bounds on type `C` do not match the trait declaration + //~^ ERROR lifetime parameters or bounds on associated type `C` do not match the trait declaration } struct Fooer; @@ -25,7 +25,7 @@ impl Foo for Fooer { type A = u32; //~^ ERROR type `A` has 1 type parameter but its trait declaration has 0 type parameters type B<'a> = u32; - //~^ ERROR lifetime parameters or bounds on type `B` do not match the trait declaration + //~^ ERROR lifetime parameters or bounds on associated type `B` do not match the trait declaration type C = T; //~^ ERROR type `C` has 1 type parameter but its trait declaration has 0 type parameters } diff --git a/tests/ui/generic-associated-types/parameter_number_and_kind_impl.stderr b/tests/ui/generic-associated-types/parameter_number_and_kind_impl.stderr index fdd6d305ab27..f7c4a07589c2 100644 --- a/tests/ui/generic-associated-types/parameter_number_and_kind_impl.stderr +++ b/tests/ui/generic-associated-types/parameter_number_and_kind_impl.stderr @@ -1,13 +1,13 @@ -error[E0195]: lifetime parameters or bounds on type `A` do not match the trait declaration +error[E0195]: lifetime parameters or bounds on associated type `A` do not match the trait declaration --> $DIR/parameter_number_and_kind_impl.rs:14:11 | LL | type A<'a>; - | ---- lifetimes in impl do not match this type in trait + | ---- lifetimes in impl do not match this associated type in trait ... LL | type A = u32; - | ^ lifetimes do not match type in trait + | ^ lifetimes do not match associated type in trait -error[E0049]: type `B` has 1 type parameter but its trait declaration has 0 type parameters +error[E0049]: associated type `B` has 1 type parameter but its trait declaration has 0 type parameters --> $DIR/parameter_number_and_kind_impl.rs:16:12 | LL | type B<'a, 'b>; @@ -20,16 +20,16 @@ LL | type B<'a, T> = Vec; | | | found 1 type parameter -error[E0195]: lifetime parameters or bounds on type `C` do not match the trait declaration +error[E0195]: lifetime parameters or bounds on associated type `C` do not match the trait declaration --> $DIR/parameter_number_and_kind_impl.rs:18:11 | LL | type C; - | - lifetimes in impl do not match this type in trait + | - lifetimes in impl do not match this associated type in trait ... LL | type C<'a> = u32; - | ^^^^ lifetimes do not match type in trait + | ^^^^ lifetimes do not match associated type in trait -error[E0049]: type `A` has 1 type parameter but its trait declaration has 0 type parameters +error[E0049]: associated type `A` has 1 type parameter but its trait declaration has 0 type parameters --> $DIR/parameter_number_and_kind_impl.rs:25:12 | LL | type A<'a>; @@ -38,16 +38,16 @@ LL | type A<'a>; LL | type A = u32; | ^ found 1 type parameter -error[E0195]: lifetime parameters or bounds on type `B` do not match the trait declaration +error[E0195]: lifetime parameters or bounds on associated type `B` do not match the trait declaration --> $DIR/parameter_number_and_kind_impl.rs:27:11 | LL | type B<'a, 'b>; - | -------- lifetimes in impl do not match this type in trait + | -------- lifetimes in impl do not match this associated type in trait ... LL | type B<'a> = u32; - | ^^^^ lifetimes do not match type in trait + | ^^^^ lifetimes do not match associated type in trait -error[E0049]: type `C` has 1 type parameter but its trait declaration has 0 type parameters +error[E0049]: associated type `C` has 1 type parameter but its trait declaration has 0 type parameters --> $DIR/parameter_number_and_kind_impl.rs:29:12 | LL | type C; diff --git a/tests/ui/generic-const-items/assoc-const-missing-type.rs b/tests/ui/generic-const-items/assoc-const-missing-type.rs index 0c94a4262ef4..dde47cf993ea 100644 --- a/tests/ui/generic-const-items/assoc-const-missing-type.rs +++ b/tests/ui/generic-const-items/assoc-const-missing-type.rs @@ -14,7 +14,7 @@ impl Trait for () { //~| ERROR mismatched types const Q = ""; //~^ ERROR missing type for `const` item - //~| ERROR lifetime parameters or bounds on const `Q` do not match the trait declaration + //~| ERROR lifetime parameters or bounds on associated const `Q` do not match the trait declaration } fn main() {} diff --git a/tests/ui/generic-const-items/assoc-const-missing-type.stderr b/tests/ui/generic-const-items/assoc-const-missing-type.stderr index 5af119dffa7c..9f6db575ec23 100644 --- a/tests/ui/generic-const-items/assoc-const-missing-type.stderr +++ b/tests/ui/generic-const-items/assoc-const-missing-type.stderr @@ -15,14 +15,14 @@ error: missing type for `const` item LL | const K = (); | ^ help: provide a type for the associated constant: `()` -error[E0195]: lifetime parameters or bounds on const `Q` do not match the trait declaration +error[E0195]: lifetime parameters or bounds on associated const `Q` do not match the trait declaration --> $DIR/assoc-const-missing-type.rs:15:12 | LL | const Q<'a>: &'a str; - | ---- lifetimes in impl do not match this const in trait + | ---- lifetimes in impl do not match this associated const in trait ... LL | const Q = ""; - | ^ lifetimes do not match const in trait + | ^ lifetimes do not match associated const in trait error: missing type for `const` item --> $DIR/assoc-const-missing-type.rs:15:12 diff --git a/tests/ui/generic-const-items/compare-impl-item.rs b/tests/ui/generic-const-items/compare-impl-item.rs index 21c958a0abec..b301cd0dae0c 100644 --- a/tests/ui/generic-const-items/compare-impl-item.rs +++ b/tests/ui/generic-const-items/compare-impl-item.rs @@ -22,7 +22,7 @@ impl

Trait

for () { const D: u16 = N; //~^ ERROR const `D` has an incompatible generic parameter for trait `Trait` const E: &'static () = &(); - //~^ ERROR lifetime parameters or bounds on const `E` do not match the trait declaration + //~^ ERROR lifetime parameters or bounds on associated const `E` do not match the trait declaration const F: usize = 1024 where diff --git a/tests/ui/generic-const-items/compare-impl-item.stderr b/tests/ui/generic-const-items/compare-impl-item.stderr index 3bf28e9da60f..f7e3ff6501b1 100644 --- a/tests/ui/generic-const-items/compare-impl-item.stderr +++ b/tests/ui/generic-const-items/compare-impl-item.stderr @@ -1,4 +1,4 @@ -error[E0049]: const `A` has 1 type parameter but its trait declaration has 0 type parameters +error[E0049]: associated const `A` has 1 type parameter but its trait declaration has 0 type parameters --> $DIR/compare-impl-item.rs:16:13 | LL | const A: (); @@ -7,7 +7,7 @@ LL | const A: (); LL | const A: () = (); | ^ found 1 type parameter -error[E0049]: const `B` has 1 const parameter but its trait declaration has 2 const parameters +error[E0049]: associated const `B` has 1 const parameter but its trait declaration has 2 const parameters --> $DIR/compare-impl-item.rs:18:13 | LL | const B: u64; @@ -18,7 +18,7 @@ LL | const B: u64; LL | const B: u64 = 0; | ^^^^^^^^^^^^ found 1 const parameter -error[E0049]: const `C` has 0 type parameters but its trait declaration has 1 type parameter +error[E0049]: associated const `C` has 0 type parameters but its trait declaration has 1 type parameter --> $DIR/compare-impl-item.rs:20:13 | LL | const C: T; @@ -27,7 +27,7 @@ LL | const C: T; LL | const C<'a>: &'a str = ""; | ^^ found 0 type parameters -error[E0053]: const `D` has an incompatible generic parameter for trait `Trait` +error[E0053]: associated const `D` has an incompatible generic parameter for trait `Trait` --> $DIR/compare-impl-item.rs:22:13 | LL | trait Trait

{ @@ -42,14 +42,14 @@ LL | impl

Trait

for () { LL | const D: u16 = N; | ^^^^^^^^^^^^ found const parameter of type `u16` -error[E0195]: lifetime parameters or bounds on const `E` do not match the trait declaration +error[E0195]: lifetime parameters or bounds on associated const `E` do not match the trait declaration --> $DIR/compare-impl-item.rs:24:12 | LL | const E<'a>: &'a (); - | ---- lifetimes in impl do not match this const in trait + | ---- lifetimes in impl do not match this associated const in trait ... LL | const E: &'static () = &(); - | ^ lifetimes do not match const in trait + | ^ lifetimes do not match associated const in trait error[E0276]: impl has stricter requirements than trait --> $DIR/compare-impl-item.rs:29:12 diff --git a/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.current.stderr b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.current.stderr index c76415d8114b..341262ac85b3 100644 --- a/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.current.stderr +++ b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.current.stderr @@ -4,7 +4,7 @@ error[E0407]: method `line_stream` is not a member of trait `X` LL | fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a member of trait `X` -error[E0049]: type `LineStream` has 0 type parameters but its trait declaration has 1 type parameter +error[E0049]: associated type `LineStream` has 0 type parameters but its trait declaration has 1 type parameter --> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:25:21 | LL | type LineStream<'a, Repr> diff --git a/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.next.stderr b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.next.stderr index 4d72490ff956..9632d2ce6249 100644 --- a/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.next.stderr +++ b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.next.stderr @@ -4,7 +4,7 @@ error[E0407]: method `line_stream` is not a member of trait `X` LL | fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a member of trait `X` -error[E0049]: type `LineStream` has 0 type parameters but its trait declaration has 1 type parameter +error[E0049]: associated type `LineStream` has 0 type parameters but its trait declaration has 1 type parameter --> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:25:21 | LL | type LineStream<'a, Repr> diff --git a/tests/ui/impl-trait/in-trait/span-bug-issue-121457.rs b/tests/ui/impl-trait/in-trait/span-bug-issue-121457.rs index ab21dae7dc50..7dc747bffba4 100644 --- a/tests/ui/impl-trait/in-trait/span-bug-issue-121457.rs +++ b/tests/ui/impl-trait/in-trait/span-bug-issue-121457.rs @@ -8,7 +8,7 @@ pub trait Iterable { impl<'a, I: 'a + Iterable> Iterable for &'a I { type Item = u32; - //~^ ERROR lifetime parameters or bounds on type `Item` do not match the trait declaration + //~^ ERROR lifetime parameters or bounds on associated type `Item` do not match the trait declaration fn iter(&self) -> impl for<'missing> Iterator> {} //~^ ERROR binding for associated type `Item` references lifetime `'missing` diff --git a/tests/ui/impl-trait/in-trait/span-bug-issue-121457.stderr b/tests/ui/impl-trait/in-trait/span-bug-issue-121457.stderr index d8a2eef94a18..eaa320455bbb 100644 --- a/tests/ui/impl-trait/in-trait/span-bug-issue-121457.stderr +++ b/tests/ui/impl-trait/in-trait/span-bug-issue-121457.stderr @@ -12,17 +12,17 @@ LL | fn iter(&self) -> impl for<'missing> Iterator $DIR/span-bug-issue-121457.rs:10:14 | LL | type Item<'a> - | ---- lifetimes in impl do not match this type in trait + | ---- lifetimes in impl do not match this associated type in trait LL | where LL | Self: 'a; | -- this bound might be missing in the impl ... LL | type Item = u32; - | ^ lifetimes do not match type in trait + | ^ lifetimes do not match associated type in trait error[E0277]: `()` is not an iterator --> $DIR/span-bug-issue-121457.rs:13:23 diff --git a/tests/ui/lifetimes/no_lending_iterators.rs b/tests/ui/lifetimes/no_lending_iterators.rs index 21395475fb3d..b3e8ad08ba18 100644 --- a/tests/ui/lifetimes/no_lending_iterators.rs +++ b/tests/ui/lifetimes/no_lending_iterators.rs @@ -25,7 +25,7 @@ impl Bar for usize { impl Bar for isize { type Item<'a> = &'a isize; - //~^ ERROR 27:14: 27:18: lifetime parameters or bounds on type `Item` do not match the trait declaration [E0195] + //~^ ERROR 27:14: 27:18: lifetime parameters or bounds on associated type `Item` do not match the trait declaration [E0195] fn poke(&mut self, item: Self::Item) { self += *item; diff --git a/tests/ui/lifetimes/no_lending_iterators.stderr b/tests/ui/lifetimes/no_lending_iterators.stderr index 9ceaef2f9b1a..340ef9358851 100644 --- a/tests/ui/lifetimes/no_lending_iterators.stderr +++ b/tests/ui/lifetimes/no_lending_iterators.stderr @@ -16,14 +16,14 @@ error: in the trait associated type is declared without lifetime parameters, so LL | type Item = &usize; | ^ this lifetime must come from the implemented type -error[E0195]: lifetime parameters or bounds on type `Item` do not match the trait declaration +error[E0195]: lifetime parameters or bounds on associated type `Item` do not match the trait declaration --> $DIR/no_lending_iterators.rs:27:14 | LL | type Item; - | - lifetimes in impl do not match this type in trait + | - lifetimes in impl do not match this associated type in trait ... LL | type Item<'a> = &'a isize; - | ^^^^ lifetimes do not match type in trait + | ^^^^ lifetimes do not match associated type in trait error: aborting due to 3 previous errors diff --git a/tests/ui/type-alias-impl-trait/impl-trait-in-type-alias-with-bad-substs.stderr b/tests/ui/type-alias-impl-trait/impl-trait-in-type-alias-with-bad-substs.stderr index 13f5d8b8ea6e..c58d919c4b12 100644 --- a/tests/ui/type-alias-impl-trait/impl-trait-in-type-alias-with-bad-substs.stderr +++ b/tests/ui/type-alias-impl-trait/impl-trait-in-type-alias-with-bad-substs.stderr @@ -1,4 +1,4 @@ -error[E0049]: type `Baz` has 1 type parameter but its trait declaration has 0 type parameters +error[E0049]: associated type `Baz` has 1 type parameter but its trait declaration has 0 type parameters --> $DIR/impl-trait-in-type-alias-with-bad-substs.rs:19:14 | LL | type Baz<'a>; From 56c08d9b329c34e7be93d4a18a2b8987779140a9 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sun, 30 Mar 2025 23:03:45 -0700 Subject: [PATCH 340/606] indirect-const-stabilize the `exact_div` intrinsic --- library/core/src/intrinsics/mod.rs | 1 + library/core/src/slice/mod.rs | 6 ------ 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index ad33e2e5fe94..cbaa810ae068 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -2735,6 +2735,7 @@ pub const fn carrying_mul_add, /// `x % y != 0` or `y == 0` or `x == T::MIN && y == -1` /// /// This intrinsic does not have a stable counterpart. +#[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] pub const unsafe fn exact_div(x: T, y: T) -> T; diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index b906899a30b3..59f8020f0c38 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -1287,7 +1287,6 @@ impl [T] { /// // let chunks: &[[_; 0]] = slice.as_chunks_unchecked() // Zero-length chunks are never allowed /// ``` #[unstable(feature = "slice_as_chunks", issue = "74985")] - #[rustc_const_unstable(feature = "slice_as_chunks", issue = "74985")] #[inline] #[must_use] pub const unsafe fn as_chunks_unchecked(&self) -> &[[T; N]] { @@ -1333,7 +1332,6 @@ impl [T] { /// assert_eq!(chunks, &[['R', 'u'], ['s', 't']]); /// ``` #[unstable(feature = "slice_as_chunks", issue = "74985")] - #[rustc_const_unstable(feature = "slice_as_chunks", issue = "74985")] #[inline] #[track_caller] #[must_use] @@ -1368,7 +1366,6 @@ impl [T] { /// assert_eq!(chunks, &[['o', 'r'], ['e', 'm']]); /// ``` #[unstable(feature = "slice_as_chunks", issue = "74985")] - #[rustc_const_unstable(feature = "slice_as_chunks", issue = "74985")] #[inline] #[track_caller] #[must_use] @@ -1448,7 +1445,6 @@ impl [T] { /// // let chunks: &[[_; 0]] = slice.as_chunks_unchecked_mut() // Zero-length chunks are never allowed /// ``` #[unstable(feature = "slice_as_chunks", issue = "74985")] - #[rustc_const_unstable(feature = "slice_as_chunks", issue = "74985")] #[inline] #[must_use] pub const unsafe fn as_chunks_unchecked_mut(&mut self) -> &mut [[T; N]] { @@ -1489,7 +1485,6 @@ impl [T] { /// assert_eq!(v, &[1, 1, 2, 2, 9]); /// ``` #[unstable(feature = "slice_as_chunks", issue = "74985")] - #[rustc_const_unstable(feature = "slice_as_chunks", issue = "74985")] #[inline] #[track_caller] #[must_use] @@ -1530,7 +1525,6 @@ impl [T] { /// assert_eq!(v, &[9, 1, 1, 2, 2]); /// ``` #[unstable(feature = "slice_as_chunks", issue = "74985")] - #[rustc_const_unstable(feature = "slice_as_chunks", issue = "74985")] #[inline] #[track_caller] #[must_use] From fad2535e4b49f95becb8f2e3166795cbf408ec73 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 11 Apr 2025 14:20:37 +1000 Subject: [PATCH 341/606] Adjust an assertion. No need to convert the `DefKind` to `DefPathData`, they're very similar types. --- compiler/rustc_resolve/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index e1476814d5c0..a526f98b91f1 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1339,12 +1339,12 @@ impl<'tcx> Resolver<'_, 'tcx> { expn_id: ExpnId, span: Span, ) -> TyCtxtFeed<'tcx, LocalDefId> { - let data = def_kind.def_path_data(name); assert!( !self.node_id_to_def_id.contains_key(&node_id), - "adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}", + "adding a def for node-id {:?}, name {:?}, data {:?} but a previous def exists: {:?}", node_id, - data, + name, + def_kind, self.tcx.definitions_untracked().def_key(self.node_id_to_def_id[&node_id].key()), ); From f97da855b1bbeecb0313023c9b4503eb82649fec Mon Sep 17 00:00:00 2001 From: Makai Date: Fri, 11 Apr 2025 15:30:00 +0800 Subject: [PATCH 342/606] suggest: remove redundant `$()?`around `vis` fragments --- compiler/rustc_expand/src/mbe/macro_rules.rs | 44 ++++++++++++++++--- .../macros/remove-repetition-issue-139480.rs | 28 ++++++++++++ .../remove-repetition-issue-139480.stderr | 44 +++++++++++++++++++ 3 files changed, 110 insertions(+), 6 deletions(-) create mode 100644 tests/ui/macros/remove-repetition-issue-139480.rs create mode 100644 tests/ui/macros/remove-repetition-issue-139480.stderr diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 77ec598e62a1..460a06f9c060 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -12,7 +12,7 @@ use rustc_ast::{self as ast, DUMMY_NODE_ID, NodeId}; use rustc_ast_pretty::pprust; use rustc_attr_parsing::{AttributeKind, find_attr}; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; -use rustc_errors::{Applicability, ErrorGuaranteed}; +use rustc_errors::{Applicability, Diag, ErrorGuaranteed}; use rustc_feature::Features; use rustc_hir as hir; use rustc_lint_defs::BuiltinLintDiag; @@ -27,19 +27,18 @@ use rustc_span::hygiene::Transparency; use rustc_span::{Ident, MacroRulesNormalizedIdent, Span, kw, sym}; use tracing::{debug, instrument, trace, trace_span}; -use super::diagnostics; use super::macro_parser::{NamedMatches, NamedParseResult}; +use super::{SequenceRepetition, diagnostics}; use crate::base::{ DummyResult, ExpandResult, ExtCtxt, MacResult, MacroExpanderResult, SyntaxExtension, SyntaxExtensionKind, TTMacroExpander, }; use crate::expand::{AstFragment, AstFragmentKind, ensure_complete_parse, parse_ast_fragment}; -use crate::mbe; use crate::mbe::diagnostics::{annotate_doc_comment, parse_failure_msg}; -use crate::mbe::macro_check; use crate::mbe::macro_parser::NamedMatch::*; use crate::mbe::macro_parser::{Error, ErrorReported, Failure, MatcherLoc, Success, TtParser}; use crate::mbe::transcribe::transcribe; +use crate::mbe::{self, KleeneOp, macro_check}; pub(crate) struct ParserAnyMacro<'a> { parser: Parser<'a>, @@ -640,6 +639,37 @@ fn is_empty_token_tree(sess: &Session, seq: &mbe::SequenceRepetition) -> bool { } } +/// Checks if a `vis` nonterminal fragment is unnecessarily wrapped in an optional repetition. +/// +/// When a `vis` fragment (which can already be empty) is wrapped in `$(...)?`, +/// this suggests removing the redundant repetition syntax since it provides no additional benefit. +fn check_redundant_vis_repetition( + err: &mut Diag<'_>, + sess: &Session, + seq: &SequenceRepetition, + span: &DelimSpan, +) { + let is_zero_or_one: bool = seq.kleene.op == KleeneOp::ZeroOrOne; + let is_vis = seq.tts.first().map_or(false, |tt| { + matches!(tt, mbe::TokenTree::MetaVarDecl(_, _, Some(NonterminalKind::Vis))) + }); + + if is_vis && is_zero_or_one { + err.note("a `vis` fragment can already be empty"); + err.multipart_suggestion( + "remove the `$(` and `)?`", + vec![ + ( + sess.source_map().span_extend_to_prev_char_before(span.open, '$', true), + "".to_string(), + ), + (span.close.with_hi(seq.kleene.span.hi()), "".to_string()), + ], + Applicability::MaybeIncorrect, + ); + } +} + /// Checks that the lhs contains no repetition which could match an empty token /// tree, because then the matcher would hang indefinitely. fn check_lhs_no_empty_seq(sess: &Session, tts: &[mbe::TokenTree]) -> Result<(), ErrorGuaranteed> { @@ -654,8 +684,10 @@ fn check_lhs_no_empty_seq(sess: &Session, tts: &[mbe::TokenTree]) -> Result<(), TokenTree::Sequence(span, seq) => { if is_empty_token_tree(sess, seq) { let sp = span.entire(); - let guar = sess.dcx().span_err(sp, "repetition matches empty token tree"); - return Err(guar); + let mut err = + sess.dcx().struct_span_err(sp, "repetition matches empty token tree"); + check_redundant_vis_repetition(&mut err, sess, seq, span); + return Err(err.emit()); } check_lhs_no_empty_seq(sess, &seq.tts)? } diff --git a/tests/ui/macros/remove-repetition-issue-139480.rs b/tests/ui/macros/remove-repetition-issue-139480.rs new file mode 100644 index 000000000000..1efb4306763e --- /dev/null +++ b/tests/ui/macros/remove-repetition-issue-139480.rs @@ -0,0 +1,28 @@ +macro_rules! ciallo { + ($($v: vis)? $name: ident) => { + //~^ error: repetition matches empty token tree + }; +} + +macro_rules! meow { + ($name: ident $($v: vis)?) => { + //~^ error: repetition matches empty token tree + }; +} + +macro_rules! gbc { + ($name: ident $/* + this comment gets removed by the suggestion + */ + ($v: vis)?) => { + //~^ error: repetition matches empty token tree + }; +} + +ciallo!(hello); + +meow!(miaow, pub); + +gbc!(mygo,); + +fn main() {} diff --git a/tests/ui/macros/remove-repetition-issue-139480.stderr b/tests/ui/macros/remove-repetition-issue-139480.stderr new file mode 100644 index 000000000000..c2475589ee9a --- /dev/null +++ b/tests/ui/macros/remove-repetition-issue-139480.stderr @@ -0,0 +1,44 @@ +error: repetition matches empty token tree + --> $DIR/remove-repetition-issue-139480.rs:2:7 + | +LL | ($($v: vis)? $name: ident) => { + | ^^^^^^^^^ + | + = note: a `vis` fragment can already be empty +help: remove the `$(` and `)?` + | +LL - ($($v: vis)? $name: ident) => { +LL + ($v: vis $name: ident) => { + | + +error: repetition matches empty token tree + --> $DIR/remove-repetition-issue-139480.rs:8:20 + | +LL | ($name: ident $($v: vis)?) => { + | ^^^^^^^^^ + | + = note: a `vis` fragment can already be empty +help: remove the `$(` and `)?` + | +LL - ($name: ident $($v: vis)?) => { +LL + ($name: ident $v: vis) => { + | + +error: repetition matches empty token tree + --> $DIR/remove-repetition-issue-139480.rs:17:9 + | +LL | ($v: vis)?) => { + | ^^^^^^^^^ + | + = note: a `vis` fragment can already be empty +help: remove the `$(` and `)?` + | +LL - ($name: ident $/* +LL - this comment gets removed by the suggestion +LL - */ +LL - ($v: vis)?) => { +LL + ($name: ident $v: vis) => { + | + +error: aborting due to 3 previous errors + From 3ebf1c2e67a03d514c0240b1d17aab3c1d2a8a04 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Fri, 11 Apr 2025 09:57:21 +0200 Subject: [PATCH 343/606] didn't catch this test failure, whoops --- tests/codegen/async-fn-debug-msvc.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/codegen/async-fn-debug-msvc.rs b/tests/codegen/async-fn-debug-msvc.rs index f0bb9a18bcea..e0c601146f81 100644 --- a/tests/codegen/async-fn-debug-msvc.rs +++ b/tests/codegen/async-fn-debug-msvc.rs @@ -20,23 +20,23 @@ async fn async_fn_test() { // CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "enum2$", // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant0", scope: [[GEN]], // For brevity, we only check the struct name and members of the last variant. -// CHECK-SAME: file: [[FILE:![0-9]*]], line: 11, +// CHECK-SAME: file: [[FILE:![0-9]*]], line: 12, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant1", scope: [[GEN]], -// CHECK-SAME: file: [[FILE]], line: 15, +// CHECK-SAME: file: [[FILE]], line: 16, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant2", scope: [[GEN]], -// CHECK-SAME: file: [[FILE]], line: 15, +// CHECK-SAME: file: [[FILE]], line: 16, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant3", scope: [[GEN]], -// CHECK-SAME: file: [[FILE]], line: 12, +// CHECK-SAME: file: [[FILE]], line: 13, // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant4", scope: [[GEN]], -// CHECK-SAME: file: [[FILE]], line: 14, +// CHECK-SAME: file: [[FILE]], line: 15, // CHECK-SAME: baseType: [[VARIANT_WRAPPER:![0-9]*]] // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) From 923f44c6313b86f3c1eeec264dce1a4317c8bbf6 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 11 Apr 2025 10:41:10 +0200 Subject: [PATCH 344/606] consistent name for `UniversalRegions` --- compiler/rustc_borrowck/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 64ad1c968565..b4e807646c0a 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -330,7 +330,7 @@ fn do_mir_borrowck<'tcx>( // will have a lifetime tied to the inference context. let mut body_owned = input_body.clone(); let mut promoted = input_promoted.to_owned(); - let free_regions = nll::replace_regions_in_mir(&infcx, &mut body_owned, &mut promoted); + let universal_regions = nll::replace_regions_in_mir(&infcx, &mut body_owned, &mut promoted); let body = &body_owned; // no further changes let location_table = PoloniusLocationTable::new(body); @@ -355,7 +355,7 @@ fn do_mir_borrowck<'tcx>( } = nll::compute_regions( root_cx, &infcx, - free_regions, + universal_regions, body, &promoted, &location_table, From 8cb727424dde83b841610700e40f399848e57700 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 11 Apr 2025 10:42:45 +0200 Subject: [PATCH 345/606] use input `def_id` to compute `movable_coroutine` This previously incorrectly returned `true` for parent functions whose first statement was `let local = ;`. While that didn't cause any bugs as we only ever access `movable_coroutine` for `yield` terminators. It was still wrong. --- compiler/rustc_borrowck/src/lib.rs | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index b4e807646c0a..94c1b54672ac 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -374,17 +374,8 @@ fn do_mir_borrowck<'tcx>( let diags_buffer = &mut BorrowckDiagnosticsBuffer::default(); nll::dump_annotation(&infcx, body, ®ioncx, &opt_closure_req, diags_buffer); - let movable_coroutine = - // The first argument is the coroutine type passed by value - if let Some(local) = body.local_decls.raw.get(1) - // Get the interior types and args which typeck computed - && let ty::Coroutine(def_id, _) = *local.ty.kind() - && tcx.coroutine_movability(def_id) == hir::Movability::Movable -{ - true -} else { - false -}; + let movable_coroutine = body.coroutine.is_some() + && tcx.coroutine_movability(def.to_def_id()) == hir::Movability::Movable; // While promoteds should mostly be correct by construction, we need to check them for // invalid moves to detect moving out of arrays:`struct S; fn main() { &([S][0]); }`. From 9eca59a94021089905c482011a2d88ee9b862a73 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 11 Apr 2025 14:32:00 +1000 Subject: [PATCH 346/606] Introduce `DefPathData::AnonAssocTy`. PR #137977 changed `DefPathData::TypeNs` to contain `Option` to account for RPITIT assoc types being anonymous. This commit changes it back to `Symbol` and gives anonymous assoc types their own variant. It makes things a bit nicer overall. --- compiler/rustc_hir/src/def.rs | 13 +++++++---- compiler/rustc_hir/src/definitions.rs | 22 ++++++++----------- compiler/rustc_middle/src/ty/print/pretty.rs | 4 ++-- .../src/ty/significant_drop_order.rs | 2 +- .../src/cfi/typeid/itanium_cxx_abi/encode.rs | 3 ++- compiler/rustc_symbol_mangling/src/v0.rs | 3 ++- compiler/rustc_ty_utils/src/assoc.rs | 4 ++-- src/tools/clippy/clippy_utils/src/lib.rs | 6 ++--- 8 files changed, 30 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index dc00b52a5936..9372ab532bf3 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -267,11 +267,16 @@ impl DefKind { | DefKind::ForeignTy | DefKind::TraitAlias | DefKind::TyParam - | DefKind::ExternCrate => DefPathData::TypeNs(Some(name.unwrap())), + | DefKind::ExternCrate => DefPathData::TypeNs(name.unwrap()), - // An associated type names will be missing for an RPITIT. It will - // later be given a name with `synthetic` in it, if necessary. - DefKind::AssocTy => DefPathData::TypeNs(name), + // An associated type name will be missing for an RPITIT. + DefKind::AssocTy => { + if let Some(name) = name { + DefPathData::TypeNs(name) + } else { + DefPathData::AnonAssocTy + } + } // It's not exactly an anon const, but wrt DefPathData, there // is no difference. diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs index c52954aa96fc..deba21d509fc 100644 --- a/compiler/rustc_hir/src/definitions.rs +++ b/compiler/rustc_hir/src/definitions.rs @@ -271,9 +271,8 @@ pub enum DefPathData { Use, /// A global asm item. GlobalAsm, - /// Something in the type namespace. Will be empty for RPITIT associated - /// types, which are given a synthetic name later, if necessary. - TypeNs(Option), + /// Something in the type namespace. + TypeNs(Symbol), /// Something in the value namespace. ValueNs(Symbol), /// Something in the macro namespace. @@ -291,6 +290,8 @@ pub enum DefPathData { /// An existential `impl Trait` type node. /// Argument position `impl Trait` have a `TypeNs` with their pretty-printed name. OpaqueTy, + /// An anonymous associated type from an RPITIT. + AnonAssocTy, /// A synthetic body for a coroutine's by-move body. SyntheticCoroutineBody, } @@ -413,9 +414,7 @@ impl DefPathData { pub fn get_opt_name(&self) -> Option { use self::DefPathData::*; match *self { - TypeNs(name) => name, - - ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name), + TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name), Impl | ForeignMod @@ -426,6 +425,7 @@ impl DefPathData { | Ctor | AnonConst | OpaqueTy + | AnonAssocTy | SyntheticCoroutineBody => None, } } @@ -433,14 +433,9 @@ impl DefPathData { pub fn name(&self) -> DefPathDataName { use self::DefPathData::*; match *self { - TypeNs(name) => { - if let Some(name) = name { - DefPathDataName::Named(name) - } else { - DefPathDataName::Anon { namespace: sym::synthetic } - } + TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => { + DefPathDataName::Named(name) } - ValueNs(name) | MacroNs(name) | LifetimeNs(name) => DefPathDataName::Named(name), // Note that this does not show up in user print-outs. CrateRoot => DefPathDataName::Anon { namespace: kw::Crate }, Impl => DefPathDataName::Anon { namespace: kw::Impl }, @@ -451,6 +446,7 @@ impl DefPathData { Ctor => DefPathDataName::Anon { namespace: sym::constructor }, AnonConst => DefPathDataName::Anon { namespace: sym::constant }, OpaqueTy => DefPathDataName::Anon { namespace: sym::opaque }, + AnonAssocTy => DefPathDataName::Anon { namespace: sym::synthetic }, SyntheticCoroutineBody => DefPathDataName::Anon { namespace: sym::synthetic }, } } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 667cc5c3f0eb..2f93197bcef1 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -620,7 +620,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { // the children of the visible parent (as was done when computing // `visible_parent_map`), looking for the specific child we currently have and then // have access to the re-exported name. - DefPathData::TypeNs(Some(ref mut name)) if Some(visible_parent) != actual_parent => { + DefPathData::TypeNs(ref mut name) if Some(visible_parent) != actual_parent => { // Item might be re-exported several times, but filter for the one // that's public and whose identifier isn't `_`. let reexport = self @@ -641,7 +641,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { } // Re-exported `extern crate` (#43189). DefPathData::CrateRoot => { - data = DefPathData::TypeNs(Some(self.tcx().crate_name(def_id.krate))); + data = DefPathData::TypeNs(self.tcx().crate_name(def_id.krate)); } _ => {} } diff --git a/compiler/rustc_middle/src/ty/significant_drop_order.rs b/compiler/rustc_middle/src/ty/significant_drop_order.rs index ce4208f2c445..561f84192b42 100644 --- a/compiler/rustc_middle/src/ty/significant_drop_order.rs +++ b/compiler/rustc_middle/src/ty/significant_drop_order.rs @@ -26,7 +26,7 @@ fn true_significant_drop_ty<'tcx>( name_rev.push(tcx.crate_name(did.krate)); } rustc_hir::definitions::DefPathData::TypeNs(symbol) => { - name_rev.push(symbol.unwrap()); + name_rev.push(symbol); } _ => return None, } diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs index d56ca9c24538..4b1b3903e403 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs @@ -721,7 +721,8 @@ fn encode_ty_name(tcx: TyCtxt<'_>, def_id: DefId) -> String { | hir::definitions::DefPathData::Use | hir::definitions::DefPathData::GlobalAsm | hir::definitions::DefPathData::MacroNs(..) - | hir::definitions::DefPathData::LifetimeNs(..) => { + | hir::definitions::DefPathData::LifetimeNs(..) + | hir::definitions::DefPathData::AnonAssocTy => { bug!("encode_ty_name: unexpected `{:?}`", disambiguated_data.data); } }); diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 8edfd16016c3..d28f10ba9e38 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -858,7 +858,8 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { | DefPathData::GlobalAsm | DefPathData::Impl | DefPathData::MacroNs(_) - | DefPathData::LifetimeNs(_) => { + | DefPathData::LifetimeNs(_) + | DefPathData::AnonAssocTy => { bug!("symbol_names: unexpected DefPathData: {:?}", disambiguated_data.data) } }; diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index b7684e85d412..9520d948f51f 100644 --- a/compiler/rustc_ty_utils/src/assoc.rs +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -252,7 +252,7 @@ fn associated_type_for_impl_trait_in_trait( assert_eq!(tcx.def_kind(trait_def_id), DefKind::Trait); let span = tcx.def_span(opaque_ty_def_id); - // No name because this is a synthetic associated type. + // No name because this is an anonymous associated type. let trait_assoc_ty = tcx.at(span).create_def(trait_def_id, None, DefKind::AssocTy); let local_def_id = trait_assoc_ty.def_id(); @@ -305,7 +305,7 @@ fn associated_type_for_impl_trait_in_impl( hir::FnRetTy::DefaultReturn(_) => tcx.def_span(impl_fn_def_id), hir::FnRetTy::Return(ty) => ty.span, }; - // No name because this is a synthetic associated type. + // No name because this is an anonymous associated type. let impl_assoc_ty = tcx.at(span).create_def(impl_local_def_id, None, DefKind::AssocTy); let local_def_id = impl_assoc_ty.def_id(); diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index bcb0f8349e21..1a6bdf5ca156 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -3502,7 +3502,7 @@ fn maybe_get_relative_path(from: &DefPath, to: &DefPath, max_super: usize) -> St // a::b::c ::d::sym refers to // e::f::sym:: :: // result should be super::super::super::super::e::f - if let DefPathData::TypeNs(Some(s)) = l { + if let DefPathData::TypeNs(s) = l { path.push(s.to_string()); } if let DefPathData::TypeNs(_) = r { @@ -3513,7 +3513,7 @@ fn maybe_get_relative_path(from: &DefPath, to: &DefPath, max_super: usize) -> St // a::b::sym:: :: refers to // c::d::e ::f::sym // when looking at `f` - Left(DefPathData::TypeNs(Some(sym))) => path.push(sym.to_string()), + Left(DefPathData::TypeNs(sym)) => path.push(sym.to_string()), // consider: // a::b::c ::d::sym refers to // e::f::sym:: :: @@ -3527,7 +3527,7 @@ fn maybe_get_relative_path(from: &DefPath, to: &DefPath, max_super: usize) -> St // `super` chain would be too long, just use the absolute path instead once(String::from("crate")) .chain(to.data.iter().filter_map(|el| { - if let DefPathData::TypeNs(Some(sym)) = el.data { + if let DefPathData::TypeNs(sym) = el.data { Some(sym.to_string()) } else { None From 848187cc8a9afe5485958702b2342939d86010f0 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 11 Apr 2025 10:46:03 +0200 Subject: [PATCH 347/606] `local_names` creation to `mbcx` creation --- compiler/rustc_borrowck/src/lib.rs | 40 +++++++++++++++--------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 94c1b54672ac..a38503c2668a 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -304,26 +304,6 @@ fn do_mir_borrowck<'tcx>( root_cx.set_tainted_by_errors(e); } - let mut local_names = IndexVec::from_elem(None, &input_body.local_decls); - for var_debug_info in &input_body.var_debug_info { - if let VarDebugInfoContents::Place(place) = var_debug_info.value { - if let Some(local) = place.as_local() { - if let Some(prev_name) = local_names[local] - && var_debug_info.name != prev_name - { - span_bug!( - var_debug_info.source_info.span, - "local {:?} has many names (`{}` vs `{}`)", - local, - prev_name, - var_debug_info.name - ); - } - local_names[local] = Some(var_debug_info.name); - } - } - } - // Replace all regions with fresh inference variables. This // requires first making our own copy of the MIR. This copy will // be modified (in place) to contain non-lexical lifetimes. It @@ -426,6 +406,26 @@ fn do_mir_borrowck<'tcx>( promoted_mbcx.report_move_errors(); } + let mut local_names = IndexVec::from_elem(None, &body.local_decls); + for var_debug_info in &body.var_debug_info { + if let VarDebugInfoContents::Place(place) = var_debug_info.value { + if let Some(local) = place.as_local() { + if let Some(prev_name) = local_names[local] + && var_debug_info.name != prev_name + { + span_bug!( + var_debug_info.source_info.span, + "local {:?} has many names (`{}` vs `{}`)", + local, + prev_name, + var_debug_info.name + ); + } + local_names[local] = Some(var_debug_info.name); + } + } + } + let mut mbcx = MirBorrowckCtxt { root_cx, infcx: &infcx, From 01864596dc67a753364df1ce2e2c0915401c57ef Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 11 Apr 2025 11:09:27 +0200 Subject: [PATCH 348/606] do not buffer `#[rustc_regions]` dump --- compiler/rustc_borrowck/src/lib.rs | 4 ++-- compiler/rustc_borrowck/src/nll.rs | 7 ++----- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index a38503c2668a..f20bbc3b2673 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -351,12 +351,12 @@ fn do_mir_borrowck<'tcx>( // We also have a `#[rustc_regions]` annotation that causes us to dump // information. - let diags_buffer = &mut BorrowckDiagnosticsBuffer::default(); - nll::dump_annotation(&infcx, body, ®ioncx, &opt_closure_req, diags_buffer); + nll::dump_annotation(&infcx, body, ®ioncx, &opt_closure_req); let movable_coroutine = body.coroutine.is_some() && tcx.coroutine_movability(def.to_def_id()) == hir::Movability::Movable; + let diags_buffer = &mut BorrowckDiagnosticsBuffer::default(); // While promoteds should mostly be correct by construction, we need to check them for // invalid moves to detect moving out of arrays:`struct S; fn main() { &([S][0]); }`. for promoted_body in &promoted { diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 8a2a34f207aa..399417937fdb 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -21,7 +21,7 @@ use tracing::{debug, instrument}; use crate::borrow_set::BorrowSet; use crate::consumers::ConsumerOptions; -use crate::diagnostics::{BorrowckDiagnosticsBuffer, RegionErrors}; +use crate::diagnostics::RegionErrors; use crate::polonius::PoloniusDiagnosticsContext; use crate::polonius::legacy::{ PoloniusFacts, PoloniusFactsExt, PoloniusLocationTable, PoloniusOutput, @@ -297,7 +297,6 @@ pub(super) fn dump_annotation<'tcx, 'infcx>( body: &Body<'tcx>, regioncx: &RegionInferenceContext<'tcx>, closure_region_requirements: &Option>, - diagnostics_buffer: &mut BorrowckDiagnosticsBuffer<'infcx, 'tcx>, ) { let tcx = infcx.tcx; let base_def_id = tcx.typeck_root_def_id(body.source.def_id()); @@ -335,13 +334,11 @@ pub(super) fn dump_annotation<'tcx, 'infcx>( } else { let mut err = infcx.dcx().struct_span_note(def_span, "no external requirements"); regioncx.annotate(tcx, &mut err); - err }; // FIXME(@lcnr): We currently don't dump the inferred hidden types here. - - diagnostics_buffer.buffer_non_error(err); + err.emit(); } fn for_each_region_constraint<'tcx>( From 0e294f2c2f56c688ea14acdeb03f491268f260ac Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 11 Apr 2025 11:18:32 +0200 Subject: [PATCH 349/606] `MirBorrowckCtxt::polonius_output` to ref --- compiler/rustc_borrowck/src/lib.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index f20bbc3b2673..e9b9cdf6e202 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -446,9 +446,9 @@ fn do_mir_borrowck<'tcx>( local_names, region_names: RefCell::default(), next_region_name: RefCell::new(1), - polonius_output, move_errors: Vec::new(), diags_buffer, + polonius_output: polonius_output.as_deref(), polonius_diagnostics: polonius_diagnostics.as_ref(), }; @@ -505,7 +505,6 @@ fn do_mir_borrowck<'tcx>( }; let body_with_facts = if consumer_options.is_some() { - let output_facts = mbcx.polonius_output; Some(Box::new(BodyWithBorrowckFacts { body: body_owned, promoted, @@ -513,7 +512,7 @@ fn do_mir_borrowck<'tcx>( region_inference_context: regioncx, location_table: polonius_input.as_ref().map(|_| location_table), input_facts: polonius_input, - output_facts, + output_facts: polonius_output, })) } else { None @@ -700,12 +699,11 @@ struct MirBorrowckCtxt<'a, 'infcx, 'tcx> { /// The counter for generating new region names. next_region_name: RefCell, - /// Results of Polonius analysis. - polonius_output: Option>, - diags_buffer: &'a mut BorrowckDiagnosticsBuffer<'infcx, 'tcx>, move_errors: Vec>, + /// Results of Polonius analysis. + polonius_output: Option<&'a PoloniusOutput>, /// When using `-Zpolonius=next`: the data used to compute errors and diagnostics. polonius_diagnostics: Option<&'a PoloniusDiagnosticsContext>, } From cfa52e48ae5f35c2d25b0c634010898e20dead68 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 11 Apr 2025 09:20:30 +0000 Subject: [PATCH 350/606] Reuse address-space computation from global alloc --- compiler/rustc_codegen_llvm/src/common.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs index 457e5452ce94..a6f277e4455b 100644 --- a/compiler/rustc_codegen_llvm/src/common.rs +++ b/compiler/rustc_codegen_llvm/src/common.rs @@ -4,8 +4,8 @@ use std::borrow::Borrow; use libc::{c_char, c_uint}; use rustc_abi as abi; +use rustc_abi::HasDataLayout; use rustc_abi::Primitive::Pointer; -use rustc_abi::{AddressSpace, HasDataLayout}; use rustc_ast::Mutability; use rustc_codegen_ssa::common::TypeKind; use rustc_codegen_ssa::traits::*; @@ -269,7 +269,8 @@ impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> { } Scalar::Ptr(ptr, _size) => { let (prov, offset) = ptr.into_parts(); - let (base_addr, base_addr_space) = match self.tcx.global_alloc(prov.alloc_id()) { + let global_alloc = self.tcx.global_alloc(prov.alloc_id()); + let base_addr = match global_alloc { GlobalAlloc::Memory(alloc) => { // For ZSTs directly codegen an aligned pointer. // This avoids generating a zero-sized constant value and actually needing a @@ -301,12 +302,10 @@ impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> { format!("alloc_{hash:032x}").as_bytes(), ); } - (value, AddressSpace::DATA) + value } } - GlobalAlloc::Function { instance, .. } => { - (self.get_fn_addr(instance), self.data_layout().instruction_address_space) - } + GlobalAlloc::Function { instance, .. } => self.get_fn_addr(instance), GlobalAlloc::VTable(ty, dyn_ty) => { let alloc = self .tcx @@ -319,14 +318,15 @@ impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> { .unwrap_memory(); let init = const_alloc_to_llvm(self, alloc, /*static*/ false); let value = self.static_addr_of_impl(init, alloc.inner().align, None); - (value, AddressSpace::DATA) + value } GlobalAlloc::Static(def_id) => { assert!(self.tcx.is_static(def_id)); assert!(!self.tcx.is_thread_local_static(def_id)); - (self.get_static(def_id), AddressSpace::DATA) + self.get_static(def_id) } }; + let base_addr_space = global_alloc.address_space(self); let llval = unsafe { llvm::LLVMConstInBoundsGEP2( self.type_i8(), From 24efefafcbddfba5d26330d33f2516ae04aa454f Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 9 Apr 2025 13:40:00 +0000 Subject: [PATCH 351/606] Avoid a reverse map that is only used in diagnostics paths --- Cargo.lock | 1 - compiler/rustc_data_structures/src/unord.rs | 10 ++++++++++ compiler/rustc_resolve/Cargo.toml | 1 - compiler/rustc_resolve/src/diagnostics.rs | 6 +++--- compiler/rustc_resolve/src/imports.rs | 4 ++-- compiler/rustc_resolve/src/late.rs | 4 ++-- compiler/rustc_resolve/src/lib.rs | 19 +++++++++++++------ compiler/rustc_resolve/src/macros.rs | 4 ++-- 8 files changed, 32 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 901113bbff56..8fbb5e6b972f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4409,7 +4409,6 @@ dependencies = [ "rustc_feature", "rustc_fluent_macro", "rustc_hir", - "rustc_index", "rustc_macros", "rustc_metadata", "rustc_middle", diff --git a/compiler/rustc_data_structures/src/unord.rs b/compiler/rustc_data_structures/src/unord.rs index baa66cd7c852..3d44fb1fd48d 100644 --- a/compiler/rustc_data_structures/src/unord.rs +++ b/compiler/rustc_data_structures/src/unord.rs @@ -109,6 +109,16 @@ impl> UnordItems { pub fn collect>>(self) -> C { self.into() } + + /// If the iterator has only one element, returns it, otherwise returns `None`. + #[track_caller] + pub fn get_only(mut self) -> Option { + let item = self.0.next(); + if self.0.next().is_some() { + return None; + } + item + } } impl UnordItems> { diff --git a/compiler/rustc_resolve/Cargo.toml b/compiler/rustc_resolve/Cargo.toml index 9ea9c58cfd17..0fcc3d8f6b3a 100644 --- a/compiler/rustc_resolve/Cargo.toml +++ b/compiler/rustc_resolve/Cargo.toml @@ -18,7 +18,6 @@ rustc_expand = { path = "../rustc_expand" } rustc_feature = { path = "../rustc_feature" } rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hir = { path = "../rustc_hir" } -rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } rustc_metadata = { path = "../rustc_metadata" } rustc_middle = { path = "../rustc_middle" } diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 56bc826c94f7..363a75911ad4 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -170,10 +170,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { fn report_with_use_injections(&mut self, krate: &Crate) { for UseError { mut err, candidates, def_id, instead, suggestion, path, is_call } in - self.use_injections.drain(..) + std::mem::take(&mut self.use_injections) { let (span, found_use) = if let Some(def_id) = def_id.as_local() { - UsePlacementFinder::check(krate, self.def_id_to_node_id[def_id]) + UsePlacementFinder::check(krate, self.def_id_to_node_id(def_id)) } else { (None, FoundUse::No) }; @@ -1435,7 +1435,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let import_suggestions = self.lookup_import_candidates(ident, Namespace::MacroNS, parent_scope, is_expected); let (span, found_use) = match parent_scope.module.nearest_parent_mod().as_local() { - Some(def_id) => UsePlacementFinder::check(krate, self.def_id_to_node_id[def_id]), + Some(def_id) => UsePlacementFinder::check(krate, self.def_id_to_node_id(def_id)), None => (None, FoundUse::No), }; show_candidates( diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 0b3633a452cb..73676849ecc2 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -641,10 +641,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { if let Some(glob_binding) = resolution.shadowed_glob { let binding_id = match binding.kind { NameBindingKind::Res(res) => { - Some(self.def_id_to_node_id[res.def_id().expect_local()]) + Some(self.def_id_to_node_id(res.def_id().expect_local())) } NameBindingKind::Module(module) => { - Some(self.def_id_to_node_id[module.def_id().expect_local()]) + Some(self.def_id_to_node_id(module.def_id().expect_local())) } NameBindingKind::Import { import, .. } => import.id(), }; diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 1389e8c811eb..73f4da8a7e2f 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -5007,8 +5007,8 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { return false; } let Some(local_did) = did.as_local() else { return true }; - let Some(node_id) = self.r.def_id_to_node_id.get(local_did) else { return true }; - !self.r.proc_macros.contains(node_id) + let node_id = self.r.def_id_to_node_id(local_did); + !self.r.proc_macros.contains(&node_id) } fn resolve_doc_links(&mut self, attrs: &[Attribute], maybe_exported: MaybeExported<'_>) { diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index e1476814d5c0..8877a9e84aec 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -56,7 +56,6 @@ use rustc_hir::def::{ }; use rustc_hir::def_id::{CRATE_DEF_ID, CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalDefIdMap}; use rustc_hir::{PrimTy, TraitCandidate}; -use rustc_index::IndexVec; use rustc_metadata::creader::{CStore, CrateLoader}; use rustc_middle::metadata::ModChild; use rustc_middle::middle::privacy::EffectiveVisibilities; @@ -1184,7 +1183,6 @@ pub struct Resolver<'ra, 'tcx> { next_node_id: NodeId, node_id_to_def_id: NodeMap>, - def_id_to_node_id: IndexVec, /// Indices of unnamed struct or variant fields with unresolved attributes. placeholder_field_indices: FxHashMap, @@ -1369,7 +1367,6 @@ impl<'tcx> Resolver<'_, 'tcx> { debug!("create_def: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id); self.node_id_to_def_id.insert(node_id, feed.downgrade()); } - assert_eq!(self.def_id_to_node_id.push(node_id), def_id); feed } @@ -1385,6 +1382,19 @@ impl<'tcx> Resolver<'_, 'tcx> { pub fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } + + /// This function is very slow, as it iterates over the entire + /// [Resolver::node_id_to_def_id] map just to find the [NodeId] + /// that corresponds to the given [LocalDefId]. Only use this in + /// diagnostics code paths. + fn def_id_to_node_id(&self, def_id: LocalDefId) -> NodeId { + self.node_id_to_def_id + .items() + .filter(|(_, v)| v.key() == def_id) + .map(|(k, _)| *k) + .get_only() + .unwrap() + } } impl<'ra, 'tcx> Resolver<'ra, 'tcx> { @@ -1417,8 +1427,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { &mut Default::default(), ); - let mut def_id_to_node_id = IndexVec::default(); - assert_eq!(def_id_to_node_id.push(CRATE_NODE_ID), CRATE_DEF_ID); let mut node_id_to_def_id = NodeMap::default(); let crate_feed = tcx.create_local_crate_def_id(crate_span); @@ -1553,7 +1561,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { lint_buffer: LintBuffer::default(), next_node_id: CRATE_NODE_ID, node_id_to_def_id, - def_id_to_node_id, placeholder_field_indices: Default::default(), invocation_parents, legacy_const_generic_args: Default::default(), diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index e2f783d887e4..1e744d4a64ed 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -345,7 +345,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { // We already lint the entire macro as unused continue; } - let node_id = self.def_id_to_node_id[def_id]; + let node_id = self.def_id_to_node_id(def_id); self.lint_buffer.buffer_lint( UNUSED_MACRO_RULES, node_id, @@ -932,7 +932,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { .invocation_parents .get(&parent_scope.expansion) .map_or(ast::CRATE_NODE_ID, |parent| { - self.def_id_to_node_id[parent.parent_def] + self.def_id_to_node_id(parent.parent_def) }); self.lint_buffer.buffer_lint( LEGACY_DERIVE_HELPERS, From f5c60f616f13e1267c1eb4df94a5a9c23c18b997 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 11 Apr 2025 09:46:05 +0000 Subject: [PATCH 352/606] Avoid another node_id_to_def_id call --- compiler/rustc_resolve/src/build_reduced_graph.rs | 4 ++-- compiler/rustc_resolve/src/lib.rs | 2 +- compiler/rustc_resolve/src/macros.rs | 8 +++----- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 4368f7882ff4..99c5cadd634e 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -1207,9 +1207,9 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { for (rule_i, rule_span) in &self.r.macro_map[&def_id.to_def_id()].rule_spans { self.r .unused_macro_rules - .entry(def_id) + .entry(node_id) .or_default() - .insert(*rule_i, (ident, *rule_span)); + .insert(*rule_i, (ident, *rule_span, def_id)); } } } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 8877a9e84aec..1815dd7d6c8d 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1140,7 +1140,7 @@ pub struct Resolver<'ra, 'tcx> { ast_transform_scopes: FxHashMap>, unused_macros: FxIndexMap, /// A map from the macro to all its potentially unused arms. - unused_macro_rules: FxIndexMap>, + unused_macro_rules: FxIndexMap>, proc_macro_stubs: FxHashSet, /// Traces collected during macro resolution and validated when it's complete. single_segment_macro_resolutions: diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 1e744d4a64ed..47e5d366107d 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -323,8 +323,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { } fn record_macro_rule_usage(&mut self, id: NodeId, rule_i: usize) { - let did = self.local_def_id(id); - if let Some(rules) = self.unused_macro_rules.get_mut(&did) { + if let Some(rules) = self.unused_macro_rules.get_mut(&id) { rules.remove(&rule_i); } } @@ -339,13 +338,12 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { ); } - for (&def_id, unused_arms) in self.unused_macro_rules.iter() { - for (&arm_i, &(ident, rule_span)) in unused_arms.to_sorted_stable_ord() { + for (&node_id, unused_arms) in self.unused_macro_rules.iter() { + for (&arm_i, &(ident, rule_span, def_id)) in unused_arms.to_sorted_stable_ord() { if self.unused_macros.contains_key(&def_id) { // We already lint the entire macro as unused continue; } - let node_id = self.def_id_to_node_id(def_id); self.lint_buffer.buffer_lint( UNUSED_MACRO_RULES, node_id, From 33a6820c2f3087e1fc5b69a2367b6d3528b767b9 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 11 Apr 2025 09:52:47 +0000 Subject: [PATCH 353/606] Avoid storing the `LocalDefId` twice --- compiler/rustc_resolve/src/build_reduced_graph.rs | 2 +- compiler/rustc_resolve/src/lib.rs | 2 +- compiler/rustc_resolve/src/macros.rs | 8 +++----- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 99c5cadd634e..cb328022c76d 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -1209,7 +1209,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { .unused_macro_rules .entry(node_id) .or_default() - .insert(*rule_i, (ident, *rule_span, def_id)); + .insert(*rule_i, (ident, *rule_span)); } } } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 1815dd7d6c8d..f6d67b67518d 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1140,7 +1140,7 @@ pub struct Resolver<'ra, 'tcx> { ast_transform_scopes: FxHashMap>, unused_macros: FxIndexMap, /// A map from the macro to all its potentially unused arms. - unused_macro_rules: FxIndexMap>, + unused_macro_rules: FxIndexMap>, proc_macro_stubs: FxHashSet, /// Traces collected during macro resolution and validated when it's complete. single_segment_macro_resolutions: diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 47e5d366107d..aee6acd77259 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -336,14 +336,12 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { ident.span, BuiltinLintDiag::UnusedMacroDefinition(ident.name), ); + // Do not report unused individual rules if the entire macro is unused + self.unused_macro_rules.swap_remove(&node_id); } for (&node_id, unused_arms) in self.unused_macro_rules.iter() { - for (&arm_i, &(ident, rule_span, def_id)) in unused_arms.to_sorted_stable_ord() { - if self.unused_macros.contains_key(&def_id) { - // We already lint the entire macro as unused - continue; - } + for (&arm_i, &(ident, rule_span)) in unused_arms.to_sorted_stable_ord() { self.lint_buffer.buffer_lint( UNUSED_MACRO_RULES, node_id, From d35e830aad37912c7d2339c37f084e1894f7141d Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 11 Apr 2025 09:34:29 +0000 Subject: [PATCH 354/606] Avoid a node_id_to_def_id call by just storing DefIds instead of NodeIds --- compiler/rustc_resolve/src/late.rs | 3 +-- compiler/rustc_resolve/src/lib.rs | 4 ++-- compiler/rustc_resolve/src/macros.rs | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 73f4da8a7e2f..a7170edb9867 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -5007,8 +5007,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { return false; } let Some(local_did) = did.as_local() else { return true }; - let node_id = self.r.def_id_to_node_id(local_did); - !self.r.proc_macros.contains(&node_id) + !self.r.proc_macros.contains(&local_did) } fn resolve_doc_links(&mut self, attrs: &[Attribute], maybe_exported: MaybeExported<'_>) { diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index f6d67b67518d..1619a2ef9fe9 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1200,7 +1200,7 @@ pub struct Resolver<'ra, 'tcx> { trait_impls: FxIndexMap>, /// A list of proc macro LocalDefIds, written out in the order in which /// they are declared in the static array generated by proc_macro_harness. - proc_macros: Vec, + proc_macros: Vec, confused_type_with_std_module: FxIndexMap, /// Whether lifetime elision was successful. lifetime_elision_allowed: FxHashSet, @@ -1640,7 +1640,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } pub fn into_outputs(self) -> ResolverOutputs { - let proc_macros = self.proc_macros.iter().map(|id| self.local_def_id(*id)).collect(); + let proc_macros = self.proc_macros; let expn_that_defined = self.expn_that_defined; let extern_crate_map = self.extern_crate_map; let maybe_unused_trait_imports = self.maybe_unused_trait_imports; diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index aee6acd77259..749b7f24c50f 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -462,7 +462,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { } fn declare_proc_macro(&mut self, id: NodeId) { - self.proc_macros.push(id) + self.proc_macros.push(self.local_def_id(id)) } fn append_stripped_cfg_item(&mut self, parent_node: NodeId, ident: Ident, cfg: ast::MetaItem) { From 98d51fb44f4944b8bdad93a529d0625b9998bc93 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 10 Apr 2025 06:42:47 +0000 Subject: [PATCH 355/606] Only compute the `DefId` when a diagnostic is definitely emitted --- compiler/rustc_resolve/src/imports.rs | 44 +++++++++++++-------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 73676849ecc2..3f3b455f4db2 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -639,38 +639,38 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } if let Some(glob_binding) = resolution.shadowed_glob { - let binding_id = match binding.kind { - NameBindingKind::Res(res) => { - Some(self.def_id_to_node_id(res.def_id().expect_local())) - } - NameBindingKind::Module(module) => { - Some(self.def_id_to_node_id(module.def_id().expect_local())) - } - NameBindingKind::Import { import, .. } => import.id(), - }; - if binding.res() != Res::Err && glob_binding.res() != Res::Err && let NameBindingKind::Import { import: glob_import, .. } = glob_binding.kind - && let Some(binding_id) = binding_id && let Some(glob_import_id) = glob_import.id() && let glob_import_def_id = self.local_def_id(glob_import_id) && self.effective_visibilities.is_exported(glob_import_def_id) && glob_binding.vis.is_public() && !binding.vis.is_public() { - self.lint_buffer.buffer_lint( - HIDDEN_GLOB_REEXPORTS, - binding_id, - binding.span, - BuiltinLintDiag::HiddenGlobReexports { - name: key.ident.name.to_string(), - namespace: key.ns.descr().to_owned(), - glob_reexport_span: glob_binding.span, - private_item_span: binding.span, - }, - ); + let binding_id = match binding.kind { + NameBindingKind::Res(res) => { + Some(self.def_id_to_node_id(res.def_id().expect_local())) + } + NameBindingKind::Module(module) => { + Some(self.def_id_to_node_id(module.def_id().expect_local())) + } + NameBindingKind::Import { import, .. } => import.id(), + }; + if let Some(binding_id) = binding_id { + self.lint_buffer.buffer_lint( + HIDDEN_GLOB_REEXPORTS, + binding_id, + binding.span, + BuiltinLintDiag::HiddenGlobReexports { + name: key.ident.name.to_string(), + namespace: key.ns.descr().to_owned(), + glob_reexport_span: glob_binding.span, + private_item_span: binding.span, + }, + ); + } } } } From 2c65469c2751f11e93e3cc5a9b1dcf1856039196 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 11 Apr 2025 11:24:24 +0200 Subject: [PATCH 356/606] move `dump_polonius_mir` --- compiler/rustc_borrowck/src/lib.rs | 18 ++++++++---------- compiler/rustc_borrowck/src/polonius/dump.rs | 2 +- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index e9b9cdf6e202..820952283bd1 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -348,6 +348,14 @@ fn do_mir_borrowck<'tcx>( // Dump MIR results into a file, if that is enabled. This lets us // write unit-tests, as well as helping with debugging. nll::dump_nll_mir(&infcx, body, ®ioncx, &opt_closure_req, &borrow_set); + polonius::dump_polonius_mir( + &infcx, + body, + ®ioncx, + &opt_closure_req, + &borrow_set, + polonius_diagnostics.as_ref(), + ); // We also have a `#[rustc_regions]` annotation that causes us to dump // information. @@ -465,16 +473,6 @@ fn do_mir_borrowck<'tcx>( mbcx.report_move_errors(); - // If requested, dump polonius MIR. - polonius::dump_polonius_mir( - &infcx, - body, - ®ioncx, - &borrow_set, - polonius_diagnostics.as_ref(), - &opt_closure_req, - ); - // For each non-user used mutable variable, check if it's been assigned from // a user-declared local. If so, then put that local into the used_mut set. // Note that this set is expected to be small - only upvars from closures diff --git a/compiler/rustc_borrowck/src/polonius/dump.rs b/compiler/rustc_borrowck/src/polonius/dump.rs index eb53a98832c3..6a943e192082 100644 --- a/compiler/rustc_borrowck/src/polonius/dump.rs +++ b/compiler/rustc_borrowck/src/polonius/dump.rs @@ -24,9 +24,9 @@ pub(crate) fn dump_polonius_mir<'tcx>( infcx: &BorrowckInferCtxt<'tcx>, body: &Body<'tcx>, regioncx: &RegionInferenceContext<'tcx>, + closure_region_requirements: &Option>, borrow_set: &BorrowSet<'tcx>, polonius_diagnostics: Option<&PoloniusDiagnosticsContext>, - closure_region_requirements: &Option>, ) { let tcx = infcx.tcx; if !tcx.sess.opts.unstable_opts.polonius.is_next_enabled() { From c5fdddc7f49c492365eab042f3c392b57cdaa7b3 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 11 Apr 2025 11:40:38 +0200 Subject: [PATCH 357/606] don't rely on `locals_are_invalidated_at_exit` --- compiler/rustc_borrowck/src/lib.rs | 56 +++++++++++++----------------- 1 file changed, 24 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 820952283bd1..1bc69abe6f9f 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -22,6 +22,7 @@ use std::cell::RefCell; use std::marker::PhantomData; use std::ops::{ControlFlow, Deref}; +use borrow_set::LocalsStateAtExit; use root_cx::BorrowCheckRootCtxt; use rustc_abi::FieldIdx; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; @@ -382,7 +383,6 @@ fn do_mir_borrowck<'tcx>( location_table: &location_table, movable_coroutine, fn_self_span_reported: Default::default(), - locals_are_invalidated_at_exit, access_place_error_reported: Default::default(), reservation_error_reported: Default::default(), uninitialized_error_reported: Default::default(), @@ -441,7 +441,6 @@ fn do_mir_borrowck<'tcx>( move_data: &move_data, location_table: &location_table, movable_coroutine, - locals_are_invalidated_at_exit, fn_self_span_reported: Default::default(), access_place_error_reported: Default::default(), reservation_error_reported: Default::default(), @@ -643,13 +642,6 @@ struct MirBorrowckCtxt<'a, 'infcx, 'tcx> { location_table: &'a PoloniusLocationTable, movable_coroutine: bool, - /// This keeps track of whether local variables are free-ed when the function - /// exits even without a `StorageDead`, which appears to be the case for - /// constants. - /// - /// I'm not sure this is the right approach - @eddyb could you try and - /// figure this out? - locals_are_invalidated_at_exit: bool, /// This field keeps track of when borrow errors are reported in the access_place function /// so that there is no duplicate reporting. This field cannot also be used for the conflicting /// borrow errors that is handled by the `reservation_error_reported` field as the inclusion @@ -925,13 +917,20 @@ impl<'a, 'tcx> ResultsVisitor<'a, 'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt< | TerminatorKind::Return | TerminatorKind::TailCall { .. } | TerminatorKind::CoroutineDrop => { - // Returning from the function implicitly kills storage for all locals and statics. - // Often, the storage will already have been killed by an explicit - // StorageDead, but we don't always emit those (notably on unwind paths), - // so this "extra check" serves as a kind of backup. - for i in state.borrows.iter() { - let borrow = &self.borrow_set[i]; - self.check_for_invalidation_at_exit(loc, borrow, span); + match self.borrow_set.locals_state_at_exit() { + LocalsStateAtExit::AllAreInvalidated => { + // Returning from the function implicitly kills storage for all locals and statics. + // Often, the storage will already have been killed by an explicit + // StorageDead, but we don't always emit those (notably on unwind paths), + // so this "extra check" serves as a kind of backup. + for i in state.borrows.iter() { + let borrow = &self.borrow_set[i]; + self.check_for_invalidation_at_exit(loc, borrow, span); + } + } + // If we do not implicitly invalidate all locals on exit, + // we check for conflicts when dropping or moving this local. + LocalsStateAtExit::SomeAreInvalidated { has_storage_dead_or_moved: _ } => {} } } @@ -1703,22 +1702,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { // we'll have a memory leak) and assume that all statics have a destructor. // // FIXME: allow thread-locals to borrow other thread locals? - - let (might_be_alive, will_be_dropped) = - if self.body.local_decls[root_place.local].is_ref_to_thread_local() { - // Thread-locals might be dropped after the function exits - // We have to dereference the outer reference because - // borrows don't conflict behind shared references. - root_place.projection = TyCtxtConsts::DEREF_PROJECTION; - (true, true) - } else { - (false, self.locals_are_invalidated_at_exit) - }; - - if !will_be_dropped { - debug!("place_is_invalidated_at_exit({:?}) - won't be dropped", place); - return; - } + let might_be_alive = if self.body.local_decls[root_place.local].is_ref_to_thread_local() { + // Thread-locals might be dropped after the function exits + // We have to dereference the outer reference because + // borrows don't conflict behind shared references. + root_place.projection = TyCtxtConsts::DEREF_PROJECTION; + true + } else { + false + }; let sd = if might_be_alive { Deep } else { Shallow(None) }; From cdf5b8d4e77d53e13eb7996d1b8d546c2af618a6 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 11 Apr 2025 15:28:09 +1000 Subject: [PATCH 358/606] Change how anonymous associated types are printed. Give them their own symbol `anon_assoc`, as is done for all the other anonymous `DefPathData` variants. --- compiler/rustc_hir/src/definitions.rs | 2 +- compiler/rustc_span/src/symbol.rs | 1 + tests/ui-fulldeps/stable-mir/check_assoc_items.rs | 4 ++-- tests/ui/delegation/unsupported.stderr | 8 ++++---- tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr | 4 ++-- tests/ui/impl-trait/in-trait/dump.rs | 2 +- tests/ui/impl-trait/in-trait/dump.stderr | 2 +- .../impl-trait/in-trait/return-dont-satisfy-bounds.stderr | 4 ++-- .../rfcs/rfc-1937-termination-trait/issue-103052-2.stderr | 4 ++-- 9 files changed, 16 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs index deba21d509fc..34f3c169505f 100644 --- a/compiler/rustc_hir/src/definitions.rs +++ b/compiler/rustc_hir/src/definitions.rs @@ -446,7 +446,7 @@ impl DefPathData { Ctor => DefPathDataName::Anon { namespace: sym::constructor }, AnonConst => DefPathDataName::Anon { namespace: sym::constant }, OpaqueTy => DefPathDataName::Anon { namespace: sym::opaque }, - AnonAssocTy => DefPathDataName::Anon { namespace: sym::synthetic }, + AnonAssocTy => DefPathDataName::Anon { namespace: sym::anon_assoc }, SyntheticCoroutineBody => DefPathDataName::Anon { namespace: sym::synthetic }, } } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 31847ae3b465..44aa7576cd0d 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -454,6 +454,7 @@ symbols! { and_then, anon, anon_adt, + anon_assoc, anonymous_lifetime_in_impl_trait, any, append_const_msg, diff --git a/tests/ui-fulldeps/stable-mir/check_assoc_items.rs b/tests/ui-fulldeps/stable-mir/check_assoc_items.rs index f6f895588f27..f75113676750 100644 --- a/tests/ui-fulldeps/stable-mir/check_assoc_items.rs +++ b/tests/ui-fulldeps/stable-mir/check_assoc_items.rs @@ -51,7 +51,7 @@ fn test_assoc_items() -> ControlFlow<()> { check_items( &trait_assoc_item_defs, &[ - "ATrait::{synthetic#0}", + "ATrait::{anon_assoc#0}", "ATrait::rpitit", "ATrait::Assoc", "ATrait::assoc_fn_no_self", @@ -64,7 +64,7 @@ fn test_assoc_items() -> ControlFlow<()> { check_items( &impl_assoc_item_defs, &[ - "::{synthetic#0}", + "::{anon_assoc#0}", "::rpitit", "::Assoc", "::assoc_fn_no_self", diff --git a/tests/ui/delegation/unsupported.stderr b/tests/ui/delegation/unsupported.stderr index 2b0bcf9d84e8..cb14d9f459a2 100644 --- a/tests/ui/delegation/unsupported.stderr +++ b/tests/ui/delegation/unsupported.stderr @@ -1,4 +1,4 @@ -error[E0391]: cycle detected when computing type of `opaque::::{synthetic#0}` +error[E0391]: cycle detected when computing type of `opaque::::{anon_assoc#0}` --> $DIR/unsupported.rs:22:25 | LL | reuse to_reuse::opaque_ret; @@ -9,7 +9,7 @@ note: ...which requires comparing an impl and trait method signature, inferring | LL | reuse to_reuse::opaque_ret; | ^^^^^^^^^^ - = note: ...which again requires computing type of `opaque::::{synthetic#0}`, completing the cycle + = note: ...which again requires computing type of `opaque::::{anon_assoc#0}`, completing the cycle note: cycle used when checking that `opaque::` is well-formed --> $DIR/unsupported.rs:21:5 | @@ -17,7 +17,7 @@ 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[E0391]: cycle detected when computing type of `opaque::::{synthetic#0}` +error[E0391]: cycle detected when computing type of `opaque::::{anon_assoc#0}` --> $DIR/unsupported.rs:25:24 | LL | reuse ToReuse::opaque_ret; @@ -28,7 +28,7 @@ note: ...which requires comparing an impl and trait method signature, inferring | LL | reuse ToReuse::opaque_ret; | ^^^^^^^^^^ - = note: ...which again requires computing type of `opaque::::{synthetic#0}`, completing the cycle + = note: ...which again requires computing type of `opaque::::{anon_assoc#0}`, completing the cycle note: cycle used when checking that `opaque::` is well-formed --> $DIR/unsupported.rs:24:5 | diff --git a/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr b/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr index fc3efb44ac76..a9dfac274d55 100644 --- a/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr +++ b/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr @@ -6,11 +6,11 @@ LL | fn bar() -> () {} | = help: the trait `std::fmt::Display` is not implemented for `()` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead -note: required by a bound in `Foo::{synthetic#0}` +note: required by a bound in `Foo::{anon_assoc#0}` --> $DIR/doesnt-satisfy.rs:2:22 | LL | fn bar() -> impl std::fmt::Display; - | ^^^^^^^^^^^^^^^^^ required by this bound in `Foo::{synthetic#0}` + | ^^^^^^^^^^^^^^^^^ required by this bound in `Foo::{anon_assoc#0}` error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/in-trait/dump.rs b/tests/ui/impl-trait/in-trait/dump.rs index 20b0e60702fa..da3cfd099b56 100644 --- a/tests/ui/impl-trait/in-trait/dump.rs +++ b/tests/ui/impl-trait/in-trait/dump.rs @@ -8,7 +8,7 @@ trait Foo { } fn hello<'s, T: Foo>(x: &'s T) -> impl Sized + use<'s, T> { -//~^ ERROR ::{synthetic#0}<'s/#1> +//~^ ERROR ::{anon_assoc#0}<'s/#1> x.hello() } diff --git a/tests/ui/impl-trait/in-trait/dump.stderr b/tests/ui/impl-trait/in-trait/dump.stderr index 958058403852..15b6f186ced5 100644 --- a/tests/ui/impl-trait/in-trait/dump.stderr +++ b/tests/ui/impl-trait/in-trait/dump.stderr @@ -1,4 +1,4 @@ -error: ::{synthetic#0}<'s/#1> +error: ::{anon_assoc#0}<'s/#1> --> $DIR/dump.rs:10:35 | LL | fn hello<'s, T: Foo>(x: &'s T) -> impl Sized + use<'s, T> { diff --git a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr index 5cb80386b35f..6571ce2d5f05 100644 --- a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr +++ b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr @@ -14,11 +14,11 @@ LL | fn foo>(self) -> impl Foo { | ^^^^^^^^^^^^ the trait `Foo` is not implemented for `impl Foo` | = help: the trait `Foo` is implemented for `Bar` -note: required by a bound in `Foo::{synthetic#0}` +note: required by a bound in `Foo::{anon_assoc#0}` --> $DIR/return-dont-satisfy-bounds.rs:2:30 | LL | fn foo(self) -> impl Foo; - | ^^^^^^ required by this bound in `Foo::{synthetic#0}` + | ^^^^^^ required by this bound in `Foo::{anon_assoc#0}` error[E0277]: the trait bound `Bar: Foo` is not satisfied --> $DIR/return-dont-satisfy-bounds.rs:8:34 diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr index f1f53e300abf..400969c279e6 100644 --- a/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr +++ b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr @@ -4,11 +4,11 @@ error[E0277]: the trait bound `Something: Termination` is not satisfied LL | fn main() -> Something { | ^^^^^^^^^ the trait `Termination` is not implemented for `Something` | -note: required by a bound in `Main::{synthetic#0}` +note: required by a bound in `Main::{anon_assoc#0}` --> $DIR/issue-103052-2.rs:3:27 | LL | fn main() -> impl std::process::Termination; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Main::{synthetic#0}` + | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Main::{anon_assoc#0}` error: aborting due to 1 previous error From 068a33245981765c3678434d5bcb71bd63d5598a Mon Sep 17 00:00:00 2001 From: Bastian Kersting Date: Fri, 11 Apr 2025 10:15:55 +0000 Subject: [PATCH 359/606] cfi: Remove #[no_sanitize(cfi)] for extern weak functions Previously (https://github.com/rust-lang/rust/pull/115200, https://github.com/rust-lang/rust/pull/138002), we added `#[no_sanitize(cfi)]` to all code paths that call to a weakly linked function. In https://github.com/rust-lang/rust/pull/138349 we fixed the root cause for this issue, which means we can now remove the corresponding attributes. --- library/std/src/sys/fd/unix.rs | 3 --- library/std/src/sys/fs/unix.rs | 14 -------------- library/std/src/sys/pal/unix/thread.rs | 3 --- library/std/src/sys/pal/unix/time.rs | 11 ----------- library/std/src/sys/pal/unix/weak.rs | 3 --- library/std/src/sys/process/unix/unix.rs | 3 --- .../src/sys/thread_local/destructors/linux_like.rs | 3 --- 7 files changed, 40 deletions(-) diff --git a/library/std/src/sys/fd/unix.rs b/library/std/src/sys/fd/unix.rs index 2042ea2c73d0..5765cb1386ab 100644 --- a/library/std/src/sys/fd/unix.rs +++ b/library/std/src/sys/fd/unix.rs @@ -257,9 +257,6 @@ impl FileDesc { } #[cfg(all(target_os = "android", target_pointer_width = "32"))] - // FIXME(#115199): Rust currently omits weak function definitions - // and its metadata from LLVM IR. - #[no_sanitize(cfi)] pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result { weak!( fn preadv64( diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs index 87865be0387d..687fc322e598 100644 --- a/library/std/src/sys/fs/unix.rs +++ b/library/std/src/sys/fs/unix.rs @@ -1463,20 +1463,6 @@ impl File { Ok(()) } - // FIXME(#115199): Rust currently omits weak function definitions - // and its metadata from LLVM IR. - #[cfg_attr( - any( - target_os = "android", - all( - target_os = "linux", - target_env = "gnu", - target_pointer_width = "32", - not(target_arch = "riscv32") - ) - ), - no_sanitize(cfi) - )] pub fn set_times(&self, times: FileTimes) -> io::Result<()> { #[cfg(not(any( target_os = "redox", diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs index 9078dd1c2316..c0662600db1d 100644 --- a/library/std/src/sys/pal/unix/thread.rs +++ b/library/std/src/sys/pal/unix/thread.rs @@ -189,9 +189,6 @@ impl Thread { } #[cfg(any(target_os = "solaris", target_os = "illumos", target_os = "nto"))] - // FIXME(#115199): Rust currently omits weak function definitions - // and its metadata from LLVM IR. - #[no_sanitize(cfi)] pub fn set_name(name: &CStr) { weak!( fn pthread_setname_np( diff --git a/library/std/src/sys/pal/unix/time.rs b/library/std/src/sys/pal/unix/time.rs index b8469b1681f0..0074d7674741 100644 --- a/library/std/src/sys/pal/unix/time.rs +++ b/library/std/src/sys/pal/unix/time.rs @@ -96,17 +96,6 @@ impl Timespec { } } - // FIXME(#115199): Rust currently omits weak function definitions - // and its metadata from LLVM IR. - #[cfg_attr( - all( - target_os = "linux", - target_env = "gnu", - target_pointer_width = "32", - not(target_arch = "riscv32") - ), - no_sanitize(cfi) - )] pub fn now(clock: libc::clockid_t) -> Timespec { use crate::mem::MaybeUninit; use crate::sys::cvt; diff --git a/library/std/src/sys/pal/unix/weak.rs b/library/std/src/sys/pal/unix/weak.rs index e4c814fba8ce..a034995e6525 100644 --- a/library/std/src/sys/pal/unix/weak.rs +++ b/library/std/src/sys/pal/unix/weak.rs @@ -155,9 +155,6 @@ unsafe fn fetch(name: &str) -> *mut libc::c_void { #[cfg(not(any(target_os = "linux", target_os = "android")))] pub(crate) macro syscall { (fn $name:ident($($param:ident : $t:ty),* $(,)?) -> $ret:ty;) => ( - // FIXME(#115199): Rust currently omits weak function definitions - // and its metadata from LLVM IR. - #[no_sanitize(cfi)] unsafe fn $name($($param: $t),*) -> $ret { weak!(fn $name($($param: $t),*) -> $ret;); diff --git a/library/std/src/sys/process/unix/unix.rs b/library/std/src/sys/process/unix/unix.rs index 191a09c8da91..3b04ec50db30 100644 --- a/library/std/src/sys/process/unix/unix.rs +++ b/library/std/src/sys/process/unix/unix.rs @@ -434,9 +434,6 @@ impl Command { target_os = "nto", target_vendor = "apple", ))] - // FIXME(#115199): Rust currently omits weak function definitions - // and its metadata from LLVM IR. - #[cfg_attr(target_os = "linux", no_sanitize(cfi))] fn posix_spawn( &mut self, stdio: &ChildPipes, diff --git a/library/std/src/sys/thread_local/destructors/linux_like.rs b/library/std/src/sys/thread_local/destructors/linux_like.rs index 817941229eef..d7cbaeb89f42 100644 --- a/library/std/src/sys/thread_local/destructors/linux_like.rs +++ b/library/std/src/sys/thread_local/destructors/linux_like.rs @@ -12,9 +12,6 @@ use crate::mem::transmute; -// FIXME: The Rust compiler currently omits weakly function definitions (i.e., -// __cxa_thread_atexit_impl) and its metadata from LLVM IR. -#[no_sanitize(cfi, kcfi)] pub unsafe fn register(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { /// This is necessary because the __cxa_thread_atexit_impl implementation /// std links to by default may be a C or C++ implementation that was not From 49cc8601821b614aa7a245dd37a837ec92192d3a Mon Sep 17 00:00:00 2001 From: LorrensP-2158466 Date: Fri, 11 Apr 2025 13:56:53 +0200 Subject: [PATCH 360/606] fix build fail on macos bacause of libffi-sys 2.3.0; This updates libffi to new major version --- src/tools/miri/Cargo.lock | 8 ++++---- src/tools/miri/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/tools/miri/Cargo.lock b/src/tools/miri/Cargo.lock index bbdcccdc17f2..6f4bd3eab51a 100644 --- a/src/tools/miri/Cargo.lock +++ b/src/tools/miri/Cargo.lock @@ -436,9 +436,9 @@ checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" [[package]] name = "libffi" -version = "3.2.0" +version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce826c243048e3d5cec441799724de52e2d42f820468431fc3fceee2341871e2" +checksum = "4a9434b6fc77375fb624698d5f8c49d7e80b10d59eb1219afda27d1f824d4074" dependencies = [ "libc", "libffi-sys", @@ -446,9 +446,9 @@ dependencies = [ [[package]] name = "libffi-sys" -version = "2.3.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f36115160c57e8529781b4183c2bb51fdc1f6d6d1ed345591d84be7703befb3c" +checksum = "ead36a2496acfc8edd6cc32352110e9478ac5b9b5f5b9856ebd3d28019addb84" dependencies = [ "cc", ] diff --git a/src/tools/miri/Cargo.toml b/src/tools/miri/Cargo.toml index e9ee19b79326..bb24e700e738 100644 --- a/src/tools/miri/Cargo.toml +++ b/src/tools/miri/Cargo.toml @@ -37,7 +37,7 @@ features = ['unprefixed_malloc_on_supported_platforms'] [target.'cfg(unix)'.dependencies] libc = "0.2" -libffi = "3.2.0" +libffi = "4.0.0" libloading = "0.8" [target.'cfg(target_family = "windows")'.dependencies] From 6788ce76c9f66b836a3b6a72d8b6df32627edecc Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Fri, 11 Apr 2025 13:47:52 +0200 Subject: [PATCH 361/606] Remove proc_macro::SourceFile::is_real(). --- .../rustc_expand/src/proc_macro_server.rs | 4 ---- library/proc_macro/src/bridge/mod.rs | 1 - library/proc_macro/src/lib.rs | 21 ++----------------- .../ui/proc-macro/auxiliary/span-api-tests.rs | 12 +---------- tests/ui/proc-macro/span-api-tests.rs | 2 -- 5 files changed, 3 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index ee6306e39610..cd4ea8edd6fd 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -689,10 +689,6 @@ impl server::SourceFile for Rustc<'_, '_> { _ => file.name.prefer_local().to_string(), } } - - fn is_real(&mut self, file: &Self::SourceFile) -> bool { - file.is_real_file() - } } impl server::Span for Rustc<'_, '_> { diff --git a/library/proc_macro/src/bridge/mod.rs b/library/proc_macro/src/bridge/mod.rs index 1b5c221425ec..d76e66521314 100644 --- a/library/proc_macro/src/bridge/mod.rs +++ b/library/proc_macro/src/bridge/mod.rs @@ -86,7 +86,6 @@ macro_rules! with_api { fn clone($self: &$S::SourceFile) -> $S::SourceFile; fn eq($self: &$S::SourceFile, other: &$S::SourceFile) -> bool; fn path($self: &$S::SourceFile) -> String; - fn is_real($self: &$S::SourceFile) -> bool; }, Span { fn debug($self: $S::Span) -> String; diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index f1cf0c5a2db7..17beef2d4702 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -623,36 +623,19 @@ impl SourceFile { /// Gets the path to this source file. /// /// ### Note - /// If the code span associated with this `SourceFile` was generated by an external macro, this - /// macro, this might not be an actual path on the filesystem. Use [`is_real`] to check. /// - /// Also note that even if `is_real` returns `true`, if `--remap-path-prefix` was passed on + /// If `--remap-path-prefix` was passed on /// the command line, the path as given might not actually be valid. - /// - /// [`is_real`]: Self::is_real #[unstable(feature = "proc_macro_span", issue = "54725")] pub fn path(&self) -> PathBuf { PathBuf::from(self.0.path()) } - - /// Returns `true` if this source file is a real source file, and not generated by an external - /// macro's expansion. - #[unstable(feature = "proc_macro_span", issue = "54725")] - pub fn is_real(&self) -> bool { - // This is a hack until intercrate spans are implemented and we can have real source files - // for spans generated in external macros. - // https://github.com/rust-lang/rust/pull/43604#issuecomment-333334368 - self.0.is_real() - } } #[unstable(feature = "proc_macro_span", issue = "54725")] impl fmt::Debug for SourceFile { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("SourceFile") - .field("path", &self.path()) - .field("is_real", &self.is_real()) - .finish() + f.debug_struct("SourceFile").field("path", &self.path()).finish() } } diff --git a/tests/ui/proc-macro/auxiliary/span-api-tests.rs b/tests/ui/proc-macro/auxiliary/span-api-tests.rs index 99db66ed6a94..8853d793943f 100644 --- a/tests/ui/proc-macro/auxiliary/span-api-tests.rs +++ b/tests/ui/proc-macro/auxiliary/span-api-tests.rs @@ -10,21 +10,11 @@ pub fn reemit(input: TokenStream) -> TokenStream { input.to_string().parse().unwrap() } -#[proc_macro] -pub fn assert_fake_source_file(input: TokenStream) -> TokenStream { - for tk in input { - let source_file = tk.span().source_file(); - assert!(!source_file.is_real(), "Source file is real: {:?}", source_file); - } - - "".parse().unwrap() -} - #[proc_macro] pub fn assert_source_file(input: TokenStream) -> TokenStream { for tk in input { let source_file = tk.span().source_file(); - assert!(source_file.is_real(), "Source file is not real: {:?}", source_file); + assert!(!source_file.as_os_str().is_empty(), "No source file for span: {:?}", tk.span()); } "".parse().unwrap() diff --git a/tests/ui/proc-macro/span-api-tests.rs b/tests/ui/proc-macro/span-api-tests.rs index ac42a7ea611a..dd8589735b2e 100644 --- a/tests/ui/proc-macro/span-api-tests.rs +++ b/tests/ui/proc-macro/span-api-tests.rs @@ -8,8 +8,6 @@ extern crate span_test_macros; extern crate span_api_tests; -// FIXME(69775): Investigate `assert_fake_source_file`. - use span_api_tests::{reemit, assert_source_file, macro_stringify}; macro_rules! say_hello { From 9eb6a5446a4e35f48ad22a5b70a74a8badb9fa0d Mon Sep 17 00:00:00 2001 From: Petros Angelatos Date: Thu, 10 Apr 2025 11:09:31 +0300 Subject: [PATCH 362/606] sync::mpsc: add miri reproducer of double free Signed-off-by: Petros Angelatos --- library/std/src/sync/mpmc/list.rs | 5 +++ .../miri/tests/pass/issues/issue-139553.rs | 45 +++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 src/tools/miri/tests/pass/issues/issue-139553.rs diff --git a/library/std/src/sync/mpmc/list.rs b/library/std/src/sync/mpmc/list.rs index d88914f52914..2dd8f41226d6 100644 --- a/library/std/src/sync/mpmc/list.rs +++ b/library/std/src/sync/mpmc/list.rs @@ -213,6 +213,11 @@ impl Channel { .compare_exchange(block, new, Ordering::Release, Ordering::Relaxed) .is_ok() { + // This yield point leaves the channel in a half-initialized state where the + // tail.block pointer is set but the head.block is not. This is used to + // facilitate the test in src/tools/miri/tests/pass/issues/issue-139553.rs + #[cfg(miri)] + crate::thread::yield_now(); self.head.block.store(new, Ordering::Release); block = new; } else { diff --git a/src/tools/miri/tests/pass/issues/issue-139553.rs b/src/tools/miri/tests/pass/issues/issue-139553.rs new file mode 100644 index 000000000000..97cb9e1a8057 --- /dev/null +++ b/src/tools/miri/tests/pass/issues/issue-139553.rs @@ -0,0 +1,45 @@ +//@compile-flags: -Zmiri-preemption-rate=0 -Zmiri-compare-exchange-weak-failure-rate=0 +use std::sync::mpsc::channel; +use std::thread; + +/// This test aims to trigger a race condition that causes a double free in the unbounded channel +/// implementation. The test relies on a particular thread scheduling to happen as annotated by the +/// comments below. +fn main() { + let (s1, r) = channel::(); + let s2 = s1.clone(); + + let t1 = thread::spawn(move || { + // 1. The first action executed is an attempt to send the first value in the channel. This + // will begin to initialize the channel but will stop at a critical momement as + // indicated by the `yield_now()` call in the `start_send` method of the implementation. + let _ = s1.send(42); + // 4. The sender is re-scheduled and it finishes the initialization of the channel by + // setting head.block to the same value as tail.block. It then proceeds to publish its + // value but observes that the channel has already disconnected (due to the concurrent + // call of `discard_all_messages`) and aborts the send. + }); + std::thread::yield_now(); + + // 2. A second sender attempts to send a value while the channel is in a half-initialized + // state. Here, half-initialized means that the `tail.block` pointer points to a valid block + // but `head.block` is still null. This condition is ensured by the yield of step 1. When + // this call returns the channel state has tail.index != head.index, tail.block != NULL, and + // head.block = NULL. + s2.send(42).unwrap(); + // 3. This thread continues with dropping the one and only receiver. When all receivers are + // gone `discard_all_messages` will attempt to drop all currently sent values and + // de-allocate all the blocks. If `tail.block != NULL` but `head.block = NULL` the + // implementation waits for the initializing sender to finish by spinning/yielding. + drop(r); + // 5. This thread is rescheduled and `discard_all_messages` observes the head.block pointer set + // by step 4 and proceeds with deallocation. In the problematic version of the code + // `head.block` is simply read via an `Acquire` load and not swapped with NULL. After this + // call returns the channel state has tail.index = head.index, tail.block = NULL, and + // head.block != NULL. + t1.join().unwrap(); + // 6. The last sender (s1) is dropped here which also attempts to cleanup any data in the + // channel. It observes `tail.index = head.index` and so it doesn't attempt to cleanup any + // messages but it also observes that `head.block != NULL` and attempts to deallocate it. + // This is however already deallocated by `discard_all_messages`, leading to a double free. +} From b9e2ac5c7b1d6bb3b6f5fdfe0819eaf7e95bf7ff Mon Sep 17 00:00:00 2001 From: Petros Angelatos Date: Tue, 8 Apr 2025 22:37:25 +0300 Subject: [PATCH 363/606] sync::mpsc: prevent double free on `Drop` This PR is fixing a regression introduced by #121646 that can lead to a double free when dropping the channel. The details of the bug can be found in the corresponding crossbeam PR https://github.com/crossbeam-rs/crossbeam/pull/1187 Signed-off-by: Petros Angelatos --- library/std/src/sync/mpmc/list.rs | 8 +++++++- src/tools/miri/tests/pass/issues/issue-139553.rs | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/library/std/src/sync/mpmc/list.rs b/library/std/src/sync/mpmc/list.rs index 2dd8f41226d6..1c6acb29e375 100644 --- a/library/std/src/sync/mpmc/list.rs +++ b/library/std/src/sync/mpmc/list.rs @@ -569,9 +569,15 @@ impl Channel { // In that case, just wait until it gets initialized. while block.is_null() { backoff.spin_heavy(); - block = self.head.block.load(Ordering::Acquire); + block = self.head.block.swap(ptr::null_mut(), Ordering::AcqRel); } } + // After this point `head.block` is not modified again and it will be deallocated if it's + // non-null. The `Drop` code of the channel, which runs after this function, also attempts + // to deallocate `head.block` if it's non-null. Therefore this function must maintain the + // invariant that if a deallocation of head.block is attemped then it must also be set to + // NULL. Failing to do so will lead to the Drop code attempting a double free. For this + // reason both reads above do an atomic swap instead of a simple atomic load. unsafe { // Drop all messages between head and tail and deallocate the heap-allocated blocks. diff --git a/src/tools/miri/tests/pass/issues/issue-139553.rs b/src/tools/miri/tests/pass/issues/issue-139553.rs index 97cb9e1a8057..119d589d1ead 100644 --- a/src/tools/miri/tests/pass/issues/issue-139553.rs +++ b/src/tools/miri/tests/pass/issues/issue-139553.rs @@ -38,7 +38,7 @@ fn main() { // call returns the channel state has tail.index = head.index, tail.block = NULL, and // head.block != NULL. t1.join().unwrap(); - // 6. The last sender (s1) is dropped here which also attempts to cleanup any data in the + // 6. The last sender (s2) is dropped here which also attempts to cleanup any data in the // channel. It observes `tail.index = head.index` and so it doesn't attempt to cleanup any // messages but it also observes that `head.block != NULL` and attempts to deallocate it. // This is however already deallocated by `discard_all_messages`, leading to a double free. From 3962069982783ccf183e273a983b0c150c51d504 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Fri, 11 Apr 2025 14:35:00 +0200 Subject: [PATCH 364/606] Replace proc_macro::SourceFile by Span::{file, local_file}. --- .../rustc_expand/src/proc_macro_server.rs | 47 ++++++++------- compiler/rustc_fluent_macro/src/fluent.rs | 3 + library/proc_macro/src/bridge/client.rs | 6 -- library/proc_macro/src/bridge/mod.rs | 10 +--- library/proc_macro/src/bridge/server.rs | 1 - library/proc_macro/src/lib.rs | 60 ++++++------------- tests/ui/proc-macro/auxiliary/expand-expr.rs | 8 +-- .../proc-macro/auxiliary/macro-only-syntax.rs | 2 +- .../ui/proc-macro/auxiliary/span-api-tests.rs | 5 +- tests/ui/proc-macro/span-api-tests.rs | 12 ++-- 10 files changed, 61 insertions(+), 93 deletions(-) diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index cd4ea8edd6fd..0ab779945f21 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -1,5 +1,4 @@ use std::ops::{Bound, Range}; -use std::sync::Arc; use ast::token::IdentIsRaw; use pm::bridge::{ @@ -18,7 +17,7 @@ use rustc_parse::parser::Parser; use rustc_parse::{exp, new_parser_from_source_str, source_str_to_stream, unwrap_or_emit_fatal}; use rustc_session::parse::ParseSess; use rustc_span::def_id::CrateNum; -use rustc_span::{BytePos, FileName, Pos, SourceFile, Span, Symbol, sym}; +use rustc_span::{BytePos, FileName, Pos, Span, Symbol, sym}; use smallvec::{SmallVec, smallvec}; use crate::base::ExtCtxt; @@ -467,7 +466,6 @@ impl<'a, 'b> Rustc<'a, 'b> { impl server::Types for Rustc<'_, '_> { type FreeFunctions = FreeFunctions; type TokenStream = TokenStream; - type SourceFile = Arc; type Span = Span; type Symbol = Symbol; } @@ -673,24 +671,6 @@ impl server::TokenStream for Rustc<'_, '_> { } } -impl server::SourceFile for Rustc<'_, '_> { - fn eq(&mut self, file1: &Self::SourceFile, file2: &Self::SourceFile) -> bool { - Arc::ptr_eq(file1, file2) - } - - fn path(&mut self, file: &Self::SourceFile) -> String { - match &file.name { - FileName::Real(name) => name - .local_path() - .expect("attempting to get a file path in an imported file in `proc_macro::SourceFile::path`") - .to_str() - .expect("non-UTF8 file path in `proc_macro::SourceFile::path`") - .to_string(), - _ => file.name.prefer_local().to_string(), - } - } -} - impl server::Span for Rustc<'_, '_> { fn debug(&mut self, span: Self::Span) -> String { if self.ecx.ecfg.span_debug { @@ -700,8 +680,29 @@ impl server::Span for Rustc<'_, '_> { } } - fn source_file(&mut self, span: Self::Span) -> Self::SourceFile { - self.psess().source_map().lookup_char_pos(span.lo()).file + fn file(&mut self, span: Self::Span) -> String { + self.psess() + .source_map() + .lookup_char_pos(span.lo()) + .file + .name + .prefer_remapped_unconditionaly() + .to_string() + } + + fn local_file(&mut self, span: Self::Span) -> Option { + self.psess() + .source_map() + .lookup_char_pos(span.lo()) + .file + .name + .clone() + .into_local_path() + .map(|p| { + p.to_str() + .expect("non-UTF8 file path in `proc_macro::SourceFile::path`") + .to_string() + }) } fn parent(&mut self, span: Self::Span) -> Option { diff --git a/compiler/rustc_fluent_macro/src/fluent.rs b/compiler/rustc_fluent_macro/src/fluent.rs index b04fd1b48f7a..c96bb48a0368 100644 --- a/compiler/rustc_fluent_macro/src/fluent.rs +++ b/compiler/rustc_fluent_macro/src/fluent.rs @@ -25,7 +25,10 @@ fn invocation_relative_path_to_absolute(span: Span, path: &str) -> PathBuf { path.to_path_buf() } else { // `/a/b/c/foo/bar.rs` contains the current macro invocation + #[cfg(bootstrap)] let mut source_file_path = span.source_file().path(); + #[cfg(not(bootstrap))] + let mut source_file_path = span.local_file().unwrap(); // `/a/b/c/foo/` source_file_path.pop(); // `/a/b/c/foo/../locales/en-US/example.ftl` diff --git a/library/proc_macro/src/bridge/client.rs b/library/proc_macro/src/bridge/client.rs index f6d4825c67b2..e7d547966a5d 100644 --- a/library/proc_macro/src/bridge/client.rs +++ b/library/proc_macro/src/bridge/client.rs @@ -111,12 +111,6 @@ impl Clone for TokenStream { } } -impl Clone for SourceFile { - fn clone(&self) -> Self { - self.clone() - } -} - impl Span { pub(crate) fn def_site() -> Span { Bridge::with(|bridge| bridge.globals.def_site) diff --git a/library/proc_macro/src/bridge/mod.rs b/library/proc_macro/src/bridge/mod.rs index d76e66521314..75d82d746540 100644 --- a/library/proc_macro/src/bridge/mod.rs +++ b/library/proc_macro/src/bridge/mod.rs @@ -81,15 +81,8 @@ macro_rules! with_api { $self: $S::TokenStream ) -> Vec>; }, - SourceFile { - fn drop($self: $S::SourceFile); - fn clone($self: &$S::SourceFile) -> $S::SourceFile; - fn eq($self: &$S::SourceFile, other: &$S::SourceFile) -> bool; - fn path($self: &$S::SourceFile) -> String; - }, Span { fn debug($self: $S::Span) -> String; - fn source_file($self: $S::Span) -> $S::SourceFile; fn parent($self: $S::Span) -> Option<$S::Span>; fn source($self: $S::Span) -> $S::Span; fn byte_range($self: $S::Span) -> Range; @@ -97,6 +90,8 @@ macro_rules! with_api { fn end($self: $S::Span) -> $S::Span; fn line($self: $S::Span) -> usize; fn column($self: $S::Span) -> usize; + fn file($self: $S::Span) -> String; + fn local_file($self: $S::Span) -> Option; fn join($self: $S::Span, other: $S::Span) -> Option<$S::Span>; fn subspan($self: $S::Span, start: Bound, end: Bound) -> Option<$S::Span>; fn resolved_at($self: $S::Span, at: $S::Span) -> $S::Span; @@ -119,7 +114,6 @@ macro_rules! with_api_handle_types { 'owned: FreeFunctions, TokenStream, - SourceFile, 'interned: Span, diff --git a/library/proc_macro/src/bridge/server.rs b/library/proc_macro/src/bridge/server.rs index 97e5a603c3ac..5beda7c3c96e 100644 --- a/library/proc_macro/src/bridge/server.rs +++ b/library/proc_macro/src/bridge/server.rs @@ -82,7 +82,6 @@ with_api_handle_types!(define_server_handles); pub trait Types { type FreeFunctions: 'static; type TokenStream: 'static + Clone; - type SourceFile: 'static + Clone; type Span: 'static + Copy + Eq + Hash; type Symbol: 'static; } diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 17beef2d4702..c46dcebedcab 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -491,12 +491,6 @@ impl Span { Span(bridge::client::Span::mixed_site()) } - /// The original source file into which this span points. - #[unstable(feature = "proc_macro_span", issue = "54725")] - pub fn source_file(&self) -> SourceFile { - SourceFile(self.0.source_file()) - } - /// The `Span` for the tokens in the previous macro expansion from which /// `self` was generated from, if any. #[unstable(feature = "proc_macro_span", issue = "54725")] @@ -546,6 +540,25 @@ impl Span { self.0.column() } + /// The path to the source file in which this span occurs, for display purposes. + /// + /// This might not correspond to a valid file system path. + /// It might be remapped, or might be an artificial path such as `""`. + #[unstable(feature = "proc_macro_span", issue = "54725")] + pub fn file(&self) -> String { + self.0.file() + } + + /// The path to the source file in which this span occurs on disk. + /// + /// This is the actual path on disk. It is unaffected by path remapping. + /// + /// This path should not be embedded in the output of the macro; prefer `file()` instead. + #[unstable(feature = "proc_macro_span", issue = "54725")] + pub fn local_file(&self) -> Option { + self.0.local_file().map(|s| PathBuf::from(s)) + } + /// Creates a new span encompassing `self` and `other`. /// /// Returns `None` if `self` and `other` are from different files. @@ -614,41 +627,6 @@ impl fmt::Debug for Span { } } -/// The source file of a given `Span`. -#[unstable(feature = "proc_macro_span", issue = "54725")] -#[derive(Clone)] -pub struct SourceFile(bridge::client::SourceFile); - -impl SourceFile { - /// Gets the path to this source file. - /// - /// ### Note - /// - /// If `--remap-path-prefix` was passed on - /// the command line, the path as given might not actually be valid. - #[unstable(feature = "proc_macro_span", issue = "54725")] - pub fn path(&self) -> PathBuf { - PathBuf::from(self.0.path()) - } -} - -#[unstable(feature = "proc_macro_span", issue = "54725")] -impl fmt::Debug for SourceFile { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("SourceFile").field("path", &self.path()).finish() - } -} - -#[unstable(feature = "proc_macro_span", issue = "54725")] -impl PartialEq for SourceFile { - fn eq(&self, other: &Self) -> bool { - self.0.eq(&other.0) - } -} - -#[unstable(feature = "proc_macro_span", issue = "54725")] -impl Eq for SourceFile {} - /// A single token or a delimited sequence of token trees (e.g., `[1, (), ..]`). #[stable(feature = "proc_macro_lib2", since = "1.29.0")] #[derive(Clone)] diff --git a/tests/ui/proc-macro/auxiliary/expand-expr.rs b/tests/ui/proc-macro/auxiliary/expand-expr.rs index 78c9fa75d9ff..14efc3c6b9f1 100644 --- a/tests/ui/proc-macro/auxiliary/expand-expr.rs +++ b/tests/ui/proc-macro/auxiliary/expand-expr.rs @@ -3,9 +3,10 @@ extern crate proc_macro; -use proc_macro::*; use std::str::FromStr; +use proc_macro::*; + // Flatten the TokenStream, removing any toplevel `Delimiter::None`s for // comparison. fn flatten(ts: TokenStream) -> Vec { @@ -136,9 +137,8 @@ pub fn check_expand_expr_file(ts: TokenStream) -> TokenStream { .to_string(); assert_eq!(input_t, parse_t); - // Check that the literal matches `Span::call_site().source_file().path()` - let expect_t = - Literal::string(&Span::call_site().source_file().path().to_string_lossy()).to_string(); + // Check that the literal matches `Span::call_site().file()` + let expect_t = Literal::string(&Span::call_site().file()).to_string(); assert_eq!(input_t, expect_t); TokenStream::new() diff --git a/tests/ui/proc-macro/auxiliary/macro-only-syntax.rs b/tests/ui/proc-macro/auxiliary/macro-only-syntax.rs index 4971de284b76..11e1910288ee 100644 --- a/tests/ui/proc-macro/auxiliary/macro-only-syntax.rs +++ b/tests/ui/proc-macro/auxiliary/macro-only-syntax.rs @@ -79,7 +79,7 @@ fn check_useful_span(token: TokenTree, expected_filename: &str) { let span = token.span(); assert!(span.column() < span.end().column()); - let source_path = span.source_file().path(); + let source_path = span.local_file().unwrap(); let filename = source_path.components().last().unwrap(); assert_eq!(filename, Component::Normal(expected_filename.as_ref())); } diff --git a/tests/ui/proc-macro/auxiliary/span-api-tests.rs b/tests/ui/proc-macro/auxiliary/span-api-tests.rs index 8853d793943f..036f2e3ac3f5 100644 --- a/tests/ui/proc-macro/auxiliary/span-api-tests.rs +++ b/tests/ui/proc-macro/auxiliary/span-api-tests.rs @@ -11,10 +11,9 @@ pub fn reemit(input: TokenStream) -> TokenStream { } #[proc_macro] -pub fn assert_source_file(input: TokenStream) -> TokenStream { +pub fn assert_local_file(input: TokenStream) -> TokenStream { for tk in input { - let source_file = tk.span().source_file(); - assert!(!source_file.as_os_str().is_empty(), "No source file for span: {:?}", tk.span()); + assert!(tk.span().local_file().is_some(), "No local file for span: {:?}", tk.span()); } "".parse().unwrap() diff --git a/tests/ui/proc-macro/span-api-tests.rs b/tests/ui/proc-macro/span-api-tests.rs index dd8589735b2e..792859ed05b1 100644 --- a/tests/ui/proc-macro/span-api-tests.rs +++ b/tests/ui/proc-macro/span-api-tests.rs @@ -8,24 +8,24 @@ extern crate span_test_macros; extern crate span_api_tests; -use span_api_tests::{reemit, assert_source_file, macro_stringify}; +use span_api_tests::{reemit, assert_local_file, macro_stringify}; macro_rules! say_hello { ($macname:ident) => ( $macname! { "Hello, world!" }) } -assert_source_file! { "Hello, world!" } +assert_local_file! { "Hello, world!" } -say_hello! { assert_source_file } +say_hello! { assert_local_file } reemit_legacy! { - assert_source_file! { "Hello, world!" } + assert_local_file! { "Hello, world!" } } -say_hello_extern! { assert_source_file } +say_hello_extern! { assert_local_file } reemit! { - assert_source_file! { "Hello, world!" } + assert_local_file! { "Hello, world!" } } fn main() { From 83033838a3d1f6ae073c5e8855452e9d0a201eed Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 11 Apr 2025 12:03:42 +0200 Subject: [PATCH 365/606] remove redundant fields --- .../src/type_check/constraint_conversion.rs | 20 ++++++++----------- .../src/type_check/free_region_relations.rs | 4 ---- compiler/rustc_borrowck/src/type_check/mod.rs | 13 +----------- .../rustc_borrowck/src/universal_regions.rs | 4 ++++ 4 files changed, 13 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index ccb257ae0936..57516565147e 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -21,7 +21,6 @@ use crate::{ClosureOutlivesSubject, ClosureRegionRequirements, ConstraintCategor pub(crate) struct ConstraintConversion<'a, 'tcx> { infcx: &'a InferCtxt<'tcx>, - tcx: TyCtxt<'tcx>, universal_regions: &'a UniversalRegions<'tcx>, /// Each RBP `GK: 'a` is assumed to be true. These encode /// relationships like `T: 'a` that are added via implicit bounds @@ -34,7 +33,6 @@ pub(crate) struct ConstraintConversion<'a, 'tcx> { /// logic expecting to see (e.g.) `ReStatic`, and if we supplied /// our special inference variable there, we would mess that up. region_bound_pairs: &'a RegionBoundPairs<'tcx>, - implicit_region_bound: ty::Region<'tcx>, param_env: ty::ParamEnv<'tcx>, known_type_outlives_obligations: &'a [ty::PolyTypeOutlivesPredicate<'tcx>], locations: Locations, @@ -49,7 +47,6 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { infcx: &'a InferCtxt<'tcx>, universal_regions: &'a UniversalRegions<'tcx>, region_bound_pairs: &'a RegionBoundPairs<'tcx>, - implicit_region_bound: ty::Region<'tcx>, param_env: ty::ParamEnv<'tcx>, known_type_outlives_obligations: &'a [ty::PolyTypeOutlivesPredicate<'tcx>], locations: Locations, @@ -59,10 +56,8 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { ) -> Self { Self { infcx, - tcx: infcx.tcx, universal_regions, region_bound_pairs, - implicit_region_bound, param_env, known_type_outlives_obligations, locations, @@ -96,7 +91,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { // into a vector. These are the regions that we will be // relating to one another. let closure_mapping = &UniversalRegions::closure_mapping( - self.tcx, + self.infcx.tcx, closure_args, closure_requirements.num_external_vids, closure_def_id, @@ -111,7 +106,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { let subject = match outlives_requirement.subject { ClosureOutlivesSubject::Region(re) => closure_mapping[re].into(), ClosureOutlivesSubject::Ty(subject_ty) => { - subject_ty.instantiate(self.tcx, |vid| closure_mapping[vid]).into() + subject_ty.instantiate(self.infcx.tcx, |vid| closure_mapping[vid]).into() } }; @@ -127,14 +122,14 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { predicate: ty::OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>, constraint_category: ConstraintCategory<'tcx>, ) { + let tcx = self.infcx.tcx; debug!("generate: constraints at: {:#?}", self.locations); // Extract out various useful fields we'll need below. let ConstraintConversion { - tcx, infcx, + universal_regions, region_bound_pairs, - implicit_region_bound, known_type_outlives_obligations, .. } = *self; @@ -145,7 +140,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { break; } - if !self.tcx.recursion_limit().value_within_limit(iteration) { + if !tcx.recursion_limit().value_within_limit(iteration) { bug!( "FIXME(-Znext-solver): Overflowed when processing region obligations: {outlives_predicates:#?}" ); @@ -170,10 +165,11 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { ); } + let implicit_region_bound = + ty::Region::new_var(tcx, universal_regions.implicit_region_bound()); // we don't actually use this for anything, but // the `TypeOutlives` code needs an origin. let origin = infer::RelateParamBound(self.span, t1, None); - TypeOutlives::new( &mut *self, tcx, @@ -205,7 +201,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { /// are dealt with during trait solving. fn replace_placeholders_with_nll>>(&mut self, value: T) -> T { if value.has_placeholders() { - fold_regions(self.tcx, value, |r, _| match r.kind() { + fold_regions(self.infcx.tcx, value, |r, _| match r.kind() { ty::RePlaceholder(placeholder) => { self.constraints.placeholder_region(self.infcx, placeholder) } diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs index eaac633b512d..536a27763d29 100644 --- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs +++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs @@ -49,14 +49,12 @@ pub(crate) struct CreateResult<'tcx> { pub(crate) fn create<'tcx>( infcx: &InferCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, - implicit_region_bound: ty::Region<'tcx>, universal_regions: UniversalRegions<'tcx>, constraints: &mut MirTypeckRegionConstraints<'tcx>, ) -> CreateResult<'tcx> { UniversalRegionRelationsBuilder { infcx, param_env, - implicit_region_bound, constraints, universal_regions, region_bound_pairs: Default::default(), @@ -181,7 +179,6 @@ struct UniversalRegionRelationsBuilder<'a, 'tcx> { infcx: &'a InferCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, universal_regions: UniversalRegions<'tcx>, - implicit_region_bound: ty::Region<'tcx>, constraints: &'a mut MirTypeckRegionConstraints<'tcx>, // outputs: @@ -320,7 +317,6 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { self.infcx, &self.universal_regions, &self.region_bound_pairs, - self.implicit_region_bound, param_env, &known_type_outlives_obligations, Locations::All(span), diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index a17dff5d2715..05e0bb3f9f34 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -113,7 +113,6 @@ pub(crate) fn type_check<'a, 'tcx>( move_data: &MoveData<'tcx>, location_map: Rc, ) -> MirTypeckResults<'tcx> { - let implicit_region_bound = ty::Region::new_var(infcx.tcx, universal_regions.fr_fn_body); let mut constraints = MirTypeckRegionConstraints { placeholder_indices: PlaceholderIndices::default(), placeholder_index_to_region: IndexVec::default(), @@ -129,13 +128,7 @@ pub(crate) fn type_check<'a, 'tcx>( region_bound_pairs, normalized_inputs_and_output, known_type_outlives_obligations, - } = free_region_relations::create( - infcx, - infcx.param_env, - implicit_region_bound, - universal_regions, - &mut constraints, - ); + } = free_region_relations::create(infcx, infcx.param_env, universal_regions, &mut constraints); let pre_obligations = infcx.take_registered_region_obligations(); assert!( @@ -160,7 +153,6 @@ pub(crate) fn type_check<'a, 'tcx>( user_type_annotations: &body.user_type_annotations, region_bound_pairs, known_type_outlives_obligations, - implicit_region_bound, reported_errors: Default::default(), universal_regions: &universal_region_relations.universal_regions, location_table, @@ -226,7 +218,6 @@ struct TypeChecker<'a, 'tcx> { user_type_annotations: &'a CanonicalUserTypeAnnotations<'tcx>, region_bound_pairs: RegionBoundPairs<'tcx>, known_type_outlives_obligations: Vec>, - implicit_region_bound: ty::Region<'tcx>, reported_errors: FxIndexSet<(Ty<'tcx>, Span)>, universal_regions: &'a UniversalRegions<'tcx>, location_table: &'a PoloniusLocationTable, @@ -422,7 +413,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.infcx, self.universal_regions, &self.region_bound_pairs, - self.implicit_region_bound, self.infcx.param_env, &self.known_type_outlives_obligations, locations, @@ -2507,7 +2497,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.infcx, self.universal_regions, &self.region_bound_pairs, - self.implicit_region_bound, self.infcx.param_env, &self.known_type_outlives_obligations, locations, diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 5c57ab99a859..c11e14d214c4 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -438,6 +438,10 @@ impl<'tcx> UniversalRegions<'tcx> { } } + pub(crate) fn implicit_region_bound(&self) -> RegionVid { + self.fr_fn_body + } + pub(crate) fn tainted_by_errors(&self) -> Option { self.indices.tainted_by_errors.get() } From 5d0048303c98ad5226cd84f2132d21be3c6171c0 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 11 Apr 2025 12:04:48 +0200 Subject: [PATCH 366/606] `NonGenericOpaqueTypeParam::ty` to `arg` --- compiler/rustc_trait_selection/messages.ftl | 4 ++-- compiler/rustc_trait_selection/src/errors.rs | 2 +- compiler/rustc_trait_selection/src/opaque_types.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_trait_selection/messages.ftl b/compiler/rustc_trait_selection/messages.ftl index 05bbb42fb7c6..74e38f525c8e 100644 --- a/compiler/rustc_trait_selection/messages.ftl +++ b/compiler/rustc_trait_selection/messages.ftl @@ -268,8 +268,8 @@ trait_selection_oc_type_compat = type not compatible with trait trait_selection_opaque_captures_lifetime = hidden type for `{$opaque_ty}` captures lifetime that does not appear in bounds .label = opaque type defined here trait_selection_opaque_type_non_generic_param = - expected generic {$kind} parameter, found `{$ty}` - .label = {STREQ($ty, "'static") -> + expected generic {$kind} parameter, found `{$arg}` + .label = {STREQ($arg, "'static") -> [true] cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type *[other] this generic parameter must be used with a generic {$kind} parameter } diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index bb4aba9d29e4..4e5581fb1da0 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -1926,7 +1926,7 @@ impl Subdiagnostic for AddPreciseCapturingForOvercapture { #[derive(Diagnostic)] #[diag(trait_selection_opaque_type_non_generic_param, code = E0792)] pub(crate) struct NonGenericOpaqueTypeParam<'a, 'tcx> { - pub ty: GenericArg<'tcx>, + pub arg: GenericArg<'tcx>, pub kind: &'a str, #[primary_span] pub span: Span, diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index 309bf4dda3d8..cce67b066dde 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -70,7 +70,7 @@ pub fn check_opaque_type_parameter_valid<'tcx>( opaque_env.param_is_error(i)?; return Err(infcx.dcx().emit_err(NonGenericOpaqueTypeParam { - ty: arg, + arg, kind, span, param_span: tcx.def_span(opaque_param.def_id), From 420390c8489c7d95320a4394beeaa6e4170e3258 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 11 Apr 2025 12:49:55 +0200 Subject: [PATCH 367/606] eagerly initialize `definitions` in sub-fn --- compiler/rustc_borrowck/src/nll.rs | 14 +----- .../rustc_borrowck/src/region_infer/mod.rs | 43 ++++++++++--------- 2 files changed, 25 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 399417937fdb..fe899bb054fa 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -117,11 +117,6 @@ pub(crate) fn compute_regions<'a, 'tcx>( Rc::clone(&location_map), ); - // Create the region inference context, taking ownership of the - // region inference data that was contained in `infcx`, and the - // base constraints generated by the type-check. - let var_infos = infcx.get_region_var_infos(); - // If requested, emit legacy polonius facts. polonius::legacy::emit_facts( &mut polonius_facts, @@ -134,13 +129,8 @@ pub(crate) fn compute_regions<'a, 'tcx>( &constraints, ); - let mut regioncx = RegionInferenceContext::new( - infcx, - var_infos, - constraints, - universal_region_relations, - location_map, - ); + let mut regioncx = + RegionInferenceContext::new(infcx, constraints, universal_region_relations, location_map); // If requested for `-Zpolonius=next`, convert NLL constraints to localized outlives constraints // and use them to compute loan liveness. diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 569c46e6403f..c82c7341f028 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -9,7 +9,7 @@ use rustc_errors::Diag; use rustc_hir::def_id::CRATE_DEF_ID; use rustc_index::IndexVec; use rustc_infer::infer::outlives::test_type_match; -use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound, VerifyIfEq}; +use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound, VerifyIfEq}; use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin}; use rustc_middle::bug; use rustc_middle::mir::{ @@ -145,7 +145,7 @@ pub struct RegionInferenceContext<'tcx> { /// variables are identified by their index (`RegionVid`). The /// definition contains information about where the region came /// from as well as its final inferred value. - pub(crate) definitions: IndexVec>, + pub(crate) definitions: Frozen>>, /// The liveness constraints added to each region. For most /// regions, these start out empty and steadily grow, though for @@ -385,6 +385,26 @@ fn sccs_info<'tcx>(infcx: &BorrowckInferCtxt<'tcx>, sccs: &ConstraintSccs) { debug!("SCC edges {:#?}", scc_node_to_edges); } +fn create_definitions<'tcx>( + infcx: &BorrowckInferCtxt<'tcx>, + universal_regions: &UniversalRegions<'tcx>, +) -> Frozen>> { + // Create a RegionDefinition for each inference variable. + let mut definitions: IndexVec<_, _> = infcx + .get_region_var_infos() + .iter() + .map(|info| RegionDefinition::new(info.universe, info.origin)) + .collect(); + + // Add the external name for all universal regions. + for (external_name, variable) in universal_regions.named_universal_regions_iter() { + debug!("region {variable:?} has external name {external_name:?}"); + definitions[variable].external_name = Some(external_name); + } + + Frozen::freeze(definitions) +} + impl<'tcx> RegionInferenceContext<'tcx> { /// Creates a new region inference context with a total of /// `num_region_variables` valid inference variables; the first N @@ -395,7 +415,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// of constraints produced by the MIR type check. pub(crate) fn new( infcx: &BorrowckInferCtxt<'tcx>, - var_infos: VarInfos, constraints: MirTypeckRegionConstraints<'tcx>, universal_region_relations: Frozen>, location_map: Rc, @@ -426,11 +445,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { infcx.set_tainted_by_errors(guar); } - // Create a RegionDefinition for each inference variable. - let definitions: IndexVec<_, _> = var_infos - .iter() - .map(|info| RegionDefinition::new(info.universe, info.origin)) - .collect(); + let definitions = create_definitions(infcx, &universal_regions); let constraint_sccs = outlives_constraints.add_outlives_static(&universal_regions, &definitions); @@ -526,18 +541,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// means that the `R1: !1` constraint here will cause /// `R1` to become `'static`. fn init_free_and_bound_regions(&mut self) { - // Update the names (if any) - // This iterator has unstable order but we collect it all into an IndexVec - for (external_name, variable) in - self.universal_region_relations.universal_regions.named_universal_regions_iter() - { - debug!( - "init_free_and_bound_regions: region {:?} has external name {:?}", - variable, external_name - ); - self.definitions[variable].external_name = Some(external_name); - } - for variable in self.definitions.indices() { let scc = self.constraint_sccs.scc(variable); From 5113f5e6025a0742524aece5d69c87ef4257d338 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Fri, 11 Apr 2025 15:29:46 +0200 Subject: [PATCH 368/606] Update rust-analyzer for new proc_macro span api. --- .../src/server_impl/rust_analyzer_span.rs | 29 +++++-------------- .../src/server_impl/token_id.rs | 22 ++++---------- 2 files changed, 13 insertions(+), 38 deletions(-) diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs index 59293ee3f965..80f6d85a3d05 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs @@ -11,7 +11,7 @@ use std::{ use intern::Symbol; use proc_macro::bridge::{self, server}; -use span::{FileId, Span, FIXUP_ERASED_FILE_AST_ID_MARKER}; +use span::{Span, FIXUP_ERASED_FILE_AST_ID_MARKER}; use tt::{TextRange, TextSize}; use crate::server_impl::{literal_kind_to_internal, token_stream::TokenStreamBuilder, TopSubtree}; @@ -27,10 +27,6 @@ mod tt { type TokenStream = crate::server_impl::TokenStream; -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub struct SourceFile { - file_id: FileId, -} pub struct FreeFunctions; pub struct RaSpanServer { @@ -46,7 +42,6 @@ pub struct RaSpanServer { impl server::Types for RaSpanServer { type FreeFunctions = FreeFunctions; type TokenStream = TokenStream; - type SourceFile = SourceFile; type Span = Span; type Symbol = Symbol; } @@ -245,25 +240,17 @@ impl server::TokenStream for RaSpanServer { } } -impl server::SourceFile for RaSpanServer { - fn eq(&mut self, file1: &Self::SourceFile, file2: &Self::SourceFile) -> bool { - file1 == file2 - } - fn path(&mut self, _file: &Self::SourceFile) -> String { - // FIXME - String::new() - } - fn is_real(&mut self, _file: &Self::SourceFile) -> bool { - true - } -} - impl server::Span for RaSpanServer { fn debug(&mut self, span: Self::Span) -> String { format!("{:?}", span) } - fn source_file(&mut self, span: Self::Span) -> Self::SourceFile { - SourceFile { file_id: span.anchor.file_id.file_id() } + fn file(&mut self, _: Self::Span) -> String { + // FIXME + String::new() + } + fn local_file(&mut self, _: Self::Span) -> Option { + // FIXME + None } fn save_span(&mut self, _span: Self::Span) -> usize { // FIXME, quote is incompatible with third-party tools diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs index 409cf3cc7813..4d7c7c46766b 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs @@ -24,8 +24,6 @@ type Literal = tt::Literal; type Span = tt::TokenId; type TokenStream = crate::server_impl::TokenStream; -#[derive(Clone)] -pub struct SourceFile; pub struct FreeFunctions; pub struct TokenIdServer { @@ -37,7 +35,6 @@ pub struct TokenIdServer { impl server::Types for TokenIdServer { type FreeFunctions = FreeFunctions; type TokenStream = TokenStream; - type SourceFile = SourceFile; type Span = Span; type Symbol = Symbol; } @@ -223,24 +220,15 @@ impl server::TokenStream for TokenIdServer { } } -impl server::SourceFile for TokenIdServer { - fn eq(&mut self, _file1: &Self::SourceFile, _file2: &Self::SourceFile) -> bool { - true - } - fn path(&mut self, _file: &Self::SourceFile) -> String { - String::new() - } - fn is_real(&mut self, _file: &Self::SourceFile) -> bool { - true - } -} - impl server::Span for TokenIdServer { fn debug(&mut self, span: Self::Span) -> String { format!("{:?}", span.0) } - fn source_file(&mut self, _span: Self::Span) -> Self::SourceFile { - SourceFile {} + fn file(&mut self, _span: Self::Span) -> String { + String::new() + } + fn local_file(&mut self, _span: Self::Span) -> Option { + None } fn save_span(&mut self, _span: Self::Span) -> usize { 0 From dc0fbcab7e0673afe62b3e8e74905d9e5f5b74a4 Mon Sep 17 00:00:00 2001 From: Jesus Checa Hidalgo Date: Fri, 11 Apr 2025 16:57:38 +0200 Subject: [PATCH 369/606] Fix profiler_builtins build script to handle full path to profiler lib LLVM_PROFILER_RT_LIB may be set to an absolute path (e.g., in Fedora builds), but `-l` expects a library name, not a path. After #138273, this caused builds to fail with a "could not find native static library" error. This patch updates the build script to split the path into directory and filename, using `cargo::rustc-link-search` for the directory and `cargo::rustc-link-lib=+verbatim` for the file. This allows profiler_builtins to correctly link the static library even when an absolute path is provided. --- library/profiler_builtins/build.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/library/profiler_builtins/build.rs b/library/profiler_builtins/build.rs index dd85239fa8cf..fc1a9ecc1ec3 100644 --- a/library/profiler_builtins/build.rs +++ b/library/profiler_builtins/build.rs @@ -9,8 +9,14 @@ use std::path::PathBuf; fn main() { if let Ok(rt) = tracked_env_var("LLVM_PROFILER_RT_LIB") { - println!("cargo::rustc-link-lib=static:+verbatim={rt}"); - return; + let rt = PathBuf::from(rt); + if let Some(lib) = rt.file_name() { + if let Some(dir) = rt.parent() { + println!("cargo::rustc-link-search=native={}", dir.display()); + } + println!("cargo::rustc-link-lib=static:+verbatim={}", lib.to_str().unwrap()); + return; + } } let target_os = env::var("CARGO_CFG_TARGET_OS").expect("CARGO_CFG_TARGET_OS was not set"); From 17d412439ad883bc52730cad194088246d557752 Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Fri, 11 Apr 2025 17:55:25 +0200 Subject: [PATCH 370/606] Update library/core/src/fmt/rt.rs --- library/core/src/fmt/rt.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/library/core/src/fmt/rt.rs b/library/core/src/fmt/rt.rs index 05e024b134d1..702aa7e34369 100644 --- a/library/core/src/fmt/rt.rs +++ b/library/core/src/fmt/rt.rs @@ -72,7 +72,6 @@ macro_rules! argument_new { // a `fn(&T, ...)`, so the invariant is maintained. ty: ArgumentType::Placeholder { value: NonNull::<$t>::from_ref($x).cast(), - // SAFETY: function pointers always have the same layout. formatter: |ptr: NonNull<()>, fmt: &mut Formatter<'_>| { let func = $f; // SAFETY: This is the same type as the `value` field. From ac45a672979b28670cf2e5de5afbb0b1fb42c0b2 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Fri, 4 Apr 2025 09:58:55 +0000 Subject: [PATCH 371/606] Use delayed bug for normalization errors in drop elaboration Normalization can fail from errors from other items so use a delayed bug instead of checking the body. --- .../rustc_mir_transform/src/elaborate_drop.rs | 11 ++--- .../drop/drop_elaboration_with_errors2.rs} | 6 ++- .../drop/drop_elaboration_with_errors2.stderr | 47 +++++++++++++++++++ .../drop/drop_elaboration_with_errors3.rs} | 8 +++- .../drop/drop_elaboration_with_errors3.stderr | 8 ++++ 5 files changed, 70 insertions(+), 10 deletions(-) rename tests/{crashes/137287.rs => ui/drop/drop_elaboration_with_errors2.rs} (68%) create mode 100644 tests/ui/drop/drop_elaboration_with_errors2.stderr rename tests/{crashes/135668.rs => ui/drop/drop_elaboration_with_errors3.rs} (87%) create mode 100644 tests/ui/drop/drop_elaboration_with_errors3.stderr diff --git a/compiler/rustc_mir_transform/src/elaborate_drop.rs b/compiler/rustc_mir_transform/src/elaborate_drop.rs index 0d8cf524661c..fa476f961235 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drop.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drop.rs @@ -266,19 +266,16 @@ where let tcx = self.tcx(); assert_eq!(self.elaborator.typing_env().typing_mode, ty::TypingMode::PostAnalysis); - // The type error for normalization may have been in dropck: see - // `compute_drop_data` in rustc_borrowck, in which case we wouldn't have - // deleted the MIR body and could have an error here as well. let field_ty = match tcx .try_normalize_erasing_regions(self.elaborator.typing_env(), f.ty(tcx, args)) { Ok(t) => t, Err(_) => Ty::new_error( self.tcx(), - self.elaborator - .body() - .tainted_by_errors - .expect("Error in drop elaboration not found by dropck."), + self.tcx().dcx().span_delayed_bug( + self.elaborator.body().span, + "Error normalizing in drop elaboration.", + ), ), }; diff --git a/tests/crashes/137287.rs b/tests/ui/drop/drop_elaboration_with_errors2.rs similarity index 68% rename from tests/crashes/137287.rs rename to tests/ui/drop/drop_elaboration_with_errors2.rs index 59fdf568d368..946c253179cb 100644 --- a/tests/crashes/137287.rs +++ b/tests/ui/drop/drop_elaboration_with_errors2.rs @@ -1,11 +1,14 @@ -//@ known-bug: #137287 +// Regression test for #137287 mod defining_scope { use super::*; pub type Alias = impl Sized; + //~^ ERROR unconstrained opaque type + //~| ERROR `impl Trait` in type aliases is unstable pub fn cast(x: Container, T>) -> Container { x + //~^ ERROR mismatched types } } @@ -21,6 +24,7 @@ impl Trait for T { type Assoc = Box; } impl Trait for defining_scope::Alias { + //~^ ERROR conflicting implementations of trait `Trait<_>` type Assoc = usize; } diff --git a/tests/ui/drop/drop_elaboration_with_errors2.stderr b/tests/ui/drop/drop_elaboration_with_errors2.stderr new file mode 100644 index 000000000000..15fe3f6ecc1f --- /dev/null +++ b/tests/ui/drop/drop_elaboration_with_errors2.stderr @@ -0,0 +1,47 @@ +error[E0658]: `impl Trait` in type aliases is unstable + --> $DIR/drop_elaboration_with_errors2.rs:5:25 + | +LL | pub type Alias = impl Sized; + | ^^^^^^^^^^ + | + = note: see issue #63063 for more information + = help: add `#![feature(type_alias_impl_trait)]` 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[E0119]: conflicting implementations of trait `Trait<_>` + --> $DIR/drop_elaboration_with_errors2.rs:26:1 + | +LL | impl Trait for T { + | ---------------------- first implementation here +... +LL | impl Trait for defining_scope::Alias { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation + +error: unconstrained opaque type + --> $DIR/drop_elaboration_with_errors2.rs:5:25 + | +LL | pub type Alias = impl Sized; + | ^^^^^^^^^^ + | + = note: `Alias` must be used in combination with a concrete type within the same crate + +error[E0308]: mismatched types + --> $DIR/drop_elaboration_with_errors2.rs:10:9 + | +LL | pub type Alias = impl Sized; + | ---------- the found opaque type +... +LL | pub fn cast(x: Container, T>) -> Container { + | - expected this type parameter --------------- expected `Container` because of return type +LL | x + | ^ expected `Container`, found `Container, T>` + | + = note: expected struct `Container` + found struct `Container, _>` + = help: type parameters must be constrained to match other types + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0119, E0308, E0658. +For more information about an error, try `rustc --explain E0119`. diff --git a/tests/crashes/135668.rs b/tests/ui/drop/drop_elaboration_with_errors3.rs similarity index 87% rename from tests/crashes/135668.rs rename to tests/ui/drop/drop_elaboration_with_errors3.rs index 00d7b5db0c67..c5ed63eb7ac2 100644 --- a/tests/crashes/135668.rs +++ b/tests/ui/drop/drop_elaboration_with_errors3.rs @@ -1,5 +1,6 @@ -//@ known-bug: #135668 +// Regression test for #135668 //@ edition: 2021 + use std::future::Future; pub async fn foo() { @@ -11,7 +12,8 @@ async fn create_task() -> impl Sized { } async fn documentation() { - include_str!("nonexistent"); + compile_error!("bonjour"); + //~^ ERROR bonjour } fn bind(_filter: F) -> impl Sized @@ -36,3 +38,5 @@ where { type Assoc = F; } + +fn main() {} diff --git a/tests/ui/drop/drop_elaboration_with_errors3.stderr b/tests/ui/drop/drop_elaboration_with_errors3.stderr new file mode 100644 index 000000000000..2d44e7c66259 --- /dev/null +++ b/tests/ui/drop/drop_elaboration_with_errors3.stderr @@ -0,0 +1,8 @@ +error: bonjour + --> $DIR/drop_elaboration_with_errors3.rs:15:5 + | +LL | compile_error!("bonjour"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + From b613e9781a773232f81af9f61a8c8ac34b04873a Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Fri, 11 Apr 2025 16:15:34 +0000 Subject: [PATCH 372/606] Use with_native_path for Windows Also add a WCStr type --- library/std/src/sys/fs/mod.rs | 30 +++++++++---- library/std/src/sys/fs/windows.rs | 69 +++++++++++++---------------- library/std/src/sys/path/windows.rs | 34 ++++++++++++++ 3 files changed, 86 insertions(+), 47 deletions(-) diff --git a/library/std/src/sys/fs/mod.rs b/library/std/src/sys/fs/mod.rs index 3b176d0d16c4..4c5e36ce67a3 100644 --- a/library/std/src/sys/fs/mod.rs +++ b/library/std/src/sys/fs/mod.rs @@ -20,6 +20,7 @@ cfg_if::cfg_if! { mod windows; use windows as imp; pub use windows::{symlink_inner, junction_point}; + use crate::sys::path::with_native_path; } else if #[cfg(target_os = "hermit")] { mod hermit; use hermit as imp; @@ -39,7 +40,7 @@ cfg_if::cfg_if! { } // FIXME: Replace this with platform-specific path conversion functions. -#[cfg(not(target_family = "unix"))] +#[cfg(not(any(target_family = "unix", target_os = "windows")))] #[inline] pub fn with_native_path(path: &Path, f: &dyn Fn(&Path) -> io::Result) -> io::Result { f(path) @@ -51,7 +52,7 @@ pub use imp::{ }; pub fn read_dir(path: &Path) -> io::Result { - // FIXME: use with_native_path + // FIXME: use with_native_path on all platforms imp::readdir(path) } @@ -68,8 +69,11 @@ pub fn remove_dir(path: &Path) -> io::Result<()> { } pub fn remove_dir_all(path: &Path) -> io::Result<()> { - // FIXME: use with_native_path - imp::remove_dir_all(path) + // FIXME: use with_native_path on all platforms + #[cfg(not(windows))] + return imp::remove_dir_all(path); + #[cfg(windows)] + with_native_path(path, &imp::remove_dir_all) } pub fn read_link(path: &Path) -> io::Result { @@ -77,6 +81,10 @@ pub fn read_link(path: &Path) -> io::Result { } pub fn symlink(original: &Path, link: &Path) -> io::Result<()> { + // FIXME: use with_native_path on all platforms + #[cfg(windows)] + return imp::symlink(original, link); + #[cfg(not(windows))] with_native_path(original, &|original| { with_native_path(link, &|link| imp::symlink(original, link)) }) @@ -105,11 +113,17 @@ pub fn canonicalize(path: &Path) -> io::Result { } pub fn copy(from: &Path, to: &Path) -> io::Result { - // FIXME: use with_native_path - imp::copy(from, to) + // FIXME: use with_native_path on all platforms + #[cfg(not(windows))] + return imp::copy(from, to); + #[cfg(windows)] + with_native_path(from, &|from| with_native_path(to, &|to| imp::copy(from, to))) } pub fn exists(path: &Path) -> io::Result { - // FIXME: use with_native_path - imp::exists(path) + // FIXME: use with_native_path on all platforms + #[cfg(not(windows))] + return imp::exists(path); + #[cfg(windows)] + with_native_path(path, &imp::exists) } diff --git a/library/std/src/sys/fs/windows.rs b/library/std/src/sys/fs/windows.rs index 15727c996837..9215f9375671 100644 --- a/library/std/src/sys/fs/windows.rs +++ b/library/std/src/sys/fs/windows.rs @@ -12,7 +12,7 @@ use crate::sync::Arc; use crate::sys::handle::Handle; use crate::sys::pal::api::{self, WinError, set_file_information_by_handle}; use crate::sys::pal::{IoResult, fill_utf16_buf, to_u16s, truncate_utf16_at_nul}; -use crate::sys::path::maybe_verbatim; +use crate::sys::path::{WCStr, maybe_verbatim}; use crate::sys::time::SystemTime; use crate::sys::{Align8, c, cvt}; use crate::sys_common::{AsInner, FromInner, IntoInner}; @@ -298,10 +298,12 @@ impl OpenOptions { impl File { pub fn open(path: &Path, opts: &OpenOptions) -> io::Result { let path = maybe_verbatim(path)?; + // SAFETY: maybe_verbatim returns null-terminated strings + let path = unsafe { WCStr::from_wchars_with_null_unchecked(&path) }; Self::open_native(&path, opts) } - fn open_native(path: &[u16], opts: &OpenOptions) -> io::Result { + fn open_native(path: &WCStr, opts: &OpenOptions) -> io::Result { let creation = opts.get_creation_mode()?; let handle = unsafe { c::CreateFileW( @@ -1212,9 +1214,8 @@ pub fn readdir(p: &Path) -> io::Result { } } -pub fn unlink(p: &Path) -> io::Result<()> { - let p_u16s = maybe_verbatim(p)?; - if unsafe { c::DeleteFileW(p_u16s.as_ptr()) } == 0 { +pub fn unlink(path: &WCStr) -> io::Result<()> { + if unsafe { c::DeleteFileW(path.as_ptr()) } == 0 { let err = api::get_last_error(); // if `DeleteFileW` fails with ERROR_ACCESS_DENIED then try to remove // the file while ignoring the readonly attribute. @@ -1223,7 +1224,7 @@ pub fn unlink(p: &Path) -> io::Result<()> { let mut opts = OpenOptions::new(); opts.access_mode(c::DELETE); opts.custom_flags(c::FILE_FLAG_OPEN_REPARSE_POINT); - if let Ok(f) = File::open_native(&p_u16s, &opts) { + if let Ok(f) = File::open_native(&path, &opts) { if f.posix_delete().is_ok() { return Ok(()); } @@ -1236,10 +1237,7 @@ pub fn unlink(p: &Path) -> io::Result<()> { } } -pub fn rename(old: &Path, new: &Path) -> io::Result<()> { - let old = maybe_verbatim(old)?; - let new = maybe_verbatim(new)?; - +pub fn rename(old: &WCStr, new: &WCStr) -> io::Result<()> { if unsafe { c::MoveFileExW(old.as_ptr(), new.as_ptr(), c::MOVEFILE_REPLACE_EXISTING) } == 0 { let err = api::get_last_error(); // if `MoveFileExW` fails with ERROR_ACCESS_DENIED then try to move @@ -1253,7 +1251,8 @@ pub fn rename(old: &Path, new: &Path) -> io::Result<()> { // Calculate the layout of the `FILE_RENAME_INFO` we pass to `SetFileInformation` // This is a dynamically sized struct so we need to get the position of the last field to calculate the actual size. - let Ok(new_len_without_nul_in_bytes): Result = ((new.len() - 1) * 2).try_into() + let Ok(new_len_without_nul_in_bytes): Result = + ((new.count_bytes() - 1) * 2).try_into() else { return Err(err).io_result(); }; @@ -1282,7 +1281,7 @@ pub fn rename(old: &Path, new: &Path) -> io::Result<()> { new.as_ptr().copy_to_nonoverlapping( (&raw mut (*file_rename_info).FileName).cast::(), - new.len(), + new.count_bytes(), ); } @@ -1309,20 +1308,19 @@ pub fn rename(old: &Path, new: &Path) -> io::Result<()> { Ok(()) } -pub fn rmdir(p: &Path) -> io::Result<()> { - let p = maybe_verbatim(p)?; +pub fn rmdir(p: &WCStr) -> io::Result<()> { cvt(unsafe { c::RemoveDirectoryW(p.as_ptr()) })?; Ok(()) } -pub fn remove_dir_all(path: &Path) -> io::Result<()> { +pub fn remove_dir_all(path: &WCStr) -> io::Result<()> { // Open a file or directory without following symlinks. let mut opts = OpenOptions::new(); opts.access_mode(c::FILE_LIST_DIRECTORY); // `FILE_FLAG_BACKUP_SEMANTICS` allows opening directories. // `FILE_FLAG_OPEN_REPARSE_POINT` opens a link instead of its target. opts.custom_flags(c::FILE_FLAG_BACKUP_SEMANTICS | c::FILE_FLAG_OPEN_REPARSE_POINT); - let file = File::open(path, &opts)?; + let file = File::open_native(path, &opts)?; // Test if the file is not a directory or a symlink to a directory. if (file.basic_info()?.FileAttributes & c::FILE_ATTRIBUTE_DIRECTORY) == 0 { @@ -1333,14 +1331,14 @@ pub fn remove_dir_all(path: &Path) -> io::Result<()> { remove_dir_all_iterative(file).io_result() } -pub fn readlink(path: &Path) -> io::Result { +pub fn readlink(path: &WCStr) -> io::Result { // Open the link with no access mode, instead of generic read. // By default FILE_LIST_DIRECTORY is denied for the junction "C:\Documents and Settings", so // this is needed for a common case. let mut opts = OpenOptions::new(); opts.access_mode(0); opts.custom_flags(c::FILE_FLAG_OPEN_REPARSE_POINT | c::FILE_FLAG_BACKUP_SEMANTICS); - let file = File::open(path, &opts)?; + let file = File::open_native(&path, &opts)?; file.readlink() } @@ -1378,19 +1376,17 @@ pub fn symlink_inner(original: &Path, link: &Path, dir: bool) -> io::Result<()> } #[cfg(not(target_vendor = "uwp"))] -pub fn link(original: &Path, link: &Path) -> io::Result<()> { - let original = maybe_verbatim(original)?; - let link = maybe_verbatim(link)?; +pub fn link(original: &WCStr, link: &WCStr) -> io::Result<()> { cvt(unsafe { c::CreateHardLinkW(link.as_ptr(), original.as_ptr(), ptr::null_mut()) })?; Ok(()) } #[cfg(target_vendor = "uwp")] -pub fn link(_original: &Path, _link: &Path) -> io::Result<()> { +pub fn link(_original: &WCStr, _link: &WCStr) -> io::Result<()> { return Err(io::const_error!(io::ErrorKind::Unsupported, "hard link are not supported on UWP")); } -pub fn stat(path: &Path) -> io::Result { +pub fn stat(path: &WCStr) -> io::Result { match metadata(path, ReparsePoint::Follow) { Err(err) if err.raw_os_error() == Some(c::ERROR_CANT_ACCESS_FILE as i32) => { if let Ok(attrs) = lstat(path) { @@ -1404,7 +1400,7 @@ pub fn stat(path: &Path) -> io::Result { } } -pub fn lstat(path: &Path) -> io::Result { +pub fn lstat(path: &WCStr) -> io::Result { metadata(path, ReparsePoint::Open) } @@ -1420,7 +1416,7 @@ impl ReparsePoint { } } -fn metadata(path: &Path, reparse: ReparsePoint) -> io::Result { +fn metadata(path: &WCStr, reparse: ReparsePoint) -> io::Result { let mut opts = OpenOptions::new(); // No read or write permissions are necessary opts.access_mode(0); @@ -1429,7 +1425,7 @@ fn metadata(path: &Path, reparse: ReparsePoint) -> io::Result { // Attempt to open the file normally. // If that fails with `ERROR_SHARING_VIOLATION` then retry using `FindFirstFileExW`. // If the fallback fails for any reason we return the original error. - match File::open(path, &opts) { + match File::open_native(&path, &opts) { Ok(file) => file.file_attr(), Err(e) if [Some(c::ERROR_SHARING_VIOLATION as _), Some(c::ERROR_ACCESS_DENIED as _)] @@ -1442,8 +1438,6 @@ fn metadata(path: &Path, reparse: ReparsePoint) -> io::Result { // However, there are special system files, such as // `C:\hiberfil.sys`, that are locked in a way that denies even that. unsafe { - let path = maybe_verbatim(path)?; - // `FindFirstFileExW` accepts wildcard file names. // Fortunately wildcards are not valid file names and // `ERROR_SHARING_VIOLATION` means the file exists (but is locked) @@ -1482,8 +1476,7 @@ fn metadata(path: &Path, reparse: ReparsePoint) -> io::Result { } } -pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> { - let p = maybe_verbatim(p)?; +pub fn set_perm(p: &WCStr, perm: FilePermissions) -> io::Result<()> { unsafe { cvt(c::SetFileAttributesW(p.as_ptr(), perm.attrs))?; Ok(()) @@ -1499,17 +1492,17 @@ fn get_path(f: &File) -> io::Result { ) } -pub fn canonicalize(p: &Path) -> io::Result { +pub fn canonicalize(p: &WCStr) -> io::Result { let mut opts = OpenOptions::new(); // No read or write permissions are necessary opts.access_mode(0); // This flag is so we can open directories too opts.custom_flags(c::FILE_FLAG_BACKUP_SEMANTICS); - let f = File::open(p, &opts)?; + let f = File::open_native(p, &opts)?; get_path(&f) } -pub fn copy(from: &Path, to: &Path) -> io::Result { +pub fn copy(from: &WCStr, to: &WCStr) -> io::Result { unsafe extern "system" fn callback( _TotalFileSize: i64, _TotalBytesTransferred: i64, @@ -1528,13 +1521,11 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { c::PROGRESS_CONTINUE } } - let pfrom = maybe_verbatim(from)?; - let pto = maybe_verbatim(to)?; let mut size = 0i64; cvt(unsafe { c::CopyFileExW( - pfrom.as_ptr(), - pto.as_ptr(), + from.as_ptr(), + to.as_ptr(), Some(callback), (&raw mut size) as *mut _, ptr::null_mut(), @@ -1624,14 +1615,14 @@ pub fn junction_point(original: &Path, link: &Path) -> io::Result<()> { } // Try to see if a file exists but, unlike `exists`, report I/O errors. -pub fn exists(path: &Path) -> io::Result { +pub fn exists(path: &WCStr) -> io::Result { // Open the file to ensure any symlinks are followed to their target. let mut opts = OpenOptions::new(); // No read, write, etc access rights are needed. opts.access_mode(0); // Backup semantics enables opening directories as well as files. opts.custom_flags(c::FILE_FLAG_BACKUP_SEMANTICS); - match File::open(path, &opts) { + match File::open_native(path, &opts) { Err(e) => match e.kind() { // The file definitely does not exist io::ErrorKind::NotFound => Ok(false), diff --git a/library/std/src/sys/path/windows.rs b/library/std/src/sys/path/windows.rs index 6547ed9aa5f3..e0e003f6a819 100644 --- a/library/std/src/sys/path/windows.rs +++ b/library/std/src/sys/path/windows.rs @@ -10,6 +10,40 @@ mod tests; pub const MAIN_SEP_STR: &str = "\\"; pub const MAIN_SEP: char = '\\'; +/// A null terminated wide string. +#[repr(transparent)] +pub struct WCStr([u16]); + +impl WCStr { + /// Convert a slice to a WCStr without checks. + /// + /// Though it is memory safe, the slice should also not contain interior nulls + /// as this may lead to unwanted truncation. + /// + /// # Safety + /// + /// The slice must end in a null. + pub unsafe fn from_wchars_with_null_unchecked(s: &[u16]) -> &Self { + unsafe { &*(s as *const [u16] as *const Self) } + } + + pub fn as_ptr(&self) -> *const u16 { + self.0.as_ptr() + } + + pub fn count_bytes(&self) -> usize { + self.0.len() + } +} + +#[inline] +pub fn with_native_path(path: &Path, f: &dyn Fn(&WCStr) -> io::Result) -> io::Result { + let path = maybe_verbatim(path)?; + // SAFETY: maybe_verbatim returns null-terminated strings + let path = unsafe { WCStr::from_wchars_with_null_unchecked(&path) }; + f(path) +} + #[inline] pub fn is_sep_byte(b: u8) -> bool { b == b'/' || b == b'\\' From 452c280f6442c02d3f4013360cd5cb71e6c54331 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 11 Apr 2025 15:27:11 -0300 Subject: [PATCH 373/606] Add spastorino to users_on_vacation --- triagebot.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/triagebot.toml b/triagebot.toml index 8a7797bd1ffe..52771a3926dc 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1126,6 +1126,7 @@ users_on_vacation = [ "jyn514", "saethlin", "Noratrieb", + "spastorino", ] [[assign.warn_non_default_branch.exceptions]] From e013cf8afcf74a5f27feb7ebb0dca248e5c489fe Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 11 Apr 2025 11:35:10 -0700 Subject: [PATCH 374/606] rustdoc-search: add unbox flag to Result aliases Fixes #139665 --- compiler/rustc_passes/src/check_attr.rs | 1 + library/std/src/io/error.rs | 1 + library/std/src/thread/mod.rs | 1 + tests/rustdoc-js-std/unbox-type-result.js | 20 ++++++++++++++++++++ tests/rustdoc-js/generics-unbox.js | 6 ++++++ tests/rustdoc-js/generics-unbox.rs | 12 ++++++++++++ 6 files changed, 41 insertions(+) create mode 100644 tests/rustdoc-js-std/unbox-type-result.js diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 9161b23428a0..c51425078122 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1109,6 +1109,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { ItemKind::Trait(_, _, _, generics, _, items) if generics.params.len() != 0 || items.iter().any(|item| matches!(item.kind, AssocItemKind::Type)) => {} + ItemKind::TyAlias(_, _, generics) if generics.params.len() != 0 => {} _ => { self.dcx().emit_err(errors::DocSearchUnboxInvalid { span: meta.span() }); } diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index 2498fb8d24fb..cf3778bd2907 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -48,6 +48,7 @@ use crate::{error, fmt, result, sys}; /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(bootstrap), doc(search_unbox))] pub type Result = result::Result; /// The error type for I/O operations of the [`Read`], [`Write`], [`Seek`], and diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 3f3ba02361cc..2097f1e304ce 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -1676,6 +1676,7 @@ impl fmt::Debug for Thread { /// [`Result`]: crate::result::Result /// [`std::panic::resume_unwind`]: crate::panic::resume_unwind #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(bootstrap), doc(search_unbox))] pub type Result = crate::result::Result>; // This packet is used to communicate the return value between the spawned diff --git a/tests/rustdoc-js-std/unbox-type-result.js b/tests/rustdoc-js-std/unbox-type-result.js new file mode 100644 index 000000000000..1f5cba58adf6 --- /dev/null +++ b/tests/rustdoc-js-std/unbox-type-result.js @@ -0,0 +1,20 @@ +// exact-check + +// Test case for https://github.com/rust-lang/rust/issues/139665 +// make sure that std::io::Result and std::thread::Result get unboxed + +const EXPECTED = [ + { + query: "File -> Metadata", + others: [ + { path: "std::fs::File", name: "metadata" }, + { path: "std::fs::File", name: "metadata_at" }, + ] + }, + { + query: "JoinHandle -> T", + others: [ + { path: "std::thread::JoinHandle", name: "join" }, + ] + }, +]; diff --git a/tests/rustdoc-js/generics-unbox.js b/tests/rustdoc-js/generics-unbox.js index 6baf00c814bb..a4f2ba8e3a63 100644 --- a/tests/rustdoc-js/generics-unbox.js +++ b/tests/rustdoc-js/generics-unbox.js @@ -31,4 +31,10 @@ const EXPECTED = [ { 'path': 'generics_unbox', 'name': 'beta' }, ], }, + { + 'query': '-> Sigma', + 'others': [ + { 'path': 'generics_unbox', 'name': 'delta' }, + ], + }, ]; diff --git a/tests/rustdoc-js/generics-unbox.rs b/tests/rustdoc-js/generics-unbox.rs index c2578575997b..b16e35ee3d46 100644 --- a/tests/rustdoc-js/generics-unbox.rs +++ b/tests/rustdoc-js/generics-unbox.rs @@ -42,3 +42,15 @@ pub fn beta(_: Inside) -> Out, Out4> { pub fn gamma(_: Inside) -> Out, Out4> { loop {} } + +pub fn delta(_: i32) -> Epsilon { + loop {} +} + +#[doc(search_unbox)] +pub struct Theta(T); + +#[doc(search_unbox)] +pub type Epsilon = Theta; + +pub struct Sigma; From 394610b6d6b0bde38f75b7cc41ec1931bb7f0323 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Fri, 11 Apr 2025 21:30:10 +0200 Subject: [PATCH 375/606] Document that `opt-dist` requires metrics to be enabled --- src/doc/rustc-dev-guide/src/building/optimized-build.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/building/optimized-build.md b/src/doc/rustc-dev-guide/src/building/optimized-build.md index 0849464eab36..62dfaca89d24 100644 --- a/src/doc/rustc-dev-guide/src/building/optimized-build.md +++ b/src/doc/rustc-dev-guide/src/building/optimized-build.md @@ -109,11 +109,16 @@ like Python or LLVM. Here is an example of how can `opt-dist` be used locally (outside of CI): -1. Build the tool with the following command: +1. Enable metrics in your `bootstrap.toml` file, because `opt-dist` expects it to be enabled: + ```toml + [build] + metrics = true + ``` +2. Build the tool with the following command: ```bash ./x build tools/opt-dist ``` -2. Run the tool with the `local` mode and provide necessary parameters: +3. Run the tool with the `local` mode and provide necessary parameters: ```bash ./build/host/stage0-tools-bin/opt-dist local \ --target-triple \ # select target, e.g. "x86_64-unknown-linux-gnu" From 52b7571707f6873175dfcd46468207640ba056d5 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Fri, 11 Apr 2025 23:00:05 -0400 Subject: [PATCH 376/606] Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index 0e93c5bf6a1d..864f74d4eadc 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 0e93c5bf6a1d5ee7bc2af63d1afb16cd28793601 +Subproject commit 864f74d4eadcaea3eeda37a2e7f4d34de233d51e From c4620021dc3d987a417abefc966996bf3ce4c617 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Sat, 12 Apr 2025 05:00:08 +0000 Subject: [PATCH 377/606] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index d2b8b5147306..d1107e515090 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -7d7de5bf3c3cbf9c2c5bbc5cbfb9197a8a427d35 +1bc56185ee257ed829a0aea7abdc3b03c5fed887 From 59a3730169a4e4a34357b2c01b9134886ddf6512 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Sat, 12 Apr 2025 05:08:28 +0000 Subject: [PATCH 378/606] fmt --- .../pass/issues/issue-134713-swap_nonoverlapping_untyped.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/tests/pass/issues/issue-134713-swap_nonoverlapping_untyped.rs b/src/tools/miri/tests/pass/issues/issue-134713-swap_nonoverlapping_untyped.rs index a1da60ce65c4..27ea12398d88 100644 --- a/src/tools/miri/tests/pass/issues/issue-134713-swap_nonoverlapping_untyped.rs +++ b/src/tools/miri/tests/pass/issues/issue-134713-swap_nonoverlapping_untyped.rs @@ -1,4 +1,4 @@ -use std::mem::{size_of, align_of}; +use std::mem::{align_of, size_of}; // See From 072678ec8631797fb2a8c4555e11418ae5e601f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Fern=C3=A1ndez=20Serrata?= <76864299+Rudxain@users.noreply.github.com> Date: Sat, 12 Apr 2025 02:18:40 -0400 Subject: [PATCH 379/606] docs: clarify uint exponent for `is_power_of_two` --- library/core/src/num/uint_macros.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 1b2acdc5a0df..3678bb091e7d 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -3343,7 +3343,7 @@ macro_rules! uint_impl { } } - /// Returns `true` if and only if `self == 2^k` for some `k`. + /// Returns `true` if and only if `self == 2^k` for some unsigned integer `k`. /// /// # Examples /// From 41931320f83f8c7742597e1d1a965901e563b3b1 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Wed, 2 Apr 2025 16:41:40 +0800 Subject: [PATCH 380/606] run-make-support: fix artifact name calculations for target This was implemented incorrectly during the porting process, where we relied on std consts. However, `run-make-support` is a host-only library, which meant that these artifact names were for the *host* and not the *target*. --- .../run-make-support/src/artifact_names.rs | 53 ++++++++++++++----- 1 file changed, 40 insertions(+), 13 deletions(-) diff --git a/src/tools/run-make-support/src/artifact_names.rs b/src/tools/run-make-support/src/artifact_names.rs index 8968f831542e..b0d588d3550a 100644 --- a/src/tools/run-make-support/src/artifact_names.rs +++ b/src/tools/run-make-support/src/artifact_names.rs @@ -1,11 +1,11 @@ //! A collection of helpers to construct artifact names, such as names of dynamic or static -//! librarys which are target-dependent. - -// FIXME(jieyouxu): convert these to return `PathBuf`s instead of strings! +//! libraries which are target-dependent. +use crate::target; use crate::targets::is_msvc; /// Construct the static library name based on the target. +#[track_caller] #[must_use] pub fn static_lib_name(name: &str) -> String { assert!(!name.contains(char::is_whitespace), "static library name cannot contain whitespace"); @@ -14,15 +14,34 @@ pub fn static_lib_name(name: &str) -> String { } /// Construct the dynamic library name based on the target. +#[track_caller] #[must_use] pub fn dynamic_lib_name(name: &str) -> String { assert!(!name.contains(char::is_whitespace), "dynamic library name cannot contain whitespace"); - format!("{}{name}.{}", std::env::consts::DLL_PREFIX, std::env::consts::DLL_EXTENSION) + format!("{}{name}.{}", dynamic_lib_prefix(), dynamic_lib_extension()) } -/// Construct the name of the import library for the dynamic library, exclusive to MSVC and -/// accepted by link.exe. +fn dynamic_lib_prefix() -> &'static str { + if target().contains("windows") { "" } else { "lib" } +} + +/// Construct the dynamic library extension based on the target. +#[must_use] +pub fn dynamic_lib_extension() -> &'static str { + let target = target(); + + if target.contains("apple") { + "dylib" + } else if target.contains("windows") { + "dll" + } else { + "so" + } +} + +/// Construct the name of the import library for the dynamic library, exclusive to MSVC and accepted +/// by link.exe. #[track_caller] #[must_use] pub fn msvc_import_dynamic_lib_name(name: &str) -> String { @@ -32,20 +51,28 @@ pub fn msvc_import_dynamic_lib_name(name: &str) -> String { format!("{name}.dll.lib") } -/// Construct the dynamic library extension based on the target. -#[must_use] -pub fn dynamic_lib_extension() -> &'static str { - std::env::consts::DLL_EXTENSION -} - /// Construct the name of a rust library (rlib). +#[track_caller] #[must_use] pub fn rust_lib_name(name: &str) -> String { format!("lib{name}.rlib") } /// Construct the binary (executable) name based on the target. +#[track_caller] #[must_use] pub fn bin_name(name: &str) -> String { - format!("{name}{}", std::env::consts::EXE_SUFFIX) + let target = target(); + + if target.contains("windows") { + format!("{name}.exe") + } else if target.contains("uefi") { + format!("{name}.efi") + } else if target.contains("wasm") { + format!("{name}.wasm") + } else if target.contains("nvptx") { + format!("{name}.ptx") + } else { + name.to_string() + } } From 4362789eb0b3001905f338a6e865c437b4756461 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Fri, 4 Apr 2025 10:40:38 +0800 Subject: [PATCH 381/606] tests: produce target artifacts and/or require crate type / ignore cross-compile Some tests fail on cross-compiled targets due to various linker problems on cross-compiled target, and having test coverage for these against cross-compiled targets is nice but not necessary. --- tests/run-make/crate-data-smoke/rmake.rs | 32 ++++++++++++++++--- tests/run-make/crate-name-priority/rmake.rs | 2 ++ .../extra-filename-with-temp-outputs/rmake.rs | 2 ++ .../output-type-permutations/rmake.rs | 4 +++ tests/run-make/reproducible-build/rmake.rs | 2 ++ tests/run-make/strip/rmake.rs | 3 +- tests/run-make/symbols-all-mangled/rmake.rs | 2 ++ 7 files changed, 41 insertions(+), 6 deletions(-) diff --git a/tests/run-make/crate-data-smoke/rmake.rs b/tests/run-make/crate-data-smoke/rmake.rs index 70f8e46b6d92..b5708d05a82b 100644 --- a/tests/run-make/crate-data-smoke/rmake.rs +++ b/tests/run-make/crate-data-smoke/rmake.rs @@ -1,9 +1,20 @@ -use run_make_support::{bin_name, rust_lib_name, rustc}; +use run_make_support::{bin_name, rust_lib_name, rustc, target}; fn main() { - rustc().print("crate-name").input("crate.rs").run().assert_stdout_equals("foo"); - rustc().print("file-names").input("crate.rs").run().assert_stdout_equals(bin_name("foo")); rustc() + .target(target()) + .print("crate-name") + .input("crate.rs") + .run() + .assert_stdout_equals("foo"); + rustc() + .target(target()) + .print("file-names") + .input("crate.rs") + .run() + .assert_stdout_equals(bin_name("foo")); + rustc() + .target(target()) .print("file-names") .crate_type("lib") .arg("--test") @@ -11,11 +22,22 @@ fn main() { .run() .assert_stdout_equals(bin_name("foo")); rustc() + .target(target()) .print("file-names") .arg("--test") .input("lib.rs") .run() .assert_stdout_equals(bin_name("mylib")); - rustc().print("file-names").input("lib.rs").run().assert_stdout_equals(rust_lib_name("mylib")); - rustc().print("file-names").input("rlib.rs").run().assert_stdout_equals(rust_lib_name("mylib")); + rustc() + .target(target()) + .print("file-names") + .input("lib.rs") + .run() + .assert_stdout_equals(rust_lib_name("mylib")); + rustc() + .target(target()) + .print("file-names") + .input("rlib.rs") + .run() + .assert_stdout_equals(rust_lib_name("mylib")); } diff --git a/tests/run-make/crate-name-priority/rmake.rs b/tests/run-make/crate-name-priority/rmake.rs index 5bdb49b33cea..82e482b5a2ef 100644 --- a/tests/run-make/crate-name-priority/rmake.rs +++ b/tests/run-make/crate-name-priority/rmake.rs @@ -4,6 +4,8 @@ // and the compiler flags, and checks that the flag is favoured each time. // See https://github.com/rust-lang/rust/pull/15518 +//@ ignore-cross-compile (relocations in generic ELF against `arm-unknown-linux-gnueabihf`) + use run_make_support::{bin_name, rfs, rustc}; fn main() { diff --git a/tests/run-make/extra-filename-with-temp-outputs/rmake.rs b/tests/run-make/extra-filename-with-temp-outputs/rmake.rs index 0910045bb857..f93a3ecc8d1b 100644 --- a/tests/run-make/extra-filename-with-temp-outputs/rmake.rs +++ b/tests/run-make/extra-filename-with-temp-outputs/rmake.rs @@ -6,6 +6,8 @@ // are named as expected. // See https://github.com/rust-lang/rust/pull/15686 +//@ ignore-cross-compile (relocations in generic ELF against `arm-unknown-linux-gnueabihf`) + use run_make_support::{bin_name, cwd, has_prefix, has_suffix, rfs, rustc, shallow_find_files}; fn main() { diff --git a/tests/run-make/output-type-permutations/rmake.rs b/tests/run-make/output-type-permutations/rmake.rs index c0569af6e84a..8da0bfaa12db 100644 --- a/tests/run-make/output-type-permutations/rmake.rs +++ b/tests/run-make/output-type-permutations/rmake.rs @@ -4,6 +4,9 @@ // files are exactly what is expected, no more, no less. // See https://github.com/rust-lang/rust/pull/12020 +//@ ignore-cross-compile +// Reason: some cross-compiled targets don't support various crate types and fail to link. + use std::path::PathBuf; use run_make_support::{ @@ -17,6 +20,7 @@ use run_make_support::{ // `dir`: the name of the directory where the test happens // `rustc_invocation`: the rustc command being tested // Any unexpected output files not listed in `must_exist` or `can_exist` will cause a failure. +#[track_caller] fn assert_expected_output_files(expectations: Expectations, rustc_invocation: impl Fn()) { let Expectations { expected_files: must_exist, allowed_files: can_exist, test_dir: dir } = expectations; diff --git a/tests/run-make/reproducible-build/rmake.rs b/tests/run-make/reproducible-build/rmake.rs index 8a8b0d6d652b..93fc30de07d7 100644 --- a/tests/run-make/reproducible-build/rmake.rs +++ b/tests/run-make/reproducible-build/rmake.rs @@ -20,6 +20,8 @@ // See https://github.com/rust-lang/rust/pull/32293 // Tracking Issue: https://github.com/rust-lang/rust/issues/129080 +//@ ignore-cross-compile (linker binary needs to run) + use run_make_support::{ bin_name, cwd, diff, is_darwin, is_windows, regex, rfs, run_in_tmpdir, rust_lib_name, rustc, }; diff --git a/tests/run-make/strip/rmake.rs b/tests/run-make/strip/rmake.rs index ef1acc26b455..01b31ac30948 100644 --- a/tests/run-make/strip/rmake.rs +++ b/tests/run-make/strip/rmake.rs @@ -1,4 +1,5 @@ -//@ ignore-windows Windows does not actually strip +//@ ignore-windows (Windows does not actually strip) +//@ ignore-cross-compile (relocations in generic ELF against `arm-unknown-linux-gnueabihf`) // Test that -Cstrip correctly strips/preserves debuginfo and symbols. diff --git a/tests/run-make/symbols-all-mangled/rmake.rs b/tests/run-make/symbols-all-mangled/rmake.rs index 1fb03c62399a..79ddd06bb94b 100644 --- a/tests/run-make/symbols-all-mangled/rmake.rs +++ b/tests/run-make/symbols-all-mangled/rmake.rs @@ -1,5 +1,7 @@ // Check that all symbols in cdylibs, staticlibs and bins are mangled //@ only-elf some object file formats create multiple symbols for each function with different names +//@ ignore-nvptx64 (needs target std) +//@ ignore-cross-compile (host-only) use run_make_support::object::read::{Object, ObjectSymbol}; use run_make_support::{bin_name, dynamic_lib_name, object, rfs, rustc, static_lib_name}; From 762ecf8e00504ba3b19c688497fd016ee781c19d Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Sat, 12 Apr 2025 15:18:01 +0800 Subject: [PATCH 382/606] tests/ui: remove outdated README We should consolidate our test suite docs in rustc-dev-guide, and this README is very outdated. --- tests/ui/README.md | 35 ----------------------------------- 1 file changed, 35 deletions(-) delete mode 100644 tests/ui/README.md diff --git a/tests/ui/README.md b/tests/ui/README.md deleted file mode 100644 index aa36481ae06e..000000000000 --- a/tests/ui/README.md +++ /dev/null @@ -1,35 +0,0 @@ -# UI Tests - -This folder contains `rustc`'s -[UI tests](https://rustc-dev-guide.rust-lang.org/tests/ui.html). - -## Test Directives (Headers) - -Typically, a UI test will have some test directives / headers which are -special comments that tell compiletest how to build and interpret a test. - -As part of an ongoing effort to rewrite compiletest -(see ), a major -change proposal to change legacy compiletest-style headers `// ` -to [`ui_test`](https://github.com/oli-obk/ui_test)-style headers -`//@ ` was accepted (see -. - -An example directive is `ignore-test`. In legacy compiletest style, the header -would be written as - -```rs -// ignore-test -``` - -but in `ui_test` style, the header would be written as - -```rs -//@ ignore-test -``` - -compiletest is changed to accept only `//@` directives for UI tests -(currently), and will reject and report an error if it encounters any -comments `// ` that may be parsed as a legacy compiletest-style -test header. To fix this, you should migrate to the `ui_test`-style header -`//@ `. From db6e3aa91387ea8abe2cc29cd4b8e245074472da Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Sat, 12 Apr 2025 15:24:25 +0800 Subject: [PATCH 383/606] tests: ensure disabled tests have a reason --- tests/ui/bootstrap/self-test/a.rs | 2 +- tests/ui/bootstrap/self-test/b.rs | 2 +- tests/ui/lint/unknown-lints/other.rs | 2 +- tests/ui/precondition-checks/read.rs | 2 +- tests/ui/precondition-checks/write.rs | 2 +- tests/ui/precondition-checks/write_bytes.rs | 2 +- .../next-solver/object-soundness-requires-generalization.rs | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/ui/bootstrap/self-test/a.rs b/tests/ui/bootstrap/self-test/a.rs index 64d2d6f11bbd..b8abd8179c91 100644 --- a/tests/ui/bootstrap/self-test/a.rs +++ b/tests/ui/bootstrap/self-test/a.rs @@ -1,2 +1,2 @@ //! Not used by compiler, this is used by bootstrap cli self-test. -//@ ignore-test +//@ ignore-test (used by bootstrap) diff --git a/tests/ui/bootstrap/self-test/b.rs b/tests/ui/bootstrap/self-test/b.rs index 91f92f67910b..5bbd2f946feb 100644 --- a/tests/ui/bootstrap/self-test/b.rs +++ b/tests/ui/bootstrap/self-test/b.rs @@ -1,2 +1,2 @@ //! Not used by compiler, used by bootstrap cli self-test. -//@ ignore-test +//@ ignore-test (used by bootstrap) diff --git a/tests/ui/lint/unknown-lints/other.rs b/tests/ui/lint/unknown-lints/other.rs index f917bff6d602..253335849161 100644 --- a/tests/ui/lint/unknown-lints/other.rs +++ b/tests/ui/lint/unknown-lints/other.rs @@ -1,4 +1,4 @@ -//@ ignore-test +//@ ignore-test (auxiliary) // Companion to allow-in-other-module.rs diff --git a/tests/ui/precondition-checks/read.rs b/tests/ui/precondition-checks/read.rs index ab9921a0ceeb..d5ab7773987f 100644 --- a/tests/ui/precondition-checks/read.rs +++ b/tests/ui/precondition-checks/read.rs @@ -2,7 +2,7 @@ //@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes //@ error-pattern: unsafe precondition(s) violated: ptr::read requires //@ revisions: null misaligned -//@ ignore-test +//@ ignore-test (unimplemented) use std::ptr; diff --git a/tests/ui/precondition-checks/write.rs b/tests/ui/precondition-checks/write.rs index f76e776fcf35..5d6b9586fad7 100644 --- a/tests/ui/precondition-checks/write.rs +++ b/tests/ui/precondition-checks/write.rs @@ -2,7 +2,7 @@ //@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes //@ error-pattern: unsafe precondition(s) violated: ptr::write requires //@ revisions: null misaligned -//@ ignore-test +//@ ignore-test (unimplemented) use std::ptr; diff --git a/tests/ui/precondition-checks/write_bytes.rs b/tests/ui/precondition-checks/write_bytes.rs index 3f64be9d1ee1..be4f5a089f03 100644 --- a/tests/ui/precondition-checks/write_bytes.rs +++ b/tests/ui/precondition-checks/write_bytes.rs @@ -2,7 +2,7 @@ //@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes //@ error-pattern: unsafe precondition(s) violated: ptr::write requires //@ revisions: null misaligned -//@ ignore-test +//@ ignore-test (unimplemented) use std::ptr; diff --git a/tests/ui/traits/next-solver/object-soundness-requires-generalization.rs b/tests/ui/traits/next-solver/object-soundness-requires-generalization.rs index 11a2617ad427..3ef6bea4fd5c 100644 --- a/tests/ui/traits/next-solver/object-soundness-requires-generalization.rs +++ b/tests/ui/traits/next-solver/object-soundness-requires-generalization.rs @@ -1,5 +1,5 @@ //@ compile-flags: -Znext-solver -//@ ignore-test +//@ ignore-test (see #114196) trait Trait { type Gat<'lt>; From 86e2a07a13ce7fd6f68c71802db8f8c8eebe0ad0 Mon Sep 17 00:00:00 2001 From: Maksim Bondarenkov Date: Sat, 12 Apr 2025 10:52:46 +0300 Subject: [PATCH 384/606] opt-dist: use executable-extension for host llvm-profdata so the merging step doesn't fail for `opt-dist local` on Windows --- src/tools/opt-dist/src/training.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/tools/opt-dist/src/training.rs b/src/tools/opt-dist/src/training.rs index 30c79f959474..47159a43140f 100644 --- a/src/tools/opt-dist/src/training.rs +++ b/src/tools/opt-dist/src/training.rs @@ -70,7 +70,9 @@ fn merge_llvm_profiles( profdata: LlvmProfdata, ) -> anyhow::Result<()> { let llvm_profdata = match profdata { - LlvmProfdata::Host => env.host_llvm_dir().join("bin/llvm-profdata"), + LlvmProfdata::Host => { + env.host_llvm_dir().join(format!("bin/llvm-profdata{}", executable_extension())) + } LlvmProfdata::Target => env .build_artifacts() .join("llvm") From ddf8237bcb05272a677cba46cffa0296b7477809 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sat, 12 Apr 2025 10:05:50 +0200 Subject: [PATCH 385/606] Fix comment in bootstrap --- src/bootstrap/src/core/build_steps/tool.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index 1c61f0a56d7b..ded7220fcedc 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -150,10 +150,7 @@ impl Step for ToolBuild { // Rustc tools (miri, clippy, cargo, rustfmt, rust-analyzer) // could use the additional optimizations. - if self.mode == Mode::ToolRustc && - // rustdoc is performance sensitive, so apply LTO to it. - is_lto_stage(&self.compiler) - { + if self.mode == Mode::ToolRustc && is_lto_stage(&self.compiler) { let lto = match builder.config.rust_lto { RustcLto::Off => Some("off"), RustcLto::Thin => Some("thin"), From 83dd8a2c2a7d948e669adc7170dfc4bf0b76a873 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sat, 12 Apr 2025 11:33:33 +0200 Subject: [PATCH 386/606] Fix name of field in doc comment --- compiler/rustc_hir/src/hir.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index c9c4936c1564..6455f33b9d15 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1756,7 +1756,7 @@ pub enum PatKind<'hir> { Never, /// A tuple pattern (e.g., `(a, b)`). - /// If the `..` pattern fragment is present, then `Option` denotes its position. + /// If the `..` pattern fragment is present, then `DotDotPos` denotes its position. /// `0 <= position <= subpats.len()` Tuple(&'hir [Pat<'hir>], DotDotPos), From 32dd3831f56973881ad2a47d4b4002d18de26c5f Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sat, 12 Apr 2025 11:38:55 +0200 Subject: [PATCH 387/606] bootstrap: fix typo in doc string --- src/bootstrap/src/core/download.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs index 5bd947f6e636..4e4b948a8fd6 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -417,7 +417,7 @@ enum DownloadSource { Dist, } -/// Functions that are only ever called once, but named for clarify and to avoid thousand-line functions. +/// Functions that are only ever called once, but named for clarity and to avoid thousand-line functions. impl Config { pub(crate) fn download_clippy(&self) -> PathBuf { self.verbose(|| println!("downloading stage0 clippy artifacts")); From 6ffebb65d6daf4fcc82cfc7fd14397bff98df1f2 Mon Sep 17 00:00:00 2001 From: Thalia Archibald Date: Sat, 12 Apr 2025 02:26:17 -0700 Subject: [PATCH 388/606] Move args into std::sys --- .../{pal/hermit/args.rs => args/hermit.rs} | 0 library/std/src/sys/args/mod.rs | 34 +++++++++++++++++++ .../src/sys/{pal/sgx/args.rs => args/sgx.rs} | 6 ++-- .../sys/{pal/uefi/args.rs => args/uefi.rs} | 2 +- .../sys/{pal/unix/args.rs => args/unix.rs} | 8 ++--- .../args.rs => args/unsupported.rs} | 0 .../sys/{pal/wasi/args.rs => args/wasi.rs} | 0 .../{pal/windows/args.rs => args/windows.rs} | 9 ++--- .../windows/args => args/windows}/tests.rs | 0 .../sys/{pal/xous/args.rs => args/xous.rs} | 4 +-- .../sys/{pal/zkvm/args.rs => args/zkvm.rs} | 2 +- library/std/src/sys/mod.rs | 1 + library/std/src/sys/pal/hermit/mod.rs | 3 +- library/std/src/sys/pal/sgx/mod.rs | 3 +- library/std/src/sys/pal/solid/mod.rs | 2 -- library/std/src/sys/pal/teeos/mod.rs | 2 -- library/std/src/sys/pal/trusty/mod.rs | 2 -- library/std/src/sys/pal/uefi/mod.rs | 1 - library/std/src/sys/pal/unix/mod.rs | 3 +- library/std/src/sys/pal/unsupported/mod.rs | 1 - library/std/src/sys/pal/wasi/mod.rs | 1 - library/std/src/sys/pal/wasip2/mod.rs | 2 -- library/std/src/sys/pal/wasm/mod.rs | 2 -- library/std/src/sys/pal/windows/mod.rs | 1 - library/std/src/sys/pal/xous/mod.rs | 1 - library/std/src/sys/pal/zkvm/mod.rs | 4 +-- 26 files changed, 53 insertions(+), 41 deletions(-) rename library/std/src/sys/{pal/hermit/args.rs => args/hermit.rs} (100%) create mode 100644 library/std/src/sys/args/mod.rs rename library/std/src/sys/{pal/sgx/args.rs => args/sgx.rs} (89%) rename library/std/src/sys/{pal/uefi/args.rs => args/uefi.rs} (99%) rename library/std/src/sys/{pal/unix/args.rs => args/unix.rs} (98%) rename library/std/src/sys/{pal/unsupported/args.rs => args/unsupported.rs} (100%) rename library/std/src/sys/{pal/wasi/args.rs => args/wasi.rs} (100%) rename library/std/src/sys/{pal/windows/args.rs => args/windows.rs} (99%) rename library/std/src/sys/{pal/windows/args => args/windows}/tests.rs (100%) rename library/std/src/sys/{pal/xous/args.rs => args/xous.rs} (91%) rename library/std/src/sys/{pal/zkvm/args.rs => args/zkvm.rs} (98%) diff --git a/library/std/src/sys/pal/hermit/args.rs b/library/std/src/sys/args/hermit.rs similarity index 100% rename from library/std/src/sys/pal/hermit/args.rs rename to library/std/src/sys/args/hermit.rs diff --git a/library/std/src/sys/args/mod.rs b/library/std/src/sys/args/mod.rs new file mode 100644 index 000000000000..6edcafe2c4c5 --- /dev/null +++ b/library/std/src/sys/args/mod.rs @@ -0,0 +1,34 @@ +//! Platform-dependent command line arguments abstraction. + +#![forbid(unsafe_op_in_unsafe_fn)] + +cfg_if::cfg_if! { + if #[cfg(target_family = "unix")] { + mod unix; + pub use unix::*; + } else if #[cfg(target_family = "windows")] { + mod windows; + pub use windows::*; + } else if #[cfg(target_os = "hermit")] { + mod hermit; + pub use hermit::*; + } else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] { + mod sgx; + pub use sgx::*; + } else if #[cfg(target_os = "uefi")] { + mod uefi; + pub use uefi::*; + } else if #[cfg(target_os = "wasi")] { + mod wasi; + pub use wasi::*; + } else if #[cfg(target_os = "xous")] { + mod xous; + pub use xous::*; + } else if #[cfg(target_os = "zkvm")] { + mod zkvm; + pub use zkvm::*; + } else { + mod unsupported; + pub use unsupported::*; + } +} diff --git a/library/std/src/sys/pal/sgx/args.rs b/library/std/src/sys/args/sgx.rs similarity index 89% rename from library/std/src/sys/pal/sgx/args.rs rename to library/std/src/sys/args/sgx.rs index e62bf383954e..efc4b7918522 100644 --- a/library/std/src/sys/pal/sgx/args.rs +++ b/library/std/src/sys/args/sgx.rs @@ -1,8 +1,10 @@ -use super::abi::usercalls::alloc; -use super::abi::usercalls::raw::ByteBuffer; +#![allow(fuzzy_provenance_casts)] // FIXME: this module systematically confuses pointers and integers + use crate::ffi::OsString; use crate::sync::atomic::{AtomicUsize, Ordering}; use crate::sys::os_str::Buf; +use crate::sys::pal::abi::usercalls::alloc; +use crate::sys::pal::abi::usercalls::raw::ByteBuffer; use crate::sys_common::FromInner; use crate::{fmt, slice}; diff --git a/library/std/src/sys/pal/uefi/args.rs b/library/std/src/sys/args/uefi.rs similarity index 99% rename from library/std/src/sys/pal/uefi/args.rs rename to library/std/src/sys/args/uefi.rs index 0c29caf2db67..4e7412937bd1 100644 --- a/library/std/src/sys/pal/uefi/args.rs +++ b/library/std/src/sys/args/uefi.rs @@ -1,9 +1,9 @@ use r_efi::protocols::loaded_image; -use super::helpers; use crate::env::current_exe; use crate::ffi::OsString; use crate::iter::Iterator; +use crate::sys::pal::helpers; use crate::{fmt, vec}; pub struct Args { diff --git a/library/std/src/sys/pal/unix/args.rs b/library/std/src/sys/args/unix.rs similarity index 98% rename from library/std/src/sys/pal/unix/args.rs rename to library/std/src/sys/args/unix.rs index 0bb7b64007ab..4c30609c0995 100644 --- a/library/std/src/sys/pal/unix/args.rs +++ b/library/std/src/sys/args/unix.rs @@ -11,7 +11,7 @@ use crate::{fmt, vec}; /// One-time global initialization. pub unsafe fn init(argc: isize, argv: *const *const u8) { - imp::init(argc, argv) + unsafe { imp::init(argc, argv) } } /// Returns the command line arguments @@ -141,7 +141,7 @@ mod imp { pub unsafe fn init(argc: isize, argv: *const *const u8) { // on GNU/Linux if we are main then we will init argv and argc twice, it "duplicates work" // BUT edge-cases are real: only using .init_array can break most emulators, dlopen, etc. - really_init(argc, argv); + unsafe { really_init(argc, argv) }; } /// glibc passes argc, argv, and envp to functions in .init_array, as a non-standard extension. @@ -159,9 +159,7 @@ mod imp { argv: *const *const u8, _envp: *const *const u8, ) { - unsafe { - really_init(argc as isize, argv); - } + unsafe { really_init(argc as isize, argv) }; } init_wrapper }; diff --git a/library/std/src/sys/pal/unsupported/args.rs b/library/std/src/sys/args/unsupported.rs similarity index 100% rename from library/std/src/sys/pal/unsupported/args.rs rename to library/std/src/sys/args/unsupported.rs diff --git a/library/std/src/sys/pal/wasi/args.rs b/library/std/src/sys/args/wasi.rs similarity index 100% rename from library/std/src/sys/pal/wasi/args.rs rename to library/std/src/sys/args/wasi.rs diff --git a/library/std/src/sys/pal/windows/args.rs b/library/std/src/sys/args/windows.rs similarity index 99% rename from library/std/src/sys/pal/windows/args.rs rename to library/std/src/sys/args/windows.rs index d973743639ab..55bd6864cae3 100644 --- a/library/std/src/sys/pal/windows/args.rs +++ b/library/std/src/sys/args/windows.rs @@ -6,17 +6,17 @@ #[cfg(test)] mod tests; -use super::ensure_no_nuls; -use super::os::current_exe; use crate::ffi::{OsStr, OsString}; use crate::num::NonZero; use crate::os::windows::prelude::*; use crate::path::{Path, PathBuf}; +use crate::sys::pal::os::current_exe; +use crate::sys::pal::{ensure_no_nuls, fill_utf16_buf}; use crate::sys::path::get_long_path; use crate::sys::{c, to_u16s}; use crate::sys_common::AsInner; use crate::sys_common::wstr::WStrUnits; -use crate::{fmt, io, iter, vec}; +use crate::{fmt, io, iter, ptr, vec}; pub fn args() -> Args { // SAFETY: `GetCommandLineW` returns a pointer to a null terminated UTF-16 @@ -384,9 +384,6 @@ pub(crate) fn to_user_path(path: &Path) -> io::Result> { from_wide_to_user_path(to_u16s(path)?) } pub(crate) fn from_wide_to_user_path(mut path: Vec) -> io::Result> { - use super::fill_utf16_buf; - use crate::ptr; - // UTF-16 encoded code points, used in parsing and building UTF-16 paths. // All of these are in the ASCII range so they can be cast directly to `u16`. const SEP: u16 = b'\\' as _; diff --git a/library/std/src/sys/pal/windows/args/tests.rs b/library/std/src/sys/args/windows/tests.rs similarity index 100% rename from library/std/src/sys/pal/windows/args/tests.rs rename to library/std/src/sys/args/windows/tests.rs diff --git a/library/std/src/sys/pal/xous/args.rs b/library/std/src/sys/args/xous.rs similarity index 91% rename from library/std/src/sys/pal/xous/args.rs rename to library/std/src/sys/args/xous.rs index 00c44ca220a9..2dd37d53422f 100644 --- a/library/std/src/sys/pal/xous/args.rs +++ b/library/std/src/sys/args/xous.rs @@ -1,6 +1,6 @@ use crate::ffi::OsString; -use crate::sys::pal::xous::os::get_application_parameters; -use crate::sys::pal::xous::os::params::ArgumentList; +use crate::sys::pal::os::get_application_parameters; +use crate::sys::pal::os::params::ArgumentList; use crate::{fmt, vec}; pub struct Args { diff --git a/library/std/src/sys/pal/zkvm/args.rs b/library/std/src/sys/args/zkvm.rs similarity index 98% rename from library/std/src/sys/pal/zkvm/args.rs rename to library/std/src/sys/args/zkvm.rs index 47857f6c448b..194ba7159d45 100644 --- a/library/std/src/sys/pal/zkvm/args.rs +++ b/library/std/src/sys/args/zkvm.rs @@ -1,7 +1,7 @@ -use super::{WORD_SIZE, abi}; use crate::ffi::OsString; use crate::fmt; use crate::sys::os_str; +use crate::sys::pal::{WORD_SIZE, abi}; use crate::sys_common::FromInner; pub struct Args { diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs index f8f220fafd1d..bc4bf11cb740 100644 --- a/library/std/src/sys/mod.rs +++ b/library/std/src/sys/mod.rs @@ -9,6 +9,7 @@ mod alloc; mod personality; pub mod anonymous_pipe; +pub mod args; pub mod backtrace; pub mod cmath; pub mod exit_guard; diff --git a/library/std/src/sys/pal/hermit/mod.rs b/library/std/src/sys/pal/hermit/mod.rs index 26211bcb1520..821836824e2b 100644 --- a/library/std/src/sys/pal/hermit/mod.rs +++ b/library/std/src/sys/pal/hermit/mod.rs @@ -18,7 +18,6 @@ use crate::os::raw::c_char; -pub mod args; pub mod env; pub mod futex; pub mod os; @@ -58,7 +57,7 @@ pub extern "C" fn __rust_abort() { // NOTE: this is not guaranteed to run, for example when Rust code is called externally. pub unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) { unsafe { - args::init(argc, argv); + crate::sys::args::init(argc, argv); } } diff --git a/library/std/src/sys/pal/sgx/mod.rs b/library/std/src/sys/pal/sgx/mod.rs index 52684e18ac27..8a87e7a7ae13 100644 --- a/library/std/src/sys/pal/sgx/mod.rs +++ b/library/std/src/sys/pal/sgx/mod.rs @@ -9,7 +9,6 @@ use crate::io::ErrorKind; use crate::sync::atomic::{AtomicBool, Ordering}; pub mod abi; -pub mod args; pub mod env; mod libunwind_integration; pub mod os; @@ -24,7 +23,7 @@ pub mod waitqueue; // NOTE: this is not guaranteed to run, for example when Rust code is called externally. pub unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) { unsafe { - args::init(argc, argv); + crate::sys::args::init(argc, argv); } } diff --git a/library/std/src/sys/pal/solid/mod.rs b/library/std/src/sys/pal/solid/mod.rs index 22052a168fd1..c41dc848a1b4 100644 --- a/library/std/src/sys/pal/solid/mod.rs +++ b/library/std/src/sys/pal/solid/mod.rs @@ -16,8 +16,6 @@ pub mod itron { use super::unsupported; } -#[path = "../unsupported/args.rs"] -pub mod args; pub mod env; // `error` is `pub(crate)` so that it can be accessed by `itron/error.rs` as // `crate::sys::error` diff --git a/library/std/src/sys/pal/teeos/mod.rs b/library/std/src/sys/pal/teeos/mod.rs index c1921a2f40df..b8095cec3e97 100644 --- a/library/std/src/sys/pal/teeos/mod.rs +++ b/library/std/src/sys/pal/teeos/mod.rs @@ -6,8 +6,6 @@ #![allow(unused_variables)] #![allow(dead_code)] -#[path = "../unsupported/args.rs"] -pub mod args; #[path = "../unsupported/env.rs"] pub mod env; //pub mod fd; diff --git a/library/std/src/sys/pal/trusty/mod.rs b/library/std/src/sys/pal/trusty/mod.rs index 5295d3fdc914..04e6b4c81868 100644 --- a/library/std/src/sys/pal/trusty/mod.rs +++ b/library/std/src/sys/pal/trusty/mod.rs @@ -1,7 +1,5 @@ //! System bindings for the Trusty OS. -#[path = "../unsupported/args.rs"] -pub mod args; #[path = "../unsupported/common.rs"] #[deny(unsafe_op_in_unsafe_fn)] mod common; diff --git a/library/std/src/sys/pal/uefi/mod.rs b/library/std/src/sys/pal/uefi/mod.rs index 9760a23084aa..cd901f48b76f 100644 --- a/library/std/src/sys/pal/uefi/mod.rs +++ b/library/std/src/sys/pal/uefi/mod.rs @@ -13,7 +13,6 @@ //! [`OsString`]: crate::ffi::OsString #![forbid(unsafe_op_in_unsafe_fn)] -pub mod args; pub mod env; pub mod helpers; pub mod os; diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs index d7106c339747..20078839a14e 100644 --- a/library/std/src/sys/pal/unix/mod.rs +++ b/library/std/src/sys/pal/unix/mod.rs @@ -6,7 +6,6 @@ use crate::io::ErrorKind; #[macro_use] pub mod weak; -pub mod args; pub mod env; #[cfg(target_os = "fuchsia")] pub mod fuchsia; @@ -47,7 +46,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { reset_sigpipe(sigpipe); stack_overflow::init(); - args::init(argc, argv); + crate::sys::args::init(argc, argv); // Normally, `thread::spawn` will call `Thread::set_name` but since this thread // already exists, we have to call it ourselves. We only do this on Apple targets diff --git a/library/std/src/sys/pal/unsupported/mod.rs b/library/std/src/sys/pal/unsupported/mod.rs index 38838b915b5c..dea42a95dcc6 100644 --- a/library/std/src/sys/pal/unsupported/mod.rs +++ b/library/std/src/sys/pal/unsupported/mod.rs @@ -1,6 +1,5 @@ #![deny(unsafe_op_in_unsafe_fn)] -pub mod args; pub mod env; pub mod os; pub mod pipe; diff --git a/library/std/src/sys/pal/wasi/mod.rs b/library/std/src/sys/pal/wasi/mod.rs index 80853e7b5a26..4ea42b1082b1 100644 --- a/library/std/src/sys/pal/wasi/mod.rs +++ b/library/std/src/sys/pal/wasi/mod.rs @@ -13,7 +13,6 @@ //! compiling for wasm. That way it's a compile time error for something that's //! guaranteed to be a runtime error! -pub mod args; pub mod env; #[allow(unused)] #[path = "../wasm/atomics/futex.rs"] diff --git a/library/std/src/sys/pal/wasip2/mod.rs b/library/std/src/sys/pal/wasip2/mod.rs index 504b947d09e2..6445bf2cc0d2 100644 --- a/library/std/src/sys/pal/wasip2/mod.rs +++ b/library/std/src/sys/pal/wasip2/mod.rs @@ -6,8 +6,6 @@ //! To begin with, this target mirrors the wasi target 1 to 1, but over //! time this will change significantly. -#[path = "../wasi/args.rs"] -pub mod args; #[path = "../wasi/env.rs"] pub mod env; #[allow(unused)] diff --git a/library/std/src/sys/pal/wasm/mod.rs b/library/std/src/sys/pal/wasm/mod.rs index 8d39b70d0397..af370020d96a 100644 --- a/library/std/src/sys/pal/wasm/mod.rs +++ b/library/std/src/sys/pal/wasm/mod.rs @@ -16,8 +16,6 @@ #![deny(unsafe_op_in_unsafe_fn)] -#[path = "../unsupported/args.rs"] -pub mod args; pub mod env; #[path = "../unsupported/os.rs"] pub mod os; diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs index bdf0cc2c59cf..3c0a5c2de263 100644 --- a/library/std/src/sys/pal/windows/mod.rs +++ b/library/std/src/sys/pal/windows/mod.rs @@ -14,7 +14,6 @@ pub mod compat; pub mod api; -pub mod args; pub mod c; pub mod env; #[cfg(not(target_vendor = "win7"))] diff --git a/library/std/src/sys/pal/xous/mod.rs b/library/std/src/sys/pal/xous/mod.rs index 58926e2beb1d..4f652d3f130d 100644 --- a/library/std/src/sys/pal/xous/mod.rs +++ b/library/std/src/sys/pal/xous/mod.rs @@ -1,6 +1,5 @@ #![forbid(unsafe_op_in_unsafe_fn)] -pub mod args; #[path = "../unsupported/env.rs"] pub mod env; pub mod os; diff --git a/library/std/src/sys/pal/zkvm/mod.rs b/library/std/src/sys/pal/zkvm/mod.rs index 4659dad16e85..ebd7b0367798 100644 --- a/library/std/src/sys/pal/zkvm/mod.rs +++ b/library/std/src/sys/pal/zkvm/mod.rs @@ -8,11 +8,9 @@ //! will likely change over time. #![forbid(unsafe_op_in_unsafe_fn)] -const WORD_SIZE: usize = size_of::(); +pub const WORD_SIZE: usize = size_of::(); pub mod abi; -#[path = "../zkvm/args.rs"] -pub mod args; pub mod env; pub mod os; #[path = "../unsupported/pipe.rs"] From 6c6a39e6bfd10bccbf6ca99479655a9ef8d87b39 Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Sat, 12 Apr 2025 10:49:39 +0000 Subject: [PATCH 389/606] cfg(kcfi) --- library/core/src/fmt/mod.rs | 2 +- library/core/src/fmt/rt.rs | 7 +++++++ tests/coverage/closure.cov-map | 18 ++++++++++-------- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 580f95eddce7..7ca390941bcd 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -7,7 +7,7 @@ use crate::char::{EscapeDebugExtArgs, MAX_LEN_UTF8}; use crate::marker::PhantomData; use crate::num::fmt as numfmt; use crate::ops::Deref; -use crate::{iter, result, str}; +use crate::{iter, mem, result, str}; mod builders; #[cfg(not(no_fp_fmt_parse))] diff --git a/library/core/src/fmt/rt.rs b/library/core/src/fmt/rt.rs index 702aa7e34369..c36feff0b62d 100644 --- a/library/core/src/fmt/rt.rs +++ b/library/core/src/fmt/rt.rs @@ -72,6 +72,13 @@ macro_rules! argument_new { // a `fn(&T, ...)`, so the invariant is maintained. ty: ArgumentType::Placeholder { value: NonNull::<$t>::from_ref($x).cast(), + #[cfg(not(any(sanitize = "cfi", sanitize = "kcfi")))] + formatter: { + let f: fn(&$t, &mut Formatter<'_>) -> Result = $f; + // SAFETY: This is only called with `value`, which has the right type. + unsafe { mem::transmute(f) } + }, + #[cfg(any(sanitize = "cfi", sanitize = "kcfi"))] formatter: |ptr: NonNull<()>, fmt: &mut Formatter<'_>| { let func = $f; // SAFETY: This is the same type as the `value` field. diff --git a/tests/coverage/closure.cov-map b/tests/coverage/closure.cov-map index 640f98956840..2d784ba09b60 100644 --- a/tests/coverage/closure.cov-map +++ b/tests/coverage/closure.cov-map @@ -140,17 +140,19 @@ Number of file 0 mappings: 6 - Code(Counter(0)) at (prev + 2, 9) to (start + 0, 10) Highest counter ID seen: c1 -Function name: closure::main::{closure#18} (unused) -Raw bytes (24): 0x[01, 01, 00, 04, 00, 19, 0d, 02, 1c, 00, 02, 1d, 02, 12, 00, 02, 11, 00, 12, 00, 01, 11, 01, 0e] +Function name: closure::main::{closure#18} +Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 19, 0d, 02, 1c, 05, 02, 1d, 02, 12, 02, 02, 11, 00, 12, 01, 01, 11, 01, 0e] Number of files: 1 - file 0 => global file 1 -Number of expressions: 0 +Number of expressions: 1 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 4 -- Code(Zero) at (prev + 25, 13) to (start + 2, 28) -- Code(Zero) at (prev + 2, 29) to (start + 2, 18) -- Code(Zero) at (prev + 2, 17) to (start + 0, 18) -- Code(Zero) at (prev + 1, 17) to (start + 1, 14) -Highest counter ID seen: (none) +- Code(Counter(0)) at (prev + 25, 13) to (start + 2, 28) +- Code(Counter(1)) at (prev + 2, 29) to (start + 2, 18) +- Code(Expression(0, Sub)) at (prev + 2, 17) to (start + 0, 18) + = (c0 - c1) +- Code(Counter(0)) at (prev + 1, 17) to (start + 1, 14) +Highest counter ID seen: c1 Function name: closure::main::{closure#19} Raw bytes (26): 0x[01, 01, 01, 01, 05, 04, 01, 43, 0d, 02, 1c, 05, 02, 1d, 02, 12, 02, 02, 11, 00, 12, 01, 01, 11, 01, 0e] From e014fd6b872edd1af42b00d33a963632107618f9 Mon Sep 17 00:00:00 2001 From: Thalia Archibald Date: Sat, 12 Apr 2025 02:37:24 -0700 Subject: [PATCH 390/606] Use unsupported args for espidf and vita --- library/std/src/sys/args/mod.rs | 2 +- library/std/src/sys/args/unix.rs | 13 ------------- library/std/src/sys/pal/unix/mod.rs | 2 ++ 3 files changed, 3 insertions(+), 14 deletions(-) diff --git a/library/std/src/sys/args/mod.rs b/library/std/src/sys/args/mod.rs index 6edcafe2c4c5..f24d6eb123e0 100644 --- a/library/std/src/sys/args/mod.rs +++ b/library/std/src/sys/args/mod.rs @@ -3,7 +3,7 @@ #![forbid(unsafe_op_in_unsafe_fn)] cfg_if::cfg_if! { - if #[cfg(target_family = "unix")] { + if #[cfg(all(target_family = "unix", not(any(target_os = "espidf", target_os = "vita"))))] { mod unix; pub use unix::*; } else if #[cfg(target_family = "windows")] { diff --git a/library/std/src/sys/args/unix.rs b/library/std/src/sys/args/unix.rs index 4c30609c0995..13c459f682ff 100644 --- a/library/std/src/sys/args/unix.rs +++ b/library/std/src/sys/args/unix.rs @@ -226,16 +226,3 @@ mod imp { (argc as isize, argv.cast()) } } - -#[cfg(any(target_os = "espidf", target_os = "vita"))] -mod imp { - use crate::ffi::c_char; - use crate::ptr; - - #[inline(always)] - pub unsafe fn init(_argc: isize, _argv: *const *const u8) {} - - pub fn argc_argv() -> (isize, *const *const c_char) { - (0, ptr::null()) - } -} diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs index 20078839a14e..f8733eb61198 100644 --- a/library/std/src/sys/pal/unix/mod.rs +++ b/library/std/src/sys/pal/unix/mod.rs @@ -26,6 +26,7 @@ pub mod time; pub fn init(_argc: isize, _argv: *const *const u8, _sigpipe: u8) {} #[cfg(not(target_os = "espidf"))] +#[cfg_attr(target_os = "vita", allow(unused_variables))] // SAFETY: must be called only once during runtime initialization. // NOTE: this is not guaranteed to run, for example when Rust code is called externally. // See `fn init()` in `library/std/src/rt.rs` for docs on `sigpipe`. @@ -46,6 +47,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { reset_sigpipe(sigpipe); stack_overflow::init(); + #[cfg(not(target_os = "vita"))] crate::sys::args::init(argc, argv); // Normally, `thread::spawn` will call `Thread::set_name` but since this thread From c36e8fcc3c128e31eaa643904c9b8b33d9a5c1a6 Mon Sep 17 00:00:00 2001 From: Yotam Ofek Date: Fri, 11 Apr 2025 14:26:26 +0000 Subject: [PATCH 391/606] In `rustc_mir_tranform`, iterate over index newtypes instead of ints --- compiler/rustc_index_macros/src/newtype.rs | 7 +++ compiler/rustc_mir_transform/src/coroutine.rs | 53 ++++++++----------- .../src/early_otherwise_branch.rs | 3 +- .../rustc_mir_transform/src/match_branches.rs | 17 +++--- .../src/multiple_return_terminators.rs | 14 +++-- compiler/rustc_mir_transform/src/validate.rs | 5 +- 6 files changed, 46 insertions(+), 53 deletions(-) diff --git a/compiler/rustc_index_macros/src/newtype.rs b/compiler/rustc_index_macros/src/newtype.rs index f0b58eabbff9..eedbe630cf2c 100644 --- a/compiler/rustc_index_macros/src/newtype.rs +++ b/compiler/rustc_index_macros/src/newtype.rs @@ -257,6 +257,13 @@ impl Parse for Newtype { } } + impl std::ops::AddAssign for #name { + #[inline] + fn add_assign(&mut self, other: usize) { + *self = *self + other; + } + } + impl rustc_index::Idx for #name { #[inline] fn new(value: usize) -> Self { diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 04d96f117072..80c729d66b1e 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -547,7 +547,7 @@ fn transform_async_context<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let get_context_def_id = tcx.require_lang_item(LangItem::GetContext, None); - for bb in START_BLOCK..body.basic_blocks.next_index() { + for bb in body.basic_blocks.indices() { let bb_data = &body[bb]; if bb_data.is_cleanup { continue; @@ -556,11 +556,11 @@ fn transform_async_context<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { match &bb_data.terminator().kind { TerminatorKind::Call { func, .. } => { let func_ty = func.ty(body, tcx); - if let ty::FnDef(def_id, _) = *func_ty.kind() { - if def_id == get_context_def_id { - let local = eliminate_get_context_call(&mut body[bb]); - replace_resume_ty_local(tcx, body, local, context_mut_ref); - } + if let ty::FnDef(def_id, _) = *func_ty.kind() + && def_id == get_context_def_id + { + let local = eliminate_get_context_call(&mut body[bb]); + replace_resume_ty_local(tcx, body, local, context_mut_ref); } } TerminatorKind::Yield { resume_arg, .. } => { @@ -1057,7 +1057,7 @@ fn insert_switch<'tcx>( let blocks = body.basic_blocks_mut().iter_mut(); for target in blocks.flat_map(|b| b.terminator_mut().successors_mut()) { - *target = BasicBlock::new(target.index() + 1); + *target += 1; } } @@ -1209,14 +1209,8 @@ fn can_return<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, typing_env: ty::Typing } // If there's a return terminator the function may return. - for block in body.basic_blocks.iter() { - if let TerminatorKind::Return = block.terminator().kind { - return true; - } - } - + body.basic_blocks.iter().any(|block| matches!(block.terminator().kind, TerminatorKind::Return)) // Otherwise the function can't return. - false } fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool { @@ -1293,12 +1287,12 @@ fn create_coroutine_resume_function<'tcx>( kind: TerminatorKind::Goto { target: poison_block }, }; } - } else if !block.is_cleanup { + } else if !block.is_cleanup // Any terminators that *can* unwind but don't have an unwind target set are also // pointed at our poisoning block (unless they're part of the cleanup path). - if let Some(unwind @ UnwindAction::Continue) = block.terminator_mut().unwind_mut() { - *unwind = UnwindAction::Cleanup(poison_block); - } + && let Some(unwind @ UnwindAction::Continue) = block.terminator_mut().unwind_mut() + { + *unwind = UnwindAction::Cleanup(poison_block); } } } @@ -1340,12 +1334,14 @@ fn create_coroutine_resume_function<'tcx>( make_coroutine_state_argument_indirect(tcx, body); match transform.coroutine_kind { + CoroutineKind::Coroutine(_) + | CoroutineKind::Desugared(CoroutineDesugaring::Async | CoroutineDesugaring::AsyncGen, _) => + { + make_coroutine_state_argument_pinned(tcx, body); + } // Iterator::next doesn't accept a pinned argument, // unlike for all other coroutine kinds. CoroutineKind::Desugared(CoroutineDesugaring::Gen, _) => {} - _ => { - make_coroutine_state_argument_pinned(tcx, body); - } } // Make sure we remove dead blocks to remove @@ -1408,8 +1404,7 @@ fn create_cases<'tcx>( let mut statements = Vec::new(); // Create StorageLive instructions for locals with live storage - for i in 0..(body.local_decls.len()) { - let l = Local::new(i); + for l in body.local_decls.indices() { let needs_storage_live = point.storage_liveness.contains(l) && !transform.remap.contains(l) && !transform.always_live_locals.contains(l); @@ -1535,15 +1530,10 @@ impl<'tcx> crate::MirPass<'tcx> for StateTransform { let coroutine_kind = body.coroutine_kind().unwrap(); // Get the discriminant type and args which typeck computed - let (discr_ty, movable) = match *coroutine_ty.kind() { - ty::Coroutine(_, args) => { - let args = args.as_coroutine(); - (args.discr_ty(tcx), coroutine_kind.movability() == hir::Movability::Movable) - } - _ => { - tcx.dcx().span_bug(body.span, format!("unexpected coroutine type {coroutine_ty}")); - } + let ty::Coroutine(_, args) = coroutine_ty.kind() else { + tcx.dcx().span_bug(body.span, format!("unexpected coroutine type {coroutine_ty}")); }; + let discr_ty = args.as_coroutine().discr_ty(tcx); let new_ret_ty = match coroutine_kind { CoroutineKind::Desugared(CoroutineDesugaring::Async, _) => { @@ -1610,6 +1600,7 @@ impl<'tcx> crate::MirPass<'tcx> for StateTransform { let always_live_locals = always_storage_live_locals(body); + let movable = coroutine_kind.movability() == hir::Movability::Movable; let liveness_info = locals_live_across_suspend_points(tcx, body, &always_live_locals, movable); diff --git a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs index 57f7893be1b8..d49f5d9f9c38 100644 --- a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs +++ b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs @@ -103,9 +103,8 @@ impl<'tcx> crate::MirPass<'tcx> for EarlyOtherwiseBranch { let mut should_cleanup = false; // Also consider newly generated bbs in the same pass - for i in 0..body.basic_blocks.len() { + for parent in body.basic_blocks.indices() { let bbs = &*body.basic_blocks; - let parent = BasicBlock::from_usize(i); let Some(opt_data) = evaluate_candidate(tcx, body, parent) else { continue }; trace!("SUCCESS: found optimization possibility to apply: {opt_data:?}"); diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs index 0d9d0368d372..5059837328e2 100644 --- a/compiler/rustc_mir_transform/src/match_branches.rs +++ b/compiler/rustc_mir_transform/src/match_branches.rs @@ -20,13 +20,11 @@ impl<'tcx> crate::MirPass<'tcx> for MatchBranchSimplification { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let typing_env = body.typing_env(tcx); let mut should_cleanup = false; - for i in 0..body.basic_blocks.len() { - let bbs = &*body.basic_blocks; - let bb_idx = BasicBlock::from_usize(i); - match bbs[bb_idx].terminator().kind { + for bb_idx in body.basic_blocks.indices() { + match &body.basic_blocks[bb_idx].terminator().kind { TerminatorKind::SwitchInt { - discr: ref _discr @ (Operand::Copy(_) | Operand::Move(_)), - ref targets, + discr: Operand::Copy(_) | Operand::Move(_), + targets, .. // We require that the possible target blocks don't contain this block. } if !targets.all_targets().contains(&bb_idx) => {} @@ -66,9 +64,10 @@ trait SimplifyMatch<'tcx> { typing_env: ty::TypingEnv<'tcx>, ) -> Option<()> { let bbs = &body.basic_blocks; - let (discr, targets) = match bbs[switch_bb_idx].terminator().kind { - TerminatorKind::SwitchInt { ref discr, ref targets, .. } => (discr, targets), - _ => unreachable!(), + let TerminatorKind::SwitchInt { discr, targets, .. } = + &bbs[switch_bb_idx].terminator().kind + else { + unreachable!(); }; let discr_ty = discr.ty(body.local_decls(), tcx); diff --git a/compiler/rustc_mir_transform/src/multiple_return_terminators.rs b/compiler/rustc_mir_transform/src/multiple_return_terminators.rs index c63bfdcee855..f59b849e85c6 100644 --- a/compiler/rustc_mir_transform/src/multiple_return_terminators.rs +++ b/compiler/rustc_mir_transform/src/multiple_return_terminators.rs @@ -18,19 +18,17 @@ impl<'tcx> crate::MirPass<'tcx> for MultipleReturnTerminators { // find basic blocks with no statement and a return terminator let mut bbs_simple_returns = DenseBitSet::new_empty(body.basic_blocks.len()); let bbs = body.basic_blocks_mut(); - for idx in bbs.indices() { - if bbs[idx].statements.is_empty() - && bbs[idx].terminator().kind == TerminatorKind::Return - { + for (idx, bb) in bbs.iter_enumerated() { + if bb.statements.is_empty() && bb.terminator().kind == TerminatorKind::Return { bbs_simple_returns.insert(idx); } } for bb in bbs { - if let TerminatorKind::Goto { target } = bb.terminator().kind { - if bbs_simple_returns.contains(target) { - bb.terminator_mut().kind = TerminatorKind::Return; - } + if let TerminatorKind::Goto { target } = bb.terminator().kind + && bbs_simple_returns.contains(target) + { + bb.terminator_mut().kind = TerminatorKind::Return; } } diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index e7930f0a1e3f..66fe3ef4141f 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -221,12 +221,11 @@ impl<'a, 'tcx> CfgChecker<'a, 'tcx> { // Check for cycles let mut stack = FxHashSet::default(); - for i in 0..parent.len() { - let mut bb = BasicBlock::from_usize(i); + for (mut bb, parent) in parent.iter_enumerated_mut() { stack.clear(); stack.insert(bb); loop { - let Some(parent) = parent[bb].take() else { break }; + let Some(parent) = parent.take() else { break }; let no_cycle = stack.insert(parent); if !no_cycle { self.fail( From bea202253ec03e2fdc4c97915a24ebe530277edf Mon Sep 17 00:00:00 2001 From: Thalia Archibald Date: Sat, 12 Apr 2025 04:29:12 -0700 Subject: [PATCH 392/606] Unify owned Args types between platforms --- library/std/src/sys/args/common.rs | 43 ++++++++++++++++++++++++++ library/std/src/sys/args/hermit.rs | 43 ++++---------------------- library/std/src/sys/args/uefi.rs | 47 ++++------------------------- library/std/src/sys/args/unix.rs | 44 ++++----------------------- library/std/src/sys/args/wasi.rs | 40 +++--------------------- library/std/src/sys/args/windows.rs | 40 ++++-------------------- library/std/src/sys/args/xous.rs | 42 ++++---------------------- 7 files changed, 77 insertions(+), 222 deletions(-) create mode 100644 library/std/src/sys/args/common.rs diff --git a/library/std/src/sys/args/common.rs b/library/std/src/sys/args/common.rs new file mode 100644 index 000000000000..43ac5e959234 --- /dev/null +++ b/library/std/src/sys/args/common.rs @@ -0,0 +1,43 @@ +use crate::ffi::OsString; +use crate::{fmt, vec}; + +pub struct Args { + iter: vec::IntoIter, +} + +impl !Send for Args {} +impl !Sync for Args {} + +impl Args { + pub(super) fn new(args: Vec) -> Self { + Args { iter: args.into_iter() } + } +} + +impl fmt::Debug for Args { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.iter.as_slice().fmt(f) + } +} + +impl Iterator for Args { + type Item = OsString; + fn next(&mut self) -> Option { + self.iter.next() + } + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +impl ExactSizeIterator for Args { + fn len(&self) -> usize { + self.iter.len() + } +} + +impl DoubleEndedIterator for Args { + fn next_back(&mut self) -> Option { + self.iter.next_back() + } +} diff --git a/library/std/src/sys/args/hermit.rs b/library/std/src/sys/args/hermit.rs index 440242602773..ddd644a55404 100644 --- a/library/std/src/sys/args/hermit.rs +++ b/library/std/src/sys/args/hermit.rs @@ -1,8 +1,12 @@ use crate::ffi::{CStr, OsString, c_char}; use crate::os::hermit::ffi::OsStringExt; +use crate::ptr; use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release}; use crate::sync::atomic::{AtomicIsize, AtomicPtr}; -use crate::{fmt, ptr, vec}; + +#[path = "common.rs"] +mod common; +pub use common::Args; static ARGC: AtomicIsize = AtomicIsize::new(0); static ARGV: AtomicPtr<*const u8> = AtomicPtr::new(ptr::null_mut()); @@ -27,40 +31,5 @@ pub fn args() -> Args { }) .collect(); - Args { iter: args.into_iter() } -} - -pub struct Args { - iter: vec::IntoIter, -} - -impl fmt::Debug for Args { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.iter.as_slice().fmt(f) - } -} - -impl !Send for Args {} -impl !Sync for Args {} - -impl Iterator for Args { - type Item = OsString; - fn next(&mut self) -> Option { - self.iter.next() - } - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() - } -} - -impl ExactSizeIterator for Args { - fn len(&self) -> usize { - self.iter.len() - } -} - -impl DoubleEndedIterator for Args { - fn next_back(&mut self) -> Option { - self.iter.next_back() - } + Args::new(args) } diff --git a/library/std/src/sys/args/uefi.rs b/library/std/src/sys/args/uefi.rs index 4e7412937bd1..84406c7f69df 100644 --- a/library/std/src/sys/args/uefi.rs +++ b/library/std/src/sys/args/uefi.rs @@ -4,11 +4,10 @@ use crate::env::current_exe; use crate::ffi::OsString; use crate::iter::Iterator; use crate::sys::pal::helpers; -use crate::{fmt, vec}; -pub struct Args { - parsed_args_list: vec::IntoIter, -} +#[path = "common.rs"] +mod common; +pub use common::Args; pub fn args() -> Args { let lazy_current_exe = || Vec::from([current_exe().map(Into::into).unwrap_or_default()]); @@ -22,51 +21,17 @@ pub fn args() -> Args { let lp_size = unsafe { (*protocol.as_ptr()).load_options_size } as usize; // Break if we are sure that it cannot be UTF-16 if lp_size < size_of::() || lp_size % size_of::() != 0 { - return Args { parsed_args_list: lazy_current_exe().into_iter() }; + return Args::new(lazy_current_exe()); } let lp_size = lp_size / size_of::(); let lp_cmd_line = unsafe { (*protocol.as_ptr()).load_options as *const u16 }; if !lp_cmd_line.is_aligned() { - return Args { parsed_args_list: lazy_current_exe().into_iter() }; + return Args::new(lazy_current_exe()); } let lp_cmd_line = unsafe { crate::slice::from_raw_parts(lp_cmd_line, lp_size) }; - Args { - parsed_args_list: parse_lp_cmd_line(lp_cmd_line) - .unwrap_or_else(lazy_current_exe) - .into_iter(), - } -} - -impl fmt::Debug for Args { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.parsed_args_list.as_slice().fmt(f) - } -} - -impl Iterator for Args { - type Item = OsString; - - fn next(&mut self) -> Option { - self.parsed_args_list.next() - } - - fn size_hint(&self) -> (usize, Option) { - self.parsed_args_list.size_hint() - } -} - -impl ExactSizeIterator for Args { - fn len(&self) -> usize { - self.parsed_args_list.len() - } -} - -impl DoubleEndedIterator for Args { - fn next_back(&mut self) -> Option { - self.parsed_args_list.next_back() - } + Args::new(parse_lp_cmd_line(lp_cmd_line).unwrap_or_else(lazy_current_exe)) } /// Implements the UEFI command-line argument parsing algorithm. diff --git a/library/std/src/sys/args/unix.rs b/library/std/src/sys/args/unix.rs index 13c459f682ff..7d7815c6dff2 100644 --- a/library/std/src/sys/args/unix.rs +++ b/library/std/src/sys/args/unix.rs @@ -5,9 +5,12 @@ #![allow(dead_code)] // runtime init functions not used during testing -use crate::ffi::{CStr, OsString}; +use crate::ffi::CStr; use crate::os::unix::ffi::OsStringExt; -use crate::{fmt, vec}; + +#[path = "common.rs"] +mod common; +pub use common::Args; /// One-time global initialization. pub unsafe fn init(argc: isize, argv: *const *const u8) { @@ -55,42 +58,7 @@ pub fn args() -> Args { vec.push(OsStringExt::from_vec(cstr.to_bytes().to_vec())); } - Args { iter: vec.into_iter() } -} - -pub struct Args { - iter: vec::IntoIter, -} - -impl !Send for Args {} -impl !Sync for Args {} - -impl fmt::Debug for Args { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.iter.as_slice().fmt(f) - } -} - -impl Iterator for Args { - type Item = OsString; - fn next(&mut self) -> Option { - self.iter.next() - } - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() - } -} - -impl ExactSizeIterator for Args { - fn len(&self) -> usize { - self.iter.len() - } -} - -impl DoubleEndedIterator for Args { - fn next_back(&mut self) -> Option { - self.iter.next_back() - } + Args::new(vec) } #[cfg(any( diff --git a/library/std/src/sys/args/wasi.rs b/library/std/src/sys/args/wasi.rs index 52cfa202af82..4795789e4c71 100644 --- a/library/std/src/sys/args/wasi.rs +++ b/library/std/src/sys/args/wasi.rs @@ -2,18 +2,14 @@ use crate::ffi::{CStr, OsStr, OsString}; use crate::os::wasi::ffi::OsStrExt; -use crate::{fmt, vec}; -pub struct Args { - iter: vec::IntoIter, -} - -impl !Send for Args {} -impl !Sync for Args {} +#[path = "common.rs"] +mod common; +pub use common::Args; /// Returns the command line arguments pub fn args() -> Args { - Args { iter: maybe_args().unwrap_or(Vec::new()).into_iter() } + Args::new(maybe_args().unwrap_or(Vec::new())) } fn maybe_args() -> Option> { @@ -31,31 +27,3 @@ fn maybe_args() -> Option> { Some(ret) } } - -impl fmt::Debug for Args { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.iter.as_slice().fmt(f) - } -} - -impl Iterator for Args { - type Item = OsString; - fn next(&mut self) -> Option { - self.iter.next() - } - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() - } -} - -impl ExactSizeIterator for Args { - fn len(&self) -> usize { - self.iter.len() - } -} - -impl DoubleEndedIterator for Args { - fn next_back(&mut self) -> Option { - self.iter.next_back() - } -} diff --git a/library/std/src/sys/args/windows.rs b/library/std/src/sys/args/windows.rs index 55bd6864cae3..47f0e5f2d05f 100644 --- a/library/std/src/sys/args/windows.rs +++ b/library/std/src/sys/args/windows.rs @@ -16,7 +16,11 @@ use crate::sys::path::get_long_path; use crate::sys::{c, to_u16s}; use crate::sys_common::AsInner; use crate::sys_common::wstr::WStrUnits; -use crate::{fmt, io, iter, ptr, vec}; +use crate::{io, iter, ptr}; + +#[path = "common.rs"] +mod common; +pub use common::Args; pub fn args() -> Args { // SAFETY: `GetCommandLineW` returns a pointer to a null terminated UTF-16 @@ -27,7 +31,7 @@ pub fn args() -> Args { current_exe().map(PathBuf::into_os_string).unwrap_or_else(|_| OsString::new()) }); - Args { parsed_args_list: parsed_args_list.into_iter() } + Args::new(parsed_args_list) } } @@ -153,38 +157,6 @@ fn parse_lp_cmd_line<'a, F: Fn() -> OsString>( ret_val } -pub struct Args { - parsed_args_list: vec::IntoIter, -} - -impl fmt::Debug for Args { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.parsed_args_list.as_slice().fmt(f) - } -} - -impl Iterator for Args { - type Item = OsString; - fn next(&mut self) -> Option { - self.parsed_args_list.next() - } - fn size_hint(&self) -> (usize, Option) { - self.parsed_args_list.size_hint() - } -} - -impl DoubleEndedIterator for Args { - fn next_back(&mut self) -> Option { - self.parsed_args_list.next_back() - } -} - -impl ExactSizeIterator for Args { - fn len(&self) -> usize { - self.parsed_args_list.len() - } -} - #[derive(Debug)] pub(crate) enum Arg { /// Add quotes (if needed) diff --git a/library/std/src/sys/args/xous.rs b/library/std/src/sys/args/xous.rs index 2dd37d53422f..09a47283d657 100644 --- a/library/std/src/sys/args/xous.rs +++ b/library/std/src/sys/args/xous.rs @@ -1,15 +1,13 @@ -use crate::ffi::OsString; use crate::sys::pal::os::get_application_parameters; use crate::sys::pal::os::params::ArgumentList; -use crate::{fmt, vec}; -pub struct Args { - parsed_args_list: vec::IntoIter, -} +#[path = "common.rs"] +mod common; +pub use common::Args; pub fn args() -> Args { let Some(params) = get_application_parameters() else { - return Args { parsed_args_list: vec![].into_iter() }; + return Args::new(vec![]); }; for param in params { @@ -18,36 +16,8 @@ pub fn args() -> Args { for arg in args { parsed_args.push(arg.into()); } - return Args { parsed_args_list: parsed_args.into_iter() }; + return Args::new(parsed_args); } } - Args { parsed_args_list: vec![].into_iter() } -} - -impl fmt::Debug for Args { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.parsed_args_list.as_slice().fmt(f) - } -} - -impl Iterator for Args { - type Item = OsString; - fn next(&mut self) -> Option { - self.parsed_args_list.next() - } - fn size_hint(&self) -> (usize, Option) { - self.parsed_args_list.size_hint() - } -} - -impl DoubleEndedIterator for Args { - fn next_back(&mut self) -> Option { - self.parsed_args_list.next_back() - } -} - -impl ExactSizeIterator for Args { - fn len(&self) -> usize { - self.parsed_args_list.len() - } + Args::new(vec![]) } From 11256a0fb09b066f2b72f24889f8c02c2ef30098 Mon Sep 17 00:00:00 2001 From: reddevilmidzy Date: Wed, 9 Apr 2025 23:22:23 +0900 Subject: [PATCH 393/606] Add regression test for #127424 --- .../const-generics-closure.rs | 13 ++++++++++ .../const-generics-closure.stderr | 26 +++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 tests/ui/const-generics/generic_const_exprs/const-generics-closure.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/const-generics-closure.stderr diff --git a/tests/ui/const-generics/generic_const_exprs/const-generics-closure.rs b/tests/ui/const-generics/generic_const_exprs/const-generics-closure.rs new file mode 100644 index 000000000000..aad8cefe5d62 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/const-generics-closure.rs @@ -0,0 +1,13 @@ +// Regression test for issue #127424 + +fn bar() -> impl Into< + [u8; { + //~^ ERROR mismatched types [E0308] + let _ = for<'a, 'b> |x: &'a &'a Vec<&'b u32>, b: bool| -> &'a Vec<&'b u32> { *x }; + //~^ ERROR `for<...>` binders for closures are experimental [E0658] + }], +> { + [89] +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/const-generics-closure.stderr b/tests/ui/const-generics/generic_const_exprs/const-generics-closure.stderr new file mode 100644 index 000000000000..5410bbdc1253 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/const-generics-closure.stderr @@ -0,0 +1,26 @@ +error[E0658]: `for<...>` binders for closures are experimental + --> $DIR/const-generics-closure.rs:6:17 + | +LL | let _ = for<'a, 'b> |x: &'a &'a Vec<&'b u32>, b: bool| -> &'a Vec<&'b u32> { *x }; + | ^^^^^^^^^^^ + | + = note: see issue #97362 for more information + = help: add `#![feature(closure_lifetime_binder)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = help: consider removing `for<...>` + +error[E0308]: mismatched types + --> $DIR/const-generics-closure.rs:4:10 + | +LL | [u8; { + | __________^ +LL | | +LL | | let _ = for<'a, 'b> |x: &'a &'a Vec<&'b u32>, b: bool| -> &'a Vec<&'b u32> { *x }; +LL | | +LL | | }], + | |_____^ expected `usize`, found `()` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0308, E0658. +For more information about an error, try `rustc --explain E0308`. From 1baa62e88494e84c30d293c31b1d214cbe4bc643 Mon Sep 17 00:00:00 2001 From: GenYuLi Date: Sat, 12 Apr 2025 22:26:38 +0800 Subject: [PATCH 394/606] Fix typo in documentation Correct the misspelling of "indentifier" to "identifier" in `library/alloc/src/fmt.rs`. --- library/alloc/src/fmt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/alloc/src/fmt.rs b/library/alloc/src/fmt.rs index e40de13f3d4a..30f42050ac8a 100644 --- a/library/alloc/src/fmt.rs +++ b/library/alloc/src/fmt.rs @@ -109,7 +109,7 @@ //! parameters (corresponding to `format_spec` in [the syntax](#syntax)). These //! parameters affect the string representation of what's being formatted. //! -//! The colon `:` in format syntax divides indentifier of the input data and +//! The colon `:` in format syntax divides identifier of the input data and //! the formatting options, the colon itself does not change anything, only //! introduces the options. //! From 8ae6485dad1dc44943bee1a99cffc19a32f1961e Mon Sep 17 00:00:00 2001 From: bohan Date: Sat, 12 Apr 2025 23:56:48 +0800 Subject: [PATCH 395/606] don't store opaque info during encoding --- compiler/rustc_metadata/src/rmeta/mod.rs | 6 +- .../rustc_middle/src/query/on_disk_cache.rs | 5 +- compiler/rustc_middle/src/ty/parameterized.rs | 2 +- compiler/rustc_span/src/hygiene.rs | 74 +++++-------------- 4 files changed, 23 insertions(+), 64 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 2f27e5f6c5dc..5aa81f41b7b4 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -36,9 +36,7 @@ use rustc_serialize::opaque::FileEncoder; use rustc_session::config::{SymbolManglingVersion, TargetModifier}; use rustc_session::cstore::{CrateDepKind, ForeignModule, LinkagePreference, NativeLib}; use rustc_span::edition::Edition; -use rustc_span::hygiene::{ - ExpnIndex, MacroKind, SyntaxContextDataNonRecursive as SyntaxContextData, -}; +use rustc_span::hygiene::{ExpnIndex, MacroKind, SyntaxContextKey}; use rustc_span::{self, ExpnData, ExpnHash, ExpnId, Ident, Span, Symbol}; use rustc_target::spec::{PanicStrategy, TargetTuple}; use table::TableBuilder; @@ -195,7 +193,7 @@ enum LazyState { Previous(NonZero), } -type SyntaxContextTable = LazyTable>>; +type SyntaxContextTable = LazyTable>>; type ExpnDataTable = LazyTable>>; type ExpnHashTable = LazyTable>>; diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index f78398c7c37d..5431097cb1d7 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -16,8 +16,7 @@ use rustc_serialize::opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixed use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_session::Session; use rustc_span::hygiene::{ - ExpnId, HygieneDecodeContext, HygieneEncodeContext, SyntaxContext, - SyntaxContextDataNonRecursive as SyntaxContextData, + ExpnId, HygieneDecodeContext, HygieneEncodeContext, SyntaxContext, SyntaxContextKey, }; use rustc_span::source_map::Spanned; use rustc_span::{ @@ -567,7 +566,7 @@ impl<'a, 'tcx> SpanDecoder for CacheDecoder<'a, 'tcx> { // We look up the position of the associated `SyntaxData` and decode it. let pos = syntax_contexts.get(&id).unwrap(); this.with_position(pos.to_usize(), |decoder| { - let data: SyntaxContextData = decode_tagged(decoder, TAG_SYNTAX_CONTEXT); + let data: SyntaxContextKey = decode_tagged(decoder, TAG_SYNTAX_CONTEXT); data }) }) diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index b56e08626920..ecd6132b3ef3 100644 --- a/compiler/rustc_middle/src/ty/parameterized.rs +++ b/compiler/rustc_middle/src/ty/parameterized.rs @@ -113,7 +113,7 @@ trivially_parameterized_over_tcx! { rustc_span::Span, rustc_span::Symbol, rustc_span::def_id::DefPathHash, - rustc_span::hygiene::SyntaxContextDataNonRecursive, + rustc_span::hygiene::SyntaxContextKey, rustc_span::Ident, rustc_type_ir::Variance, rustc_hir::Attribute, diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 9be16f8ce0c9..33152d2d9394 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -56,7 +56,7 @@ impl !PartialOrd for SyntaxContext {} /// If this part of two syntax contexts is equal, then the whole syntax contexts should be equal. /// The other fields are only for caching. -type SyntaxContextKey = (SyntaxContext, ExpnId, Transparency); +pub type SyntaxContextKey = (SyntaxContext, ExpnId, Transparency); #[derive(Clone, Copy, Debug)] struct SyntaxContextData { @@ -71,17 +71,6 @@ struct SyntaxContextData { dollar_crate_name: Symbol, } -/// Same as `SyntaxContextData`, but `opaque(_and_semitransparent)` cannot be recursive -/// and use `None` if they need to refer to self. Used for encoding and decoding metadata. -#[derive(Encodable, Decodable)] -pub struct SyntaxContextDataNonRecursive { - outer_expn: ExpnId, - outer_transparency: Transparency, - parent: SyntaxContext, - opaque: Option, - opaque_and_semitransparent: Option, -} - impl SyntaxContextData { fn new( (parent, outer_expn, outer_transparency): SyntaxContextKey, @@ -122,19 +111,6 @@ impl SyntaxContextData { } } -impl SyntaxContextDataNonRecursive { - fn recursive(&self, ctxt: SyntaxContext) -> SyntaxContextData { - SyntaxContextData { - outer_expn: self.outer_expn, - outer_transparency: self.outer_transparency, - parent: self.parent, - opaque: self.opaque.unwrap_or(ctxt), - opaque_and_semitransparent: self.opaque_and_semitransparent.unwrap_or(ctxt), - dollar_crate_name: kw::DollarCrate, - } - } -} - rustc_index::newtype_index! { /// A unique ID associated with a macro invocation and expansion. #[orderable] @@ -658,19 +634,6 @@ impl HygieneData { SyntaxContextData::new(key, opaque, opaque_and_semitransparent); ctxt } - - fn non_recursive_ctxt(&self, ctxt: SyntaxContext) -> SyntaxContextDataNonRecursive { - debug_assert!(!self.syntax_context_data[ctxt.0 as usize].is_decode_placeholder()); - let data = &self.syntax_context_data[ctxt.0 as usize]; - SyntaxContextDataNonRecursive { - outer_expn: data.outer_expn, - outer_transparency: data.outer_transparency, - parent: data.parent, - opaque: (data.opaque != ctxt).then_some(data.opaque), - opaque_and_semitransparent: (data.opaque_and_semitransparent != ctxt) - .then_some(data.opaque_and_semitransparent), - } - } } pub fn walk_chain(span: Span, to: SyntaxContext) -> Span { @@ -1300,7 +1263,7 @@ impl HygieneEncodeContext { pub fn encode( &self, encoder: &mut T, - mut encode_ctxt: impl FnMut(&mut T, u32, &SyntaxContextDataNonRecursive), + mut encode_ctxt: impl FnMut(&mut T, u32, &SyntaxContextKey), mut encode_expn: impl FnMut(&mut T, ExpnId, &ExpnData, ExpnHash), ) { // When we serialize a `SyntaxContextData`, we may end up serializing @@ -1425,10 +1388,7 @@ pub fn decode_expn_id( // to track which `SyntaxContext`s we have already decoded. // The provided closure will be invoked to deserialize a `SyntaxContextData` // if we haven't already seen the id of the `SyntaxContext` we are deserializing. -pub fn decode_syntax_context< - D: Decoder, - F: FnOnce(&mut D, u32) -> SyntaxContextDataNonRecursive, ->( +pub fn decode_syntax_context SyntaxContextKey>( d: &mut D, context: &HygieneDecodeContext, decode_data: F, @@ -1450,16 +1410,9 @@ pub fn decode_syntax_context< // Don't try to decode data while holding the lock, since we need to // be able to recursively decode a SyntaxContext - let ctxt_data = decode_data(d, raw_id); - - let ctxt = HygieneData::with(|hygiene_data| { - let ctxt_key = (ctxt_data.parent, ctxt_data.outer_expn, ctxt_data.outer_transparency); - *hygiene_data.syntax_context_map.entry(ctxt_key).or_insert_with(|| { - let ctxt = SyntaxContext::from_usize(hygiene_data.syntax_context_data.len()); - hygiene_data.syntax_context_data.push(ctxt_data.recursive(ctxt)); - ctxt - }) - }); + let (parent, expn_id, transparency) = decode_data(d, raw_id); + let ctxt = + HygieneData::with(|hygiene_data| hygiene_data.alloc_ctxt(parent, expn_id, transparency)); let mut inner = context.inner.lock(); let new_len = raw_id as usize + 1; @@ -1471,12 +1424,21 @@ pub fn decode_syntax_context< ctxt } -fn for_all_ctxts_in( +fn for_all_ctxts_in( ctxts: impl Iterator, mut f: F, ) { - let all_data: Vec<_> = - HygieneData::with(|data| ctxts.map(|ctxt| (ctxt, data.non_recursive_ctxt(ctxt))).collect()); + let all_data: Vec<_> = HygieneData::with(|data| { + ctxts + .map(|ctxt| { + (ctxt, { + let item = data.syntax_context_data[ctxt.0 as usize]; + debug_assert!(!item.is_decode_placeholder()); + item.key() + }) + }) + .collect() + }); for (ctxt, data) in all_data.into_iter() { f(ctxt.0, ctxt, &data); } From 6ba9649e7c80b999b956adbdad3e9ecbbb1e24f3 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 12 Apr 2025 11:50:33 -0700 Subject: [PATCH 396/606] End all lines in src/stage0 with trailing newline --- src/stage0 | 2 +- src/tools/bump-stage0/src/main.rs | 25 +++++++++++++------------ 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/stage0 b/src/stage0 index b3841d253f34..6e86501a72ab 100644 --- a/src/stage0 +++ b/src/stage0 @@ -476,4 +476,4 @@ dist/2025-04-02/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz=e67a33440c3e021ff2 dist/2025-04-02/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=0ea7e17d7bb67d6a6c4b2f864aaffcd96512f15f17f0acc63751eb1df6c486a7 dist/2025-04-02/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=b73d37b704ab58921172cc561f5598db6a504dcd4d7980966f7c26caaf6d3594 dist/2025-04-02/rustc-nightly-x86_64-unknown-netbsd.tar.gz=986f6c594d37bcbd3833e053640ba8775f68d26a65c5618386654ef55d7b3542 -dist/2025-04-02/rustc-nightly-x86_64-unknown-netbsd.tar.xz=c0d9a88c30d2ab38ec3a11fabb5515ed9bc3ac1a8e35a438d68bf7ff82f6b843 \ No newline at end of file +dist/2025-04-02/rustc-nightly-x86_64-unknown-netbsd.tar.xz=c0d9a88c30d2ab38ec3a11fabb5515ed9bc3ac1a8e35a438d68bf7ff82f6b843 diff --git a/src/tools/bump-stage0/src/main.rs b/src/tools/bump-stage0/src/main.rs index f51072718a34..d679084ae44b 100644 --- a/src/tools/bump-stage0/src/main.rs +++ b/src/tools/bump-stage0/src/main.rs @@ -65,32 +65,33 @@ impl Tool { nightly_branch, } = &self.config; - file_content.push_str(&format!("dist_server={}", dist_server)); - file_content.push_str(&format!("\nartifacts_server={}", artifacts_server)); + file_content.push_str(&format!("dist_server={}\n", dist_server)); + file_content.push_str(&format!("artifacts_server={}\n", artifacts_server)); file_content.push_str(&format!( - "\nartifacts_with_llvm_assertions_server={}", + "artifacts_with_llvm_assertions_server={}\n", artifacts_with_llvm_assertions_server )); - file_content.push_str(&format!("\ngit_merge_commit_email={}", git_merge_commit_email)); - file_content.push_str(&format!("\ngit_repository={}", git_repository)); - file_content.push_str(&format!("\nnightly_branch={}", nightly_branch)); + file_content.push_str(&format!("git_merge_commit_email={}\n", git_merge_commit_email)); + file_content.push_str(&format!("git_repository={}\n", git_repository)); + file_content.push_str(&format!("nightly_branch={}\n", nightly_branch)); - file_content.push_str("\n\n"); + file_content.push_str("\n"); file_content.push_str(COMMENTS); + file_content.push_str("\n"); let compiler = self.detect_compiler()?; - file_content.push_str(&format!("\ncompiler_date={}", compiler.date)); - file_content.push_str(&format!("\ncompiler_version={}", compiler.version)); + file_content.push_str(&format!("compiler_date={}\n", compiler.date)); + file_content.push_str(&format!("compiler_version={}\n", compiler.version)); if let Some(rustfmt) = self.detect_rustfmt()? { - file_content.push_str(&format!("\nrustfmt_date={}", rustfmt.date)); - file_content.push_str(&format!("\nrustfmt_version={}", rustfmt.version)); + file_content.push_str(&format!("rustfmt_date={}\n", rustfmt.date)); + file_content.push_str(&format!("rustfmt_version={}\n", rustfmt.version)); } file_content.push_str("\n"); for (key, value) in self.checksums { - file_content.push_str(&format!("\n{}={}", key, value)); + file_content.push_str(&format!("{}={}\n", key, value)); } std::fs::write(PATH, file_content)?; From bc94c38d98b327e6a616e1b74da0143a474a3b1a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 12 Apr 2025 04:54:14 +0000 Subject: [PATCH 397/606] Proactively update coroutine drop shim's phase to account for later passes applied during shim query --- compiler/rustc_mir_transform/src/coroutine.rs | 7 +++++++ .../post-cleanup-phase-validation.rs | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 tests/ui/async-await/post-cleanup-phase-validation.rs diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 04d96f117072..02609d65b0f8 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -1169,6 +1169,13 @@ fn create_coroutine_drop_shim<'tcx>( dump_mir(tcx, false, "coroutine_drop", &0, &body, |_, _| Ok(())); body.source.instance = drop_instance; + // Creating a coroutine drop shim happens on `Analysis(PostCleanup) -> Runtime(Initial)` + // but the pass manager doesn't update the phase of the coroutine drop shim. Update the + // phase of the drop shim so that later on when we run the pass manager on the shim, in + // the `mir_shims` query, we don't ICE on the intra-pass validation before we've updated + // the phase of the body from analysis. + body.phase = MirPhase::Runtime(RuntimePhase::Initial); + body } diff --git a/tests/ui/async-await/post-cleanup-phase-validation.rs b/tests/ui/async-await/post-cleanup-phase-validation.rs new file mode 100644 index 000000000000..a347e35c26db --- /dev/null +++ b/tests/ui/async-await/post-cleanup-phase-validation.rs @@ -0,0 +1,19 @@ +//@ compile-flags: -Zvalidate-mir +//@ edition: 2024 +//@ build-pass + +// Regression test that we don't ICE when encountering a transmute in a coroutine's +// drop shim body, which is conceptually in the Runtime phase but wasn't having the +// phase updated b/c the pass manager neither optimizes nor updates the phase for +// drop shim bodies. + +struct HasDrop; +impl Drop for HasDrop { + fn drop(&mut self) {} +} + +fn main() { + async { + vec![async { HasDrop }.await]; + }; +} From accae530ce1eca367e53325e8596a83e94aac2d2 Mon Sep 17 00:00:00 2001 From: jackh726 Date: Tue, 8 Apr 2025 00:49:54 +0000 Subject: [PATCH 398/606] Move FlagComputation, PatternKind, and TypeWalker to rustc_type_ir --- compiler/rustc_middle/src/arena.rs | 1 - compiler/rustc_middle/src/ty/consts.rs | 15 + compiler/rustc_middle/src/ty/context.rs | 10 +- compiler/rustc_middle/src/ty/flags.rs | 359 ----------------- compiler/rustc_middle/src/ty/generic_args.rs | 15 + compiler/rustc_middle/src/ty/list.rs | 8 +- compiler/rustc_middle/src/ty/mod.rs | 2 - compiler/rustc_middle/src/ty/pattern.rs | 47 ++- compiler/rustc_middle/src/ty/sty.rs | 15 + compiler/rustc_type_ir/src/flags.rs | 365 ++++++++++++++++++ compiler/rustc_type_ir/src/inherent.rs | 2 +- compiler/rustc_type_ir/src/interner.rs | 10 +- compiler/rustc_type_ir/src/ir_print.rs | 7 +- compiler/rustc_type_ir/src/lib.rs | 3 + compiler/rustc_type_ir/src/pattern.rs | 16 + .../src/ty => rustc_type_ir/src}/walk.rs | 122 ++---- 16 files changed, 530 insertions(+), 467 deletions(-) delete mode 100644 compiler/rustc_middle/src/ty/flags.rs create mode 100644 compiler/rustc_type_ir/src/pattern.rs rename compiler/{rustc_middle/src/ty => rustc_type_ir/src}/walk.rs (55%) diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 98273a05446a..d1bbb0598fec 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -89,7 +89,6 @@ macro_rules! arena_types { [] name_set: rustc_data_structures::unord::UnordSet, [] autodiff_item: rustc_ast::expand::autodiff_attrs::AutoDiffItem, [] ordered_name_set: rustc_data_structures::fx::FxIndexSet, - [] pats: rustc_middle::ty::PatternKind<'tcx>, [] valtree: rustc_middle::ty::ValTreeKind<'tcx>, // Note that this deliberately duplicates items in the `rustc_hir::arena`, diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index ae1c6c670cbc..dc5fe2d8f8b0 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -3,6 +3,7 @@ use std::borrow::Cow; use rustc_data_structures::intern::Interned; use rustc_error_messages::MultiSpan; use rustc_macros::HashStable; +use rustc_type_ir::walk::TypeWalker; use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo}; use crate::ty::{self, Ty, TyCtxt}; @@ -243,4 +244,18 @@ impl<'tcx> Const<'tcx> { pub fn is_ct_infer(self) -> bool { matches!(self.kind(), ty::ConstKind::Infer(_)) } + + /// Iterator that walks `self` and any types reachable from + /// `self`, in depth-first order. Note that just walks the types + /// that appear in `self`, it does not descend into the fields of + /// structs or variants. For example: + /// + /// ```text + /// isize => { isize } + /// Foo> => { Foo>, Bar, isize } + /// [isize] => { [isize], isize } + /// ``` + pub fn walk(self) -> TypeWalker> { + TypeWalker::new(self.into()) + } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index abf6cbbcd877..6e5ac13bd2cf 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -870,7 +870,7 @@ impl<'tcx> CtxtInterners<'tcx> { Ty(Interned::new_unchecked( self.type_ .intern(kind, |kind| { - let flags = super::flags::FlagComputation::for_kind(&kind); + let flags = ty::FlagComputation::>::for_kind(&kind); let stable_hash = self.stable_hash(&flags, sess, untracked, &kind); InternedInSet(self.arena.alloc(WithCachedTypeInfo { @@ -896,7 +896,7 @@ impl<'tcx> CtxtInterners<'tcx> { Const(Interned::new_unchecked( self.const_ .intern(kind, |kind: ty::ConstKind<'_>| { - let flags = super::flags::FlagComputation::for_const_kind(&kind); + let flags = ty::FlagComputation::>::for_const_kind(&kind); let stable_hash = self.stable_hash(&flags, sess, untracked, &kind); InternedInSet(self.arena.alloc(WithCachedTypeInfo { @@ -912,7 +912,7 @@ impl<'tcx> CtxtInterners<'tcx> { fn stable_hash<'a, T: HashStable>>( &self, - flags: &ty::flags::FlagComputation, + flags: &ty::FlagComputation>, sess: &'a Session, untracked: &'a Untracked, val: &T, @@ -940,7 +940,7 @@ impl<'tcx> CtxtInterners<'tcx> { Predicate(Interned::new_unchecked( self.predicate .intern(kind, |kind| { - let flags = super::flags::FlagComputation::for_predicate(kind); + let flags = ty::FlagComputation::>::for_predicate(kind); let stable_hash = self.stable_hash(&flags, sess, untracked, &kind); @@ -961,7 +961,7 @@ impl<'tcx> CtxtInterners<'tcx> { } else { self.clauses .intern_ref(clauses, || { - let flags = super::flags::FlagComputation::for_clauses(clauses); + let flags = ty::FlagComputation::>::for_clauses(clauses); InternedInSet(ListWithCachedTypeInfo::from_arena( &*self.arena, diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs deleted file mode 100644 index 2424923fb787..000000000000 --- a/compiler/rustc_middle/src/ty/flags.rs +++ /dev/null @@ -1,359 +0,0 @@ -use std::slice; - -use crate::ty::{self, GenericArg, GenericArgKind, InferConst, Ty, TypeFlags}; - -#[derive(Debug)] -pub struct FlagComputation { - pub flags: TypeFlags, - - /// see `Ty::outer_exclusive_binder` for details - pub outer_exclusive_binder: ty::DebruijnIndex, -} - -impl FlagComputation { - fn new() -> FlagComputation { - FlagComputation { flags: TypeFlags::empty(), outer_exclusive_binder: ty::INNERMOST } - } - - #[allow(rustc::usage_of_ty_tykind)] - pub fn for_kind(kind: &ty::TyKind<'_>) -> FlagComputation { - let mut result = FlagComputation::new(); - result.add_kind(kind); - result - } - - pub fn for_predicate(binder: ty::Binder<'_, ty::PredicateKind<'_>>) -> FlagComputation { - let mut result = FlagComputation::new(); - result.add_predicate(binder); - result - } - - pub fn for_const_kind(kind: &ty::ConstKind<'_>) -> FlagComputation { - let mut result = FlagComputation::new(); - result.add_const_kind(kind); - result - } - - pub fn for_clauses(clauses: &[ty::Clause<'_>]) -> FlagComputation { - let mut result = FlagComputation::new(); - for c in clauses { - result.add_flags(c.as_predicate().flags()); - result.add_exclusive_binder(c.as_predicate().outer_exclusive_binder()); - } - result - } - - fn add_flags(&mut self, flags: TypeFlags) { - self.flags = self.flags | flags; - } - - /// indicates that `self` refers to something at binding level `binder` - fn add_bound_var(&mut self, binder: ty::DebruijnIndex) { - let exclusive_binder = binder.shifted_in(1); - self.add_exclusive_binder(exclusive_binder); - } - - /// indicates that `self` refers to something *inside* binding - /// level `binder` -- not bound by `binder`, but bound by the next - /// binder internal to it - fn add_exclusive_binder(&mut self, exclusive_binder: ty::DebruijnIndex) { - self.outer_exclusive_binder = self.outer_exclusive_binder.max(exclusive_binder); - } - - /// Adds the flags/depth from a set of types that appear within the current type, but within a - /// region binder. - fn bound_computation(&mut self, value: ty::Binder<'_, T>, f: F) - where - F: FnOnce(&mut Self, T), - { - let mut computation = FlagComputation::new(); - - if !value.bound_vars().is_empty() { - computation.add_flags(TypeFlags::HAS_BINDER_VARS); - } - - f(&mut computation, value.skip_binder()); - - self.add_flags(computation.flags); - - // The types that contributed to `computation` occurred within - // a region binder, so subtract one from the region depth - // within when adding the depth to `self`. - let outer_exclusive_binder = computation.outer_exclusive_binder; - if outer_exclusive_binder > ty::INNERMOST { - self.add_exclusive_binder(outer_exclusive_binder.shifted_out(1)); - } // otherwise, this binder captures nothing - } - - #[allow(rustc::usage_of_ty_tykind)] - fn add_kind(&mut self, kind: &ty::TyKind<'_>) { - match kind { - &ty::Bool - | &ty::Char - | &ty::Int(_) - | &ty::Float(_) - | &ty::Uint(_) - | &ty::Never - | &ty::Str - | &ty::Foreign(..) => {} - - &ty::Error(_) => self.add_flags(TypeFlags::HAS_ERROR), - - &ty::Param(_) => { - self.add_flags(TypeFlags::HAS_TY_PARAM); - } - - &ty::Closure(_, args) - | &ty::Coroutine(_, args) - | &ty::CoroutineClosure(_, args) - | &ty::CoroutineWitness(_, args) => { - self.add_args(args); - } - - &ty::Bound(debruijn, _) => { - self.add_bound_var(debruijn); - self.add_flags(TypeFlags::HAS_TY_BOUND); - } - - &ty::Placeholder(..) => { - self.add_flags(TypeFlags::HAS_TY_PLACEHOLDER); - } - - &ty::Infer(infer) => match infer { - ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => { - self.add_flags(TypeFlags::HAS_TY_FRESH) - } - - ty::TyVar(_) | ty::IntVar(_) | ty::FloatVar(_) => { - self.add_flags(TypeFlags::HAS_TY_INFER) - } - }, - - &ty::Adt(_, args) => { - self.add_args(args); - } - - &ty::Alias(kind, data) => { - self.add_flags(match kind { - ty::Projection => TypeFlags::HAS_TY_PROJECTION, - ty::Weak => TypeFlags::HAS_TY_WEAK, - ty::Opaque => TypeFlags::HAS_TY_OPAQUE, - ty::Inherent => TypeFlags::HAS_TY_INHERENT, - }); - - self.add_alias_ty(data); - } - - &ty::Dynamic(obj, r, _) => { - for predicate in obj.iter() { - self.bound_computation(predicate, |computation, predicate| match predicate { - ty::ExistentialPredicate::Trait(tr) => computation.add_args(tr.args), - ty::ExistentialPredicate::Projection(p) => { - computation.add_existential_projection(&p); - } - ty::ExistentialPredicate::AutoTrait(_) => {} - }); - } - - self.add_region(r); - } - - &ty::Array(tt, len) => { - self.add_ty(tt); - self.add_const(len); - } - - &ty::Pat(ty, pat) => { - self.add_ty(ty); - match *pat { - ty::PatternKind::Range { start, end } => { - self.add_const(start); - self.add_const(end); - } - } - } - - &ty::Slice(tt) => self.add_ty(tt), - - &ty::RawPtr(ty, _) => { - self.add_ty(ty); - } - - &ty::Ref(r, ty, _) => { - self.add_region(r); - self.add_ty(ty); - } - - &ty::Tuple(types) => { - self.add_tys(types); - } - - &ty::FnDef(_, args) => { - self.add_args(args); - } - - &ty::FnPtr(sig_tys, _) => self.bound_computation(sig_tys, |computation, sig_tys| { - computation.add_tys(sig_tys.inputs_and_output); - }), - - &ty::UnsafeBinder(bound_ty) => { - self.bound_computation(bound_ty.into(), |computation, ty| { - computation.add_ty(ty); - }) - } - } - } - - fn add_predicate(&mut self, binder: ty::Binder<'_, ty::PredicateKind<'_>>) { - self.bound_computation(binder, |computation, atom| computation.add_predicate_atom(atom)); - } - - fn add_predicate_atom(&mut self, atom: ty::PredicateKind<'_>) { - match atom { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) => { - self.add_args(trait_pred.trait_ref.args); - } - ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(ty::HostEffectPredicate { - trait_ref, - constness: _, - })) => { - self.add_args(trait_ref.args); - } - ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate( - a, - b, - ))) => { - self.add_region(a); - self.add_region(b); - } - ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate( - ty, - region, - ))) => { - self.add_ty(ty); - self.add_region(region); - } - ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => { - self.add_const(ct); - self.add_ty(ty); - } - ty::PredicateKind::Subtype(ty::SubtypePredicate { a_is_expected: _, a, b }) => { - self.add_ty(a); - self.add_ty(b); - } - ty::PredicateKind::Coerce(ty::CoercePredicate { a, b }) => { - self.add_ty(a); - self.add_ty(b); - } - ty::PredicateKind::Clause(ty::ClauseKind::Projection(ty::ProjectionPredicate { - projection_term, - term, - })) => { - self.add_alias_term(projection_term); - self.add_term(term); - } - ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => { - self.add_args(slice::from_ref(&arg)); - } - ty::PredicateKind::DynCompatible(_def_id) => {} - ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(uv)) => { - self.add_const(uv); - } - ty::PredicateKind::ConstEquate(expected, found) => { - self.add_const(expected); - self.add_const(found); - } - ty::PredicateKind::Ambiguous => {} - ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term }) => { - self.add_alias_term(alias); - self.add_term(term); - } - ty::PredicateKind::AliasRelate(t1, t2, _) => { - self.add_term(t1); - self.add_term(t2); - } - } - } - - fn add_ty(&mut self, ty: Ty<'_>) { - self.add_flags(ty.flags()); - self.add_exclusive_binder(ty.outer_exclusive_binder()); - } - - fn add_tys(&mut self, tys: &[Ty<'_>]) { - for &ty in tys { - self.add_ty(ty); - } - } - - fn add_region(&mut self, r: ty::Region<'_>) { - self.add_flags(r.type_flags()); - if let ty::ReBound(debruijn, _) = r.kind() { - self.add_bound_var(debruijn); - } - } - - fn add_const(&mut self, c: ty::Const<'_>) { - self.add_flags(c.flags()); - self.add_exclusive_binder(c.outer_exclusive_binder()); - } - - fn add_const_kind(&mut self, c: &ty::ConstKind<'_>) { - match *c { - ty::ConstKind::Unevaluated(uv) => { - self.add_args(uv.args); - self.add_flags(TypeFlags::HAS_CT_PROJECTION); - } - ty::ConstKind::Infer(infer) => match infer { - InferConst::Fresh(_) => self.add_flags(TypeFlags::HAS_CT_FRESH), - InferConst::Var(_) => self.add_flags(TypeFlags::HAS_CT_INFER), - }, - ty::ConstKind::Bound(debruijn, _) => { - self.add_bound_var(debruijn); - self.add_flags(TypeFlags::HAS_CT_BOUND); - } - ty::ConstKind::Param(_) => { - self.add_flags(TypeFlags::HAS_CT_PARAM); - } - ty::ConstKind::Placeholder(_) => { - self.add_flags(TypeFlags::HAS_CT_PLACEHOLDER); - } - ty::ConstKind::Value(cv) => self.add_ty(cv.ty), - ty::ConstKind::Expr(e) => self.add_args(e.args()), - ty::ConstKind::Error(_) => self.add_flags(TypeFlags::HAS_ERROR), - } - } - - fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection<'_>) { - self.add_args(projection.args); - match projection.term.unpack() { - ty::TermKind::Ty(ty) => self.add_ty(ty), - ty::TermKind::Const(ct) => self.add_const(ct), - } - } - - fn add_alias_ty(&mut self, alias_ty: ty::AliasTy<'_>) { - self.add_args(alias_ty.args); - } - - fn add_alias_term(&mut self, alias_term: ty::AliasTerm<'_>) { - self.add_args(alias_term.args); - } - - fn add_args(&mut self, args: &[GenericArg<'_>]) { - for kind in args { - match kind.unpack() { - GenericArgKind::Type(ty) => self.add_ty(ty), - GenericArgKind::Lifetime(lt) => self.add_region(lt), - GenericArgKind::Const(ct) => self.add_const(ct), - } - } - } - - fn add_term(&mut self, term: ty::Term<'_>) { - match term.unpack() { - ty::TermKind::Ty(ty) => self.add_ty(ty), - ty::TermKind::Const(ct) => self.add_const(ct), - } - } -} diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index 9c1ff134f0fd..1f04937232dd 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -11,6 +11,7 @@ use rustc_hir::def_id::DefId; use rustc_macros::{HashStable, TyDecodable, TyEncodable, extension}; use rustc_serialize::{Decodable, Encodable}; use rustc_type_ir::WithCachedTypeInfo; +use rustc_type_ir::walk::TypeWalker; use smallvec::SmallVec; use crate::ty::codec::{TyDecoder, TyEncoder}; @@ -297,6 +298,20 @@ impl<'tcx> GenericArg<'tcx> { GenericArgKind::Const(ct) => ct.is_ct_infer(), } } + + /// Iterator that walks `self` and any types reachable from + /// `self`, in depth-first order. Note that just walks the types + /// that appear in `self`, it does not descend into the fields of + /// structs or variants. For example: + /// + /// ```text + /// isize => { isize } + /// Foo> => { Foo>, Bar, isize } + /// [isize] => { [isize], isize } + /// ``` + pub fn walk(self) -> TypeWalker> { + TypeWalker::new(self) + } } impl<'a, 'tcx> Lift> for GenericArg<'a> { diff --git a/compiler/rustc_middle/src/ty/list.rs b/compiler/rustc_middle/src/ty/list.rs index 0fd370a56195..0cf5820959ee 100644 --- a/compiler/rustc_middle/src/ty/list.rs +++ b/compiler/rustc_middle/src/ty/list.rs @@ -7,9 +7,9 @@ use std::{fmt, iter, mem, ptr, slice}; use rustc_data_structures::aligned::{Aligned, align_of}; use rustc_data_structures::sync::DynSync; use rustc_serialize::{Encodable, Encoder}; +use rustc_type_ir::FlagComputation; -use super::flags::FlagComputation; -use super::{DebruijnIndex, TypeFlags}; +use super::{DebruijnIndex, TyCtxt, TypeFlags}; use crate::arena::Arena; /// `List` is a bit like `&[T]`, but with some critical differences. @@ -299,8 +299,8 @@ impl TypeInfo { } } -impl From for TypeInfo { - fn from(computation: FlagComputation) -> TypeInfo { +impl<'tcx> From>> for TypeInfo { + fn from(computation: FlagComputation>) -> TypeInfo { TypeInfo { flags: computation.flags, outer_exclusive_binder: computation.outer_exclusive_binder, diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index a2b3acac3f26..61e869f5de41 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -117,7 +117,6 @@ pub mod cast; pub mod codec; pub mod error; pub mod fast_reject; -pub mod flags; pub mod inhabitedness; pub mod layout; pub mod normalize_erasing_regions; @@ -128,7 +127,6 @@ pub mod significant_drop_order; pub mod trait_def; pub mod util; pub mod vtable; -pub mod walk; mod adt; mod assoc; diff --git a/compiler/rustc_middle/src/ty/pattern.rs b/compiler/rustc_middle/src/ty/pattern.rs index 4cad1ab20991..758adc42e3eb 100644 --- a/compiler/rustc_middle/src/ty/pattern.rs +++ b/compiler/rustc_middle/src/ty/pattern.rs @@ -1,14 +1,40 @@ use std::fmt; use rustc_data_structures::intern::Interned; -use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; +use rustc_macros::HashStable; +use rustc_type_ir::ir_print::IrPrint; +use rustc_type_ir::{ + FlagComputation, Flags, {self as ir}, +}; +use super::TyCtxt; use crate::ty; +pub type PatternKind<'tcx> = ir::PatternKind>; + #[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable)] #[rustc_pass_by_value] pub struct Pattern<'tcx>(pub Interned<'tcx, PatternKind<'tcx>>); +impl<'tcx> Flags for Pattern<'tcx> { + fn flags(&self) -> rustc_type_ir::TypeFlags { + match &**self { + ty::PatternKind::Range { start, end } => { + FlagComputation::for_const_kind(&start.kind()).flags + | FlagComputation::for_const_kind(&end.kind()).flags + } + } + } + + fn outer_exclusive_binder(&self) -> rustc_type_ir::DebruijnIndex { + match &**self { + ty::PatternKind::Range { start, end } => { + start.outer_exclusive_binder().max(end.outer_exclusive_binder()) + } + } + } +} + impl<'tcx> std::ops::Deref for Pattern<'tcx> { type Target = PatternKind<'tcx>; @@ -23,9 +49,9 @@ impl<'tcx> fmt::Debug for Pattern<'tcx> { } } -impl<'tcx> fmt::Debug for PatternKind<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match *self { +impl<'tcx> IrPrint> for TyCtxt<'tcx> { + fn print(t: &PatternKind<'tcx>, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *t { PatternKind::Range { start, end } => { write!(f, "{start}")?; @@ -53,10 +79,15 @@ impl<'tcx> fmt::Debug for PatternKind<'tcx> { } } } + + fn print_debug(t: &PatternKind<'tcx>, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + Self::print(t, fmt) + } } -#[derive(Clone, PartialEq, Eq, Hash)] -#[derive(HashStable, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)] -pub enum PatternKind<'tcx> { - Range { start: ty::Const<'tcx>, end: ty::Const<'tcx> }, +impl<'tcx> rustc_type_ir::inherent::IntoKind for Pattern<'tcx> { + type Kind = PatternKind<'tcx>; + fn kind(self) -> Self::Kind { + *self + } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 27ee363f1c14..d9a65ae57a09 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -16,6 +16,7 @@ use rustc_hir::def_id::DefId; use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, extension}; use rustc_span::{DUMMY_SP, Span, Symbol, sym}; use rustc_type_ir::TyKind::*; +use rustc_type_ir::walk::TypeWalker; use rustc_type_ir::{self as ir, BoundVar, CollectAndApply, DynKind, TypeVisitableExt, elaborate}; use tracing::instrument; use ty::util::{AsyncDropGlueMorphology, IntTypeExt}; @@ -2029,6 +2030,20 @@ impl<'tcx> Ty<'tcx> { pub fn is_known_rigid(self) -> bool { self.kind().is_known_rigid() } + + /// Iterator that walks `self` and any types reachable from + /// `self`, in depth-first order. Note that just walks the types + /// that appear in `self`, it does not descend into the fields of + /// structs or variants. For example: + /// + /// ```text + /// isize => { isize } + /// Foo> => { Foo>, Bar, isize } + /// [isize] => { [isize], isize } + /// ``` + pub fn walk(self) -> TypeWalker> { + TypeWalker::new(self.into()) + } } impl<'tcx> rustc_type_ir::inherent::Tys> for &'tcx ty::List> { diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs index 6a2498242fee..e9d3a149a730 100644 --- a/compiler/rustc_type_ir/src/flags.rs +++ b/compiler/rustc_type_ir/src/flags.rs @@ -1,3 +1,9 @@ +use std::slice; + +use crate::inherent::*; +use crate::visit::Flags; +use crate::{self as ty, Interner}; + bitflags::bitflags! { /// Flags that we track on types. These flags are propagated upwards /// through the type during type construction, so that we can quickly check @@ -128,3 +134,362 @@ bitflags::bitflags! { const HAS_BINDER_VARS = 1 << 23; } } + +#[derive(Debug)] +pub struct FlagComputation { + pub flags: TypeFlags, + + /// see `Ty::outer_exclusive_binder` for details + pub outer_exclusive_binder: ty::DebruijnIndex, + + interner: std::marker::PhantomData, +} + +impl FlagComputation { + fn new() -> FlagComputation { + FlagComputation { + flags: TypeFlags::empty(), + outer_exclusive_binder: ty::INNERMOST, + interner: std::marker::PhantomData, + } + } + + #[allow(rustc::usage_of_ty_tykind)] + pub fn for_kind(kind: &ty::TyKind) -> FlagComputation { + let mut result = FlagComputation::new(); + result.add_kind(kind); + result + } + + pub fn for_predicate(binder: ty::Binder>) -> FlagComputation { + let mut result = FlagComputation::new(); + result.add_predicate(binder); + result + } + + pub fn for_const_kind(kind: &ty::ConstKind) -> FlagComputation { + let mut result = FlagComputation::new(); + result.add_const_kind(kind); + result + } + + pub fn for_clauses(clauses: &[I::Clause]) -> FlagComputation { + let mut result = FlagComputation::new(); + for c in clauses { + result.add_flags(c.as_predicate().flags()); + result.add_exclusive_binder(c.as_predicate().outer_exclusive_binder()); + } + result + } + + fn add_flags(&mut self, flags: TypeFlags) { + self.flags = self.flags | flags; + } + + /// indicates that `self` refers to something at binding level `binder` + fn add_bound_var(&mut self, binder: ty::DebruijnIndex) { + let exclusive_binder = binder.shifted_in(1); + self.add_exclusive_binder(exclusive_binder); + } + + /// indicates that `self` refers to something *inside* binding + /// level `binder` -- not bound by `binder`, but bound by the next + /// binder internal to it + fn add_exclusive_binder(&mut self, exclusive_binder: ty::DebruijnIndex) { + self.outer_exclusive_binder = self.outer_exclusive_binder.max(exclusive_binder); + } + + /// Adds the flags/depth from a set of types that appear within the current type, but within a + /// region binder. + fn bound_computation(&mut self, value: ty::Binder, f: F) + where + F: FnOnce(&mut Self, T), + { + let mut computation = FlagComputation::new(); + + if !value.bound_vars().is_empty() { + computation.add_flags(TypeFlags::HAS_BINDER_VARS); + } + + f(&mut computation, value.skip_binder()); + + self.add_flags(computation.flags); + + // The types that contributed to `computation` occurred within + // a region binder, so subtract one from the region depth + // within when adding the depth to `self`. + let outer_exclusive_binder = computation.outer_exclusive_binder; + if outer_exclusive_binder > ty::INNERMOST { + self.add_exclusive_binder(outer_exclusive_binder.shifted_out(1)); + } // otherwise, this binder captures nothing + } + + #[allow(rustc::usage_of_ty_tykind)] + fn add_kind(&mut self, kind: &ty::TyKind) { + match *kind { + ty::Bool + | ty::Char + | ty::Int(_) + | ty::Float(_) + | ty::Uint(_) + | ty::Never + | ty::Str + | ty::Foreign(..) => {} + + ty::Error(_) => self.add_flags(TypeFlags::HAS_ERROR), + + ty::Param(_) => { + self.add_flags(TypeFlags::HAS_TY_PARAM); + } + + ty::Closure(_, args) + | ty::Coroutine(_, args) + | ty::CoroutineClosure(_, args) + | ty::CoroutineWitness(_, args) => { + self.add_args(args.as_slice()); + } + + ty::Bound(debruijn, _) => { + self.add_bound_var(debruijn); + self.add_flags(TypeFlags::HAS_TY_BOUND); + } + + ty::Placeholder(..) => { + self.add_flags(TypeFlags::HAS_TY_PLACEHOLDER); + } + + ty::Infer(infer) => match infer { + ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => { + self.add_flags(TypeFlags::HAS_TY_FRESH) + } + + ty::TyVar(_) | ty::IntVar(_) | ty::FloatVar(_) => { + self.add_flags(TypeFlags::HAS_TY_INFER) + } + }, + + ty::Adt(_, args) => { + self.add_args(args.as_slice()); + } + + ty::Alias(kind, data) => { + self.add_flags(match kind { + ty::Projection => TypeFlags::HAS_TY_PROJECTION, + ty::Weak => TypeFlags::HAS_TY_WEAK, + ty::Opaque => TypeFlags::HAS_TY_OPAQUE, + ty::Inherent => TypeFlags::HAS_TY_INHERENT, + }); + + self.add_alias_ty(data); + } + + ty::Dynamic(obj, r, _) => { + for predicate in obj.iter() { + self.bound_computation(predicate, |computation, predicate| match predicate { + ty::ExistentialPredicate::Trait(tr) => { + computation.add_args(tr.args.as_slice()) + } + ty::ExistentialPredicate::Projection(p) => { + computation.add_existential_projection(&p); + } + ty::ExistentialPredicate::AutoTrait(_) => {} + }); + } + + self.add_region(r); + } + + ty::Array(tt, len) => { + self.add_ty(tt); + self.add_const(len); + } + + ty::Pat(ty, pat) => { + self.add_ty(ty); + self.add_flags(pat.flags()); + } + + ty::Slice(tt) => self.add_ty(tt), + + ty::RawPtr(ty, _) => { + self.add_ty(ty); + } + + ty::Ref(r, ty, _) => { + self.add_region(r); + self.add_ty(ty); + } + + ty::Tuple(types) => { + self.add_tys(types); + } + + ty::FnDef(_, args) => { + self.add_args(args.as_slice()); + } + + ty::FnPtr(sig_tys, _) => self.bound_computation(sig_tys, |computation, sig_tys| { + computation.add_tys(sig_tys.inputs_and_output); + }), + + ty::UnsafeBinder(bound_ty) => { + self.bound_computation(bound_ty.into(), |computation, ty| { + computation.add_ty(ty); + }) + } + } + } + + fn add_predicate(&mut self, binder: ty::Binder>) { + self.bound_computation(binder, |computation, atom| computation.add_predicate_atom(atom)); + } + + fn add_predicate_atom(&mut self, atom: ty::PredicateKind) { + match atom { + ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) => { + self.add_args(trait_pred.trait_ref.args.as_slice()); + } + ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(ty::HostEffectPredicate { + trait_ref, + constness: _, + })) => { + self.add_args(trait_ref.args.as_slice()); + } + ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate( + a, + b, + ))) => { + self.add_region(a); + self.add_region(b); + } + ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate( + ty, + region, + ))) => { + self.add_ty(ty); + self.add_region(region); + } + ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => { + self.add_const(ct); + self.add_ty(ty); + } + ty::PredicateKind::Subtype(ty::SubtypePredicate { a_is_expected: _, a, b }) => { + self.add_ty(a); + self.add_ty(b); + } + ty::PredicateKind::Coerce(ty::CoercePredicate { a, b }) => { + self.add_ty(a); + self.add_ty(b); + } + ty::PredicateKind::Clause(ty::ClauseKind::Projection(ty::ProjectionPredicate { + projection_term, + term, + })) => { + self.add_alias_term(projection_term); + self.add_term(term); + } + ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => { + self.add_args(slice::from_ref(&arg)); + } + ty::PredicateKind::DynCompatible(_def_id) => {} + ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(uv)) => { + self.add_const(uv); + } + ty::PredicateKind::ConstEquate(expected, found) => { + self.add_const(expected); + self.add_const(found); + } + ty::PredicateKind::Ambiguous => {} + ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term }) => { + self.add_alias_term(alias); + self.add_term(term); + } + ty::PredicateKind::AliasRelate(t1, t2, _) => { + self.add_term(t1); + self.add_term(t2); + } + } + } + + fn add_ty(&mut self, ty: I::Ty) { + self.add_flags(ty.flags()); + self.add_exclusive_binder(ty.outer_exclusive_binder()); + } + + fn add_tys(&mut self, tys: I::Tys) { + for ty in tys.iter() { + self.add_ty(ty); + } + } + + fn add_region(&mut self, r: I::Region) { + self.add_flags(r.flags()); + if let ty::ReBound(debruijn, _) = r.kind() { + self.add_bound_var(debruijn); + } + } + + fn add_const(&mut self, c: I::Const) { + self.add_flags(c.flags()); + self.add_exclusive_binder(c.outer_exclusive_binder()); + } + + fn add_const_kind(&mut self, c: &ty::ConstKind) { + match *c { + ty::ConstKind::Unevaluated(uv) => { + self.add_args(uv.args.as_slice()); + self.add_flags(TypeFlags::HAS_CT_PROJECTION); + } + ty::ConstKind::Infer(infer) => match infer { + ty::InferConst::Fresh(_) => self.add_flags(TypeFlags::HAS_CT_FRESH), + ty::InferConst::Var(_) => self.add_flags(TypeFlags::HAS_CT_INFER), + }, + ty::ConstKind::Bound(debruijn, _) => { + self.add_bound_var(debruijn); + self.add_flags(TypeFlags::HAS_CT_BOUND); + } + ty::ConstKind::Param(_) => { + self.add_flags(TypeFlags::HAS_CT_PARAM); + } + ty::ConstKind::Placeholder(_) => { + self.add_flags(TypeFlags::HAS_CT_PLACEHOLDER); + } + ty::ConstKind::Value(cv) => self.add_ty(cv.ty()), + ty::ConstKind::Expr(e) => self.add_args(e.args().as_slice()), + ty::ConstKind::Error(_) => self.add_flags(TypeFlags::HAS_ERROR), + } + } + + fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection) { + self.add_args(projection.args.as_slice()); + match projection.term.kind() { + ty::TermKind::Ty(ty) => self.add_ty(ty), + ty::TermKind::Const(ct) => self.add_const(ct), + } + } + + fn add_alias_ty(&mut self, alias_ty: ty::AliasTy) { + self.add_args(alias_ty.args.as_slice()); + } + + fn add_alias_term(&mut self, alias_term: ty::AliasTerm) { + self.add_args(alias_term.args.as_slice()); + } + + fn add_args(&mut self, args: &[I::GenericArg]) { + for kind in args { + match kind.kind() { + ty::GenericArgKind::Type(ty) => self.add_ty(ty), + ty::GenericArgKind::Lifetime(lt) => self.add_region(lt), + ty::GenericArgKind::Const(ct) => self.add_const(ct), + } + } + } + + fn add_term(&mut self, term: I::Term) { + match term.kind() { + ty::TermKind::Ty(ty) => self.add_ty(ty), + ty::TermKind::Const(ct) => self.add_const(ct), + } + } +} diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index 6e6c40580d83..417803e75ead 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -583,7 +583,7 @@ pub trait Span: Copy + Debug + Hash + Eq + TypeFoldable { pub trait SliceLike: Sized + Copy { type Item: Copy; - type IntoIter: Iterator; + type IntoIter: Iterator + DoubleEndedIterator; fn iter(self) -> Self::IntoIter; diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index a9e6764e2182..71bfeabfda87 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -31,6 +31,7 @@ pub trait Interner: + IrPrint> + IrPrint> + IrPrint> + + IrPrint> { type DefId: DefId; type LocalDefId: Copy + Debug + Hash + Eq + Into + TypeFoldable; @@ -104,7 +105,14 @@ pub trait Interner: type ErrorGuaranteed: Copy + Debug + Hash + Eq; type BoundExistentialPredicates: BoundExistentialPredicates; type AllocId: Copy + Debug + Hash + Eq; - type Pat: Copy + Debug + Hash + Eq + Debug + Relate; + type Pat: Copy + + Debug + + Hash + + Eq + + Debug + + Relate + + Flags + + IntoKind>; type Safety: Safety; type Abi: Abi; diff --git a/compiler/rustc_type_ir/src/ir_print.rs b/compiler/rustc_type_ir/src/ir_print.rs index 0c71f3a3df2a..c259a9747f0d 100644 --- a/compiler/rustc_type_ir/src/ir_print.rs +++ b/compiler/rustc_type_ir/src/ir_print.rs @@ -2,8 +2,8 @@ use std::fmt; use crate::{ AliasTerm, AliasTy, Binder, CoercePredicate, ExistentialProjection, ExistentialTraitRef, FnSig, - HostEffectPredicate, Interner, NormalizesTo, OutlivesPredicate, ProjectionPredicate, - SubtypePredicate, TraitPredicate, TraitRef, + HostEffectPredicate, Interner, NormalizesTo, OutlivesPredicate, PatternKind, + ProjectionPredicate, SubtypePredicate, TraitPredicate, TraitRef, }; pub trait IrPrint { @@ -57,9 +57,10 @@ define_display_via_print!( AliasTy, AliasTerm, FnSig, + PatternKind, ); -define_debug_via_print!(TraitRef, ExistentialTraitRef, ExistentialProjection); +define_debug_via_print!(TraitRef, ExistentialTraitRef, ExistentialProjection, PatternKind); impl fmt::Display for OutlivesPredicate where diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index bdc61e956f8c..792090effcff 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -31,6 +31,7 @@ pub mod outlives; pub mod relate; pub mod search_graph; pub mod solve; +pub mod walk; // These modules are not `pub` since they are glob-imported. #[macro_use] @@ -44,6 +45,7 @@ mod generic_arg; mod infer_ctxt; mod interner; mod opaque_ty; +mod pattern; mod predicate; mod predicate_kind; mod region_kind; @@ -67,6 +69,7 @@ pub use generic_arg::*; pub use infer_ctxt::*; pub use interner::*; pub use opaque_ty::*; +pub use pattern::*; pub use predicate::*; pub use predicate_kind::*; pub use region_kind::*; diff --git a/compiler/rustc_type_ir/src/pattern.rs b/compiler/rustc_type_ir/src/pattern.rs new file mode 100644 index 000000000000..d74a82da1f92 --- /dev/null +++ b/compiler/rustc_type_ir/src/pattern.rs @@ -0,0 +1,16 @@ +use derive_where::derive_where; +#[cfg(feature = "nightly")] +use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext}; +use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; + +use crate::Interner; + +#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] +#[cfg_attr( + feature = "nightly", + derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext) +)] +pub enum PatternKind { + Range { start: I::Const, end: I::Const }, +} diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_type_ir/src/walk.rs similarity index 55% rename from compiler/rustc_middle/src/ty/walk.rs rename to compiler/rustc_type_ir/src/walk.rs index a23316ae6fc8..5683e1f1712c 100644 --- a/compiler/rustc_middle/src/ty/walk.rs +++ b/compiler/rustc_type_ir/src/walk.rs @@ -1,20 +1,21 @@ //! An iterator over the type substructure. //! WARNING: this does not keep track of the region depth. -use rustc_data_structures::sso::SsoHashSet; use smallvec::{SmallVec, smallvec}; use tracing::debug; -use crate::ty::{self, GenericArg, GenericArgKind, Ty}; +use crate::data_structures::SsoHashSet; +use crate::inherent::*; +use crate::{self as ty, Interner}; // The TypeWalker's stack is hot enough that it's worth going to some effort to // avoid heap allocations. -type TypeWalkerStack<'tcx> = SmallVec<[GenericArg<'tcx>; 8]>; +type TypeWalkerStack = SmallVec<[::GenericArg; 8]>; -pub struct TypeWalker<'tcx> { - stack: TypeWalkerStack<'tcx>, +pub struct TypeWalker { + stack: TypeWalkerStack, last_subtree: usize, - pub visited: SsoHashSet>, + pub visited: SsoHashSet, } /// An iterator for walking the type tree. @@ -25,8 +26,8 @@ pub struct TypeWalker<'tcx> { /// in this situation walker only visits each type once. /// It maintains a set of visited types and /// skips any types that are already there. -impl<'tcx> TypeWalker<'tcx> { - pub fn new(root: GenericArg<'tcx>) -> Self { +impl TypeWalker { + pub fn new(root: I::GenericArg) -> Self { Self { stack: smallvec![root], last_subtree: 1, visited: SsoHashSet::new() } } @@ -47,16 +48,16 @@ impl<'tcx> TypeWalker<'tcx> { } } -impl<'tcx> Iterator for TypeWalker<'tcx> { - type Item = GenericArg<'tcx>; +impl Iterator for TypeWalker { + type Item = I::GenericArg; - fn next(&mut self) -> Option> { + fn next(&mut self) -> Option { debug!("next(): stack={:?}", self.stack); loop { let next = self.stack.pop()?; self.last_subtree = self.stack.len(); if self.visited.insert(next) { - push_inner(&mut self.stack, next); + push_inner::(&mut self.stack, next); debug!("next: stack={:?}", self.stack); return Some(next); } @@ -64,63 +65,15 @@ impl<'tcx> Iterator for TypeWalker<'tcx> { } } -impl<'tcx> GenericArg<'tcx> { - /// Iterator that walks `self` and any types reachable from - /// `self`, in depth-first order. Note that just walks the types - /// that appear in `self`, it does not descend into the fields of - /// structs or variants. For example: - /// - /// ```text - /// isize => { isize } - /// Foo> => { Foo>, Bar, isize } - /// [isize] => { [isize], isize } - /// ``` - pub fn walk(self) -> TypeWalker<'tcx> { - TypeWalker::new(self) - } -} - -impl<'tcx> Ty<'tcx> { - /// Iterator that walks `self` and any types reachable from - /// `self`, in depth-first order. Note that just walks the types - /// that appear in `self`, it does not descend into the fields of - /// structs or variants. For example: - /// - /// ```text - /// isize => { isize } - /// Foo> => { Foo>, Bar, isize } - /// [isize] => { [isize], isize } - /// ``` - pub fn walk(self) -> TypeWalker<'tcx> { - TypeWalker::new(self.into()) - } -} - -impl<'tcx> ty::Const<'tcx> { - /// Iterator that walks `self` and any types reachable from - /// `self`, in depth-first order. Note that just walks the types - /// that appear in `self`, it does not descend into the fields of - /// structs or variants. For example: - /// - /// ```text - /// isize => { isize } - /// Foo> => { Foo>, Bar, isize } - /// [isize] => { [isize], isize } - /// ``` - pub fn walk(self) -> TypeWalker<'tcx> { - TypeWalker::new(self.into()) - } -} - /// We push `GenericArg`s on the stack in reverse order so as to /// maintain a pre-order traversal. As of the time of this /// writing, the fact that the traversal is pre-order is not /// known to be significant to any code, but it seems like the /// natural order one would expect (basically, the order of the /// types as they are written). -fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) { - match parent.unpack() { - GenericArgKind::Type(parent_ty) => match *parent_ty.kind() { +fn push_inner(stack: &mut TypeWalkerStack, parent: I::GenericArg) { + match parent.kind() { + ty::GenericArgKind::Type(parent_ty) => match parent_ty.kind() { ty::Bool | ty::Char | ty::Int(_) @@ -136,7 +89,7 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) | ty::Foreign(..) => {} ty::Pat(ty, pat) => { - match *pat { + match pat.kind() { ty::PatternKind::Range { start, end } => { stack.push(end.into()); stack.push(start.into()); @@ -163,22 +116,25 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) } ty::Dynamic(obj, lt, _) => { stack.push(lt.into()); - stack.extend(obj.iter().rev().flat_map(|predicate| { - let (args, opt_ty) = match predicate.skip_binder() { - ty::ExistentialPredicate::Trait(tr) => (tr.args, None), - ty::ExistentialPredicate::Projection(p) => (p.args, Some(p.term)), - ty::ExistentialPredicate::AutoTrait(_) => - // Empty iterator - { - (ty::GenericArgs::empty(), None) - } - }; + stack.extend( + obj.iter() + .rev() + .filter_map(|predicate| { + let (args, opt_ty) = match predicate.skip_binder() { + ty::ExistentialPredicate::Trait(tr) => (tr.args, None), + ty::ExistentialPredicate::Projection(p) => (p.args, Some(p.term)), + ty::ExistentialPredicate::AutoTrait(_) => { + return None; + } + }; - args.iter().rev().chain(opt_ty.map(|term| match term.unpack() { - ty::TermKind::Ty(ty) => ty.into(), - ty::TermKind::Const(ct) => ct.into(), - })) - })); + Some(args.iter().rev().chain(opt_ty.map(|term| match term.kind() { + ty::TermKind::Ty(ty) => ty.into(), + ty::TermKind::Const(ct) => ct.into(), + }))) + }) + .flatten(), + ); } ty::Adt(_, args) | ty::Closure(_, args) @@ -188,7 +144,7 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) | ty::FnDef(_, args) => { stack.extend(args.iter().rev()); } - ty::Tuple(ts) => stack.extend(ts.iter().rev().map(GenericArg::from)), + ty::Tuple(ts) => stack.extend(ts.iter().rev().map(|ty| ty.into())), ty::FnPtr(sig_tys, _hdr) => { stack.extend( sig_tys.skip_binder().inputs_and_output.iter().rev().map(|ty| ty.into()), @@ -198,15 +154,15 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) stack.push(bound_ty.skip_binder().into()); } }, - GenericArgKind::Lifetime(_) => {} - GenericArgKind::Const(parent_ct) => match parent_ct.kind() { + ty::GenericArgKind::Lifetime(_) => {} + ty::GenericArgKind::Const(parent_ct) => match parent_ct.kind() { ty::ConstKind::Infer(_) | ty::ConstKind::Param(_) | ty::ConstKind::Placeholder(_) | ty::ConstKind::Bound(..) | ty::ConstKind::Error(_) => {} - ty::ConstKind::Value(cv) => stack.push(cv.ty.into()), + ty::ConstKind::Value(cv) => stack.push(cv.ty().into()), ty::ConstKind::Expr(expr) => stack.extend(expr.args().iter().rev()), ty::ConstKind::Unevaluated(ct) => { From f472cc8cd4c57687aac38fe3589818f1cc7956ba Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sat, 12 Apr 2025 19:58:19 +0200 Subject: [PATCH 399/606] error on unsafe attributes in pre-2024 editions the `no_mangle`, `link_section` and `export_name` attributes are exceptions, and can still be used without an unsafe in earlier editions --- .../src/error_codes/E0755.md | 4 +-- .../src/error_codes/E0756.md | 4 +-- .../src/error_codes/E0757.md | 7 ++-- compiler/rustc_feature/src/builtin_attrs.rs | 33 ++++++++++++++----- compiler/rustc_parse/src/validate_attr.rs | 10 ++++-- tests/codegen/cffi/ffi-const.rs | 2 +- tests/codegen/cffi/ffi-pure.rs | 2 +- .../feature-gates/feature-gate-ffi_const.rs | 2 +- .../feature-gate-ffi_const.stderr | 4 +-- .../ui/feature-gates/feature-gate-ffi_pure.rs | 2 +- .../feature-gate-ffi_pure.stderr | 4 +-- tests/ui/ffi-attrs/ffi_const.rs | 11 ++++--- tests/ui/ffi-attrs/ffi_const.stderr | 25 ++++++++++---- tests/ui/ffi-attrs/ffi_const2.rs | 4 +-- tests/ui/ffi-attrs/ffi_const2.stderr | 4 +-- tests/ui/ffi-attrs/ffi_pure.rs | 11 ++++--- tests/ui/ffi-attrs/ffi_pure.stderr | 25 ++++++++++---- 17 files changed, 102 insertions(+), 52 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0755.md b/compiler/rustc_error_codes/src/error_codes/E0755.md index 88b7f4849690..b67f078c78ec 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0755.md +++ b/compiler/rustc_error_codes/src/error_codes/E0755.md @@ -5,7 +5,7 @@ Erroneous code example: ```compile_fail,E0755 #![feature(ffi_pure)] -#[ffi_pure] // error! +#[unsafe(ffi_pure)] // error! pub fn foo() {} # fn main() {} ``` @@ -17,7 +17,7 @@ side effects or infinite loops: #![feature(ffi_pure)] extern "C" { - #[ffi_pure] // ok! + #[unsafe(ffi_pure)] // ok! pub fn strlen(s: *const i8) -> isize; } # fn main() {} diff --git a/compiler/rustc_error_codes/src/error_codes/E0756.md b/compiler/rustc_error_codes/src/error_codes/E0756.md index ffdc421aab58..aadde038d12c 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0756.md +++ b/compiler/rustc_error_codes/src/error_codes/E0756.md @@ -6,7 +6,7 @@ Erroneous code example: ```compile_fail,E0756 #![feature(ffi_const)] -#[ffi_const] // error! +#[unsafe(ffi_const)] // error! pub fn foo() {} # fn main() {} ``` @@ -18,7 +18,7 @@ which have no side effects except for their return value: #![feature(ffi_const)] extern "C" { - #[ffi_const] // ok! + #[unsafe(ffi_const)] // ok! pub fn strlen(s: *const i8) -> i32; } # fn main() {} diff --git a/compiler/rustc_error_codes/src/error_codes/E0757.md b/compiler/rustc_error_codes/src/error_codes/E0757.md index 41b06b23c4f2..fb75b028f45c 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0757.md +++ b/compiler/rustc_error_codes/src/error_codes/E0757.md @@ -6,8 +6,9 @@ Erroneous code example: #![feature(ffi_const, ffi_pure)] extern "C" { - #[ffi_const] - #[ffi_pure] // error: `#[ffi_const]` function cannot be `#[ffi_pure]` + #[unsafe(ffi_const)] + #[unsafe(ffi_pure)] + //~^ ERROR `#[ffi_const]` function cannot be `#[ffi_pure]` pub fn square(num: i32) -> i32; } ``` @@ -19,7 +20,7 @@ As `ffi_const` provides stronger guarantees than `ffi_pure`, remove the #![feature(ffi_const)] extern "C" { - #[ffi_const] + #[unsafe(ffi_const)] pub fn square(num: i32) -> i32; } ``` diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 1e33e2e9393f..7615362e1f9d 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -6,6 +6,7 @@ use AttributeDuplicates::*; use AttributeGate::*; use AttributeType::*; use rustc_data_structures::fx::FxHashMap; +use rustc_span::edition::Edition; use rustc_span::{Symbol, sym}; use crate::{Features, Stability}; @@ -65,9 +66,12 @@ pub enum AttributeSafety { /// Normal attribute that does not need `#[unsafe(...)]` Normal, - /// Unsafe attribute that requires safety obligations - /// to be discharged - Unsafe, + /// Unsafe attribute that requires safety obligations to be discharged. + /// + /// An error is emitted when `#[unsafe(...)]` is omitted, except when the attribute's edition + /// is less than the one stored in `unsafe_since`. This handles attributes that were safe in + /// earlier editions, but become unsafe in later ones. + Unsafe { unsafe_since: Option }, } #[derive(Clone, Copy)] @@ -187,12 +191,23 @@ macro_rules! template { } macro_rules! ungated { + (unsafe($edition:ident) $attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr $(,)?) => { + BuiltinAttribute { + name: sym::$attr, + encode_cross_crate: $encode_cross_crate, + type_: $typ, + safety: AttributeSafety::Unsafe { unsafe_since: Some(Edition::$edition) }, + template: $tpl, + gate: Ungated, + duplicates: $duplicates, + } + }; (unsafe $attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr $(,)?) => { BuiltinAttribute { name: sym::$attr, encode_cross_crate: $encode_cross_crate, type_: $typ, - safety: AttributeSafety::Unsafe, + safety: AttributeSafety::Unsafe { unsafe_since: None }, template: $tpl, gate: Ungated, duplicates: $duplicates, @@ -217,7 +232,7 @@ macro_rules! gated { name: sym::$attr, encode_cross_crate: $encode_cross_crate, type_: $typ, - safety: AttributeSafety::Unsafe, + safety: AttributeSafety::Unsafe { unsafe_since: None }, template: $tpl, duplicates: $duplicates, gate: Gated(Stability::Unstable, sym::$gate, $msg, Features::$gate), @@ -228,7 +243,7 @@ macro_rules! gated { name: sym::$attr, encode_cross_crate: $encode_cross_crate, type_: $typ, - safety: AttributeSafety::Unsafe, + safety: AttributeSafety::Unsafe { unsafe_since: None }, template: $tpl, duplicates: $duplicates, gate: Gated(Stability::Unstable, sym::$attr, $msg, Features::$attr), @@ -423,9 +438,9 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), ungated!(no_link, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No), ungated!(repr, Normal, template!(List: "C"), DuplicatesOk, EncodeCrossCrate::No), - ungated!(unsafe export_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding, EncodeCrossCrate::No), - ungated!(unsafe link_section, Normal, template!(NameValueStr: "name"), FutureWarnPreceding, EncodeCrossCrate::No), - ungated!(unsafe no_mangle, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No), + ungated!(unsafe(Edition2024) export_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding, EncodeCrossCrate::No), + ungated!(unsafe(Edition2024) link_section, Normal, template!(NameValueStr: "name"), FutureWarnPreceding, EncodeCrossCrate::No), + ungated!(unsafe(Edition2024) no_mangle, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No), ungated!(used, Normal, template!(Word, List: "compiler|linker"), WarnFollowing, EncodeCrossCrate::No), ungated!(link_ordinal, Normal, template!(List: "ordinal"), ErrorPreceding, EncodeCrossCrate::Yes), diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index 6bbd650dcdfe..6a1c2af48ed5 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -157,7 +157,7 @@ fn is_attr_template_compatible(template: &AttributeTemplate, meta: &ast::MetaIte pub fn check_attribute_safety(psess: &ParseSess, safety: AttributeSafety, attr: &Attribute) { let attr_item = attr.get_normal_item(); - if safety == AttributeSafety::Unsafe { + if let AttributeSafety::Unsafe { unsafe_since } = safety { if let ast::Safety::Default = attr_item.unsafety { let path_span = attr_item.path.span; @@ -167,7 +167,13 @@ pub fn check_attribute_safety(psess: &ParseSess, safety: AttributeSafety, attr: // square bracket respectively. let diag_span = attr_item.span(); - if attr.span.at_least_rust_2024() { + // Attributes can be safe in earlier editions, and become unsafe in later ones. + let emit_error = match unsafe_since { + None => true, + Some(unsafe_since) => attr.span.edition() >= unsafe_since, + }; + + if emit_error { psess.dcx().emit_err(errors::UnsafeAttrOutsideUnsafe { span: path_span, suggestion: errors::UnsafeAttrOutsideUnsafeSuggestion { diff --git a/tests/codegen/cffi/ffi-const.rs b/tests/codegen/cffi/ffi-const.rs index 6c90902e89fe..3ea9d517ec25 100644 --- a/tests/codegen/cffi/ffi-const.rs +++ b/tests/codegen/cffi/ffi-const.rs @@ -10,6 +10,6 @@ extern "C" { // CHECK-LABEL: declare{{.*}}void @foo() // CHECK-SAME: [[ATTRS:#[0-9]+]] // CHECK-DAG: attributes [[ATTRS]] = { {{.*}}memory(none){{.*}} } - #[ffi_const] + #[unsafe(ffi_const)] pub fn foo(); } diff --git a/tests/codegen/cffi/ffi-pure.rs b/tests/codegen/cffi/ffi-pure.rs index 2c5d5f5b4b12..a61e80ecf652 100644 --- a/tests/codegen/cffi/ffi-pure.rs +++ b/tests/codegen/cffi/ffi-pure.rs @@ -10,6 +10,6 @@ extern "C" { // CHECK-LABEL: declare{{.*}}void @foo() // CHECK-SAME: [[ATTRS:#[0-9]+]] // CHECK-DAG: attributes [[ATTRS]] = { {{.*}}memory(read){{.*}} } - #[ffi_pure] + #[unsafe(ffi_pure)] pub fn foo(); } diff --git a/tests/ui/feature-gates/feature-gate-ffi_const.rs b/tests/ui/feature-gates/feature-gate-ffi_const.rs index 9f3d783ccd69..35f91b99a6f4 100644 --- a/tests/ui/feature-gates/feature-gate-ffi_const.rs +++ b/tests/ui/feature-gates/feature-gate-ffi_const.rs @@ -1,6 +1,6 @@ #![crate_type = "lib"] extern "C" { - #[ffi_const] //~ ERROR the `#[ffi_const]` attribute is an experimental feature + #[unsafe(ffi_const)] //~ ERROR the `#[ffi_const]` attribute is an experimental feature pub fn foo(); } diff --git a/tests/ui/feature-gates/feature-gate-ffi_const.stderr b/tests/ui/feature-gates/feature-gate-ffi_const.stderr index d083b826d6e1..7e8c941be07d 100644 --- a/tests/ui/feature-gates/feature-gate-ffi_const.stderr +++ b/tests/ui/feature-gates/feature-gate-ffi_const.stderr @@ -1,8 +1,8 @@ error[E0658]: the `#[ffi_const]` attribute is an experimental feature --> $DIR/feature-gate-ffi_const.rs:4:5 | -LL | #[ffi_const] - | ^^^^^^^^^^^^ +LL | #[unsafe(ffi_const)] + | ^^^^^^^^^^^^^^^^^^^^ | = note: see issue #58328 for more information = help: add `#![feature(ffi_const)]` to the crate attributes to enable diff --git a/tests/ui/feature-gates/feature-gate-ffi_pure.rs b/tests/ui/feature-gates/feature-gate-ffi_pure.rs index b0dfa01ff4c2..0f1288b234e4 100644 --- a/tests/ui/feature-gates/feature-gate-ffi_pure.rs +++ b/tests/ui/feature-gates/feature-gate-ffi_pure.rs @@ -1,6 +1,6 @@ #![crate_type = "lib"] extern "C" { - #[ffi_pure] //~ ERROR the `#[ffi_pure]` attribute is an experimental feature + #[unsafe(ffi_pure)] //~ ERROR the `#[ffi_pure]` attribute is an experimental feature pub fn foo(); } diff --git a/tests/ui/feature-gates/feature-gate-ffi_pure.stderr b/tests/ui/feature-gates/feature-gate-ffi_pure.stderr index 6544d450eeb9..cf923536d6c5 100644 --- a/tests/ui/feature-gates/feature-gate-ffi_pure.stderr +++ b/tests/ui/feature-gates/feature-gate-ffi_pure.stderr @@ -1,8 +1,8 @@ error[E0658]: the `#[ffi_pure]` attribute is an experimental feature --> $DIR/feature-gate-ffi_pure.rs:4:5 | -LL | #[ffi_pure] - | ^^^^^^^^^^^ +LL | #[unsafe(ffi_pure)] + | ^^^^^^^^^^^^^^^^^^^ | = note: see issue #58329 for more information = help: add `#![feature(ffi_pure)]` to the crate attributes to enable diff --git a/tests/ui/ffi-attrs/ffi_const.rs b/tests/ui/ffi-attrs/ffi_const.rs index aa20a4d4c653..dddc862b0fa6 100644 --- a/tests/ui/ffi-attrs/ffi_const.rs +++ b/tests/ui/ffi-attrs/ffi_const.rs @@ -1,15 +1,18 @@ #![feature(ffi_const)] #![crate_type = "lib"] -#[ffi_const] //~ ERROR `#[ffi_const]` may only be used on foreign functions +#[unsafe(ffi_const)] //~ ERROR `#[ffi_const]` may only be used on foreign functions pub fn foo() {} -#[ffi_const] //~ ERROR `#[ffi_const]` may only be used on foreign functions +#[unsafe(ffi_const)] //~ ERROR `#[ffi_const]` may only be used on foreign functions macro_rules! bar { - () => () + () => {}; } extern "C" { - #[ffi_const] //~ ERROR `#[ffi_const]` may only be used on foreign functions + #[unsafe(ffi_const)] //~ ERROR `#[ffi_const]` may only be used on foreign functions static INT: i32; + + #[ffi_const] //~ ERROR unsafe attribute used without unsafe + fn bar(); } diff --git a/tests/ui/ffi-attrs/ffi_const.stderr b/tests/ui/ffi-attrs/ffi_const.stderr index 394b98f89712..7f31237539d1 100644 --- a/tests/ui/ffi-attrs/ffi_const.stderr +++ b/tests/ui/ffi-attrs/ffi_const.stderr @@ -1,21 +1,32 @@ +error: unsafe attribute used without unsafe + --> $DIR/ffi_const.rs:16:7 + | +LL | #[ffi_const] + | ^^^^^^^^^ usage of unsafe attribute + | +help: wrap the attribute in `unsafe(...)` + | +LL | #[unsafe(ffi_const)] + | +++++++ + + error[E0756]: `#[ffi_const]` may only be used on foreign functions --> $DIR/ffi_const.rs:4:1 | -LL | #[ffi_const] - | ^^^^^^^^^^^^ +LL | #[unsafe(ffi_const)] + | ^^^^^^^^^^^^^^^^^^^^ error[E0756]: `#[ffi_const]` may only be used on foreign functions --> $DIR/ffi_const.rs:7:1 | -LL | #[ffi_const] - | ^^^^^^^^^^^^ +LL | #[unsafe(ffi_const)] + | ^^^^^^^^^^^^^^^^^^^^ error[E0756]: `#[ffi_const]` may only be used on foreign functions --> $DIR/ffi_const.rs:13:5 | -LL | #[ffi_const] - | ^^^^^^^^^^^^ +LL | #[unsafe(ffi_const)] + | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0756`. diff --git a/tests/ui/ffi-attrs/ffi_const2.rs b/tests/ui/ffi-attrs/ffi_const2.rs index 82fe8a9c91dd..8a8de13b1530 100644 --- a/tests/ui/ffi-attrs/ffi_const2.rs +++ b/tests/ui/ffi-attrs/ffi_const2.rs @@ -1,8 +1,8 @@ #![feature(ffi_const, ffi_pure)] extern "C" { - #[ffi_pure] //~ ERROR `#[ffi_const]` function cannot be `#[ffi_pure]` - #[ffi_const] + #[unsafe(ffi_pure)] //~ ERROR `#[ffi_const]` function cannot be `#[ffi_pure]` + #[unsafe(ffi_const)] pub fn baz(); } diff --git a/tests/ui/ffi-attrs/ffi_const2.stderr b/tests/ui/ffi-attrs/ffi_const2.stderr index b8cbc296370d..d4c9bc42ec9e 100644 --- a/tests/ui/ffi-attrs/ffi_const2.stderr +++ b/tests/ui/ffi-attrs/ffi_const2.stderr @@ -1,8 +1,8 @@ error[E0757]: `#[ffi_const]` function cannot be `#[ffi_pure]` --> $DIR/ffi_const2.rs:4:5 | -LL | #[ffi_pure] - | ^^^^^^^^^^^ +LL | #[unsafe(ffi_pure)] + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/ffi-attrs/ffi_pure.rs b/tests/ui/ffi-attrs/ffi_pure.rs index 6d2f3a614ec9..1f4812f55cf1 100644 --- a/tests/ui/ffi-attrs/ffi_pure.rs +++ b/tests/ui/ffi-attrs/ffi_pure.rs @@ -1,15 +1,18 @@ #![feature(ffi_pure)] #![crate_type = "lib"] -#[ffi_pure] //~ ERROR `#[ffi_pure]` may only be used on foreign functions +#[unsafe(ffi_pure)] //~ ERROR `#[ffi_pure]` may only be used on foreign functions pub fn foo() {} -#[ffi_pure] //~ ERROR `#[ffi_pure]` may only be used on foreign functions +#[unsafe(ffi_pure)] //~ ERROR `#[ffi_pure]` may only be used on foreign functions macro_rules! bar { - () => () + () => {}; } extern "C" { - #[ffi_pure] //~ ERROR `#[ffi_pure]` may only be used on foreign functions + #[unsafe(ffi_pure)] //~ ERROR `#[ffi_pure]` may only be used on foreign functions static INT: i32; + + #[ffi_pure] //~ ERROR unsafe attribute used without unsafe + fn bar(); } diff --git a/tests/ui/ffi-attrs/ffi_pure.stderr b/tests/ui/ffi-attrs/ffi_pure.stderr index 8b61a4b609fc..bd1177c01e2b 100644 --- a/tests/ui/ffi-attrs/ffi_pure.stderr +++ b/tests/ui/ffi-attrs/ffi_pure.stderr @@ -1,21 +1,32 @@ +error: unsafe attribute used without unsafe + --> $DIR/ffi_pure.rs:16:7 + | +LL | #[ffi_pure] + | ^^^^^^^^ usage of unsafe attribute + | +help: wrap the attribute in `unsafe(...)` + | +LL | #[unsafe(ffi_pure)] + | +++++++ + + error[E0755]: `#[ffi_pure]` may only be used on foreign functions --> $DIR/ffi_pure.rs:4:1 | -LL | #[ffi_pure] - | ^^^^^^^^^^^ +LL | #[unsafe(ffi_pure)] + | ^^^^^^^^^^^^^^^^^^^ error[E0755]: `#[ffi_pure]` may only be used on foreign functions --> $DIR/ffi_pure.rs:7:1 | -LL | #[ffi_pure] - | ^^^^^^^^^^^ +LL | #[unsafe(ffi_pure)] + | ^^^^^^^^^^^^^^^^^^^ error[E0755]: `#[ffi_pure]` may only be used on foreign functions --> $DIR/ffi_pure.rs:13:5 | -LL | #[ffi_pure] - | ^^^^^^^^^^^ +LL | #[unsafe(ffi_pure)] + | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0755`. From 5d90ccb0fa2e9d2bb0146de225921ebc260b30bb Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Sun, 13 Apr 2025 00:35:06 +0100 Subject: [PATCH 400/606] Move `select_unpredictable` to the `hint` module --- library/core/src/bool.rs | 48 ------------------ library/core/src/hint.rs | 49 +++++++++++++++++++ library/core/src/intrinsics/mod.rs | 2 +- library/core/src/slice/mod.rs | 2 +- .../core/src/slice/sort/shared/smallsort.rs | 18 +++---- .../intrinsics/select_unpredictable.rs | 8 +-- 6 files changed, 64 insertions(+), 63 deletions(-) diff --git a/library/core/src/bool.rs b/library/core/src/bool.rs index d525ab425e60..2016ece007eb 100644 --- a/library/core/src/bool.rs +++ b/library/core/src/bool.rs @@ -61,52 +61,4 @@ impl bool { pub fn then T>(self, f: F) -> Option { if self { Some(f()) } else { None } } - - /// Returns either `true_val` or `false_val` depending on the value of - /// `self`, with a hint to the compiler that `self` is unlikely - /// to be correctly predicted by a CPU’s branch predictor. - /// - /// This method is functionally equivalent to - /// ```ignore (this is just for illustrative purposes) - /// fn select_unpredictable(b: bool, true_val: T, false_val: T) -> T { - /// if b { true_val } else { false_val } - /// } - /// ``` - /// but might generate different assembly. In particular, on platforms with - /// a conditional move or select instruction (like `cmov` on x86 or `csel` - /// on ARM) the optimizer might use these instructions to avoid branches, - /// which can benefit performance if the branch predictor is struggling - /// with predicting `condition`, such as in an implementation of binary - /// search. - /// - /// Note however that this lowering is not guaranteed (on any platform) and - /// should not be relied upon when trying to write constant-time code. Also - /// be aware that this lowering might *decrease* performance if `condition` - /// is well-predictable. It is advisable to perform benchmarks to tell if - /// this function is useful. - /// - /// # Examples - /// - /// Distribute values evenly between two buckets: - /// ``` - /// #![feature(select_unpredictable)] - /// - /// use std::hash::BuildHasher; - /// - /// fn append(hasher: &H, v: i32, bucket_one: &mut Vec, bucket_two: &mut Vec) { - /// let hash = hasher.hash_one(&v); - /// let bucket = (hash % 2 == 0).select_unpredictable(bucket_one, bucket_two); - /// bucket.push(v); - /// } - /// # let hasher = std::collections::hash_map::RandomState::new(); - /// # let mut bucket_one = Vec::new(); - /// # let mut bucket_two = Vec::new(); - /// # append(&hasher, 42, &mut bucket_one, &mut bucket_two); - /// # assert_eq!(bucket_one.len() + bucket_two.len(), 1); - /// ``` - #[inline(always)] - #[unstable(feature = "select_unpredictable", issue = "133962")] - pub fn select_unpredictable(self, true_val: T, false_val: T) -> T { - crate::intrinsics::select_unpredictable(self, true_val, false_val) - } } diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index 5ce282b05de7..f6708cc4bc91 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -734,3 +734,52 @@ pub const fn unlikely(b: bool) -> bool { pub const fn cold_path() { crate::intrinsics::cold_path() } + +/// Returns either `true_val` or `false_val` depending on the value of `b`, +/// with a hint to the compiler that `b` is unlikely to be correctly +/// predicted by a CPU’s branch predictor. +/// +/// This method is functionally equivalent to +/// ```ignore (this is just for illustrative purposes) +/// fn select_unpredictable(b: bool, true_val: T, false_val: T) -> T { +/// if b { true_val } else { false_val } +/// } +/// ``` +/// but might generate different assembly. In particular, on platforms with +/// a conditional move or select instruction (like `cmov` on x86 or `csel` +/// on ARM) the optimizer might use these instructions to avoid branches, +/// which can benefit performance if the branch predictor is struggling +/// with predicting `condition`, such as in an implementation of binary +/// search. +/// +/// Note however that this lowering is not guaranteed (on any platform) and +/// should not be relied upon when trying to write constant-time code. Also +/// be aware that this lowering might *decrease* performance if `condition` +/// is well-predictable. It is advisable to perform benchmarks to tell if +/// this function is useful. +/// +/// # Examples +/// +/// Distribute values evenly between two buckets: +/// ``` +/// #![feature(select_unpredictable)] +/// +/// use std::hash::BuildHasher; +/// use std::hint; +/// +/// fn append(hasher: &H, v: i32, bucket_one: &mut Vec, bucket_two: &mut Vec) { +/// let hash = hasher.hash_one(&v); +/// let bucket = hint::select_unpredictable(hash % 2 == 0, bucket_one, bucket_two); +/// bucket.push(v); +/// } +/// # let hasher = std::collections::hash_map::RandomState::new(); +/// # let mut bucket_one = Vec::new(); +/// # let mut bucket_two = Vec::new(); +/// # append(&hasher, 42, &mut bucket_one, &mut bucket_two); +/// # assert_eq!(bucket_one.len() + bucket_two.len(), 1); +/// ``` +#[inline(always)] +#[unstable(feature = "select_unpredictable", issue = "133962")] +pub fn select_unpredictable(b: bool, true_val: T, false_val: T) -> T { + crate::intrinsics::select_unpredictable(b, true_val, false_val) +} diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index e99776a71c1d..a55a52cf34c5 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -1326,7 +1326,7 @@ pub const fn unlikely(b: bool) -> bool { /// Therefore, implementations must not require the user to uphold /// any safety invariants. /// -/// The public form of this instrinsic is [`bool::select_unpredictable`]. +/// The public form of this instrinsic is [`core::hint::select_unpredictable`]. #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic] #[rustc_nounwind] diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index b906899a30b3..d91b5bacbebc 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -2828,7 +2828,7 @@ impl [T] { // Binary search interacts poorly with branch prediction, so force // the compiler to use conditional moves if supported by the target // architecture. - base = (cmp == Greater).select_unpredictable(base, mid); + base = hint::select_unpredictable(cmp == Greater, base, mid); // This is imprecise in the case where `size` is odd and the // comparison returns Greater: the mid element still gets included diff --git a/library/core/src/slice/sort/shared/smallsort.rs b/library/core/src/slice/sort/shared/smallsort.rs index 95f196a40d01..4280f7570db4 100644 --- a/library/core/src/slice/sort/shared/smallsort.rs +++ b/library/core/src/slice/sort/shared/smallsort.rs @@ -2,7 +2,7 @@ use crate::mem::{self, ManuallyDrop, MaybeUninit}; use crate::slice::sort::shared::FreezeMarker; -use crate::{intrinsics, ptr, slice}; +use crate::{hint, intrinsics, ptr, slice}; // It's important to differentiate between SMALL_SORT_THRESHOLD performance for // small slices and small-sort performance sorting small sub-slices as part of @@ -408,8 +408,8 @@ where // } // The goal is to generate cmov instructions here. - let v_a_swap = should_swap.select_unpredictable(v_b, v_a); - let v_b_swap = should_swap.select_unpredictable(v_a, v_b); + let v_a_swap = hint::select_unpredictable(should_swap, v_b, v_a); + let v_b_swap = hint::select_unpredictable(should_swap, v_a, v_b); let v_b_swap_tmp = ManuallyDrop::new(ptr::read(v_b_swap)); ptr::copy(v_a_swap, v_a, 1); @@ -640,15 +640,15 @@ pub unsafe fn sort4_stable bool>( // 1, 1 | c b a d let c3 = is_less(&*c, &*a); let c4 = is_less(&*d, &*b); - let min = c3.select_unpredictable(c, a); - let max = c4.select_unpredictable(b, d); - let unknown_left = c3.select_unpredictable(a, c4.select_unpredictable(c, b)); - let unknown_right = c4.select_unpredictable(d, c3.select_unpredictable(b, c)); + let min = hint::select_unpredictable(c3, c, a); + let max = hint::select_unpredictable(c4, b, d); + let unknown_left = hint::select_unpredictable(c3, a, hint::select_unpredictable(c4, c, b)); + let unknown_right = hint::select_unpredictable(c4, d, hint::select_unpredictable(c3, b, c)); // Sort the last two unknown elements. let c5 = is_less(&*unknown_right, &*unknown_left); - let lo = c5.select_unpredictable(unknown_right, unknown_left); - let hi = c5.select_unpredictable(unknown_left, unknown_right); + let lo = hint::select_unpredictable(c5, unknown_right, unknown_left); + let hi = hint::select_unpredictable(c5, unknown_left, unknown_right); ptr::copy_nonoverlapping(min, dst, 1); ptr::copy_nonoverlapping(lo, dst.add(1), 1); diff --git a/tests/codegen/intrinsics/select_unpredictable.rs b/tests/codegen/intrinsics/select_unpredictable.rs index 68a02c8342d0..2db4ae174b33 100644 --- a/tests/codegen/intrinsics/select_unpredictable.rs +++ b/tests/codegen/intrinsics/select_unpredictable.rs @@ -46,21 +46,21 @@ pub fn test_zst(p: bool, a: (), b: ()) -> () { pub fn test_int2(p: bool, a: u64, b: u64) -> u64 { // CHECK-LABEL: define{{.*}} @test_int2 // CHECK: select i1 %p, i64 %a, i64 %b, !unpredictable - p.select_unpredictable(a, b) + core::hint::select_unpredictable(p, a, b) } #[no_mangle] pub fn test_pair2(p: bool, a: (u64, u64), b: (u64, u64)) -> (u64, u64) { // CHECK-LABEL: define{{.*}} @test_pair2 // CHECK: select i1 %p, {{.*}}, !unpredictable - p.select_unpredictable(a, b) + core::hint::select_unpredictable(p, a, b) } #[no_mangle] pub fn test_struct2(p: bool, a: Large, b: Large) -> Large { // CHECK-LABEL: define{{.*}} @test_struct2 // CHECK: select i1 %p, {{.*}}, !unpredictable - p.select_unpredictable(a, b) + core::hint::select_unpredictable(p, a, b) } #[no_mangle] @@ -68,5 +68,5 @@ pub fn test_zst2(p: bool, a: (), b: ()) -> () { // CHECK-LABEL: define{{.*}} @test_zst2 // CHECK-NEXT: start: // CHECK-NEXT: ret void - p.select_unpredictable(a, b) + core::hint::select_unpredictable(p, a, b) } From f35eae780b492cca74d6ada59dc857959d937cd4 Mon Sep 17 00:00:00 2001 From: dianne Date: Fri, 14 Mar 2025 18:56:15 -0700 Subject: [PATCH 401/606] store the kind of pattern adjustments in `pat_adjustments` This allows us to better distinguish builtin and overloaded implicit dereferences. --- .../rustc_hir_typeck/src/expr_use_visitor.rs | 6 ++--- compiler/rustc_hir_typeck/src/pat.rs | 3 ++- compiler/rustc_middle/src/ty/adjustment.rs | 22 +++++++++++++++++++ .../rustc_middle/src/ty/structural_impls.rs | 6 +++++ .../rustc_middle/src/ty/typeck_results.rs | 10 ++++++--- .../src/thir/pattern/migration.rs | 8 +++---- .../rustc_mir_build/src/thir/pattern/mod.rs | 9 ++++---- .../clippy_lints/src/pattern_type_mismatch.rs | 2 +- 8 files changed, 50 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 27df8f0e98a1..f43f9b5187b6 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -1227,9 +1227,9 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx // actually this is somewhat "disjoint" from the code below // that aims to account for `ref x`. if let Some(vec) = self.cx.typeck_results().pat_adjustments().get(pat.hir_id) { - if let Some(first_ty) = vec.first() { - debug!("pat_ty(pat={:?}) found adjusted ty `{:?}`", pat, first_ty); - return Ok(*first_ty); + if let Some(first_adjust) = vec.first() { + debug!("pat_ty(pat={:?}) found adjustment `{:?}`", pat, first_adjust); + return Ok(first_adjust.source); } } else if let PatKind::Ref(subpat, _) = pat.kind && self.cx.typeck_results().skipped_ref_pats().contains(pat.hir_id) diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index fbc783c05090..c19d8cf6dc54 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -29,6 +29,7 @@ use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode}; use tracing::{debug, instrument, trace}; use ty::VariantDef; +use ty::adjustment::{PatAdjust, PatAdjustment}; use super::report_unexpected_variant_res; use crate::expectation::Expectation; @@ -415,7 +416,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .pat_adjustments_mut() .entry(pat.hir_id) .or_default() - .push(expected); + .push(PatAdjustment { kind: PatAdjust::BuiltinDeref, source: expected }); let mut binding_mode = ByRef::Yes(match pat_info.binding_mode { // If default binding mode is by value, make it `ref` or `ref mut` diff --git a/compiler/rustc_middle/src/ty/adjustment.rs b/compiler/rustc_middle/src/ty/adjustment.rs index f8ab555305f0..981d67e58d4b 100644 --- a/compiler/rustc_middle/src/ty/adjustment.rs +++ b/compiler/rustc_middle/src/ty/adjustment.rs @@ -214,3 +214,25 @@ pub enum CustomCoerceUnsized { /// Records the index of the field being coerced. Struct(FieldIdx), } + +/// Represents an implicit coercion applied to the scrutinee of a match before testing a pattern +/// against it. Currently, this is used only for implicit dereferences. +#[derive(Clone, Copy, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] +pub struct PatAdjustment<'tcx> { + pub kind: PatAdjust, + /// The type of the scrutinee before the adjustment is applied, or the "adjusted type" of the + /// pattern. + pub source: Ty<'tcx>, +} + +/// Represents implicit coercions of patterns' types, rather than values' types. +#[derive(Clone, Copy, PartialEq, Debug, TyEncodable, TyDecodable, HashStable)] +#[derive(TypeFoldable, TypeVisitable)] +pub enum PatAdjust { + /// An implicit dereference before matching, such as when matching the pattern `0` against a + /// scrutinee of type `&u8` or `&mut u8`. + BuiltinDeref, + /// An implicit call to `Deref(Mut)::deref(_mut)` before matching, such as when matching the + /// pattern `[..]` against a scrutinee of type `Vec`. + OverloadedDeref, +} diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 798ef352c408..6434e1a1ad9a 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -61,6 +61,12 @@ impl<'tcx> fmt::Debug for ty::adjustment::Adjustment<'tcx> { } } +impl<'tcx> fmt::Debug for ty::adjustment::PatAdjustment<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{} -> {:?}", self.source, self.kind) + } +} + impl fmt::Debug for ty::BoundRegionKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index 90c6ef67fb88..ee8113b0f762 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -90,7 +90,7 @@ pub struct TypeckResults<'tcx> { /// /// See: /// - pat_adjustments: ItemLocalMap>>, + pat_adjustments: ItemLocalMap>>, /// Set of reference patterns that match against a match-ergonomics inserted reference /// (as opposed to against a reference in the scrutinee type). @@ -403,11 +403,15 @@ impl<'tcx> TypeckResults<'tcx> { LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_binding_modes } } - pub fn pat_adjustments(&self) -> LocalTableInContext<'_, Vec>> { + pub fn pat_adjustments( + &self, + ) -> LocalTableInContext<'_, Vec>> { LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_adjustments } } - pub fn pat_adjustments_mut(&mut self) -> LocalTableInContextMut<'_, Vec>> { + pub fn pat_adjustments_mut( + &mut self, + ) -> LocalTableInContextMut<'_, Vec>> { LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_adjustments } } diff --git a/compiler/rustc_mir_build/src/thir/pattern/migration.rs b/compiler/rustc_mir_build/src/thir/pattern/migration.rs index bd7787b643d5..c688b6f2848c 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/migration.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/migration.rs @@ -5,7 +5,7 @@ use rustc_errors::MultiSpan; use rustc_hir::{BindingMode, ByRef, HirId, Mutability}; use rustc_lint as lint; use rustc_middle::span_bug; -use rustc_middle::ty::{self, Rust2024IncompatiblePatInfo, Ty, TyCtxt}; +use rustc_middle::ty::{self, Rust2024IncompatiblePatInfo, TyCtxt}; use rustc_span::{Ident, Span}; use crate::errors::{Rust2024IncompatiblePat, Rust2024IncompatiblePatSugg}; @@ -93,10 +93,10 @@ impl<'a> PatMigration<'a> { pub(super) fn visit_implicit_derefs<'tcx>( &mut self, pat_span: Span, - adjustments: &[Ty<'tcx>], + adjustments: &[ty::adjustment::PatAdjustment<'tcx>], ) -> Option<(Span, Mutability)> { - let implicit_deref_mutbls = adjustments.iter().map(|ref_ty| { - let &ty::Ref(_, _, mutbl) = ref_ty.kind() else { + let implicit_deref_mutbls = adjustments.iter().map(|adjust| { + let &ty::Ref(_, _, mutbl) = adjust.source.kind() else { span_bug!(pat_span, "pattern implicitly dereferences a non-ref type"); }; mutbl diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 73d60cf44423..f682581d763b 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -18,6 +18,7 @@ use rustc_middle::mir::interpret::LitToConstInput; use rustc_middle::thir::{ Ascription, FieldPat, LocalVarId, Pat, PatKind, PatRange, PatRangeBoundary, }; +use rustc_middle::ty::adjustment::PatAdjustment; use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt, TypingMode}; use rustc_middle::{bug, span_bug}; @@ -63,7 +64,7 @@ pub(super) fn pat_from_hir<'a, 'tcx>( impl<'a, 'tcx> PatCtxt<'a, 'tcx> { fn lower_pattern(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box> { - let adjustments: &[Ty<'tcx>] = + let adjustments: &[PatAdjustment<'tcx>] = self.typeck_results.pat_adjustments().get(pat.hir_id).map_or(&[], |v| &**v); // Track the default binding mode for the Rust 2024 migration suggestion. @@ -102,11 +103,11 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { _ => self.lower_pattern_unadjusted(pat), }; - let adjusted_pat = adjustments.iter().rev().fold(unadjusted_pat, |thir_pat, ref_ty| { - debug!("{:?}: wrapping pattern with type {:?}", thir_pat, ref_ty); + let adjusted_pat = adjustments.iter().rev().fold(unadjusted_pat, |thir_pat, adjust| { + debug!("{:?}: wrapping pattern with type {:?}", thir_pat, adjust); Box::new(Pat { span: thir_pat.span, - ty: *ref_ty, + ty: adjust.source, kind: PatKind::Deref { subpattern: thir_pat }, }) }); diff --git a/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs b/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs index 8f1a1ee76c6a..96d3f7196c0c 100644 --- a/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs +++ b/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs @@ -179,7 +179,7 @@ fn find_first_mismatch(cx: &LateContext<'_>, pat: &Pat<'_>) -> Option<(Span, Mut }; if let Some(adjustments) = cx.typeck_results().pat_adjustments().get(adjust_pat.hir_id) { if let [first, ..] = **adjustments { - if let ty::Ref(.., mutability) = *first.kind() { + if let ty::Ref(.., mutability) = *first.source.kind() { let level = if p.hir_id == pat.hir_id { Level::Top } else { From 756670f40ebedd4a6cb1ebf356cb327442888d0a Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sun, 23 Mar 2025 20:45:36 -0700 Subject: [PATCH 402/606] Extend the chaining logic to slices too --- library/core/src/cmp.rs | 32 ++++++ library/core/src/slice/cmp.rs | 178 ++++++++++++++++++++++++++++------ library/core/src/tuple.rs | 29 +++++- tests/codegen/array-cmp.rs | 55 +++++++++-- 4 files changed, 256 insertions(+), 38 deletions(-) diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index 0dc2cc72e06c..c315131f4136 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -2053,6 +2053,22 @@ mod impls { fn ge(&self, other: &&B) -> bool { PartialOrd::ge(*self, *other) } + #[inline] + fn __chaining_lt(&self, other: &&B) -> ControlFlow { + PartialOrd::__chaining_lt(*self, *other) + } + #[inline] + fn __chaining_le(&self, other: &&B) -> ControlFlow { + PartialOrd::__chaining_le(*self, *other) + } + #[inline] + fn __chaining_gt(&self, other: &&B) -> ControlFlow { + PartialOrd::__chaining_gt(*self, *other) + } + #[inline] + fn __chaining_ge(&self, other: &&B) -> ControlFlow { + PartialOrd::__chaining_ge(*self, *other) + } } #[stable(feature = "rust1", since = "1.0.0")] impl Ord for &A @@ -2108,6 +2124,22 @@ mod impls { fn ge(&self, other: &&mut B) -> bool { PartialOrd::ge(*self, *other) } + #[inline] + fn __chaining_lt(&self, other: &&mut B) -> ControlFlow { + PartialOrd::__chaining_lt(*self, *other) + } + #[inline] + fn __chaining_le(&self, other: &&mut B) -> ControlFlow { + PartialOrd::__chaining_le(*self, *other) + } + #[inline] + fn __chaining_gt(&self, other: &&mut B) -> ControlFlow { + PartialOrd::__chaining_gt(*self, *other) + } + #[inline] + fn __chaining_ge(&self, other: &&mut B) -> ControlFlow { + PartialOrd::__chaining_ge(*self, *other) + } } #[stable(feature = "rust1", since = "1.0.0")] impl Ord for &mut A diff --git a/library/core/src/slice/cmp.rs b/library/core/src/slice/cmp.rs index da85f42926e6..5ce72b46eee3 100644 --- a/library/core/src/slice/cmp.rs +++ b/library/core/src/slice/cmp.rs @@ -5,6 +5,7 @@ use crate::ascii; use crate::cmp::{self, BytewiseEq, Ordering}; use crate::intrinsics::compare_bytes; use crate::num::NonZero; +use crate::ops::ControlFlow; #[stable(feature = "rust1", since = "1.0.0")] impl PartialEq<[U]> for [T] @@ -31,12 +32,64 @@ impl Ord for [T] { } } +#[inline] +fn as_underlying(x: ControlFlow) -> u8 { + // SAFETY: This will only compile if `bool` and `ControlFlow` have the same + // size (which isn't guaranteed but this is libcore). Because they have the same + // size, it's a niched implementation, which in one byte means there can't be + // any uninitialized memory. The callers then only check for `0` or `1` from this, + // which must necessarily match the `Break` variant, and we're fine no matter + // what ends up getting picked as the value representing `Continue(())`. + unsafe { crate::mem::transmute(x) } +} + /// Implements comparison of slices [lexicographically](Ord#lexicographical-comparison). #[stable(feature = "rust1", since = "1.0.0")] impl PartialOrd for [T] { + #[inline] fn partial_cmp(&self, other: &[T]) -> Option { SlicePartialOrd::partial_compare(self, other) } + #[inline] + fn lt(&self, other: &Self) -> bool { + // This is certainly not the obvious way to implement these methods. + // Unfortunately, using anything that looks at the discriminant means that + // LLVM sees a check for `2` (aka `ControlFlow::Continue(())`) and + // gets very distracted by that, ending up generating extraneous code. + // This should be changed to something simpler once either LLVM is smarter, + // see , or we generate + // niche discriminant checks in a way that doesn't trigger it. + + as_underlying(self.__chaining_lt(other)) == 1 + } + #[inline] + fn le(&self, other: &Self) -> bool { + as_underlying(self.__chaining_le(other)) != 0 + } + #[inline] + fn gt(&self, other: &Self) -> bool { + as_underlying(self.__chaining_gt(other)) == 1 + } + #[inline] + fn ge(&self, other: &Self) -> bool { + as_underlying(self.__chaining_ge(other)) != 0 + } + #[inline] + fn __chaining_lt(&self, other: &Self) -> ControlFlow { + SliceChain::chaining_lt(self, other) + } + #[inline] + fn __chaining_le(&self, other: &Self) -> ControlFlow { + SliceChain::chaining_le(self, other) + } + #[inline] + fn __chaining_gt(&self, other: &Self) -> ControlFlow { + SliceChain::chaining_gt(self, other) + } + #[inline] + fn __chaining_ge(&self, other: &Self) -> ControlFlow { + SliceChain::chaining_ge(self, other) + } } #[doc(hidden)] @@ -99,26 +152,65 @@ trait SlicePartialOrd: Sized { fn partial_compare(left: &[Self], right: &[Self]) -> Option; } +#[doc(hidden)] +// intermediate trait for specialization of slice's PartialOrd chaining methods +trait SliceChain: Sized { + fn chaining_lt(left: &[Self], right: &[Self]) -> ControlFlow; + fn chaining_le(left: &[Self], right: &[Self]) -> ControlFlow; + fn chaining_gt(left: &[Self], right: &[Self]) -> ControlFlow; + fn chaining_ge(left: &[Self], right: &[Self]) -> ControlFlow; +} + +type AlwaysBreak = ControlFlow; + impl SlicePartialOrd for A { default fn partial_compare(left: &[A], right: &[A]) -> Option { - let l = cmp::min(left.len(), right.len()); - - // Slice to the loop iteration range to enable bound check - // elimination in the compiler - let lhs = &left[..l]; - let rhs = &right[..l]; - - for i in 0..l { - match lhs[i].partial_cmp(&rhs[i]) { - Some(Ordering::Equal) => (), - non_eq => return non_eq, - } - } - - left.len().partial_cmp(&right.len()) + let elem_chain = |a, b| match PartialOrd::partial_cmp(a, b) { + Some(Ordering::Equal) => ControlFlow::Continue(()), + non_eq => ControlFlow::Break(non_eq), + }; + let len_chain = |a: &_, b: &_| ControlFlow::Break(usize::partial_cmp(a, b)); + let AlwaysBreak::Break(b) = chaining_impl(left, right, elem_chain, len_chain); + b } } +impl SliceChain for A { + default fn chaining_lt(left: &[Self], right: &[Self]) -> ControlFlow { + chaining_impl(left, right, PartialOrd::__chaining_lt, usize::__chaining_lt) + } + default fn chaining_le(left: &[Self], right: &[Self]) -> ControlFlow { + chaining_impl(left, right, PartialOrd::__chaining_le, usize::__chaining_le) + } + default fn chaining_gt(left: &[Self], right: &[Self]) -> ControlFlow { + chaining_impl(left, right, PartialOrd::__chaining_gt, usize::__chaining_gt) + } + default fn chaining_ge(left: &[Self], right: &[Self]) -> ControlFlow { + chaining_impl(left, right, PartialOrd::__chaining_ge, usize::__chaining_ge) + } +} + +#[inline] +fn chaining_impl<'l, 'r, A: PartialOrd, B, C>( + left: &'l [A], + right: &'r [A], + elem_chain: impl Fn(&'l A, &'r A) -> ControlFlow, + len_chain: impl for<'a> FnOnce(&'a usize, &'a usize) -> ControlFlow, +) -> ControlFlow { + let l = cmp::min(left.len(), right.len()); + + // Slice to the loop iteration range to enable bound check + // elimination in the compiler + let lhs = &left[..l]; + let rhs = &right[..l]; + + for i in 0..l { + elem_chain(&lhs[i], &rhs[i])?; + } + + len_chain(&left.len(), &right.len()) +} + // This is the impl that we would like to have. Unfortunately it's not sound. // See `partial_ord_slice.rs`. /* @@ -165,21 +257,13 @@ trait SliceOrd: Sized { impl SliceOrd for A { default fn compare(left: &[Self], right: &[Self]) -> Ordering { - let l = cmp::min(left.len(), right.len()); - - // Slice to the loop iteration range to enable bound check - // elimination in the compiler - let lhs = &left[..l]; - let rhs = &right[..l]; - - for i in 0..l { - match lhs[i].cmp(&rhs[i]) { - Ordering::Equal => (), - non_eq => return non_eq, - } - } - - left.len().cmp(&right.len()) + let elem_chain = |a, b| match Ord::cmp(a, b) { + Ordering::Equal => ControlFlow::Continue(()), + non_eq => ControlFlow::Break(non_eq), + }; + let len_chain = |a: &_, b: &_| ControlFlow::Break(usize::cmp(a, b)); + let AlwaysBreak::Break(b) = chaining_impl(left, right, elem_chain, len_chain); + b } } @@ -191,7 +275,7 @@ impl SliceOrd for A { /// * For every `x` and `y` of this type, `Ord(x, y)` must return the same /// value as `Ord::cmp(transmute::<_, u8>(x), transmute::<_, u8>(y))`. #[rustc_specialization_trait] -unsafe trait UnsignedBytewiseOrd {} +unsafe trait UnsignedBytewiseOrd: Ord {} unsafe impl UnsignedBytewiseOrd for bool {} unsafe impl UnsignedBytewiseOrd for u8 {} @@ -225,6 +309,38 @@ impl SliceOrd for A { } } +// Don't generate our own chaining loops for `memcmp`-able things either. +impl SliceChain for A { + #[inline] + fn chaining_lt(left: &[Self], right: &[Self]) -> ControlFlow { + match SliceOrd::compare(left, right) { + Ordering::Equal => ControlFlow::Continue(()), + ne => ControlFlow::Break(ne.is_lt()), + } + } + #[inline] + fn chaining_le(left: &[Self], right: &[Self]) -> ControlFlow { + match SliceOrd::compare(left, right) { + Ordering::Equal => ControlFlow::Continue(()), + ne => ControlFlow::Break(ne.is_le()), + } + } + #[inline] + fn chaining_gt(left: &[Self], right: &[Self]) -> ControlFlow { + match SliceOrd::compare(left, right) { + Ordering::Equal => ControlFlow::Continue(()), + ne => ControlFlow::Break(ne.is_gt()), + } + } + #[inline] + fn chaining_ge(left: &[Self], right: &[Self]) -> ControlFlow { + match SliceOrd::compare(left, right) { + Ordering::Equal => ControlFlow::Continue(()), + ne => ControlFlow::Break(ne.is_ge()), + } + } +} + pub(super) trait SliceContains: Sized { fn slice_contains(&self, x: &[Self]) -> bool; } diff --git a/library/core/src/tuple.rs b/library/core/src/tuple.rs index d754bb903430..02eb805ece12 100644 --- a/library/core/src/tuple.rs +++ b/library/core/src/tuple.rs @@ -2,7 +2,7 @@ use crate::cmp::Ordering::{self, *}; use crate::marker::{ConstParamTy_, StructuralPartialEq, UnsizedConstParamTy}; -use crate::ops::ControlFlow::{Break, Continue}; +use crate::ops::ControlFlow::{self, Break, Continue}; // Recursive macro for implementing n-ary tuple functions and operations // @@ -95,6 +95,22 @@ macro_rules! tuple_impls { fn gt(&self, other: &($($T,)+)) -> bool { lexical_ord!(gt, __chaining_gt, $( ${ignore($T)} self.${index()}, other.${index()} ),+) } + #[inline] + fn __chaining_lt(&self, other: &($($T,)+)) -> ControlFlow { + lexical_chain!(__chaining_lt, $( ${ignore($T)} self.${index()}, other.${index()} ),+) + } + #[inline] + fn __chaining_le(&self, other: &($($T,)+)) -> ControlFlow { + lexical_chain!(__chaining_le, $( ${ignore($T)} self.${index()}, other.${index()} ),+) + } + #[inline] + fn __chaining_gt(&self, other: &($($T,)+)) -> ControlFlow { + lexical_chain!(__chaining_gt, $( ${ignore($T)} self.${index()}, other.${index()} ),+) + } + #[inline] + fn __chaining_ge(&self, other: &($($T,)+)) -> ControlFlow { + lexical_chain!(__chaining_ge, $( ${ignore($T)} self.${index()}, other.${index()} ),+) + } } } @@ -187,6 +203,17 @@ macro_rules! lexical_ord { }; } +// Same parameter interleaving as `lexical_ord` above +macro_rules! lexical_chain { + ($chain_rel: ident, $a:expr, $b:expr $(,$rest_a:expr, $rest_b:expr)*) => {{ + PartialOrd::$chain_rel(&$a, &$b)?; + lexical_chain!($chain_rel $(,$rest_a, $rest_b)*) + }}; + ($chain_rel: ident) => { + Continue(()) + }; +} + macro_rules! lexical_partial_cmp { ($a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => { match ($a).partial_cmp(&$b) { diff --git a/tests/codegen/array-cmp.rs b/tests/codegen/array-cmp.rs index f9b7be898828..0d3376554017 100644 --- a/tests/codegen/array-cmp.rs +++ b/tests/codegen/array-cmp.rs @@ -1,6 +1,7 @@ // Ensure the asm for array comparisons is properly optimized. //@ compile-flags: -C opt-level=2 +//@ needs-deterministic-layouts (checks depend on tuple layout) #![crate_type = "lib"] @@ -19,13 +20,55 @@ pub fn compare() -> bool { } // CHECK-LABEL: @array_of_tuple_le -// CHECK: call{{.+}}i8 @llvm.scmp.i8.i16 -// CHECK: call{{.+}}i8 @llvm.ucmp.i8.i16 -// CHECK: call{{.+}}i8 @llvm.scmp.i8.i16 -// CHECK: call{{.+}}i8 @llvm.ucmp.i8.i16 -// CHECK: %[[RET:.+]] = icmp slt i8 {{.+}}, 1 -// CHECK: ret i8 %[[RET]] #[no_mangle] pub fn array_of_tuple_le(a: &[(i16, u16); 2], b: &[(i16, u16); 2]) -> bool { + // Ensure that, after all the optimizations have run, the happy path just checks + // `eq` on each corresponding pair and moves onto the next one if it is. + // Then there's a dedup'd comparison for the place that's different. + // (As opposed to, say, running a full `[su]cmp` as part of checking equality.) + + // This is written quite specifically because different library code was triggering + // along the way, so this + // has enough checks to make sure that's not happening. It doesn't need to be + // *exactly* this IR, but be careful if you ever need to update these checks. + + // CHECK: start: + // CHECK: %[[A00:.+]] = load i16, ptr %a + // CHECK: %[[B00:.+]] = load i16, ptr %b + // CHECK-NOT: cmp + // CHECK: %[[EQ00:.+]] = icmp eq i16 %[[A00]], %[[B00]] + // CHECK-NEXT: br i1 %[[EQ00]], label %[[L01:.+]], label %[[EXIT_S:.+]] + + // CHECK: [[L01]]: + // CHECK: %[[PA01:.+]] = getelementptr{{.+}}i8, ptr %a, {{i32|i64}} 2 + // CHECK: %[[PB01:.+]] = getelementptr{{.+}}i8, ptr %b, {{i32|i64}} 2 + // CHECK: %[[A01:.+]] = load i16, ptr %[[PA01]] + // CHECK: %[[B01:.+]] = load i16, ptr %[[PB01]] + // CHECK-NOT: cmp + // CHECK: %[[EQ01:.+]] = icmp eq i16 %[[A01]], %[[B01]] + // CHECK-NEXT: br i1 %[[EQ01]], label %[[L10:.+]], label %[[EXIT_U:.+]] + + // CHECK: [[L10]]: + // CHECK: %[[PA10:.+]] = getelementptr{{.+}}i8, ptr %a, {{i32|i64}} 4 + // CHECK: %[[PB10:.+]] = getelementptr{{.+}}i8, ptr %b, {{i32|i64}} 4 + // CHECK: %[[A10:.+]] = load i16, ptr %[[PA10]] + // CHECK: %[[B10:.+]] = load i16, ptr %[[PB10]] + // CHECK-NOT: cmp + // CHECK: %[[EQ10:.+]] = icmp eq i16 %[[A10]], %[[B10]] + // CHECK-NEXT: br i1 %[[EQ10]], label %[[L11:.+]], label %[[EXIT_S]] + + // CHECK: [[L11]]: + // CHECK: %[[PA11:.+]] = getelementptr{{.+}}i8, ptr %a, {{i32|i64}} 6 + // CHECK: %[[PB11:.+]] = getelementptr{{.+}}i8, ptr %b, {{i32|i64}} 6 + // CHECK: %[[A11:.+]] = load i16, ptr %[[PA11]] + // CHECK: %[[B11:.+]] = load i16, ptr %[[PB11]] + // CHECK-NOT: cmp + // CHECK: %[[EQ11:.+]] = icmp eq i16 %[[A11]], %[[B11]] + // CHECK-NEXT: br i1 %[[EQ11]], label %[[DONE:.+]], label %[[EXIT_U]] + + // CHECK: [[DONE]]: + // CHECK: %[[RET:.+]] = phi i1 [ %{{.+}}, %[[EXIT_S]] ], [ %{{.+}}, %[[EXIT_U]] ], [ true, %[[L11]] ] + // CHECK: ret i1 %[[RET]] + a <= b } From 21b7360a9aecac472d6b7b9716c8e57641f648d0 Mon Sep 17 00:00:00 2001 From: Sky Date: Fri, 14 Feb 2025 15:56:24 -0500 Subject: [PATCH 403/606] Initial `UnsafePinned`/`UnsafeUnpin` impl [Part 1: Libs] --- compiler/rustc_abi/src/layout.rs | 8 +- compiler/rustc_hir/src/lang_items.rs | 3 + compiler/rustc_lint/src/types.rs | 4 +- compiler/rustc_middle/src/ty/adt.rs | 13 ++ compiler/rustc_span/src/symbol.rs | 2 + compiler/rustc_ty_utils/src/layout.rs | 7 +- library/core/src/lib.rs | 1 + library/core/src/marker.rs | 29 +++ library/core/src/pin.rs | 5 + library/core/src/pin/unsafe_pinned.rs | 197 ++++++++++++++++++ .../unsafe-pinned-hides-niche.rs | 29 +++ 11 files changed, 290 insertions(+), 8 deletions(-) create mode 100644 library/core/src/pin/unsafe_pinned.rs create mode 100644 tests/ui/rfcs/rfc-3467-unsafe-pinned/unsafe-pinned-hides-niche.rs diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index 7bffeaf4cc9e..42250aa173bb 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -315,7 +315,7 @@ impl LayoutCalculator { repr: &ReprOptions, variants: &IndexSlice>, is_enum: bool, - is_unsafe_cell: bool, + is_special_no_niche: bool, scalar_valid_range: (Bound, Bound), discr_range_of_repr: impl Fn(i128, i128) -> (Integer, bool), discriminants: impl Iterator, @@ -348,7 +348,7 @@ impl LayoutCalculator { repr, variants, is_enum, - is_unsafe_cell, + is_special_no_niche, scalar_valid_range, always_sized, present_first, @@ -505,7 +505,7 @@ impl LayoutCalculator { repr: &ReprOptions, variants: &IndexSlice>, is_enum: bool, - is_unsafe_cell: bool, + is_special_no_niche: bool, scalar_valid_range: (Bound, Bound), always_sized: bool, present_first: VariantIdx, @@ -524,7 +524,7 @@ impl LayoutCalculator { let mut st = self.univariant(&variants[v], repr, kind)?; st.variants = Variants::Single { index: v }; - if is_unsafe_cell { + if is_special_no_niche { let hide_niches = |scalar: &mut _| match scalar { Scalar::Initialized { value, valid_range } => { *valid_range = WrappingRange::full(value.size(dl)) diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 90fab01ba2d4..d4488b4b6576 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -182,6 +182,7 @@ language_item_table! { DynMetadata, sym::dyn_metadata, dyn_metadata, Target::Struct, GenericRequirement::None; Freeze, sym::freeze, freeze_trait, Target::Trait, GenericRequirement::Exact(0); + UnsafeUnpin, sym::unsafe_unpin, unsafe_unpin_trait, Target::Trait, GenericRequirement::Exact(0); FnPtrTrait, sym::fn_ptr_trait, fn_ptr_trait, Target::Trait, GenericRequirement::Exact(0); FnPtrAddr, sym::fn_ptr_addr, fn_ptr_addr, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None; @@ -235,6 +236,8 @@ language_item_table! { IndexMut, sym::index_mut, index_mut_trait, Target::Trait, GenericRequirement::Exact(1); UnsafeCell, sym::unsafe_cell, unsafe_cell_type, Target::Struct, GenericRequirement::None; + UnsafePinned, sym::unsafe_pinned, unsafe_pinned_type, Target::Struct, GenericRequirement::None; + VaList, sym::va_list, va_list, Target::Struct, GenericRequirement::None; Deref, sym::deref, deref_trait, Target::Trait, GenericRequirement::Exact(0); diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index a6c82f574a1c..a084dacfb5be 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -864,8 +864,8 @@ fn ty_is_known_nonnull<'tcx>( return true; } - // `UnsafeCell` has its niche hidden. - if def.is_unsafe_cell() { + // `UnsafeCell` and `UnsafePinned` have their niche hidden. + if def.is_unsafe_cell() || def.is_unsafe_pinned() { return false; } diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index 00fe5cb0c5d6..66517c97a687 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -53,6 +53,10 @@ bitflags::bitflags! { const IS_VARIANT_LIST_NON_EXHAUSTIVE = 1 << 8; /// Indicates whether the type is `UnsafeCell`. const IS_UNSAFE_CELL = 1 << 9; + /// Indicates whether the type is `UnsafePinned`. + const IS_UNSAFE_PINNED = 1 << 10; + /// Indicates whether the type is anonymous. + const IS_ANONYMOUS = 1 << 11; } } rustc_data_structures::external_bitflags_debug! { AdtFlags } @@ -302,6 +306,9 @@ impl AdtDefData { if tcx.is_lang_item(did, LangItem::UnsafeCell) { flags |= AdtFlags::IS_UNSAFE_CELL; } + if tcx.is_lang_item(did, LangItem::UnsafePinned) { + flags |= AdtFlags::IS_UNSAFE_PINNED; + } AdtDefData { did, variants, flags, repr } } @@ -405,6 +412,12 @@ impl<'tcx> AdtDef<'tcx> { self.flags().contains(AdtFlags::IS_UNSAFE_CELL) } + /// Returns `true` if this is `UnsafePinned`. + #[inline] + pub fn is_unsafe_pinned(self) -> bool { + self.flags().contains(AdtFlags::IS_UNSAFE_PINNED) + } + /// Returns `true` if this is `ManuallyDrop`. #[inline] pub fn is_manually_drop(self) -> bool { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 986370f50191..63be641d0c1e 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -2215,6 +2215,8 @@ symbols! { unsafe_fields, unsafe_no_drop_flag, unsafe_pin_internals, + unsafe_pinned, + unsafe_unpin, unsize, unsized_const_param_ty, unsized_const_params, diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 0017186c1b08..1915ba623cb2 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -514,6 +514,9 @@ fn layout_of_uncached<'tcx>( return map_layout(cx.calc.layout_of_union(&def.repr(), &variants)); } + // UnsafeCell and UnsafePinned both disable niche optimizations + let is_special_no_niche = def.is_unsafe_cell() || def.is_unsafe_pinned(); + let get_discriminant_type = |min, max| abi::Integer::repr_discr(tcx, ty, &def.repr(), min, max); @@ -542,7 +545,7 @@ fn layout_of_uncached<'tcx>( &def.repr(), &variants, def.is_enum(), - def.is_unsafe_cell(), + is_special_no_niche, tcx.layout_scalar_valid_range(def.did()), get_discriminant_type, discriminants_iter(), @@ -568,7 +571,7 @@ fn layout_of_uncached<'tcx>( &def.repr(), &variants, def.is_enum(), - def.is_unsafe_cell(), + is_special_no_niche, tcx.layout_scalar_valid_range(def.did()), get_discriminant_type, discriminants_iter(), diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index dc06aa4c38d5..5f701921eb66 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -127,6 +127,7 @@ #![feature(ub_checks)] #![feature(unchecked_neg)] #![feature(unchecked_shifts)] +#![feature(unsafe_pinned)] #![feature(utf16_extra)] #![feature(variant_count)] // tidy-alphabetical-end diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 68011310d2ca..9dc20beda6c6 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -17,6 +17,7 @@ use crate::cell::UnsafeCell; use crate::cmp; use crate::fmt::Debug; use crate::hash::{Hash, Hasher}; +use crate::pin::UnsafePinned; /// Implements a given marker trait for multiple types at the same time. /// @@ -878,6 +879,23 @@ marker_impls! { {T: ?Sized} &mut T, } +/// Used to determine whether a type contains any `UnsafePinned` (or `PhantomPinned`) internally, +/// but not through an indirection. This affects, for example, whether we emit `noalias` metadata +/// for `&mut T` or not. +/// +/// This is part of [RFC 3467](https://rust-lang.github.io/rfcs/3467-unsafe-pinned.html), and is +/// tracked by [#125735](https://github.com/rust-lang/rust/issues/125735). +#[cfg_attr(not(bootstrap), lang = "unsafe_unpin")] +#[cfg_attr(bootstrap, allow(dead_code))] +pub(crate) unsafe auto trait UnsafeUnpin {} + +impl !UnsafeUnpin for UnsafePinned {} +unsafe impl UnsafeUnpin for PhantomData {} +unsafe impl UnsafeUnpin for *const T {} +unsafe impl UnsafeUnpin for *mut T {} +unsafe impl UnsafeUnpin for &T {} +unsafe impl UnsafeUnpin for &mut T {} + /// Types that do not require any pinning guarantees. /// /// For information on what "pinning" is, see the [`pin` module] documentation. @@ -953,6 +971,11 @@ pub auto trait Unpin {} /// A marker type which does not implement `Unpin`. /// /// If a type contains a `PhantomPinned`, it will not implement `Unpin` by default. +// +// FIXME(unsafe_pinned): This is *not* a stable guarantee we want to make, at least not yet. +// Note that for backwards compatibility with the new [`UnsafePinned`] wrapper type, placing this +// marker in your struct acts as if you wrapped the entire struct in an `UnsafePinned`. This type +// will likely eventually be deprecated, and all new code should be using `UnsafePinned` instead. #[stable(feature = "pin", since = "1.33.0")] #[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct PhantomPinned; @@ -960,6 +983,12 @@ pub struct PhantomPinned; #[stable(feature = "pin", since = "1.33.0")] impl !Unpin for PhantomPinned {} +// This is a small hack to allow existing code which uses PhantomPinned to opt-out of noalias to +// continue working. Ideally PhantomPinned could just wrap an `UnsafePinned<()>` to get the same +// effect, but we can't add a new field to an already stable unit struct -- that would be a breaking +// change. +impl !UnsafeUnpin for PhantomPinned {} + marker_impls! { #[stable(feature = "pin", since = "1.33.0")] Unpin for diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index 2ef1bbfd1fa7..48ed5ae451e4 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -931,6 +931,11 @@ use crate::{ }; use crate::{cmp, fmt}; +mod unsafe_pinned; + +#[unstable(feature = "unsafe_pinned", issue = "125735")] +pub use self::unsafe_pinned::UnsafePinned; + /// A pointer which pins its pointee in place. /// /// [`Pin`] is a wrapper around some kind of pointer `Ptr` which makes that pointer "pin" its diff --git a/library/core/src/pin/unsafe_pinned.rs b/library/core/src/pin/unsafe_pinned.rs new file mode 100644 index 000000000000..5fb628c8adbc --- /dev/null +++ b/library/core/src/pin/unsafe_pinned.rs @@ -0,0 +1,197 @@ +use crate::marker::{PointerLike, Unpin}; +use crate::ops::{CoerceUnsized, DispatchFromDyn}; +use crate::pin::Pin; +use crate::{fmt, ptr}; + +/// This type provides a way to opt-out of typical aliasing rules; +/// specifically, `&mut UnsafePinned` is not guaranteed to be a unique pointer. +/// +/// However, even if you define your type like `pub struct Wrapper(UnsafePinned<...>)`, it is still +/// very risky to have an `&mut Wrapper` that aliases anything else. Many functions that work +/// generically on `&mut T` assume that the memory that stores `T` is uniquely owned (such as +/// `mem::swap`). In other words, while having aliasing with `&mut Wrapper` is not immediate +/// Undefined Behavior, it is still unsound to expose such a mutable reference to code you do not +/// control! Techniques such as pinning via [`Pin`] are needed to ensure soundness. +/// +/// Similar to [`UnsafeCell`](crate::cell::UnsafeCell), `UnsafePinned` will not usually show up in +/// the public API of a library. It is an internal implementation detail of libraries that need to +/// support aliasing mutable references. +/// +/// Further note that this does *not* lift the requirement that shared references must be read-only! +/// Use `UnsafeCell` for that. +/// +/// This type blocks niches the same way `UnsafeCell` does. +#[cfg_attr(not(bootstrap), lang = "unsafe_pinned")] +#[repr(transparent)] +#[unstable(feature = "unsafe_pinned", issue = "125735")] +pub struct UnsafePinned { + value: T, +} + +/// When this type is used, that almost certainly means safe APIs need to use pinning to avoid the +/// aliases from becoming invalidated. Therefore let's mark this as `!Unpin`. You can always opt +/// back in to `Unpin` with an `impl` block, provided your API is still sound while unpinned. +#[unstable(feature = "unsafe_pinned", issue = "125735")] +impl !Unpin for UnsafePinned {} + +/// The type is `Copy` when `T` is to avoid people assuming that `Copy` implies there is no +/// `UnsafePinned` anywhere. (This is an issue with `UnsafeCell`: people use `Copy` bounds to mean +/// `Freeze`.) Given that there is no `unsafe impl Copy for ...`, this is also the option that +/// leaves the user more choices (as they can always wrap this in a `!Copy` type). +// FIXME(unsafe_pinned): this may be unsound or a footgun? +#[unstable(feature = "unsafe_pinned", issue = "125735")] +impl Copy for UnsafePinned {} + +#[unstable(feature = "unsafe_pinned", issue = "125735")] +impl Clone for UnsafePinned { + fn clone(&self) -> Self { + *self + } +} + +// `Send` and `Sync` are inherited from `T`. This is similar to `SyncUnsafeCell`, since +// we eventually concluded that `UnsafeCell` implicitly making things `!Sync` is sometimes +// unergonomic. A type that needs to be `!Send`/`!Sync` should really have an explicit +// opt-out itself, e.g. via an `PhantomData<*mut T>` or (one day) via `impl !Send`/`impl !Sync`. + +impl UnsafePinned { + /// Constructs a new instance of `UnsafePinned` which will wrap the specified value. + /// + /// All access to the inner value through `&UnsafePinned` or `&mut UnsafePinned` or + /// `Pin<&mut UnsafePinned>` requires `unsafe` code. + #[inline(always)] + #[must_use] + #[unstable(feature = "unsafe_pinned", issue = "125735")] + pub const fn new(value: T) -> Self { + UnsafePinned { value } + } + + /// Unwraps the value, consuming this `UnsafePinned`. + #[inline(always)] + #[must_use] + #[unstable(feature = "unsafe_pinned", issue = "125735")] + #[rustc_allow_const_fn_unstable(const_precise_live_drops)] + pub const fn into_inner(self) -> T { + self.value + } +} + +impl UnsafePinned { + /// Get read-write access to the contents of a pinned `UnsafePinned`. + #[inline(always)] + #[must_use] + #[unstable(feature = "unsafe_pinned", issue = "125735")] + pub const fn get_mut_pinned(self: Pin<&mut Self>) -> *mut T { + // SAFETY: we're not using `get_unchecked_mut` to unpin anything + unsafe { self.get_unchecked_mut() }.get_mut_unchecked() + } + + /// Get read-write access to the contents of an `UnsafePinned`. + /// + /// You should usually be using `get_mut_pinned` instead to explicitly track the fact that this + /// memory is "pinned" due to there being aliases. + #[inline(always)] + #[must_use] + #[unstable(feature = "unsafe_pinned", issue = "125735")] + pub const fn get_mut_unchecked(&mut self) -> *mut T { + ptr::from_mut(self) as *mut T + } + + /// Get read-only access to the contents of a shared `UnsafePinned`. + /// + /// Note that `&UnsafePinned` is read-only if `&T` is read-only. This means that if there is + /// mutation of the `T`, future reads from the `*const T` returned here are UB! Use + /// [`UnsafeCell`] if you also need interior mutability. + /// + /// [`UnsafeCell`]: crate::cell::UnsafeCell + /// + /// ```rust,no_run + /// #![feature(unsafe_pinned)] + /// use std::pin::UnsafePinned; + /// + /// unsafe { + /// let mut x = UnsafePinned::new(0); + /// let ptr = x.get(); // read-only pointer, assumes immutability + /// x.get_mut_unchecked().write(1); + /// ptr.read(); // UB! + /// } + /// ``` + #[inline(always)] + #[must_use] + #[unstable(feature = "unsafe_pinned", issue = "125735")] + pub const fn get(&self) -> *const T { + ptr::from_ref(self) as *const T + } + + /// Gets an immutable pointer to the wrapped value. + /// + /// The difference from [`get`] is that this function accepts a raw pointer, which is useful to + /// avoid the creation of temporary references. + /// + /// [`get`]: UnsafePinned::get + #[inline(always)] + #[must_use] + #[unstable(feature = "unsafe_pinned", issue = "125735")] + pub const fn raw_get(this: *const Self) -> *const T { + this as *const T + } + + /// Gets a mutable pointer to the wrapped value. + /// + /// The difference from [`get_mut_pinned`] and [`get_mut_unchecked`] is that this function + /// accepts a raw pointer, which is useful to avoid the creation of temporary references. + /// + /// [`get_mut_pinned`]: UnsafePinned::get_mut_pinned + /// [`get_mut_unchecked`]: UnsafePinned::get_mut_unchecked + #[inline(always)] + #[must_use] + #[unstable(feature = "unsafe_pinned", issue = "125735")] + pub const fn raw_get_mut(this: *mut Self) -> *mut T { + this as *mut T + } +} + +#[unstable(feature = "unsafe_pinned", issue = "125735")] +impl Default for UnsafePinned { + /// Creates an `UnsafePinned`, with the `Default` value for T. + fn default() -> Self { + UnsafePinned::new(T::default()) + } +} + +#[unstable(feature = "unsafe_pinned", issue = "125735")] +impl From for UnsafePinned { + /// Creates a new `UnsafePinned` containing the given value. + fn from(value: T) -> Self { + UnsafePinned::new(value) + } +} + +#[unstable(feature = "unsafe_pinned", issue = "125735")] +impl fmt::Debug for UnsafePinned { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("UnsafePinned").finish_non_exhaustive() + } +} + +#[unstable(feature = "coerce_unsized", issue = "18598")] +// #[unstable(feature = "unsafe_pinned", issue = "125735")] +impl, U> CoerceUnsized> for UnsafePinned {} + +// Allow types that wrap `UnsafePinned` to also implement `DispatchFromDyn` +// and become dyn-compatible method receivers. +// Note that currently `UnsafePinned` itself cannot be a method receiver +// because it does not implement Deref. +// In other words: +// `self: UnsafePinned<&Self>` won't work +// `self: UnsafePinned` becomes possible +// FIXME(unsafe_pinned) this logic is copied from UnsafeCell, is it still sound? +#[unstable(feature = "dispatch_from_dyn", issue = "none")] +// #[unstable(feature = "unsafe_pinned", issue = "125735")] +impl, U> DispatchFromDyn> for UnsafePinned {} + +#[unstable(feature = "pointer_like_trait", issue = "none")] +// #[unstable(feature = "unsafe_pinned", issue = "125735")] +impl PointerLike for UnsafePinned {} + +// FIXME(unsafe_pinned): impl PinCoerceUnsized for UnsafePinned? diff --git a/tests/ui/rfcs/rfc-3467-unsafe-pinned/unsafe-pinned-hides-niche.rs b/tests/ui/rfcs/rfc-3467-unsafe-pinned/unsafe-pinned-hides-niche.rs new file mode 100644 index 000000000000..a1ff9a1f69fd --- /dev/null +++ b/tests/ui/rfcs/rfc-3467-unsafe-pinned/unsafe-pinned-hides-niche.rs @@ -0,0 +1,29 @@ +//@ check-pass +// this test ensures that UnsafePinned hides the niche of its inner type, just like UnsafeCell does + +#![crate_type = "lib"] +#![feature(unsafe_pinned)] + +use std::num::NonZero; +use std::pin::UnsafePinned; + +macro_rules! assert_size_is { + ($ty:ty = $size:expr) => { + const _: () = assert!(size_of::<$ty>() == $size); + }; +} + +assert_size_is!(UnsafePinned<()> = 0); +assert_size_is!(UnsafePinned = 1); + +assert_size_is!( UnsafePinned< u32> = 4); +assert_size_is!( UnsafePinned< NonZero> = 4); +assert_size_is!( UnsafePinned>> = 4); +assert_size_is!(Option> = 8); +assert_size_is!(Option>> = 8); +assert_size_is!(Option>>> = 8); + +assert_size_is!( UnsafePinned< &()> = size_of::()); +assert_size_is!( UnsafePinned> = size_of::()); +assert_size_is!(Option> = size_of::() * 2); +assert_size_is!(Option>> = size_of::() * 2); From 16334cdfd4640dbae4c3f5699d4f81ae358c715f Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Sun, 13 Apr 2025 17:33:55 +0800 Subject: [PATCH 404/606] tests: convert `tests/ui/lint/dead-code/self-assign.rs` to known-bug --- tests/ui/lint/dead-code/self-assign.rs | 30 ++++++++++----- tests/ui/lint/dead-code/self-assign.stderr | 44 ---------------------- 2 files changed, 20 insertions(+), 54 deletions(-) delete mode 100644 tests/ui/lint/dead-code/self-assign.stderr diff --git a/tests/ui/lint/dead-code/self-assign.rs b/tests/ui/lint/dead-code/self-assign.rs index 072a899e1bdb..357846baf221 100644 --- a/tests/ui/lint/dead-code/self-assign.rs +++ b/tests/ui/lint/dead-code/self-assign.rs @@ -1,19 +1,29 @@ -// Test that dead code warnings are issued for superfluous assignments of -// fields or variables to themselves (issue #75356). - -//@ ignore-test FIXME(81658, 83171) +//! Test that dead code warnings are issued for superfluous assignments of fields or variables to +//! themselves (issue #75356). +//! +//! # History of this test (to aid relanding of a fixed version of #81473) +//! +//! - Original lint request was about self-assignments not triggering sth like `dead_code`. +//! - `dead_code` lint expansion for self-assignments was implemented in #87129. +//! - Unfortunately implementation components of #87129 had to be disabled as part of reverts +//! #86212, #83171 (to revert #81473) to address regressions #81626 and #81658. +//! - Consequently, none of the following warnings are emitted. //@ check-pass + +// Implementation of self-assignment `dead_code` lint expansions disabled due to reverts. +//@ known-bug: #75356 + #![allow(unused_assignments)] #![warn(dead_code)] fn main() { let mut x = 0; x = x; - //~^ WARNING: useless assignment of variable of type `i32` to itself + // FIXME ~^ WARNING: useless assignment of variable of type `i32` to itself x = (x); - //~^ WARNING: useless assignment of variable of type `i32` to itself + // FIXME ~^ WARNING: useless assignment of variable of type `i32` to itself x = {x}; // block expressions don't count as self-assignments @@ -22,10 +32,10 @@ fn main() { struct S<'a> { f: &'a str } let mut s = S { f: "abc" }; s = s; - //~^ WARNING: useless assignment of variable of type `S` to itself + // FIXME ~^ WARNING: useless assignment of variable of type `S` to itself s.f = s.f; - //~^ WARNING: useless assignment of field of type `&str` to itself + // FIXME ~^ WARNING: useless assignment of field of type `&str` to itself struct N0 { x: Box } @@ -34,11 +44,11 @@ fn main() { struct N3 { n: N2 }; let mut n3 = N3 { n: N2(N1 { n: N0 { x: Box::new(42) } }) }; n3.n.0.n.x = n3.n.0.n.x; - //~^ WARNING: useless assignment of field of type `Box` to itself + // FIXME ~^ WARNING: useless assignment of field of type `Box` to itself let mut t = (1, ((2, 3, (4, 5)),)); t.1.0.2.1 = t.1.0.2.1; - //~^ WARNING: useless assignment of field of type `i32` to itself + // FIXME ~^ WARNING: useless assignment of field of type `i32` to itself let mut y = 0; diff --git a/tests/ui/lint/dead-code/self-assign.stderr b/tests/ui/lint/dead-code/self-assign.stderr deleted file mode 100644 index bb79c0ec72a3..000000000000 --- a/tests/ui/lint/dead-code/self-assign.stderr +++ /dev/null @@ -1,44 +0,0 @@ -warning: useless assignment of variable of type `i32` to itself - --> $DIR/self-assign.rs:10:5 - | -LL | x = x; - | ^^^^^ - | -note: the lint level is defined here - --> $DIR/self-assign.rs:6:9 - | -LL | #![warn(dead_code)] - | ^^^^^^^^^ - -warning: useless assignment of variable of type `i32` to itself - --> $DIR/self-assign.rs:13:5 - | -LL | x = (x); - | ^^^^^^^ - -warning: useless assignment of variable of type `S` to itself - --> $DIR/self-assign.rs:22:5 - | -LL | s = s; - | ^^^^^ - -warning: useless assignment of field of type `&str` to itself - --> $DIR/self-assign.rs:25:5 - | -LL | s.f = s.f; - | ^^^^^^^^^ - -warning: useless assignment of field of type `Box` to itself - --> $DIR/self-assign.rs:34:5 - | -LL | n3.n.0.n.x = n3.n.0.n.x; - | ^^^^^^^^^^^^^^^^^^^^^^^ - -warning: useless assignment of field of type `i32` to itself - --> $DIR/self-assign.rs:38:5 - | -LL | t.1.0.2.1 = t.1.0.2.1; - | ^^^^^^^^^^^^^^^^^^^^^ - -warning: 6 warnings emitted - From 6b2262ecde4bc03d5e3fdca27dbb5493c135e2df Mon Sep 17 00:00:00 2001 From: zjp Date: Sun, 13 Apr 2025 18:07:43 +0800 Subject: [PATCH 405/606] add missing `extern crate rustc_middle` in rustc_smir::run! docstring --- compiler/rustc_smir/src/rustc_internal/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index a546a44c8700..a616a37305b8 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -244,6 +244,7 @@ where /// ```ignore(needs-extern-crate) /// # extern crate rustc_driver; /// # extern crate rustc_interface; +/// # extern crate rustc_middle; /// # #[macro_use] /// # extern crate rustc_smir; /// # extern crate stable_mir; @@ -264,6 +265,7 @@ where /// ```ignore(needs-extern-crate) /// # extern crate rustc_driver; /// # extern crate rustc_interface; +/// # extern crate rustc_middle; /// # #[macro_use] /// # extern crate rustc_smir; /// # extern crate stable_mir; From 6d5f6fd2937a3bce2ed7f75e9210393d98f66125 Mon Sep 17 00:00:00 2001 From: zjp Date: Sun, 13 Apr 2025 18:09:10 +0800 Subject: [PATCH 406/606] import rustc_smir::rustc_internal in run_driver! --- compiler/rustc_smir/src/rustc_internal/mod.rs | 1 + tests/ui-fulldeps/stable-mir/check_abi.rs | 1 - tests/ui-fulldeps/stable-mir/check_allocation.rs | 1 - tests/ui-fulldeps/stable-mir/check_assoc_items.rs | 1 - tests/ui-fulldeps/stable-mir/check_attribute.rs | 1 - tests/ui-fulldeps/stable-mir/check_binop.rs | 1 - tests/ui-fulldeps/stable-mir/check_crate_defs.rs | 1 - tests/ui-fulldeps/stable-mir/check_def_ty.rs | 1 - tests/ui-fulldeps/stable-mir/check_defs.rs | 1 - tests/ui-fulldeps/stable-mir/check_foreign.rs | 1 - tests/ui-fulldeps/stable-mir/check_instance.rs | 1 - tests/ui-fulldeps/stable-mir/check_intrinsics.rs | 1 - tests/ui-fulldeps/stable-mir/check_item_kind.rs | 1 - tests/ui-fulldeps/stable-mir/check_normalization.rs | 1 - tests/ui-fulldeps/stable-mir/check_trait_queries.rs | 1 - tests/ui-fulldeps/stable-mir/check_transform.rs | 1 - tests/ui-fulldeps/stable-mir/check_ty_fold.rs | 1 - tests/ui-fulldeps/stable-mir/compilation-result.rs | 1 - tests/ui-fulldeps/stable-mir/crate-info.rs | 1 - tests/ui-fulldeps/stable-mir/projections.rs | 1 - tests/ui-fulldeps/stable-mir/smir_serde.rs | 1 - tests/ui-fulldeps/stable-mir/smir_visitor.rs | 1 - 22 files changed, 1 insertion(+), 21 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index a616a37305b8..146ba17d14fc 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -330,6 +330,7 @@ macro_rules! run_driver { use rustc_driver::{Callbacks, Compilation, run_compiler}; use rustc_middle::ty::TyCtxt; use rustc_interface::interface; + use rustc_smir::rustc_internal; use stable_mir::CompilerError; use std::ops::ControlFlow; diff --git a/tests/ui-fulldeps/stable-mir/check_abi.rs b/tests/ui-fulldeps/stable-mir/check_abi.rs index ef2d5b4854be..ebf2e333f085 100644 --- a/tests/ui-fulldeps/stable-mir/check_abi.rs +++ b/tests/ui-fulldeps/stable-mir/check_abi.rs @@ -17,7 +17,6 @@ extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; -use rustc_smir::rustc_internal; use stable_mir::abi::{ ArgAbi, CallConvention, FieldsShape, IntegerLength, PassMode, Primitive, Scalar, ValueAbi, VariantsShape, diff --git a/tests/ui-fulldeps/stable-mir/check_allocation.rs b/tests/ui-fulldeps/stable-mir/check_allocation.rs index c102f86a2286..ae2609bbc122 100644 --- a/tests/ui-fulldeps/stable-mir/check_allocation.rs +++ b/tests/ui-fulldeps/stable-mir/check_allocation.rs @@ -19,7 +19,6 @@ extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; -use rustc_smir::rustc_internal; use stable_mir::crate_def::CrateDef; use stable_mir::mir::alloc::GlobalAlloc; use stable_mir::mir::mono::{Instance, InstanceKind, StaticDef}; diff --git a/tests/ui-fulldeps/stable-mir/check_assoc_items.rs b/tests/ui-fulldeps/stable-mir/check_assoc_items.rs index f75113676750..9d611543b5aa 100644 --- a/tests/ui-fulldeps/stable-mir/check_assoc_items.rs +++ b/tests/ui-fulldeps/stable-mir/check_assoc_items.rs @@ -17,7 +17,6 @@ extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; -use rustc_smir::rustc_internal; use std::io::Write; use std::collections::HashSet; use stable_mir::CrateDef; diff --git a/tests/ui-fulldeps/stable-mir/check_attribute.rs b/tests/ui-fulldeps/stable-mir/check_attribute.rs index de5ba15f6ea4..4148fc0cb6a0 100644 --- a/tests/ui-fulldeps/stable-mir/check_attribute.rs +++ b/tests/ui-fulldeps/stable-mir/check_attribute.rs @@ -15,7 +15,6 @@ extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; -use rustc_smir::rustc_internal; use stable_mir::{CrateDef, CrateItems}; use std::io::Write; use std::ops::ControlFlow; diff --git a/tests/ui-fulldeps/stable-mir/check_binop.rs b/tests/ui-fulldeps/stable-mir/check_binop.rs index 65b3ffd27ab0..6a141e9c5775 100644 --- a/tests/ui-fulldeps/stable-mir/check_binop.rs +++ b/tests/ui-fulldeps/stable-mir/check_binop.rs @@ -15,7 +15,6 @@ extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; -use rustc_smir::rustc_internal; use stable_mir::mir::mono::Instance; use stable_mir::mir::visit::{Location, MirVisitor}; use stable_mir::mir::{LocalDecl, Rvalue, Statement, StatementKind, Terminator, TerminatorKind}; diff --git a/tests/ui-fulldeps/stable-mir/check_crate_defs.rs b/tests/ui-fulldeps/stable-mir/check_crate_defs.rs index 71cca94c34f6..31c47192d090 100644 --- a/tests/ui-fulldeps/stable-mir/check_crate_defs.rs +++ b/tests/ui-fulldeps/stable-mir/check_crate_defs.rs @@ -16,7 +16,6 @@ extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; -use rustc_smir::rustc_internal; use stable_mir::CrateDef; use std::collections::HashSet; use std::io::Write; diff --git a/tests/ui-fulldeps/stable-mir/check_def_ty.rs b/tests/ui-fulldeps/stable-mir/check_def_ty.rs index 37b9a83e33e7..00a34f138673 100644 --- a/tests/ui-fulldeps/stable-mir/check_def_ty.rs +++ b/tests/ui-fulldeps/stable-mir/check_def_ty.rs @@ -17,7 +17,6 @@ extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; -use rustc_smir::rustc_internal; use stable_mir::ty::{Ty, ForeignItemKind}; use stable_mir::*; use std::io::Write; diff --git a/tests/ui-fulldeps/stable-mir/check_defs.rs b/tests/ui-fulldeps/stable-mir/check_defs.rs index cd3d76d87601..1ba73377d6e9 100644 --- a/tests/ui-fulldeps/stable-mir/check_defs.rs +++ b/tests/ui-fulldeps/stable-mir/check_defs.rs @@ -19,7 +19,6 @@ extern crate stable_mir; use std::assert_matches::assert_matches; use mir::{mono::Instance, TerminatorKind::*}; use stable_mir::mir::mono::InstanceKind; -use rustc_smir::rustc_internal; use stable_mir::ty::{RigidTy, TyKind, Ty, UintTy}; use stable_mir::*; use std::io::Write; diff --git a/tests/ui-fulldeps/stable-mir/check_foreign.rs b/tests/ui-fulldeps/stable-mir/check_foreign.rs index bc3956b30908..4419050ceb2c 100644 --- a/tests/ui-fulldeps/stable-mir/check_foreign.rs +++ b/tests/ui-fulldeps/stable-mir/check_foreign.rs @@ -17,7 +17,6 @@ extern crate rustc_interface; extern crate rustc_span; extern crate stable_mir; -use rustc_smir::rustc_internal; use stable_mir::{ ty::{Abi, ForeignItemKind}, *, diff --git a/tests/ui-fulldeps/stable-mir/check_instance.rs b/tests/ui-fulldeps/stable-mir/check_instance.rs index 72a138f907e7..1510a622cdfd 100644 --- a/tests/ui-fulldeps/stable-mir/check_instance.rs +++ b/tests/ui-fulldeps/stable-mir/check_instance.rs @@ -21,7 +21,6 @@ use std::ops::ControlFlow; use mir::mono::Instance; use mir::TerminatorKind::*; -use rustc_smir::rustc_internal; use stable_mir::ty::{RigidTy, TyKind}; use stable_mir::*; diff --git a/tests/ui-fulldeps/stable-mir/check_intrinsics.rs b/tests/ui-fulldeps/stable-mir/check_intrinsics.rs index 07a2a62e0668..3f04abbb9d76 100644 --- a/tests/ui-fulldeps/stable-mir/check_intrinsics.rs +++ b/tests/ui-fulldeps/stable-mir/check_intrinsics.rs @@ -20,7 +20,6 @@ extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; -use rustc_smir::rustc_internal; use stable_mir::mir::mono::{Instance, InstanceKind}; use stable_mir::mir::visit::{Location, MirVisitor}; use stable_mir::mir::{LocalDecl, Terminator, TerminatorKind}; diff --git a/tests/ui-fulldeps/stable-mir/check_item_kind.rs b/tests/ui-fulldeps/stable-mir/check_item_kind.rs index 647ce534589e..bb8c00c64c95 100644 --- a/tests/ui-fulldeps/stable-mir/check_item_kind.rs +++ b/tests/ui-fulldeps/stable-mir/check_item_kind.rs @@ -16,7 +16,6 @@ extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; -use rustc_smir::rustc_internal; use stable_mir::*; use std::io::Write; use std::ops::ControlFlow; diff --git a/tests/ui-fulldeps/stable-mir/check_normalization.rs b/tests/ui-fulldeps/stable-mir/check_normalization.rs index de14202adb9c..797cb4cd5d05 100644 --- a/tests/ui-fulldeps/stable-mir/check_normalization.rs +++ b/tests/ui-fulldeps/stable-mir/check_normalization.rs @@ -17,7 +17,6 @@ extern crate stable_mir; use mir::mono::Instance; use ty::{Ty, TyKind, RigidTy}; -use rustc_smir::rustc_internal; use stable_mir::*; use std::io::Write; use std::ops::ControlFlow; diff --git a/tests/ui-fulldeps/stable-mir/check_trait_queries.rs b/tests/ui-fulldeps/stable-mir/check_trait_queries.rs index 23c2844d3f16..d9170d0c4081 100644 --- a/tests/ui-fulldeps/stable-mir/check_trait_queries.rs +++ b/tests/ui-fulldeps/stable-mir/check_trait_queries.rs @@ -16,7 +16,6 @@ extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; -use rustc_smir::rustc_internal; use stable_mir::CrateDef; use std::collections::HashSet; use std::io::Write; diff --git a/tests/ui-fulldeps/stable-mir/check_transform.rs b/tests/ui-fulldeps/stable-mir/check_transform.rs index d9fc924933fa..604cc72c3418 100644 --- a/tests/ui-fulldeps/stable-mir/check_transform.rs +++ b/tests/ui-fulldeps/stable-mir/check_transform.rs @@ -17,7 +17,6 @@ extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; -use rustc_smir::rustc_internal; use stable_mir::mir::alloc::GlobalAlloc; use stable_mir::mir::mono::Instance; use stable_mir::mir::{Body, ConstOperand, Operand, Rvalue, StatementKind, TerminatorKind}; diff --git a/tests/ui-fulldeps/stable-mir/check_ty_fold.rs b/tests/ui-fulldeps/stable-mir/check_ty_fold.rs index 9d71697178e5..23233f8406cf 100644 --- a/tests/ui-fulldeps/stable-mir/check_ty_fold.rs +++ b/tests/ui-fulldeps/stable-mir/check_ty_fold.rs @@ -17,7 +17,6 @@ extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; -use rustc_smir::rustc_internal; use stable_mir::mir::{ Body, FieldIdx, MirVisitor, Place, ProjectionElem, visit::{Location, PlaceContext}, diff --git a/tests/ui-fulldeps/stable-mir/compilation-result.rs b/tests/ui-fulldeps/stable-mir/compilation-result.rs index b8a9e720e546..39416636fd67 100644 --- a/tests/ui-fulldeps/stable-mir/compilation-result.rs +++ b/tests/ui-fulldeps/stable-mir/compilation-result.rs @@ -16,7 +16,6 @@ extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; -use rustc_smir::rustc_internal; use std::io::Write; /// This test will generate and analyze a dummy crate using the stable mir. diff --git a/tests/ui-fulldeps/stable-mir/crate-info.rs b/tests/ui-fulldeps/stable-mir/crate-info.rs index 4d2d7e26276b..e2086d5e5790 100644 --- a/tests/ui-fulldeps/stable-mir/crate-info.rs +++ b/tests/ui-fulldeps/stable-mir/crate-info.rs @@ -18,7 +18,6 @@ extern crate rustc_interface; extern crate stable_mir; use rustc_hir::def::DefKind; -use rustc_smir::rustc_internal; use stable_mir::ItemKind; use stable_mir::crate_def::CrateDef; use stable_mir::mir::mono::Instance; diff --git a/tests/ui-fulldeps/stable-mir/projections.rs b/tests/ui-fulldeps/stable-mir/projections.rs index 6f82eba61fce..f3bd894ac690 100644 --- a/tests/ui-fulldeps/stable-mir/projections.rs +++ b/tests/ui-fulldeps/stable-mir/projections.rs @@ -17,7 +17,6 @@ extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; -use rustc_smir::rustc_internal; use stable_mir::ItemKind; use stable_mir::crate_def::CrateDef; use stable_mir::mir::{ProjectionElem, Rvalue, StatementKind}; diff --git a/tests/ui-fulldeps/stable-mir/smir_serde.rs b/tests/ui-fulldeps/stable-mir/smir_serde.rs index 9b3638a9f2f4..3b3d743ad326 100644 --- a/tests/ui-fulldeps/stable-mir/smir_serde.rs +++ b/tests/ui-fulldeps/stable-mir/smir_serde.rs @@ -19,7 +19,6 @@ extern crate serde_json; extern crate stable_mir; use rustc_middle::ty::TyCtxt; -use rustc_smir::rustc_internal; use serde_json::to_string; use stable_mir::mir::Body; use std::io::{BufWriter, Write}; diff --git a/tests/ui-fulldeps/stable-mir/smir_visitor.rs b/tests/ui-fulldeps/stable-mir/smir_visitor.rs index 0a579a07cef1..d225d9773fe5 100644 --- a/tests/ui-fulldeps/stable-mir/smir_visitor.rs +++ b/tests/ui-fulldeps/stable-mir/smir_visitor.rs @@ -16,7 +16,6 @@ extern crate rustc_driver; extern crate rustc_interface; extern crate stable_mir; -use rustc_smir::rustc_internal; use stable_mir::mir::MirVisitor; use stable_mir::mir::MutMirVisitor; use stable_mir::*; From b203d403676472d0e214092bd076909089550055 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Sat, 12 Apr 2025 07:55:20 +0800 Subject: [PATCH 407/606] compiletest: add `camino` for UTF-8 path handling --- Cargo.lock | 1 + src/tools/compiletest/Cargo.toml | 1 + 2 files changed, 2 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 8e35435e3f9b..c80bfef485c2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -719,6 +719,7 @@ version = "0.0.0" dependencies = [ "anstyle-svg", "build_helper", + "camino", "colored", "diff", "getopts", diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml index 3db34ed24cc2..ba1b8f256586 100644 --- a/src/tools/compiletest/Cargo.toml +++ b/src/tools/compiletest/Cargo.toml @@ -10,6 +10,7 @@ doctest = false # tidy-alphabetical-start anstyle-svg = "0.1.3" build_helper = { path = "../../build_helper" } +camino = "1" colored = "2" diff = "0.1.10" getopts = "0.2" From e24b0c8e0a9d0b898ede993b62c32d9ebaff27bd Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Sat, 12 Apr 2025 07:55:57 +0800 Subject: [PATCH 408/606] compiletest: consistently use `{Utf8Path,Utf8PathBuf}` Since compiletest already assumes UTF-8 paths and does not try to be robust against non-UTF-8 paths. --- src/tools/compiletest/src/common.rs | 71 ++++--- src/tools/compiletest/src/compute_diff.rs | 17 +- src/tools/compiletest/src/debuggers.rs | 27 ++- src/tools/compiletest/src/errors.rs | 6 +- src/tools/compiletest/src/header.rs | 105 +++++----- src/tools/compiletest/src/header/tests.rs | 26 +-- src/tools/compiletest/src/lib.rs | 149 +++++++------- src/tools/compiletest/src/runtest.rs | 188 ++++++++---------- src/tools/compiletest/src/runtest/assembly.rs | 4 +- .../compiletest/src/runtest/codegen_units.rs | 4 +- src/tools/compiletest/src/runtest/coverage.rs | 21 +- src/tools/compiletest/src/runtest/debugger.rs | 19 +- .../compiletest/src/runtest/debuginfo.rs | 51 ++--- src/tools/compiletest/src/runtest/js_doc.rs | 3 +- src/tools/compiletest/src/runtest/mir_opt.rs | 43 ++-- src/tools/compiletest/src/runtest/run_make.rs | 32 +-- src/tools/compiletest/src/runtest/ui.rs | 10 +- src/tools/compiletest/src/tests.rs | 12 +- src/tools/compiletest/src/util.rs | 38 ++-- src/tools/compiletest/src/util/tests.rs | 10 +- 20 files changed, 403 insertions(+), 433 deletions(-) diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 6750b5288f42..604c5fcbddff 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -1,18 +1,17 @@ use std::collections::{BTreeSet, HashMap, HashSet}; -use std::ffi::OsString; -use std::path::{Path, PathBuf}; use std::process::Command; use std::str::FromStr; use std::sync::OnceLock; use std::{fmt, iter}; use build_helper::git::GitConfig; +use camino::{Utf8Path, Utf8PathBuf}; use semver::Version; use serde::de::{Deserialize, Deserializer, Error as _}; pub use self::Mode::*; use crate::executor::{ColorConfig, OutputFormat}; -use crate::util::{PathBufExt, add_dylib_path}; +use crate::util::{Utf8PathBufExt, add_dylib_path}; macro_rules! string_enum { ($(#[$meta:meta])* $vis:vis enum $name:ident { $($variant:ident => $repr:expr,)* }) => { @@ -183,25 +182,25 @@ pub struct Config { pub fail_fast: bool, /// The library paths required for running the compiler. - pub compile_lib_path: PathBuf, + pub compile_lib_path: Utf8PathBuf, /// The library paths required for running compiled programs. - pub run_lib_path: PathBuf, + pub run_lib_path: Utf8PathBuf, /// The rustc executable. - pub rustc_path: PathBuf, + pub rustc_path: Utf8PathBuf, /// The cargo executable. - pub cargo_path: Option, + pub cargo_path: Option, /// Rustc executable used to compile run-make recipes. - pub stage0_rustc_path: Option, + pub stage0_rustc_path: Option, /// The rustdoc executable. - pub rustdoc_path: Option, + pub rustdoc_path: Option, /// The coverage-dump executable. - pub coverage_dump_path: Option, + pub coverage_dump_path: Option, /// The Python executable to use for LLDB and htmldocck. pub python: String, @@ -213,27 +212,27 @@ pub struct Config { pub jsondoclint_path: Option, /// The LLVM `FileCheck` binary path. - pub llvm_filecheck: Option, + pub llvm_filecheck: Option, /// Path to LLVM's bin directory. - pub llvm_bin_dir: Option, + pub llvm_bin_dir: Option, /// The path to the Clang executable to run Clang-based tests with. If /// `None` then these tests will be ignored. pub run_clang_based_tests_with: Option, /// The directory containing the sources. - pub src_root: PathBuf, + pub src_root: Utf8PathBuf, /// The directory containing the test suite sources. Must be a subdirectory of `src_root`. - pub src_test_suite_root: PathBuf, + pub src_test_suite_root: Utf8PathBuf, /// Root build directory (e.g. `build/`). - pub build_root: PathBuf, + pub build_root: Utf8PathBuf, /// Test suite specific build directory (e.g. `build/host/test/ui/`). - pub build_test_suite_root: PathBuf, + pub build_test_suite_root: Utf8PathBuf, /// The directory containing the compiler sysroot - pub sysroot_base: PathBuf, + pub sysroot_base: Utf8PathBuf, /// The number of the stage under test. pub stage: u32, @@ -301,7 +300,7 @@ pub struct Config { pub host: String, /// Path to / name of the Microsoft Console Debugger (CDB) executable - pub cdb: Option, + pub cdb: Option, /// Version of CDB pub cdb_version: Option<[u16; 4]>, @@ -322,7 +321,7 @@ pub struct Config { pub system_llvm: bool, /// Path to the android tools - pub android_cross_path: PathBuf, + pub android_cross_path: Utf8PathBuf, /// Extra parameter to run adb on arm-linux-androideabi pub adb_path: String, @@ -346,7 +345,7 @@ pub struct Config { pub color: ColorConfig, /// where to find the remote test client process, if we're using it - pub remote_test_client: Option, + pub remote_test_client: Option, /// mode describing what file the actual ui output will be compared to pub compare_mode: Option, @@ -414,7 +413,7 @@ pub struct Config { /// Path to minicore aux library, used for `no_core` tests that need `core` stubs in /// cross-compilation scenarios that do not otherwise want/need to `-Zbuild-std`. Used in e.g. /// ABI tests. - pub minicore_path: PathBuf, + pub minicore_path: Utf8PathBuf, } impl Config { @@ -804,8 +803,8 @@ fn serde_parse_u32<'de, D: Deserializer<'de>>(deserializer: D) -> Result, compare_mode: &Option, kind: &str, -) -> PathBuf { +) -> Utf8PathBuf { assert!(UI_EXTENSIONS.contains(&kind)); let mut parts = Vec::new(); @@ -865,7 +864,7 @@ pub const UI_COVERAGE_MAP: &str = "cov-map"; /// ``` /// /// This is created early when tests are collected to avoid race conditions. -pub fn output_relative_path(config: &Config, relative_dir: &Path) -> PathBuf { +pub fn output_relative_path(config: &Config, relative_dir: &Utf8Path) -> Utf8PathBuf { config.build_test_suite_root.join(relative_dir) } @@ -874,10 +873,10 @@ pub fn output_testname_unique( config: &Config, testpaths: &TestPaths, revision: Option<&str>, -) -> PathBuf { +) -> Utf8PathBuf { let mode = config.compare_mode.as_ref().map_or("", |m| m.to_str()); let debugger = config.debugger.as_ref().map_or("", |m| m.to_str()); - PathBuf::from(&testpaths.file.file_stem().unwrap()) + Utf8PathBuf::from(&testpaths.file.file_stem().unwrap()) .with_extra_extension(config.mode.output_dir_disambiguator()) .with_extra_extension(revision.unwrap_or("")) .with_extra_extension(mode) @@ -887,7 +886,11 @@ pub fn output_testname_unique( /// Absolute path to the directory where all output for the given /// test/revision should reside. Example: /// /path/to/build/host-tuple/test/ui/relative/testname.revision.mode/ -pub fn output_base_dir(config: &Config, testpaths: &TestPaths, revision: Option<&str>) -> PathBuf { +pub fn output_base_dir( + config: &Config, + testpaths: &TestPaths, + revision: Option<&str>, +) -> Utf8PathBuf { output_relative_path(config, &testpaths.relative_dir) .join(output_testname_unique(config, testpaths, revision)) } @@ -895,12 +898,20 @@ pub fn output_base_dir(config: &Config, testpaths: &TestPaths, revision: Option< /// Absolute path to the base filename used as output for the given /// test/revision. Example: /// /path/to/build/host-tuple/test/ui/relative/testname.revision.mode/testname -pub fn output_base_name(config: &Config, testpaths: &TestPaths, revision: Option<&str>) -> PathBuf { +pub fn output_base_name( + config: &Config, + testpaths: &TestPaths, + revision: Option<&str>, +) -> Utf8PathBuf { output_base_dir(config, testpaths, revision).join(testpaths.file.file_stem().unwrap()) } /// Absolute path to the directory to use for incremental compilation. Example: /// /path/to/build/host-tuple/test/ui/relative/testname.mode/testname.inc -pub fn incremental_dir(config: &Config, testpaths: &TestPaths, revision: Option<&str>) -> PathBuf { +pub fn incremental_dir( + config: &Config, + testpaths: &TestPaths, + revision: Option<&str>, +) -> Utf8PathBuf { output_base_name(config, testpaths, revision).with_extension("inc") } diff --git a/src/tools/compiletest/src/compute_diff.rs b/src/tools/compiletest/src/compute_diff.rs index 4c942c51bae1..509e7e117039 100644 --- a/src/tools/compiletest/src/compute_diff.rs +++ b/src/tools/compiletest/src/compute_diff.rs @@ -1,6 +1,7 @@ use std::collections::VecDeque; use std::fs::{File, FileType}; -use std::path::Path; + +use camino::Utf8Path; #[derive(Debug, PartialEq)] pub enum DiffLine { @@ -112,8 +113,8 @@ pub(crate) fn write_diff(expected: &str, actual: &str, context_size: usize) -> S /// Returns whether any data was actually written. pub(crate) fn write_filtered_diff( diff_filename: &str, - out_dir: &Path, - compare_dir: &Path, + out_dir: &Utf8Path, + compare_dir: &Utf8Path, verbose: bool, filter: Filter, ) -> bool @@ -123,19 +124,21 @@ where use std::io::{Read, Write}; let mut diff_output = File::create(diff_filename).unwrap(); let mut wrote_data = false; - for entry in walkdir::WalkDir::new(out_dir) { + for entry in walkdir::WalkDir::new(out_dir.as_std_path()) { let entry = entry.expect("failed to read file"); let extension = entry.path().extension().and_then(|p| p.to_str()); if filter(entry.file_type(), extension) { - let expected_path = compare_dir.join(entry.path().strip_prefix(&out_dir).unwrap()); + let expected_path = compare_dir + .as_std_path() + .join(entry.path().strip_prefix(&out_dir.as_std_path()).unwrap()); let expected = if let Ok(s) = std::fs::read(&expected_path) { s } else { continue }; let actual_path = entry.path(); let actual = std::fs::read(&actual_path).unwrap(); let diff = unified_diff::diff( &expected, - &expected_path.to_string_lossy(), + &expected_path.to_str().unwrap(), &actual, - &actual_path.to_string_lossy(), + &actual_path.to_str().unwrap(), 3, ); wrote_data |= !diff.is_empty(); diff --git a/src/tools/compiletest/src/debuggers.rs b/src/tools/compiletest/src/debuggers.rs index 5126e55aea12..c133d7fd4fbd 100644 --- a/src/tools/compiletest/src/debuggers.rs +++ b/src/tools/compiletest/src/debuggers.rs @@ -1,9 +1,9 @@ use std::env; -use std::ffi::OsString; -use std::path::{Path, PathBuf}; use std::process::Command; use std::sync::Arc; +use camino::{Utf8Path, Utf8PathBuf}; + use crate::common::{Config, Debugger}; pub(crate) fn configure_cdb(config: &Config) -> Option> { @@ -78,12 +78,15 @@ fn is_pc_windows_msvc_target(target: &str) -> bool { target.ends_with("-pc-windows-msvc") } -fn find_cdb(target: &str) -> Option { +fn find_cdb(target: &str) -> Option { if !(cfg!(windows) && is_pc_windows_msvc_target(target)) { return None; } - let pf86 = env::var_os("ProgramFiles(x86)").or_else(|| env::var_os("ProgramFiles"))?; + let pf86 = Utf8PathBuf::from_path_buf( + env::var_os("ProgramFiles(x86)").or_else(|| env::var_os("ProgramFiles"))?.into(), + ) + .unwrap(); let cdb_arch = if cfg!(target_arch = "x86") { "x86" } else if cfg!(target_arch = "x86_64") { @@ -96,8 +99,7 @@ fn find_cdb(target: &str) -> Option { return None; // No compatible CDB.exe in the Windows 10 SDK }; - let mut path = PathBuf::new(); - path.push(pf86); + let mut path = pf86; path.push(r"Windows Kits\10\Debuggers"); // We could check 8.1 etc. too? path.push(cdb_arch); path.push(r"cdb.exe"); @@ -106,15 +108,15 @@ fn find_cdb(target: &str) -> Option { return None; } - Some(path.into_os_string()) + Some(path) } /// Returns Path to CDB pub(crate) fn analyze_cdb( cdb: Option, target: &str, -) -> (Option, Option<[u16; 4]>) { - let cdb = cdb.map(OsString::from).or_else(|| find_cdb(target)); +) -> (Option, Option<[u16; 4]>) { + let cdb = cdb.map(Utf8PathBuf::from).or_else(|| find_cdb(target)); let mut version = None; if let Some(cdb) = cdb.as_ref() { @@ -143,7 +145,7 @@ pub(crate) fn extract_cdb_version(full_version_line: &str) -> Option<[u16; 4]> { pub(crate) fn analyze_gdb( gdb: Option, target: &str, - android_cross_path: &Path, + android_cross_path: &Utf8Path, ) -> (Option, Option) { #[cfg(not(windows))] const GDB_FALLBACK: &str = "gdb"; @@ -152,10 +154,7 @@ pub(crate) fn analyze_gdb( let fallback_gdb = || { if is_android_gdb_target(target) { - let mut gdb_path = match android_cross_path.to_str() { - Some(x) => x.to_owned(), - None => panic!("cannot find android cross path"), - }; + let mut gdb_path = android_cross_path.to_string(); gdb_path.push_str("/bin/gdb"); gdb_path } else { diff --git a/src/tools/compiletest/src/errors.rs b/src/tools/compiletest/src/errors.rs index 64d68eb7f23e..3bb98276bf52 100644 --- a/src/tools/compiletest/src/errors.rs +++ b/src/tools/compiletest/src/errors.rs @@ -2,9 +2,9 @@ use std::fmt; use std::fs::File; use std::io::BufReader; use std::io::prelude::*; -use std::path::Path; use std::sync::OnceLock; +use camino::Utf8Path; use regex::Regex; use tracing::*; @@ -102,8 +102,8 @@ impl Error { /// /// If revision is not None, then we look /// for `//[X]~` instead, where `X` is the current revision. -pub fn load_errors(testfile: &Path, revision: Option<&str>) -> Vec { - let rdr = BufReader::new(File::open(testfile).unwrap()); +pub fn load_errors(testfile: &Utf8Path, revision: Option<&str>) -> Vec { + let rdr = BufReader::new(File::open(testfile.as_std_path()).unwrap()); // `last_nonfollow_error` tracks the most recently seen // line with an error template that did not use the diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 3406e8749a15..33ecdec49917 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -3,9 +3,9 @@ use std::env; use std::fs::File; use std::io::BufReader; use std::io::prelude::*; -use std::path::{Path, PathBuf}; use std::process::Command; +use camino::{Utf8Path, Utf8PathBuf}; use semver::Version; use tracing::*; @@ -45,12 +45,12 @@ pub struct EarlyProps { } impl EarlyProps { - pub fn from_file(config: &Config, testfile: &Path) -> Self { - let file = File::open(testfile).expect("open test file to parse earlyprops"); + pub fn from_file(config: &Config, testfile: &Utf8Path) -> Self { + let file = File::open(testfile.as_std_path()).expect("open test file to parse earlyprops"); Self::from_reader(config, testfile, file) } - pub fn from_reader(config: &Config, testfile: &Path, rdr: R) -> Self { + pub fn from_reader(config: &Config, testfile: &Utf8Path, rdr: R) -> Self { let mut props = EarlyProps::default(); let mut poisoned = false; iter_header( @@ -66,7 +66,7 @@ impl EarlyProps { ); if poisoned { - eprintln!("errors encountered during EarlyProps parsing: {}", testfile.display()); + eprintln!("errors encountered during EarlyProps parsing: {}", testfile); panic!("errors encountered during EarlyProps parsing"); } @@ -88,7 +88,7 @@ pub struct TestProps { pub doc_flags: Vec, // If present, the name of a file that this test should match when // pretty-printed - pub pp_exact: Option, + pub pp_exact: Option, /// Auxiliary crates that should be built and made available to this test. pub(crate) aux: AuxProps, // Environment settings to use for compiling @@ -134,7 +134,7 @@ pub struct TestProps { // not set by end-users; rather it is set by the incremental // testing harness and used when generating compilation // arguments. (In particular, it propagates to the aux-builds.) - pub incremental_dir: Option, + pub incremental_dir: Option, // If `true`, this test will use incremental compilation. // // This can be set manually with the `incremental` header, or implicitly @@ -311,7 +311,12 @@ impl TestProps { } } - pub fn from_aux_file(&self, testfile: &Path, revision: Option<&str>, config: &Config) -> Self { + pub fn from_aux_file( + &self, + testfile: &Utf8Path, + revision: Option<&str>, + config: &Config, + ) -> Self { let mut props = TestProps::new(); // copy over select properties to the aux build: @@ -322,10 +327,10 @@ impl TestProps { props } - pub fn from_file(testfile: &Path, revision: Option<&str>, config: &Config) -> Self { + pub fn from_file(testfile: &Utf8Path, revision: Option<&str>, config: &Config) -> Self { let mut props = TestProps::new(); props.load_from(testfile, revision, config); - props.exec_env.push(("RUSTC".to_string(), config.rustc_path.display().to_string())); + props.exec_env.push(("RUSTC".to_string(), config.rustc_path.to_string())); match (props.pass_mode, props.fail_mode) { (None, None) if config.mode == Mode::Ui => props.fail_mode = Some(FailMode::Check), @@ -340,10 +345,10 @@ impl TestProps { /// tied to a particular revision `foo` (indicated by writing /// `//@[foo]`), then the property is ignored unless `test_revision` is /// `Some("foo")`. - fn load_from(&mut self, testfile: &Path, test_revision: Option<&str>, config: &Config) { + fn load_from(&mut self, testfile: &Utf8Path, test_revision: Option<&str>, config: &Config) { let mut has_edition = false; if !testfile.is_dir() { - let file = File::open(testfile).unwrap(); + let file = File::open(testfile.as_std_path()).unwrap(); let mut poisoned = false; @@ -600,7 +605,7 @@ impl TestProps { ); if poisoned { - eprintln!("errors encountered during TestProps parsing: {}", testfile.display()); + eprintln!("errors encountered during TestProps parsing: {}", testfile); panic!("errors encountered during TestProps parsing"); } } @@ -871,7 +876,7 @@ fn iter_header( mode: Mode, _suite: &str, poisoned: &mut bool, - testfile: &Path, + testfile: &Utf8Path, rdr: impl Read, it: &mut dyn FnMut(DirectiveLine<'_>), ) { @@ -923,9 +928,7 @@ fn iter_header( eprintln!( "error: detected unknown compiletest test directive `{}` in {}:{}", - directive_line.raw_directive, - testfile.display(), - line_number, + directive_line.raw_directive, testfile, line_number, ); return; @@ -937,10 +940,7 @@ fn iter_header( eprintln!( "error: detected trailing compiletest test directive `{}` in {}:{}\n \ help: put the trailing directive in it's own line: `//@ {}`", - trailing_directive, - testfile.display(), - line_number, - trailing_directive, + trailing_directive, testfile, line_number, trailing_directive, ); return; @@ -952,7 +952,12 @@ fn iter_header( } impl Config { - fn parse_and_update_revisions(&self, testfile: &Path, line: &str, existing: &mut Vec) { + fn parse_and_update_revisions( + &self, + testfile: &Utf8Path, + line: &str, + existing: &mut Vec, + ) { const FORBIDDEN_REVISION_NAMES: [&str; 2] = [ // `//@ revisions: true false` Implying `--cfg=true` and `--cfg=false` makes it very // weird for the test, since if the test writer wants a cfg of the same revision name @@ -965,26 +970,19 @@ impl Config { if let Some(raw) = self.parse_name_value_directive(line, "revisions") { if self.mode == Mode::RunMake { - panic!("`run-make` tests do not support revisions: {}", testfile.display()); + panic!("`run-make` tests do not support revisions: {}", testfile); } let mut duplicates: HashSet<_> = existing.iter().cloned().collect(); for revision in raw.split_whitespace() { if !duplicates.insert(revision.to_string()) { - panic!( - "duplicate revision: `{}` in line `{}`: {}", - revision, - raw, - testfile.display() - ); + panic!("duplicate revision: `{}` in line `{}`: {}", revision, raw, testfile); } if FORBIDDEN_REVISION_NAMES.contains(&revision) { panic!( "revision name `{revision}` is not permitted: `{}` in line `{}`: {}", - revision, - raw, - testfile.display() + revision, raw, testfile ); } @@ -995,8 +993,7 @@ impl Config { "revision name `{revision}` is not permitted in a test suite that uses \ `FileCheck` annotations as it is confusing when used as custom `FileCheck` \ prefix: `{revision}` in line `{}`: {}", - raw, - testfile.display() + raw, testfile ); } @@ -1016,11 +1013,11 @@ impl Config { (name.to_owned(), value.to_owned()) } - fn parse_pp_exact(&self, line: &str, testfile: &Path) -> Option { + fn parse_pp_exact(&self, line: &str, testfile: &Utf8Path) -> Option { if let Some(s) = self.parse_name_value_directive(line, "pp-exact") { - Some(PathBuf::from(&s)) + Some(Utf8PathBuf::from(&s)) } else if self.parse_name_directive(line, "pp-exact") { - testfile.file_name().map(PathBuf::from) + testfile.file_name().map(Utf8PathBuf::from) } else { None } @@ -1126,20 +1123,19 @@ fn expand_variables(mut value: String, config: &Config) -> String { if value.contains(CWD) { let cwd = env::current_dir().unwrap(); - value = value.replace(CWD, &cwd.to_string_lossy()); + value = value.replace(CWD, &cwd.to_str().unwrap()); } if value.contains(SRC_BASE) { - value = value.replace(SRC_BASE, &config.src_test_suite_root.to_str().unwrap()); + value = value.replace(SRC_BASE, &config.src_test_suite_root.as_str()); } if value.contains(TEST_SUITE_BUILD_BASE) { - value = - value.replace(TEST_SUITE_BUILD_BASE, &config.build_test_suite_root.to_str().unwrap()); + value = value.replace(TEST_SUITE_BUILD_BASE, &config.build_test_suite_root.as_str()); } if value.contains(SYSROOT_BASE) { - value = value.replace(SYSROOT_BASE, &config.sysroot_base.to_str().unwrap()); + value = value.replace(SYSROOT_BASE, &config.sysroot_base.as_str()); } if value.contains(TARGET_LINKER) { @@ -1152,9 +1148,9 @@ fn expand_variables(mut value: String, config: &Config) -> String { if value.contains(RUST_SRC_BASE) { let src_base = config.sysroot_base.join("lib/rustlib/src/rust"); - src_base.try_exists().expect(&*format!("{} should exists", src_base.display())); - let src_base = src_base.read_link().unwrap_or(src_base); - value = value.replace(RUST_SRC_BASE, &src_base.to_string_lossy()); + src_base.try_exists().expect(&*format!("{} should exists", src_base)); + let src_base = src_base.read_link_utf8().unwrap_or(src_base); + value = value.replace(RUST_SRC_BASE, &src_base.as_str()); } value @@ -1257,14 +1253,14 @@ pub fn llvm_has_libzstd(config: &Config) -> bool { // contains a path to that static lib, and that it exists. // // See compiler/rustc_llvm/build.rs for more details and similar expectations. - fn is_zstd_in_config(llvm_bin_dir: &Path) -> Option<()> { + fn is_zstd_in_config(llvm_bin_dir: &Utf8Path) -> Option<()> { let llvm_config_path = llvm_bin_dir.join("llvm-config"); let output = Command::new(llvm_config_path).arg("--system-libs").output().ok()?; assert!(output.status.success(), "running llvm-config --system-libs failed"); let libs = String::from_utf8(output.stdout).ok()?; for lib in libs.split_whitespace() { - if lib.ends_with("libzstd.a") && Path::new(lib).exists() { + if lib.ends_with("libzstd.a") && Utf8Path::new(lib).exists() { return Some(()); } } @@ -1282,7 +1278,7 @@ pub fn llvm_has_libzstd(config: &Config) -> bool { // `lld` supports it. If not, an error will be emitted: "LLVM was not built with // LLVM_ENABLE_ZSTD or did not find zstd at build time". #[cfg(unix)] - fn is_lld_built_with_zstd(llvm_bin_dir: &Path) -> Option<()> { + fn is_lld_built_with_zstd(llvm_bin_dir: &Utf8Path) -> Option<()> { let lld_path = llvm_bin_dir.join("lld"); if lld_path.exists() { // We can't call `lld` as-is, it expects to be invoked by a compiler driver using a @@ -1318,7 +1314,7 @@ pub fn llvm_has_libzstd(config: &Config) -> bool { } #[cfg(not(unix))] - fn is_lld_built_with_zstd(_llvm_bin_dir: &Path) -> Option<()> { + fn is_lld_built_with_zstd(_llvm_bin_dir: &Utf8Path) -> Option<()> { None } @@ -1385,7 +1381,7 @@ pub(crate) fn make_test_description( config: &Config, cache: &HeadersCache, name: String, - path: &Path, + path: &Utf8Path, src: R, test_revision: Option<&str>, poisoned: &mut bool, @@ -1416,7 +1412,7 @@ pub(crate) fn make_test_description( ignore_message = Some(reason.into()); } IgnoreDecision::Error { message } => { - eprintln!("error: {}:{line_number}: {message}", path.display()); + eprintln!("error: {}:{line_number}: {message}", path); *poisoned = true; return; } @@ -1446,7 +1442,7 @@ pub(crate) fn make_test_description( ); if local_poisoned { - eprintln!("errors encountered when trying to make test description: {}", path.display()); + eprintln!("errors encountered when trying to make test description: {}", path); panic!("errors encountered when trying to make test description"); } @@ -1555,7 +1551,7 @@ fn ignore_lldb(config: &Config, line: &str) -> IgnoreDecision { IgnoreDecision::Continue } -fn ignore_llvm(config: &Config, path: &Path, line: &str) -> IgnoreDecision { +fn ignore_llvm(config: &Config, path: &Utf8Path, line: &str) -> IgnoreDecision { if let Some(needed_components) = config.parse_name_value_directive(line, "needs-llvm-components") { @@ -1567,8 +1563,7 @@ fn ignore_llvm(config: &Config, path: &Path, line: &str) -> IgnoreDecision { if env::var_os("COMPILETEST_REQUIRE_ALL_LLVM_COMPONENTS").is_some() { panic!( "missing LLVM component {}, and COMPILETEST_REQUIRE_ALL_LLVM_COMPONENTS is set: {}", - missing_component, - path.display() + missing_component, path ); } return IgnoreDecision::Ignore { diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index f3461f3c244f..3a8c3748de99 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -1,6 +1,6 @@ use std::io::Read; -use std::path::Path; +use camino::Utf8Path; use semver::Version; use super::{ @@ -13,7 +13,7 @@ use crate::executor::{CollectedTestDesc, ShouldPanic}; fn make_test_description( config: &Config, name: String, - path: &Path, + path: &Utf8Path, src: R, revision: Option<&str>, ) -> CollectedTestDesc { @@ -230,12 +230,12 @@ fn cfg() -> ConfigBuilder { fn parse_rs(config: &Config, contents: &str) -> EarlyProps { let bytes = contents.as_bytes(); - EarlyProps::from_reader(config, Path::new("a.rs"), bytes) + EarlyProps::from_reader(config, Utf8Path::new("a.rs"), bytes) } fn check_ignore(config: &Config, contents: &str) -> bool { let tn = String::new(); - let p = Path::new("a.rs"); + let p = Utf8Path::new("a.rs"); let d = make_test_description(&config, tn, p, std::io::Cursor::new(contents), None); d.ignore } @@ -244,7 +244,7 @@ fn check_ignore(config: &Config, contents: &str) -> bool { fn should_fail() { let config: Config = cfg().build(); let tn = String::new(); - let p = Path::new("a.rs"); + let p = Utf8Path::new("a.rs"); let d = make_test_description(&config, tn.clone(), p, std::io::Cursor::new(""), None); assert_eq!(d.should_panic, ShouldPanic::No); @@ -784,7 +784,7 @@ fn threads_support() { } } -fn run_path(poisoned: &mut bool, path: &Path, buf: &[u8]) { +fn run_path(poisoned: &mut bool, path: &Utf8Path, buf: &[u8]) { let rdr = std::io::Cursor::new(&buf); iter_header(Mode::Ui, "ui", poisoned, path, rdr, &mut |_| {}); } @@ -794,7 +794,7 @@ fn test_unknown_directive_check() { let mut poisoned = false; run_path( &mut poisoned, - Path::new("a.rs"), + Utf8Path::new("a.rs"), include_bytes!("./test-auxillary/unknown_directive.rs"), ); assert!(poisoned); @@ -805,7 +805,7 @@ fn test_known_directive_check_no_error() { let mut poisoned = false; run_path( &mut poisoned, - Path::new("a.rs"), + Utf8Path::new("a.rs"), include_bytes!("./test-auxillary/known_directive.rs"), ); assert!(!poisoned); @@ -816,7 +816,7 @@ fn test_error_annotation_no_error() { let mut poisoned = false; run_path( &mut poisoned, - Path::new("a.rs"), + Utf8Path::new("a.rs"), include_bytes!("./test-auxillary/error_annotation.rs"), ); assert!(!poisoned); @@ -827,7 +827,7 @@ fn test_non_rs_unknown_directive_not_checked() { let mut poisoned = false; run_path( &mut poisoned, - Path::new("a.Makefile"), + Utf8Path::new("a.Makefile"), include_bytes!("./test-auxillary/not_rs.Makefile"), ); assert!(!poisoned); @@ -836,21 +836,21 @@ fn test_non_rs_unknown_directive_not_checked() { #[test] fn test_trailing_directive() { let mut poisoned = false; - run_path(&mut poisoned, Path::new("a.rs"), b"//@ only-x86 only-arm"); + run_path(&mut poisoned, Utf8Path::new("a.rs"), b"//@ only-x86 only-arm"); assert!(poisoned); } #[test] fn test_trailing_directive_with_comment() { let mut poisoned = false; - run_path(&mut poisoned, Path::new("a.rs"), b"//@ only-x86 only-arm with comment"); + run_path(&mut poisoned, Utf8Path::new("a.rs"), b"//@ only-x86 only-arm with comment"); assert!(poisoned); } #[test] fn test_not_trailing_directive() { let mut poisoned = false; - run_path(&mut poisoned, Path::new("a.rs"), b"//@ revisions: incremental"); + run_path(&mut poisoned, Utf8Path::new("a.rs"), b"//@ revisions: incremental"); assert!(!poisoned); } diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 720663b30ef4..b969b22750bc 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -22,16 +22,15 @@ pub mod util; use core::panic; use std::collections::HashSet; -use std::ffi::OsString; use std::fmt::Write; use std::io::{self, ErrorKind}; -use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; use std::sync::{Arc, OnceLock}; use std::time::SystemTime; use std::{env, fs, vec}; use build_helper::git::{get_git_modified_files, get_git_untracked_files}; +use camino::{Utf8Path, Utf8PathBuf}; use getopts::Options; use tracing::*; use walkdir::WalkDir; @@ -230,15 +229,19 @@ pub fn parse_config(args: Vec) -> Config { panic!() } - fn opt_path(m: &getopts::Matches, nm: &str) -> PathBuf { - match m.opt_str(nm) { - Some(s) => PathBuf::from(&s), - None => panic!("no option (=path) found for {}", nm), + fn make_absolute(path: Utf8PathBuf) -> Utf8PathBuf { + if path.is_relative() { + Utf8PathBuf::try_from(env::current_dir().unwrap()).unwrap().join(path) + } else { + path } } - fn make_absolute(path: PathBuf) -> PathBuf { - if path.is_relative() { env::current_dir().unwrap().join(path) } else { path } + fn opt_path(m: &getopts::Matches, nm: &str) -> Utf8PathBuf { + match m.opt_str(nm) { + Some(s) => Utf8PathBuf::from(&s), + None => panic!("no option (=path) found for {}", nm), + } } let target = opt_str2(matches.opt_str("target")); @@ -279,12 +282,12 @@ pub fn parse_config(args: Vec) -> Config { .free .iter() .map(|f| { - let path = Path::new(f); + let path = Utf8Path::new(f); let mut iter = path.iter().skip(1); // We skip the test folder and check if the user passed `rmake.rs`. if iter.next().is_some_and(|s| s == "rmake.rs") && iter.next().is_none() { - path.parent().unwrap().to_str().unwrap().to_string() + path.parent().unwrap().to_string() } else { f.to_string() } @@ -316,8 +319,8 @@ pub fn parse_config(args: Vec) -> Config { assert!( src_test_suite_root.starts_with(&src_root), "`src-root` must be a parent of `src-test-suite-root`: `src-root`=`{}`, `src-test-suite-root` = `{}`", - src_root.display(), - src_test_suite_root.display() + src_root, + src_test_suite_root ); let build_root = opt_path(matches, "build-root"); @@ -332,16 +335,16 @@ pub fn parse_config(args: Vec) -> Config { compile_lib_path: make_absolute(opt_path(matches, "compile-lib-path")), run_lib_path: make_absolute(opt_path(matches, "run-lib-path")), rustc_path: opt_path(matches, "rustc-path"), - cargo_path: matches.opt_str("cargo-path").map(PathBuf::from), - stage0_rustc_path: matches.opt_str("stage0-rustc-path").map(PathBuf::from), - rustdoc_path: matches.opt_str("rustdoc-path").map(PathBuf::from), - coverage_dump_path: matches.opt_str("coverage-dump-path").map(PathBuf::from), + cargo_path: matches.opt_str("cargo-path").map(Utf8PathBuf::from), + stage0_rustc_path: matches.opt_str("stage0-rustc-path").map(Utf8PathBuf::from), + rustdoc_path: matches.opt_str("rustdoc-path").map(Utf8PathBuf::from), + coverage_dump_path: matches.opt_str("coverage-dump-path").map(Utf8PathBuf::from), python: matches.opt_str("python").unwrap(), jsondocck_path: matches.opt_str("jsondocck-path"), jsondoclint_path: matches.opt_str("jsondoclint-path"), run_clang_based_tests_with: matches.opt_str("run-clang-based-tests-with"), - llvm_filecheck: matches.opt_str("llvm-filecheck").map(PathBuf::from), - llvm_bin_dir: matches.opt_str("llvm-bin-dir").map(PathBuf::from), + llvm_filecheck: matches.opt_str("llvm-filecheck").map(Utf8PathBuf::from), + llvm_bin_dir: matches.opt_str("llvm-bin-dir").map(Utf8PathBuf::from), src_root, src_test_suite_root, @@ -407,7 +410,7 @@ pub fn parse_config(args: Vec) -> Config { }, only_modified: matches.opt_present("only-modified"), color, - remote_test_client: matches.opt_str("remote-test-client").map(PathBuf::from), + remote_test_client: matches.opt_str("remote-test-client").map(Utf8PathBuf::from), compare_mode, rustfix_coverage: matches.opt_present("rustfix-coverage"), has_html_tidy, @@ -450,19 +453,19 @@ pub fn parse_config(args: Vec) -> Config { pub fn log_config(config: &Config) { let c = config; logv(c, "configuration:".to_string()); - logv(c, format!("compile_lib_path: {:?}", config.compile_lib_path)); - logv(c, format!("run_lib_path: {:?}", config.run_lib_path)); - logv(c, format!("rustc_path: {:?}", config.rustc_path.display())); + logv(c, format!("compile_lib_path: {}", config.compile_lib_path)); + logv(c, format!("run_lib_path: {}", config.run_lib_path)); + logv(c, format!("rustc_path: {}", config.rustc_path)); logv(c, format!("cargo_path: {:?}", config.cargo_path)); logv(c, format!("rustdoc_path: {:?}", config.rustdoc_path)); - logv(c, format!("src_root: {}", config.src_root.display())); - logv(c, format!("src_test_suite_root: {}", config.src_test_suite_root.display())); + logv(c, format!("src_root: {}", config.src_root)); + logv(c, format!("src_test_suite_root: {}", config.src_test_suite_root)); - logv(c, format!("build_root: {}", config.build_root.display())); - logv(c, format!("build_test_suite_root: {}", config.build_test_suite_root.display())); + logv(c, format!("build_root: {}", config.build_root)); + logv(c, format!("build_test_suite_root: {}", config.build_test_suite_root)); - logv(c, format!("sysroot_base: {}", config.sysroot_base.display())); + logv(c, format!("sysroot_base: {}", config.sysroot_base)); logv(c, format!("stage: {}", config.stage)); logv(c, format!("stage_id: {}", config.stage_id)); @@ -480,16 +483,16 @@ pub fn log_config(config: &Config) { logv(c, format!("target-rustcflags: {:?}", config.target_rustcflags)); logv(c, format!("target: {}", config.target)); logv(c, format!("host: {}", config.host)); - logv(c, format!("android-cross-path: {:?}", config.android_cross_path.display())); - logv(c, format!("adb_path: {:?}", config.adb_path)); - logv(c, format!("adb_test_dir: {:?}", config.adb_test_dir)); + logv(c, format!("android-cross-path: {}", config.android_cross_path)); + logv(c, format!("adb_path: {}", config.adb_path)); + logv(c, format!("adb_test_dir: {}", config.adb_test_dir)); logv(c, format!("adb_device_status: {}", config.adb_device_status)); logv(c, format!("ar: {}", config.ar)); logv(c, format!("target-linker: {:?}", config.target_linker)); logv(c, format!("host-linker: {:?}", config.host_linker)); logv(c, format!("verbose: {}", config.verbose)); logv(c, format!("format: {:?}", config.format)); - logv(c, format!("minicore_path: {:?}", config.minicore_path.display())); + logv(c, format!("minicore_path: {}", config.minicore_path)); logv(c, "\n".to_string()); } @@ -517,7 +520,7 @@ pub fn run_tests(config: Arc) { coverage_file_path.push("rustfix_missing_coverage.txt"); if coverage_file_path.exists() { if let Err(e) = fs::remove_file(&coverage_file_path) { - panic!("Could not delete {} due to {}", coverage_file_path.display(), e) + panic!("Could not delete {} due to {}", coverage_file_path, e) } } } @@ -619,13 +622,13 @@ struct TestCollectorCx { config: Arc, cache: HeadersCache, common_inputs_stamp: Stamp, - modified_tests: Vec, + modified_tests: Vec, } /// Mutable state used during test collection. struct TestCollector { tests: Vec, - found_path_stems: HashSet, + found_path_stems: HashSet, poisoned: bool, } @@ -635,14 +638,13 @@ struct TestCollector { /// regardless of whether any filters/tests were specified on the command-line, /// because filtering is handled later by libtest. pub(crate) fn collect_and_make_tests(config: Arc) -> Vec { - debug!("making tests from {}", config.src_test_suite_root.display()); + debug!("making tests from {}", config.src_test_suite_root); let common_inputs_stamp = common_inputs_stamp(&config); let modified_tests = modified_tests(&config, &config.src_test_suite_root).unwrap_or_else(|err| { panic!( "modified_tests got error from dir: {}, error: {}", - config.src_test_suite_root.display(), - err + config.src_test_suite_root, err ) }); let cache = HeadersCache::load(&config); @@ -651,12 +653,9 @@ pub(crate) fn collect_and_make_tests(config: Arc) -> Vec let mut collector = TestCollector { tests: vec![], found_path_stems: HashSet::new(), poisoned: false }; - collect_tests_from_dir(&cx, &mut collector, &cx.config.src_test_suite_root, Path::new("")) + collect_tests_from_dir(&cx, &mut collector, &cx.config.src_test_suite_root, Utf8Path::new("")) .unwrap_or_else(|reason| { - panic!( - "Could not read tests from {}: {reason}", - cx.config.src_test_suite_root.display() - ) + panic!("Could not read tests from {}: {reason}", cx.config.src_test_suite_root) }); let TestCollector { tests, found_path_stems, poisoned } = collector; @@ -725,24 +724,29 @@ fn common_inputs_stamp(config: &Config) -> Stamp { /// the `--only-modified` flag is in use. /// /// (Might be inaccurate in some cases.) -fn modified_tests(config: &Config, dir: &Path) -> Result, String> { +fn modified_tests(config: &Config, dir: &Utf8Path) -> Result, String> { // If `--only-modified` wasn't passed, the list of modified tests won't be // used for anything, so avoid some work and just return an empty list. if !config.only_modified { return Ok(vec![]); } - let files = - get_git_modified_files(&config.git_config(), Some(dir), &vec!["rs", "stderr", "fixed"])?; + let files = get_git_modified_files( + &config.git_config(), + Some(dir.as_std_path()), + &vec!["rs", "stderr", "fixed"], + )?; // Add new test cases to the list, it will be convenient in daily development. let untracked_files = get_git_untracked_files(&config.git_config(), None)?.unwrap_or(vec![]); let all_paths = [&files[..], &untracked_files[..]].concat(); let full_paths = { - let mut full_paths: Vec = all_paths + let mut full_paths: Vec = all_paths .into_iter() - .map(|f| PathBuf::from(f).with_extension("").with_extension("rs")) - .filter_map(|f| if Path::new(&f).exists() { f.canonicalize().ok() } else { None }) + .map(|f| Utf8PathBuf::from(f).with_extension("").with_extension("rs")) + .filter_map( + |f| if Utf8Path::new(&f).exists() { f.canonicalize_utf8().ok() } else { None }, + ) .collect(); full_paths.dedup(); full_paths.sort_unstable(); @@ -756,8 +760,8 @@ fn modified_tests(config: &Config, dir: &Path) -> Result, String> { fn collect_tests_from_dir( cx: &TestCollectorCx, collector: &mut TestCollector, - dir: &Path, - relative_dir_path: &Path, + dir: &Utf8Path, + relative_dir_path: &Utf8Path, ) -> io::Result<()> { // Ignore directories that contain a file named `compiletest-ignore-dir`. if dir.join("compiletest-ignore-dir").exists() { @@ -790,16 +794,16 @@ fn collect_tests_from_dir( // subdirectories we find, except for `auxiliary` directories. // FIXME: this walks full tests tree, even if we have something to ignore // use walkdir/ignore like in tidy? - for file in fs::read_dir(dir)? { + for file in fs::read_dir(dir.as_std_path())? { let file = file?; - let file_path = file.path(); - let file_name = file.file_name(); + let file_path = Utf8PathBuf::try_from(file.path()).unwrap(); + let file_name = file_path.file_name().unwrap(); - if is_test(&file_name) + if is_test(file_name) && (!cx.config.only_modified || cx.modified_tests.contains(&file_path)) { // We found a test file, so create the corresponding libtest structures. - debug!("found test file: {:?}", file_path.display()); + debug!(%file_path, "found test file"); // Record the stem of the test file, to check for overlaps later. let rel_test_path = relative_dir_path.join(file_path.file_stem().unwrap()); @@ -810,22 +814,20 @@ fn collect_tests_from_dir( make_test(cx, collector, &paths); } else if file_path.is_dir() { // Recurse to find more tests in a subdirectory. - let relative_file_path = relative_dir_path.join(file.file_name()); - if &file_name != "auxiliary" { - debug!("found directory: {:?}", file_path.display()); + let relative_file_path = relative_dir_path.join(file_name); + if file_name != "auxiliary" { + debug!(%file_path, "found directory"); collect_tests_from_dir(cx, collector, &file_path, &relative_file_path)?; } } else { - debug!("found other file/directory: {:?}", file_path.display()); + debug!(%file_path, "found other file/directory"); } } Ok(()) } /// Returns true if `file_name` looks like a proper test file name. -pub fn is_test(file_name: &OsString) -> bool { - let file_name = file_name.to_str().unwrap(); - +pub fn is_test(file_name: &str) -> bool { if !file_name.ends_with(".rs") { return false; } @@ -844,7 +846,7 @@ fn make_test(cx: &TestCollectorCx, collector: &mut TestCollector, testpaths: &Te let test_path = if cx.config.mode == Mode::RunMake { testpaths.file.join("rmake.rs") } else { - PathBuf::from(&testpaths.file) + testpaths.file.clone() }; // Scan the test file to discover its revisions, if any. @@ -899,7 +901,7 @@ fn make_test(cx: &TestCollectorCx, collector: &mut TestCollector, testpaths: &Te /// The path of the `stamp` file that gets created or updated whenever a /// particular test completes successfully. -fn stamp_file_path(config: &Config, testpaths: &TestPaths, revision: Option<&str>) -> PathBuf { +fn stamp_file_path(config: &Config, testpaths: &TestPaths, revision: Option<&str>) -> Utf8PathBuf { output_base_dir(config, testpaths, revision).join("stamp") } @@ -912,7 +914,7 @@ fn files_related_to_test( testpaths: &TestPaths, props: &EarlyProps, revision: Option<&str>, -) -> Vec { +) -> Vec { let mut related = vec![]; if testpaths.file.is_dir() { @@ -920,7 +922,7 @@ fn files_related_to_test( for entry in WalkDir::new(&testpaths.file) { let path = entry.unwrap().into_path(); if path.is_file() { - related.push(path); + related.push(Utf8PathBuf::try_from(path).unwrap()); } } } else { @@ -991,7 +993,7 @@ struct Stamp { impl Stamp { /// Creates a timestamp holding the last-modified time of the specified file. - fn from_path(path: &Path) -> Self { + fn from_path(path: &Utf8Path) -> Self { let mut stamp = Stamp { time: SystemTime::UNIX_EPOCH }; stamp.add_path(path); stamp @@ -999,8 +1001,8 @@ impl Stamp { /// Updates this timestamp to the last-modified time of the specified file, /// if it is later than the currently-stored timestamp. - fn add_path(&mut self, path: &Path) { - let modified = fs::metadata(path) + fn add_path(&mut self, path: &Utf8Path) { + let modified = fs::metadata(path.as_std_path()) .and_then(|metadata| metadata.modified()) .unwrap_or(SystemTime::UNIX_EPOCH); self.time = self.time.max(modified); @@ -1009,7 +1011,8 @@ impl Stamp { /// Updates this timestamp to the most recent last-modified time of all files /// recursively contained in the given directory, if it is later than the /// currently-stored timestamp. - fn add_dir(&mut self, path: &Path) { + fn add_dir(&mut self, path: &Utf8Path) { + let path = path.as_std_path(); for entry in WalkDir::new(path) { let entry = entry.unwrap(); if entry.file_type().is_file() { @@ -1042,7 +1045,7 @@ fn make_test_name(config: &Config, testpaths: &TestPaths, revision: Option<&str> config.mode, debugger, mode_suffix, - path.display(), + path, revision.map_or("".to_string(), |rev| format!("#{}", rev)) ) } @@ -1064,7 +1067,7 @@ fn make_test_name(config: &Config, testpaths: &TestPaths, revision: Option<&str> /// To avoid problems, we forbid test names from overlapping in this way. /// /// See for more context. -fn check_for_overlapping_test_paths(found_path_stems: &HashSet) { +fn check_for_overlapping_test_paths(found_path_stems: &HashSet) { let mut collisions = Vec::new(); for path in found_path_stems { for ancestor in path.ancestors().skip(1) { @@ -1077,7 +1080,7 @@ fn check_for_overlapping_test_paths(found_path_stems: &HashSet) { collisions.sort(); let collisions: String = collisions .into_iter() - .map(|(path, check_parent)| format!("test {path:?} clashes with {check_parent:?}\n")) + .map(|(path, check_parent)| format!("test {path} clashes with {check_parent}\n")) .collect(); panic!( "{collisions}\n\ diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 208d32833c9c..722ba66e9541 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1,15 +1,15 @@ use std::borrow::Cow; use std::collections::{HashMap, HashSet}; -use std::ffi::{OsStr, OsString}; +use std::ffi::OsString; use std::fs::{self, File, create_dir_all}; use std::hash::{DefaultHasher, Hash, Hasher}; use std::io::prelude::*; use std::io::{self, BufReader}; -use std::path::{Path, PathBuf}; use std::process::{Child, Command, ExitStatus, Output, Stdio}; use std::sync::Arc; use std::{env, iter, str}; +use camino::{Utf8Path, Utf8PathBuf}; use colored::Colorize; use regex::{Captures, Regex}; use tracing::*; @@ -25,7 +25,7 @@ use crate::compute_diff::{DiffLine, make_diff, write_diff, write_filtered_diff}; use crate::errors::{self, Error, ErrorKind}; use crate::header::TestProps; use crate::read2::{Truncated, read2_abbreviated}; -use crate::util::{PathBufExt, add_dylib_path, logv, static_regex}; +use crate::util::{Utf8PathBufExt, add_dylib_path, logv, static_regex}; use crate::{ColorConfig, json, stamp_file_path}; mod debugger; @@ -131,7 +131,7 @@ pub fn run(config: Arc, testpaths: &TestPaths, revision: Option<&str>) { // We're going to be dumping a lot of info. Start on a new line. print!("\n\n"); } - debug!("running {:?}", testpaths.file.display()); + debug!("running {}", testpaths.file); let mut props = TestProps::from_file(&testpaths.file, revision, &config); // For non-incremental (i.e. regular UI) tests, the incremental directory @@ -144,7 +144,7 @@ pub fn run(config: Arc, testpaths: &TestPaths, revision: Option<&str>) { let cx = TestCx { config: &config, props: &props, testpaths, revision }; if let Err(e) = create_dir_all(&cx.output_base_dir()) { - panic!("failed to create output base directory {}: {e}", cx.output_base_dir().display()); + panic!("failed to create output base directory {}: {e}", cx.output_base_dir()); } if props.incremental { @@ -207,7 +207,8 @@ pub fn compute_stamp_hash(config: &Config) -> String { format!("{:x}", hash.finish()) } -fn remove_and_create_dir_all(path: &Path) { +fn remove_and_create_dir_all(path: &Utf8Path) { + let path = path.as_std_path(); let _ = fs::remove_dir_all(path); fs::create_dir_all(path).unwrap(); } @@ -423,7 +424,7 @@ impl<'test> TestCx<'test> { let aux_dir = self.aux_output_dir_name(); let input: &str = match read_from { ReadFrom::Stdin(_) => "-", - ReadFrom::Path => self.testpaths.file.to_str().unwrap(), + ReadFrom::Path => self.testpaths.file.as_str(), }; let mut rustc = Command::new(&self.config.rustc_path); @@ -590,10 +591,7 @@ impl<'test> TestCx<'test> { // FIXME(#65865) return; } else { - self.fatal(&format!( - "no error pattern specified in {:?}", - self.testpaths.file.display() - )); + self.fatal(&format!("no error pattern specified in {}", self.testpaths.file)); } } @@ -697,17 +695,17 @@ impl<'test> TestCx<'test> { } // On Windows, translate all '\' path separators to '/' - let file_name = format!("{}", self.testpaths.file.display()).replace(r"\", "/"); + let file_name = self.testpaths.file.to_string().replace(r"\", "/"); // On Windows, keep all '\' path separators to match the paths reported in the JSON output // from the compiler let diagnostic_file_name = if self.props.remap_src_base { - let mut p = PathBuf::from(FAKE_SRC_BASE); + let mut p = Utf8PathBuf::from(FAKE_SRC_BASE); p.push(&self.testpaths.relative_dir); p.push(self.testpaths.file.file_name().unwrap()); - p.display().to_string() + p.to_string() } else { - self.testpaths.file.display().to_string() + self.testpaths.file.to_string() }; let expect_help = expected_errors.iter().any(|ee| ee.kind == Some(ErrorKind::Help)); @@ -887,7 +885,7 @@ impl<'test> TestCx<'test> { /// `root_out_dir` and `root_testpaths` refer to the parameters of the actual test being run. /// Auxiliaries, no matter how deep, have the same root_out_dir and root_testpaths. - fn document(&self, root_out_dir: &Path, root_testpaths: &TestPaths) -> ProcRes { + fn document(&self, root_out_dir: &Utf8Path, root_testpaths: &TestPaths) -> ProcRes { if self.props.build_aux_docs { for rel_ab in &self.props.aux.builds { let aux_testpaths = self.compute_aux_test_paths(root_testpaths, rel_ab); @@ -916,13 +914,13 @@ impl<'test> TestCx<'test> { // actual --out-dir given to the auxiliary or test, as opposed to the root out dir for the entire // test - let out_dir: Cow<'_, Path> = if self.props.unique_doc_out_dir { + let out_dir: Cow<'_, Utf8Path> = if self.props.unique_doc_out_dir { let file_name = self.testpaths.file.file_stem().expect("file name should not be empty"); - let out_dir = PathBuf::from_iter([ + let out_dir = Utf8PathBuf::from_iter([ root_out_dir, - Path::new("docs"), - Path::new(file_name), - Path::new("doc"), + Utf8Path::new("docs"), + Utf8Path::new(file_name), + Utf8Path::new("doc"), ]); create_dir_all(&out_dir).unwrap(); Cow::Owned(out_dir) @@ -935,7 +933,7 @@ impl<'test> TestCx<'test> { rustdoc.current_dir(current_dir); rustdoc .arg("-L") - .arg(self.config.run_lib_path.to_str().unwrap()) + .arg(self.config.run_lib_path.as_path()) .arg("-L") .arg(aux_dir) .arg("-o") @@ -1073,7 +1071,7 @@ impl<'test> TestCx<'test> { let test_ab = of.file.parent().expect("test file path has no parent").join("auxiliary").join(rel_ab); if !test_ab.exists() { - self.fatal(&format!("aux-build `{}` source not found", test_ab.display())) + self.fatal(&format!("aux-build `{}` source not found", test_ab)) } TestPaths { @@ -1110,7 +1108,7 @@ impl<'test> TestCx<'test> { || !self.props.aux.proc_macros.is_empty() } - fn aux_output_dir(&self) -> PathBuf { + fn aux_output_dir(&self) -> Utf8PathBuf { let aux_dir = self.aux_output_dir_name(); if !self.props.aux.builds.is_empty() { @@ -1126,7 +1124,7 @@ impl<'test> TestCx<'test> { aux_dir } - fn build_all_auxiliary(&self, of: &TestPaths, aux_dir: &Path, rustc: &mut Command) { + fn build_all_auxiliary(&self, of: &TestPaths, aux_dir: &Utf8Path, rustc: &mut Command) { for rel_ab in &self.props.aux.builds { self.build_auxiliary(of, rel_ab, &aux_dir, None); } @@ -1146,12 +1144,7 @@ impl<'test> TestCx<'test> { |rustc: &mut Command, aux_name: &str, aux_path: &str, aux_type: AuxType| { let lib_name = get_lib_name(&path_to_crate_name(aux_path), aux_type); if let Some(lib_name) = lib_name { - rustc.arg("--extern").arg(format!( - "{}={}/{}", - aux_name, - aux_dir.display(), - lib_name - )); + rustc.arg("--extern").arg(format!("{}={}/{}", aux_name, aux_dir, lib_name)); } }; @@ -1172,7 +1165,7 @@ impl<'test> TestCx<'test> { let aux_type = self.build_auxiliary(of, aux_file, aux_dir, None); if let Some(lib_name) = get_lib_name(aux_file.trim_end_matches(".rs"), aux_type) { let lib_path = aux_dir.join(&lib_name); - rustc.arg(format!("-Zcodegen-backend={}", lib_path.display())); + rustc.arg(format!("-Zcodegen-backend={}", lib_path)); } } } @@ -1188,7 +1181,7 @@ impl<'test> TestCx<'test> { if self.props.add_core_stubs { let minicore_path = self.build_minicore(); rustc.arg("--extern"); - rustc.arg(&format!("minicore={}", minicore_path.to_str().unwrap())); + rustc.arg(&format!("minicore={}", minicore_path)); } let aux_dir = self.aux_output_dir(); @@ -1206,7 +1199,7 @@ impl<'test> TestCx<'test> { /// Builds `minicore`. Returns the path to the minicore rlib within the base test output /// directory. - fn build_minicore(&self) -> PathBuf { + fn build_minicore(&self) -> Utf8PathBuf { let output_file_path = self.output_base_dir().join("libminicore.rlib"); let mut rustc = self.make_compile_args( &self.config.minicore_path, @@ -1223,10 +1216,7 @@ impl<'test> TestCx<'test> { let res = self.compose_and_run(rustc, self.config.compile_lib_path.as_path(), None, None); if !res.status.success() { self.fatal_proc_rec( - &format!( - "auxiliary build of {:?} failed to compile: ", - self.config.minicore_path.display() - ), + &format!("auxiliary build of {} failed to compile: ", self.config.minicore_path), &res, ); } @@ -1241,7 +1231,7 @@ impl<'test> TestCx<'test> { &self, of: &TestPaths, source_path: &str, - aux_dir: &Path, + aux_dir: &Utf8Path, aux_type: Option, ) -> AuxType { let aux_testpaths = self.compute_aux_test_paths(of, source_path); @@ -1338,10 +1328,7 @@ impl<'test> TestCx<'test> { ); if !auxres.status.success() { self.fatal_proc_rec( - &format!( - "auxiliary build of {:?} failed to compile: ", - aux_testpaths.file.display() - ), + &format!("auxiliary build of {} failed to compile: ", aux_testpaths.file), &auxres, ); } @@ -1350,8 +1337,8 @@ impl<'test> TestCx<'test> { fn read2_abbreviated(&self, child: Child) -> (Output, Truncated) { let mut filter_paths_from_len = Vec::new(); - let mut add_path = |path: &Path| { - let path = path.display().to_string(); + let mut add_path = |path: &Utf8Path| { + let path = path.to_string(); let windows = path.replace("\\", "\\\\"); if windows != path { filter_paths_from_len.push(windows); @@ -1373,8 +1360,8 @@ impl<'test> TestCx<'test> { fn compose_and_run( &self, mut command: Command, - lib_path: &Path, - aux_path: Option<&Path>, + lib_path: &Utf8Path, + aux_path: Option<&Utf8Path>, input: Option, ) -> ProcRes { let cmdline = { @@ -1419,9 +1406,9 @@ impl<'test> TestCx<'test> { matches!(self.config.suite.as_str(), "rustdoc-ui" | "rustdoc-js" | "rustdoc-json") } - fn get_mir_dump_dir(&self) -> PathBuf { + fn get_mir_dump_dir(&self) -> Utf8PathBuf { let mut mir_dump_dir = self.config.build_test_suite_root.clone(); - debug!("input_file: {:?}", self.testpaths.file); + debug!("input_file: {}", self.testpaths.file); mir_dump_dir.push(&self.testpaths.relative_dir); mir_dump_dir.push(self.testpaths.file.file_stem().unwrap()); mir_dump_dir @@ -1429,7 +1416,7 @@ impl<'test> TestCx<'test> { fn make_compile_args( &self, - input_file: &Path, + input_file: &Utf8Path, output_file: TargetLocation, emit: Emit, allow_unused: AllowUnused, @@ -1470,7 +1457,7 @@ impl<'test> TestCx<'test> { // Similarly, vendored sources shouldn't be shown when running from a dist tarball. rustc.arg("-Z").arg(format!( "ignore-directory-in-diagnostics-source-blocks={}", - self.config.src_root.join("vendor").to_str().unwrap(), + self.config.src_root.join("vendor"), )); // Optionally prevent default --sysroot if specified in test compile-flags. @@ -1494,7 +1481,7 @@ impl<'test> TestCx<'test> { if !is_rustdoc { if let Some(ref incremental_dir) = self.props.incremental_dir { - rustc.args(&["-C", &format!("incremental={}", incremental_dir.display())]); + rustc.args(&["-C", &format!("incremental={}", incremental_dir)]); rustc.args(&["-Z", "incremental-verify-ich"]); } @@ -1538,7 +1525,7 @@ impl<'test> TestCx<'test> { let mir_dump_dir = self.get_mir_dump_dir(); remove_and_create_dir_all(&mir_dump_dir); let mut dir_opt = "-Zdump-mir-dir=".to_string(); - dir_opt.push_str(mir_dump_dir.to_str().unwrap()); + dir_opt.push_str(mir_dump_dir.as_str()); debug!("dir_opt: {:?}", dir_opt); rustc.arg(dir_opt); }; @@ -1631,8 +1618,7 @@ impl<'test> TestCx<'test> { if self.props.remap_src_base { rustc.arg(format!( "--remap-path-prefix={}={}", - self.config.src_test_suite_root.to_str().unwrap(), - FAKE_SRC_BASE, + self.config.src_test_suite_root, FAKE_SRC_BASE, )); } @@ -1755,7 +1741,7 @@ impl<'test> TestCx<'test> { rustc } - fn make_exe_name(&self) -> PathBuf { + fn make_exe_name(&self) -> Utf8PathBuf { // Using a single letter here to keep the path length down for // Windows. Some test names get very long. rustc creates `rcgu` // files with the module name appended to it which can more than @@ -1806,7 +1792,7 @@ impl<'test> TestCx<'test> { } } - fn make_cmdline(&self, command: &Command, libpath: &Path) -> String { + fn make_cmdline(&self, command: &Command, libpath: &Utf8Path) -> String { use crate::util; // Linux and mac don't require adjusting the library search path @@ -1819,7 +1805,7 @@ impl<'test> TestCx<'test> { format!("{}=\"{}\"", util::lib_path_env_var(), util::make_new_path(path)) } - format!("{} {:?}", lib_path_cmd_prefix(libpath.to_str().unwrap()), command) + format!("{} {:?}", lib_path_cmd_prefix(libpath.as_str()), command) } } @@ -1833,20 +1819,19 @@ impl<'test> TestCx<'test> { return; } - let path = Path::new(proc_name); + let path = Utf8Path::new(proc_name); let proc_name = if path.file_stem().is_some_and(|p| p == "rmake") { - OsString::from_iter( + String::from_iter( path.parent() .unwrap() .file_name() .into_iter() - .chain(Some(OsStr::new("/"))) + .chain(Some("/")) .chain(path.file_name()), ) } else { path.file_name().unwrap().into() }; - let proc_name = proc_name.to_string_lossy(); println!("------{proc_name} stdout------------------------------"); println!("{}", out); println!("------{proc_name} stderr------------------------------"); @@ -1856,18 +1841,18 @@ impl<'test> TestCx<'test> { fn dump_output_file(&self, out: &str, extension: &str) { let outfile = self.make_out_name(extension); - fs::write(&outfile, out).unwrap(); + fs::write(outfile.as_std_path(), out).unwrap(); } /// Creates a filename for output with the given extension. /// E.g., `/.../testname.revision.mode/testname.extension`. - fn make_out_name(&self, extension: &str) -> PathBuf { + fn make_out_name(&self, extension: &str) -> Utf8PathBuf { self.output_base_name().with_extension(extension) } /// Gets the directory where auxiliary files are written. /// E.g., `/.../testname.revision.mode/auxiliary/`. - fn aux_output_dir_name(&self) -> PathBuf { + fn aux_output_dir_name(&self) -> Utf8PathBuf { self.output_base_dir() .join("auxiliary") .with_extra_extension(self.config.mode.aux_dir_disambiguator()) @@ -1875,12 +1860,12 @@ impl<'test> TestCx<'test> { /// Gets the directory where auxiliary binaries are written. /// E.g., `/.../testname.revision.mode/auxiliary/bin`. - fn aux_bin_output_dir_name(&self) -> PathBuf { + fn aux_bin_output_dir_name(&self) -> Utf8PathBuf { self.aux_output_dir_name().join("bin") } /// Generates a unique name for the test, such as `testname.revision.mode`. - fn output_testname_unique(&self) -> PathBuf { + fn output_testname_unique(&self) -> Utf8PathBuf { output_testname_unique(self.config, self.testpaths, self.safe_revision()) } @@ -1893,14 +1878,14 @@ impl<'test> TestCx<'test> { /// Gets the absolute path to the directory where all output for the given /// test/revision should reside. /// E.g., `/path/to/build/host-tuple/test/ui/relative/testname.revision.mode/`. - fn output_base_dir(&self) -> PathBuf { + fn output_base_dir(&self) -> Utf8PathBuf { output_base_dir(self.config, self.testpaths, self.safe_revision()) } /// Gets the absolute path to the base filename used as output for the given /// test/revision. /// E.g., `/.../relative/testname.revision.mode/testname`. - fn output_base_name(&self) -> PathBuf { + fn output_base_name(&self) -> Utf8PathBuf { output_base_name(self.config, self.testpaths, self.safe_revision()) } @@ -1935,7 +1920,7 @@ impl<'test> TestCx<'test> { // codegen tests (using FileCheck) - fn compile_test_and_save_ir(&self) -> (ProcRes, PathBuf) { + fn compile_test_and_save_ir(&self) -> (ProcRes, Utf8PathBuf) { let output_path = self.output_base_name().with_extension("ll"); let input_file = &self.testpaths.file; let rustc = self.make_compile_args( @@ -1951,7 +1936,7 @@ impl<'test> TestCx<'test> { (proc_res, output_path) } - fn verify_with_filecheck(&self, output: &Path) -> ProcRes { + fn verify_with_filecheck(&self, output: &Utf8Path) -> ProcRes { let mut filecheck = Command::new(self.config.llvm_filecheck.as_ref().unwrap()); filecheck.arg("--input-file").arg(output).arg(&self.testpaths.file); @@ -1981,7 +1966,7 @@ impl<'test> TestCx<'test> { filecheck.args(&self.props.filecheck_flags); // FIXME(jieyouxu): don't pass an empty Path - self.compose_and_run(filecheck, Path::new(""), None, None) + self.compose_and_run(filecheck, Utf8Path::new(""), None, None) } fn charset() -> &'static str { @@ -1989,7 +1974,7 @@ impl<'test> TestCx<'test> { if cfg!(target_os = "freebsd") { "ISO-8859-1" } else { "UTF-8" } } - fn compare_to_default_rustdoc(&mut self, out_dir: &Path) { + fn compare_to_default_rustdoc(&mut self, out_dir: &Utf8Path) { if !self.config.has_html_tidy { return; } @@ -2141,12 +2126,8 @@ impl<'test> TestCx<'test> { }; } - fn get_lines>( - &self, - path: &P, - mut other_files: Option<&mut Vec>, - ) -> Vec { - let content = fs::read_to_string(&path).unwrap(); + fn get_lines(&self, path: &Utf8Path, mut other_files: Option<&mut Vec>) -> Vec { + let content = fs::read_to_string(path.as_std_path()).unwrap(); let mut ignore = false; content .lines() @@ -2192,8 +2173,8 @@ impl<'test> TestCx<'test> { for other_file in other_files { let mut path = self.testpaths.file.clone(); path.set_file_name(&format!("{}.rs", other_file)); - let path = fs::canonicalize(path).expect("failed to canonicalize"); - let normalized = path.to_str().unwrap().replace('\\', "/"); + let path = path.canonicalize_utf8().expect("failed to canonicalize"); + let normalized = path.as_str().replace('\\', "/"); files.insert(normalized, self.get_lines(&path, None)); } @@ -2377,26 +2358,24 @@ impl<'test> TestCx<'test> { let mut normalized = output.to_string(); - let mut normalize_path = |from: &Path, to: &str| { - let mut from = from.display().to_string(); - if json { - from = from.replace("\\", "\\\\"); - } - normalized = normalized.replace(&from, to); + let mut normalize_path = |from: &Utf8Path, to: &str| { + let from = if json { &from.as_str().replace("\\", "\\\\") } else { from.as_str() }; + + normalized = normalized.replace(from, to); }; let parent_dir = self.testpaths.file.parent().unwrap(); normalize_path(parent_dir, "$DIR"); if self.props.remap_src_base { - let mut remapped_parent_dir = PathBuf::from(FAKE_SRC_BASE); - if self.testpaths.relative_dir != Path::new("") { + let mut remapped_parent_dir = Utf8PathBuf::from(FAKE_SRC_BASE); + if self.testpaths.relative_dir != Utf8Path::new("") { remapped_parent_dir.push(&self.testpaths.relative_dir); } normalize_path(&remapped_parent_dir, "$DIR"); } - let base_dir = Path::new("/rustc/FAKE_PREFIX"); + let base_dir = Utf8Path::new("/rustc/FAKE_PREFIX"); // Fake paths into the libstd/libcore normalize_path(&base_dir.join("library"), "$SRC_DIR"); // `ui-fulldeps` tests can show paths to the compiler source when testing macros from @@ -2406,8 +2385,8 @@ impl<'test> TestCx<'test> { // Real paths into the libstd/libcore let rust_src_dir = &self.config.sysroot_base.join("lib/rustlib/src/rust"); - rust_src_dir.try_exists().expect(&*format!("{} should exists", rust_src_dir.display())); - let rust_src_dir = rust_src_dir.read_link().unwrap_or(rust_src_dir.to_path_buf()); + rust_src_dir.try_exists().expect(&*format!("{} should exists", rust_src_dir)); + let rust_src_dir = rust_src_dir.read_link_utf8().unwrap_or(rust_src_dir.to_path_buf()); normalize_path(&rust_src_dir.join("library"), "$SRC_DIR_REAL"); // eg. @@ -2547,7 +2526,7 @@ impl<'test> TestCx<'test> { .replace("\r\n", "\n") } - fn expected_output_path(&self, kind: &str) -> PathBuf { + fn expected_output_path(&self, kind: &str) -> Utf8PathBuf { let mut path = expected_output_path(&self.testpaths, self.revision, &self.config.compare_mode, kind); @@ -2576,19 +2555,18 @@ impl<'test> TestCx<'test> { } } - fn load_expected_output_from_path(&self, path: &Path) -> Result { - fs::read_to_string(path).map_err(|err| { - format!("failed to load expected output from `{}`: {}", path.display(), err) - }) + fn load_expected_output_from_path(&self, path: &Utf8Path) -> Result { + fs::read_to_string(path) + .map_err(|err| format!("failed to load expected output from `{}`: {}", path, err)) } - fn delete_file(&self, file: &Path) { + fn delete_file(&self, file: &Utf8Path) { if !file.exists() { // Deleting a nonexistent file would error. return; } - if let Err(e) = fs::remove_file(file) { - self.fatal(&format!("failed to delete `{}`: {}", file.display(), e,)); + if let Err(e) = fs::remove_file(file.as_std_path()) { + self.fatal(&format!("failed to delete `{}`: {}", file, e,)); } } @@ -2694,8 +2672,8 @@ impl<'test> TestCx<'test> { fn show_diff( &self, stream: &str, - expected_path: &Path, - actual_path: &Path, + expected_path: &Utf8Path, + actual_path: &Utf8Path, expected: &str, actual: &str, actual_unnormalized: &str, @@ -2834,7 +2812,7 @@ impl<'test> TestCx<'test> { fs::create_dir_all(&incremental_dir).unwrap(); if self.config.verbose { - println!("init_incremental_test: incremental_dir={}", incremental_dir.display()); + println!("init_incremental_test: incremental_dir={incremental_dir}"); } } } @@ -2892,8 +2870,8 @@ impl ProcRes { #[derive(Debug)] enum TargetLocation { - ThisFile(PathBuf), - ThisDirectory(PathBuf), + ThisFile(Utf8PathBuf), + ThisDirectory(Utf8PathBuf), } enum AllowUnused { diff --git a/src/tools/compiletest/src/runtest/assembly.rs b/src/tools/compiletest/src/runtest/assembly.rs index 89d7de58c203..91d4f620f719 100644 --- a/src/tools/compiletest/src/runtest/assembly.rs +++ b/src/tools/compiletest/src/runtest/assembly.rs @@ -1,4 +1,4 @@ -use std::path::PathBuf; +use camino::Utf8PathBuf; use super::{AllowUnused, Emit, LinkToAux, ProcRes, TargetLocation, TestCx}; @@ -19,7 +19,7 @@ impl TestCx<'_> { } } - fn compile_test_and_save_assembly(&self) -> (ProcRes, PathBuf) { + fn compile_test_and_save_assembly(&self) -> (ProcRes, Utf8PathBuf) { // This works with both `--emit asm` (as default output name for the assembly) // and `ptx-linker` because the latter can write output at requested location. let output_path = self.output_base_name().with_extension("s"); diff --git a/src/tools/compiletest/src/runtest/codegen_units.rs b/src/tools/compiletest/src/runtest/codegen_units.rs index 6c866cbef21a..8dfa8d18d1a0 100644 --- a/src/tools/compiletest/src/runtest/codegen_units.rs +++ b/src/tools/compiletest/src/runtest/codegen_units.rs @@ -26,9 +26,7 @@ impl TestCx<'_> { .stdout .lines() .filter(|line| line.starts_with(PREFIX)) - .map(|line| { - line.replace(&self.testpaths.file.display().to_string(), "TEST_PATH").to_string() - }) + .map(|line| line.replace(&self.testpaths.file.as_str(), "TEST_PATH").to_string()) .map(|line| str_to_mono_item(&line, true)) .collect(); diff --git a/src/tools/compiletest/src/runtest/coverage.rs b/src/tools/compiletest/src/runtest/coverage.rs index 56fc5baf5f24..41cfeaee35ff 100644 --- a/src/tools/compiletest/src/runtest/coverage.rs +++ b/src/tools/compiletest/src/runtest/coverage.rs @@ -1,9 +1,9 @@ //! Code specific to the coverage test suites. use std::ffi::OsStr; -use std::path::{Path, PathBuf}; use std::process::Command; +use camino::{Utf8Path, Utf8PathBuf}; use glob::glob; use crate::common::{UI_COVERAGE, UI_COVERAGE_MAP}; @@ -11,7 +11,7 @@ use crate::runtest::{Emit, ProcRes, TestCx, WillExecute}; use crate::util::static_regex; impl<'test> TestCx<'test> { - fn coverage_dump_path(&self) -> &Path { + fn coverage_dump_path(&self) -> &Utf8Path { self.config .coverage_dump_path .as_deref() @@ -79,10 +79,8 @@ impl<'test> TestCx<'test> { std::fs::remove_file(&profdata_path).unwrap(); } - let proc_res = self.exec_compiled_test_general( - &[("LLVM_PROFILE_FILE", &profraw_path.to_str().unwrap())], - false, - ); + let proc_res = + self.exec_compiled_test_general(&[("LLVM_PROFILE_FILE", profraw_path.as_str())], false); if self.props.failure_status.is_some() { self.check_correct_failure_status(&proc_res); } else if !proc_res.status.success() { @@ -158,8 +156,8 @@ impl<'test> TestCx<'test> { /// `.profraw` files and doctest executables to the given vectors. fn run_doctests_for_coverage( &self, - profraw_paths: &mut Vec, - bin_paths: &mut Vec, + profraw_paths: &mut Vec, + bin_paths: &mut Vec, ) { // Put .profraw files and doctest executables in dedicated directories, // to make it easier to glob them all later. @@ -204,10 +202,9 @@ impl<'test> TestCx<'test> { self.fatal_proc_rec("rustdoc --test failed!", &proc_res) } - fn glob_iter(path: impl AsRef) -> impl Iterator { - let path_str = path.as_ref().to_str().unwrap(); - let iter = glob(path_str).unwrap(); - iter.map(Result::unwrap) + fn glob_iter(path: impl AsRef) -> impl Iterator { + let iter = glob(path.as_ref().as_str()).unwrap(); + iter.map(Result::unwrap).map(Utf8PathBuf::try_from).map(Result::unwrap) } // Find all profraw files in the profraw directory. diff --git a/src/tools/compiletest/src/runtest/debugger.rs b/src/tools/compiletest/src/runtest/debugger.rs index d9e5c3fa0d8f..a4103c5b4a9a 100644 --- a/src/tools/compiletest/src/runtest/debugger.rs +++ b/src/tools/compiletest/src/runtest/debugger.rs @@ -1,7 +1,8 @@ use std::fmt::Write; use std::fs::File; use std::io::{BufRead, BufReader}; -use std::path::{Path, PathBuf}; + +use camino::{Utf8Path, Utf8PathBuf}; use crate::common::Config; use crate::runtest::ProcRes; @@ -15,11 +16,15 @@ pub(super) struct DebuggerCommands { /// Contains the source line number to check and the line itself check_lines: Vec<(usize, String)>, /// Source file name - file: PathBuf, + file: Utf8PathBuf, } impl DebuggerCommands { - pub fn parse_from(file: &Path, config: &Config, debugger_prefix: &str) -> Result { + pub fn parse_from( + file: &Utf8Path, + config: &Config, + debugger_prefix: &str, + ) -> Result { let command_directive = format!("{debugger_prefix}-command"); let check_directive = format!("{debugger_prefix}-check"); @@ -27,7 +32,7 @@ impl DebuggerCommands { let mut commands = vec![]; let mut check_lines = vec![]; let mut counter = 0; - let reader = BufReader::new(File::open(file).unwrap()); + let reader = BufReader::new(File::open(file.as_std_path()).unwrap()); for (line_no, line) in reader.lines().enumerate() { counter += 1; let line = line.map_err(|e| format!("Error while parsing debugger commands: {}", e))?; @@ -50,7 +55,7 @@ impl DebuggerCommands { } } - Ok(Self { commands, breakpoint_lines, check_lines, file: file.to_owned() }) + Ok(Self { commands, breakpoint_lines, check_lines, file: file.to_path_buf() }) } /// Given debugger output and lines to check, ensure that every line is @@ -81,10 +86,10 @@ impl DebuggerCommands { if missing.is_empty() { Ok(()) } else { - let fname = self.file.file_name().unwrap().to_string_lossy(); + let fname = self.file.file_name().unwrap(); let mut msg = format!( "check directive(s) from `{}` not found in debugger output. errors:", - self.file.display() + self.file ); for (src_lineno, err_line) in missing { diff --git a/src/tools/compiletest/src/runtest/debuginfo.rs b/src/tools/compiletest/src/runtest/debuginfo.rs index 50e733cd31b6..31240dff9a19 100644 --- a/src/tools/compiletest/src/runtest/debuginfo.rs +++ b/src/tools/compiletest/src/runtest/debuginfo.rs @@ -1,9 +1,9 @@ use std::ffi::{OsStr, OsString}; use std::fs::File; use std::io::{BufRead, BufReader, Read}; -use std::path::Path; use std::process::{Command, Output, Stdio}; +use camino::Utf8Path; use tracing::debug; use super::debugger::DebuggerCommands; @@ -73,11 +73,11 @@ impl TestCx<'_> { let mut js_extension = self.testpaths.file.clone(); js_extension.set_extension("cdb.js"); if js_extension.exists() { - script_str.push_str(&format!(".scriptload \"{}\"\n", js_extension.to_string_lossy())); + script_str.push_str(&format!(".scriptload \"{}\"\n", js_extension)); } // Set breakpoints on every line that contains the string "#break" - let source_file_name = self.testpaths.file.file_name().unwrap().to_string_lossy(); + let source_file_name = self.testpaths.file.file_name().unwrap(); for line in &dbg_cmds.breakpoint_lines { script_str.push_str(&format!("bp `{}:{}`\n", source_file_name, line)); } @@ -151,16 +151,11 @@ impl TestCx<'_> { if is_android_gdb_target(&self.config.target) { cmds = cmds.replace("run", "continue"); - let tool_path = match self.config.android_cross_path.to_str() { - Some(x) => x.to_owned(), - None => self.fatal("cannot find android cross path"), - }; - // write debugger script let mut script_str = String::with_capacity(2048); script_str.push_str(&format!("set charset {}\n", Self::charset())); - script_str.push_str(&format!("set sysroot {}\n", tool_path)); - script_str.push_str(&format!("file {}\n", exe_file.to_str().unwrap())); + script_str.push_str(&format!("set sysroot {}\n", &self.config.android_cross_path)); + script_str.push_str(&format!("file {}\n", exe_file)); script_str.push_str("target remote :5039\n"); script_str.push_str(&format!( "set solib-search-path \ @@ -169,12 +164,8 @@ impl TestCx<'_> { )); for line in &dbg_cmds.breakpoint_lines { script_str.push_str( - format!( - "break {:?}:{}\n", - self.testpaths.file.file_name().unwrap().to_string_lossy(), - *line - ) - .as_str(), + format!("break {}:{}\n", self.testpaths.file.file_name().unwrap(), *line) + .as_str(), ); } script_str.push_str(&cmds); @@ -203,7 +194,7 @@ impl TestCx<'_> { self.config.adb_test_dir.clone(), if self.config.target.contains("aarch64") { "64" } else { "" }, self.config.adb_test_dir.clone(), - exe_file.file_name().unwrap().to_str().unwrap() + exe_file.file_name().unwrap() ); debug!("adb arg: {}", adb_arg); @@ -242,7 +233,7 @@ impl TestCx<'_> { let mut gdb = Command::new(&format!("{}-gdb", self.config.target)); gdb.args(debugger_opts); // FIXME(jieyouxu): don't pass an empty Path - let cmdline = self.make_cmdline(&gdb, Path::new("")); + let cmdline = self.make_cmdline(&gdb, Utf8Path::new("")); logv(self.config, format!("executing {}", cmdline)); cmdline }; @@ -259,7 +250,6 @@ impl TestCx<'_> { } } else { let rust_pp_module_abs_path = self.config.src_root.join("src").join("etc"); - let rust_pp_module_abs_path = rust_pp_module_abs_path.to_str().unwrap(); // write debugger script let mut script_str = String::with_capacity(2048); script_str.push_str(&format!("set charset {}\n", Self::charset())); @@ -274,17 +264,15 @@ impl TestCx<'_> { // GDB's script auto loading safe path script_str.push_str(&format!( "add-auto-load-safe-path {}\n", - rust_pp_module_abs_path.replace(r"\", r"\\") + rust_pp_module_abs_path.as_str().replace(r"\", r"\\") )); - let output_base_dir = self.output_base_dir().to_str().unwrap().to_owned(); - // Add the directory containing the output binary to // include embedded pretty printers to GDB's script // auto loading safe path script_str.push_str(&format!( "add-auto-load-safe-path {}\n", - output_base_dir.replace(r"\", r"\\") + self.output_base_dir().as_str().replace(r"\", r"\\") )); } } @@ -301,12 +289,13 @@ impl TestCx<'_> { script_str.push_str("set print pretty off\n"); // Add the pretty printer directory to GDB's source-file search path - script_str - .push_str(&format!("directory {}\n", rust_pp_module_abs_path.replace(r"\", r"\\"))); + script_str.push_str(&format!( + "directory {}\n", + rust_pp_module_abs_path.as_str().replace(r"\", r"\\") + )); // Load the target executable - script_str - .push_str(&format!("file {}\n", exe_file.to_str().unwrap().replace(r"\", r"\\"))); + script_str.push_str(&format!("file {}\n", exe_file.as_str().replace(r"\", r"\\"))); // Force GDB to print values in the Rust format. script_str.push_str("set language rust\n"); @@ -315,7 +304,7 @@ impl TestCx<'_> { for line in &dbg_cmds.breakpoint_lines { script_str.push_str(&format!( "break '{}':{}\n", - self.testpaths.file.file_name().unwrap().to_string_lossy(), + self.testpaths.file.file_name().unwrap(), *line )); } @@ -410,14 +399,14 @@ impl TestCx<'_> { script_str.push_str(&format!( "command script import {}/lldb_lookup.py\n", - rust_pp_module_abs_path.to_str().unwrap() + rust_pp_module_abs_path )); File::open(rust_pp_module_abs_path.join("lldb_commands")) .and_then(|mut file| file.read_to_string(&mut script_str)) .expect("Failed to read lldb_commands"); // Set breakpoints on every line that contains the string "#break" - let source_file_name = self.testpaths.file.file_name().unwrap().to_string_lossy(); + let source_file_name = self.testpaths.file.file_name().unwrap(); for line in &dbg_cmds.breakpoint_lines { script_str.push_str(&format!( "breakpoint set --file '{}' --line {}\n", @@ -451,7 +440,7 @@ impl TestCx<'_> { } } - fn run_lldb(&self, test_executable: &Path, debugger_script: &Path) -> ProcRes { + fn run_lldb(&self, test_executable: &Utf8Path, debugger_script: &Utf8Path) -> ProcRes { // Prepare the lldb_batchmode which executes the debugger script let lldb_script_path = self.config.src_root.join("src/etc/lldb_batchmode.py"); let pythonpath = if let Ok(pp) = std::env::var("PYTHONPATH") { diff --git a/src/tools/compiletest/src/runtest/js_doc.rs b/src/tools/compiletest/src/runtest/js_doc.rs index d630affbec10..fd53f01ca174 100644 --- a/src/tools/compiletest/src/runtest/js_doc.rs +++ b/src/tools/compiletest/src/runtest/js_doc.rs @@ -9,8 +9,7 @@ impl TestCx<'_> { self.document(&out_dir, &self.testpaths); - let file_stem = - self.testpaths.file.file_stem().and_then(|f| f.to_str()).expect("no file stem"); + let file_stem = self.testpaths.file.file_stem().expect("no file stem"); let res = self.run_command_to_procres( Command::new(&nodejs) .arg(self.config.src_root.join("src/tools/rustdoc-js/tester.js")) diff --git a/src/tools/compiletest/src/runtest/mir_opt.rs b/src/tools/compiletest/src/runtest/mir_opt.rs index d1ec00357449..ded6a68fe587 100644 --- a/src/tools/compiletest/src/runtest/mir_opt.rs +++ b/src/tools/compiletest/src/runtest/mir_opt.rs @@ -1,6 +1,6 @@ use std::fs; -use std::path::{Path, PathBuf}; +use camino::{Utf8Path, Utf8PathBuf}; use glob::glob; use miropt_test_tools::{MiroptTest, MiroptTestFile, files_for_miropt_test}; use tracing::debug; @@ -14,7 +14,7 @@ impl TestCx<'_> { let should_run = self.should_run(pm); let mut test_info = files_for_miropt_test( - &self.testpaths.file, + &self.testpaths.file.as_std_path(), self.config.get_pointer_width(), self.config.target_cfg().panic.for_miropt_test_tools(), ); @@ -38,20 +38,15 @@ impl TestCx<'_> { fn check_mir_dump(&self, test_info: MiroptTest) { let test_dir = self.testpaths.file.parent().unwrap(); - let test_crate = - self.testpaths.file.file_stem().unwrap().to_str().unwrap().replace('-', "_"); + let test_crate = self.testpaths.file.file_stem().unwrap().replace('-', "_"); let MiroptTest { run_filecheck, suffix, files, passes: _ } = test_info; if self.config.bless { - for e in - glob(&format!("{}/{}.*{}.mir", test_dir.display(), test_crate, suffix)).unwrap() - { + for e in glob(&format!("{}/{}.*{}.mir", test_dir, test_crate, suffix)).unwrap() { fs::remove_file(e.unwrap()).unwrap(); } - for e in - glob(&format!("{}/{}.*{}.diff", test_dir.display(), test_crate, suffix)).unwrap() - { + for e in glob(&format!("{}/{}.*{}.diff", test_dir, test_crate, suffix)).unwrap() { fs::remove_file(e.unwrap()).unwrap(); } } @@ -60,19 +55,15 @@ impl TestCx<'_> { let dumped_string = if let Some(after) = to_file { self.diff_mir_files(from_file.into(), after.into()) } else { - let mut output_file = PathBuf::new(); + let mut output_file = Utf8PathBuf::new(); output_file.push(self.get_mir_dump_dir()); output_file.push(&from_file); - debug!( - "comparing the contents of: {} with {}", - output_file.display(), - expected_file.display() - ); + debug!("comparing the contents of: {} with {:?}", output_file, expected_file); if !output_file.exists() { panic!( "Output file `{}` from test does not exist, available files are in `{}`", - output_file.display(), - output_file.parent().unwrap().display() + output_file, + output_file.parent().unwrap() ); } self.check_mir_test_timestamp(&from_file, &output_file); @@ -107,21 +98,20 @@ impl TestCx<'_> { } } - fn diff_mir_files(&self, before: PathBuf, after: PathBuf) -> String { - let to_full_path = |path: PathBuf| { + fn diff_mir_files(&self, before: Utf8PathBuf, after: Utf8PathBuf) -> String { + let to_full_path = |path: Utf8PathBuf| { let full = self.get_mir_dump_dir().join(&path); if !full.exists() { panic!( "the mir dump file for {} does not exist (requested in {})", - path.display(), - self.testpaths.file.display(), + path, self.testpaths.file, ); } full }; let before = to_full_path(before); let after = to_full_path(after); - debug!("comparing the contents of: {} with {}", before.display(), after.display()); + debug!("comparing the contents of: {} with {}", before, after); let before = fs::read_to_string(before).unwrap(); let after = fs::read_to_string(after).unwrap(); let before = self.normalize_output(&before, &[]); @@ -138,8 +128,8 @@ impl TestCx<'_> { dumped_string } - fn check_mir_test_timestamp(&self, test_name: &str, output_file: &Path) { - let t = |file| fs::metadata(file).unwrap().modified().unwrap(); + fn check_mir_test_timestamp(&self, test_name: &str, output_file: &Utf8Path) { + let t = |file: &Utf8Path| fs::metadata(file.as_std_path()).unwrap().modified().unwrap(); let source_file = &self.testpaths.file; let output_time = t(output_file); let source_time = t(source_file); @@ -147,8 +137,7 @@ impl TestCx<'_> { debug!("source file time: {:?} output file time: {:?}", source_time, output_time); panic!( "test source file `{}` is newer than potentially stale output file `{}`.", - source_file.display(), - test_name + source_file, test_name ); } } diff --git a/src/tools/compiletest/src/runtest/run_make.rs b/src/tools/compiletest/src/runtest/run_make.rs index 073116933bdb..a5ce929f9b8e 100644 --- a/src/tools/compiletest/src/runtest/run_make.rs +++ b/src/tools/compiletest/src/runtest/run_make.rs @@ -1,8 +1,8 @@ -use std::path::Path; use std::process::{Command, Output, Stdio}; use std::{env, fs}; use build_helper::fs::{ignore_not_found, recursive_remove}; +use camino::{Utf8Path, Utf8PathBuf}; use super::{ProcRes, TestCx, disable_error_reporting}; use crate::util::{copy_dir_all, dylib_env_var}; @@ -39,14 +39,16 @@ impl TestCx<'_> { // Copy all input files (apart from rmake.rs) to the temporary directory, // so that the input directory structure from `tests/run-make/` is mirrored // to the `rmake_out` directory. - for path in walkdir::WalkDir::new(&self.testpaths.file).min_depth(1) { - let path = path.unwrap().path().to_path_buf(); + for entry in walkdir::WalkDir::new(&self.testpaths.file).min_depth(1) { + let entry = entry.unwrap(); + let path = entry.path(); + let path = <&Utf8Path>::try_from(path).unwrap(); if path.file_name().is_some_and(|s| s != "rmake.rs") { let target = rmake_out_dir.join(path.strip_prefix(&self.testpaths.file).unwrap()); if path.is_dir() { - copy_dir_all(&path, target).unwrap(); + copy_dir_all(&path, &target).unwrap(); } else { - fs::copy(&path, target).unwrap(); + fs::copy(path.as_std_path(), target).unwrap(); } } } @@ -83,8 +85,10 @@ impl TestCx<'_> { // on some linux distros. // 2. Specific library paths in `self.config.compile_lib_path` needed for running rustc. - let base_dylib_search_paths = - Vec::from_iter(env::split_paths(&env::var(dylib_env_var()).unwrap())); + let base_dylib_search_paths = Vec::from_iter( + env::split_paths(&env::var(dylib_env_var()).unwrap()) + .map(|p| Utf8PathBuf::try_from(p).expect("dylib env var contains non-UTF8 paths")), + ); // Calculate the paths of the recipe binary. As previously discussed, this is placed at // `/` with `bin_name` being `rmake` or `rmake.exe` depending on @@ -113,13 +117,13 @@ impl TestCx<'_> { .arg("-o") .arg(&recipe_bin) // Specify library search paths for `run_make_support`. - .arg(format!("-Ldependency={}", &support_lib_path.parent().unwrap().to_string_lossy())) - .arg(format!("-Ldependency={}", &support_lib_deps.to_string_lossy())) - .arg(format!("-Ldependency={}", &support_lib_deps_deps.to_string_lossy())) + .arg(format!("-Ldependency={}", &support_lib_path.parent().unwrap())) + .arg(format!("-Ldependency={}", &support_lib_deps)) + .arg(format!("-Ldependency={}", &support_lib_deps_deps)) // Provide `run_make_support` as extern prelude, so test writers don't need to write // `extern run_make_support;`. .arg("--extern") - .arg(format!("run_make_support={}", &support_lib_path.to_string_lossy())) + .arg(format!("run_make_support={}", &support_lib_path)) .arg("--edition=2021") .arg(&self.testpaths.file.join("rmake.rs")) .arg("-Cprefer-dynamic"); @@ -240,7 +244,7 @@ impl TestCx<'_> { if self.config.target.contains("msvc") && !self.config.cc.is_empty() { // We need to pass a path to `lib.exe`, so assume that `cc` is `cl.exe` // and that `lib.exe` lives next to it. - let lib = Path::new(&self.config.cc).parent().unwrap().join("lib.exe"); + let lib = Utf8Path::new(&self.config.cc).parent().unwrap().join("lib.exe"); // MSYS doesn't like passing flags of the form `/foo` as it thinks it's // a path and instead passes `C:\msys64\foo`, so convert all @@ -262,8 +266,8 @@ impl TestCx<'_> { cmd.env("IS_MSVC", "1") .env("IS_WINDOWS", "1") - .env("MSVC_LIB", format!("'{}' -nologo", lib.display())) - .env("MSVC_LIB_PATH", format!("{}", lib.display())) + .env("MSVC_LIB", format!("'{}' -nologo", lib)) + .env("MSVC_LIB_PATH", &lib) // Note: we diverge from legacy run_make and don't lump `CC` the compiler and // default flags together. .env("CC_DEFAULT_FLAGS", &cflags) diff --git a/src/tools/compiletest/src/runtest/ui.rs b/src/tools/compiletest/src/runtest/ui.rs index 974e5170465e..e87b037cd289 100644 --- a/src/tools/compiletest/src/runtest/ui.rs +++ b/src/tools/compiletest/src/runtest/ui.rs @@ -68,7 +68,7 @@ impl TestCx<'_> { { let mut coverage_file_path = self.config.build_test_suite_root.clone(); coverage_file_path.push("rustfix_missing_coverage.txt"); - debug!("coverage_file_path: {}", coverage_file_path.display()); + debug!("coverage_file_path: {}", coverage_file_path); let mut file = OpenOptions::new() .create(true) @@ -76,8 +76,8 @@ impl TestCx<'_> { .open(coverage_file_path.as_path()) .expect("could not create or open file"); - if let Err(e) = writeln!(file, "{}", self.testpaths.file.display()) { - panic!("couldn't write to {}: {e:?}", coverage_file_path.display()); + if let Err(e) = writeln!(file, "{}", self.testpaths.file) { + panic!("couldn't write to {}: {e:?}", coverage_file_path); } } } else if self.props.run_rustfix { @@ -119,7 +119,7 @@ impl TestCx<'_> { self.testpaths.relative_dir.join(self.testpaths.file.file_name().unwrap()); println!( "To only update this specific test, also pass `--test-args {}`", - relative_path_to_file.display(), + relative_path_to_file, ); self.fatal_proc_rec( &format!("{} errors occurred comparing output.", errors), @@ -211,8 +211,6 @@ impl TestCx<'_> { let crate_name = self.testpaths.file.file_stem().expect("test must have a file stem"); // crate name must be alphanumeric or `_`. - let crate_name = - crate_name.to_str().expect("crate name implies file name must be valid UTF-8"); // replace `a.foo` -> `a__foo` for crate name purposes. // replace `revision-name-with-dashes` -> `revision_name_with_underscore` let crate_name = crate_name.replace('.', "__"); diff --git a/src/tools/compiletest/src/tests.rs b/src/tools/compiletest/src/tests.rs index 43c6dc0a67e8..e3e4a81755d0 100644 --- a/src/tools/compiletest/src/tests.rs +++ b/src/tools/compiletest/src/tests.rs @@ -1,5 +1,3 @@ -use std::ffi::OsString; - use crate::debuggers::{extract_gdb_version, extract_lldb_version}; use crate::is_test; @@ -60,11 +58,11 @@ fn test_extract_lldb_version() { #[test] fn is_test_test() { - assert!(is_test(&OsString::from("a_test.rs"))); - assert!(!is_test(&OsString::from(".a_test.rs"))); - assert!(!is_test(&OsString::from("a_cat.gif"))); - assert!(!is_test(&OsString::from("#a_dog_gif"))); - assert!(!is_test(&OsString::from("~a_temp_file"))); + assert!(is_test("a_test.rs")); + assert!(!is_test(".a_test.rs")); + assert!(!is_test("a_cat.gif")); + assert!(!is_test("#a_dog_gif")); + assert!(!is_test("~a_temp_file")); } #[test] diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs index bff02f1db9f0..81f5679aead7 100644 --- a/src/tools/compiletest/src/util.rs +++ b/src/tools/compiletest/src/util.rs @@ -1,8 +1,7 @@ use std::env; -use std::ffi::OsStr; -use std::path::{Path, PathBuf}; use std::process::Command; +use camino::{Utf8Path, Utf8PathBuf}; use tracing::*; use crate::common::Config; @@ -34,21 +33,21 @@ pub fn logv(config: &Config, s: String) { } } -pub trait PathBufExt { +pub trait Utf8PathBufExt { /// Append an extension to the path, even if it already has one. - fn with_extra_extension>(&self, extension: S) -> PathBuf; + fn with_extra_extension(&self, extension: &str) -> Utf8PathBuf; } -impl PathBufExt for PathBuf { - fn with_extra_extension>(&self, extension: S) -> PathBuf { - if extension.as_ref().is_empty() { +impl Utf8PathBufExt for Utf8PathBuf { + fn with_extra_extension(&self, extension: &str) -> Utf8PathBuf { + if extension.is_empty() { self.clone() } else { - let mut fname = self.file_name().unwrap().to_os_string(); - if !extension.as_ref().to_str().unwrap().starts_with('.') { - fname.push("."); + let mut fname = self.file_name().unwrap().to_string(); + if !extension.starts_with('.') { + fname.push_str("."); } - fname.push(extension); + fname.push_str(extension); self.with_file_name(fname) } } @@ -71,22 +70,27 @@ pub fn dylib_env_var() -> &'static str { /// Adds a list of lookup paths to `cmd`'s dynamic library lookup path. /// If the dylib_path_var is already set for this cmd, the old value will be overwritten! -pub fn add_dylib_path(cmd: &mut Command, paths: impl Iterator>) { +pub fn add_dylib_path( + cmd: &mut Command, + paths: impl Iterator>, +) { let path_env = env::var_os(dylib_env_var()); let old_paths = path_env.as_ref().map(env::split_paths); let new_paths = paths.map(Into::into).chain(old_paths.into_iter().flatten()); cmd.env(dylib_env_var(), env::join_paths(new_paths).unwrap()); } -pub fn copy_dir_all(src: impl AsRef, dst: impl AsRef) -> std::io::Result<()> { - std::fs::create_dir_all(&dst)?; - for entry in std::fs::read_dir(src)? { +pub fn copy_dir_all(src: &Utf8Path, dst: &Utf8Path) -> std::io::Result<()> { + std::fs::create_dir_all(dst.as_std_path())?; + for entry in std::fs::read_dir(src.as_std_path())? { let entry = entry?; + let path = Utf8PathBuf::try_from(entry.path()).unwrap(); + let file_name = path.file_name().unwrap(); let ty = entry.file_type()?; if ty.is_dir() { - copy_dir_all(entry.path(), dst.as_ref().join(entry.file_name()))?; + copy_dir_all(&path, &dst.join(file_name))?; } else { - std::fs::copy(entry.path(), dst.as_ref().join(entry.file_name()))?; + std::fs::copy(path.as_std_path(), dst.join(file_name).as_std_path())?; } } Ok(()) diff --git a/src/tools/compiletest/src/util/tests.rs b/src/tools/compiletest/src/util/tests.rs index b09a183b14e6..5bcae0dcee14 100644 --- a/src/tools/compiletest/src/util/tests.rs +++ b/src/tools/compiletest/src/util/tests.rs @@ -3,12 +3,12 @@ use super::*; #[test] fn path_buf_with_extra_extension_test() { assert_eq!( - PathBuf::from("foo.rs.stderr"), - PathBuf::from("foo.rs").with_extra_extension("stderr") + Utf8PathBuf::from("foo.rs.stderr"), + Utf8PathBuf::from("foo.rs").with_extra_extension("stderr") ); assert_eq!( - PathBuf::from("foo.rs.stderr"), - PathBuf::from("foo.rs").with_extra_extension(".stderr") + Utf8PathBuf::from("foo.rs.stderr"), + Utf8PathBuf::from("foo.rs").with_extra_extension(".stderr") ); - assert_eq!(PathBuf::from("foo.rs"), PathBuf::from("foo.rs").with_extra_extension("")); + assert_eq!(Utf8PathBuf::from("foo.rs"), Utf8PathBuf::from("foo.rs").with_extra_extension("")); } From 957324b0a0f532dff28755155c5ce07a2ca04383 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Sat, 12 Apr 2025 12:32:27 +0800 Subject: [PATCH 409/606] rustdoc-gui-test: pass a `camino::Utf8PathBuf` to `compiletest` --- Cargo.lock | 1 + src/tools/rustdoc-gui-test/Cargo.toml | 1 + src/tools/rustdoc-gui-test/src/main.rs | 6 +++++- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index c80bfef485c2..b0d6aa5659a3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4672,6 +4672,7 @@ name = "rustdoc-gui-test" version = "0.1.0" dependencies = [ "build_helper", + "camino", "compiletest", "getopts", "walkdir", diff --git a/src/tools/rustdoc-gui-test/Cargo.toml b/src/tools/rustdoc-gui-test/Cargo.toml index f7384a98f856..8d958ac94f30 100644 --- a/src/tools/rustdoc-gui-test/Cargo.toml +++ b/src/tools/rustdoc-gui-test/Cargo.toml @@ -5,6 +5,7 @@ edition = "2021" [dependencies] build_helper = { path = "../../build_helper" } +camino = "1" compiletest = { path = "../compiletest" } getopts = "0.2" walkdir = "2" diff --git a/src/tools/rustdoc-gui-test/src/main.rs b/src/tools/rustdoc-gui-test/src/main.rs index f1c6e13d3ae8..addb0af4a541 100644 --- a/src/tools/rustdoc-gui-test/src/main.rs +++ b/src/tools/rustdoc-gui-test/src/main.rs @@ -118,7 +118,11 @@ If you want to install the `browser-ui-test` dependency, run `npm install browse ..Default::default() }; - let test_props = TestProps::from_file(&librs, None, &compiletest_c); + let test_props = TestProps::from_file( + &camino::Utf8PathBuf::try_from(librs).unwrap(), + None, + &compiletest_c, + ); if !test_props.compile_flags.is_empty() { cargo.env("RUSTDOCFLAGS", test_props.compile_flags.join(" ")); From 15a93c5683fa4a5c7a10b3e3385178ff0fd0fed6 Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Sun, 13 Apr 2025 21:15:15 +0800 Subject: [PATCH 410/606] std/thread: Use default stack size from menuconfig for NuttX * Update comments to clarify the usage of zero as an indication for default stack size configuration * Adjust conditional compilation to reflect the changes in stack size handling for the NuttX platform This change improves clarity and consistency in stack size configuration across platforms. Signed-off-by: Huang Qi --- library/std/src/sys/pal/unix/thread.rs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs index 9078dd1c2316..4f1517b7ef42 100644 --- a/library/std/src/sys/pal/unix/thread.rs +++ b/library/std/src/sys/pal/unix/thread.rs @@ -8,14 +8,19 @@ use crate::sys::weak::weak; use crate::sys::{os, stack_overflow}; use crate::time::Duration; use crate::{cmp, io, ptr}; -#[cfg(not(any(target_os = "l4re", target_os = "vxworks", target_os = "espidf")))] +#[cfg(not(any( + target_os = "l4re", + target_os = "vxworks", + target_os = "espidf", + target_os = "nuttx" +)))] pub const DEFAULT_MIN_STACK_SIZE: usize = 2 * 1024 * 1024; #[cfg(target_os = "l4re")] pub const DEFAULT_MIN_STACK_SIZE: usize = 1024 * 1024; #[cfg(target_os = "vxworks")] pub const DEFAULT_MIN_STACK_SIZE: usize = 256 * 1024; -#[cfg(target_os = "espidf")] -pub const DEFAULT_MIN_STACK_SIZE: usize = 0; // 0 indicates that the stack size configured in the ESP-IDF menuconfig system should be used +#[cfg(any(target_os = "espidf", target_os = "nuttx"))] +pub const DEFAULT_MIN_STACK_SIZE: usize = 0; // 0 indicates that the stack size configured in the ESP-IDF/NuttX menuconfig system should be used #[cfg(target_os = "fuchsia")] mod zircon { @@ -52,10 +57,10 @@ impl Thread { let mut attr: mem::MaybeUninit = mem::MaybeUninit::uninit(); assert_eq!(libc::pthread_attr_init(attr.as_mut_ptr()), 0); - #[cfg(target_os = "espidf")] + #[cfg(any(target_os = "espidf", target_os = "nuttx"))] if stack > 0 { // Only set the stack if a non-zero value is passed - // 0 is used as an indication that the default stack size configured in the ESP-IDF menuconfig system should be used + // 0 is used as an indication that the default stack size configured in the ESP-IDF/NuttX menuconfig system should be used assert_eq!( libc::pthread_attr_setstacksize( attr.as_mut_ptr(), @@ -65,7 +70,7 @@ impl Thread { ); } - #[cfg(not(target_os = "espidf"))] + #[cfg(not(any(target_os = "espidf", target_os = "nuttx")))] { let stack_size = cmp::max(stack, min_stack_size(attr.as_ptr())); From a404015775276f2e21e16c69fab36cc8228d51f6 Mon Sep 17 00:00:00 2001 From: Ayush Singh Date: Tue, 8 Apr 2025 12:28:42 +0530 Subject: [PATCH 411/606] std: sys: process: uefi: Use NULL stdin by default According to the docs in `Command::output`: > By default, stdout and stderr are captured (and used to provide the resulting output). Stdin is not inherited from the parent and any attempt by the child process to read from the stdin stream will result in the stream immediately closing. This was being violated by UEFI which was inheriting stdin by default. While the docs don't explicitly state that the default should be NULL, the behaviour seems like reading from NULL. UEFI however, has a bit of a problem. The `EFI_SIMPLE_TEXT_INPUT_PROTOCOL` only provides support for reading 1 key press. This means that you either get an error, or it is assumed that the keypress was read successfully. So there is no way to have a successful read of length 0. Currently, I am returning UNSUPPORTED error when trying to read from NULL stdin. On linux however, you will get a read of length 0 for Null stdin. One possible way to get around this is to translate one of the UEFI errors to a read 0 (Maybe unsupported?). It is also possible to have a non-standard error code, but well, not sure if we go that route. Alternatively, if meaning of Stdio::Null is platform dependent, it should be fine to keep the current behaviour of returning an error. Signed-off-by: Ayush Singh --- library/std/src/sys/process/uefi.rs | 112 +++++++++++++++++++++++++++- 1 file changed, 109 insertions(+), 3 deletions(-) diff --git a/library/std/src/sys/process/uefi.rs b/library/std/src/sys/process/uefi.rs index b46418ae9bb6..fb5aa5ca2669 100644 --- a/library/std/src/sys/process/uefi.rs +++ b/library/std/src/sys/process/uefi.rs @@ -1,4 +1,4 @@ -use r_efi::protocols::simple_text_output; +use r_efi::protocols::{simple_text_input, simple_text_output}; use crate::collections::BTreeMap; pub use crate::ffi::OsString as EnvKey; @@ -122,6 +122,22 @@ impl Command { } } + fn create_stdin( + s: Stdio, + ) -> io::Result>> { + match s { + Stdio::Null => unsafe { + helpers::OwnedProtocol::create( + uefi_command_internal::InputProtocol::null(), + simple_text_input::PROTOCOL_GUID, + ) + } + .map(Some), + Stdio::Inherit => Ok(None), + Stdio::MakePipe => unsupported(), + } + } + pub fn output(&mut self) -> io::Result<(ExitStatus, Vec, Vec)> { let mut cmd = uefi_command_internal::Image::load_image(&self.prog)?; @@ -149,6 +165,14 @@ impl Command { cmd.stderr_inherit() }; + // Setup Stdin + let stdin = Self::create_stdin(Stdio::Null)?; + if let Some(con) = stdin { + cmd.stdin_init(con) + } else { + cmd.stdin_inherit() + }; + let env = env_changes(&self.env); // Set any new vars @@ -334,7 +358,7 @@ impl<'a> fmt::Debug for CommandArgs<'a> { #[allow(dead_code)] mod uefi_command_internal { - use r_efi::protocols::{loaded_image, simple_text_output}; + use r_efi::protocols::{loaded_image, simple_text_input, simple_text_output}; use crate::ffi::{OsStr, OsString}; use crate::io::{self, const_error}; @@ -350,6 +374,7 @@ mod uefi_command_internal { handle: NonNull, stdout: Option>, stderr: Option>, + stdin: Option>, st: OwnedTable, args: Option<(*mut u16, usize)>, } @@ -384,7 +409,14 @@ mod uefi_command_internal { helpers::open_protocol(child_handle, loaded_image::PROTOCOL_GUID).unwrap(); let st = OwnedTable::from_table(unsafe { (*loaded_image.as_ptr()).system_table }); - Ok(Self { handle: child_handle, stdout: None, stderr: None, st, args: None }) + Ok(Self { + handle: child_handle, + stdout: None, + stderr: None, + stdin: None, + st, + args: None, + }) } } @@ -445,6 +477,17 @@ mod uefi_command_internal { } } + fn set_stdin( + &mut self, + handle: r_efi::efi::Handle, + protocol: *mut simple_text_input::Protocol, + ) { + unsafe { + (*self.st.as_mut_ptr()).console_in_handle = handle; + (*self.st.as_mut_ptr()).con_in = protocol; + } + } + pub fn stdout_init(&mut self, protocol: helpers::OwnedProtocol) { self.set_stdout( protocol.handle().as_ptr(), @@ -471,6 +514,19 @@ mod uefi_command_internal { unsafe { self.set_stderr((*st.as_ptr()).standard_error_handle, (*st.as_ptr()).std_err) } } + pub(crate) fn stdin_init(&mut self, protocol: helpers::OwnedProtocol) { + self.set_stdin( + protocol.handle().as_ptr(), + protocol.as_ref() as *const InputProtocol as *mut simple_text_input::Protocol, + ); + self.stdin = Some(protocol); + } + + pub(crate) fn stdin_inherit(&mut self) { + let st: NonNull = system_table().cast(); + unsafe { self.set_stdin((*st.as_ptr()).console_in_handle, (*st.as_ptr()).con_in) } + } + pub fn stderr(&self) -> io::Result> { match &self.stderr { Some(stderr) => stderr.as_ref().utf8(), @@ -722,6 +778,56 @@ mod uefi_command_internal { } } + #[repr(C)] + pub(crate) struct InputProtocol { + reset: simple_text_input::ProtocolReset, + read_key_stroke: simple_text_input::ProtocolReadKeyStroke, + wait_for_key: r_efi::efi::Event, + } + + impl InputProtocol { + pub(crate) fn null() -> Self { + let evt = helpers::OwnedEvent::new( + r_efi::efi::EVT_NOTIFY_WAIT, + r_efi::efi::TPL_CALLBACK, + Some(Self::empty_notify), + None, + ) + .unwrap(); + + Self { + reset: Self::null_reset, + read_key_stroke: Self::null_read_key, + wait_for_key: evt.into_raw(), + } + } + + extern "efiapi" fn null_reset( + _: *mut simple_text_input::Protocol, + _: r_efi::efi::Boolean, + ) -> r_efi::efi::Status { + r_efi::efi::Status::SUCCESS + } + + extern "efiapi" fn null_read_key( + _: *mut simple_text_input::Protocol, + _: *mut simple_text_input::InputKey, + ) -> r_efi::efi::Status { + r_efi::efi::Status::UNSUPPORTED + } + + extern "efiapi" fn empty_notify(_: r_efi::efi::Event, _: *mut crate::ffi::c_void) {} + } + + impl Drop for InputProtocol { + fn drop(&mut self) { + // Close wait_for_key + unsafe { + let _ = helpers::OwnedEvent::from_raw(self.wait_for_key); + } + } + } + pub fn create_args(prog: &OsStr, args: &[OsString]) -> Box<[u16]> { const QUOTE: u16 = 0x0022; const SPACE: u16 = 0x0020; From af25995d11f8630a071a7f4776f0798d22942a9f Mon Sep 17 00:00:00 2001 From: Ayush Singh Date: Sun, 13 Apr 2025 20:11:44 +0530 Subject: [PATCH 412/606] std: sys: stdio: uefi: Tread UNSUPPORTED Status as read(0) Allows implementing Stdio::Null for Command in a deterministic manner. Signed-off-by: Ayush Singh --- library/std/src/sys/stdio/uefi.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/library/std/src/sys/stdio/uefi.rs b/library/std/src/sys/stdio/uefi.rs index 257e321dd03d..ccd6bf658b0f 100644 --- a/library/std/src/sys/stdio/uefi.rs +++ b/library/std/src/sys/stdio/uefi.rs @@ -142,8 +142,12 @@ impl io::Write for Stderr { // UTF-16 character should occupy 4 bytes at most in UTF-8 pub const STDIN_BUF_SIZE: usize = 4; -pub fn is_ebadf(_err: &io::Error) -> bool { - false +pub fn is_ebadf(err: &io::Error) -> bool { + if let Some(x) = err.raw_os_error() { + r_efi::efi::Status::UNSUPPORTED.as_usize() == x + } else { + false + } } pub fn panic_output() -> Option { From d994fef7495ecbc1e18c95588253869f3a765edf Mon Sep 17 00:00:00 2001 From: Ayush Singh Date: Thu, 10 Apr 2025 10:40:50 +0530 Subject: [PATCH 413/606] std: sys: process: uefi: Allow specifying Stdin Stdio::MakePipe is not supported. For Stdio::Null, return UNSUPPORTED. This is treated as read(0). Additionally, have infinte loop on the notify function to prevent wait_for_key from returning. Signed-off-by: Ayush Singh --- library/std/src/sys/process/uefi.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/library/std/src/sys/process/uefi.rs b/library/std/src/sys/process/uefi.rs index fb5aa5ca2669..5f922292d054 100644 --- a/library/std/src/sys/process/uefi.rs +++ b/library/std/src/sys/process/uefi.rs @@ -23,6 +23,7 @@ pub struct Command { args: Vec, stdout: Option, stderr: Option, + stdin: Option, env: CommandEnv, } @@ -48,6 +49,7 @@ impl Command { args: Vec::new(), stdout: None, stderr: None, + stdin: None, env: Default::default(), } } @@ -64,8 +66,8 @@ impl Command { panic!("unsupported") } - pub fn stdin(&mut self, _stdin: Stdio) { - panic!("unsupported") + pub fn stdin(&mut self, stdin: Stdio) { + self.stdin = Some(stdin); } pub fn stdout(&mut self, stdout: Stdio) { @@ -166,7 +168,8 @@ impl Command { }; // Setup Stdin - let stdin = Self::create_stdin(Stdio::Null)?; + let stdin = self.stdin.unwrap_or(Stdio::Null); + let stdin = Self::create_stdin(stdin)?; if let Some(con) = stdin { cmd.stdin_init(con) } else { From 93bee0789a45ea7d5d65bb9301c4ad5ece3abeb2 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 12 Apr 2025 22:40:34 +0300 Subject: [PATCH 414/606] UI tests: migrate remaining compile time `error-pattern`s to line annotations when possible. --- tests/incremental/const-generic-type-cycle.rs | 5 +- tests/incremental/delayed_span_bug.rs | 3 +- tests/incremental/link_order/main.rs | 3 +- tests/rustdoc-ui/deprecated-attrs.rs | 1 - tests/rustdoc-ui/deprecated-attrs.stderr | 6 +- tests/rustdoc-ui/invalid-theme-name.rs | 2 +- .../ui-fulldeps/missing-rustc-driver-error.rs | 8 +- tests/ui/abi/fixed_x18.rs | 1 - tests/ui/associated-types/issue-36499.rs | 2 - tests/ui/associated-types/issue-36499.stderr | 2 +- tests/ui/check-cfg/cargo-feature.rs | 3 +- .../codegen/empty-static-libs-issue-108825.rs | 4 +- .../cfg-arg-invalid-1.rs | 6 +- .../cfg-arg-invalid-2.rs | 6 +- .../cfg-arg-invalid-4.rs | 6 +- .../cfg-arg-invalid-6.rs | 6 +- .../cfg-arg-invalid-8.rs | 6 +- .../cfg-arg-invalid-9.rs | 6 +- .../cfg-empty-codemap.rs | 6 +- tests/ui/consts/miri_unleashed/drop.rs | 3 +- tests/ui/consts/miri_unleashed/drop.stderr | 4 +- tests/ui/debuginfo/dwarf-versions.rs | 1 - .../error-codes/E0152-duplicate-lang-items.rs | 4 +- .../E0152-duplicate-lang-items.stderr | 3 +- tests/ui/error-codes/E0602.rs | 6 +- .../extern-flag/invalid-crate-name-dashed.rs | 2 +- tests/ui/issues/issue-37131.rs | 3 +- .../layout/unknown-when-no-type-parameter.rs | 4 +- .../unknown-when-no-type-parameter.stderr | 2 +- .../suggest-libname-only-1.rs | 3 +- .../suggest-libname-only-1.stderr | 2 +- .../suggest-libname-only-2.rs | 3 +- .../suggest-libname-only-2.stderr | 2 +- tests/ui/lint/cli-unknown-force-warn.rs | 6 +- tests/ui/lint/lint-removed-cmdline-deny.rs | 6 +- .../ui/lint/lint-removed-cmdline-deny.stderr | 4 +- tests/ui/lint/lint-removed-cmdline.rs | 6 +- tests/ui/lint/lint-removed-cmdline.stderr | 4 +- tests/ui/lint/lint-renamed-cmdline-deny.rs | 9 +- .../ui/lint/lint-renamed-cmdline-deny.stderr | 4 +- tests/ui/lint/lint-renamed-cmdline.rs | 6 +- tests/ui/lint/lint-renamed-cmdline.stderr | 4 +- .../ui/lint/lint-unknown-lint-cmdline-deny.rs | 11 +- tests/ui/lint/lint-unknown-lint-cmdline.rs | 11 +- tests/ui/lint/non-local-defs/cargo-update.rs | 3 +- tests/ui/missing/missing-return.rs | 5 +- tests/ui/missing/missing-return.stderr | 2 +- tests/ui/nested-ty-params.rs | 1 - tests/ui/nested-ty-params.stderr | 4 +- tests/ui/no_std/no-std-no-start-binary.rs | 1 - tests/ui/optimization-remark.rs | 5 +- .../packed/packed-struct-generic-transmute.rs | 2 - .../packed-struct-generic-transmute.stderr | 2 +- tests/ui/packed/packed-struct-transmute.rs | 1 - .../ui/packed/packed-struct-transmute.stderr | 2 +- tests/ui/parser/utf16-be-without-bom.rs | Bin 202 -> 183 bytes tests/ui/parser/utf16-le-without-bom.rs | Bin 203 -> 184 bytes tests/ui/print-request/print-lints-help.rs | 5 +- tests/ui/proc-macro/inner-attrs.rs | 9 +- tests/ui/proc-macro/inner-attrs.stderr | 8 +- tests/ui/proc-macro/inner-attrs.stdout | 806 +++++++++--------- ...region-invariant-static-error-reporting.rs | 3 +- .../forbidden-target-feature-flag-disable.rs | 2 +- .../tied-features-no-implication-1.rs | 2 - .../deny-unstable-lint-command-line.rs | 3 +- ...warn-unknown-unstable-lint-command-line.rs | 3 +- 66 files changed, 546 insertions(+), 518 deletions(-) diff --git a/tests/incremental/const-generic-type-cycle.rs b/tests/incremental/const-generic-type-cycle.rs index cd0437f7ef66..40a40ebd13fe 100644 --- a/tests/incremental/const-generic-type-cycle.rs +++ b/tests/incremental/const-generic-type-cycle.rs @@ -3,7 +3,6 @@ // //@ compile-flags: -Zincremental-ignore-spans //@ revisions: cpass cfail -//@ error-pattern: cycle detected when computing type of `Bar::N` #![feature(trait_alias)] #![crate_type="lib"] @@ -13,5 +12,9 @@ trait Bar {} #[cfg(cfail)] trait Bar {} +//[cfail]~^ ERROR cycle detected when computing type of `Bar::N` +//[cfail]~| ERROR cycle detected when computing type of `Bar::N` +//[cfail]~| ERROR cycle detected when computing type of `Bar::N` +//[cfail]~| ERROR `(dyn Bar<{ 2 + 1 }> + 'static)` is forbidden as the type of a const generic parameter trait BB = Bar<{ 2 + 1 }>; diff --git a/tests/incremental/delayed_span_bug.rs b/tests/incremental/delayed_span_bug.rs index 1534aca5dddf..7b409db2e18e 100644 --- a/tests/incremental/delayed_span_bug.rs +++ b/tests/incremental/delayed_span_bug.rs @@ -1,8 +1,7 @@ //@ revisions: cfail1 cfail2 //@ should-ice -//@ error-pattern: delayed bug triggered by #[rustc_delayed_bug_from_inside_query] #![feature(rustc_attrs)] #[rustc_delayed_bug_from_inside_query] -fn main() {} +fn main() {} //~ ERROR delayed bug triggered by #[rustc_delayed_bug_from_inside_query] diff --git a/tests/incremental/link_order/main.rs b/tests/incremental/link_order/main.rs index 847a47a75598..20931e25dd4b 100644 --- a/tests/incremental/link_order/main.rs +++ b/tests/incremental/link_order/main.rs @@ -1,5 +1,4 @@ //@ aux-build:my_lib.rs -//@ error-pattern: error: linking with //@ revisions:cfail1 cfail2 //@ compile-flags:-Z query-dep-graph @@ -10,3 +9,5 @@ extern crate my_lib; fn main() {} + +//~? ERROR linking with diff --git a/tests/rustdoc-ui/deprecated-attrs.rs b/tests/rustdoc-ui/deprecated-attrs.rs index 0ae65a5eaf7c..dcf8a52de41d 100644 --- a/tests/rustdoc-ui/deprecated-attrs.rs +++ b/tests/rustdoc-ui/deprecated-attrs.rs @@ -1,5 +1,4 @@ //@ compile-flags: --passes unknown-pass -//@ error-pattern: the `passes` flag no longer functions #![doc(no_default_passes)] //~^ ERROR unknown `doc` attribute `no_default_passes` diff --git a/tests/rustdoc-ui/deprecated-attrs.stderr b/tests/rustdoc-ui/deprecated-attrs.stderr index a30523e73297..3e9820522338 100644 --- a/tests/rustdoc-ui/deprecated-attrs.stderr +++ b/tests/rustdoc-ui/deprecated-attrs.stderr @@ -4,7 +4,7 @@ warning: the `passes` flag no longer functions = help: you may want to use --document-private-items error: unknown `doc` attribute `no_default_passes` - --> $DIR/deprecated-attrs.rs:4:8 + --> $DIR/deprecated-attrs.rs:3:8 | LL | #![doc(no_default_passes)] | ^^^^^^^^^^^^^^^^^ no longer functions @@ -15,7 +15,7 @@ LL | #![doc(no_default_passes)] = note: `#[deny(invalid_doc_attributes)]` on by default error: unknown `doc` attribute `passes` - --> $DIR/deprecated-attrs.rs:11:8 + --> $DIR/deprecated-attrs.rs:10:8 | LL | #![doc(passes = "collapse-docs unindent-comments")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no longer functions @@ -25,7 +25,7 @@ LL | #![doc(passes = "collapse-docs unindent-comments")] = note: `doc(passes)` is now a no-op error: unknown `doc` attribute `plugins` - --> $DIR/deprecated-attrs.rs:17:8 + --> $DIR/deprecated-attrs.rs:16:8 | LL | #![doc(plugins = "xxx")] | ^^^^^^^^^^^^^^^ no longer functions diff --git a/tests/rustdoc-ui/invalid-theme-name.rs b/tests/rustdoc-ui/invalid-theme-name.rs index 7f1d191c89de..22b5e616a3d4 100644 --- a/tests/rustdoc-ui/invalid-theme-name.rs +++ b/tests/rustdoc-ui/invalid-theme-name.rs @@ -1,4 +1,4 @@ //@ compile-flags:--theme {{src-base}}/invalid-theme-name.rs -//@ error-pattern: must have a .css extension //~? ERROR invalid argument: "$DIR/invalid-theme-name.rs" +//~? HELP must have a .css extension diff --git a/tests/ui-fulldeps/missing-rustc-driver-error.rs b/tests/ui-fulldeps/missing-rustc-driver-error.rs index d582efada908..c6dff2d99dde 100644 --- a/tests/ui-fulldeps/missing-rustc-driver-error.rs +++ b/tests/ui-fulldeps/missing-rustc-driver-error.rs @@ -1,11 +1,15 @@ // Test that we get the following hint when trying to use a compiler crate without rustc_driver. -//@ error-pattern: try adding `extern crate rustc_driver;` at the top level of this crate -//@ compile-flags: --emit link --error-format=human +//@ compile-flags: --emit link //@ normalize-stderr: ".*crate .* required.*\n\n" -> "" //@ normalize-stderr: "aborting due to [0-9]+" -> "aborting due to NUMBER" +//@ dont-require-annotations: ERROR #![feature(rustc_private)] extern crate rustc_serialize; fn main() {} + +//~? HELP try adding `extern crate rustc_driver;` at the top level of this crate +//~? HELP try adding `extern crate rustc_driver;` at the top level of this crate +//~? HELP try adding `extern crate rustc_driver;` at the top level of this crate diff --git a/tests/ui/abi/fixed_x18.rs b/tests/ui/abi/fixed_x18.rs index d373468f68fe..d64b845e5bd1 100644 --- a/tests/ui/abi/fixed_x18.rs +++ b/tests/ui/abi/fixed_x18.rs @@ -2,7 +2,6 @@ // Behavior on aarch64 is tested by tests/codegen/fixed-x18.rs. // //@ revisions: x64 i686 arm riscv32 riscv64 -//@ error-pattern: the `-Zfixed-x18` flag is not supported //@ dont-check-compiler-stderr // //@ compile-flags: -Zfixed-x18 diff --git a/tests/ui/associated-types/issue-36499.rs b/tests/ui/associated-types/issue-36499.rs index 606918b40b70..941b1aaa0d54 100644 --- a/tests/ui/associated-types/issue-36499.rs +++ b/tests/ui/associated-types/issue-36499.rs @@ -1,5 +1,3 @@ -//@ error-pattern: aborting due to 1 previous error - fn main() { 2 + +2; //~ ERROR leading `+` is not supported } diff --git a/tests/ui/associated-types/issue-36499.stderr b/tests/ui/associated-types/issue-36499.stderr index dd91bac81586..aebf0faae2dc 100644 --- a/tests/ui/associated-types/issue-36499.stderr +++ b/tests/ui/associated-types/issue-36499.stderr @@ -1,5 +1,5 @@ error: leading `+` is not supported - --> $DIR/issue-36499.rs:4:9 + --> $DIR/issue-36499.rs:2:9 | LL | 2 + +2; | ^ unexpected `+` diff --git a/tests/ui/check-cfg/cargo-feature.rs b/tests/ui/check-cfg/cargo-feature.rs index a9380ddae1a9..a02b0437057f 100644 --- a/tests/ui/check-cfg/cargo-feature.rs +++ b/tests/ui/check-cfg/cargo-feature.rs @@ -10,7 +10,7 @@ //@ [none]compile-flags: --check-cfg=cfg(feature,values()) //@ [some]compile-flags: --check-cfg=cfg(feature,values("bitcode")) //@ [some]compile-flags: --check-cfg=cfg(CONFIG_NVME,values("y")) -//@ [none]error-pattern:Cargo.toml +//@ dont-require-annotations: HELP #[cfg(feature = "serde")] //~^ WARNING unexpected `cfg` condition value @@ -27,6 +27,7 @@ fn tokio() {} #[cfg(CONFIG_NVME = "m")] //[none]~^ WARNING unexpected `cfg` condition name //[some]~^^ WARNING unexpected `cfg` condition value +//[none]~| HELP Cargo.toml fn tokio() {} fn main() {} diff --git a/tests/ui/codegen/empty-static-libs-issue-108825.rs b/tests/ui/codegen/empty-static-libs-issue-108825.rs index 46bd6d6b2da4..4c644be0954e 100644 --- a/tests/ui/codegen/empty-static-libs-issue-108825.rs +++ b/tests/ui/codegen/empty-static-libs-issue-108825.rs @@ -3,7 +3,6 @@ //@ compile-flags: -Cpanic=abort --print=native-static-libs //@ build-pass -//@ error-pattern: note: native-static-libs: //@ dont-check-compiler-stderr (libcore links `/defaultlib:msvcrt` or `/defaultlib:libcmt` on MSVC) //@ ignore-pass (the note is emitted later in the compilation pipeline, needs build) @@ -14,3 +13,6 @@ fn panic(_info: &core::panic::PanicInfo) -> ! { loop {} } + +//~? NOTE native-static-libs: +//~? NOTE Link against the following native artifacts when linking against this static library diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-1.rs b/tests/ui/conditional-compilation/cfg-arg-invalid-1.rs index cd181f4a49f6..28d2d266b623 100644 --- a/tests/ui/conditional-compilation/cfg-arg-invalid-1.rs +++ b/tests/ui/conditional-compilation/cfg-arg-invalid-1.rs @@ -1,3 +1,5 @@ -//@ compile-flags: --error-format=human --cfg a(b=c) -//@ error-pattern: invalid `--cfg` argument: `a(b=c)` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\") +//@ compile-flags: --cfg a(b=c) + fn main() {} + +//~? ERROR invalid `--cfg` argument: `a(b=c)` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\") diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-2.rs b/tests/ui/conditional-compilation/cfg-arg-invalid-2.rs index a0c16bd1f80a..a46022602e27 100644 --- a/tests/ui/conditional-compilation/cfg-arg-invalid-2.rs +++ b/tests/ui/conditional-compilation/cfg-arg-invalid-2.rs @@ -1,3 +1,5 @@ -//@ compile-flags: --error-format=human --cfg a{b} -//@ error-pattern: invalid `--cfg` argument: `a{b}` (expected `key` or `key="value"`) +//@ compile-flags: --cfg a{b} + fn main() {} + +//~? ERROR invalid `--cfg` argument: `a{b}` (expected `key` or `key="value"`) diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-4.rs b/tests/ui/conditional-compilation/cfg-arg-invalid-4.rs index 30402d51852f..ba34708c171b 100644 --- a/tests/ui/conditional-compilation/cfg-arg-invalid-4.rs +++ b/tests/ui/conditional-compilation/cfg-arg-invalid-4.rs @@ -1,3 +1,5 @@ -//@ compile-flags: --error-format=human --cfg a(b) -//@ error-pattern: invalid `--cfg` argument: `a(b)` (expected `key` or `key="value"`) +//@ compile-flags: --cfg a(b) + fn main() {} + +//~? ERROR invalid `--cfg` argument: `a(b)` (expected `key` or `key="value"`) diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-6.rs b/tests/ui/conditional-compilation/cfg-arg-invalid-6.rs index e0ce66eab877..2c2fc105958a 100644 --- a/tests/ui/conditional-compilation/cfg-arg-invalid-6.rs +++ b/tests/ui/conditional-compilation/cfg-arg-invalid-6.rs @@ -1,3 +1,5 @@ -//@ compile-flags: --error-format=human --cfg a{ -//@ error-pattern: invalid `--cfg` argument: `a{` (expected `key` or `key="value"`) +//@ compile-flags: --cfg a{ + fn main() {} + +//~? ERROR invalid `--cfg` argument: `a{` (expected `key` or `key="value"`) diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-8.rs b/tests/ui/conditional-compilation/cfg-arg-invalid-8.rs index 33f8da25830e..c9185fc7b259 100644 --- a/tests/ui/conditional-compilation/cfg-arg-invalid-8.rs +++ b/tests/ui/conditional-compilation/cfg-arg-invalid-8.rs @@ -1,3 +1,5 @@ -//@ compile-flags: --error-format=human --cfg ) -//@ error-pattern: invalid `--cfg` argument: `)` (expected `key` or `key="value"`) +//@ compile-flags: --cfg ) + fn main() {} + +//~? ERROR invalid `--cfg` argument: `)` (expected `key` or `key="value"`) diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-9.rs b/tests/ui/conditional-compilation/cfg-arg-invalid-9.rs index 8ab3b101da79..8d07165dfae4 100644 --- a/tests/ui/conditional-compilation/cfg-arg-invalid-9.rs +++ b/tests/ui/conditional-compilation/cfg-arg-invalid-9.rs @@ -1,4 +1,6 @@ // Test for missing quotes around value, issue #66450. -//@ compile-flags: --error-format=human --cfg key=value -//@ error-pattern: invalid `--cfg` argument: `key=value` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\") +//@ compile-flags: --cfg key=value + fn main() {} + +//~? ERROR invalid `--cfg` argument: `key=value` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\") diff --git a/tests/ui/conditional-compilation/cfg-empty-codemap.rs b/tests/ui/conditional-compilation/cfg-empty-codemap.rs index d8fc02777595..9f7ef1bcf9aa 100644 --- a/tests/ui/conditional-compilation/cfg-empty-codemap.rs +++ b/tests/ui/conditional-compilation/cfg-empty-codemap.rs @@ -1,8 +1,8 @@ // Tests that empty source_maps don't ICE (#23301) -//@ compile-flags: --error-format=human --cfg "" - -//@ error-pattern: invalid `--cfg` argument: `""` (expected `key` or `key="value"`) +//@ compile-flags: --cfg "" pub fn main() { } + +//~? ERROR invalid `--cfg` argument: `""` (expected `key` or `key="value"`) diff --git a/tests/ui/consts/miri_unleashed/drop.rs b/tests/ui/consts/miri_unleashed/drop.rs index 17d089222d96..190072d9c206 100644 --- a/tests/ui/consts/miri_unleashed/drop.rs +++ b/tests/ui/consts/miri_unleashed/drop.rs @@ -1,5 +1,4 @@ //@ compile-flags: -Zunleash-the-miri-inside-of-you -//@ error-pattern: calling non-const function ` as Drop>::drop` use std::mem::ManuallyDrop; @@ -15,5 +14,7 @@ static TEST_OK: () = { static TEST_BAD: () = { let _v: Vec = Vec::new(); }; //~ ERROR could not evaluate static initializer + //~| NOTE calling non-const function ` as Drop>::drop` + //~| NOTE inside `std::ptr::drop_in_place::> - shim(Some(Vec))` //~? WARN skipping const checks diff --git a/tests/ui/consts/miri_unleashed/drop.stderr b/tests/ui/consts/miri_unleashed/drop.stderr index 40a29d5a819a..f9ff5491ea6c 100644 --- a/tests/ui/consts/miri_unleashed/drop.stderr +++ b/tests/ui/consts/miri_unleashed/drop.stderr @@ -1,5 +1,5 @@ error[E0080]: could not evaluate static initializer - --> $DIR/drop.rs:17:1 + --> $DIR/drop.rs:16:1 | LL | }; | ^ calling non-const function ` as Drop>::drop` @@ -10,7 +10,7 @@ note: inside `std::ptr::drop_in_place::> - shim(Some(Vec))` warning: skipping const checks | help: skipping check that does not even have a feature gate - --> $DIR/drop.rs:16:9 + --> $DIR/drop.rs:15:9 | LL | let _v: Vec = Vec::new(); | ^^ diff --git a/tests/ui/debuginfo/dwarf-versions.rs b/tests/ui/debuginfo/dwarf-versions.rs index 6030b2fcf3cd..bb18cadce435 100644 --- a/tests/ui/debuginfo/dwarf-versions.rs +++ b/tests/ui/debuginfo/dwarf-versions.rs @@ -6,7 +6,6 @@ //@[zero] compile-flags: -Zdwarf-version=0 //@[one] compile-flags: -Zdwarf-version=1 -//@[one] error-pattern: requested DWARF version 1 is not supported //@[two] compile-flags: -Zdwarf-version=2 //@[two] check-pass diff --git a/tests/ui/error-codes/E0152-duplicate-lang-items.rs b/tests/ui/error-codes/E0152-duplicate-lang-items.rs index 089810b1ad24..f707b72f9b2b 100644 --- a/tests/ui/error-codes/E0152-duplicate-lang-items.rs +++ b/tests/ui/error-codes/E0152-duplicate-lang-items.rs @@ -3,8 +3,9 @@ //! //! Issue: -//@ error-pattern: first defined in crate `std` //@ normalize-stderr: "loaded from .*libstd-.*.rlib" -> "loaded from SYSROOT/libstd-*.rlib" +//@ dont-require-annotations: NOTE + #![feature(lang_items)] extern crate core; @@ -14,6 +15,7 @@ use core::panic::PanicInfo; #[lang = "panic_impl"] fn panic_impl(info: &PanicInfo) -> ! { //~^ ERROR: found duplicate lang item `panic_impl` + //~| NOTE first defined in crate `std` loop {} } diff --git a/tests/ui/error-codes/E0152-duplicate-lang-items.stderr b/tests/ui/error-codes/E0152-duplicate-lang-items.stderr index 3c3d64322f3c..2fe0d18fc2f4 100644 --- a/tests/ui/error-codes/E0152-duplicate-lang-items.stderr +++ b/tests/ui/error-codes/E0152-duplicate-lang-items.stderr @@ -1,8 +1,9 @@ error[E0152]: found duplicate lang item `panic_impl` - --> $DIR/E0152-duplicate-lang-items.rs:15:1 + --> $DIR/E0152-duplicate-lang-items.rs:16:1 | LL | / fn panic_impl(info: &PanicInfo) -> ! { LL | | +LL | | LL | | loop {} LL | | } | |_^ diff --git a/tests/ui/error-codes/E0602.rs b/tests/ui/error-codes/E0602.rs index cba15bb92d45..381bd1ffb54c 100644 --- a/tests/ui/error-codes/E0602.rs +++ b/tests/ui/error-codes/E0602.rs @@ -1,11 +1,11 @@ //@ compile-flags:-D bogus //@ check-pass - -//@ error-pattern:requested on the command line with `-D bogus` -//@ error-pattern:`#[warn(unknown_lints)]` on by default +//@ dont-require-annotations: NOTE fn main() {} //~? WARN unknown lint: `bogus` //~? WARN unknown lint: `bogus` //~? WARN unknown lint: `bogus` +//~? NOTE requested on the command line with `-D bogus` +//~? NOTE `#[warn(unknown_lints)]` on by default diff --git a/tests/ui/extern-flag/invalid-crate-name-dashed.rs b/tests/ui/extern-flag/invalid-crate-name-dashed.rs index b336cc84569e..bbf473cc5142 100644 --- a/tests/ui/extern-flag/invalid-crate-name-dashed.rs +++ b/tests/ui/extern-flag/invalid-crate-name-dashed.rs @@ -1,5 +1,4 @@ //@ compile-flags: --extern=my-awesome-library=libawesome.rlib -//@ error-pattern: consider replacing the dashes with underscores: `my_awesome_library` // In a sense, this is a regression test for issue #113035. We no longer suggest // `pub use my-awesome-library::*;` (sic!) as we outright ban this crate name. @@ -9,3 +8,4 @@ pub use my_awesome_library::*; fn main() {} //~? ERROR crate name `my-awesome-library` passed to `--extern` is not a valid ASCII identifier +//~? HELP consider replacing the dashes with underscores: `my_awesome_library` diff --git a/tests/ui/issues/issue-37131.rs b/tests/ui/issues/issue-37131.rs index 16681ac21d11..e91c76e1390e 100644 --- a/tests/ui/issues/issue-37131.rs +++ b/tests/ui/issues/issue-37131.rs @@ -1,4 +1,6 @@ //~ ERROR can't find crate for `std` +//~| NOTE target may not be installed +//~| NOTE can't find crate // Tests that compiling for a target which is not installed will result in a helpful // error message. @@ -6,5 +8,4 @@ //@ ignore-arm //@ needs-llvm-components: arm -//@ error-pattern:target may not be installed fn main() { } diff --git a/tests/ui/layout/unknown-when-no-type-parameter.rs b/tests/ui/layout/unknown-when-no-type-parameter.rs index 500b7938eeb0..87f90aa438ab 100644 --- a/tests/ui/layout/unknown-when-no-type-parameter.rs +++ b/tests/ui/layout/unknown-when-no-type-parameter.rs @@ -1,13 +1,13 @@ #![feature(trivial_bounds)] -//@ error-pattern: the type `<() as Project>::Assoc` has an unknown layout - trait Project { type Assoc; } fn foo() where (): Project { [(); size_of::<<() as Project>::Assoc>()]; //~ ERROR evaluation of constant value failed + //~| NOTE the type `<() as Project>::Assoc` has an unknown layout + //~| NOTE inside `std::mem::size_of::<<() as Project>::Assoc>` } fn main() {} diff --git a/tests/ui/layout/unknown-when-no-type-parameter.stderr b/tests/ui/layout/unknown-when-no-type-parameter.stderr index a2dbb191ee27..35fbb11f156a 100644 --- a/tests/ui/layout/unknown-when-no-type-parameter.stderr +++ b/tests/ui/layout/unknown-when-no-type-parameter.stderr @@ -1,5 +1,5 @@ error[E0080]: evaluation of constant value failed - --> $DIR/unknown-when-no-type-parameter.rs:10:10 + --> $DIR/unknown-when-no-type-parameter.rs:8:10 | LL | [(); size_of::<<() as Project>::Assoc>()]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the type `<() as Project>::Assoc` has an unknown layout diff --git a/tests/ui/link-native-libs/suggest-libname-only-1.rs b/tests/ui/link-native-libs/suggest-libname-only-1.rs index 4ccfa086bde6..c69949d1fdb3 100644 --- a/tests/ui/link-native-libs/suggest-libname-only-1.rs +++ b/tests/ui/link-native-libs/suggest-libname-only-1.rs @@ -1,10 +1,11 @@ //@ build-fail //@ compile-flags: --crate-type rlib -//@ error-pattern: only provide the library name `foo`, not the full filename #[link(name = "libfoo.a", kind = "static")] extern { } //~ WARN extern declarations without an explicit ABI are deprecated + //~| HELP explicitly specify the "C" ABI pub fn main() { } //~? ERROR could not find native static library `libfoo.a` +//~? HELP only provide the library name `foo`, not the full filename diff --git a/tests/ui/link-native-libs/suggest-libname-only-1.stderr b/tests/ui/link-native-libs/suggest-libname-only-1.stderr index 85a3599e8dbd..0320294a8004 100644 --- a/tests/ui/link-native-libs/suggest-libname-only-1.stderr +++ b/tests/ui/link-native-libs/suggest-libname-only-1.stderr @@ -1,5 +1,5 @@ warning: extern declarations without an explicit ABI are deprecated - --> $DIR/suggest-libname-only-1.rs:6:1 + --> $DIR/suggest-libname-only-1.rs:5:1 | LL | extern { } | ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"` diff --git a/tests/ui/link-native-libs/suggest-libname-only-2.rs b/tests/ui/link-native-libs/suggest-libname-only-2.rs index c35b4a674b77..d5150c327cd5 100644 --- a/tests/ui/link-native-libs/suggest-libname-only-2.rs +++ b/tests/ui/link-native-libs/suggest-libname-only-2.rs @@ -1,10 +1,11 @@ //@ build-fail //@ compile-flags: --crate-type rlib -//@ error-pattern: only provide the library name `bar`, not the full filename #[link(name = "bar.lib", kind = "static")] extern { } //~ WARN extern declarations without an explicit ABI are deprecated + //~| HELP explicitly specify the "C" ABI pub fn main() { } //~? ERROR could not find native static library `bar.lib` +//~? HELP only provide the library name `bar`, not the full filename diff --git a/tests/ui/link-native-libs/suggest-libname-only-2.stderr b/tests/ui/link-native-libs/suggest-libname-only-2.stderr index d5c88931ad54..e492aea27b45 100644 --- a/tests/ui/link-native-libs/suggest-libname-only-2.stderr +++ b/tests/ui/link-native-libs/suggest-libname-only-2.stderr @@ -1,5 +1,5 @@ warning: extern declarations without an explicit ABI are deprecated - --> $DIR/suggest-libname-only-2.rs:6:1 + --> $DIR/suggest-libname-only-2.rs:5:1 | LL | extern { } | ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"` diff --git a/tests/ui/lint/cli-unknown-force-warn.rs b/tests/ui/lint/cli-unknown-force-warn.rs index 330d5570e21b..0c60f48c5142 100644 --- a/tests/ui/lint/cli-unknown-force-warn.rs +++ b/tests/ui/lint/cli-unknown-force-warn.rs @@ -3,12 +3,12 @@ //@ check-pass //@ compile-flags: --force-warn foo-qux - -//@ error-pattern: requested on the command line with `--force-warn foo_qux` -//@ error-pattern: `#[warn(unknown_lints)]` on by default +//@ dont-require-annotations: NOTE fn main() {} //~? WARN unknown lint: `foo_qux` //~? WARN unknown lint: `foo_qux` //~? WARN unknown lint: `foo_qux` +//~? NOTE requested on the command line with `--force-warn foo_qux` +//~? NOTE `#[warn(unknown_lints)]` on by default diff --git a/tests/ui/lint/lint-removed-cmdline-deny.rs b/tests/ui/lint/lint-removed-cmdline-deny.rs index 6616781d5cb7..83bbd248aa0c 100644 --- a/tests/ui/lint/lint-removed-cmdline-deny.rs +++ b/tests/ui/lint/lint-removed-cmdline-deny.rs @@ -2,9 +2,7 @@ // cc #30346 //@ compile-flags:-D renamed-and-removed-lints -D raw_pointer_derive - -//@ error-pattern:requested on the command line with `-D raw_pointer_derive` -//@ error-pattern:requested on the command line with `-D renamed-and-removed-lints` +//@ dont-require-annotations: NOTE #![warn(unused)] @@ -14,3 +12,5 @@ fn main() { let unused = (); } //~ ERROR unused variable: `unused` //~? ERROR lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok //~? ERROR lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok //~? ERROR lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok +//~? NOTE requested on the command line with `-D raw_pointer_derive` +//~? NOTE requested on the command line with `-D renamed-and-removed-lints` diff --git a/tests/ui/lint/lint-removed-cmdline-deny.stderr b/tests/ui/lint/lint-removed-cmdline-deny.stderr index 27a3504a16a7..2fb237339cd8 100644 --- a/tests/ui/lint/lint-removed-cmdline-deny.stderr +++ b/tests/ui/lint/lint-removed-cmdline-deny.stderr @@ -14,13 +14,13 @@ error: lint `raw_pointer_derive` has been removed: using derive with raw pointer = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: unused variable: `unused` - --> $DIR/lint-removed-cmdline-deny.rs:12:17 + --> $DIR/lint-removed-cmdline-deny.rs:10:17 | LL | fn main() { let unused = (); } | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused` | note: the lint level is defined here - --> $DIR/lint-removed-cmdline-deny.rs:11:8 + --> $DIR/lint-removed-cmdline-deny.rs:9:8 | LL | #[deny(warnings)] | ^^^^^^^^ diff --git a/tests/ui/lint/lint-removed-cmdline.rs b/tests/ui/lint/lint-removed-cmdline.rs index 4dde3dbc3817..f83747a3a6be 100644 --- a/tests/ui/lint/lint-removed-cmdline.rs +++ b/tests/ui/lint/lint-removed-cmdline.rs @@ -2,9 +2,7 @@ // cc #30346 //@ compile-flags:-D raw_pointer_derive - -//@ error-pattern:`#[warn(renamed_and_removed_lints)]` on by default -//@ error-pattern:requested on the command line with `-D raw_pointer_derive` +//@ dont-require-annotations: NOTE #![warn(unused)] @@ -14,3 +12,5 @@ fn main() { let unused = (); } //~ ERROR unused variable: `unused` //~? WARN lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok //~? WARN lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok //~? WARN lint `raw_pointer_derive` has been removed: using derive with raw pointers is ok +//~? NOTE `#[warn(renamed_and_removed_lints)]` on by default +//~? NOTE requested on the command line with `-D raw_pointer_derive` diff --git a/tests/ui/lint/lint-removed-cmdline.stderr b/tests/ui/lint/lint-removed-cmdline.stderr index 7994f9bcfd91..64e7c572ca73 100644 --- a/tests/ui/lint/lint-removed-cmdline.stderr +++ b/tests/ui/lint/lint-removed-cmdline.stderr @@ -14,13 +14,13 @@ warning: lint `raw_pointer_derive` has been removed: using derive with raw point = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: unused variable: `unused` - --> $DIR/lint-removed-cmdline.rs:12:17 + --> $DIR/lint-removed-cmdline.rs:10:17 | LL | fn main() { let unused = (); } | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused` | note: the lint level is defined here - --> $DIR/lint-removed-cmdline.rs:11:8 + --> $DIR/lint-removed-cmdline.rs:9:8 | LL | #[deny(warnings)] | ^^^^^^^^ diff --git a/tests/ui/lint/lint-renamed-cmdline-deny.rs b/tests/ui/lint/lint-renamed-cmdline-deny.rs index 0ea4ce408175..c8b035078154 100644 --- a/tests/ui/lint/lint-renamed-cmdline-deny.rs +++ b/tests/ui/lint/lint-renamed-cmdline-deny.rs @@ -1,8 +1,6 @@ //@ compile-flags:-D renamed-and-removed-lints -D bare_trait_object - -//@ error-pattern:use the new name `bare_trait_objects` -//@ error-pattern:requested on the command line with `-D bare_trait_object` -//@ error-pattern:requested on the command line with `-D renamed-and-removed-lints` +//@ dont-require-annotations: HELP +//@ dont-require-annotations: NOTE #[deny(unused)] fn main() { let unused = (); } //~ ERROR unused variable: `unused` @@ -10,3 +8,6 @@ fn main() { let unused = (); } //~ ERROR unused variable: `unused` //~? ERROR lint `bare_trait_object` has been renamed to `bare_trait_objects` //~? ERROR lint `bare_trait_object` has been renamed to `bare_trait_objects` //~? ERROR lint `bare_trait_object` has been renamed to `bare_trait_objects` +//~? HELP use the new name `bare_trait_objects` +//~? NOTE requested on the command line with `-D bare_trait_object` +//~? NOTE requested on the command line with `-D renamed-and-removed-lints` diff --git a/tests/ui/lint/lint-renamed-cmdline-deny.stderr b/tests/ui/lint/lint-renamed-cmdline-deny.stderr index a49cdc84f9e4..b42b82834c19 100644 --- a/tests/ui/lint/lint-renamed-cmdline-deny.stderr +++ b/tests/ui/lint/lint-renamed-cmdline-deny.stderr @@ -17,13 +17,13 @@ error: lint `bare_trait_object` has been renamed to `bare_trait_objects` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: unused variable: `unused` - --> $DIR/lint-renamed-cmdline-deny.rs:8:17 + --> $DIR/lint-renamed-cmdline-deny.rs:6:17 | LL | fn main() { let unused = (); } | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused` | note: the lint level is defined here - --> $DIR/lint-renamed-cmdline-deny.rs:7:8 + --> $DIR/lint-renamed-cmdline-deny.rs:5:8 | LL | #[deny(unused)] | ^^^^^^ diff --git a/tests/ui/lint/lint-renamed-cmdline.rs b/tests/ui/lint/lint-renamed-cmdline.rs index 45df7b6d640d..757cb514267c 100644 --- a/tests/ui/lint/lint-renamed-cmdline.rs +++ b/tests/ui/lint/lint-renamed-cmdline.rs @@ -1,7 +1,5 @@ //@ compile-flags:-D bare_trait_object - -//@ error-pattern:requested on the command line with `-D bare_trait_object` -//@ error-pattern:`#[warn(renamed_and_removed_lints)]` on by default +//@ dont-require-annotations: NOTE #[deny(unused)] fn main() { let unused = (); } //~ ERROR unused variable: `unused` @@ -9,3 +7,5 @@ fn main() { let unused = (); } //~ ERROR unused variable: `unused` //~? WARN lint `bare_trait_object` has been renamed to `bare_trait_objects` //~? WARN lint `bare_trait_object` has been renamed to `bare_trait_objects` //~? WARN lint `bare_trait_object` has been renamed to `bare_trait_objects` +//~? NOTE requested on the command line with `-D bare_trait_object` +//~? NOTE `#[warn(renamed_and_removed_lints)]` on by default diff --git a/tests/ui/lint/lint-renamed-cmdline.stderr b/tests/ui/lint/lint-renamed-cmdline.stderr index 901e7a642d1f..efd399e21694 100644 --- a/tests/ui/lint/lint-renamed-cmdline.stderr +++ b/tests/ui/lint/lint-renamed-cmdline.stderr @@ -17,13 +17,13 @@ warning: lint `bare_trait_object` has been renamed to `bare_trait_objects` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: unused variable: `unused` - --> $DIR/lint-renamed-cmdline.rs:7:17 + --> $DIR/lint-renamed-cmdline.rs:5:17 | LL | fn main() { let unused = (); } | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused` | note: the lint level is defined here - --> $DIR/lint-renamed-cmdline.rs:6:8 + --> $DIR/lint-renamed-cmdline.rs:4:8 | LL | #[deny(unused)] | ^^^^^^ diff --git a/tests/ui/lint/lint-unknown-lint-cmdline-deny.rs b/tests/ui/lint/lint-unknown-lint-cmdline-deny.rs index e2f7c73eacf0..ac001e1b6a04 100644 --- a/tests/ui/lint/lint-unknown-lint-cmdline-deny.rs +++ b/tests/ui/lint/lint-unknown-lint-cmdline-deny.rs @@ -1,9 +1,6 @@ //@ compile-flags:-D unknown-lints -D bogus -D dead_cod - -//@ error-pattern:requested on the command line with `-D bogus` -//@ error-pattern:requested on the command line with `-D dead_cod` -//@ error-pattern:requested on the command line with `-D unknown-lints` -//@ error-pattern:did you mean: `dead_code` +//@ dont-require-annotations: HELP +//@ dont-require-annotations: NOTE fn main() { } @@ -13,3 +10,7 @@ fn main() { } //~? ERROR unknown lint: `dead_cod` //~? ERROR unknown lint: `bogus` //~? ERROR unknown lint: `dead_cod` +//~? NOTE requested on the command line with `-D bogus` +//~? NOTE requested on the command line with `-D dead_cod` +//~? NOTE requested on the command line with `-D unknown-lints` +//~? HELP did you mean: `dead_code` diff --git a/tests/ui/lint/lint-unknown-lint-cmdline.rs b/tests/ui/lint/lint-unknown-lint-cmdline.rs index 931e945a1a32..7eb8c1f73142 100644 --- a/tests/ui/lint/lint-unknown-lint-cmdline.rs +++ b/tests/ui/lint/lint-unknown-lint-cmdline.rs @@ -1,10 +1,7 @@ //@ check-pass //@ compile-flags:-D bogus -D dead_cod - -//@ error-pattern:requested on the command line with `-D bogus` -//@ error-pattern:`#[warn(unknown_lints)]` on by default -//@ error-pattern:requested on the command line with `-D dead_cod` -//@ error-pattern:did you mean: `dead_code` +//@ dont-require-annotations: HELP +//@ dont-require-annotations: NOTE fn main() { } @@ -14,3 +11,7 @@ fn main() { } //~? WARN unknown lint: `dead_cod` //~? WARN unknown lint: `bogus` //~? WARN unknown lint: `dead_cod` +//~? NOTE requested on the command line with `-D bogus` +//~? NOTE `#[warn(unknown_lints)]` on by default +//~? NOTE requested on the command line with `-D dead_cod` +//~? HELP did you mean: `dead_code` diff --git a/tests/ui/lint/non-local-defs/cargo-update.rs b/tests/ui/lint/non-local-defs/cargo-update.rs index 8b8c15795d37..f778752b28af 100644 --- a/tests/ui/lint/non-local-defs/cargo-update.rs +++ b/tests/ui/lint/non-local-defs/cargo-update.rs @@ -8,7 +8,7 @@ // // and since we specifically want to check the presence // of the `cargo update` suggestion we assert it here. -//@ error-pattern: `cargo update -p non_local_macro` +//@ dont-require-annotations: NOTE extern crate non_local_macro; @@ -16,5 +16,6 @@ struct LocalStruct; non_local_macro::non_local_impl!(LocalStruct); //~^ WARN non-local `impl` definition +//~| NOTE `cargo update -p non_local_macro` fn main() {} diff --git a/tests/ui/missing/missing-return.rs b/tests/ui/missing/missing-return.rs index 5d9839a969c1..4d48e7c13e2c 100644 --- a/tests/ui/missing/missing-return.rs +++ b/tests/ui/missing/missing-return.rs @@ -1,5 +1,4 @@ -//@ error-pattern: return - fn f() -> isize { } //~ ERROR mismatched types - + //~| NOTE implicitly returns `()` as its body has no tail or `return` expression + //~| NOTE expected `isize`, found `()` fn main() { f(); } diff --git a/tests/ui/missing/missing-return.stderr b/tests/ui/missing/missing-return.stderr index 5f7fb504075c..b2d202b9b572 100644 --- a/tests/ui/missing/missing-return.stderr +++ b/tests/ui/missing/missing-return.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/missing-return.rs:3:11 + --> $DIR/missing-return.rs:1:11 | LL | fn f() -> isize { } | - ^^^^^ expected `isize`, found `()` diff --git a/tests/ui/nested-ty-params.rs b/tests/ui/nested-ty-params.rs index 866e6230f9ea..c00c3bc33723 100644 --- a/tests/ui/nested-ty-params.rs +++ b/tests/ui/nested-ty-params.rs @@ -1,4 +1,3 @@ -//@ error-pattern:can't use generic parameters from outer item fn hd(v: Vec ) -> U { fn hd1(w: [U]) -> U { return w[0]; } //~^ ERROR can't use generic parameters from outer item diff --git a/tests/ui/nested-ty-params.stderr b/tests/ui/nested-ty-params.stderr index a9cdec667199..7ca65b421b25 100644 --- a/tests/ui/nested-ty-params.stderr +++ b/tests/ui/nested-ty-params.stderr @@ -1,5 +1,5 @@ error[E0401]: can't use generic parameters from outer item - --> $DIR/nested-ty-params.rs:3:16 + --> $DIR/nested-ty-params.rs:2:16 | LL | fn hd(v: Vec ) -> U { | - type parameter from outer item @@ -9,7 +9,7 @@ LL | fn hd1(w: [U]) -> U { return w[0]; } | help: try introducing a local generic parameter here: `` error[E0401]: can't use generic parameters from outer item - --> $DIR/nested-ty-params.rs:3:23 + --> $DIR/nested-ty-params.rs:2:23 | LL | fn hd(v: Vec ) -> U { | - type parameter from outer item diff --git a/tests/ui/no_std/no-std-no-start-binary.rs b/tests/ui/no_std/no-std-no-start-binary.rs index df68b99346af..6853e2d4228f 100644 --- a/tests/ui/no_std/no-std-no-start-binary.rs +++ b/tests/ui/no_std/no-std-no-start-binary.rs @@ -1,5 +1,4 @@ //@ compile-flags: -Cpanic=abort --emit link -//@ error-pattern:using `fn main` requires the standard library // Make sure that we don't emit an error message mentioning internal lang items. diff --git a/tests/ui/optimization-remark.rs b/tests/ui/optimization-remark.rs index ebcf3b40ab25..165fc63c0076 100644 --- a/tests/ui/optimization-remark.rs +++ b/tests/ui/optimization-remark.rs @@ -12,9 +12,8 @@ // //@ [merge1] compile-flags: -Cremark=all -Cremark=giraffe //@ [merge2] compile-flags: -Cremark=inline -Cremark=giraffe -// -//@ error-pattern: inline (missed): 'f' not inlined into 'g' //@ dont-check-compiler-stderr +//@ dont-require-annotations: NOTE #[no_mangle] #[inline(never)] @@ -25,3 +24,5 @@ pub fn f() { pub fn g() { f(); } + +//~? NOTE inline (missed): 'f' not inlined into 'g' diff --git a/tests/ui/packed/packed-struct-generic-transmute.rs b/tests/ui/packed/packed-struct-generic-transmute.rs index 17e72bebc7dc..66972633d800 100644 --- a/tests/ui/packed/packed-struct-generic-transmute.rs +++ b/tests/ui/packed/packed-struct-generic-transmute.rs @@ -3,8 +3,6 @@ // the error points to the start of the file, not the line with the // transmute -//@ error-pattern: cannot transmute between types of different sizes, or dependently-sized types - use std::mem; #[repr(packed)] diff --git a/tests/ui/packed/packed-struct-generic-transmute.stderr b/tests/ui/packed/packed-struct-generic-transmute.stderr index e91f49884298..983742b78be1 100644 --- a/tests/ui/packed/packed-struct-generic-transmute.stderr +++ b/tests/ui/packed/packed-struct-generic-transmute.stderr @@ -1,5 +1,5 @@ error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/packed-struct-generic-transmute.rs:24:38 + --> $DIR/packed-struct-generic-transmute.rs:22:38 | LL | let oof: Oof<[u8; 5], i32> = mem::transmute(foo); | ^^^^^^^^^^^^^^ diff --git a/tests/ui/packed/packed-struct-transmute.rs b/tests/ui/packed/packed-struct-transmute.rs index 5ad6524ff817..24ac1f4ac41c 100644 --- a/tests/ui/packed/packed-struct-transmute.rs +++ b/tests/ui/packed/packed-struct-transmute.rs @@ -4,7 +4,6 @@ // transmute //@ normalize-stderr: "\d+ bits" -> "N bits" -//@ error-pattern: cannot transmute between types of different sizes, or dependently-sized types use std::mem; diff --git a/tests/ui/packed/packed-struct-transmute.stderr b/tests/ui/packed/packed-struct-transmute.stderr index 4d75820e9449..c5f556f6d0c1 100644 --- a/tests/ui/packed/packed-struct-transmute.stderr +++ b/tests/ui/packed/packed-struct-transmute.stderr @@ -1,5 +1,5 @@ error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/packed-struct-transmute.rs:26:24 + --> $DIR/packed-struct-transmute.rs:25:24 | LL | let oof: Oof = mem::transmute(foo); | ^^^^^^^^^^^^^^ diff --git a/tests/ui/parser/utf16-be-without-bom.rs b/tests/ui/parser/utf16-be-without-bom.rs index 538728735f06c249c0bff31d9ffc067cc19a2a01..1f2abc1ad5616cf155dd8a747578b1396dab1340 100644 GIT binary patch delta 74 zcmX@bxSergkFtTjzJo$aeqM=gQEFjnW>KncVqRW;Nn%N6eqOPaf@@Hae-Ia!zJ6U< T8H6*@N{XWn#!k_gxIqd4w+tBB delta 140 zcmdnac#5%JU*AC?IX|}`GbdFyEhjO(*h)cHH?^oJzeqPNzbH4c#5SWeH!+V3qz)on zkXTZZT9jv{P@0#WmtUTzP+XE&RHBfdrcjcfor+auYDGb6a!G26LVjK< diff --git a/tests/ui/parser/utf16-le-without-bom.rs b/tests/ui/parser/utf16-le-without-bom.rs index fc413663c9c09ac7b521f8a39e7e856c3067fb0f..bb95f0dd07178ce8768bcf576213f4f9cc3c7d4c 100644 GIT binary patch delta 74 zcmX@jxPx(GkFtTjzJo$aeqM=gQEFjnW>KncVqRW;Nn%N6eqOPaf@@Hae-Ia!zJ6U< T8H6*@N{XWn#!k_gxIr2Kx1Si? delta 140 zcmdnNc$%?ZU*AC?IX|}`GbdFyEhjO(*h)cHH?^oJzeqPNzbH4c#5SWeH!+V3qz)on zkXTZZT9jv{P@0#WmtUTzP+XE&RHBfdrcjcfor+auYDGb6a!G26LVjK $DIR/inner-attrs.rs:65:12 + --> $DIR/inner-attrs.rs:64:12 | LL | #![print_attr] | ^^^^^^^^^^ not a non-macro inner attribute @@ -11,19 +11,19 @@ LL | #![print_attr] | ^^^^^^^^^^ not a non-macro inner attribute error: expected non-macro inner attribute, found attribute macro `print_attr` - --> $DIR/inner-attrs.rs:73:12 + --> $DIR/inner-attrs.rs:74:12 | LL | #![print_attr] | ^^^^^^^^^^ not a non-macro inner attribute error: expected non-macro inner attribute, found attribute macro `print_attr` - --> $DIR/inner-attrs.rs:77:12 + --> $DIR/inner-attrs.rs:79:12 | LL | #![print_attr] | ^^^^^^^^^^ not a non-macro inner attribute warning: extern declarations without an explicit ABI are deprecated - --> $DIR/inner-attrs.rs:82:1 + --> $DIR/inner-attrs.rs:85:1 | LL | extern { | ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"` diff --git a/tests/ui/proc-macro/inner-attrs.stdout b/tests/ui/proc-macro/inner-attrs.stdout index ed47ee2cf5ac..4496f7b90c4e 100644 --- a/tests/ui/proc-macro/inner-attrs.stdout +++ b/tests/ui/proc-macro/inner-attrs.stdout @@ -2,7 +2,7 @@ PRINT-ATTR_ARGS INPUT (DISPLAY): first PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ Ident { ident: "first", - span: $DIR/inner-attrs.rs:18:25: 18:30 (#0), + span: $DIR/inner-attrs.rs:17:25: 17:30 (#0), }, ] PRINT-ATTR INPUT (DISPLAY): #[print_target_and_args(second)] fn foo() @@ -13,44 +13,74 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Alone, - span: $DIR/inner-attrs.rs:19:1: 19:2 (#0), + span: $DIR/inner-attrs.rs:18:1: 18:2 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "print_target_and_args", - span: $DIR/inner-attrs.rs:19:3: 19:24 (#0), + span: $DIR/inner-attrs.rs:18:3: 18:24 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "second", - span: $DIR/inner-attrs.rs:19:25: 19:31 (#0), + span: $DIR/inner-attrs.rs:18:25: 18:31 (#0), }, ], - span: $DIR/inner-attrs.rs:19:24: 19:32 (#0), + span: $DIR/inner-attrs.rs:18:24: 18:32 (#0), }, ], - span: $DIR/inner-attrs.rs:19:2: 19:33 (#0), + span: $DIR/inner-attrs.rs:18:2: 18:33 (#0), }, Ident { ident: "fn", - span: $DIR/inner-attrs.rs:20:1: 20:3 (#0), + span: $DIR/inner-attrs.rs:19:1: 19:3 (#0), }, Ident { ident: "foo", - span: $DIR/inner-attrs.rs:20:4: 20:7 (#0), + span: $DIR/inner-attrs.rs:19:4: 19:7 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [], - span: $DIR/inner-attrs.rs:20:7: 20:9 (#0), + span: $DIR/inner-attrs.rs:19:7: 19:9 (#0), }, Group { delimiter: Brace, stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/inner-attrs.rs:20:5: 20:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attrs.rs:20:6: 20:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/inner-attrs.rs:20:8: 20:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "third", + span: $DIR/inner-attrs.rs:20:30: 20:35 (#0), + }, + ], + span: $DIR/inner-attrs.rs:20:29: 20:36 (#0), + }, + ], + span: $DIR/inner-attrs.rs:20:7: 20:37 (#0), + }, Punct { ch: '#', spacing: Joint, @@ -68,58 +98,28 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ ident: "print_target_and_args", span: $DIR/inner-attrs.rs:21:8: 21:29 (#0), }, - Group { - delimiter: Parenthesis, - stream: TokenStream [ - Ident { - ident: "third", - span: $DIR/inner-attrs.rs:21:30: 21:35 (#0), - }, - ], - span: $DIR/inner-attrs.rs:21:29: 21:36 (#0), - }, - ], - span: $DIR/inner-attrs.rs:21:7: 21:37 (#0), - }, - Punct { - ch: '#', - spacing: Joint, - span: $DIR/inner-attrs.rs:22:5: 22:6 (#0), - }, - Punct { - ch: '!', - spacing: Alone, - span: $DIR/inner-attrs.rs:22:6: 22:7 (#0), - }, - Group { - delimiter: Bracket, - stream: TokenStream [ - Ident { - ident: "print_target_and_args", - span: $DIR/inner-attrs.rs:22:8: 22:29 (#0), - }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "fourth", - span: $DIR/inner-attrs.rs:22:30: 22:36 (#0), + span: $DIR/inner-attrs.rs:21:30: 21:36 (#0), }, ], - span: $DIR/inner-attrs.rs:22:29: 22:37 (#0), + span: $DIR/inner-attrs.rs:21:29: 21:37 (#0), }, ], - span: $DIR/inner-attrs.rs:22:7: 22:38 (#0), + span: $DIR/inner-attrs.rs:21:7: 21:38 (#0), }, ], - span: $DIR/inner-attrs.rs:20:10: 23:2 (#0), + span: $DIR/inner-attrs.rs:19:10: 22:2 (#0), }, ] PRINT-ATTR_ARGS INPUT (DISPLAY): second PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ Ident { ident: "second", - span: $DIR/inner-attrs.rs:19:25: 19:31 (#0), + span: $DIR/inner-attrs.rs:18:25: 18:31 (#0), }, ] PRINT-ATTR INPUT (DISPLAY): fn foo() @@ -129,16 +129,106 @@ PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): fn foo() PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "fn", - span: $DIR/inner-attrs.rs:20:1: 20:3 (#0), + span: $DIR/inner-attrs.rs:19:1: 19:3 (#0), }, Ident { ident: "foo", - span: $DIR/inner-attrs.rs:20:4: 20:7 (#0), + span: $DIR/inner-attrs.rs:19:4: 19:7 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [], - span: $DIR/inner-attrs.rs:20:7: 20:9 (#0), + span: $DIR/inner-attrs.rs:19:7: 19:9 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/inner-attrs.rs:20:5: 20:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attrs.rs:20:6: 20:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/inner-attrs.rs:20:8: 20:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "third", + span: $DIR/inner-attrs.rs:20:30: 20:35 (#0), + }, + ], + span: $DIR/inner-attrs.rs:20:29: 20:36 (#0), + }, + ], + span: $DIR/inner-attrs.rs:20:7: 20:37 (#0), + }, + Punct { + ch: '#', + spacing: Joint, + span: $DIR/inner-attrs.rs:21:5: 21:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attrs.rs:21:6: 21:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/inner-attrs.rs:21:8: 21:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "fourth", + span: $DIR/inner-attrs.rs:21:30: 21:36 (#0), + }, + ], + span: $DIR/inner-attrs.rs:21:29: 21:37 (#0), + }, + ], + span: $DIR/inner-attrs.rs:21:7: 21:38 (#0), + }, + ], + span: $DIR/inner-attrs.rs:19:10: 22:2 (#0), + }, +] +PRINT-ATTR_ARGS INPUT (DISPLAY): third +PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ + Ident { + ident: "third", + span: $DIR/inner-attrs.rs:20:30: 20:35 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): fn foo() { #![print_target_and_args(fourth)] } +PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): fn foo() { #! [print_target_and_args(fourth)] } +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "fn", + span: $DIR/inner-attrs.rs:19:1: 19:3 (#0), + }, + Ident { + ident: "foo", + span: $DIR/inner-attrs.rs:19:4: 19:7 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: $DIR/inner-attrs.rs:19:7: 19:9 (#0), }, Group { delimiter: Brace, @@ -160,146 +250,56 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ ident: "print_target_and_args", span: $DIR/inner-attrs.rs:21:8: 21:29 (#0), }, - Group { - delimiter: Parenthesis, - stream: TokenStream [ - Ident { - ident: "third", - span: $DIR/inner-attrs.rs:21:30: 21:35 (#0), - }, - ], - span: $DIR/inner-attrs.rs:21:29: 21:36 (#0), - }, - ], - span: $DIR/inner-attrs.rs:21:7: 21:37 (#0), - }, - Punct { - ch: '#', - spacing: Joint, - span: $DIR/inner-attrs.rs:22:5: 22:6 (#0), - }, - Punct { - ch: '!', - spacing: Alone, - span: $DIR/inner-attrs.rs:22:6: 22:7 (#0), - }, - Group { - delimiter: Bracket, - stream: TokenStream [ - Ident { - ident: "print_target_and_args", - span: $DIR/inner-attrs.rs:22:8: 22:29 (#0), - }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "fourth", - span: $DIR/inner-attrs.rs:22:30: 22:36 (#0), + span: $DIR/inner-attrs.rs:21:30: 21:36 (#0), }, ], - span: $DIR/inner-attrs.rs:22:29: 22:37 (#0), + span: $DIR/inner-attrs.rs:21:29: 21:37 (#0), }, ], - span: $DIR/inner-attrs.rs:22:7: 22:38 (#0), + span: $DIR/inner-attrs.rs:21:7: 21:38 (#0), }, ], - span: $DIR/inner-attrs.rs:20:10: 23:2 (#0), - }, -] -PRINT-ATTR_ARGS INPUT (DISPLAY): third -PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ - Ident { - ident: "third", - span: $DIR/inner-attrs.rs:21:30: 21:35 (#0), - }, -] -PRINT-ATTR INPUT (DISPLAY): fn foo() { #![print_target_and_args(fourth)] } -PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): fn foo() { #! [print_target_and_args(fourth)] } -PRINT-ATTR INPUT (DEBUG): TokenStream [ - Ident { - ident: "fn", - span: $DIR/inner-attrs.rs:20:1: 20:3 (#0), - }, - Ident { - ident: "foo", - span: $DIR/inner-attrs.rs:20:4: 20:7 (#0), - }, - Group { - delimiter: Parenthesis, - stream: TokenStream [], - span: $DIR/inner-attrs.rs:20:7: 20:9 (#0), - }, - Group { - delimiter: Brace, - stream: TokenStream [ - Punct { - ch: '#', - spacing: Joint, - span: $DIR/inner-attrs.rs:22:5: 22:6 (#0), - }, - Punct { - ch: '!', - spacing: Alone, - span: $DIR/inner-attrs.rs:22:6: 22:7 (#0), - }, - Group { - delimiter: Bracket, - stream: TokenStream [ - Ident { - ident: "print_target_and_args", - span: $DIR/inner-attrs.rs:22:8: 22:29 (#0), - }, - Group { - delimiter: Parenthesis, - stream: TokenStream [ - Ident { - ident: "fourth", - span: $DIR/inner-attrs.rs:22:30: 22:36 (#0), - }, - ], - span: $DIR/inner-attrs.rs:22:29: 22:37 (#0), - }, - ], - span: $DIR/inner-attrs.rs:22:7: 22:38 (#0), - }, - ], - span: $DIR/inner-attrs.rs:20:10: 23:2 (#0), + span: $DIR/inner-attrs.rs:19:10: 22:2 (#0), }, ] PRINT-ATTR_ARGS INPUT (DISPLAY): fourth PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ Ident { ident: "fourth", - span: $DIR/inner-attrs.rs:22:30: 22:36 (#0), + span: $DIR/inner-attrs.rs:21:30: 21:36 (#0), }, ] PRINT-ATTR INPUT (DISPLAY): fn foo() {} PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "fn", - span: $DIR/inner-attrs.rs:20:1: 20:3 (#0), + span: $DIR/inner-attrs.rs:19:1: 19:3 (#0), }, Ident { ident: "foo", - span: $DIR/inner-attrs.rs:20:4: 20:7 (#0), + span: $DIR/inner-attrs.rs:19:4: 19:7 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [], - span: $DIR/inner-attrs.rs:20:7: 20:9 (#0), + span: $DIR/inner-attrs.rs:19:7: 19:9 (#0), }, Group { delimiter: Brace, stream: TokenStream [], - span: $DIR/inner-attrs.rs:20:10: 23:2 (#0), + span: $DIR/inner-attrs.rs:19:10: 22:2 (#0), }, ] PRINT-ATTR_ARGS INPUT (DISPLAY): mod_first PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ Ident { ident: "mod_first", - span: $DIR/inner-attrs.rs:25:25: 25:34 (#0), + span: $DIR/inner-attrs.rs:24:25: 24:34 (#0), }, ] PRINT-ATTR INPUT (DISPLAY): #[print_target_and_args(mod_second)] mod inline_mod @@ -313,39 +313,69 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Alone, - span: $DIR/inner-attrs.rs:26:1: 26:2 (#0), + span: $DIR/inner-attrs.rs:25:1: 25:2 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "print_target_and_args", - span: $DIR/inner-attrs.rs:26:3: 26:24 (#0), + span: $DIR/inner-attrs.rs:25:3: 25:24 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "mod_second", - span: $DIR/inner-attrs.rs:26:25: 26:35 (#0), + span: $DIR/inner-attrs.rs:25:25: 25:35 (#0), }, ], - span: $DIR/inner-attrs.rs:26:24: 26:36 (#0), + span: $DIR/inner-attrs.rs:25:24: 25:36 (#0), }, ], - span: $DIR/inner-attrs.rs:26:2: 26:37 (#0), + span: $DIR/inner-attrs.rs:25:2: 25:37 (#0), }, Ident { ident: "mod", - span: $DIR/inner-attrs.rs:27:1: 27:4 (#0), + span: $DIR/inner-attrs.rs:26:1: 26:4 (#0), }, Ident { ident: "inline_mod", - span: $DIR/inner-attrs.rs:27:5: 27:15 (#0), + span: $DIR/inner-attrs.rs:26:5: 26:15 (#0), }, Group { delimiter: Brace, stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/inner-attrs.rs:27:5: 27:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attrs.rs:27:6: 27:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/inner-attrs.rs:27:8: 27:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "mod_third", + span: $DIR/inner-attrs.rs:27:30: 27:39 (#0), + }, + ], + span: $DIR/inner-attrs.rs:27:29: 27:40 (#0), + }, + ], + span: $DIR/inner-attrs.rs:27:7: 27:41 (#0), + }, Punct { ch: '#', spacing: Joint, @@ -363,58 +393,28 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ ident: "print_target_and_args", span: $DIR/inner-attrs.rs:28:8: 28:29 (#0), }, - Group { - delimiter: Parenthesis, - stream: TokenStream [ - Ident { - ident: "mod_third", - span: $DIR/inner-attrs.rs:28:30: 28:39 (#0), - }, - ], - span: $DIR/inner-attrs.rs:28:29: 28:40 (#0), - }, - ], - span: $DIR/inner-attrs.rs:28:7: 28:41 (#0), - }, - Punct { - ch: '#', - spacing: Joint, - span: $DIR/inner-attrs.rs:29:5: 29:6 (#0), - }, - Punct { - ch: '!', - spacing: Alone, - span: $DIR/inner-attrs.rs:29:6: 29:7 (#0), - }, - Group { - delimiter: Bracket, - stream: TokenStream [ - Ident { - ident: "print_target_and_args", - span: $DIR/inner-attrs.rs:29:8: 29:29 (#0), - }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "mod_fourth", - span: $DIR/inner-attrs.rs:29:30: 29:40 (#0), + span: $DIR/inner-attrs.rs:28:30: 28:40 (#0), }, ], - span: $DIR/inner-attrs.rs:29:29: 29:41 (#0), + span: $DIR/inner-attrs.rs:28:29: 28:41 (#0), }, ], - span: $DIR/inner-attrs.rs:29:7: 29:42 (#0), + span: $DIR/inner-attrs.rs:28:7: 28:42 (#0), }, ], - span: $DIR/inner-attrs.rs:27:16: 30:2 (#0), + span: $DIR/inner-attrs.rs:26:16: 29:2 (#0), }, ] PRINT-ATTR_ARGS INPUT (DISPLAY): mod_second PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ Ident { ident: "mod_second", - span: $DIR/inner-attrs.rs:26:25: 26:35 (#0), + span: $DIR/inner-attrs.rs:25:25: 25:35 (#0), }, ] PRINT-ATTR INPUT (DISPLAY): mod inline_mod @@ -427,11 +427,96 @@ PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): mod inline_mod PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "mod", - span: $DIR/inner-attrs.rs:27:1: 27:4 (#0), + span: $DIR/inner-attrs.rs:26:1: 26:4 (#0), }, Ident { ident: "inline_mod", - span: $DIR/inner-attrs.rs:27:5: 27:15 (#0), + span: $DIR/inner-attrs.rs:26:5: 26:15 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/inner-attrs.rs:27:5: 27:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attrs.rs:27:6: 27:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/inner-attrs.rs:27:8: 27:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "mod_third", + span: $DIR/inner-attrs.rs:27:30: 27:39 (#0), + }, + ], + span: $DIR/inner-attrs.rs:27:29: 27:40 (#0), + }, + ], + span: $DIR/inner-attrs.rs:27:7: 27:41 (#0), + }, + Punct { + ch: '#', + spacing: Joint, + span: $DIR/inner-attrs.rs:28:5: 28:6 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attrs.rs:28:6: 28:7 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "print_target_and_args", + span: $DIR/inner-attrs.rs:28:8: 28:29 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "mod_fourth", + span: $DIR/inner-attrs.rs:28:30: 28:40 (#0), + }, + ], + span: $DIR/inner-attrs.rs:28:29: 28:41 (#0), + }, + ], + span: $DIR/inner-attrs.rs:28:7: 28:42 (#0), + }, + ], + span: $DIR/inner-attrs.rs:26:16: 29:2 (#0), + }, +] +PRINT-ATTR_ARGS INPUT (DISPLAY): mod_third +PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ + Ident { + ident: "mod_third", + span: $DIR/inner-attrs.rs:27:30: 27:39 (#0), + }, +] +PRINT-ATTR INPUT (DISPLAY): mod inline_mod { #![print_target_and_args(mod_fourth)] } +PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): mod inline_mod { #! [print_target_and_args(mod_fourth)] } +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "mod", + span: $DIR/inner-attrs.rs:26:1: 26:4 (#0), + }, + Ident { + ident: "inline_mod", + span: $DIR/inner-attrs.rs:26:5: 26:15 (#0), }, Group { delimiter: Brace, @@ -453,129 +538,44 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ ident: "print_target_and_args", span: $DIR/inner-attrs.rs:28:8: 28:29 (#0), }, - Group { - delimiter: Parenthesis, - stream: TokenStream [ - Ident { - ident: "mod_third", - span: $DIR/inner-attrs.rs:28:30: 28:39 (#0), - }, - ], - span: $DIR/inner-attrs.rs:28:29: 28:40 (#0), - }, - ], - span: $DIR/inner-attrs.rs:28:7: 28:41 (#0), - }, - Punct { - ch: '#', - spacing: Joint, - span: $DIR/inner-attrs.rs:29:5: 29:6 (#0), - }, - Punct { - ch: '!', - spacing: Alone, - span: $DIR/inner-attrs.rs:29:6: 29:7 (#0), - }, - Group { - delimiter: Bracket, - stream: TokenStream [ - Ident { - ident: "print_target_and_args", - span: $DIR/inner-attrs.rs:29:8: 29:29 (#0), - }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "mod_fourth", - span: $DIR/inner-attrs.rs:29:30: 29:40 (#0), + span: $DIR/inner-attrs.rs:28:30: 28:40 (#0), }, ], - span: $DIR/inner-attrs.rs:29:29: 29:41 (#0), + span: $DIR/inner-attrs.rs:28:29: 28:41 (#0), }, ], - span: $DIR/inner-attrs.rs:29:7: 29:42 (#0), + span: $DIR/inner-attrs.rs:28:7: 28:42 (#0), }, ], - span: $DIR/inner-attrs.rs:27:16: 30:2 (#0), - }, -] -PRINT-ATTR_ARGS INPUT (DISPLAY): mod_third -PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ - Ident { - ident: "mod_third", - span: $DIR/inner-attrs.rs:28:30: 28:39 (#0), - }, -] -PRINT-ATTR INPUT (DISPLAY): mod inline_mod { #![print_target_and_args(mod_fourth)] } -PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): mod inline_mod { #! [print_target_and_args(mod_fourth)] } -PRINT-ATTR INPUT (DEBUG): TokenStream [ - Ident { - ident: "mod", - span: $DIR/inner-attrs.rs:27:1: 27:4 (#0), - }, - Ident { - ident: "inline_mod", - span: $DIR/inner-attrs.rs:27:5: 27:15 (#0), - }, - Group { - delimiter: Brace, - stream: TokenStream [ - Punct { - ch: '#', - spacing: Joint, - span: $DIR/inner-attrs.rs:29:5: 29:6 (#0), - }, - Punct { - ch: '!', - spacing: Alone, - span: $DIR/inner-attrs.rs:29:6: 29:7 (#0), - }, - Group { - delimiter: Bracket, - stream: TokenStream [ - Ident { - ident: "print_target_and_args", - span: $DIR/inner-attrs.rs:29:8: 29:29 (#0), - }, - Group { - delimiter: Parenthesis, - stream: TokenStream [ - Ident { - ident: "mod_fourth", - span: $DIR/inner-attrs.rs:29:30: 29:40 (#0), - }, - ], - span: $DIR/inner-attrs.rs:29:29: 29:41 (#0), - }, - ], - span: $DIR/inner-attrs.rs:29:7: 29:42 (#0), - }, - ], - span: $DIR/inner-attrs.rs:27:16: 30:2 (#0), + span: $DIR/inner-attrs.rs:26:16: 29:2 (#0), }, ] PRINT-ATTR_ARGS INPUT (DISPLAY): mod_fourth PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ Ident { ident: "mod_fourth", - span: $DIR/inner-attrs.rs:29:30: 29:40 (#0), + span: $DIR/inner-attrs.rs:28:30: 28:40 (#0), }, ] PRINT-ATTR INPUT (DISPLAY): mod inline_mod {} PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "mod", - span: $DIR/inner-attrs.rs:27:1: 27:4 (#0), + span: $DIR/inner-attrs.rs:26:1: 26:4 (#0), }, Ident { ident: "inline_mod", - span: $DIR/inner-attrs.rs:27:5: 27:15 (#0), + span: $DIR/inner-attrs.rs:26:5: 26:15 (#0), }, Group { delimiter: Brace, stream: TokenStream [], - span: $DIR/inner-attrs.rs:27:16: 30:2 (#0), + span: $DIR/inner-attrs.rs:26:16: 29:2 (#0), }, ] PRINT-DERIVE INPUT (DISPLAY): struct MyDerivePrint @@ -585,63 +585,63 @@ PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): struct MyDerivePrint PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "struct", - span: $DIR/inner-attrs.rs:37:1: 37:7 (#0), + span: $DIR/inner-attrs.rs:36:1: 36:7 (#0), }, Ident { ident: "MyDerivePrint", - span: $DIR/inner-attrs.rs:37:8: 37:21 (#0), + span: $DIR/inner-attrs.rs:36:8: 36:21 (#0), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "field", - span: $DIR/inner-attrs.rs:38:5: 38:10 (#0), + span: $DIR/inner-attrs.rs:37:5: 37:10 (#0), }, Punct { ch: ':', spacing: Alone, - span: $DIR/inner-attrs.rs:38:10: 38:11 (#0), + span: $DIR/inner-attrs.rs:37:10: 37:11 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "u8", - span: $DIR/inner-attrs.rs:38:13: 38:15 (#0), + span: $DIR/inner-attrs.rs:37:13: 37:15 (#0), }, Punct { ch: ';', spacing: Alone, - span: $DIR/inner-attrs.rs:38:15: 38:16 (#0), + span: $DIR/inner-attrs.rs:37:15: 37:16 (#0), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "match", - span: $DIR/inner-attrs.rs:39:9: 39:14 (#0), + span: $DIR/inner-attrs.rs:38:9: 38:14 (#0), }, Ident { ident: "true", - span: $DIR/inner-attrs.rs:39:15: 39:19 (#0), + span: $DIR/inner-attrs.rs:38:15: 38:19 (#0), }, Group { delimiter: Brace, stream: TokenStream [ Ident { ident: "_", - span: $DIR/inner-attrs.rs:40:13: 40:14 (#0), + span: $DIR/inner-attrs.rs:39:13: 39:14 (#0), }, Punct { ch: '=', spacing: Joint, - span: $DIR/inner-attrs.rs:40:15: 40:16 (#0), + span: $DIR/inner-attrs.rs:39:15: 39:16 (#0), }, Punct { ch: '>', spacing: Alone, - span: $DIR/inner-attrs.rs:40:16: 40:17 (#0), + span: $DIR/inner-attrs.rs:39:16: 39:17 (#0), }, Group { delimiter: Brace, @@ -649,69 +649,69 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Joint, - span: $DIR/inner-attrs.rs:41:17: 41:18 (#0), + span: $DIR/inner-attrs.rs:40:17: 40:18 (#0), }, Punct { ch: '!', spacing: Alone, - span: $DIR/inner-attrs.rs:41:18: 41:19 (#0), + span: $DIR/inner-attrs.rs:40:18: 40:19 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "rustc_dummy", - span: $DIR/inner-attrs.rs:41:41: 41:52 (#0), + span: $DIR/inner-attrs.rs:40:41: 40:52 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "third", - span: $DIR/inner-attrs.rs:41:53: 41:58 (#0), + span: $DIR/inner-attrs.rs:40:53: 40:58 (#0), }, ], - span: $DIR/inner-attrs.rs:41:52: 41:59 (#0), + span: $DIR/inner-attrs.rs:40:52: 40:59 (#0), }, ], - span: $DIR/inner-attrs.rs:41:19: 41:61 (#0), + span: $DIR/inner-attrs.rs:40:19: 40:61 (#0), }, Ident { ident: "true", - span: $DIR/inner-attrs.rs:42:17: 42:21 (#0), + span: $DIR/inner-attrs.rs:41:17: 41:21 (#0), }, ], - span: $DIR/inner-attrs.rs:40:18: 43:14 (#0), + span: $DIR/inner-attrs.rs:39:18: 42:14 (#0), }, ], - span: $DIR/inner-attrs.rs:39:20: 44:10 (#0), + span: $DIR/inner-attrs.rs:38:20: 43:10 (#0), }, Punct { ch: ';', spacing: Alone, - span: $DIR/inner-attrs.rs:44:10: 44:11 (#0), + span: $DIR/inner-attrs.rs:43:10: 43:11 (#0), }, Literal { kind: Integer, symbol: "0", suffix: None, - span: $DIR/inner-attrs.rs:45:9: 45:10 (#0), + span: $DIR/inner-attrs.rs:44:9: 44:10 (#0), }, ], - span: $DIR/inner-attrs.rs:38:17: 46:6 (#0), + span: $DIR/inner-attrs.rs:37:17: 45:6 (#0), }, ], - span: $DIR/inner-attrs.rs:38:12: 46:7 (#0), + span: $DIR/inner-attrs.rs:37:12: 45:7 (#0), }, ], - span: $DIR/inner-attrs.rs:37:22: 47:2 (#0), + span: $DIR/inner-attrs.rs:36:22: 46:2 (#0), }, ] PRINT-ATTR_ARGS INPUT (DISPLAY): tuple_attrs PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ Ident { ident: "tuple_attrs", - span: $DIR/inner-attrs.rs:50:29: 50:40 (#0), + span: $DIR/inner-attrs.rs:49:29: 49:40 (#0), }, ] PRINT-ATTR INPUT (DISPLAY): (3, 4, { #![cfg_attr(not(FALSE), rustc_dummy(innermost))] 5 }); @@ -724,23 +724,23 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ kind: Integer, symbol: "3", suffix: None, - span: $DIR/inner-attrs.rs:51:9: 51:10 (#0), + span: $DIR/inner-attrs.rs:50:9: 50:10 (#0), }, Punct { ch: ',', spacing: Alone, - span: $DIR/inner-attrs.rs:51:10: 51:11 (#0), + span: $DIR/inner-attrs.rs:50:10: 50:11 (#0), }, Literal { kind: Integer, symbol: "4", suffix: None, - span: $DIR/inner-attrs.rs:51:12: 51:13 (#0), + span: $DIR/inner-attrs.rs:50:12: 50:13 (#0), }, Punct { ch: ',', spacing: Alone, - span: $DIR/inner-attrs.rs:51:13: 51:14 (#0), + span: $DIR/inner-attrs.rs:50:13: 50:14 (#0), }, Group { delimiter: Brace, @@ -748,85 +748,85 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Joint, + span: $DIR/inner-attrs.rs:51:13: 51:14 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attrs.rs:51:14: 51:15 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "cfg_attr", + span: $DIR/inner-attrs.rs:51:16: 51:24 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "not", + span: $DIR/inner-attrs.rs:51:25: 51:28 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "FALSE", + span: $DIR/inner-attrs.rs:51:29: 51:34 (#0), + }, + ], + span: $DIR/inner-attrs.rs:51:28: 51:35 (#0), + }, + Punct { + ch: ',', + spacing: Alone, + span: $DIR/inner-attrs.rs:51:35: 51:36 (#0), + }, + Ident { + ident: "rustc_dummy", + span: $DIR/inner-attrs.rs:51:37: 51:48 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "innermost", + span: $DIR/inner-attrs.rs:51:49: 51:58 (#0), + }, + ], + span: $DIR/inner-attrs.rs:51:48: 51:59 (#0), + }, + ], + span: $DIR/inner-attrs.rs:51:24: 51:60 (#0), + }, + ], + span: $DIR/inner-attrs.rs:51:15: 51:61 (#0), + }, + Literal { + kind: Integer, + symbol: "5", + suffix: None, span: $DIR/inner-attrs.rs:52:13: 52:14 (#0), }, - Punct { - ch: '!', - spacing: Alone, - span: $DIR/inner-attrs.rs:52:14: 52:15 (#0), - }, - Group { - delimiter: Bracket, - stream: TokenStream [ - Ident { - ident: "cfg_attr", - span: $DIR/inner-attrs.rs:52:16: 52:24 (#0), - }, - Group { - delimiter: Parenthesis, - stream: TokenStream [ - Ident { - ident: "not", - span: $DIR/inner-attrs.rs:52:25: 52:28 (#0), - }, - Group { - delimiter: Parenthesis, - stream: TokenStream [ - Ident { - ident: "FALSE", - span: $DIR/inner-attrs.rs:52:29: 52:34 (#0), - }, - ], - span: $DIR/inner-attrs.rs:52:28: 52:35 (#0), - }, - Punct { - ch: ',', - spacing: Alone, - span: $DIR/inner-attrs.rs:52:35: 52:36 (#0), - }, - Ident { - ident: "rustc_dummy", - span: $DIR/inner-attrs.rs:52:37: 52:48 (#0), - }, - Group { - delimiter: Parenthesis, - stream: TokenStream [ - Ident { - ident: "innermost", - span: $DIR/inner-attrs.rs:52:49: 52:58 (#0), - }, - ], - span: $DIR/inner-attrs.rs:52:48: 52:59 (#0), - }, - ], - span: $DIR/inner-attrs.rs:52:24: 52:60 (#0), - }, - ], - span: $DIR/inner-attrs.rs:52:15: 52:61 (#0), - }, - Literal { - kind: Integer, - symbol: "5", - suffix: None, - span: $DIR/inner-attrs.rs:53:13: 53:14 (#0), - }, ], - span: $DIR/inner-attrs.rs:51:15: 54:10 (#0), + span: $DIR/inner-attrs.rs:50:15: 53:10 (#0), }, ], - span: $DIR/inner-attrs.rs:50:43: 55:6 (#0), + span: $DIR/inner-attrs.rs:49:43: 54:6 (#0), }, Punct { ch: ';', spacing: Alone, - span: $DIR/inner-attrs.rs:55:6: 55:7 (#0), + span: $DIR/inner-attrs.rs:54:6: 54:7 (#0), }, ] PRINT-ATTR_ARGS INPUT (DISPLAY): tuple_attrs PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ Ident { ident: "tuple_attrs", - span: $DIR/inner-attrs.rs:57:29: 57:40 (#0), + span: $DIR/inner-attrs.rs:56:29: 56:40 (#0), }, ] PRINT-ATTR INPUT (DISPLAY): (3, 4, { #![cfg_attr(not(FALSE), rustc_dummy(innermost))] 5 }); @@ -839,23 +839,23 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ kind: Integer, symbol: "3", suffix: None, - span: $DIR/inner-attrs.rs:58:9: 58:10 (#0), + span: $DIR/inner-attrs.rs:57:9: 57:10 (#0), }, Punct { ch: ',', spacing: Alone, - span: $DIR/inner-attrs.rs:58:10: 58:11 (#0), + span: $DIR/inner-attrs.rs:57:10: 57:11 (#0), }, Literal { kind: Integer, symbol: "4", suffix: None, - span: $DIR/inner-attrs.rs:58:12: 58:13 (#0), + span: $DIR/inner-attrs.rs:57:12: 57:13 (#0), }, Punct { ch: ',', spacing: Alone, - span: $DIR/inner-attrs.rs:58:13: 58:14 (#0), + span: $DIR/inner-attrs.rs:57:13: 57:14 (#0), }, Group { delimiter: Brace, @@ -863,105 +863,105 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ Punct { ch: '#', spacing: Joint, - span: $DIR/inner-attrs.rs:59:13: 59:14 (#0), + span: $DIR/inner-attrs.rs:58:13: 58:14 (#0), }, Punct { ch: '!', spacing: Alone, - span: $DIR/inner-attrs.rs:59:14: 59:15 (#0), + span: $DIR/inner-attrs.rs:58:14: 58:15 (#0), }, Group { delimiter: Bracket, stream: TokenStream [ Ident { ident: "cfg_attr", - span: $DIR/inner-attrs.rs:59:16: 59:24 (#0), + span: $DIR/inner-attrs.rs:58:16: 58:24 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "not", - span: $DIR/inner-attrs.rs:59:25: 59:28 (#0), + span: $DIR/inner-attrs.rs:58:25: 58:28 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "FALSE", - span: $DIR/inner-attrs.rs:59:29: 59:34 (#0), + span: $DIR/inner-attrs.rs:58:29: 58:34 (#0), }, ], - span: $DIR/inner-attrs.rs:59:28: 59:35 (#0), + span: $DIR/inner-attrs.rs:58:28: 58:35 (#0), }, Punct { ch: ',', spacing: Alone, - span: $DIR/inner-attrs.rs:59:35: 59:36 (#0), + span: $DIR/inner-attrs.rs:58:35: 58:36 (#0), }, Ident { ident: "rustc_dummy", - span: $DIR/inner-attrs.rs:59:37: 59:48 (#0), + span: $DIR/inner-attrs.rs:58:37: 58:48 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [ Ident { ident: "innermost", - span: $DIR/inner-attrs.rs:59:49: 59:58 (#0), + span: $DIR/inner-attrs.rs:58:49: 58:58 (#0), }, ], - span: $DIR/inner-attrs.rs:59:48: 59:59 (#0), + span: $DIR/inner-attrs.rs:58:48: 58:59 (#0), }, ], - span: $DIR/inner-attrs.rs:59:24: 59:60 (#0), + span: $DIR/inner-attrs.rs:58:24: 58:60 (#0), }, ], - span: $DIR/inner-attrs.rs:59:15: 59:61 (#0), + span: $DIR/inner-attrs.rs:58:15: 58:61 (#0), }, Literal { kind: Integer, symbol: "5", suffix: None, - span: $DIR/inner-attrs.rs:60:13: 60:14 (#0), + span: $DIR/inner-attrs.rs:59:13: 59:14 (#0), }, ], - span: $DIR/inner-attrs.rs:58:15: 61:10 (#0), + span: $DIR/inner-attrs.rs:57:15: 60:10 (#0), }, ], - span: $DIR/inner-attrs.rs:57:43: 62:6 (#0), + span: $DIR/inner-attrs.rs:56:43: 61:6 (#0), }, Punct { ch: ';', spacing: Alone, - span: $DIR/inner-attrs.rs:62:6: 62:7 (#0), + span: $DIR/inner-attrs.rs:61:6: 61:7 (#0), }, ] PRINT-ATTR_ARGS INPUT (DISPLAY): tenth PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ Ident { ident: "tenth", - span: $DIR/inner-attrs.rs:84:42: 84:47 (#0), + span: $DIR/inner-attrs.rs:87:42: 87:47 (#0), }, ] PRINT-ATTR INPUT (DISPLAY): fn weird_extern() {} PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "fn", - span: $DIR/inner-attrs.rs:83:5: 83:7 (#0), + span: $DIR/inner-attrs.rs:86:5: 86:7 (#0), }, Ident { ident: "weird_extern", - span: $DIR/inner-attrs.rs:83:8: 83:20 (#0), + span: $DIR/inner-attrs.rs:86:8: 86:20 (#0), }, Group { delimiter: Parenthesis, stream: TokenStream [], - span: $DIR/inner-attrs.rs:83:20: 83:22 (#0), + span: $DIR/inner-attrs.rs:86:20: 86:22 (#0), }, Group { delimiter: Brace, stream: TokenStream [], - span: $DIR/inner-attrs.rs:83:23: 85:6 (#0), + span: $DIR/inner-attrs.rs:86:23: 88:6 (#0), }, ] diff --git a/tests/ui/regions/region-invariant-static-error-reporting.rs b/tests/ui/regions/region-invariant-static-error-reporting.rs index e58eea3f61ae..9792c101fa89 100644 --- a/tests/ui/regions/region-invariant-static-error-reporting.rs +++ b/tests/ui/regions/region-invariant-static-error-reporting.rs @@ -3,7 +3,7 @@ // over time, but this test used to exhibit some pretty bogus messages // that were not remotely helpful. -//@ error-pattern:requires that `'a` must outlive `'static` +//@ dont-require-annotations: NOTE struct Invariant<'a>(Option<&'a mut &'a mut ()>); @@ -14,6 +14,7 @@ fn unify<'a>(x: Option>, f: fn(Invariant<'a>)) { x.unwrap() } else { mk_static() //~ ERROR lifetime may not live long enough + //~| NOTE assignment requires that `'a` must outlive `'static` }; f(bad); } diff --git a/tests/ui/target-feature/forbidden-target-feature-flag-disable.rs b/tests/ui/target-feature/forbidden-target-feature-flag-disable.rs index fda0b1c08cb2..d394dbe7b15d 100644 --- a/tests/ui/target-feature/forbidden-target-feature-flag-disable.rs +++ b/tests/ui/target-feature/forbidden-target-feature-flag-disable.rs @@ -4,7 +4,7 @@ //@ compile-flags: -Ctarget-feature=-forced-atomics // For now this is just a warning. //@ build-pass -//@error-pattern: unsound because it changes the ABI + #![feature(no_core, lang_items)] #![no_core] diff --git a/tests/ui/target-feature/tied-features-no-implication-1.rs b/tests/ui/target-feature/tied-features-no-implication-1.rs index 0a98a7eeccf4..63a1d77dae9f 100644 --- a/tests/ui/target-feature/tied-features-no-implication-1.rs +++ b/tests/ui/target-feature/tied-features-no-implication-1.rs @@ -2,9 +2,7 @@ //@ compile-flags: --crate-type=rlib --target=aarch64-unknown-linux-gnu //@ needs-llvm-components: aarch64 //@[paca] compile-flags: -Ctarget-feature=+paca -//@[paca] error-pattern: the target features paca, pacg must all be either enabled or disabled together //@[pacg] compile-flags: -Ctarget-feature=+pacg -//@[paca] error-pattern: the target features paca, pacg must all be either enabled or disabled together #![feature(no_core, lang_items)] #![no_core] diff --git a/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.rs b/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.rs index 9304e20b4290..6005bc96ad6d 100644 --- a/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.rs +++ b/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.rs @@ -1,6 +1,7 @@ //~ ERROR unknown lint: `test_unstable_lint` +//~^ NOTE the `test_unstable_lint` lint is unstable //@ check-fail //@ compile-flags: -Dunknown_lints -Atest_unstable_lint -//@ error-pattern: the `test_unstable_lint` lint is unstable +//@ dont-require-annotations: NOTE fn main() {} diff --git a/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.rs b/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.rs index 76983419c685..c32a21a01632 100644 --- a/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.rs +++ b/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.rs @@ -1,6 +1,7 @@ //~ WARN unknown lint: `test_unstable_lint` +//~^ NOTE the `test_unstable_lint` lint is unstable //@ check-pass //@ compile-flags: -Wunknown_lints -Atest_unstable_lint -//@ error-pattern: the `test_unstable_lint` lint is unstable +//@ dont-require-annotations: NOTE fn main() {} From 9f35fe47c75cf404a7ae2c64dbeaf37277106504 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Fri, 4 Oct 2024 12:54:09 +0000 Subject: [PATCH 415/606] JumpThreading: Re-enable and fix Not ops on non-booleans --- .../rustc_mir_transform/src/jump_threading.rs | 29 +++++------- ...bitwise_not.JumpThreading.panic-abort.diff | 6 +-- ...itwise_not.JumpThreading.panic-unwind.diff | 6 +-- ...logical_not.JumpThreading.panic-abort.diff | 46 +++++++++++++++++++ ...ogical_not.JumpThreading.panic-unwind.diff | 46 +++++++++++++++++++ tests/mir-opt/jump_threading.rs | 14 ++++-- 6 files changed, 120 insertions(+), 27 deletions(-) create mode 100644 tests/mir-opt/jump_threading.logical_not.JumpThreading.panic-abort.diff create mode 100644 tests/mir-opt/jump_threading.logical_not.JumpThreading.panic-unwind.diff diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs index 0a72a9d669fe..375cf88e3e9b 100644 --- a/compiler/rustc_mir_transform/src/jump_threading.rs +++ b/compiler/rustc_mir_transform/src/jump_threading.rs @@ -150,14 +150,6 @@ impl Condition { fn matches(&self, value: ScalarInt) -> bool { (self.value == value) == (self.polarity == Polarity::Eq) } - - fn inv(mut self) -> Self { - self.polarity = match self.polarity { - Polarity::Eq => Polarity::Ne, - Polarity::Ne => Polarity::Eq, - }; - self - } } #[derive(Copy, Clone, Debug)] @@ -495,19 +487,20 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> { } } } - // Transfer the conditions on the copy rhs, after inversing polarity. + // Transfer the conditions on the copy rhs, after inverting the value of the condition. Rvalue::UnaryOp(UnOp::Not, Operand::Move(place) | Operand::Copy(place)) => { - if !place.ty(self.body, self.tcx).ty.is_bool() { - // Constructing the conditions by inverting the polarity - // of equality is only correct for bools. That is to say, - // `!a == b` is not `a != b` for integers greater than 1 bit. - return; - } + let layout = self.ecx.layout_of(place.ty(self.body, self.tcx).ty).unwrap(); let Some(conditions) = state.try_get_idx(lhs, &self.map) else { return }; let Some(place) = self.map.find(place.as_ref()) else { return }; - // FIXME: I think This could be generalized to not bool if we - // actually perform a logical not on the condition's value. - let conds = conditions.map(self.arena, Condition::inv); + let conds = conditions.map(self.arena, |mut cond| { + cond.value = self + .ecx + .unary_op(UnOp::Not, &ImmTy::from_scalar_int(cond.value, layout)) + .unwrap() + .to_scalar_int() + .unwrap(); + cond + }); state.insert_value_idx(place, conds, &self.map); } // We expect `lhs ?= A`. We found `lhs = Eq(rhs, B)`. diff --git a/tests/mir-opt/jump_threading.bitwise_not.JumpThreading.panic-abort.diff b/tests/mir-opt/jump_threading.bitwise_not.JumpThreading.panic-abort.diff index 047441e60991..c3272f21d6c1 100644 --- a/tests/mir-opt/jump_threading.bitwise_not.JumpThreading.panic-abort.diff +++ b/tests/mir-opt/jump_threading.bitwise_not.JumpThreading.panic-abort.diff @@ -3,7 +3,7 @@ fn bitwise_not() -> i32 { let mut _0: i32; - let mut _1: i32; + let _1: i32; let mut _2: bool; let mut _3: i32; let mut _4: i32; @@ -13,7 +13,6 @@ bb0: { StorageLive(_1); - _1 = const 0_i32; _1 = const 1_i32; StorageLive(_2); StorageLive(_3); @@ -22,7 +21,8 @@ _3 = Not(move _4); StorageDead(_4); _2 = Eq(move _3, const 0_i32); - switchInt(move _2) -> [0: bb2, otherwise: bb1]; +- switchInt(move _2) -> [0: bb2, otherwise: bb1]; ++ goto -> bb2; } bb1: { diff --git a/tests/mir-opt/jump_threading.bitwise_not.JumpThreading.panic-unwind.diff b/tests/mir-opt/jump_threading.bitwise_not.JumpThreading.panic-unwind.diff index 047441e60991..c3272f21d6c1 100644 --- a/tests/mir-opt/jump_threading.bitwise_not.JumpThreading.panic-unwind.diff +++ b/tests/mir-opt/jump_threading.bitwise_not.JumpThreading.panic-unwind.diff @@ -3,7 +3,7 @@ fn bitwise_not() -> i32 { let mut _0: i32; - let mut _1: i32; + let _1: i32; let mut _2: bool; let mut _3: i32; let mut _4: i32; @@ -13,7 +13,6 @@ bb0: { StorageLive(_1); - _1 = const 0_i32; _1 = const 1_i32; StorageLive(_2); StorageLive(_3); @@ -22,7 +21,8 @@ _3 = Not(move _4); StorageDead(_4); _2 = Eq(move _3, const 0_i32); - switchInt(move _2) -> [0: bb2, otherwise: bb1]; +- switchInt(move _2) -> [0: bb2, otherwise: bb1]; ++ goto -> bb2; } bb1: { diff --git a/tests/mir-opt/jump_threading.logical_not.JumpThreading.panic-abort.diff b/tests/mir-opt/jump_threading.logical_not.JumpThreading.panic-abort.diff new file mode 100644 index 000000000000..ad8be1ef5a18 --- /dev/null +++ b/tests/mir-opt/jump_threading.logical_not.JumpThreading.panic-abort.diff @@ -0,0 +1,46 @@ +- // MIR for `logical_not` before JumpThreading ++ // MIR for `logical_not` after JumpThreading + + fn logical_not() -> i32 { + let mut _0: i32; + let _1: bool; + let mut _2: bool; + let mut _3: bool; + let mut _4: bool; + scope 1 { + debug a => _1; + } + + bb0: { + StorageLive(_1); + _1 = const false; + StorageLive(_2); + StorageLive(_3); + StorageLive(_4); + _4 = copy _1; + _3 = Not(move _4); + StorageDead(_4); + _2 = Eq(move _3, const true); +- switchInt(move _2) -> [0: bb2, otherwise: bb1]; ++ goto -> bb1; + } + + bb1: { + StorageDead(_3); + _0 = const 1_i32; + goto -> bb3; + } + + bb2: { + StorageDead(_3); + _0 = const 0_i32; + goto -> bb3; + } + + bb3: { + StorageDead(_2); + StorageDead(_1); + return; + } + } + diff --git a/tests/mir-opt/jump_threading.logical_not.JumpThreading.panic-unwind.diff b/tests/mir-opt/jump_threading.logical_not.JumpThreading.panic-unwind.diff new file mode 100644 index 000000000000..ad8be1ef5a18 --- /dev/null +++ b/tests/mir-opt/jump_threading.logical_not.JumpThreading.panic-unwind.diff @@ -0,0 +1,46 @@ +- // MIR for `logical_not` before JumpThreading ++ // MIR for `logical_not` after JumpThreading + + fn logical_not() -> i32 { + let mut _0: i32; + let _1: bool; + let mut _2: bool; + let mut _3: bool; + let mut _4: bool; + scope 1 { + debug a => _1; + } + + bb0: { + StorageLive(_1); + _1 = const false; + StorageLive(_2); + StorageLive(_3); + StorageLive(_4); + _4 = copy _1; + _3 = Not(move _4); + StorageDead(_4); + _2 = Eq(move _3, const true); +- switchInt(move _2) -> [0: bb2, otherwise: bb1]; ++ goto -> bb1; + } + + bb1: { + StorageDead(_3); + _0 = const 1_i32; + goto -> bb3; + } + + bb2: { + StorageDead(_3); + _0 = const 0_i32; + goto -> bb3; + } + + bb3: { + StorageDead(_2); + StorageDead(_1); + return; + } + } + diff --git a/tests/mir-opt/jump_threading.rs b/tests/mir-opt/jump_threading.rs index 743ee8e728bb..009e1060700c 100644 --- a/tests/mir-opt/jump_threading.rs +++ b/tests/mir-opt/jump_threading.rs @@ -532,14 +532,19 @@ fn floats() -> u32 { pub fn bitwise_not() -> i32 { // CHECK-LABEL: fn bitwise_not( - // CHECK: switchInt( // Test for #131195, which was optimizing `!a == b` into `a != b`. - let mut a: i32 = 0; - a = 1; + let a = 1; if !a == 0 { 1 } else { 0 } } +pub fn logical_not() -> i32 { + // CHECK-LABEL: fn logical_not( + + let a = false; + if !a == true { 1 } else { 0 } +} + fn main() { // CHECK-LABEL: fn main( too_complex(Ok(0)); @@ -555,6 +560,8 @@ fn main() { aggregate(7); assume(7, false); floats(); + bitwise_not(); + logical_not(); } // EMIT_MIR jump_threading.too_complex.JumpThreading.diff @@ -572,3 +579,4 @@ fn main() { // EMIT_MIR jump_threading.aggregate_copy.JumpThreading.diff // EMIT_MIR jump_threading.floats.JumpThreading.diff // EMIT_MIR jump_threading.bitwise_not.JumpThreading.diff +// EMIT_MIR jump_threading.logical_not.JumpThreading.diff From 41a5d8ef3da4769bdd4349ef540110a6e80e6c1e Mon Sep 17 00:00:00 2001 From: clubby789 Date: Mon, 7 Oct 2024 17:31:43 +0000 Subject: [PATCH 416/606] JumpThreading: Bail out on interp errors --- .../rustc_mir_transform/src/jump_threading.rs | 158 ++++++++++-------- 1 file changed, 91 insertions(+), 67 deletions(-) diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs index 375cf88e3e9b..8b4b214a3d45 100644 --- a/compiler/rustc_mir_transform/src/jump_threading.rs +++ b/compiler/rustc_mir_transform/src/jump_threading.rs @@ -90,7 +90,11 @@ impl<'tcx> crate::MirPass<'tcx> for JumpThreading { }; for bb in body.basic_blocks.indices() { - finder.start_from_switch(bb); + let old_len = finder.opportunities.len(); + // If we have any const-eval errors discard any opportunities found + if finder.start_from_switch(bb).is_none() { + finder.opportunities.truncate(old_len); + } } let opportunities = finder.opportunities; @@ -172,8 +176,21 @@ impl<'a> ConditionSet<'a> { self.iter().filter(move |c| c.matches(value)) } - fn map(self, arena: &'a DroplessArena, f: impl Fn(Condition) -> Condition) -> ConditionSet<'a> { - ConditionSet(arena.alloc_from_iter(self.iter().map(f))) + fn map( + self, + arena: &'a DroplessArena, + f: impl Fn(Condition) -> Option, + ) -> Option> { + let mut all_ok = true; + let set = arena.alloc_from_iter(self.iter().map_while(|c| { + if let Some(c) = f(c) { + Some(c) + } else { + all_ok = false; + None + } + })); + all_ok.then_some(ConditionSet(set)) } } @@ -184,28 +201,28 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> { /// Recursion entry point to find threading opportunities. #[instrument(level = "trace", skip(self))] - fn start_from_switch(&mut self, bb: BasicBlock) { + fn start_from_switch(&mut self, bb: BasicBlock) -> Option<()> { let bbdata = &self.body[bb]; if bbdata.is_cleanup || self.loop_headers.contains(bb) { - return; + return Some(()); } - let Some((discr, targets)) = bbdata.terminator().kind.as_switch() else { return }; - let Some(discr) = discr.place() else { return }; + let Some((discr, targets)) = bbdata.terminator().kind.as_switch() else { return Some(()) }; + let Some(discr) = discr.place() else { return Some(()) }; debug!(?discr, ?bb); let discr_ty = discr.ty(self.body, self.tcx).ty; let Ok(discr_layout) = self.ecx.layout_of(discr_ty) else { - return; + return Some(()); }; - let Some(discr) = self.map.find(discr.as_ref()) else { return }; + let Some(discr) = self.map.find(discr.as_ref()) else { return Some(()) }; debug!(?discr); let cost = CostChecker::new(self.tcx, self.typing_env, None, self.body); let mut state = State::new_reachable(); let conds = if let Some((value, then, else_)) = targets.as_static_if() { - let Some(value) = ScalarInt::try_from_uint(value, discr_layout.size) else { return }; + let value = ScalarInt::try_from_uint(value, discr_layout.size)?; self.arena.alloc_from_iter([ Condition { value, polarity: Polarity::Eq, target: then }, Condition { value, polarity: Polarity::Ne, target: else_ }, @@ -219,7 +236,7 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> { let conds = ConditionSet(conds); state.insert_value_idx(discr, conds, &self.map); - self.find_opportunity(bb, state, cost, 0); + self.find_opportunity(bb, state, cost, 0) } /// Recursively walk statements backwards from this bb's terminator to find threading @@ -231,10 +248,10 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> { mut state: State>, mut cost: CostChecker<'_, 'tcx>, depth: usize, - ) { + ) -> Option<()> { // Do not thread through loop headers. if self.loop_headers.contains(bb) { - return; + return Some(()); } debug!(cost = ?cost.cost()); @@ -242,16 +259,16 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> { self.body.basic_blocks[bb].statements.iter().enumerate().rev() { if self.is_empty(&state) { - return; + return Some(()); } cost.visit_statement(stmt, Location { block: bb, statement_index }); if cost.cost() > MAX_COST { - return; + return Some(()); } // Attempt to turn the `current_condition` on `lhs` into a condition on another place. - self.process_statement(bb, stmt, &mut state); + self.process_statement(bb, stmt, &mut state)?; // When a statement mutates a place, assignments to that place that happen // above the mutation cannot fulfill a condition. @@ -263,7 +280,7 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> { } if self.is_empty(&state) || depth >= MAX_BACKTRACK { - return; + return Some(()); } let last_non_rec = self.opportunities.len(); @@ -276,9 +293,9 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> { match term.kind { TerminatorKind::SwitchInt { ref discr, ref targets } => { self.process_switch_int(discr, targets, bb, &mut state); - self.find_opportunity(pred, state, cost, depth + 1); + self.find_opportunity(pred, state, cost, depth + 1)?; } - _ => self.recurse_through_terminator(pred, || state, &cost, depth), + _ => self.recurse_through_terminator(pred, || state, &cost, depth)?, } } else if let &[ref predecessors @ .., last_pred] = &predecessors[..] { for &pred in predecessors { @@ -303,12 +320,13 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> { let first = &mut new_tos[0]; *first = ThreadingOpportunity { chain: vec![bb], target: first.target }; self.opportunities.truncate(last_non_rec + 1); - return; + return Some(()); } for op in self.opportunities[last_non_rec..].iter_mut() { op.chain.push(bb); } + Some(()) } /// Extract the mutated place from a statement. @@ -422,23 +440,23 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> { lhs: PlaceIndex, rhs: &Operand<'tcx>, state: &mut State>, - ) { + ) -> Option<()> { match rhs { // If we expect `lhs ?= A`, we have an opportunity if we assume `constant == A`. Operand::Constant(constant) => { - let Some(constant) = - self.ecx.eval_mir_constant(&constant.const_, constant.span, None).discard_err() - else { - return; - }; + let constant = self + .ecx + .eval_mir_constant(&constant.const_, constant.span, None) + .discard_err()?; self.process_constant(bb, lhs, constant, state); } // Transfer the conditions on the copied rhs. Operand::Move(rhs) | Operand::Copy(rhs) => { - let Some(rhs) = self.map.find(rhs.as_ref()) else { return }; + let Some(rhs) = self.map.find(rhs.as_ref()) else { return Some(()) }; state.insert_place_idx(rhs, lhs, &self.map); } } + Some(()) } #[instrument(level = "trace", skip(self))] @@ -448,14 +466,18 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> { lhs_place: &Place<'tcx>, rhs: &Rvalue<'tcx>, state: &mut State>, - ) { - let Some(lhs) = self.map.find(lhs_place.as_ref()) else { return }; + ) -> Option<()> { + let Some(lhs) = self.map.find(lhs_place.as_ref()) else { + return Some(()); + }; match rhs { - Rvalue::Use(operand) => self.process_operand(bb, lhs, operand, state), + Rvalue::Use(operand) => self.process_operand(bb, lhs, operand, state)?, // Transfer the conditions on the copy rhs. - Rvalue::CopyForDeref(rhs) => self.process_operand(bb, lhs, &Operand::Copy(*rhs), state), + Rvalue::CopyForDeref(rhs) => { + self.process_operand(bb, lhs, &Operand::Copy(*rhs), state)? + } Rvalue::Discriminant(rhs) => { - let Some(rhs) = self.map.find_discr(rhs.as_ref()) else { return }; + let Some(rhs) = self.map.find_discr(rhs.as_ref()) else { return Some(()) }; state.insert_place_idx(rhs, lhs, &self.map); } // If we expect `lhs ?= A`, we have an opportunity if we assume `constant == A`. @@ -463,7 +485,7 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> { let agg_ty = lhs_place.ty(self.body, self.tcx).ty; let lhs = match kind { // Do not support unions. - AggregateKind::Adt(.., Some(_)) => return, + AggregateKind::Adt(.., Some(_)) => return Some(()), AggregateKind::Adt(_, variant_index, ..) if agg_ty.is_enum() => { if let Some(discr_target) = self.map.apply(lhs, TrackElem::Discriminant) && let Some(discr_value) = self @@ -476,31 +498,31 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> { if let Some(idx) = self.map.apply(lhs, TrackElem::Variant(*variant_index)) { idx } else { - return; + return Some(()); } } _ => lhs, }; for (field_index, operand) in operands.iter_enumerated() { if let Some(field) = self.map.apply(lhs, TrackElem::Field(field_index)) { - self.process_operand(bb, field, operand, state); + self.process_operand(bb, field, operand, state)?; } } } // Transfer the conditions on the copy rhs, after inverting the value of the condition. Rvalue::UnaryOp(UnOp::Not, Operand::Move(place) | Operand::Copy(place)) => { let layout = self.ecx.layout_of(place.ty(self.body, self.tcx).ty).unwrap(); - let Some(conditions) = state.try_get_idx(lhs, &self.map) else { return }; - let Some(place) = self.map.find(place.as_ref()) else { return }; + let Some(conditions) = state.try_get_idx(lhs, &self.map) else { return Some(()) }; + let Some(place) = self.map.find(place.as_ref()) else { return Some(()) }; let conds = conditions.map(self.arena, |mut cond| { cond.value = self .ecx .unary_op(UnOp::Not, &ImmTy::from_scalar_int(cond.value, layout)) - .unwrap() + .discard_err()? .to_scalar_int() - .unwrap(); - cond - }); + .discard_err()?; + Some(cond) + })?; state.insert_value_idx(place, conds, &self.map); } // We expect `lhs ?= A`. We found `lhs = Eq(rhs, B)`. @@ -510,34 +532,34 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> { box (Operand::Move(place) | Operand::Copy(place), Operand::Constant(value)) | box (Operand::Constant(value), Operand::Move(place) | Operand::Copy(place)), ) => { - let Some(conditions) = state.try_get_idx(lhs, &self.map) else { return }; - let Some(place) = self.map.find(place.as_ref()) else { return }; + let Some(conditions) = state.try_get_idx(lhs, &self.map) else { return Some(()) }; + let Some(place) = self.map.find(place.as_ref()) else { return Some(()) }; let equals = match op { BinOp::Eq => ScalarInt::TRUE, BinOp::Ne => ScalarInt::FALSE, - _ => return, + _ => return Some(()), }; if value.const_.ty().is_floating_point() { // Floating point equality does not follow bit-patterns. // -0.0 and NaN both have special rules for equality, // and therefore we cannot use integer comparisons for them. // Avoid handling them, though this could be extended in the future. - return; + return Some(()); } - let Some(value) = value.const_.try_eval_scalar_int(self.tcx, self.typing_env) - else { - return; - }; - let conds = conditions.map(self.arena, |c| Condition { - value, - polarity: if c.matches(equals) { Polarity::Eq } else { Polarity::Ne }, - ..c - }); + let value = value.const_.try_eval_scalar_int(self.tcx, self.typing_env)?; + let conds = conditions.map(self.arena, |c| { + Some(Condition { + value, + polarity: if c.matches(equals) { Polarity::Eq } else { Polarity::Ne }, + ..c + }) + })?; state.insert_value_idx(place, conds, &self.map); } _ => {} } + Some(()) } #[instrument(level = "trace", skip(self))] @@ -546,7 +568,7 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> { bb: BasicBlock, stmt: &Statement<'tcx>, state: &mut State>, - ) { + ) -> Option<()> { let register_opportunity = |c: Condition| { debug!(?bb, ?c.target, "register"); self.opportunities.push(ThreadingOpportunity { chain: vec![bb], target: c.target }) @@ -559,30 +581,32 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> { // If we expect `discriminant(place) ?= A`, // we have an opportunity if `variant_index ?= A`. StatementKind::SetDiscriminant { box place, variant_index } => { - let Some(discr_target) = self.map.find_discr(place.as_ref()) else { return }; + let Some(discr_target) = self.map.find_discr(place.as_ref()) else { + return Some(()); + }; let enum_ty = place.ty(self.body, self.tcx).ty; // `SetDiscriminant` guarantees that the discriminant is now `variant_index`. // Even if the discriminant write does nothing due to niches, it is UB to set the // discriminant when the data does not encode the desired discriminant. - let Some(discr) = - self.ecx.discriminant_for_variant(enum_ty, *variant_index).discard_err() - else { - return; - }; + let discr = + self.ecx.discriminant_for_variant(enum_ty, *variant_index).discard_err()?; self.process_immediate(bb, discr_target, discr, state); } // If we expect `lhs ?= true`, we have an opportunity if we assume `lhs == true`. StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume( Operand::Copy(place) | Operand::Move(place), )) => { - let Some(conditions) = state.try_get(place.as_ref(), &self.map) else { return }; + let Some(conditions) = state.try_get(place.as_ref(), &self.map) else { + return Some(()); + }; conditions.iter_matches(ScalarInt::TRUE).for_each(register_opportunity); } StatementKind::Assign(box (lhs_place, rhs)) => { - self.process_assign(bb, lhs_place, rhs, state); + self.process_assign(bb, lhs_place, rhs, state)?; } _ => {} } + Some(()) } #[instrument(level = "trace", skip(self, state, cost))] @@ -593,7 +617,7 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> { state: impl FnOnce() -> State>, cost: &CostChecker<'_, 'tcx>, depth: usize, - ) { + ) -> Option<()> { let term = self.body.basic_blocks[bb].terminator(); let place_to_flood = match term.kind { // We come from a target, so those are not possible. @@ -608,9 +632,9 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> { | TerminatorKind::FalseUnwind { .. } | TerminatorKind::Yield { .. } => bug!("{term:?} invalid"), // Cannot reason about inline asm. - TerminatorKind::InlineAsm { .. } => return, + TerminatorKind::InlineAsm { .. } => return Some(()), // `SwitchInt` is handled specially. - TerminatorKind::SwitchInt { .. } => return, + TerminatorKind::SwitchInt { .. } => return Some(()), // We can recurse, no thing particular to do. TerminatorKind::Goto { .. } => None, // Flood the overwritten place, and progress through. @@ -625,7 +649,7 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> { if let Some(place_to_flood) = place_to_flood { state.flood_with(place_to_flood.as_ref(), &self.map, ConditionSet::BOTTOM); } - self.find_opportunity(bb, state, cost.clone(), depth + 1); + self.find_opportunity(bb, state, cost.clone(), depth + 1) } #[instrument(level = "trace", skip(self))] From d50a8d5fb3727277f82440524e20a67e29dead4c Mon Sep 17 00:00:00 2001 From: jyn Date: Tue, 11 Mar 2025 00:24:08 -0400 Subject: [PATCH 417/606] Improve `-Z crate-attr` diagnostics - Show the `#![ ... ]` in the span (to make it clear that it should not be included in the CLI argument) - Show more detailed errors when the crate has valid token trees but invalid syntax. Previously, `crate-attr=feature(foo),feature(bar)` would just say "invalid crate attribute" and point at the comma. Now, it explicitly says that the comma was unexpected, which is useful when using `--error-format=short`. It also fixes the column to show the correct span. - Recover from parse errors. Previously we would abort immediately on syntax errors; now we go on to try and type-check the rest of the crate. The new diagnostic code also happens to be slightly shorter. --- compiler/rustc_ast/src/attr/mod.rs | 2 +- compiler/rustc_builtin_macros/messages.ftl | 2 - .../rustc_builtin_macros/src/cmdline_attrs.rs | 57 ++++++++----------- compiler/rustc_builtin_macros/src/errors.rs | 7 --- .../ui/attributes/z-crate-attr/garbage.stderr | 16 +++--- tests/ui/attributes/z-crate-attr/injection.rs | 6 +- .../attributes/z-crate-attr/injection.stderr | 17 ++++-- .../ui/attributes/z-crate-attr/injection2.rs | 3 + .../attributes/z-crate-attr/injection2.stderr | 15 +++++ .../attributes/z-crate-attr/inner-attr.stderr | 6 +- tests/ui/attributes/z-crate-attr/multiple.rs | 4 +- .../attributes/z-crate-attr/multiple.stderr | 8 +-- .../z-crate-attr/unbalanced-paren.rs | 4 +- .../z-crate-attr/unbalanced-paren.stderr | 13 +++-- 14 files changed, 82 insertions(+), 78 deletions(-) create mode 100644 tests/ui/attributes/z-crate-attr/injection2.rs create mode 100644 tests/ui/attributes/z-crate-attr/injection2.stderr diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index 0b65246693dd..d656d9b0b8af 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -627,7 +627,7 @@ pub fn mk_doc_comment( Attribute { kind: AttrKind::DocComment(comment_kind, data), id: g.mk_attr_id(), style, span } } -pub fn mk_attr( +fn mk_attr( g: &AttrIdGenerator, style: AttrStyle, unsafety: Safety, diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl index 603dc90bafca..5316e90847ac 100644 --- a/compiler/rustc_builtin_macros/messages.ftl +++ b/compiler/rustc_builtin_macros/messages.ftl @@ -231,8 +231,6 @@ builtin_macros_format_unused_args = multiple unused formatting arguments builtin_macros_format_use_positional = consider using a positional formatting argument instead -builtin_macros_invalid_crate_attribute = invalid crate attribute - builtin_macros_multiple_default_attrs = multiple `#[default]` attributes .note = only one `#[default]` attribute is needed .label = `#[default]` used here diff --git a/compiler/rustc_builtin_macros/src/cmdline_attrs.rs b/compiler/rustc_builtin_macros/src/cmdline_attrs.rs index 6afd8c4b43b9..423b6a15b646 100644 --- a/compiler/rustc_builtin_macros/src/cmdline_attrs.rs +++ b/compiler/rustc_builtin_macros/src/cmdline_attrs.rs @@ -1,44 +1,37 @@ //! Attributes injected into the crate root from command line using `-Z crate-attr`. -use rustc_ast::attr::mk_attr; -use rustc_ast::{self as ast, AttrItem, AttrStyle, token}; -use rustc_parse::parser::ForceCollect; -use rustc_parse::{new_parser_from_source_str, unwrap_or_emit_fatal}; +use rustc_ast::{self as ast}; +use rustc_errors::Diag; +use rustc_parse::parser::attr::InnerAttrPolicy; +use rustc_parse::{parse_in, source_str_to_stream}; use rustc_session::parse::ParseSess; use rustc_span::FileName; -use crate::errors; - pub fn inject(krate: &mut ast::Crate, psess: &ParseSess, attrs: &[String]) { for raw_attr in attrs { - let mut parser = unwrap_or_emit_fatal(new_parser_from_source_str( - psess, - FileName::cli_crate_attr_source_code(raw_attr), - raw_attr.clone(), - )); - - let start_span = parser.token.span; - let AttrItem { unsafety, path, args, tokens: _ } = - match parser.parse_attr_item(ForceCollect::No) { - Ok(ai) => ai, - Err(err) => { + let source = format!("#![{raw_attr}]"); + let parse = || -> Result>> { + let tokens = source_str_to_stream( + psess, + FileName::cli_crate_attr_source_code(raw_attr), + source, + None, + )?; + parse_in(psess, tokens, "", |p| { + p.parse_attribute(InnerAttrPolicy::Permitted) + }) + .map_err(|e| vec![e]) + }; + let meta = match parse() { + Ok(meta) => meta, + Err(errs) => { + for err in errs { err.emit(); - continue; } - }; - let end_span = parser.token.span; - if parser.token != token::Eof { - psess.dcx().emit_err(errors::InvalidCrateAttr { span: start_span.to(end_span) }); - continue; - } + continue; + } + }; - krate.attrs.push(mk_attr( - &psess.attr_id_generator, - AttrStyle::Inner, - unsafety, - path, - args, - start_span.to(end_span), - )); + krate.attrs.push(meta); } } diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index 4bbe212f4296..c2b1dff4cf1f 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -109,13 +109,6 @@ pub(crate) struct ProcMacro { pub(crate) span: Span, } -#[derive(Diagnostic)] -#[diag(builtin_macros_invalid_crate_attribute)] -pub(crate) struct InvalidCrateAttr { - #[primary_span] - pub(crate) span: Span, -} - #[derive(Diagnostic)] #[diag(builtin_macros_non_abi)] pub(crate) struct NonABI { diff --git a/tests/ui/attributes/z-crate-attr/garbage.stderr b/tests/ui/attributes/z-crate-attr/garbage.stderr index 082046e31f8c..12d18b0845fc 100644 --- a/tests/ui/attributes/z-crate-attr/garbage.stderr +++ b/tests/ui/attributes/z-crate-attr/garbage.stderr @@ -1,20 +1,20 @@ error: unknown start of token: ` - --> :1:1 + --> :1:4 | -LL | `%~@$# - | ^ +LL | #![`%~@$#] + | ^ | help: Unicode character '`' (Grave Accent) looks like ''' (Single Quote), but it is not | -LL - `%~@$# -LL + '%~@$# +LL - #![`%~@$#] +LL + #!['%~@$#] | error: expected identifier, found `%` - --> :1:2 + --> :1:5 | -LL | `%~@$# - | ^ expected identifier +LL | #![`%~@$#] + | ^ expected identifier error: aborting due to 2 previous errors diff --git a/tests/ui/attributes/z-crate-attr/injection.rs b/tests/ui/attributes/z-crate-attr/injection.rs index a91f9d2886e3..ee7a27c7490c 100644 --- a/tests/ui/attributes/z-crate-attr/injection.rs +++ b/tests/ui/attributes/z-crate-attr/injection.rs @@ -1,5 +1,3 @@ //@ compile-flags: '-Zcrate-attr=feature(yeet_expr)]fn main(){}#[inline' - -fn foo() {} - -//~? ERROR unexpected closing delimiter: `]` +//~? ERROR unexpected token +fn foo() {} //~ ERROR `main` function not found diff --git a/tests/ui/attributes/z-crate-attr/injection.stderr b/tests/ui/attributes/z-crate-attr/injection.stderr index 6fec98baf8df..899dad07e604 100644 --- a/tests/ui/attributes/z-crate-attr/injection.stderr +++ b/tests/ui/attributes/z-crate-attr/injection.stderr @@ -1,8 +1,15 @@ -error: unexpected closing delimiter: `]` - --> :1:19 +error: unexpected token: keyword `fn` + --> :1:23 | -LL | feature(yeet_expr)]fn main(){}#[inline - | ^ unexpected closing delimiter +LL | #![feature(yeet_expr)]fn main(){}#[inline] + | ^^ unexpected token after this -error: aborting due to 1 previous error +error[E0601]: `main` function not found in crate `injection` + --> $DIR/injection.rs:3:12 + | +LL | fn foo() {} + | ^ consider adding a `main` function to `$DIR/injection.rs` +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0601`. diff --git a/tests/ui/attributes/z-crate-attr/injection2.rs b/tests/ui/attributes/z-crate-attr/injection2.rs new file mode 100644 index 000000000000..67ae3d17f3e7 --- /dev/null +++ b/tests/ui/attributes/z-crate-attr/injection2.rs @@ -0,0 +1,3 @@ +//@ compile-flags: -Zcrate-attr=feature(yeet_expr)]#![allow(warnings) +//~? ERROR unexpected token +fn foo() {} //~ ERROR `main` function not found diff --git a/tests/ui/attributes/z-crate-attr/injection2.stderr b/tests/ui/attributes/z-crate-attr/injection2.stderr new file mode 100644 index 000000000000..51f54f900a19 --- /dev/null +++ b/tests/ui/attributes/z-crate-attr/injection2.stderr @@ -0,0 +1,15 @@ +error: unexpected token: `#` + --> :1:23 + | +LL | #![feature(yeet_expr)]#![allow(warnings)] + | ^ unexpected token after this + +error[E0601]: `main` function not found in crate `injection2` + --> $DIR/injection2.rs:3:12 + | +LL | fn foo() {} + | ^ consider adding a `main` function to `$DIR/injection2.rs` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0601`. diff --git a/tests/ui/attributes/z-crate-attr/inner-attr.stderr b/tests/ui/attributes/z-crate-attr/inner-attr.stderr index 06a063d310b6..1acb8c2e750b 100644 --- a/tests/ui/attributes/z-crate-attr/inner-attr.stderr +++ b/tests/ui/attributes/z-crate-attr/inner-attr.stderr @@ -1,8 +1,8 @@ error: expected identifier, found `#` - --> :1:1 + --> :1:4 | -LL | #![feature(foo)] - | ^ expected identifier +LL | #![#![feature(foo)]] + | ^ expected identifier error: aborting due to 1 previous error diff --git a/tests/ui/attributes/z-crate-attr/multiple.rs b/tests/ui/attributes/z-crate-attr/multiple.rs index 47d35d2c3fdf..8c60ea64feca 100644 --- a/tests/ui/attributes/z-crate-attr/multiple.rs +++ b/tests/ui/attributes/z-crate-attr/multiple.rs @@ -1,5 +1,3 @@ //@ compile-flags: -Zcrate-attr=feature(foo),feature(bar) - +//~? ERROR expected `]` fn main() {} - -//~? ERROR invalid crate attribute diff --git a/tests/ui/attributes/z-crate-attr/multiple.stderr b/tests/ui/attributes/z-crate-attr/multiple.stderr index 9f968a7e1346..b95c95dcd739 100644 --- a/tests/ui/attributes/z-crate-attr/multiple.stderr +++ b/tests/ui/attributes/z-crate-attr/multiple.stderr @@ -1,8 +1,8 @@ -error: invalid crate attribute - --> :1:1 +error: expected `]`, found `,` + --> :1:16 | -LL | feature(foo),feature(bar) - | ^^^^^^^^^^^^^ +LL | #![feature(foo),feature(bar)] + | ^ expected `]` error: aborting due to 1 previous error diff --git a/tests/ui/attributes/z-crate-attr/unbalanced-paren.rs b/tests/ui/attributes/z-crate-attr/unbalanced-paren.rs index 77d5d698f659..5ef0a75a3a87 100644 --- a/tests/ui/attributes/z-crate-attr/unbalanced-paren.rs +++ b/tests/ui/attributes/z-crate-attr/unbalanced-paren.rs @@ -1,6 +1,4 @@ // Show diagnostics for unbalanced parens. //@ compile-flags: -Zcrate-attr=( - +//~? ERROR mismatched closing delimiter fn main() {} - -//~? ERROR this file contains an unclosed delimiter diff --git a/tests/ui/attributes/z-crate-attr/unbalanced-paren.stderr b/tests/ui/attributes/z-crate-attr/unbalanced-paren.stderr index 47b1b764ba9a..f6545d1db8bc 100644 --- a/tests/ui/attributes/z-crate-attr/unbalanced-paren.stderr +++ b/tests/ui/attributes/z-crate-attr/unbalanced-paren.stderr @@ -1,10 +1,11 @@ -error: this file contains an unclosed delimiter - --> :1:2 +error: mismatched closing delimiter: `]` + --> :1:4 | -LL | ( - | -^ - | | - | unclosed delimiter +LL | #![(] + | -^^ mismatched closing delimiter + | || + | |unclosed delimiter + | closing delimiter possibly meant for this error: aborting due to 1 previous error From 2f96e784e2f2085087ababfc509fb877000299fe Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 13 Apr 2025 22:01:54 +0000 Subject: [PATCH 418/606] Visit place in BackwardIncompatibleDropHint statement --- compiler/rustc_borrowck/src/def_use.rs | 3 +++ compiler/rustc_borrowck/src/lib.rs | 2 +- compiler/rustc_middle/src/mir/pretty.rs | 2 +- compiler/rustc_middle/src/mir/visit.rs | 14 ++++++++++++-- .../src/cleanup_post_borrowck.rs | 3 ++- compiler/rustc_mir_transform/src/simplify.rs | 14 -------------- ...d.method_1.ElaborateDrops.after.panic-abort.mir | 3 --- ....method_1.ElaborateDrops.after.panic-unwind.mir | 3 --- 8 files changed, 19 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_borrowck/src/def_use.rs b/compiler/rustc_borrowck/src/def_use.rs index 263f68d6a3dc..b9ced81c46c1 100644 --- a/compiler/rustc_borrowck/src/def_use.rs +++ b/compiler/rustc_borrowck/src/def_use.rs @@ -77,6 +77,9 @@ pub(crate) fn categorize(context: PlaceContext) -> Option { // Debug info is neither def nor use. PlaceContext::NonUse(NonUseContext::VarDebugInfo) => None, + // Backwards incompatible drop hint is not a use, just a marker for linting. + PlaceContext::NonUse(NonUseContext::BackwardIncompatibleDropHint) => None, + PlaceContext::MutatingUse(MutatingUseContext::Deinit | MutatingUseContext::SetDiscriminant) => { bug!("These statements are not allowed in this MIR phase") } diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 64ad1c968565..f6903250a2e9 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -1301,7 +1301,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { error_reported } - /// Through #123739, backward incompatible drops (BIDs) are introduced. + /// Through #123739, `BackwardIncompatibleDropHint`s (BIDs) are introduced. /// We would like to emit lints whether borrow checking fails at these future drop locations. #[instrument(level = "debug", skip(self, state))] fn check_backward_incompatible_drop( diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 5a038b27337c..bf701e309698 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -859,7 +859,7 @@ impl Debug for Statement<'_> { BackwardIncompatibleDropHint { ref place, reason: _ } => { // For now, we don't record the reason because there is only one use case, // which is to report breaking change in drop order by Edition 2024 - write!(fmt, "backward incompatible drop({place:?})") + write!(fmt, "BackwardIncompatibleDropHint({place:?})") } } } diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 3c83d962900a..de4d5140e857 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -457,9 +457,15 @@ macro_rules! make_mir_visitor { } } } + StatementKind::BackwardIncompatibleDropHint { place, .. } => { + self.visit_place( + place, + PlaceContext::NonUse(NonUseContext::BackwardIncompatibleDropHint), + location + ); + } StatementKind::ConstEvalCounter => {} StatementKind::Nop => {} - StatementKind::BackwardIncompatibleDropHint { .. } => {} } } @@ -1348,6 +1354,8 @@ pub enum NonUseContext { AscribeUserTy(ty::Variance), /// The data of a user variable, for debug info. VarDebugInfo, + /// A `BackwardIncompatibleDropHint` statement, meant for edition 2024 lints. + BackwardIncompatibleDropHint, } #[derive(Copy, Clone, Debug, PartialEq, Eq)] @@ -1422,7 +1430,9 @@ impl PlaceContext { use NonUseContext::*; match self { PlaceContext::MutatingUse(_) => ty::Invariant, - PlaceContext::NonUse(StorageDead | StorageLive | VarDebugInfo) => ty::Invariant, + PlaceContext::NonUse( + StorageDead | StorageLive | VarDebugInfo | BackwardIncompatibleDropHint, + ) => ty::Invariant, PlaceContext::NonMutatingUse( Inspect | Copy | Move | PlaceMention | SharedBorrow | FakeBorrow | RawBorrow | Projection, diff --git a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs index cb8440198573..4be67b873f73 100644 --- a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs +++ b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs @@ -35,7 +35,8 @@ impl<'tcx> crate::MirPass<'tcx> for CleanupPostBorrowck { // MIR building, and are not needed after InstrumentCoverage. CoverageKind::BlockMarker { .. } | CoverageKind::SpanMarker { .. }, ) - | StatementKind::FakeRead(..) => statement.make_nop(), + | StatementKind::FakeRead(..) + | StatementKind::BackwardIncompatibleDropHint { .. } => statement.make_nop(), StatementKind::Assign(box ( _, Rvalue::Cast( diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index 84905f4a400f..5947637cded9 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -597,20 +597,6 @@ impl<'tcx> MutVisitor<'tcx> for LocalUpdater<'tcx> { self.tcx } - fn visit_statement(&mut self, statement: &mut Statement<'tcx>, location: Location) { - if let StatementKind::BackwardIncompatibleDropHint { place, reason: _ } = - &mut statement.kind - { - self.visit_local( - &mut place.local, - PlaceContext::MutatingUse(MutatingUseContext::Store), - location, - ); - } else { - self.super_statement(statement, location); - } - } - fn visit_local(&mut self, l: &mut Local, _: PlaceContext, _: Location) { *l = self.map[*l].unwrap(); } diff --git a/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-abort.mir b/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-abort.mir index ee6e16d20fd8..7d7cb76960ed 100644 --- a/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-abort.mir +++ b/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-abort.mir @@ -73,9 +73,6 @@ fn method_1(_1: Guard) -> () { } bb7: { - backward incompatible drop(_2); - backward incompatible drop(_4); - backward incompatible drop(_5); goto -> bb21; } diff --git a/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-unwind.mir b/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-unwind.mir index ee6e16d20fd8..7d7cb76960ed 100644 --- a/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-unwind.mir +++ b/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-unwind.mir @@ -73,9 +73,6 @@ fn method_1(_1: Guard) -> () { } bb7: { - backward incompatible drop(_2); - backward incompatible drop(_4); - backward incompatible drop(_5); goto -> bb21; } From 75558b2ffe4f7f8ece1c964bf8b791f6f475b914 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 2 Apr 2025 10:11:22 +1100 Subject: [PATCH 419/606] Remove unused `StaticLifetimeVisitor`. --- compiler/rustc_middle/src/ty/diagnostics.rs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index d3abb3d64b8c..674c7a5e3ee7 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -592,18 +592,6 @@ impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor<'v> { } } -/// Collect al types that have an implicit `'static` obligation that we could suggest `'_` for. -pub struct StaticLifetimeVisitor<'tcx>(pub Vec, pub crate::hir::map::Map<'tcx>); - -impl<'v> hir::intravisit::Visitor<'v> for StaticLifetimeVisitor<'v> { - fn visit_lifetime(&mut self, lt: &'v hir::Lifetime) { - if let hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Static = lt.res - { - self.0.push(lt.ident.span); - } - } -} - pub struct IsSuggestableVisitor<'tcx> { tcx: TyCtxt<'tcx>, infer_suggestable: bool, From 7c5f2265e8267f9f116086d31d7ec83c0198c37b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 2 Apr 2025 10:13:05 +1100 Subject: [PATCH 420/606] Remove unused `Map` field from `TraitObjectVisitor`. Also reduce visibility. --- compiler/rustc_middle/src/ty/context.rs | 4 ++-- compiler/rustc_middle/src/ty/diagnostics.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index abf6cbbcd877..92d7645bf747 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2147,7 +2147,7 @@ impl<'tcx> TyCtxt<'tcx> { return vec![]; }; - let mut v = TraitObjectVisitor(vec![], self.hir()); + let mut v = TraitObjectVisitor(vec![]); v.visit_ty_unambig(hir_output); v.0 } @@ -2160,7 +2160,7 @@ impl<'tcx> TyCtxt<'tcx> { scope_def_id: LocalDefId, ) -> Option<(Vec<&'tcx hir::Ty<'tcx>>, Span, Option)> { let hir_id = self.local_def_id_to_hir_id(scope_def_id); - let mut v = TraitObjectVisitor(vec![], self.hir()); + let mut v = TraitObjectVisitor(vec![]); // when the return type is a type alias if let Some(hir::FnDecl { output: hir::FnRetTy::Return(hir_output), .. }) = self.hir_fn_decl_by_hir_id(hir_id) && let hir::TyKind::Path(hir::QPath::Resolved( diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 674c7a5e3ee7..09db6eee2c9e 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -571,7 +571,7 @@ pub fn suggest_constraining_type_params<'a>( } /// Collect al types that have an implicit `'static` obligation that we could suggest `'_` for. -pub struct TraitObjectVisitor<'tcx>(pub Vec<&'tcx hir::Ty<'tcx>>, pub crate::hir::map::Map<'tcx>); +pub(crate) struct TraitObjectVisitor<'tcx>(pub(crate) Vec<&'tcx hir::Ty<'tcx>>); impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor<'v> { fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) { From 1a3dee40628c01733af12bae02c32d856db6cb0d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 2 Apr 2025 10:08:37 +1100 Subject: [PATCH 421/606] Remove `rustc_middle::hir::Map`. It's unused. --- compiler/rustc_middle/src/hir/map.rs | 10 ---------- compiler/rustc_middle/src/hir/mod.rs | 5 ----- 2 files changed, 15 deletions(-) diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs index daf95420c432..e0dd76bce824 100644 --- a/compiler/rustc_middle/src/hir/map.rs +++ b/compiler/rustc_middle/src/hir/map.rs @@ -18,16 +18,6 @@ use crate::middle::debugger_visualizer::DebuggerVisualizerFile; use crate::query::LocalCrate; use crate::ty::TyCtxt; -// FIXME: the structure was necessary in the past but now it -// only serves as "namespace" for HIR-related methods, and can be -// removed if all the methods are reasonably renamed and moved to tcx -// (https://github.com/rust-lang/rust/pull/118256#issuecomment-1826442834). -#[allow(unused)] // FIXME: temporary -#[derive(Copy, Clone)] -pub struct Map<'hir> { - pub(super) tcx: TyCtxt<'hir>, -} - /// An iterator that walks up the ancestor tree of a given `HirId`. /// Constructed using `tcx.hir_parent_iter(hir_id)`. struct ParentHirIterator<'tcx> { diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index 640ac70d3a75..a28dcb0cb8ef 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -116,11 +116,6 @@ impl ModuleItems { } impl<'tcx> TyCtxt<'tcx> { - #[inline(always)] - pub fn hir(self) -> map::Map<'tcx> { - map::Map { tcx: self } - } - pub fn parent_module(self, id: HirId) -> LocalModDefId { if !id.is_owner() && self.def_kind(id.owner) == DefKind::Mod { LocalModDefId::new_unchecked(id.owner.def_id) From 9734e44b836fa66546b7acc116ad579685f5112e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 2 Apr 2025 13:00:45 +1100 Subject: [PATCH 422/606] Documentation fixes. Remove old references to the HIR map. --- compiler/rustc_hir/src/intravisit.rs | 2 +- compiler/rustc_middle/src/hir/map.rs | 6 ++- compiler/rustc_middle/src/query/mod.rs | 16 +++---- .../rustc-dev-guide/src/appendix/glossary.md | 1 - src/doc/rustc-dev-guide/src/hir.md | 43 ++++++++----------- 5 files changed, 33 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 93d20dfa7996..3c2897ef1d95 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -6,7 +6,7 @@ //! 1. **Shallow visit**: Get a simple callback for every item (or item-like thing) in the HIR. //! - Example: find all items with a `#[foo]` attribute on them. //! - How: Use the `hir_crate_items` or `hir_module_items` query to traverse over item-like ids -//! (ItemId, TraitItemId, etc.) and use tcx.def_kind and `tcx.hir().item*(id)` to filter and +//! (ItemId, TraitItemId, etc.) and use tcx.def_kind and `tcx.hir_item*(id)` to filter and //! access actual item-like thing, respectively. //! - Pro: Efficient; just walks the lists of item ids and gives users control whether to access //! the hir_owners themselves or not. diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs index e0dd76bce824..fee707f7b4c9 100644 --- a/compiler/rustc_middle/src/hir/map.rs +++ b/compiler/rustc_middle/src/hir/map.rs @@ -1,3 +1,7 @@ +//! This module used to contain a type called `Map`. That type has since been +//! eliminated, and all its methods are now on `TyCtxt`. But the module name +//! stays as `map` because there isn't an obviously better name for it. + use rustc_abi::ExternAbi; use rustc_ast::visit::{VisitorResult, walk_list}; use rustc_data_structures::fingerprint::Fingerprint; @@ -325,7 +329,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Returns an iterator of the `DefId`s for all body-owners in this /// crate. If you would prefer to iterate over the bodies - /// themselves, you can do `self.hir().krate().body_ids.iter()`. + /// themselves, you can do `self.hir_crate(()).body_ids.iter()`. #[inline] pub fn hir_body_owners(self) -> impl Iterator { self.hir_crate_items(()).body_owners.iter().copied() diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 28a59d3e73e8..e94f088304b1 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -161,11 +161,11 @@ rustc_queries! { /// Represents crate as a whole (as distinct from the top-level crate module). /// - /// If you call `hir_crate` (e.g., indirectly by calling `tcx.hir_crate()`), - /// we will have to assume that any change means that you need to be recompiled. - /// This is because the `hir_crate` query gives you access to all other items. - /// To avoid this fate, do not call `tcx.hir_crate()`; instead, - /// prefer wrappers like [`TyCtxt::hir_visit_all_item_likes_in_crate`]. + /// If you call `tcx.hir_crate(())` we will have to assume that any change + /// means that you need to be recompiled. This is because the `hir_crate` + /// query gives you access to all other items. To avoid this fate, do not + /// call `tcx.hir_crate(())`; instead, prefer wrappers like + /// [`TyCtxt::hir_visit_all_item_likes_in_crate`]. query hir_crate(key: ()) -> &'tcx Crate<'tcx> { arena_cache eval_always @@ -197,7 +197,7 @@ rustc_queries! { /// Gives access to the HIR node's parent for the HIR owner `key`. /// - /// This can be conveniently accessed by methods on `tcx.hir()`. + /// This can be conveniently accessed by `tcx.hir_*` methods. /// Avoid calling this query directly. query hir_owner_parent(key: hir::OwnerId) -> hir::HirId { desc { |tcx| "getting HIR parent of `{}`", tcx.def_path_str(key) } @@ -205,7 +205,7 @@ rustc_queries! { /// Gives access to the HIR nodes and bodies inside `key` if it's a HIR owner. /// - /// This can be conveniently accessed by methods on `tcx.hir()`. + /// This can be conveniently accessed by `tcx.hir_*` methods. /// Avoid calling this query directly. query opt_hir_owner_nodes(key: LocalDefId) -> Option<&'tcx hir::OwnerNodes<'tcx>> { desc { |tcx| "getting HIR owner items in `{}`", tcx.def_path_str(key) } @@ -214,7 +214,7 @@ rustc_queries! { /// Gives access to the HIR attributes inside the HIR owner `key`. /// - /// This can be conveniently accessed by methods on `tcx.hir()`. + /// This can be conveniently accessed by `tcx.hir_*` methods. /// Avoid calling this query directly. query hir_attr_map(key: hir::OwnerId) -> &'tcx hir::AttributeMap<'tcx> { desc { |tcx| "getting HIR owner attributes in `{}`", tcx.def_path_str(key) } diff --git a/src/doc/rustc-dev-guide/src/appendix/glossary.md b/src/doc/rustc-dev-guide/src/appendix/glossary.md index a7c3236d356b..1837b59e850a 100644 --- a/src/doc/rustc-dev-guide/src/appendix/glossary.md +++ b/src/doc/rustc-dev-guide/src/appendix/glossary.md @@ -31,7 +31,6 @@ Term | Meaning generics | The list of generic parameters defined on an item. There are three kinds of generic parameters: Type, lifetime and const parameters. HIR | The _high-level [IR](#ir)_, created by lowering and desugaring the AST. ([see more](../hir.md)) `HirId` | Identifies a particular node in the HIR by combining a def-id with an "intra-definition offset". See [the HIR chapter for more](../hir.md#identifiers-in-the-hir). -HIR map | The HIR map, accessible via `tcx.hir()`, allows you to quickly navigate the HIR and convert between various forms of identifiers. ICE | Short for _internal compiler error_, this is when the compiler crashes. ICH | Short for _incremental compilation hash_, these are used as fingerprints for things such as HIR and crate metadata, to check if changes have been made. This is useful in incremental compilation to see if part of a crate has changed and should be recompiled. `infcx` | The type inference context (`InferCtxt`). (see `rustc_middle::infer`) diff --git a/src/doc/rustc-dev-guide/src/hir.md b/src/doc/rustc-dev-guide/src/hir.md index 75f5a9e20452..65779f3129d9 100644 --- a/src/doc/rustc-dev-guide/src/hir.md +++ b/src/doc/rustc-dev-guide/src/hir.md @@ -100,7 +100,7 @@ The HIR uses a bunch of different identifiers that coexist and serve different p a wrapper around a [`HirId`]. For more info about HIR bodies, please refer to the [HIR chapter][hir-bodies]. -These identifiers can be converted into one another through the [HIR map][map]. +These identifiers can be converted into one another through the `TyCtxt`. [`DefId`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/def_id/struct.DefId.html [`LocalDefId`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/def_id/struct.LocalDefId.html @@ -110,30 +110,24 @@ These identifiers can be converted into one another through the [HIR map][map]. [`CrateNum`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/def_id/struct.CrateNum.html [`DefIndex`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/def_id/struct.DefIndex.html [`Body`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir/struct.Body.html -[hir-map]: ./hir.md#the-hir-map [hir-bodies]: ./hir.md#hir-bodies -[map]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/map/struct.Map.html -## The HIR Map +## HIR Operations Most of the time when you are working with the HIR, you will do so via -the **HIR Map**, accessible in the tcx via [`tcx.hir()`] (and defined in -the [`hir::map`] module). The [HIR map] contains a [number of methods] to -convert between IDs of various kinds and to lookup data associated -with a HIR node. +`TyCtxt`. It contains a number of methods, defined in the `hir::map` module and +mostly prefixed with `hir_`, to convert between IDs of various kinds and to +lookup data associated with a HIR node. -[`tcx.hir()`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html#method.hir -[`hir::map`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/map/index.html -[HIR map]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/map/struct.Map.html -[number of methods]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/map/struct.Map.html#methods +[`TyCtxt`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html For example, if you have a [`LocalDefId`], and you would like to convert it -to a [`HirId`], you can use [`tcx.hir().local_def_id_to_hir_id(def_id)`][local_def_id_to_hir_id]. +to a [`HirId`], you can use [`tcx.local_def_id_to_hir_id(def_id)`][local_def_id_to_hir_id]. You need a `LocalDefId`, rather than a `DefId`, since only local items have HIR nodes. -[local_def_id_to_hir_id]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/map/struct.Map.html#method.local_def_id_to_hir_id +[local_def_id_to_hir_id]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html#method.local_def_id_to_hir_id -Similarly, you can use [`tcx.hir().find(n)`][find] to lookup the node for a +Similarly, you can use [`tcx.hir_node(n)`][hir_node] to lookup the node for a [`HirId`]. This returns a `Option>`, where [`Node`] is an enum defined in the map. By matching on this, you can find out what sort of node the `HirId` referred to and also get a pointer to the data @@ -142,15 +136,16 @@ that `n` must be some HIR expression, you can do [`tcx.hir_expect_expr(n)`][expect_expr], which will extract and return the [`&hir::Expr`][Expr], panicking if `n` is not in fact an expression. -[find]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/map/struct.Map.html#method.find +[hir_node]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html#method.hir_node [`Node`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir/enum.Node.html [expect_expr]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html#method.expect_expr [Expr]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir/struct.Expr.html -Finally, you can use the HIR map to find the parents of nodes, via -calls like [`tcx.hir().get_parent(n)`][get_parent]. +Finally, you can find the parents of nodes, via +calls like [`tcx.parent_hir_node(n)`][parent_hir_node]. + +[get_parent_item]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html#method.parent_hir_node -[get_parent]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/map/struct.Map.html#method.get_parent ## HIR Bodies @@ -158,10 +153,10 @@ A [`rustc_hir::Body`] represents some kind of executable code, such as the body of a function/closure or the definition of a constant. Bodies are associated with an **owner**, which is typically some kind of item (e.g. an `fn()` or `const`), but could also be a closure expression -(e.g. `|x, y| x + y`). You can use the HIR map to find the body -associated with a given def-id ([`maybe_body_owned_by`]) or to find -the owner of a body ([`body_owner_def_id`]). +(e.g. `|x, y| x + y`). You can use the `TyCtxt` to find the body +associated with a given def-id ([`hir_maybe_body_owned_by`]) or to find +the owner of a body ([`hir_body_owner_def_id`]). [`rustc_hir::Body`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir/struct.Body.html -[`maybe_body_owned_by`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/map/struct.Map.html#method.maybe_body_owned_by -[`body_owner_def_id`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/map/struct.Map.html#method.body_owner_def_id +[`hir_maybe_body_owned_by`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html#method.hir_maybe_body_owned_by +[`hir_body_owner_def_id`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html#method.hir_body_owner_def_id From ed5f31ab01d41a01b7206eafdf97b458dc41141a Mon Sep 17 00:00:00 2001 From: Thalia Archibald Date: Sun, 13 Apr 2025 04:21:10 -0700 Subject: [PATCH 423/606] Avoid unused clones in Cloned and Copied Avoid cloning in `Cloned` or copying in `Copied` when elements are only needed by reference or not at all. There is already some precedent for this, given that `__iterator_get_unchecked` is implemented, which can skip elements. The reduced clones are technically observable by a user impl of `Clone`. --- library/core/src/iter/adapters/cloned.rs | 88 +++++++++++++++++++++- library/core/src/iter/adapters/copied.rs | 95 +++++++++++++++++++----- 2 files changed, 163 insertions(+), 20 deletions(-) diff --git a/library/core/src/iter/adapters/cloned.rs b/library/core/src/iter/adapters/cloned.rs index aea6d64281ae..72d746289711 100644 --- a/library/core/src/iter/adapters/cloned.rs +++ b/library/core/src/iter/adapters/cloned.rs @@ -1,5 +1,6 @@ use core::num::NonZero; +use crate::cmp::Ordering; use crate::iter::adapters::zip::try_get_unchecked; use crate::iter::adapters::{SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce}; use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen, UncheckedIterator}; @@ -41,13 +42,31 @@ where self.it.next().cloned() } + #[inline] fn size_hint(&self) -> (usize, Option) { self.it.size_hint() } + #[inline] + fn count(self) -> usize { + self.it.count() + } + + fn last(self) -> Option { + self.it.last().cloned() + } + + #[inline] + fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { + self.it.advance_by(n) + } + + fn nth(&mut self, n: usize) -> Option { + self.it.nth(n).cloned() + } + fn try_fold(&mut self, init: B, f: F) -> R where - Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try, { @@ -61,6 +80,58 @@ where self.it.map(T::clone).fold(init, f) } + fn find

(&mut self, mut predicate: P) -> Option + where + P: FnMut(&Self::Item) -> bool, + { + self.it.find(move |x| predicate(&x)).cloned() + } + + fn max_by(self, mut compare: F) -> Option + where + F: FnMut(&Self::Item, &Self::Item) -> Ordering, + { + self.it.max_by(move |&x, &y| compare(x, y)).cloned() + } + + fn min_by(self, mut compare: F) -> Option + where + F: FnMut(&Self::Item, &Self::Item) -> Ordering, + { + self.it.min_by(move |&x, &y| compare(x, y)).cloned() + } + + fn cmp(self, other: O) -> Ordering + where + O: IntoIterator, + Self::Item: Ord, + { + self.it.cmp_by(other, |x, y| x.cmp(&y)) + } + + fn partial_cmp(self, other: O) -> Option + where + O: IntoIterator, + Self::Item: PartialOrd, + { + self.it.partial_cmp_by(other, |x, y| x.partial_cmp(&y)) + } + + fn eq(self, other: O) -> bool + where + O: IntoIterator, + Self::Item: PartialEq, + { + self.it.eq_by(other, |x, y| x == &y) + } + + fn is_sorted_by(self, mut compare: F) -> bool + where + F: FnMut(&Self::Item, &Self::Item) -> bool, + { + self.it.is_sorted_by(move |&x, &y| compare(x, y)) + } + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> T where Self: TrustedRandomAccessNoCoerce, @@ -81,9 +152,13 @@ where self.it.next_back().cloned() } + #[inline] + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { + self.it.advance_back_by(n) + } + fn try_rfold(&mut self, init: B, f: F) -> R where - Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try, { @@ -96,6 +171,13 @@ where { self.it.map(T::clone).rfold(init, f) } + + fn rfind

(&mut self, mut predicate: P) -> Option + where + P: FnMut(&Self::Item) -> bool, + { + self.it.rfind(move |x| predicate(&x)).cloned() + } } #[stable(feature = "iter_cloned", since = "1.1.0")] @@ -104,10 +186,12 @@ where I: ExactSizeIterator, T: Clone, { + #[inline] fn len(&self) -> usize { self.it.len() } + #[inline] fn is_empty(&self) -> bool { self.it.is_empty() } diff --git a/library/core/src/iter/adapters/copied.rs b/library/core/src/iter/adapters/copied.rs index 23e4e25ab538..73913aa34a9e 100644 --- a/library/core/src/iter/adapters/copied.rs +++ b/library/core/src/iter/adapters/copied.rs @@ -1,3 +1,4 @@ +use crate::cmp::Ordering; use crate::iter::adapters::zip::try_get_unchecked; use crate::iter::adapters::{SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce}; use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen}; @@ -48,20 +49,35 @@ where fn next_chunk( &mut self, - ) -> Result<[Self::Item; N], array::IntoIter> - where - Self: Sized, - { + ) -> Result<[Self::Item; N], array::IntoIter> { >::spec_next_chunk(&mut self.it) } + #[inline] fn size_hint(&self) -> (usize, Option) { self.it.size_hint() } + #[inline] + fn count(self) -> usize { + self.it.count() + } + + fn last(self) -> Option { + self.it.last().copied() + } + + #[inline] + fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { + self.it.advance_by(n) + } + + fn nth(&mut self, n: usize) -> Option { + self.it.nth(n).copied() + } + fn try_fold(&mut self, init: B, f: F) -> R where - Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try, { @@ -75,21 +91,56 @@ where self.it.fold(init, copy_fold(f)) } - fn nth(&mut self, n: usize) -> Option { - self.it.nth(n).copied() + fn find

(&mut self, mut predicate: P) -> Option + where + P: FnMut(&Self::Item) -> bool, + { + self.it.find(move |x| predicate(&x)).copied() } - fn last(self) -> Option { - self.it.last().copied() + fn max_by(self, mut compare: F) -> Option + where + F: FnMut(&Self::Item, &Self::Item) -> Ordering, + { + self.it.max_by(move |&x, &y| compare(x, y)).copied() } - fn count(self) -> usize { - self.it.count() + fn min_by(self, mut compare: F) -> Option + where + F: FnMut(&Self::Item, &Self::Item) -> Ordering, + { + self.it.min_by(move |&x, &y| compare(x, y)).copied() } - #[inline] - fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { - self.it.advance_by(n) + fn cmp(self, other: O) -> Ordering + where + O: IntoIterator, + Self::Item: Ord, + { + self.it.cmp_by(other, |x, y| x.cmp(&y)) + } + + fn partial_cmp(self, other: O) -> Option + where + O: IntoIterator, + Self::Item: PartialOrd, + { + self.it.partial_cmp_by(other, |x, y| x.partial_cmp(&y)) + } + + fn eq(self, other: O) -> bool + where + O: IntoIterator, + Self::Item: PartialEq, + { + self.it.eq_by(other, |x, y| x == &y) + } + + fn is_sorted_by(self, mut compare: F) -> bool + where + F: FnMut(&Self::Item, &Self::Item) -> bool, + { + self.it.is_sorted_by(move |&x, &y| compare(x, y)) } unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> T @@ -112,9 +163,13 @@ where self.it.next_back().copied() } + #[inline] + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { + self.it.advance_back_by(n) + } + fn try_rfold(&mut self, init: B, f: F) -> R where - Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try, { @@ -128,9 +183,11 @@ where self.it.rfold(init, copy_fold(f)) } - #[inline] - fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { - self.it.advance_back_by(n) + fn rfind

(&mut self, mut predicate: P) -> Option + where + P: FnMut(&Self::Item) -> bool, + { + self.it.rfind(move |x| predicate(&x)).copied() } } @@ -140,10 +197,12 @@ where I: ExactSizeIterator, T: Copy, { + #[inline] fn len(&self) -> usize { self.it.len() } + #[inline] fn is_empty(&self) -> bool { self.it.is_empty() } From 3efd9f5d0c39c427025c7f388c7793017d2eea18 Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Mon, 14 Apr 2025 01:38:18 +0200 Subject: [PATCH 424/606] Switch to `diagnostic::on_unimplemented` --- compiler/rustc_data_structures/src/marker.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_data_structures/src/marker.rs b/compiler/rustc_data_structures/src/marker.rs index 744ae9b6fe2a..5f07cfef1335 100644 --- a/compiler/rustc_data_structures/src/marker.rs +++ b/compiler/rustc_data_structures/src/marker.rs @@ -1,13 +1,13 @@ use std::alloc::Allocator; -#[rustc_on_unimplemented(message = "`{Self}` doesn't implement `DynSend`. \ +#[diagnostic::on_unimplemented(message = "`{Self}` doesn't implement `DynSend`. \ Add it to `rustc_data_structures::marker` or use `IntoDynSyncSend` if it's already `Send`")] // This is an auto trait for types which can be sent across threads if `sync::is_dyn_thread_safe()` // is true. These types can be wrapped in a `FromDyn` to get a `Send` type. Wrapping a // `Send` type in `IntoDynSyncSend` will create a `DynSend` type. pub unsafe auto trait DynSend {} -#[rustc_on_unimplemented(message = "`{Self}` doesn't implement `DynSync`. \ +#[diagnostic::on_unimplemented(message = "`{Self}` doesn't implement `DynSync`. \ Add it to `rustc_data_structures::marker` or use `IntoDynSyncSend` if it's already `Sync`")] // This is an auto trait for types which can be shared across threads if `sync::is_dyn_thread_safe()` // is true. These types can be wrapped in a `FromDyn` to get a `Sync` type. Wrapping a From c73598f0fb0ef2cfcdc784e577a96bb8041445ba Mon Sep 17 00:00:00 2001 From: xizheyin Date: Mon, 17 Mar 2025 22:22:32 +0800 Subject: [PATCH 425/606] Report span of test when should_panic test failed Signed-off-by: xizheyin --- library/test/src/test_result.rs | 7 +++- .../failed-doctest-should-panic.stdout | 2 +- .../test-should-panic-failed-show-span.rs | 42 +++++++++++++++++++ ...t-should-panic-failed-show-span.run.stdout | 38 +++++++++++++++++ .../test-should-panic-failed-show-span.stderr | 21 ++++++++++ 5 files changed, 108 insertions(+), 2 deletions(-) create mode 100644 tests/ui/test-attrs/test-should-panic-failed-show-span.rs create mode 100644 tests/ui/test-attrs/test-should-panic-failed-show-span.run.stdout create mode 100644 tests/ui/test-attrs/test-should-panic-failed-show-span.stderr diff --git a/library/test/src/test_result.rs b/library/test/src/test_result.rs index 959cd730fa43..a312894c25c4 100644 --- a/library/test/src/test_result.rs +++ b/library/test/src/test_result.rs @@ -77,7 +77,12 @@ pub(crate) fn calc_result( // The test should have panicked, but didn't panic. (ShouldPanic::Yes, None) | (ShouldPanic::YesWithMessage(_), None) => { - TestResult::TrFailedMsg("test did not panic as expected".to_string()) + let fn_location = if !desc.source_file.is_empty() { + &format!(" at {}:{}:{}", desc.source_file, desc.start_line, desc.start_col) + } else { + "" + }; + TestResult::TrFailedMsg(format!("test did not panic as expected{}", fn_location)) } // The test should not have panicked, but did panic. diff --git a/tests/rustdoc-ui/doctest/failed-doctest-should-panic.stdout b/tests/rustdoc-ui/doctest/failed-doctest-should-panic.stdout index 90c0463d832e..2b04b77c9dc5 100644 --- a/tests/rustdoc-ui/doctest/failed-doctest-should-panic.stdout +++ b/tests/rustdoc-ui/doctest/failed-doctest-should-panic.stdout @@ -5,7 +5,7 @@ test $DIR/failed-doctest-should-panic.rs - Foo (line 10) - should panic ... FAIL failures: ---- $DIR/failed-doctest-should-panic.rs - Foo (line 10) stdout ---- -note: test did not panic as expected +note: test did not panic as expected at $DIR/failed-doctest-should-panic.rs:10:0 failures: $DIR/failed-doctest-should-panic.rs - Foo (line 10) diff --git a/tests/ui/test-attrs/test-should-panic-failed-show-span.rs b/tests/ui/test-attrs/test-should-panic-failed-show-span.rs new file mode 100644 index 000000000000..960673bcc0d9 --- /dev/null +++ b/tests/ui/test-attrs/test-should-panic-failed-show-span.rs @@ -0,0 +1,42 @@ +//@ run-fail +//@ check-run-results +//@ compile-flags: --test +//@ exec-env:RUST_BACKTRACE=0 +//@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" +//@ run-flags: --test-threads=1 + +#[test] +#[should_panic] +fn should_panic_with_any_message() { + panic!("Panic!"); +} + +#[test] +#[should_panic = "message"] +fn should_panic_with_message() { + panic!("message"); +} + +#[test] +#[should_panic] +fn should_panic_with_any_message_does_not_panic() { + // DON'T PANIC +} + +#[test] +#[should_panic = "message"] +fn should_panic_with_message_does_not_panic() { + // DON'T PANIC +} + +#[test] +#[should_panic = "message"] +fn should_panic_with_substring_panics_with_incorrect_string() { + panic!("ZOMGWTFBBQ"); +} + +#[test] +#[should_panic = "message"] +fn should_panic_with_substring_panics_with_non_string_value() { + panic!(123); //~ WARNING panic message is not a string literal +} diff --git a/tests/ui/test-attrs/test-should-panic-failed-show-span.run.stdout b/tests/ui/test-attrs/test-should-panic-failed-show-span.run.stdout new file mode 100644 index 000000000000..4edc67694b9e --- /dev/null +++ b/tests/ui/test-attrs/test-should-panic-failed-show-span.run.stdout @@ -0,0 +1,38 @@ + +running 6 tests +test should_panic_with_any_message - should panic ... ok +test should_panic_with_any_message_does_not_panic - should panic ... FAILED +test should_panic_with_message - should panic ... ok +test should_panic_with_message_does_not_panic - should panic ... FAILED +test should_panic_with_substring_panics_with_incorrect_string - should panic ... FAILED +test should_panic_with_substring_panics_with_non_string_value - should panic ... FAILED + +failures: + +---- should_panic_with_any_message_does_not_panic stdout ---- +note: test did not panic as expected at $DIR/test-should-panic-failed-show-span.rs:22:4 +---- should_panic_with_message_does_not_panic stdout ---- +note: test did not panic as expected at $DIR/test-should-panic-failed-show-span.rs:28:4 +---- should_panic_with_substring_panics_with_incorrect_string stdout ---- + +thread 'should_panic_with_substring_panics_with_incorrect_string' panicked at $DIR/test-should-panic-failed-show-span.rs:35:5: +ZOMGWTFBBQ +note: panic did not contain expected string + panic message: `"ZOMGWTFBBQ"`, + expected substring: `"message"` +---- should_panic_with_substring_panics_with_non_string_value stdout ---- + +thread 'should_panic_with_substring_panics_with_non_string_value' panicked at $DIR/test-should-panic-failed-show-span.rs:41:5: +Box +note: expected panic with string value, + found non-string value: `TypeId(0x56ced5e4a15bd89050bb9674fa2df013)` + expected substring: `"message"` + +failures: + should_panic_with_any_message_does_not_panic + should_panic_with_message_does_not_panic + should_panic_with_substring_panics_with_incorrect_string + should_panic_with_substring_panics_with_non_string_value + +test result: FAILED. 2 passed; 4 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + diff --git a/tests/ui/test-attrs/test-should-panic-failed-show-span.stderr b/tests/ui/test-attrs/test-should-panic-failed-show-span.stderr new file mode 100644 index 000000000000..e803ff5513c6 --- /dev/null +++ b/tests/ui/test-attrs/test-should-panic-failed-show-span.stderr @@ -0,0 +1,21 @@ +warning: panic message is not a string literal + --> $DIR/test-should-panic-failed-show-span.rs:41:12 + | +LL | panic!(123); + | ^^^ + | + = note: this usage of `panic!()` is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see + = note: `#[warn(non_fmt_panics)]` on by default +help: add a "{}" format string to `Display` the message + | +LL | panic!("{}", 123); + | +++++ +help: or use std::panic::panic_any instead + | +LL - panic!(123); +LL + std::panic::panic_any(123); + | + +warning: 1 warning emitted + From dc3a586eed198548316fcbfff2d5c28df0728750 Mon Sep 17 00:00:00 2001 From: xizheyin Date: Tue, 8 Apr 2025 09:40:37 +0800 Subject: [PATCH 426/606] Adjust test directives Signed-off-by: xizheyin --- .../test-should-panic-failed-show-span.rs | 10 ++++++--- ...t-should-panic-failed-show-span.run.stderr | 13 ++++++++++++ ...t-should-panic-failed-show-span.run.stdout | 12 +++-------- .../test-should-panic-failed-show-span.stderr | 21 ------------------- 4 files changed, 23 insertions(+), 33 deletions(-) create mode 100644 tests/ui/test-attrs/test-should-panic-failed-show-span.run.stderr delete mode 100644 tests/ui/test-attrs/test-should-panic-failed-show-span.stderr diff --git a/tests/ui/test-attrs/test-should-panic-failed-show-span.rs b/tests/ui/test-attrs/test-should-panic-failed-show-span.rs index 960673bcc0d9..f400f614142d 100644 --- a/tests/ui/test-attrs/test-should-panic-failed-show-span.rs +++ b/tests/ui/test-attrs/test-should-panic-failed-show-span.rs @@ -1,9 +1,12 @@ +//@ compile-flags: --test +//@ run-flags: --test-threads=1 --nocapture //@ run-fail //@ check-run-results -//@ compile-flags: --test //@ exec-env:RUST_BACKTRACE=0 //@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" -//@ run-flags: --test-threads=1 +//@ normalize-stdout: "TypeId\(0x[0-9a-f]+\)" -> "TypeId($$HEX)" +//@ needs-threads +//@ needs-unwind (panic) #[test] #[should_panic] @@ -37,6 +40,7 @@ fn should_panic_with_substring_panics_with_incorrect_string() { #[test] #[should_panic = "message"] +#[expect(non_fmt_panics)] fn should_panic_with_substring_panics_with_non_string_value() { - panic!(123); //~ WARNING panic message is not a string literal + panic!(123); } diff --git a/tests/ui/test-attrs/test-should-panic-failed-show-span.run.stderr b/tests/ui/test-attrs/test-should-panic-failed-show-span.run.stderr new file mode 100644 index 000000000000..db379a16b52a --- /dev/null +++ b/tests/ui/test-attrs/test-should-panic-failed-show-span.run.stderr @@ -0,0 +1,13 @@ + +thread 'should_panic_with_any_message' panicked at $DIR/test-should-panic-failed-show-span.rs:14:5: +Panic! +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace + +thread 'should_panic_with_message' panicked at $DIR/test-should-panic-failed-show-span.rs:20:5: +message + +thread 'should_panic_with_substring_panics_with_incorrect_string' panicked at $DIR/test-should-panic-failed-show-span.rs:38:5: +ZOMGWTFBBQ + +thread 'should_panic_with_substring_panics_with_non_string_value' panicked at $DIR/test-should-panic-failed-show-span.rs:45:5: +Box diff --git a/tests/ui/test-attrs/test-should-panic-failed-show-span.run.stdout b/tests/ui/test-attrs/test-should-panic-failed-show-span.run.stdout index 4edc67694b9e..75600b4d3d66 100644 --- a/tests/ui/test-attrs/test-should-panic-failed-show-span.run.stdout +++ b/tests/ui/test-attrs/test-should-panic-failed-show-span.run.stdout @@ -10,22 +10,16 @@ test should_panic_with_substring_panics_with_non_string_value - should panic ... failures: ---- should_panic_with_any_message_does_not_panic stdout ---- -note: test did not panic as expected at $DIR/test-should-panic-failed-show-span.rs:22:4 +note: test did not panic as expected at $DIR/test-should-panic-failed-show-span.rs:25:4 ---- should_panic_with_message_does_not_panic stdout ---- -note: test did not panic as expected at $DIR/test-should-panic-failed-show-span.rs:28:4 +note: test did not panic as expected at $DIR/test-should-panic-failed-show-span.rs:31:4 ---- should_panic_with_substring_panics_with_incorrect_string stdout ---- - -thread 'should_panic_with_substring_panics_with_incorrect_string' panicked at $DIR/test-should-panic-failed-show-span.rs:35:5: -ZOMGWTFBBQ note: panic did not contain expected string panic message: `"ZOMGWTFBBQ"`, expected substring: `"message"` ---- should_panic_with_substring_panics_with_non_string_value stdout ---- - -thread 'should_panic_with_substring_panics_with_non_string_value' panicked at $DIR/test-should-panic-failed-show-span.rs:41:5: -Box note: expected panic with string value, - found non-string value: `TypeId(0x56ced5e4a15bd89050bb9674fa2df013)` + found non-string value: `TypeId($HEX)` expected substring: `"message"` failures: diff --git a/tests/ui/test-attrs/test-should-panic-failed-show-span.stderr b/tests/ui/test-attrs/test-should-panic-failed-show-span.stderr deleted file mode 100644 index e803ff5513c6..000000000000 --- a/tests/ui/test-attrs/test-should-panic-failed-show-span.stderr +++ /dev/null @@ -1,21 +0,0 @@ -warning: panic message is not a string literal - --> $DIR/test-should-panic-failed-show-span.rs:41:12 - | -LL | panic!(123); - | ^^^ - | - = note: this usage of `panic!()` is deprecated; it will be a hard error in Rust 2021 - = note: for more information, see - = note: `#[warn(non_fmt_panics)]` on by default -help: add a "{}" format string to `Display` the message - | -LL | panic!("{}", 123); - | +++++ -help: or use std::panic::panic_any instead - | -LL - panic!(123); -LL + std::panic::panic_any(123); - | - -warning: 1 warning emitted - From edfdb9205c9f507628d957b048420a8d3a29a0d2 Mon Sep 17 00:00:00 2001 From: xizheyin Date: Mon, 14 Apr 2025 14:00:04 +0800 Subject: [PATCH 427/606] Add ui test unreachable-by-call-arguments-issue-139627.rs Signed-off-by: xizheyin --- ...eachable-by-call-arguments-issue-139627.rs | 15 ++++++++ ...able-by-call-arguments-issue-139627.stderr | 36 +++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 tests/ui/reachable/unreachable-by-call-arguments-issue-139627.rs create mode 100644 tests/ui/reachable/unreachable-by-call-arguments-issue-139627.stderr diff --git a/tests/ui/reachable/unreachable-by-call-arguments-issue-139627.rs b/tests/ui/reachable/unreachable-by-call-arguments-issue-139627.rs new file mode 100644 index 000000000000..422ae95e8b72 --- /dev/null +++ b/tests/ui/reachable/unreachable-by-call-arguments-issue-139627.rs @@ -0,0 +1,15 @@ +#![deny(unreachable_code)] +#![deny(unused)] + +pub enum Void {} + +pub struct S(T); + +pub fn foo(void: Void, void1: Void) { //~ ERROR unused variable: `void1` + let s = S(void); //~ ERROR unused variable: `s` + drop(s); //~ ERROR unreachable expression + let s1 = S { 0: void1 }; + drop(s1); +} + +fn main() {} diff --git a/tests/ui/reachable/unreachable-by-call-arguments-issue-139627.stderr b/tests/ui/reachable/unreachable-by-call-arguments-issue-139627.stderr new file mode 100644 index 000000000000..ce24705324e5 --- /dev/null +++ b/tests/ui/reachable/unreachable-by-call-arguments-issue-139627.stderr @@ -0,0 +1,36 @@ +error: unreachable expression + --> $DIR/unreachable-by-call-arguments-issue-139627.rs:10:10 + | +LL | let s = S(void); + | ------- any code following this expression is unreachable +LL | drop(s); + | ^ unreachable expression + | +note: this expression has type `S`, which is uninhabited + --> $DIR/unreachable-by-call-arguments-issue-139627.rs:9:13 + | +LL | let s = S(void); + | ^^^^^^^ +note: the lint level is defined here + --> $DIR/unreachable-by-call-arguments-issue-139627.rs:2:9 + | +LL | #![deny(unused)] + | ^^^^^^ + = note: `#[deny(unreachable_code)]` implied by `#[deny(unused)]` + +error: unused variable: `s` + --> $DIR/unreachable-by-call-arguments-issue-139627.rs:9:9 + | +LL | let s = S(void); + | ^ help: if this is intentional, prefix it with an underscore: `_s` + | + = note: `#[deny(unused_variables)]` implied by `#[deny(unused)]` + +error: unused variable: `void1` + --> $DIR/unreachable-by-call-arguments-issue-139627.rs:8:24 + | +LL | pub fn foo(void: Void, void1: Void) { + | ^^^^^ help: if this is intentional, prefix it with an underscore: `_void1` + +error: aborting due to 3 previous errors + From abce592029671a2f65e50901ad5fc55e42fdf930 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 11 Apr 2025 19:44:11 +1000 Subject: [PATCH 428/606] Use `Symbol` in `LateContext::get_associated_type`. To avoid unnecessary interning. --- compiler/rustc_lint/src/context.rs | 9 +++++++-- compiler/rustc_lint/src/deref_into_dyn_supertrait.rs | 2 +- src/tools/clippy/clippy_lints/src/format_args.rs | 2 +- src/tools/clippy/clippy_lints/src/len_zero.rs | 2 +- .../clippy_lints/src/methods/iter_overeager_cloned.rs | 2 +- .../clippy_lints/src/methods/unnecessary_iter_cloned.rs | 2 +- .../clippy_lints/src/methods/unnecessary_to_owned.rs | 6 +++--- src/tools/clippy/clippy_utils/src/ty/mod.rs | 2 +- 8 files changed, 16 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 16c9e08c78d3..a2d5ffe256d5 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -855,11 +855,16 @@ impl<'tcx> LateContext<'tcx> { &self, self_ty: Ty<'tcx>, trait_id: DefId, - name: &str, + name: Symbol, ) -> Option> { let tcx = self.tcx; tcx.associated_items(trait_id) - .find_by_ident_and_kind(tcx, Ident::from_str(name), ty::AssocKind::Type, trait_id) + .find_by_ident_and_kind( + tcx, + Ident::with_dummy_span(name), + ty::AssocKind::Type, + trait_id, + ) .and_then(|assoc| { let proj = Ty::new_projection(tcx, assoc.def_id, [self_ty]); tcx.try_normalize_erasing_regions(self.typing_env(), proj).ok() diff --git a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs index ec8f84415759..5989ef9519cd 100644 --- a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs +++ b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs @@ -69,7 +69,7 @@ impl<'tcx> LateLintPass<'tcx> for DerefIntoDynSupertrait { && let ty::Dynamic(data, _, ty::Dyn) = self_ty.kind() && let Some(self_principal) = data.principal() // `::Target` is `dyn target_principal` - && let Some(target) = cx.get_associated_type(self_ty, did, "Target") + && let Some(target) = cx.get_associated_type(self_ty, did, sym::Target) && let ty::Dynamic(data, _, ty::Dyn) = target.kind() && let Some(target_principal) = data.principal() // `target_principal` is a supertrait of `t_principal` diff --git a/src/tools/clippy/clippy_lints/src/format_args.rs b/src/tools/clippy/clippy_lints/src/format_args.rs index 3862ff7921db..06224f57c5c5 100644 --- a/src/tools/clippy/clippy_lints/src/format_args.rs +++ b/src/tools/clippy/clippy_lints/src/format_args.rs @@ -550,7 +550,7 @@ impl<'tcx> FormatArgsExpr<'_, 'tcx> { // a `Target` that is in `self.ty_msrv_map`. if let Some(deref_trait_id) = self.cx.tcx.lang_items().deref_trait() && implements_trait(self.cx, ty, deref_trait_id, &[]) - && let Some(target_ty) = self.cx.get_associated_type(ty, deref_trait_id, "Target") + && let Some(target_ty) = self.cx.get_associated_type(ty, deref_trait_id, sym::Target) && let Some(msrv) = self.ty_msrv_map.get(&target_ty) && msrv.is_none_or(|msrv| self.msrv.meets(self.cx, msrv)) { diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs index 72e22ae59d8f..b01929747d69 100644 --- a/src/tools/clippy/clippy_lints/src/len_zero.rs +++ b/src/tools/clippy/clippy_lints/src/len_zero.rs @@ -644,7 +644,7 @@ fn has_is_empty(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { && cx.tcx.get_diagnostic_item(sym::Deref).is_some_and(|deref_id| { implements_trait(cx, ty, deref_id, &[]) && cx - .get_associated_type(ty, deref_id, "Target") + .get_associated_type(ty, deref_id, sym::Target) .is_some_and(|deref_ty| ty_has_is_empty(cx, deref_ty, depth + 1)) })) }, diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs b/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs index f51bdc78f8a5..7bb625222ec0 100644 --- a/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs @@ -48,7 +48,7 @@ pub(super) fn check<'tcx>( && let Some(method_id) = typeck.type_dependent_def_id(cloned_call.hir_id) && cx.tcx.trait_of_item(method_id) == Some(iter_id) && let cloned_recv_ty = typeck.expr_ty_adjusted(cloned_recv) - && let Some(iter_assoc_ty) = cx.get_associated_type(cloned_recv_ty, iter_id, "Item") + && let Some(iter_assoc_ty) = cx.get_associated_type(cloned_recv_ty, iter_id, sym::Item) && matches!(*iter_assoc_ty.kind(), ty::Ref(_, ty, _) if !is_copy(cx, ty)) { if needs_into_iter diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs index c0e015685881..20cf35363d13 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs @@ -99,7 +99,7 @@ pub fn check_for_loop_iter( && let Some(into_iterator_trait_id) = cx.tcx.get_diagnostic_item(sym::IntoIterator) && let collection_ty = cx.typeck_results().expr_ty(collection) && implements_trait(cx, collection_ty, into_iterator_trait_id, &[]) - && let Some(into_iter_item_ty) = cx.get_associated_type(collection_ty, into_iterator_trait_id, "Item") + && let Some(into_iter_item_ty) = cx.get_associated_type(collection_ty, into_iterator_trait_id, sym::Item) && iter_item_ty == into_iter_item_ty && let Some(collection_snippet) = collection.span.get_source_text(cx) { diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs index 62ba3012643c..206b0a8ae3cd 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -153,7 +153,7 @@ fn check_addr_of_expr( } if let Some(deref_trait_id) = cx.tcx.get_diagnostic_item(sym::Deref) && implements_trait(cx, receiver_ty, deref_trait_id, &[]) - && cx.get_associated_type(receiver_ty, deref_trait_id, "Target") == Some(target_ty) + && cx.get_associated_type(receiver_ty, deref_trait_id, sym::Target) == Some(target_ty) // Make sure that it's actually calling the right `.to_string()`, (#10033) // *or* this is a `Cow::into_owned()` call (which would be the wrong into_owned receiver (str != Cow) // but that's ok for Cow::into_owned specifically) @@ -322,7 +322,7 @@ fn check_split_call_arg(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: Symb // add `.as_ref()` to the suggestion. let as_ref = if is_type_lang_item(cx, cx.typeck_results().expr_ty(expr), LangItem::String) && let Some(deref_trait_id) = cx.tcx.get_diagnostic_item(sym::Deref) - && cx.get_associated_type(cx.typeck_results().expr_ty(receiver), deref_trait_id, "Target") + && cx.get_associated_type(cx.typeck_results().expr_ty(receiver), deref_trait_id, sym::Target) != Some(cx.tcx.types.str_) { ".as_ref()" @@ -648,7 +648,7 @@ fn is_to_string_on_string_like<'a>( && let GenericArgKind::Type(ty) = generic_arg.unpack() && let Some(deref_trait_id) = cx.tcx.get_diagnostic_item(sym::Deref) && let Some(as_ref_trait_id) = cx.tcx.get_diagnostic_item(sym::AsRef) - && (cx.get_associated_type(ty, deref_trait_id, "Target") == Some(cx.tcx.types.str_) + && (cx.get_associated_type(ty, deref_trait_id, sym::Target) == Some(cx.tcx.types.str_) || implements_trait(cx, ty, as_ref_trait_id, &[cx.tcx.types.str_.into()])) { true diff --git a/src/tools/clippy/clippy_utils/src/ty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/mod.rs index 29cbf62c3d4c..3779e2f30623 100644 --- a/src/tools/clippy/clippy_utils/src/ty/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ty/mod.rs @@ -156,7 +156,7 @@ pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<' pub fn get_iterator_item_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option> { cx.tcx .get_diagnostic_item(sym::Iterator) - .and_then(|iter_did| cx.get_associated_type(ty, iter_did, "Item")) + .and_then(|iter_did| cx.get_associated_type(ty, iter_did, sym::Item)) } /// Get the diagnostic name of a type, e.g. `sym::HashMap`. To check if a type From ce2aa97cd647bdfcb5859489d93526622bb388a0 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 11 Apr 2025 06:28:59 +1000 Subject: [PATCH 429/606] Move `has_self` field to `hir::AssocKind::Fn`. `hir::AssocItem` currently has a boolean `fn_has_self_parameter` field, which is misplaced, because it's only relevant for associated fns, not for associated consts or types. This commit moves it (and renames it) to the `AssocKind::Fn` variant, where it belongs. This requires introducing a new C-style enum, `AssocTag`, which is like `AssocKind` but without the fields. This is because `AssocKind` values are passed to various functions like `find_by_ident_and_kind` to indicate what kind of associated item should be searched for, and having to specify `has_self` isn't relevant there. New methods: - Predicates `AssocItem::is_fn` and `AssocItem::is_method`. - `AssocItem::as_tag` which converts `AssocItem::kind` to `AssocTag`. Removed `find_by_name_and_kinds`, which is unused. `AssocItem::descr` can now distinguish between methods and associated functions, which slightly improves some error messages. --- compiler/rustc_ast_lowering/src/delegation.rs | 2 +- .../src/diagnostics/conflict_errors.rs | 2 +- .../rustc_codegen_cranelift/src/main_shim.rs | 4 +- .../rustc_hir_analysis/src/check/check.rs | 4 +- .../src/check/compare_impl_item.rs | 14 +- compiler/rustc_hir_analysis/src/check/mod.rs | 8 +- .../rustc_hir_analysis/src/check/wfcheck.rs | 6 +- compiler/rustc_hir_analysis/src/collect.rs | 6 +- .../src/collect/resolve_bound_vars.rs | 16 +-- .../src/collect/type_of/opaque.rs | 4 +- .../src/hir_ty_lowering/bounds.rs | 26 ++-- .../src/hir_ty_lowering/errors.rs | 57 ++++---- .../src/hir_ty_lowering/mod.rs | 124 ++++++++++-------- .../rustc_hir_analysis/src/impl_wf_check.rs | 2 +- compiler/rustc_hir_typeck/src/demand.rs | 10 +- compiler/rustc_hir_typeck/src/expr.rs | 4 +- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 5 +- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 2 +- compiler/rustc_hir_typeck/src/method/mod.rs | 2 +- compiler/rustc_hir_typeck/src/method/probe.rs | 15 +-- .../rustc_hir_typeck/src/method/suggest.rs | 27 ++-- compiler/rustc_lint/src/context.rs | 7 +- compiler/rustc_metadata/src/rmeta/decoder.rs | 11 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 2 +- compiler/rustc_middle/src/mir/mod.rs | 4 +- compiler/rustc_middle/src/ty/adjustment.rs | 4 +- compiler/rustc_middle/src/ty/assoc.rs | 62 +++++---- compiler/rustc_middle/src/ty/instance.rs | 2 +- compiler/rustc_middle/src/ty/mod.rs | 2 +- compiler/rustc_middle/src/ty/util.rs | 4 +- .../src/builder/matches/test.rs | 2 +- compiler/rustc_mir_transform/src/shim.rs | 2 +- .../src/mono_checks/move_check.rs | 4 +- .../rustc_resolve/src/late/diagnostics.rs | 2 +- .../cfi/typeid/itanium_cxx_abi/transform.rs | 2 +- .../rustc_smir/src/rustc_smir/convert/ty.rs | 5 +- .../rustc_smir/src/stable_mir/mir/pretty.rs | 3 +- compiler/rustc_smir/src/stable_mir/ty.rs | 6 +- .../src/error_reporting/infer/mod.rs | 8 +- .../trait_impl_difference.rs | 2 +- .../infer/nice_region_error/util.rs | 2 +- .../error_reporting/infer/note_and_explain.rs | 2 +- .../src/error_reporting/traits/ambiguity.rs | 2 +- .../src/error_reporting/traits/suggestions.rs | 2 +- .../src/traits/dyn_compatibility.rs | 4 +- .../src/traits/vtable.rs | 6 +- compiler/rustc_ty_utils/src/assoc.rs | 20 ++- src/librustdoc/clean/inline.rs | 12 +- src/librustdoc/clean/mod.rs | 4 +- .../src/bool_assert_comparison.rs | 2 +- src/tools/clippy/clippy_lints/src/len_zero.rs | 11 +- .../src/methods/needless_collect.rs | 4 +- .../clippy_lints/src/methods/or_fun_call.rs | 2 +- .../src/needless_borrows_for_generic_args.rs | 2 +- .../clippy_lints/src/same_name_method.rs | 3 +- .../src/unconditional_recursion.rs | 4 +- .../clippy/clippy_lints/src/unused_self.rs | 2 +- src/tools/clippy/clippy_utils/src/ty/mod.rs | 6 +- .../impl_bounds.stderr | 4 +- .../normalize/normalize-param-env-2.stderr | 4 +- 60 files changed, 288 insertions(+), 284 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs index 2296b05f69b4..93c627f64c96 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -85,7 +85,7 @@ impl<'hir> LoweringContext<'_, 'hir> { .delegation_fn_sigs .get(&local_def_id) .is_some_and(|sig| sig.has_self), - None => self.tcx.associated_item(def_id).fn_has_self_parameter, + None => self.tcx.associated_item(def_id).is_method(), }, _ => span_bug!(span, "unexpected DefKind for delegation item"), } diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 8a8ecc3b96e3..fe6dff7ff1b6 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -647,7 +647,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { && tc.polarity() == ty::PredicatePolarity::Positive && supertrait_def_ids(tcx, tc.def_id()) .flat_map(|trait_did| tcx.associated_items(trait_did).in_definition_order()) - .any(|item| item.fn_has_self_parameter) + .any(|item| item.is_method()) }) }) { return None; diff --git a/compiler/rustc_codegen_cranelift/src/main_shim.rs b/compiler/rustc_codegen_cranelift/src/main_shim.rs index 3b48adb7e918..6eef97c14dd2 100644 --- a/compiler/rustc_codegen_cranelift/src/main_shim.rs +++ b/compiler/rustc_codegen_cranelift/src/main_shim.rs @@ -1,6 +1,6 @@ use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext}; use rustc_hir::LangItem; -use rustc_middle::ty::{AssocKind, GenericArg}; +use rustc_middle::ty::{AssocTag, GenericArg}; use rustc_session::config::EntryFnType; use rustc_span::{DUMMY_SP, Ident}; @@ -107,7 +107,7 @@ pub(crate) fn maybe_create_entry_wrapper( .find_by_ident_and_kind( tcx, Ident::from_str("report"), - AssocKind::Fn, + AssocTag::Fn, termination_trait, ) .unwrap(); diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index f50746dd18d6..c2706a1d4013 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -443,7 +443,7 @@ fn best_definition_site_of_opaque<'tcx>( let impl_def_id = tcx.local_parent(parent); for assoc in tcx.associated_items(impl_def_id).in_definition_order() { match assoc.kind { - ty::AssocKind::Const | ty::AssocKind::Fn => { + ty::AssocKind::Const | ty::AssocKind::Fn { .. } => { if let ControlFlow::Break(span) = locator.check(assoc.def_id.expect_local()) { return Some(span); @@ -942,7 +942,7 @@ fn check_impl_items_against_trait<'tcx>( if res.is_ok() { match ty_impl_item.kind { - ty::AssocKind::Fn => { + ty::AssocKind::Fn { .. } => { compare_impl_item::refine::check_refining_return_position_impl_trait_in_trait( tcx, ty_impl_item, diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 29a9931696ff..7dfdf1ae237d 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -43,7 +43,7 @@ pub(super) fn compare_impl_item( debug!(?impl_trait_ref); match impl_item.kind { - ty::AssocKind::Fn => compare_impl_method(tcx, impl_item, trait_item, impl_trait_ref), + ty::AssocKind::Fn { .. } => compare_impl_method(tcx, impl_item, trait_item, impl_trait_ref), ty::AssocKind::Type => compare_impl_ty(tcx, impl_item, trait_item, impl_trait_ref), ty::AssocKind::Const => compare_impl_const(tcx, impl_item, trait_item, impl_trait_ref), } @@ -1036,7 +1036,7 @@ fn report_trait_method_mismatch<'tcx>( ); match &terr { TypeError::ArgumentMutability(0) | TypeError::ArgumentSorts(_, 0) - if trait_m.fn_has_self_parameter => + if trait_m.is_method() => { let ty = trait_sig.inputs()[0]; let sugg = get_self_string(ty, |ty| ty == impl_trait_ref.self_ty()); @@ -1255,7 +1255,7 @@ fn compare_self_type<'tcx>( get_self_string(self_arg_ty, can_eq_self) }; - match (trait_m.fn_has_self_parameter, impl_m.fn_has_self_parameter) { + match (trait_m.is_method(), impl_m.is_method()) { (false, false) | (true, true) => {} (false, true) => { @@ -1363,7 +1363,7 @@ fn compare_number_of_generics<'tcx>( let mut err_occurred = None; for (kind, trait_count, impl_count) in matchings { if impl_count != trait_count { - let arg_spans = |kind: ty::AssocKind, generics: &hir::Generics<'_>| { + let arg_spans = |item: &ty::AssocItem, generics: &hir::Generics<'_>| { let mut spans = generics .params .iter() @@ -1373,7 +1373,7 @@ fn compare_number_of_generics<'tcx>( } => { // A fn can have an arbitrary number of extra elided lifetimes for the // same signature. - !matches!(kind, ty::AssocKind::Fn) + !item.is_fn() } _ => true, }) @@ -1386,7 +1386,7 @@ fn compare_number_of_generics<'tcx>( }; let (trait_spans, impl_trait_spans) = if let Some(def_id) = trait_.def_id.as_local() { let trait_item = tcx.hir_expect_trait_item(def_id); - let arg_spans: Vec = arg_spans(trait_.kind, trait_item.generics); + let arg_spans: Vec = arg_spans(&trait_, trait_item.generics); let impl_trait_spans: Vec = trait_item .generics .params @@ -1412,7 +1412,7 @@ fn compare_number_of_generics<'tcx>( _ => None, }) .collect(); - let spans = arg_spans(impl_.kind, impl_item.generics); + let spans = arg_spans(&impl_, impl_item.generics); let span = spans.first().copied(); let mut err = tcx.dcx().struct_span_err( diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 30921b6f055d..523db9440a41 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -407,14 +407,14 @@ fn fn_sig_suggestion<'tcx>( .enumerate() .map(|(i, ty)| { Some(match ty.kind() { - ty::Param(_) if assoc.fn_has_self_parameter && i == 0 => "self".to_string(), + ty::Param(_) if assoc.is_method() && i == 0 => "self".to_string(), ty::Ref(reg, ref_ty, mutability) if i == 0 => { let reg = format!("{reg} "); let reg = match ®[..] { "'_ " | " " => "", reg => reg, }; - if assoc.fn_has_self_parameter { + if assoc.is_method() { match ref_ty.kind() { ty::Param(param) if param.name == kw::SelfUpper => { format!("&{}{}self", reg, mutability.prefix_str()) @@ -427,7 +427,7 @@ fn fn_sig_suggestion<'tcx>( } } _ => { - if assoc.fn_has_self_parameter && i == 0 { + if assoc.is_method() && i == 0 { format!("self: {ty}") } else { format!("_: {ty}") @@ -489,7 +489,7 @@ fn suggestion_signature<'tcx>( ); match assoc.kind { - ty::AssocKind::Fn => fn_sig_suggestion( + ty::AssocKind::Fn { .. } => fn_sig_suggestion( tcx, tcx.liberate_late_bound_regions( assoc.def_id, diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 6292d03bf6ac..af7830fd6642 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -432,7 +432,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, trait_def_id: LocalDefId) { let item_required_bounds = match tcx.associated_item(item_def_id).kind { // In our example, this corresponds to `into_iter` method - ty::AssocKind::Fn => { + ty::AssocKind::Fn { .. } => { // For methods, we check the function signature's return type for any GATs // to constrain. In the `into_iter` case, we see that the return type // `Self::Iter<'a>` is a GAT we want to gather any potential missing bounds from. @@ -1089,7 +1089,7 @@ fn check_associated_item( ); Ok(()) } - ty::AssocKind::Fn => { + ty::AssocKind::Fn { .. } => { let sig = tcx.fn_sig(item.def_id).instantiate_identity(); let hir_sig = sig_if_method.expect("bad signature for method"); check_fn_or_method( @@ -1716,7 +1716,7 @@ fn check_method_receiver<'tcx>( ) -> Result<(), ErrorGuaranteed> { let tcx = wfcx.tcx(); - if !method.fn_has_self_parameter { + if !method.is_method() { return Ok(()); } diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index deded6904d48..4520fbe352ce 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -44,7 +44,7 @@ use rustc_trait_selection::traits::ObligationCtxt; use tracing::{debug, instrument}; use crate::errors; -use crate::hir_ty_lowering::errors::assoc_kind_str; +use crate::hir_ty_lowering::errors::assoc_tag_str; use crate::hir_ty_lowering::{FeedConstTy, HirTyLowerer, RegionInferReason}; pub(crate) mod dump; @@ -450,7 +450,7 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { item_def_id: DefId, item_segment: &rustc_hir::PathSegment<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tcx>, - kind: ty::AssocKind, + assoc_tag: ty::AssocTag, ) -> Result<(DefId, ty::GenericArgsRef<'tcx>), ErrorGuaranteed> { if let Some(trait_ref) = poly_trait_ref.no_bound_vars() { let item_args = self.lowerer().lower_generic_args_of_assoc_item( @@ -525,7 +525,7 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { inferred_sugg, bound, mpart_sugg, - what: assoc_kind_str(kind), + what: assoc_tag_str(assoc_tag), })) } } diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 9bcda35ee87a..1c477755e5ac 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -1811,7 +1811,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { self.tcx, type_def_id, constraint.ident, - ty::AssocKind::Fn, + ty::AssocTag::Fn, ) { bound_vars.extend( self.tcx @@ -1843,7 +1843,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { self.tcx, type_def_id, constraint.ident, - ty::AssocKind::Type, + ty::AssocTag::Type, ) .map(|(bound_vars, _)| bound_vars); self.with(scope, |this| { @@ -1875,13 +1875,13 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { tcx: TyCtxt<'tcx>, def_id: DefId, assoc_ident: Ident, - assoc_kind: ty::AssocKind, + assoc_tag: ty::AssocTag, ) -> Option<(Vec, &'tcx ty::AssocItem)> { let trait_defines_associated_item_named = |trait_def_id: DefId| { tcx.associated_items(trait_def_id).find_by_ident_and_kind( tcx, assoc_ident, - assoc_kind, + assoc_tag, trait_def_id, ) }; @@ -1894,8 +1894,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { let Some((def_id, bound_vars)) = stack.pop() else { break None; }; - // See issue #83753. If someone writes an associated type on a non-trait, just treat it as - // there being no supertrait HRTBs. + // See issue #83753. If someone writes an associated type on a non-trait, just treat it + // as there being no supertrait HRTBs. match tcx.def_kind(def_id) { DefKind::Trait | DefKind::TraitAlias | DefKind::Impl { .. } => {} _ => break None, @@ -2067,7 +2067,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { self.tcx, trait_def_id, item_segment.ident, - ty::AssocKind::Fn, + ty::AssocTag::Fn, ) }); @@ -2112,7 +2112,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { self.tcx, trait_def_id, item_segment.ident, - ty::AssocKind::Fn, + ty::AssocTag::Fn, ) else { return; }; diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs index 772197a53ace..f06636447194 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs @@ -32,7 +32,9 @@ pub(super) fn find_opaque_ty_constraints_for_impl_trait_in_assoc_type( for &assoc_id in tcx.associated_item_def_ids(impl_def_id) { let assoc = tcx.associated_item(assoc_id); match assoc.kind { - ty::AssocKind::Const | ty::AssocKind::Fn => locator.check(assoc_id.expect_local()), + ty::AssocKind::Const | ty::AssocKind::Fn { .. } => { + locator.check(assoc_id.expect_local()) + } // Associated types don't have bodies, so they can't constrain hidden types ty::AssocKind::Type => {} } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 24d05b49861c..bf91eb1b8fda 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -431,16 +431,16 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) -> Result<(), ErrorGuaranteed> { let tcx = self.tcx(); - let assoc_kind = if constraint.gen_args.parenthesized + let assoc_tag = if constraint.gen_args.parenthesized == hir::GenericArgsParentheses::ReturnTypeNotation { - ty::AssocKind::Fn + ty::AssocTag::Fn } else if let hir::AssocItemConstraintKind::Equality { term: hir::Term::Const(_) } = constraint.kind { - ty::AssocKind::Const + ty::AssocTag::Const } else { - ty::AssocKind::Type + ty::AssocTag::Type }; // Given something like `U: Trait`, we want to produce a predicate like @@ -453,7 +453,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // trait SuperTrait { type T; } let candidate = if self.probe_trait_that_defines_assoc_item( trait_ref.def_id(), - assoc_kind, + assoc_tag, constraint.ident, ) { // Simple case: The assoc item is defined in the current trait. @@ -464,7 +464,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { self.probe_single_bound_for_assoc_item( || traits::supertraits(tcx, trait_ref), AssocItemQSelf::Trait(trait_ref.def_id()), - assoc_kind, + assoc_tag, constraint.ident, path_span, Some(constraint), @@ -474,7 +474,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let assoc_item = self .probe_assoc_item( constraint.ident, - assoc_kind, + assoc_tag, hir_ref_id, constraint.span, candidate.def_id(), @@ -493,7 +493,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }) .or_insert(constraint.span); - let projection_term = if let ty::AssocKind::Fn = assoc_kind { + let projection_term = if let ty::AssocTag::Fn = assoc_tag { let bound_vars = tcx.late_bound_vars(constraint.hir_id); ty::Binder::bind_with_vars( self.lower_return_type_notation_ty(candidate, assoc_item.def_id, path_span)?.into(), @@ -542,7 +542,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }; match constraint.kind { - hir::AssocItemConstraintKind::Equality { .. } if let ty::AssocKind::Fn = assoc_kind => { + hir::AssocItemConstraintKind::Equality { .. } if let ty::AssocTag::Fn = assoc_tag => { return Err(self.dcx().emit_err(crate::errors::ReturnTypeNotationEqualityBound { span: constraint.span, })); @@ -679,7 +679,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { trait_def_id, hir_ty.span, item_segment, - ty::AssocKind::Type, + ty::AssocTag::Type, ); return Ty::new_error(tcx, guar); }; @@ -771,7 +771,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) }, AssocItemQSelf::SelfTyAlias, - ty::AssocKind::Fn, + ty::AssocTag::Fn, assoc_ident, span, None, @@ -783,7 +783,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) => self.probe_single_ty_param_bound_for_assoc_item( param_did.expect_local(), qself.span, - ty::AssocKind::Fn, + ty::AssocTag::Fn, assoc_ident, span, )?, @@ -823,7 +823,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let trait_def_id = bound.def_id(); let assoc_ty = self - .probe_assoc_item(assoc_ident, ty::AssocKind::Fn, qpath_hir_id, span, trait_def_id) + .probe_assoc_item(assoc_ident, ty::AssocTag::Fn, qpath_hir_id, span, trait_def_id) .expect("failed to find associated type"); Ok((bound, assoc_ty.def_id)) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 5a0524d33fde..4f8d5471b6f4 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -116,7 +116,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { &self, all_candidates: impl Fn() -> I, qself: AssocItemQSelf, - assoc_kind: ty::AssocKind, + assoc_tag: ty::AssocTag, assoc_ident: Ident, span: Span, constraint: Option<&hir::AssocItemConstraint<'tcx>>, @@ -134,14 +134,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }) { return self.complain_about_assoc_kind_mismatch( assoc_item, - assoc_kind, + assoc_tag, assoc_ident, span, constraint, ); } - let assoc_kind_str = assoc_kind_str(assoc_kind); + let assoc_kind_str = assoc_tag_str(assoc_tag); let qself_str = qself.to_string(tcx); // The fallback span is needed because `assoc_name` might be an `Fn()`'s `Output` without a @@ -168,7 +168,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let all_candidate_names: Vec<_> = all_candidates() .flat_map(|r| tcx.associated_items(r.def_id()).in_definition_order()) .filter_map(|item| { - (!item.is_impl_trait_in_trait() && item.kind == assoc_kind).then_some(item.name) + (!item.is_impl_trait_in_trait() && item.as_tag() == assoc_tag).then_some(item.name) }) .collect(); @@ -200,7 +200,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .iter() .flat_map(|trait_def_id| tcx.associated_items(*trait_def_id).in_definition_order()) .filter_map(|item| { - (!item.is_impl_trait_in_trait() && item.kind == assoc_kind).then_some(item.name) + (!item.is_impl_trait_in_trait() && item.as_tag() == assoc_tag).then_some(item.name) }) .collect(); @@ -213,7 +213,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .filter(|trait_def_id| { tcx.associated_items(trait_def_id) .filter_by_name_unhygienic(suggested_name) - .any(|item| item.kind == assoc_kind) + .any(|item| item.as_tag() == assoc_tag) }) .collect::>()[..] { @@ -330,7 +330,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { fn complain_about_assoc_kind_mismatch( &self, assoc_item: &ty::AssocItem, - assoc_kind: ty::AssocKind, + assoc_tag: ty::AssocTag, ident: Ident, span: Span, constraint: Option<&hir::AssocItemConstraint<'tcx>>, @@ -375,17 +375,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { hir::Term::Ty(ty) => ty.span, hir::Term::Const(ct) => ct.span(), }; - (span, Some(ident.span), assoc_item.kind, assoc_kind) + (span, Some(ident.span), assoc_item.as_tag(), assoc_tag) } else { - (ident.span, None, assoc_kind, assoc_item.kind) + (ident.span, None, assoc_tag, assoc_item.as_tag()) }; self.dcx().emit_err(errors::AssocKindMismatch { span, - expected: assoc_kind_str(expected), - got: assoc_kind_str(got), + expected: assoc_tag_str(expected), + got: assoc_tag_str(got), expected_because_label, - assoc_kind: assoc_kind_str(assoc_item.kind), + assoc_kind: assoc_tag_str(assoc_item.as_tag()), def_span: tcx.def_span(assoc_item.def_id), bound_on_assoc_const_label, wrap_in_braces_sugg, @@ -398,9 +398,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { types: &[String], traits: &[String], name: Symbol, - kind: ty::AssocKind, + assoc_tag: ty::AssocTag, ) -> ErrorGuaranteed { - let kind_str = assoc_kind_str(kind); + let kind_str = assoc_tag_str(assoc_tag); let mut err = struct_span_code_err!(self.dcx(), span, E0223, "ambiguous associated {kind_str}"); if self @@ -569,7 +569,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { candidates: Vec<(DefId, (DefId, DefId))>, fulfillment_errors: Vec>, span: Span, - kind: ty::AssocKind, + assoc_tag: ty::AssocTag, ) -> ErrorGuaranteed { // FIXME(fmease): This was copied in parts from an old version of `rustc_hir_typeck::method::suggest`. // Either @@ -579,14 +579,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let tcx = self.tcx(); - let kind_str = assoc_kind_str(kind); + let assoc_tag_str = assoc_tag_str(assoc_tag); let adt_did = self_ty.ty_adt_def().map(|def| def.did()); let add_def_label = |err: &mut Diag<'_>| { if let Some(did) = adt_did { err.span_label( tcx.def_span(did), format!( - "associated {kind_str} `{name}` not found for this {}", + "associated {assoc_tag_str} `{name}` not found for this {}", tcx.def_descr(did) ), ); @@ -615,11 +615,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { self.dcx(), name.span, E0220, - "associated {kind_str} `{name}` not found for `{self_ty}` in the current scope" + "associated {assoc_tag_str} `{name}` not found for `{self_ty}` in the current scope" ); err.span_label(name.span, format!("associated item not found in `{self_ty}`")); err.note(format!( - "the associated {kind_str} was found for\n{type_candidates}{additional_types}", + "the associated {assoc_tag_str} was found for\n{type_candidates}{additional_types}", )); add_def_label(&mut err); return err.emit(); @@ -700,7 +700,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let mut err = self.dcx().struct_span_err( name.span, - format!("the associated {kind_str} `{name}` exists for `{self_ty}`, but its trait bounds were not satisfied") + format!("the associated {assoc_tag_str} `{name}` exists for `{self_ty}`, but its trait bounds were not satisfied") ); if !bounds.is_empty() { err.note(format!( @@ -710,7 +710,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } err.span_label( name.span, - format!("associated {kind_str} cannot be referenced on `{self_ty}` due to unsatisfied trait bounds") + format!("associated {assoc_tag_str} cannot be referenced on `{self_ty}` due to unsatisfied trait bounds") ); for (span, mut bounds) in bound_spans { @@ -812,7 +812,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let assoc_item = tcx.associated_items(trait_def).find_by_ident_and_kind( tcx, ident, - ty::AssocKind::Type, + ty::AssocTag::Type, trait_def, ); @@ -1022,12 +1022,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .map(|simple_ty| tcx.incoherent_impls(simple_ty)) }) && let name = Symbol::intern(&format!("{ident2}_{ident3}")) - && let Some(ty::AssocItem { kind: ty::AssocKind::Fn, .. }) = inherent_impls + && let Some(item) = inherent_impls .iter() .flat_map(|inherent_impl| { tcx.associated_items(inherent_impl).filter_by_name_unhygienic(name) }) .next() + && item.is_fn() { Err(struct_span_code_err!(self.dcx(), span, E0223, "ambiguous associated type") .with_span_suggestion_verbose( @@ -1629,10 +1630,10 @@ fn generics_args_err_extend<'a>( } } -pub(crate) fn assoc_kind_str(kind: ty::AssocKind) -> &'static str { - match kind { - ty::AssocKind::Fn => "function", - ty::AssocKind::Const => "constant", - ty::AssocKind::Type => "type", +pub(crate) fn assoc_tag_str(assoc_tag: ty::AssocTag) -> &'static str { + match assoc_tag { + ty::AssocTag::Fn => "function", + ty::AssocTag::Const => "constant", + ty::AssocTag::Type => "type", } } 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 83aa0d956201..0fb406d99080 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -38,8 +38,8 @@ use rustc_middle::middle::stability::AllowUnstable; use rustc_middle::mir::interpret::LitToConstInput; use rustc_middle::ty::print::PrintPolyTraitRefExt as _; use rustc_middle::ty::{ - self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, ParamEnv, Ty, TyCtxt, - TypeVisitableExt, TypingMode, Upcast, fold_regions, + self, AssocTag, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, ParamEnv, Ty, + TyCtxt, TypeVisitableExt, TypingMode, Upcast, fold_regions, }; use rustc_middle::{bug, span_bug}; use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; @@ -51,7 +51,7 @@ use rustc_trait_selection::traits::wf::object_region_bounds; use rustc_trait_selection::traits::{self, ObligationCtxt}; use tracing::{debug, instrument}; -use self::errors::assoc_kind_str; +use self::errors::assoc_tag_str; use crate::check::check_abi_fn_ptr; use crate::errors::{AmbiguousLifetimeBound, BadReturnTypeNotation, NoVariantNamed}; use crate::hir_ty_lowering::errors::{GenericsArgsErrExtend, prohibit_assoc_item_constraint}; @@ -168,7 +168,7 @@ pub trait HirTyLowerer<'tcx> { item_def_id: DefId, item_segment: &hir::PathSegment<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tcx>, - kind: ty::AssocKind, + assoc_tag: ty::AssocTag, ) -> Result<(DefId, GenericArgsRef<'tcx>), ErrorGuaranteed>; fn lower_fn_sig( @@ -251,10 +251,10 @@ enum LowerAssocMode { } impl LowerAssocMode { - fn kind(self) -> ty::AssocKind { + fn assoc_tag(self) -> ty::AssocTag { match self { - LowerAssocMode::Type { .. } => ty::AssocKind::Type, - LowerAssocMode::Const => ty::AssocKind::Const, + LowerAssocMode::Type { .. } => ty::AssocTag::Type, + LowerAssocMode::Const => ty::AssocTag::Const, } } @@ -268,7 +268,8 @@ impl LowerAssocMode { fn permit_variants(self) -> bool { match self { LowerAssocMode::Type { permit_variants } => permit_variants, - // FIXME(mgca): Support paths like `Option::::None` or `Option::::Some` which resolve to const ctors/fn items respectively + // FIXME(mgca): Support paths like `Option::::None` or `Option::::Some` which + // resolve to const ctors/fn items respectively. LowerAssocMode::Const => false, } } @@ -932,12 +933,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { fn probe_trait_that_defines_assoc_item( &self, trait_def_id: DefId, - assoc_kind: ty::AssocKind, + assoc_tag: AssocTag, assoc_ident: Ident, ) -> bool { self.tcx() .associated_items(trait_def_id) - .find_by_ident_and_kind(self.tcx(), assoc_ident, assoc_kind, trait_def_id) + .find_by_ident_and_kind(self.tcx(), assoc_ident, assoc_tag, trait_def_id) .is_some() } @@ -975,7 +976,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { &self, ty_param_def_id: LocalDefId, ty_param_span: Span, - kind: ty::AssocKind, + assoc_tag: AssocTag, assoc_ident: Ident, span: Span, ) -> Result, ErrorGuaranteed> { @@ -993,7 +994,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { traits::transitive_bounds_that_define_assoc_item(tcx, trait_refs, assoc_ident) }, AssocItemQSelf::TyParam(ty_param_def_id, ty_param_span), - kind, + assoc_tag, assoc_ident, span, None, @@ -1010,7 +1011,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { &self, all_candidates: impl Fn() -> I, qself: AssocItemQSelf, - assoc_kind: ty::AssocKind, + assoc_tag: AssocTag, assoc_ident: Ident, span: Span, constraint: Option<&hir::AssocItemConstraint<'tcx>>, @@ -1021,14 +1022,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let tcx = self.tcx(); let mut matching_candidates = all_candidates().filter(|r| { - self.probe_trait_that_defines_assoc_item(r.def_id(), assoc_kind, assoc_ident) + self.probe_trait_that_defines_assoc_item(r.def_id(), assoc_tag, assoc_ident) }); let Some(bound) = matching_candidates.next() else { let reported = self.complain_about_assoc_item_not_found( all_candidates, qself, - assoc_kind, + assoc_tag, assoc_ident, span, constraint, @@ -1040,7 +1041,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { if let Some(bound2) = matching_candidates.next() { debug!(?bound2); - let assoc_kind_str = errors::assoc_kind_str(assoc_kind); + let assoc_kind_str = errors::assoc_tag_str(assoc_tag); let qself_str = qself.to_string(tcx); let mut err = self.dcx().create_err(crate::errors::AmbiguousAssocItem { span, @@ -1059,14 +1060,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }, ); - // FIXME(#97583): Print associated item bindings properly (i.e., not as equality predicates!). + // FIXME(#97583): Print associated item bindings properly (i.e., not as equality + // predicates!). // FIXME: Turn this into a structured, translateable & more actionable suggestion. let mut where_bounds = vec![]; for bound in [bound, bound2].into_iter().chain(matching_candidates) { let bound_id = bound.def_id(); let bound_span = tcx .associated_items(bound_id) - .find_by_ident_and_kind(tcx, assoc_ident, assoc_kind, bound_id) + .find_by_ident_and_kind(tcx, assoc_ident, assoc_tag, bound_id) .and_then(|item| tcx.hir_span_if_local(item.def_id)); if let Some(bound_span) = bound_span { @@ -1265,7 +1267,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { qself_ty, hir_ref_id, span, - mode.kind(), + mode.assoc_tag(), )? { return Ok(LoweredAssoc::Term(did, args)); } @@ -1296,7 +1298,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) }, AssocItemQSelf::SelfTyAlias, - mode.kind(), + mode.assoc_tag(), assoc_ident, span, None, @@ -1308,12 +1310,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) => self.probe_single_ty_param_bound_for_assoc_item( param_did.expect_local(), qself.span, - mode.kind(), + mode.assoc_tag(), assoc_ident, span, )?, _ => { - let kind_str = assoc_kind_str(mode.kind()); + let kind_str = assoc_tag_str(mode.assoc_tag()); let reported = if variant_resolution.is_some() { // Variant in type position let msg = format!("expected {kind_str}, found variant `{assoc_ident}`"); @@ -1420,7 +1422,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { &[qself_ty.to_string()], &traits, assoc_ident.name, - mode.kind(), + mode.assoc_tag(), ) }; return Err(reported); @@ -1429,10 +1431,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let trait_did = bound.def_id(); let assoc_item = self - .probe_assoc_item(assoc_ident, mode.kind(), hir_ref_id, span, trait_did) + .probe_assoc_item(assoc_ident, mode.assoc_tag(), hir_ref_id, span, trait_did) .expect("failed to find associated item"); - let (def_id, args) = - self.lower_assoc_shared(span, assoc_item.def_id, assoc_segment, bound, mode.kind())?; + let (def_id, args) = self.lower_assoc_shared( + span, + assoc_item.def_id, + assoc_segment, + bound, + mode.assoc_tag(), + )?; let result = LoweredAssoc::Term(def_id, args); if let Some(variant_def_id) = variant_resolution { @@ -1469,20 +1476,21 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { self_ty: Ty<'tcx>, block: HirId, span: Span, - kind: ty::AssocKind, + assoc_tag: ty::AssocTag, ) -> Result)>, ErrorGuaranteed> { let tcx = self.tcx(); if !tcx.features().inherent_associated_types() { - match kind { - // Don't attempt to look up inherent associated types when the feature is not enabled. - // Theoretically it'd be fine to do so since we feature-gate their definition site. - // However, due to current limitations of the implementation (caused by us performing - // selection during HIR ty lowering instead of in the trait solver), IATs can lead to cycle - // errors (#108491) which mask the feature-gate error, needlessly confusing users - // who use IATs by accident (#113265). - ty::AssocKind::Type => return Ok(None), - ty::AssocKind::Const => { + match assoc_tag { + // Don't attempt to look up inherent associated types when the feature is not + // enabled. Theoretically it'd be fine to do so since we feature-gate their + // definition site. However, due to current limitations of the implementation + // (caused by us performing selection during HIR ty lowering instead of in the + // trait solver), IATs can lead to cycle errors (#108491) which mask the + // feature-gate error, needlessly confusing users who use IATs by accident + // (#113265). + ty::AssocTag::Type => return Ok(None), + ty::AssocTag::Const => { // We also gate the mgca codepath for type-level uses of inherent consts // with the inherent_associated_types feature gate since it relies on the // same machinery and has similar rough edges. @@ -1494,7 +1502,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) .emit()); } - ty::AssocKind::Fn => unreachable!(), + ty::AssocTag::Fn => unreachable!(), } } @@ -1503,7 +1511,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .inherent_impls(adt_did) .iter() .filter_map(|&impl_| { - let (item, scope) = self.probe_assoc_item_unchecked(name, kind, block, impl_)?; + let (item, scope) = + self.probe_assoc_item_unchecked(name, assoc_tag, block, impl_)?; Some((impl_, (item.def_id, scope))) }) .collect(); @@ -1542,7 +1551,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { self_ty, |self_ty| { self.select_inherent_assoc_candidates( - infcx, name, span, self_ty, param_env, candidates, kind, + infcx, name, span, self_ty, param_env, candidates, assoc_tag, ) }, )?; @@ -1570,7 +1579,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { self_ty: Ty<'tcx>, param_env: ParamEnv<'tcx>, candidates: Vec<(DefId, (DefId, DefId))>, - kind: ty::AssocKind, + assoc_tag: ty::AssocTag, ) -> Result<(DefId, (DefId, DefId)), ErrorGuaranteed> { let tcx = self.tcx(); let mut fulfillment_errors = Vec::new(); @@ -1621,7 +1630,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { candidates, fulfillment_errors, span, - kind, + assoc_tag, )), &[applicable_candidate] => Ok(applicable_candidate), @@ -1640,12 +1649,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { fn probe_assoc_item( &self, ident: Ident, - kind: ty::AssocKind, + assoc_tag: ty::AssocTag, block: HirId, span: Span, scope: DefId, ) -> Option { - let (item, scope) = self.probe_assoc_item_unchecked(ident, kind, block, scope)?; + let (item, scope) = self.probe_assoc_item_unchecked(ident, assoc_tag, block, scope)?; self.check_assoc_item(item.def_id, ident, scope, block, span); Some(item) } @@ -1657,7 +1666,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { fn probe_assoc_item_unchecked( &self, ident: Ident, - kind: ty::AssocKind, + assoc_tag: ty::AssocTag, block: HirId, scope: DefId, ) -> Option<(ty::AssocItem, /*scope*/ DefId)> { @@ -1670,7 +1679,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let item = tcx .associated_items(scope) .filter_by_name_unhygienic(ident.name) - .find(|i| i.kind == kind && i.ident(tcx).normalize_to_macros_2_0() == ident)?; + .find(|i| i.as_tag() == assoc_tag && i.ident(tcx).normalize_to_macros_2_0() == ident)?; Some((*item, def_scope)) } @@ -1770,7 +1779,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { item_def_id, trait_segment, item_segment, - ty::AssocKind::Type, + ty::AssocTag::Type, ) { Ok((item_def_id, item_args)) => { Ty::new_projection_from_args(self.tcx(), item_def_id, item_args) @@ -1795,7 +1804,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { item_def_id, trait_segment, item_segment, - ty::AssocKind::Const, + ty::AssocTag::Const, ) { Ok((item_def_id, item_args)) => { let uv = ty::UnevaluatedConst::new(item_def_id, item_args); @@ -1813,7 +1822,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { item_def_id: DefId, trait_segment: &hir::PathSegment<'tcx>, item_segment: &hir::PathSegment<'tcx>, - kind: ty::AssocKind, + assoc_tag: ty::AssocTag, ) -> Result<(DefId, GenericArgsRef<'tcx>), ErrorGuaranteed> { let tcx = self.tcx(); @@ -1821,7 +1830,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { debug!(?trait_def_id); let Some(self_ty) = opt_self_ty else { - return Err(self.error_missing_qpath_self_ty(trait_def_id, span, item_segment, kind)); + return Err(self.error_missing_qpath_self_ty( + trait_def_id, + span, + item_segment, + assoc_tag, + )); }; debug!(?self_ty); @@ -1840,7 +1854,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { trait_def_id: DefId, span: Span, item_segment: &hir::PathSegment<'tcx>, - kind: ty::AssocKind, + assoc_tag: ty::AssocTag, ) -> ErrorGuaranteed { let tcx = self.tcx(); let path_str = tcx.def_path_str(trait_def_id); @@ -1877,7 +1891,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // FIXME: also look at `tcx.generics_of(self.item_def_id()).params` any that // references the trait. Relevant for the first case in // `src/test/ui/associated-types/associated-types-in-ambiguous-context.rs` - self.report_ambiguous_assoc(span, &type_names, &[path_str], item_segment.ident.name, kind) + self.report_ambiguous_assoc( + span, + &type_names, + &[path_str], + item_segment.ident.name, + assoc_tag, + ) } pub fn prohibit_generic_args<'a>( @@ -2862,7 +2882,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let assoc = tcx.associated_items(trait_ref.def_id).find_by_ident_and_kind( tcx, *ident, - ty::AssocKind::Fn, + ty::AssocTag::Fn, trait_ref.def_id, )?; diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs index c30b39dfe765..1ab36ce1dcb9 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs @@ -119,7 +119,7 @@ pub(crate) fn enforce_impl_lifetime_params_are_constrained( vec![] } } - ty::AssocKind::Fn | ty::AssocKind::Const => vec![], + ty::AssocKind::Fn { .. } | ty::AssocKind::Const => vec![], } }) .collect(); diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index fec459954107..d1bc54ed73ea 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -1089,14 +1089,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// This function checks whether the method is not static and does not accept other parameters than `self`. fn has_only_self_parameter(&self, method: &AssocItem) -> bool { - match method.kind { - ty::AssocKind::Fn => { - method.fn_has_self_parameter - && self.tcx.fn_sig(method.def_id).skip_binder().inputs().skip_binder().len() - == 1 - } - _ => false, - } + method.is_method() + && self.tcx.fn_sig(method.def_id).skip_binder().inputs().skip_binder().len() == 1 } /// If the given `HirId` corresponds to a block with a trailing expression, return that expression diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index de2f039cb1c8..56c205b6f879 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -2588,9 +2588,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .into_iter() .flat_map(|i| self.tcx.associated_items(i).in_definition_order()) // Only assoc fn with no receivers. - .filter(|item| { - matches!(item.kind, ty::AssocKind::Fn) && !item.fn_has_self_parameter - }) + .filter(|item| item.is_fn() && !item.is_method()) .filter_map(|item| { // Only assoc fns that return `Self` let fn_sig = self.tcx.fn_sig(item.def_id).skip_binder(); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 81eb8510785b..3a0f3a4a5f0b 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -616,7 +616,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some((DefKind::AssocFn, def_id)) = self.typeck_results.borrow().type_dependent_def(call_expr.hir_id) && let Some(assoc) = tcx.opt_associated_item(def_id) - && assoc.fn_has_self_parameter + && assoc.is_method() { Some(*receiver) } else { @@ -642,8 +642,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { TraitsInScope, |mut ctxt| ctxt.probe_for_similar_candidate(), ) - && let ty::AssocKind::Fn = assoc.kind - && assoc.fn_has_self_parameter + && assoc.is_method() { let args = self.infcx.fresh_args_for_item(call_name.span, assoc.def_id); let fn_sig = tcx.fn_sig(assoc.def_id).instantiate(tcx, args); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index e14f1528d2c4..74cc8181418c 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -314,7 +314,7 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> { item_def_id: DefId, item_segment: &rustc_hir::PathSegment<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tcx>, - _kind: ty::AssocKind, + _assoc_tag: ty::AssocTag, ) -> Result<(DefId, ty::GenericArgsRef<'tcx>), ErrorGuaranteed> { let trait_ref = self.instantiate_binder_with_fresh_vars( span, diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index ddfd27ccf6b7..39cb139a199e 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -379,7 +379,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let def_id = method_item.def_id; - if method_item.kind != ty::AssocKind::Fn { + if !method_item.is_fn() { span_bug!(tcx.def_span(def_id), "expected `{m_name}` to be an associated function"); } diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 0a01ec89a327..d5d85c812b2d 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -992,7 +992,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { fn matches_return_type(&self, method: ty::AssocItem, expected: Ty<'tcx>) -> bool { match method.kind { - ty::AssocKind::Fn => self.probe(|_| { + ty::AssocKind::Fn { .. } => self.probe(|_| { let args = self.fresh_args_for_item(self.span, method.def_id); let fty = self.tcx.fn_sig(method.def_id).instantiate(self.tcx, args); let fty = self.instantiate_binder_with_fresh_vars(self.span, infer::FnCall, fty); @@ -1678,7 +1678,6 @@ impl<'tcx> Pick<'tcx> { kind: _, container: _, trait_item_def_id: _, - fn_has_self_parameter: _, opt_rpitit_info: _, }, kind: _, @@ -1712,7 +1711,7 @@ impl<'tcx> Pick<'tcx> { )); match (self.item.kind, self.item.container) { - (ty::AssocKind::Fn, _) => { + (ty::AssocKind::Fn { .. }, _) => { // FIXME: This should be a `span_suggestion` instead of `help` // However `self.span` only // highlights the method name, so we can't use it. Also consider reusing @@ -2252,10 +2251,10 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // In Path mode (i.e., resolving a value like `T::next`), consider any // associated value (i.e., methods, constants) but not types. match self.mode { - Mode::MethodCall => item.fn_has_self_parameter, + Mode::MethodCall => item.is_method(), Mode::Path => match item.kind { ty::AssocKind::Type => false, - ty::AssocKind::Fn | ty::AssocKind::Const => true, + ty::AssocKind::Fn { .. } | ty::AssocKind::Const => true, }, } // FIXME -- check for types that deref to `Self`, @@ -2277,7 +2276,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { impl_ty: Ty<'tcx>, args: GenericArgsRef<'tcx>, ) -> (Ty<'tcx>, Option>) { - if item.kind == ty::AssocKind::Fn && self.mode == Mode::MethodCall { + if item.is_fn() && self.mode == Mode::MethodCall { let sig = self.xform_method_sig(item.def_id, args); (sig.inputs()[0], Some(sig.output())) } else { @@ -2328,8 +2327,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { /// Determine if the given associated item type is relevant in the current context. fn is_relevant_kind_for_mode(&self, kind: ty::AssocKind) -> bool { match (self.mode, kind) { - (Mode::MethodCall, ty::AssocKind::Fn) => true, - (Mode::Path, ty::AssocKind::Const | ty::AssocKind::Fn) => true, + (Mode::MethodCall, ty::AssocKind::Fn { .. }) => true, + (Mode::Path, ty::AssocKind::Const | ty::AssocKind::Fn { .. }) => true, _ => false, } } diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 68f13d654d6e..1b9771636a7d 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -713,7 +713,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && let Some(candidate) = tcx.associated_items(impl_def_id).find_by_ident_and_kind( self.tcx, item_ident, - ty::AssocKind::Type, + ty::AssocTag::Type, impl_def_id, ) && let Some(adt_def) = tcx.type_of(candidate.def_id).skip_binder().ty_adt_def() @@ -1442,7 +1442,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(assoc) = self.associated_value(*def_id, item_ident) { // Check for both mode is the same so we avoid suggesting // incorrect associated item. - match (mode, assoc.fn_has_self_parameter, source) { + match (mode, assoc.is_method(), source) { (Mode::MethodCall, true, SelfSource::MethodCall(_)) => { // We check that the suggest type is actually // different from the received one @@ -1834,7 +1834,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty_args = self.infcx.fresh_args_for_item(span, similar_candidate.def_id); let fn_sig = tcx.fn_sig(similar_candidate.def_id).instantiate(tcx, ty_args); let fn_sig = self.instantiate_binder_with_fresh_vars(span, infer::FnCall, fn_sig); - if similar_candidate.fn_has_self_parameter { + if similar_candidate.is_method() { if let Some(args) = args && fn_sig.inputs()[1..].len() == args.len() { @@ -1902,7 +1902,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { if let Some(candidates) = find_attr!(self.tcx.get_all_attrs(inherent_method.def_id), AttributeKind::Confusables{symbols, ..} => symbols) && candidates.contains(&item_name.name) - && let ty::AssocKind::Fn = inherent_method.kind + && inherent_method.is_fn() { let args = ty::GenericArgs::identity_for_item(self.tcx, inherent_method.def_id) @@ -2116,8 +2116,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Only assoc fn with no receivers and only if // they are resolvable .filter(|item| { - matches!(item.kind, ty::AssocKind::Fn) - && !item.fn_has_self_parameter + matches!(item.kind, ty::AssocKind::Fn { has_self: false }) && self .probe_for_name( Mode::Path, @@ -2261,7 +2260,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let assoc = self.associated_value(assoc_did, item_name)?; - if assoc.kind != ty::AssocKind::Fn { + if !assoc.is_fn() { return None; } @@ -3208,7 +3207,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If this method receives `&self`, then the provided // argument _should_ coerce, so it's valid to suggest // just changing the path. - && pick.item.fn_has_self_parameter + && pick.item.is_method() && let Some(self_ty) = self.tcx.fn_sig(pick.item.def_id).instantiate_identity().inputs().skip_binder().get(0) && self_ty.is_ref() @@ -3560,7 +3559,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { || (("Pin::new" == *pre) && ((sym::as_ref == item_name.name) || !unpin)) || inputs_len.is_some_and(|inputs_len| { - pick.item.kind == ty::AssocKind::Fn + pick.item.is_fn() && self .tcx .fn_sig(pick.item.def_id) @@ -3618,7 +3617,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && pick.autoderefs == 0 // Check that the method of the same name that was found on the new `Pin` // receiver has the same number of arguments that appear in the user's code. - && inputs_len.is_some_and(|inputs_len| pick.item.kind == ty::AssocKind::Fn && self.tcx.fn_sig(pick.item.def_id).skip_binder().skip_binder().inputs().len() == inputs_len) + && inputs_len.is_some_and(|inputs_len| pick.item.is_fn() && self.tcx.fn_sig(pick.item.def_id).skip_binder().skip_binder().inputs().len() == inputs_len) { let indent = self .tcx @@ -3756,7 +3755,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && self .associated_value(info.def_id, item_name) .filter(|item| { - if let ty::AssocKind::Fn = item.kind { + if item.is_fn() { let id = item .def_id .as_local() @@ -4279,13 +4278,13 @@ fn print_disambiguation_help<'tcx>( item: ty::AssocItem, ) -> Option { let trait_impl_type = trait_ref.self_ty().peel_refs(); - let trait_ref = if item.fn_has_self_parameter { + let trait_ref = if item.is_method() { trait_ref.print_only_trait_name().to_string() } else { format!("<{} as {}>", trait_ref.args[0], trait_ref.print_only_trait_name()) }; Some( - if matches!(item.kind, ty::AssocKind::Fn) + if item.is_fn() && let SelfSource::MethodCall(receiver) = source && let Some(args) = args { @@ -4304,7 +4303,7 @@ fn print_disambiguation_help<'tcx>( let args = if let Some(first_arg_type) = first_arg_type && (first_arg_type == tcx.types.self_param || first_arg_type == trait_impl_type - || item.fn_has_self_parameter) + || item.is_method()) { Some(receiver) } else { diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index a2d5ffe256d5..dd3c514704a1 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -859,12 +859,7 @@ impl<'tcx> LateContext<'tcx> { ) -> Option> { let tcx = self.tcx; tcx.associated_items(trait_id) - .find_by_ident_and_kind( - tcx, - Ident::with_dummy_span(name), - ty::AssocKind::Type, - trait_id, - ) + .find_by_ident_and_kind(tcx, Ident::with_dummy_span(name), ty::AssocTag::Type, trait_id) .and_then(|assoc| { let proj = Ty::new_projection(tcx, assoc.def_id, [self_ty]); tcx.try_normalize_erasing_regions(self.typing_env(), proj).ok() diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 4cc12ca2e0bf..cc3b2a241e4a 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1337,10 +1337,12 @@ impl<'a> CrateMetadataRef<'a> { } else { self.item_name(id) }; - let (kind, has_self) = match self.def_kind(id) { - DefKind::AssocConst => (ty::AssocKind::Const, false), - DefKind::AssocFn => (ty::AssocKind::Fn, self.get_fn_has_self_parameter(id, sess)), - DefKind::AssocTy => (ty::AssocKind::Type, false), + let kind = match self.def_kind(id) { + DefKind::AssocConst => ty::AssocKind::Const, + DefKind::AssocFn => { + ty::AssocKind::Fn { has_self: self.get_fn_has_self_parameter(id, sess) } + } + DefKind::AssocTy => ty::AssocKind::Type, _ => bug!("cannot get associated-item of `{:?}`", self.def_key(id)), }; let container = self.root.tables.assoc_container.get(self, id).unwrap(); @@ -1353,7 +1355,6 @@ impl<'a> CrateMetadataRef<'a> { def_id: self.local_def_id(id), trait_item_def_id: self.get_trait_item_def_id(id), container, - fn_has_self_parameter: has_self, opt_rpitit_info, } } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 5c8e2888ec98..cc9da16ffdbb 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1338,7 +1338,7 @@ fn should_encode_const(def_kind: DefKind) -> bool { fn should_encode_fn_impl_trait_in_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool { if let Some(assoc_item) = tcx.opt_associated_item(def_id) && assoc_item.container == ty::AssocItemContainer::Trait - && assoc_item.kind == ty::AssocKind::Fn + && assoc_item.is_fn() { true } else { diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 4dfb362f3a22..db19c858e7c1 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1636,8 +1636,8 @@ pub fn find_self_call<'tcx>( &body[block].terminator && let Operand::Constant(box ConstOperand { const_, .. }) = func && let ty::FnDef(def_id, fn_args) = *const_.ty().kind() - && let Some(ty::AssocItem { fn_has_self_parameter: true, .. }) = - tcx.opt_associated_item(def_id) + && let Some(item) = tcx.opt_associated_item(def_id) + && item.is_method() && let [Spanned { node: Operand::Move(self_place) | Operand::Copy(self_place), .. }, ..] = **args { diff --git a/compiler/rustc_middle/src/ty/adjustment.rs b/compiler/rustc_middle/src/ty/adjustment.rs index f8ab555305f0..3425da485595 100644 --- a/compiler/rustc_middle/src/ty/adjustment.rs +++ b/compiler/rustc_middle/src/ty/adjustment.rs @@ -5,7 +5,7 @@ use rustc_hir::lang_items::LangItem; use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; use rustc_span::Span; -use crate::ty::{self, Ty, TyCtxt}; +use crate::ty::{Ty, TyCtxt}; #[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] pub enum PointerCoercion { @@ -133,7 +133,7 @@ impl OverloadedDeref { }; tcx.associated_items(trait_def_id) .in_definition_order() - .find(|m| m.kind == ty::AssocKind::Fn) + .find(|item| item.is_fn()) .unwrap() .def_id } diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs index bbaf735fbdb9..3c1e5ed9e114 100644 --- a/compiler/rustc_middle/src/ty/assoc.rs +++ b/compiler/rustc_middle/src/ty/assoc.rs @@ -26,10 +26,6 @@ pub struct AssocItem { /// the associated item on the trait that this implements. pub trait_item_def_id: Option, - /// Whether this is a method with an explicit self - /// as its first parameter, allowing method calls. - pub fn_has_self_parameter: bool, - /// `Some` if the associated item (an associated type) comes from the /// return-position `impl Trait` in trait desugaring. The `ImplTraitInTraitData` /// provides additional information about its source. @@ -78,7 +74,7 @@ impl AssocItem { pub fn signature(&self, tcx: TyCtxt<'_>) -> String { match self.kind { - ty::AssocKind::Fn => { + ty::AssocKind::Fn { .. } => { // We skip the binder here because the binder would deanonymize all // late-bound regions, and we don't want method signatures to show up // `as for<'r> fn(&'r MyType)`. Pretty-printing handles late-bound @@ -99,12 +95,28 @@ impl AssocItem { pub fn descr(&self) -> &'static str { match self.kind { ty::AssocKind::Const => "associated const", - ty::AssocKind::Fn if self.fn_has_self_parameter => "method", - ty::AssocKind::Fn => "associated function", + ty::AssocKind::Fn { has_self: true } => "method", + ty::AssocKind::Fn { has_self: false } => "associated function", ty::AssocKind::Type => "associated type", } } + pub fn is_fn(&self) -> bool { + matches!(self.kind, ty::AssocKind::Fn { .. }) + } + + pub fn is_method(&self) -> bool { + matches!(self.kind, ty::AssocKind::Fn { has_self: true }) + } + + pub fn as_tag(&self) -> AssocTag { + match self.kind { + AssocKind::Const => AssocTag::Const, + AssocKind::Fn { .. } => AssocTag::Fn, + AssocKind::Type => AssocTag::Type, + } + } + pub fn is_impl_trait_in_trait(&self) -> bool { self.opt_rpitit_info.is_some() } @@ -131,7 +143,7 @@ impl AssocItem { #[derive(Copy, Clone, PartialEq, Debug, HashStable, Eq, Hash, Encodable, Decodable)] pub enum AssocKind { Const, - Fn, + Fn { has_self: bool }, Type, } @@ -139,14 +151,14 @@ impl AssocKind { pub fn namespace(&self) -> Namespace { match *self { ty::AssocKind::Type => Namespace::TypeNS, - ty::AssocKind::Const | ty::AssocKind::Fn => Namespace::ValueNS, + ty::AssocKind::Const | ty::AssocKind::Fn { .. } => Namespace::ValueNS, } } pub fn as_def_kind(&self) -> DefKind { match self { AssocKind::Const => DefKind::AssocConst, - AssocKind::Fn => DefKind::AssocFn, + AssocKind::Fn { .. } => DefKind::AssocFn, AssocKind::Type => DefKind::AssocTy, } } @@ -155,15 +167,22 @@ impl AssocKind { impl std::fmt::Display for AssocKind { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - // FIXME: fails to distinguish between "associated function" and - // "method" because `has_self` isn't known here. - AssocKind::Fn => write!(f, "method"), + AssocKind::Fn { has_self: true } => write!(f, "method"), + AssocKind::Fn { has_self: false } => write!(f, "associated function"), AssocKind::Const => write!(f, "associated const"), AssocKind::Type => write!(f, "associated type"), } } } +// Like `AssocKind`, but just the tag, no fields. Used in various kinds of matching. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum AssocTag { + Const, + Fn, + Type, +} + /// A list of `ty::AssocItem`s in definition order that allows for efficient lookup by name. /// /// When doing lookup by name, we try to postpone hygienic comparison for as long as possible since @@ -207,27 +226,14 @@ impl AssocItems { &self, tcx: TyCtxt<'_>, ident: Ident, - kind: AssocKind, + assoc_tag: AssocTag, parent_def_id: DefId, ) -> Option<&ty::AssocItem> { self.filter_by_name_unhygienic(ident.name) - .filter(|item| item.kind == kind) + .filter(|item| item.as_tag() == assoc_tag) .find(|item| tcx.hygienic_eq(ident, item.ident(tcx), parent_def_id)) } - /// Returns the associated item with the given identifier and any of `AssocKind`, if one - /// exists. The identifier is matched hygienically. - pub fn find_by_ident_and_kinds( - &self, - tcx: TyCtxt<'_>, - ident: Ident, - // Sorted in order of what kinds to look at - kinds: &[AssocKind], - parent_def_id: DefId, - ) -> Option<&ty::AssocItem> { - kinds.iter().find_map(|kind| self.find_by_ident_and_kind(tcx, ident, *kind, parent_def_id)) - } - /// Returns the associated item with the given identifier in the given `Namespace`, if one /// exists. The identifier is matched hygienically. pub fn find_by_ident_and_namespace( diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 07f2a602f2bf..faad0a82acbf 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -746,7 +746,7 @@ impl<'tcx> Instance<'tcx> { let call_once = tcx .associated_items(fn_once) .in_definition_order() - .find(|it| it.kind == ty::AssocKind::Fn) + .find(|it| it.is_fn()) .unwrap() .def_id; let track_caller = diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index a2b3acac3f26..30c889c39d93 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1464,7 +1464,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn provided_trait_methods(self, id: DefId) -> impl 'tcx + Iterator { self.associated_items(id) .in_definition_order() - .filter(move |item| item.kind == AssocKind::Fn && item.defaultness(self).has_value()) + .filter(move |item| item.is_fn() && item.defaultness(self).has_value()) } pub fn repr_options_of_def(self, did: LocalDefId) -> ReprOptions { diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 857b462b9eb1..dfc11de283d8 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -819,7 +819,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Get an English description for the item's kind. pub fn def_kind_descr(self, def_kind: DefKind, def_id: DefId) -> &'static str { match def_kind { - DefKind::AssocFn if self.associated_item(def_id).fn_has_self_parameter => "method", + DefKind::AssocFn if self.associated_item(def_id).is_method() => "method", DefKind::Closure if let Some(coroutine_kind) = self.coroutine_kind(def_id) => { match coroutine_kind { hir::CoroutineKind::Desugared( @@ -873,7 +873,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Gets an English article for the [`TyCtxt::def_kind_descr`]. pub fn def_kind_descr_article(self, def_kind: DefKind, def_id: DefId) -> &'static str { match def_kind { - DefKind::AssocFn if self.associated_item(def_id).fn_has_self_parameter => "a", + DefKind::AssocFn if self.associated_item(def_id).is_method() => "a", DefKind::Closure if let Some(coroutine_kind) = self.coroutine_kind(def_id) => { match coroutine_kind { hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, ..) => "an", diff --git a/compiler/rustc_mir_build/src/builder/matches/test.rs b/compiler/rustc_mir_build/src/builder/matches/test.rs index d1f9d4c34fe1..16da60929984 100644 --- a/compiler/rustc_mir_build/src/builder/matches/test.rs +++ b/compiler/rustc_mir_build/src/builder/matches/test.rs @@ -715,7 +715,7 @@ fn trait_method<'tcx>( let item = tcx .associated_items(trait_def_id) .filter_by_name_unhygienic(method_name) - .find(|item| item.kind == ty::AssocKind::Fn) + .find(|item| item.is_fn()) .expect("trait method not found"); let method_ty = Ty::new_fn_def(tcx, item.def_id, args); diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index c9771467e499..c13ffae36498 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -66,7 +66,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body< let call_mut = tcx .associated_items(fn_mut) .in_definition_order() - .find(|it| it.kind == ty::AssocKind::Fn) + .find(|it| it.is_fn()) .unwrap() .def_id; diff --git a/compiler/rustc_monomorphize/src/mono_checks/move_check.rs b/compiler/rustc_monomorphize/src/mono_checks/move_check.rs index 55d52d5075dc..7251ef478c6f 100644 --- a/compiler/rustc_monomorphize/src/mono_checks/move_check.rs +++ b/compiler/rustc_monomorphize/src/mono_checks/move_check.rs @@ -3,7 +3,7 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_hir::def_id::DefId; use rustc_middle::mir::visit::Visitor as MirVisitor; use rustc_middle::mir::{self, Location, traversal}; -use rustc_middle::ty::{self, AssocKind, Instance, Ty, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, AssocTag, Instance, Ty, TyCtxt, TypeFoldable}; use rustc_session::Limit; use rustc_session::lint::builtin::LARGE_ASSIGNMENTS; use rustc_span::source_map::Spanned; @@ -194,7 +194,7 @@ fn assoc_fn_of_type<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, fn_ident: Ident) -> if let Some(new) = tcx.associated_items(impl_def_id).find_by_ident_and_kind( tcx, fn_ident, - AssocKind::Fn, + AssocTag::Fn, def_id, ) { return Some(new.def_id); diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index c2761bd2717f..ae81021e0bea 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1994,7 +1994,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { .iter() .flat_map(|i| self.r.tcx.associated_items(i).in_definition_order()) // Only assoc fn with no receivers. - .filter(|item| matches!(item.kind, ty::AssocKind::Fn) && !item.fn_has_self_parameter) + .filter(|item| item.is_fn() && !item.is_method()) .filter_map(|item| { // Only assoc fns that return `Self` let fn_sig = self.r.tcx.fn_sig(item.def_id).skip_binder(); diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs index 129a32c6edd8..718b9a4fa3b8 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs @@ -446,7 +446,7 @@ pub(crate) fn transform_instance<'tcx>( let call = tcx .associated_items(trait_id) .in_definition_order() - .find(|it| it.kind == ty::AssocKind::Fn) + .find(|it| it.is_fn()) .expect("No call-family function on closure-like Fn trait?") .def_id; diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index 28fc68d5e491..94f3be9fef73 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -896,9 +896,9 @@ impl<'tcx> Stable<'tcx> for ty::AssocKind { fn stable(&self, _tables: &mut Tables<'_>) -> Self::T { use stable_mir::ty::AssocKind; - match self { + match *self { ty::AssocKind::Const => AssocKind::Const, - ty::AssocKind::Fn => AssocKind::Fn, + ty::AssocKind::Fn { has_self } => AssocKind::Fn { has_self }, ty::AssocKind::Type => AssocKind::Type, } } @@ -926,7 +926,6 @@ impl<'tcx> Stable<'tcx> for ty::AssocItem { kind: self.kind.stable(tables), container: self.container.stable(tables), trait_item_def_id: self.trait_item_def_id.map(|did| tables.assoc_def(did)), - fn_has_self_parameter: self.fn_has_self_parameter, opt_rpitit_info: self.opt_rpitit_info.map(|rpitit| rpitit.stable(tables)), } } diff --git a/compiler/rustc_smir/src/stable_mir/mir/pretty.rs b/compiler/rustc_smir/src/stable_mir/mir/pretty.rs index 439ebe978e59..60d9e122940b 100644 --- a/compiler/rustc_smir/src/stable_mir/mir/pretty.rs +++ b/compiler/rustc_smir/src/stable_mir/mir/pretty.rs @@ -22,7 +22,8 @@ impl Display for Ty { impl Display for AssocKind { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { - AssocKind::Fn => write!(f, "method"), + AssocKind::Fn { has_self: true } => write!(f, "method"), + AssocKind::Fn { has_self: false } => write!(f, "associated function"), AssocKind::Const => write!(f, "associated const"), AssocKind::Type => write!(f, "associated type"), } diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs index 3fcbbb0e138b..63ce756162a5 100644 --- a/compiler/rustc_smir/src/stable_mir/ty.rs +++ b/compiler/rustc_smir/src/stable_mir/ty.rs @@ -1586,10 +1586,6 @@ pub struct AssocItem { /// the associated item on the trait that this implements. pub trait_item_def_id: Option, - /// Whether this is a method with an explicit self - /// as its first parameter, allowing method calls. - pub fn_has_self_parameter: bool, - /// `Some` if the associated item (an associated type) comes from the /// return-position `impl Trait` in trait desugaring. The `ImplTraitInTraitData` /// provides additional information about its source. @@ -1599,7 +1595,7 @@ pub struct AssocItem { #[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub enum AssocKind { Const, - Fn, + Fn { has_self: bool }, Type, } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index 40f8af1f6913..cbadb46c17d9 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -2334,7 +2334,7 @@ impl<'tcx> ObligationCause<'tcx> { subdiags: Vec, ) -> ObligationCauseFailureCode { match self.code() { - ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Fn, .. } => { + ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Fn { .. }, .. } => { ObligationCauseFailureCode::MethodCompat { span, subdiags } } ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Type, .. } => { @@ -2398,7 +2398,7 @@ impl<'tcx> ObligationCause<'tcx> { fn as_requirement_str(&self) -> &'static str { match self.code() { - ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Fn, .. } => { + ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Fn { .. }, .. } => { "method type is compatible with trait" } ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Type, .. } => { @@ -2422,7 +2422,9 @@ pub struct ObligationCauseAsDiagArg<'tcx>(pub ObligationCause<'tcx>); impl IntoDiagArg for ObligationCauseAsDiagArg<'_> { fn into_diag_arg(self, _: &mut Option) -> rustc_errors::DiagArgValue { let kind = match self.0.code() { - ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Fn, .. } => "method_compat", + ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Fn { .. }, .. } => { + "method_compat" + } ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Type, .. } => "type_compat", ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Const, .. } => { "const_compat" diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs index 742059228510..b66bd2c6ab78 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs @@ -98,7 +98,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let assoc_item = self.tcx().associated_item(trait_item_def_id); let mut visitor = TypeParamSpanVisitor { tcx: self.tcx(), types: vec![] }; match assoc_item.kind { - ty::AssocKind::Fn => { + ty::AssocKind::Fn { .. } => { if let Some(hir_id) = assoc_item.def_id.as_local().map(|id| self.tcx().local_def_id_to_hir_id(id)) { diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs index fd2d2fa72105..4a71ab4e06a3 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs @@ -158,6 +158,6 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { && self .tcx() .opt_associated_item(scope_def_id.to_def_id()) - .is_some_and(|i| i.fn_has_self_parameter) + .is_some_and(|i| i.is_method()) } } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs index 5583deda99a4..02f21b5465c6 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs @@ -782,7 +782,7 @@ fn foo(&self) -> Self::T { String::new() } let methods: Vec<(Span, String)> = items .in_definition_order() .filter(|item| { - ty::AssocKind::Fn == item.kind + item.is_fn() && Some(item.name) != current_method_ident && !tcx.is_doc_hidden(item.def_id) }) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs index 59c93db9c8ff..e3e1583a48fa 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs @@ -349,7 +349,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { { let (verb, noun) = match self.tcx.associated_item(item_id).kind { ty::AssocKind::Const => ("refer to the", "constant"), - ty::AssocKind::Fn => ("call", "function"), + ty::AssocKind::Fn { .. } => ("call", "function"), // This is already covered by E0223, but this following single match // arm doesn't hurt here. ty::AssocKind::Type => ("refer to the", "type"), diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index b963e4a2c7c4..38aac8e70b52 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -5411,7 +5411,7 @@ fn point_at_assoc_type_restriction( tcx.associated_items(data.impl_or_alias_def_id).find_by_ident_and_kind( tcx, Ident::with_dummy_span(name), - ty::AssocKind::Type, + ty::AssocTag::Type, data.impl_or_alias_def_id, ) { diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index bf9fcb0915a5..76892db9ef7b 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -301,7 +301,7 @@ pub fn dyn_compatibility_violations_for_assoc_item( ty::AssocKind::Const => { vec![DynCompatibilityViolation::AssocConst(item.name, item.ident(tcx).span)] } - ty::AssocKind::Fn => virtual_call_violations_for_method(tcx, trait_def_id, item) + ty::AssocKind::Fn { .. } => virtual_call_violations_for_method(tcx, trait_def_id, item) .into_iter() .map(|v| { let node = tcx.hir_get_if_local(item.def_id); @@ -344,7 +344,7 @@ fn virtual_call_violations_for_method<'tcx>( let sig = tcx.fn_sig(method.def_id).instantiate_identity(); // The method's first parameter must be named `self` - if !method.fn_has_self_parameter { + if !method.is_method() { let sugg = if let Some(hir::Node::TraitItem(hir::TraitItem { generics, kind: hir::TraitItemKind::Fn(sig, _), diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs index 165174c0bcc1..3565c11249ad 100644 --- a/compiler/rustc_trait_selection/src/traits/vtable.rs +++ b/compiler/rustc_trait_selection/src/traits/vtable.rs @@ -197,10 +197,8 @@ fn own_existential_vtable_entries_iter( tcx: TyCtxt<'_>, trait_def_id: DefId, ) -> impl Iterator { - let trait_methods = tcx - .associated_items(trait_def_id) - .in_definition_order() - .filter(|item| item.kind == ty::AssocKind::Fn); + let trait_methods = + tcx.associated_items(trait_def_id).in_definition_order().filter(|item| item.is_fn()); // Now list each method's DefId (for within its trait). let own_entries = trait_methods.filter_map(move |&trait_method| { diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index 9520d948f51f..79de071b6878 100644 --- a/compiler/rustc_ty_utils/src/assoc.rs +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -129,10 +129,10 @@ fn associated_item(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AssocItem { fn associated_item_from_trait_item_ref(trait_item_ref: &hir::TraitItemRef) -> ty::AssocItem { let owner_id = trait_item_ref.id.owner_id; - let (kind, has_self) = match trait_item_ref.kind { - hir::AssocItemKind::Const => (ty::AssocKind::Const, false), - hir::AssocItemKind::Fn { has_self } => (ty::AssocKind::Fn, has_self), - hir::AssocItemKind::Type => (ty::AssocKind::Type, false), + let kind = match trait_item_ref.kind { + hir::AssocItemKind::Const => ty::AssocKind::Const, + hir::AssocItemKind::Fn { has_self } => ty::AssocKind::Fn { has_self }, + hir::AssocItemKind::Type => ty::AssocKind::Type, }; ty::AssocItem { @@ -141,17 +141,16 @@ fn associated_item_from_trait_item_ref(trait_item_ref: &hir::TraitItemRef) -> ty def_id: owner_id.to_def_id(), trait_item_def_id: Some(owner_id.to_def_id()), container: ty::AssocItemContainer::Trait, - fn_has_self_parameter: has_self, opt_rpitit_info: None, } } fn associated_item_from_impl_item_ref(impl_item_ref: &hir::ImplItemRef) -> ty::AssocItem { let def_id = impl_item_ref.id.owner_id; - let (kind, has_self) = match impl_item_ref.kind { - hir::AssocItemKind::Const => (ty::AssocKind::Const, false), - hir::AssocItemKind::Fn { has_self } => (ty::AssocKind::Fn, has_self), - hir::AssocItemKind::Type => (ty::AssocKind::Type, false), + let kind = match impl_item_ref.kind { + hir::AssocItemKind::Const => ty::AssocKind::Const, + hir::AssocItemKind::Fn { has_self } => ty::AssocKind::Fn { has_self }, + hir::AssocItemKind::Type => ty::AssocKind::Type, }; ty::AssocItem { @@ -160,7 +159,6 @@ fn associated_item_from_impl_item_ref(impl_item_ref: &hir::ImplItemRef) -> ty::A def_id: def_id.to_def_id(), trait_item_def_id: impl_item_ref.trait_item_def_id, container: ty::AssocItemContainer::Impl, - fn_has_self_parameter: has_self, opt_rpitit_info: None, } } @@ -269,7 +267,6 @@ fn associated_type_for_impl_trait_in_trait( def_id, trait_item_def_id: None, container: ty::AssocItemContainer::Trait, - fn_has_self_parameter: false, opt_rpitit_info: Some(ImplTraitInTraitData::Trait { fn_def_id: fn_def_id.to_def_id(), opaque_def_id: opaque_ty_def_id.to_def_id(), @@ -322,7 +319,6 @@ fn associated_type_for_impl_trait_in_impl( def_id, trait_item_def_id: Some(trait_assoc_def_id), container: ty::AssocItemContainer::Impl, - fn_has_self_parameter: false, opt_rpitit_info: Some(ImplTraitInTraitData::Impl { fn_def_id: impl_fn_def_id.to_def_id() }), }); diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 3a2b6974681b..2f6870e3c368 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -490,17 +490,17 @@ pub(crate) fn build_impl( return true; } if let Some(associated_trait) = associated_trait { - let assoc_kind = match item.kind { - hir::ImplItemKind::Const(..) => ty::AssocKind::Const, - hir::ImplItemKind::Fn(..) => ty::AssocKind::Fn, - hir::ImplItemKind::Type(..) => ty::AssocKind::Type, + let assoc_tag = match item.kind { + hir::ImplItemKind::Const(..) => ty::AssocTag::Const, + hir::ImplItemKind::Fn(..) => ty::AssocTag::Fn, + hir::ImplItemKind::Type(..) => ty::AssocTag::Type, }; let trait_item = tcx .associated_items(associated_trait.def_id) .find_by_ident_and_kind( tcx, item.ident, - assoc_kind, + assoc_tag, associated_trait.def_id, ) .unwrap(); // SAFETY: For all impl items there exists trait item that has the same name. @@ -527,7 +527,7 @@ pub(crate) fn build_impl( .find_by_ident_and_kind( tcx, item.ident(tcx), - item.kind, + item.as_tag(), associated_trait.def_id, ) .unwrap(); // corresponding associated item has to exist diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 45a915719e9f..7cfd204aa137 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1374,10 +1374,10 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo } } } - ty::AssocKind::Fn => { + ty::AssocKind::Fn { has_self } => { let mut item = inline::build_function(cx, assoc_item.def_id); - if assoc_item.fn_has_self_parameter { + if has_self { let self_ty = match assoc_item.container { ty::AssocItemContainer::Impl => { tcx.type_of(assoc_item.container_id(tcx)).instantiate_identity() diff --git a/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs b/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs index ad18c7039eed..4a876b854165 100644 --- a/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs +++ b/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs @@ -56,7 +56,7 @@ fn is_impl_not_trait_with_bool_out<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) - cx.tcx.associated_items(trait_id).find_by_ident_and_kind( cx.tcx, Ident::from_str("Output"), - ty::AssocKind::Type, + ty::AssocTag::Type, trait_id, ) }) diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs index b01929747d69..77085d52a32e 100644 --- a/src/tools/clippy/clippy_lints/src/len_zero.rs +++ b/src/tools/clippy/clippy_lints/src/len_zero.rs @@ -13,7 +13,7 @@ use rustc_hir::{ QPath, TraitItemRef, TyKind, }; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::{self, AssocKind, FnSig, Ty}; +use rustc_middle::ty::{self, FnSig, Ty}; use rustc_session::declare_lint_pass; use rustc_span::source_map::Spanned; use rustc_span::symbol::sym; @@ -288,8 +288,7 @@ fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, ident: Iden .items() .flat_map(|&i| cx.tcx.associated_items(i).filter_by_name_unhygienic(is_empty)) .any(|i| { - i.kind == AssocKind::Fn - && i.fn_has_self_parameter + i.is_method() && cx.tcx.fn_sig(i.def_id).skip_binder().inputs().skip_binder().len() == 1 }); @@ -466,7 +465,7 @@ fn check_for_is_empty( .inherent_impls(impl_ty) .iter() .flat_map(|&id| cx.tcx.associated_items(id).filter_by_name_unhygienic(is_empty)) - .find(|item| item.kind == AssocKind::Fn); + .find(|item| item.is_fn()); let (msg, is_empty_span, self_kind) = match is_empty { None => ( @@ -486,7 +485,7 @@ fn check_for_is_empty( None, ), Some(is_empty) - if !(is_empty.fn_has_self_parameter + if !(is_empty.is_method() && check_is_empty_sig( cx, cx.tcx.fn_sig(is_empty.def_id).instantiate_identity().skip_binder(), @@ -608,7 +607,7 @@ fn is_empty_array(expr: &Expr<'_>) -> bool { fn has_is_empty(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { /// Gets an `AssocItem` and return true if it matches `is_empty(self)`. fn is_is_empty(cx: &LateContext<'_>, item: &ty::AssocItem) -> bool { - if item.kind == AssocKind::Fn { + if item.is_fn() { let sig = cx.tcx.fn_sig(item.def_id).skip_binder(); let ty = sig.skip_binder(); ty.inputs().len() == 1 diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs index 239ee6c729fb..e4a29b6560e5 100644 --- a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs @@ -17,7 +17,7 @@ use rustc_hir::{ }; use rustc_lint::LateContext; use rustc_middle::hir::nested_filter; -use rustc_middle::ty::{self, AssocKind, ClauseKind, EarlyBinder, GenericArg, GenericArgKind, Ty}; +use rustc_middle::ty::{self, AssocTag, ClauseKind, EarlyBinder, GenericArg, GenericArgKind, Ty}; use rustc_span::symbol::Ident; use rustc_span::{Span, sym}; @@ -241,7 +241,7 @@ fn is_contains_sig(cx: &LateContext<'_>, call_id: HirId, iter_expr: &Expr<'_>) - && let Some(iter_item) = cx.tcx.associated_items(iter_trait).find_by_ident_and_kind( cx.tcx, Ident::with_dummy_span(sym::Item), - AssocKind::Type, + AssocTag::Type, iter_trait, ) && let args = cx.tcx.mk_args(&[GenericArg::from(typeck.expr_ty_adjusted(iter_expr))]) diff --git a/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs b/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs index c03420a5143e..6eeeea5d77c7 100644 --- a/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs +++ b/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs @@ -78,7 +78,7 @@ pub(super) fn check<'tcx>( .iter() .flat_map(|impl_id| cx.tcx.associated_items(impl_id).filter_by_name_unhygienic(sugg)) .find_map(|assoc| { - if assoc.fn_has_self_parameter + if assoc.is_method() && cx.tcx.fn_sig(assoc.def_id).skip_binder().inputs().skip_binder().len() == 1 { Some(assoc.def_id) diff --git a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs index f686cc912ddb..e579dd5947d7 100644 --- a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs +++ b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs @@ -299,7 +299,7 @@ fn has_ref_mut_self_method(cx: &LateContext<'_>, trait_def_id: DefId) -> bool { .associated_items(trait_def_id) .in_definition_order() .any(|assoc_item| { - if assoc_item.fn_has_self_parameter { + if assoc_item.is_method() { let self_ty = cx .tcx .fn_sig(assoc_item.def_id) diff --git a/src/tools/clippy/clippy_lints/src/same_name_method.rs b/src/tools/clippy/clippy_lints/src/same_name_method.rs index 552135b15fd8..ae677e110af2 100644 --- a/src/tools/clippy/clippy_lints/src/same_name_method.rs +++ b/src/tools/clippy/clippy_lints/src/same_name_method.rs @@ -3,7 +3,6 @@ use rustc_data_structures::fx::FxHashMap; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{HirId, Impl, ItemKind, Node, Path, QPath, TraitRef, TyKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::AssocKind; use rustc_session::declare_lint_pass; use rustc_span::Span; use rustc_span::symbol::Symbol; @@ -85,7 +84,7 @@ impl<'tcx> LateLintPass<'tcx> for SameNameMethod { cx.tcx .associated_items(did) .in_definition_order() - .filter(|assoc_item| matches!(assoc_item.kind, AssocKind::Fn)) + .filter(|assoc_item| assoc_item.is_fn()) .map(|assoc_item| assoc_item.name) .collect() } else { diff --git a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs index 51c7d6fce312..2104eb302ab8 100644 --- a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs +++ b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs @@ -10,7 +10,7 @@ use rustc_hir::{Body, Expr, ExprKind, FnDecl, HirId, Item, ItemKind, Node, QPath use rustc_hir_analysis::lower_ty; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; -use rustc_middle::ty::{self, AssocKind, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_session::impl_lint_pass; use rustc_span::symbol::{Ident, kw}; use rustc_span::{Span, sym}; @@ -322,7 +322,7 @@ impl UnconditionalRecursion { .in_definition_order() // We're not interested in foreign implementations of the `Default` trait. .find(|item| { - item.kind == AssocKind::Fn && item.def_id.is_local() && item.name == kw::Default + item.is_fn() && item.def_id.is_local() && item.name == kw::Default }) && let Some(body_node) = cx.tcx.hir_get_if_local(assoc_item.def_id) && let Some(body_id) = body_node.body_id() diff --git a/src/tools/clippy/clippy_lints/src/unused_self.rs b/src/tools/clippy/clippy_lints/src/unused_self.rs index 582aa6e6001e..d0067b1a65e7 100644 --- a/src/tools/clippy/clippy_lints/src/unused_self.rs +++ b/src/tools/clippy/clippy_lints/src/unused_self.rs @@ -74,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedSelf { .is_some() }; if let ItemKind::Impl(Impl { of_trait: None, .. }) = parent_item.kind - && assoc_item.fn_has_self_parameter + && assoc_item.is_method() && let ImplItemKind::Fn(.., body_id) = &impl_item.kind && (!cx.effective_visibilities.is_exported(impl_item.owner_id.def_id) || !self.avoid_breaking_exported_api) && let body = cx.tcx.hir_body(*body_id) diff --git a/src/tools/clippy/clippy_utils/src/ty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/mod.rs index 3779e2f30623..d33e59342a59 100644 --- a/src/tools/clippy/clippy_utils/src/ty/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ty/mod.rs @@ -19,7 +19,7 @@ use rustc_middle::mir::interpret::Scalar; use rustc_middle::traits::EvaluationResult; use rustc_middle::ty::layout::ValidityRequirement; use rustc_middle::ty::{ - self, AdtDef, AliasTy, AssocItem, AssocKind, Binder, BoundRegion, FnSig, GenericArg, GenericArgKind, + self, AdtDef, AliasTy, AssocItem, AssocTag, Binder, BoundRegion, FnSig, GenericArg, GenericArgKind, GenericArgsRef, GenericParamDefKind, IntTy, ParamEnv, Region, RegionKind, TraitRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, UintTy, Upcast, VariantDef, VariantDiscr, }; @@ -1112,7 +1112,7 @@ pub fn make_projection<'tcx>( let Some(assoc_item) = tcx.associated_items(container_id).find_by_ident_and_kind( tcx, Ident::with_dummy_span(assoc_ty), - AssocKind::Type, + AssocTag::Type, container_id, ) else { debug_assert!(false, "type `{assoc_ty}` not found in `{container_id:?}`"); @@ -1345,7 +1345,7 @@ pub fn get_adt_inherent_method<'a>(cx: &'a LateContext<'_>, ty: Ty<'_>, method_n .associated_items(did) .filter_by_name_unhygienic(method_name) .next() - .filter(|item| item.kind == AssocKind::Fn) + .filter(|item| item.as_tag() == AssocTag::Fn) }) } else { None diff --git a/tests/ui/generic-associated-types/impl_bounds.stderr b/tests/ui/generic-associated-types/impl_bounds.stderr index 231c0dd89c52..7847bbd813cd 100644 --- a/tests/ui/generic-associated-types/impl_bounds.stderr +++ b/tests/ui/generic-associated-types/impl_bounds.stderr @@ -57,14 +57,14 @@ note: required for `Fooy` to implement `Copy` | LL | #[derive(Copy, Clone)] | ^^^^ unsatisfied trait bound introduced in this `derive` macro -note: the requirement `Fooy: Copy` appears on the `impl`'s method `d` but not on the corresponding trait's method +note: the requirement `Fooy: Copy` appears on the `impl`'s associated function `d` but not on the corresponding trait's associated function --> $DIR/impl_bounds.rs:7:8 | LL | trait Foo { | --- in this trait ... LL | fn d() where Self: Clone; - | ^ this trait's method doesn't have the requirement `Fooy: Copy` + | ^ this trait's associated function doesn't have the requirement `Fooy: Copy` help: consider restricting type parameter `T` with trait `Copy` | LL | impl Foo for Fooy { diff --git a/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr b/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr index 74a0a90885da..d179c8059623 100644 --- a/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr +++ b/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr @@ -4,14 +4,14 @@ error[E0275]: overflow evaluating the requirement `<() as A>::Assoc: A` LL | Self::Assoc: A, | ^^^^ | -note: the requirement `<() as A>::Assoc: A` appears on the `impl`'s method `f` but not on the corresponding trait's method +note: the requirement `<() as A>::Assoc: A` appears on the `impl`'s associated function `f` but not on the corresponding trait's associated function --> $DIR/normalize-param-env-2.rs:12:8 | LL | trait A { | - in this trait ... LL | fn f() - | ^ this trait's method doesn't have the requirement `<() as A>::Assoc: A` + | ^ this trait's associated function doesn't have the requirement `<() as A>::Assoc: A` error[E0275]: overflow evaluating the requirement `<() as A>::Assoc: A` --> $DIR/normalize-param-env-2.rs:24:22 From 8c8212ef12b13ccb635c81aa9e29915dd1c189e5 Mon Sep 17 00:00:00 2001 From: xizheyin Date: Mon, 14 Apr 2025 14:29:14 +0800 Subject: [PATCH 430/606] Consistent with treating Ctor Call as Struct in liveness analysis Signed-off-by: xizheyin --- compiler/rustc_passes/src/liveness.rs | 5 ++- ...eachable-by-call-arguments-issue-139627.rs | 7 ++-- ...able-by-call-arguments-issue-139627.stderr | 36 ------------------- 3 files changed, 8 insertions(+), 40 deletions(-) delete mode 100644 tests/ui/reachable/unreachable-by-call-arguments-issue-139627.stderr diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index 06eb76c30c5f..24fac1999111 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -1021,7 +1021,10 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } hir::ExprKind::Call(ref f, args) => { - let succ = self.check_is_ty_uninhabited(expr, succ); + let is_ctor = |f: &Expr<'_>| matches!(f.kind, hir::ExprKind::Path(hir::QPath::Resolved(_, path)) if matches!(path.res, rustc_hir::def::Res::Def(rustc_hir::def::DefKind::Ctor(_, _), _))); + let succ = + if !is_ctor(f) { self.check_is_ty_uninhabited(expr, succ) } else { succ }; + let succ = self.propagate_through_exprs(args, succ); self.propagate_through_expr(f, succ) } diff --git a/tests/ui/reachable/unreachable-by-call-arguments-issue-139627.rs b/tests/ui/reachable/unreachable-by-call-arguments-issue-139627.rs index 422ae95e8b72..b3310ac1c754 100644 --- a/tests/ui/reachable/unreachable-by-call-arguments-issue-139627.rs +++ b/tests/ui/reachable/unreachable-by-call-arguments-issue-139627.rs @@ -1,3 +1,4 @@ +//@ check-pass #![deny(unreachable_code)] #![deny(unused)] @@ -5,9 +6,9 @@ pub enum Void {} pub struct S(T); -pub fn foo(void: Void, void1: Void) { //~ ERROR unused variable: `void1` - let s = S(void); //~ ERROR unused variable: `s` - drop(s); //~ ERROR unreachable expression +pub fn foo(void: Void, void1: Void) { + let s = S(void); + drop(s); let s1 = S { 0: void1 }; drop(s1); } diff --git a/tests/ui/reachable/unreachable-by-call-arguments-issue-139627.stderr b/tests/ui/reachable/unreachable-by-call-arguments-issue-139627.stderr deleted file mode 100644 index ce24705324e5..000000000000 --- a/tests/ui/reachable/unreachable-by-call-arguments-issue-139627.stderr +++ /dev/null @@ -1,36 +0,0 @@ -error: unreachable expression - --> $DIR/unreachable-by-call-arguments-issue-139627.rs:10:10 - | -LL | let s = S(void); - | ------- any code following this expression is unreachable -LL | drop(s); - | ^ unreachable expression - | -note: this expression has type `S`, which is uninhabited - --> $DIR/unreachable-by-call-arguments-issue-139627.rs:9:13 - | -LL | let s = S(void); - | ^^^^^^^ -note: the lint level is defined here - --> $DIR/unreachable-by-call-arguments-issue-139627.rs:2:9 - | -LL | #![deny(unused)] - | ^^^^^^ - = note: `#[deny(unreachable_code)]` implied by `#[deny(unused)]` - -error: unused variable: `s` - --> $DIR/unreachable-by-call-arguments-issue-139627.rs:9:9 - | -LL | let s = S(void); - | ^ help: if this is intentional, prefix it with an underscore: `_s` - | - = note: `#[deny(unused_variables)]` implied by `#[deny(unused)]` - -error: unused variable: `void1` - --> $DIR/unreachable-by-call-arguments-issue-139627.rs:8:24 - | -LL | pub fn foo(void: Void, void1: Void) { - | ^^^^^ help: if this is intentional, prefix it with an underscore: `_void1` - -error: aborting due to 3 previous errors - From f3344ef4bd57ac7609b40f1da75d685032e965f1 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Mon, 14 Apr 2025 15:28:41 +0800 Subject: [PATCH 431/606] tests: use `compiletest-ignore-dir` for bootstrap self-tests --- tests/ui/bootstrap/self-test/a.rs | 1 - tests/ui/bootstrap/self-test/b.rs | 1 - tests/ui/bootstrap/self-test/compiletest-ignore-dir | 0 3 files changed, 2 deletions(-) create mode 100644 tests/ui/bootstrap/self-test/compiletest-ignore-dir diff --git a/tests/ui/bootstrap/self-test/a.rs b/tests/ui/bootstrap/self-test/a.rs index b8abd8179c91..0818665af9f2 100644 --- a/tests/ui/bootstrap/self-test/a.rs +++ b/tests/ui/bootstrap/self-test/a.rs @@ -1,2 +1 @@ //! Not used by compiler, this is used by bootstrap cli self-test. -//@ ignore-test (used by bootstrap) diff --git a/tests/ui/bootstrap/self-test/b.rs b/tests/ui/bootstrap/self-test/b.rs index 5bbd2f946feb..aeb4688830db 100644 --- a/tests/ui/bootstrap/self-test/b.rs +++ b/tests/ui/bootstrap/self-test/b.rs @@ -1,2 +1 @@ //! Not used by compiler, used by bootstrap cli self-test. -//@ ignore-test (used by bootstrap) diff --git a/tests/ui/bootstrap/self-test/compiletest-ignore-dir b/tests/ui/bootstrap/self-test/compiletest-ignore-dir new file mode 100644 index 000000000000..e69de29bb2d1 From 1ac3d6bba71fce59939e6a4d50de98e289e87b9b Mon Sep 17 00:00:00 2001 From: "Eddy (Eduard) Stefes" Date: Mon, 14 Apr 2025 09:49:43 +0200 Subject: [PATCH 432/606] Let CStrings be either 1 or 2 byte aligned. Some architectures (like s390x) require strings to be 2 byte aligned. Therefor the section name will be marked with a .2 postfix on this architectures. Allowing a section name with a .1 or .2 postfix will make the test pass on either platform. --- tests/assembly/cstring-merging.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/assembly/cstring-merging.rs b/tests/assembly/cstring-merging.rs index 07f25d1e1a42..b5c530ac35d7 100644 --- a/tests/assembly/cstring-merging.rs +++ b/tests/assembly/cstring-merging.rs @@ -5,7 +5,7 @@ use std::ffi::CStr; -// CHECK: .section .rodata.str1.1,"aMS" +// CHECK: .section .rodata.str1.{{[12]}},"aMS" // CHECK: .Lanon.{{.+}}: // CHECK-NEXT: .asciz "foo" #[unsafe(no_mangle)] From 6a8718cab772ecfbce3de7a701e9abf8e476bc37 Mon Sep 17 00:00:00 2001 From: reddevilmidzy Date: Mon, 14 Apr 2025 11:06:46 +0900 Subject: [PATCH 433/606] Add test for issue 34834 --- .../associated_type_bound/hrtb-associated.rs | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 tests/ui/traits/associated_type_bound/hrtb-associated.rs diff --git a/tests/ui/traits/associated_type_bound/hrtb-associated.rs b/tests/ui/traits/associated_type_bound/hrtb-associated.rs new file mode 100644 index 000000000000..59e5a09c0cbb --- /dev/null +++ b/tests/ui/traits/associated_type_bound/hrtb-associated.rs @@ -0,0 +1,30 @@ +//@ check-pass +//! This test ensures that HRTB (higher-ranked trait bounds) on associated types +//! compile correctly. This was previously rejected by the compiler. +//! Related issue: + +pub trait Provides<'a> { + type Item; +} + +pub trait Selector: for<'a> Provides<'a> { + type Namespace: PartialEq + for<'a> PartialEq<>::Item>; + + fn get_namespace(&self) -> ::Item; +} + +pub struct MySelector; + +impl<'a> Provides<'a> for MySelector { + type Item = &'a str; +} + +impl Selector for MySelector { + type Namespace = String; + + fn get_namespace(&self) -> &str { + unimplemented!() + } +} + +fn main() {} From 2c2c9df653079893c34dc9ef72201fdab3a67abc Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 14 Apr 2025 12:43:16 +0200 Subject: [PATCH 434/606] drop global where-bounds before merging candidates --- .../src/solve/trait_goals.rs | 8 +++-- .../cycles/inductive-cycle-but-err.rs | 8 +++++ .../cycles/inductive-cycle-but-err.stderr | 21 +++++++++--- ...global-where-bound-region-constraints-2.rs | 33 +++++++++++++++++++ .../global-where-bound-region-constraints.rs | 29 ++++++++++++++++ 5 files changed, 93 insertions(+), 6 deletions(-) create mode 100644 tests/ui/traits/winnowing/global-where-bound-region-constraints-2.rs create mode 100644 tests/ui/traits/winnowing/global-where-bound-region-constraints.rs diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index d42c9980f463..b96ffcbc7957 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -1238,10 +1238,11 @@ where D: SolverDelegate, I: Interner, { + #[instrument(level = "debug", skip(self, goal), ret)] pub(super) fn merge_trait_candidates( &mut self, goal: Goal>, - candidates: Vec>, + mut candidates: Vec>, ) -> Result<(CanonicalResponse, Option), NoSolution> { if let TypingMode::Coherence = self.typing_mode() { let all_candidates: Vec<_> = candidates.into_iter().map(|c| c.result).collect(); @@ -1323,13 +1324,16 @@ where // If there are *only* global where bounds, then make sure to return that this // is still reported as being proven-via the param-env so that rigid projections - // operate correctly. + // operate correctly. Otherwise, drop all global where-bounds before merging the + // remaining candidates. let proven_via = if candidates.iter().all(|c| matches!(c.source, CandidateSource::ParamEnv(_))) { TraitGoalProvenVia::ParamEnv } else { + candidates.retain(|c| !matches!(c.source, CandidateSource::ParamEnv(_))); TraitGoalProvenVia::Misc }; + let all_candidates: Vec<_> = candidates.into_iter().map(|c| c.result).collect(); if let Some(response) = self.try_merge_responses(&all_candidates) { Ok((response, Some(proven_via))) diff --git a/tests/ui/traits/next-solver/cycles/inductive-cycle-but-err.rs b/tests/ui/traits/next-solver/cycles/inductive-cycle-but-err.rs index b0c778e7f574..754fc872e457 100644 --- a/tests/ui/traits/next-solver/cycles/inductive-cycle-but-err.rs +++ b/tests/ui/traits/next-solver/cycles/inductive-cycle-but-err.rs @@ -34,9 +34,17 @@ where MultipleNested: Trait, {} +// We ignore the trivially true global where-bounds when checking that this +// impl is well-formed, meaning that we depend on `MultipleNested: Trait` when +// recursively proving `MultipleCandidates: Trait`. +// +// These overflow errors will disappear once we treat these cycles as either +// productive or an error. impl Trait for MultipleNested +//~^ ERROR overflow evaluating the requirement `MultipleNested: Trait` where MultipleCandidates: Trait, + //~^ ERROR overflow evaluating the requirement `MultipleCandidates: Trait` DoesNotImpl: Trait, {} diff --git a/tests/ui/traits/next-solver/cycles/inductive-cycle-but-err.stderr b/tests/ui/traits/next-solver/cycles/inductive-cycle-but-err.stderr index acacaf6a331d..7895a2636345 100644 --- a/tests/ui/traits/next-solver/cycles/inductive-cycle-but-err.stderr +++ b/tests/ui/traits/next-solver/cycles/inductive-cycle-but-err.stderr @@ -1,16 +1,29 @@ +error[E0275]: overflow evaluating the requirement `MultipleNested: Trait` + --> $DIR/inductive-cycle-but-err.rs:43:16 + | +LL | impl Trait for MultipleNested + | ^^^^^^^^^^^^^^ + +error[E0275]: overflow evaluating the requirement `MultipleCandidates: Trait` + --> $DIR/inductive-cycle-but-err.rs:46:25 + | +LL | MultipleCandidates: Trait, + | ^^^^^ + error[E0277]: the trait bound `MultipleCandidates: Trait` is not satisfied - --> $DIR/inductive-cycle-but-err.rs:46:19 + --> $DIR/inductive-cycle-but-err.rs:54:19 | LL | impls_trait::(); | ^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `MultipleCandidates` | = help: the trait `Trait` is implemented for `MultipleCandidates` note: required by a bound in `impls_trait` - --> $DIR/inductive-cycle-but-err.rs:43:19 + --> $DIR/inductive-cycle-but-err.rs:51:19 | LL | fn impls_trait() {} | ^^^^^ required by this bound in `impls_trait` -error: aborting due to 1 previous error +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0275, E0277. +For more information about an error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/winnowing/global-where-bound-region-constraints-2.rs b/tests/ui/traits/winnowing/global-where-bound-region-constraints-2.rs new file mode 100644 index 000000000000..d422605a2923 --- /dev/null +++ b/tests/ui/traits/winnowing/global-where-bound-region-constraints-2.rs @@ -0,0 +1,33 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@ check-pass + +// Regression test for trait-system-refactor-initiative#172. +// +// In this test the global where-bound simply constrains the +// object lifetime bound to 'static while the builtin impl +// ends up also emitting a `dyn Any: 'static` type outlives +// constraint. This previously resulted in ambiguity. We now +// always prefer the impl. + +pub trait Any: 'static {} + +pub trait Downcast: Any +where + T: Any, +{ +} + +// elided object lifetime: `dyn Any + 'static` +impl dyn Any { + pub fn is(&self) + where + T: Any, + // elaboration adds global where-clause `dyn Any + 'static: Any` + Self: Downcast, + { + } +} + +fn main() {} diff --git a/tests/ui/traits/winnowing/global-where-bound-region-constraints.rs b/tests/ui/traits/winnowing/global-where-bound-region-constraints.rs new file mode 100644 index 000000000000..3bc8b0438bf8 --- /dev/null +++ b/tests/ui/traits/winnowing/global-where-bound-region-constraints.rs @@ -0,0 +1,29 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@ check-pass + +// Regression test for trait-system-refactor-initiative#172. +// +// The next-generation trait solver previously simply tried +// to merge the global where-bounds with the impl candidates. +// This caused ambiguity in case the where-bound had stricter +// region requirements than the impl. + +trait Trait {} +struct Foo<'a, 'b>(&'a (), &'b ()); +impl<'a> Trait for Foo<'a, 'static> {} + +fn impls_trait() {} +fn foo() +where + Foo<'static, 'static>: Trait, +{ + // impl requires `'1 to be 'static + // global where-bound requires both '0 and '1 to be 'static + // + // we always prefer the impl here. + impls_trait::>(); +} + +fn main() {} From ce9d8678ca9d25c603dfc655a5f955bee4a0a9fe Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 14 Apr 2025 10:37:51 +0200 Subject: [PATCH 435/606] do not leak auto traits in item bounds --- .../src/solve/trait_goals.rs | 32 ++++++++++++++---- .../avoid-query-cycle-via-item-bound.rs | 33 +++++++++++++++++++ tests/ui/impl-trait/in-trait/refine-cycle.rs | 3 ++ 3 files changed, 61 insertions(+), 7 deletions(-) create mode 100644 tests/ui/impl-trait/auto-trait-leakage/avoid-query-cycle-via-item-bound.rs diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index d42c9980f463..3adfac3d4292 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -164,6 +164,7 @@ where ecx: &mut EvalCtxt<'_, D>, goal: Goal, ) -> Result, NoSolution> { + let cx = ecx.cx(); if goal.predicate.polarity != ty::PredicatePolarity::Positive { return Err(NoSolution); } @@ -174,20 +175,37 @@ where // Only consider auto impls of unsafe traits when there are no unsafe // fields. - if ecx.cx().trait_is_unsafe(goal.predicate.def_id()) + if cx.trait_is_unsafe(goal.predicate.def_id()) && goal.predicate.self_ty().has_unsafe_fields() { return Err(NoSolution); } - // We only look into opaque types during analysis for opaque types - // outside of their defining scope. Doing so for opaques in the - // defining scope may require calling `typeck` on the same item we're - // currently type checking, which will result in a fatal cycle that - // ideally we want to avoid, since we can make progress on this goal - // via an alias bound or a locally-inferred hidden type instead. + // We leak the implemented auto traits of opaques outside of their defining scope. + // This depends on `typeck` of the defining scope of that opaque, which may result in + // fatal query cycles. + // + // We only get to this point if we're outside of the defining scope as we'd otherwise + // be able to normalize the opaque type. We may also cycle in case `typeck` of a defining + // scope relies on the current context, e.g. either because it also leaks auto trait + // bounds of opaques defined in the current context or by evaluating the current item. + // + // To avoid this we don't try to leak auto trait bounds if they can also be proven via + // item bounds of the opaque. These bounds are always applicable as auto traits must not + // have any generic parameters. They would also get preferred over the impl candidate + // when merging candidates anyways. + // + // See tests/ui/impl-trait/auto-trait-leakage/avoid-query-cycle-via-item-bound.rs. if let ty::Alias(ty::Opaque, opaque_ty) = goal.predicate.self_ty().kind() { debug_assert!(ecx.opaque_type_is_rigid(opaque_ty.def_id)); + for item_bound in cx.item_self_bounds(opaque_ty.def_id).skip_binder() { + if item_bound + .as_trait_clause() + .is_some_and(|b| b.def_id() == goal.predicate.def_id()) + { + return Err(NoSolution); + } + } } ecx.probe_and_evaluate_goal_for_constituent_tys( diff --git a/tests/ui/impl-trait/auto-trait-leakage/avoid-query-cycle-via-item-bound.rs b/tests/ui/impl-trait/auto-trait-leakage/avoid-query-cycle-via-item-bound.rs new file mode 100644 index 000000000000..7f366fdcabd2 --- /dev/null +++ b/tests/ui/impl-trait/auto-trait-leakage/avoid-query-cycle-via-item-bound.rs @@ -0,0 +1,33 @@ +//@ check-pass +//@ revisions: current next +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) + +// When proving auto trait bounds, make sure that we depend on auto trait +// leakage if we can also prove it via an item bound. +fn is_send(_: T) {} + +fn direct() -> impl Send { + is_send(check(false)); // leaks auto traits, depends on `check` + 1u16 +} + +trait Indir: Send {} +impl Indir for u32 {} +fn indir() -> impl Indir { + is_send(check(false)); // leaks auto traits, depends on `check` + 1u32 +} + +fn check(b: bool) -> impl Sized { + if b { + // must not leak auto traits, as we otherwise get a query cycle. + is_send(direct()); + is_send(indir()); + } + 1u64 +} + +fn main() { + check(true); +} diff --git a/tests/ui/impl-trait/in-trait/refine-cycle.rs b/tests/ui/impl-trait/in-trait/refine-cycle.rs index 78d672a7ed60..d97f9821347e 100644 --- a/tests/ui/impl-trait/in-trait/refine-cycle.rs +++ b/tests/ui/impl-trait/in-trait/refine-cycle.rs @@ -1,4 +1,7 @@ //@ check-pass +//@ revisions: current next +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) // Make sure that refinement checking doesn't cause a cycle in `Instance::resolve` // which calls `compare_impl_item`. From 2e79f7cd6102ac7faa4938f61f056e26b08249a9 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 14 Apr 2025 10:38:16 +0200 Subject: [PATCH 436/606] move tests --- .../impl-trait/{ => auto-trait-leakage}/auto-trait-coherence.rs | 0 .../{ => auto-trait-leakage}/auto-trait-coherence.stderr | 0 .../{ => auto-trait-leakage}/auto-trait-contains-err.rs | 0 .../{ => auto-trait-leakage}/auto-trait-contains-err.stderr | 0 .../impl-trait/{ => auto-trait-leakage}/auto-trait-leak-rpass.rs | 0 tests/ui/impl-trait/{ => auto-trait-leakage}/auto-trait-leak.rs | 0 .../ui/impl-trait/{ => auto-trait-leakage}/auto-trait-leak.stderr | 0 tests/ui/impl-trait/{ => auto-trait-leakage}/auto-trait-leak2.rs | 0 .../impl-trait/{ => auto-trait-leakage}/auto-trait-leak2.stderr | 0 9 files changed, 0 insertions(+), 0 deletions(-) rename tests/ui/impl-trait/{ => auto-trait-leakage}/auto-trait-coherence.rs (100%) rename tests/ui/impl-trait/{ => auto-trait-leakage}/auto-trait-coherence.stderr (100%) rename tests/ui/impl-trait/{ => auto-trait-leakage}/auto-trait-contains-err.rs (100%) rename tests/ui/impl-trait/{ => auto-trait-leakage}/auto-trait-contains-err.stderr (100%) rename tests/ui/impl-trait/{ => auto-trait-leakage}/auto-trait-leak-rpass.rs (100%) rename tests/ui/impl-trait/{ => auto-trait-leakage}/auto-trait-leak.rs (100%) rename tests/ui/impl-trait/{ => auto-trait-leakage}/auto-trait-leak.stderr (100%) rename tests/ui/impl-trait/{ => auto-trait-leakage}/auto-trait-leak2.rs (100%) rename tests/ui/impl-trait/{ => auto-trait-leakage}/auto-trait-leak2.stderr (100%) diff --git a/tests/ui/impl-trait/auto-trait-coherence.rs b/tests/ui/impl-trait/auto-trait-leakage/auto-trait-coherence.rs similarity index 100% rename from tests/ui/impl-trait/auto-trait-coherence.rs rename to tests/ui/impl-trait/auto-trait-leakage/auto-trait-coherence.rs diff --git a/tests/ui/impl-trait/auto-trait-coherence.stderr b/tests/ui/impl-trait/auto-trait-leakage/auto-trait-coherence.stderr similarity index 100% rename from tests/ui/impl-trait/auto-trait-coherence.stderr rename to tests/ui/impl-trait/auto-trait-leakage/auto-trait-coherence.stderr diff --git a/tests/ui/impl-trait/auto-trait-contains-err.rs b/tests/ui/impl-trait/auto-trait-leakage/auto-trait-contains-err.rs similarity index 100% rename from tests/ui/impl-trait/auto-trait-contains-err.rs rename to tests/ui/impl-trait/auto-trait-leakage/auto-trait-contains-err.rs diff --git a/tests/ui/impl-trait/auto-trait-contains-err.stderr b/tests/ui/impl-trait/auto-trait-leakage/auto-trait-contains-err.stderr similarity index 100% rename from tests/ui/impl-trait/auto-trait-contains-err.stderr rename to tests/ui/impl-trait/auto-trait-leakage/auto-trait-contains-err.stderr diff --git a/tests/ui/impl-trait/auto-trait-leak-rpass.rs b/tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak-rpass.rs similarity index 100% rename from tests/ui/impl-trait/auto-trait-leak-rpass.rs rename to tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak-rpass.rs diff --git a/tests/ui/impl-trait/auto-trait-leak.rs b/tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak.rs similarity index 100% rename from tests/ui/impl-trait/auto-trait-leak.rs rename to tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak.rs diff --git a/tests/ui/impl-trait/auto-trait-leak.stderr b/tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak.stderr similarity index 100% rename from tests/ui/impl-trait/auto-trait-leak.stderr rename to tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak.stderr diff --git a/tests/ui/impl-trait/auto-trait-leak2.rs b/tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak2.rs similarity index 100% rename from tests/ui/impl-trait/auto-trait-leak2.rs rename to tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak2.rs diff --git a/tests/ui/impl-trait/auto-trait-leak2.stderr b/tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak2.stderr similarity index 100% rename from tests/ui/impl-trait/auto-trait-leak2.stderr rename to tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak2.stderr From 836ea25b4d42d307a75e98ec0c703dbc8bcdab79 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 14 Apr 2025 11:02:36 +0200 Subject: [PATCH 437/606] add RPITIT tests: method compat auto trait leakage --- ...atability-via-leakage-cycle.current.stderr | 58 +++++++++ ...ompatability-via-leakage-cycle.next.stderr | 122 ++++++++++++++++++ .../method-compatability-via-leakage-cycle.rs | 30 +++++ .../method-compatability-via-leakage.rs | 14 ++ 4 files changed, 224 insertions(+) create mode 100644 tests/ui/impl-trait/in-trait/method-compatability-via-leakage-cycle.current.stderr create mode 100644 tests/ui/impl-trait/in-trait/method-compatability-via-leakage-cycle.next.stderr create mode 100644 tests/ui/impl-trait/in-trait/method-compatability-via-leakage-cycle.rs create mode 100644 tests/ui/impl-trait/in-trait/method-compatability-via-leakage.rs diff --git a/tests/ui/impl-trait/in-trait/method-compatability-via-leakage-cycle.current.stderr b/tests/ui/impl-trait/in-trait/method-compatability-via-leakage-cycle.current.stderr new file mode 100644 index 000000000000..bf598d627094 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/method-compatability-via-leakage-cycle.current.stderr @@ -0,0 +1,58 @@ +error[E0391]: cycle detected when computing type of `::{anon_assoc#0}` + --> $DIR/method-compatability-via-leakage-cycle.rs:21:24 + | +LL | fn foo(b: bool) -> impl Sized { + | ^^^^^^^^^^ + | +note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process... + --> $DIR/method-compatability-via-leakage-cycle.rs:21:24 + | +LL | fn foo(b: bool) -> impl Sized { + | ^^^^^^^^^^ + = note: ...which requires evaluating trait selection obligation `::foo::{opaque#0}: core::marker::Send`... +note: ...which requires computing type of opaque `::foo::{opaque#0}`... + --> $DIR/method-compatability-via-leakage-cycle.rs:21:24 + | +LL | fn foo(b: bool) -> impl Sized { + | ^^^^^^^^^^ +note: ...which requires borrow-checking `::foo`... + --> $DIR/method-compatability-via-leakage-cycle.rs:21:5 + | +LL | fn foo(b: bool) -> impl Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires promoting constants in MIR for `::foo`... + --> $DIR/method-compatability-via-leakage-cycle.rs:21:5 + | +LL | fn foo(b: bool) -> impl Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires checking if `::foo` contains FFI-unwind calls... + --> $DIR/method-compatability-via-leakage-cycle.rs:21:5 + | +LL | fn foo(b: bool) -> impl Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires building MIR for `::foo`... + --> $DIR/method-compatability-via-leakage-cycle.rs:21:5 + | +LL | fn foo(b: bool) -> impl Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires match-checking `::foo`... + --> $DIR/method-compatability-via-leakage-cycle.rs:21:5 + | +LL | fn foo(b: bool) -> impl Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires type-checking `::foo`... + --> $DIR/method-compatability-via-leakage-cycle.rs:21:5 + | +LL | fn foo(b: bool) -> impl Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which again requires computing type of `::{anon_assoc#0}`, completing the cycle +note: cycle used when checking that `` is well-formed + --> $DIR/method-compatability-via-leakage-cycle.rs:17:1 + | +LL | impl Trait for u32 { + | ^^^^^^^^^^^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/impl-trait/in-trait/method-compatability-via-leakage-cycle.next.stderr b/tests/ui/impl-trait/in-trait/method-compatability-via-leakage-cycle.next.stderr new file mode 100644 index 000000000000..6bec5bbc0632 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/method-compatability-via-leakage-cycle.next.stderr @@ -0,0 +1,122 @@ +error[E0391]: cycle detected when computing type of `::{anon_assoc#0}` + --> $DIR/method-compatability-via-leakage-cycle.rs:21:24 + | +LL | fn foo(b: bool) -> impl Sized { + | ^^^^^^^^^^ + | +note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process... + --> $DIR/method-compatability-via-leakage-cycle.rs:21:5 + | +LL | fn foo(b: bool) -> impl Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires computing type of `::foo::{opaque#0}`... + --> $DIR/method-compatability-via-leakage-cycle.rs:21:24 + | +LL | fn foo(b: bool) -> impl Sized { + | ^^^^^^^^^^ +note: ...which requires computing type of opaque `::foo::{opaque#0}`... + --> $DIR/method-compatability-via-leakage-cycle.rs:21:24 + | +LL | fn foo(b: bool) -> impl Sized { + | ^^^^^^^^^^ +note: ...which requires borrow-checking `::foo`... + --> $DIR/method-compatability-via-leakage-cycle.rs:21:5 + | +LL | fn foo(b: bool) -> impl Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires promoting constants in MIR for `::foo`... + --> $DIR/method-compatability-via-leakage-cycle.rs:21:5 + | +LL | fn foo(b: bool) -> impl Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires checking if `::foo` contains FFI-unwind calls... + --> $DIR/method-compatability-via-leakage-cycle.rs:21:5 + | +LL | fn foo(b: bool) -> impl Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires building MIR for `::foo`... + --> $DIR/method-compatability-via-leakage-cycle.rs:21:5 + | +LL | fn foo(b: bool) -> impl Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires match-checking `::foo`... + --> $DIR/method-compatability-via-leakage-cycle.rs:21:5 + | +LL | fn foo(b: bool) -> impl Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires type-checking `::foo`... + --> $DIR/method-compatability-via-leakage-cycle.rs:21:5 + | +LL | fn foo(b: bool) -> impl Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which again requires computing type of `::{anon_assoc#0}`, completing the cycle +note: cycle used when checking that `` is well-formed + --> $DIR/method-compatability-via-leakage-cycle.rs:17:1 + | +LL | impl Trait for u32 { + | ^^^^^^^^^^^^^^^^^^ + = 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[E0391]: cycle detected when computing type of `::{anon_assoc#0}` + --> $DIR/method-compatability-via-leakage-cycle.rs:21:24 + | +LL | fn foo(b: bool) -> impl Sized { + | ^^^^^^^^^^ + | +note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process... + --> $DIR/method-compatability-via-leakage-cycle.rs:21:5 + | +LL | fn foo(b: bool) -> impl Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires computing type of `::foo::{opaque#0}`... + --> $DIR/method-compatability-via-leakage-cycle.rs:21:24 + | +LL | fn foo(b: bool) -> impl Sized { + | ^^^^^^^^^^ +note: ...which requires computing type of opaque `::foo::{opaque#0}`... + --> $DIR/method-compatability-via-leakage-cycle.rs:21:24 + | +LL | fn foo(b: bool) -> impl Sized { + | ^^^^^^^^^^ +note: ...which requires borrow-checking `::foo`... + --> $DIR/method-compatability-via-leakage-cycle.rs:21:5 + | +LL | fn foo(b: bool) -> impl Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires promoting constants in MIR for `::foo`... + --> $DIR/method-compatability-via-leakage-cycle.rs:21:5 + | +LL | fn foo(b: bool) -> impl Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires checking if `::foo` contains FFI-unwind calls... + --> $DIR/method-compatability-via-leakage-cycle.rs:21:5 + | +LL | fn foo(b: bool) -> impl Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires building MIR for `::foo`... + --> $DIR/method-compatability-via-leakage-cycle.rs:21:5 + | +LL | fn foo(b: bool) -> impl Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires match-checking `::foo`... + --> $DIR/method-compatability-via-leakage-cycle.rs:21:5 + | +LL | fn foo(b: bool) -> impl Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires type-checking `::foo`... + --> $DIR/method-compatability-via-leakage-cycle.rs:21:5 + | +LL | fn foo(b: bool) -> impl Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which again requires computing type of `::{anon_assoc#0}`, completing the cycle +note: cycle used when checking that `` is well-formed + --> $DIR/method-compatability-via-leakage-cycle.rs:17:1 + | +LL | impl Trait for u32 { + | ^^^^^^^^^^^^^^^^^^ + = 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 + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/impl-trait/in-trait/method-compatability-via-leakage-cycle.rs b/tests/ui/impl-trait/in-trait/method-compatability-via-leakage-cycle.rs new file mode 100644 index 000000000000..917820dc2b8b --- /dev/null +++ b/tests/ui/impl-trait/in-trait/method-compatability-via-leakage-cycle.rs @@ -0,0 +1,30 @@ +//@ revisions: current next +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) +//@ known-bug: #139788 + +// Recursively using the trait method inside of an impl in case checking +// method compatability relies on opaque type leakage currently causes a +// cycle error. + +trait Trait { + // desugars to + // type Assoc: Sized + Send; + // fn foo(b: bool) -> Self::Assoc; + fn foo(b: bool) -> impl Sized + Send; +} + +impl Trait for u32 { + // desugars to + // type Assoc = impl_rpit::; + // fn foo(b: bool) -> Self::Assoc { .. } + fn foo(b: bool) -> impl Sized { + if b { + u32::foo(false) + } else { + 1u32 + } + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/in-trait/method-compatability-via-leakage.rs b/tests/ui/impl-trait/in-trait/method-compatability-via-leakage.rs new file mode 100644 index 000000000000..249ec0728c1a --- /dev/null +++ b/tests/ui/impl-trait/in-trait/method-compatability-via-leakage.rs @@ -0,0 +1,14 @@ +//@ check-pass +//@ revisions: current next +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) + +trait Trait { + fn foo() -> impl Sized + Send; +} + +impl Trait for u32 { + fn foo() -> impl Sized {} +} + +fn main() {} From 582718380119e0e7aa2da76ea49d111b3735c2c3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 14 Apr 2025 13:56:51 +0200 Subject: [PATCH 438/606] ptr docs: add missing backtics around 'usize' --- library/core/src/ptr/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 2357ba23aa0d..445c789a7de2 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -278,7 +278,7 @@ //! ### Using Strict Provenance //! //! Most code needs no changes to conform to strict provenance, as the only really concerning -//! operation is casts from usize to a pointer. For code which *does* cast a `usize` to a pointer, +//! operation is casts from `usize` to a pointer. For code which *does* cast a `usize` to a pointer, //! the scope of the change depends on exactly what you're doing. //! //! In general, you just need to make sure that if you want to convert a `usize` address to a From 9c88eb6c4344cc2387900bb362f09291f031e9c2 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 14 Apr 2025 14:46:48 +0200 Subject: [PATCH 439/606] normalize: prefer ParamEnv over AliasBound --- .../src/solve/assembly/mod.rs | 51 +++++++++++-------- .../norm-where-bound-gt-alias-bound.rs | 29 +++++++++++ 2 files changed, 59 insertions(+), 21 deletions(-) create mode 100644 tests/ui/traits/winnowing/norm-where-bound-gt-alias-bound.rs diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index 384a304c4a9d..ee000b117486 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -792,37 +792,46 @@ where }; match proven_via { - // Even when a trait bound has been proven using a where-bound, we - // still need to consider alias-bounds for normalization, see - // tests/ui/next-solver/alias-bound-shadowed-by-env.rs. - // - // FIXME(const_trait_impl): should this behavior also be used by - // constness checking. Doing so is *at least theoretically* breaking, - // see github.com/rust-lang/rust/issues/133044#issuecomment-2500709754 TraitGoalProvenVia::ParamEnv | TraitGoalProvenVia::AliasBound => { - let mut candidates_from_env_and_bounds: Vec<_> = candidates - .iter() - .filter(|c| { - matches!( - c.source, - CandidateSource::AliasBound | CandidateSource::ParamEnv(_) - ) - }) - .map(|c| c.result) - .collect(); + let mut considered_candidates = Vec::new(); + considered_candidates.extend( + candidates + .iter() + .filter(|c| matches!(c.source, CandidateSource::ParamEnv(_))) + .map(|c| c.result), + ); + + // Even when a trait bound has been proven using a where-bound, we + // still need to consider alias-bounds for normalization, see + // tests/ui/next-solver/alias-bound-shadowed-by-env.rs. + // + // We still need to prefer where-bounds over alias-bounds however. + // See tests/ui/winnowing/norm-where-bound-gt-alias-bound.rs. + // + // FIXME(const_trait_impl): should this behavior also be used by + // constness checking. Doing so is *at least theoretically* breaking, + // see github.com/rust-lang/rust/issues/133044#issuecomment-2500709754 + if considered_candidates.is_empty() { + considered_candidates.extend( + candidates + .iter() + .filter(|c| matches!(c.source, CandidateSource::AliasBound)) + .map(|c| c.result), + ); + } // If the trait goal has been proven by using the environment, we want to treat // aliases as rigid if there are no applicable projection bounds in the environment. - if candidates_from_env_and_bounds.is_empty() { + if considered_candidates.is_empty() { if let Ok(response) = inject_normalize_to_rigid_candidate(self) { - candidates_from_env_and_bounds.push(response); + considered_candidates.push(response); } } - if let Some(response) = self.try_merge_responses(&candidates_from_env_and_bounds) { + if let Some(response) = self.try_merge_responses(&considered_candidates) { Ok(response) } else { - self.flounder(&candidates_from_env_and_bounds) + self.flounder(&considered_candidates) } } TraitGoalProvenVia::Misc => { diff --git a/tests/ui/traits/winnowing/norm-where-bound-gt-alias-bound.rs b/tests/ui/traits/winnowing/norm-where-bound-gt-alias-bound.rs new file mode 100644 index 000000000000..cdfb0ee45af4 --- /dev/null +++ b/tests/ui/traits/winnowing/norm-where-bound-gt-alias-bound.rs @@ -0,0 +1,29 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@ check-pass + +// Make sure we prefer the `I::IntoIterator: Iterator` +// where-bound over the `I::Intoiterator: Iterator` +// alias-bound. + +trait Iterator { + type Item; +} + +trait IntoIterator { + type Item; + type IntoIter: Iterator; +} + +fn normalize>() {} + +fn foo() +where + I: IntoIterator, + I::IntoIter: Iterator, +{ + normalize::(); +} + +fn main() {} From dc584580f36dd7d92c8b93405e6a0a1efc727a88 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Mon, 14 Apr 2025 14:27:15 +0100 Subject: [PATCH 440/606] Add myself to mailmap --- .mailmap | 1 + 1 file changed, 1 insertion(+) diff --git a/.mailmap b/.mailmap index b09aebd12dd8..c3ce111bfe3b 100644 --- a/.mailmap +++ b/.mailmap @@ -292,6 +292,7 @@ James Hinshelwood James Miller James Perry James Sanderson +Jamie Hill-Daniel Jana Dönszelmann Jana Dönszelmann Jana Dönszelmann From d5de2fa8bba93cf5cde42b4605b6886f8660f5bf Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Mon, 14 Apr 2025 15:32:34 +0200 Subject: [PATCH 441/606] use `realpath` in `bootstrap.py` when creating build-dir this avoids crashes when `./build` is a symlink to a non-existent directory. --- src/bootstrap/bootstrap.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 01a9792f1b37..42c314eaa654 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -1298,7 +1298,7 @@ def bootstrap(args): build.check_vendored_status() if not os.path.exists(build.build_dir): - os.makedirs(build.build_dir) + os.makedirs(os.path.realpath(build.build_dir)) # Fetch/build the bootstrap build.download_toolchain() From 1b46969a11b2cfa000593b225af94a9d3bfbedfc Mon Sep 17 00:00:00 2001 From: clubby789 Date: Mon, 14 Apr 2025 14:16:30 +0100 Subject: [PATCH 442/606] Specify `--print info=file` syntax in `--help` --- compiler/rustc_session/src/config.rs | 14 ++++---------- tests/run-make/rustc-help/help-v.diff | 2 +- tests/run-make/rustc-help/help-v.stdout | 6 ++++-- tests/run-make/rustc-help/help.stdout | 6 ++++-- .../invalid-compile-flags/print-without-arg.stderr | 5 +++-- 5 files changed, 16 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index bdd54a15147b..fc05470d941c 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1560,9 +1560,10 @@ The default is {DEFAULT_EDITION} and the latest stable edition is {LATEST_STABLE ) }); -static PRINT_KINDS_STRING: LazyLock = LazyLock::new(|| { +static PRINT_HELP: LazyLock = LazyLock::new(|| { format!( - "[{}]", + "Compiler information to print on stdout (or to a file)\n\ + INFO may be one of ({}).", PRINT_KINDS.iter().map(|(name, _)| format!("{name}")).collect::>().join("|") ) }); @@ -1621,14 +1622,7 @@ pub fn rustc_optgroups() -> Vec { "Comma separated list of types of output for the compiler to emit", "[asm|llvm-bc|llvm-ir|obj|metadata|link|dep-info|mir]", ), - opt( - Stable, - Multi, - "", - "print", - "Compiler information to print on stdout", - &PRINT_KINDS_STRING, - ), + opt(Stable, Multi, "", "print", &PRINT_HELP, "INFO[=FILE]"), opt(Stable, FlagMulti, "g", "", "Equivalent to -C debuginfo=2", ""), opt(Stable, FlagMulti, "O", "", "Equivalent to -C opt-level=3", ""), opt(Stable, Opt, "o", "", "Write output to ", "FILENAME"), diff --git a/tests/run-make/rustc-help/help-v.diff b/tests/run-make/rustc-help/help-v.diff index 22c5dd81bdb0..30703f6424e7 100644 --- a/tests/run-make/rustc-help/help-v.diff +++ b/tests/run-make/rustc-help/help-v.diff @@ -1,4 +1,4 @@ -@@ -51,10 +51,27 @@ +@@ -53,10 +53,27 @@ Set a codegen option -V, --version Print version info and exit -v, --verbose Use verbose output diff --git a/tests/run-make/rustc-help/help-v.stdout b/tests/run-make/rustc-help/help-v.stdout index f19ca1e9f90a..13af6e21060b 100644 --- a/tests/run-make/rustc-help/help-v.stdout +++ b/tests/run-make/rustc-help/help-v.stdout @@ -29,8 +29,10 @@ Options: --emit [asm|llvm-bc|llvm-ir|obj|metadata|link|dep-info|mir] Comma separated list of types of output for the compiler to emit - --print [all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|crate-root-lint-levels|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|supported-crate-types|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models] - Compiler information to print on stdout + --print INFO[=FILE] + Compiler information to print on stdout (or to a file) + INFO may be one of + (all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|crate-root-lint-levels|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|supported-crate-types|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models). -g Equivalent to -C debuginfo=2 -O Equivalent to -C opt-level=3 -o FILENAME Write output to diff --git a/tests/run-make/rustc-help/help.stdout b/tests/run-make/rustc-help/help.stdout index f7d352966035..62757d989eb3 100644 --- a/tests/run-make/rustc-help/help.stdout +++ b/tests/run-make/rustc-help/help.stdout @@ -29,8 +29,10 @@ Options: --emit [asm|llvm-bc|llvm-ir|obj|metadata|link|dep-info|mir] Comma separated list of types of output for the compiler to emit - --print [all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|crate-root-lint-levels|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|supported-crate-types|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models] - Compiler information to print on stdout + --print INFO[=FILE] + Compiler information to print on stdout (or to a file) + INFO may be one of + (all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|crate-root-lint-levels|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|supported-crate-types|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models). -g Equivalent to -C debuginfo=2 -O Equivalent to -C opt-level=3 -o FILENAME Write output to diff --git a/tests/ui/invalid-compile-flags/print-without-arg.stderr b/tests/ui/invalid-compile-flags/print-without-arg.stderr index 8abaee5056ba..fd2a36e761be 100644 --- a/tests/ui/invalid-compile-flags/print-without-arg.stderr +++ b/tests/ui/invalid-compile-flags/print-without-arg.stderr @@ -1,5 +1,6 @@ error: Argument to option 'print' missing Usage: - --print [all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|crate-root-lint-levels|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|supported-crate-types|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models] - Compiler information to print on stdout + --print INFO[=FILE] Compiler information to print on stdout (or to a file) + INFO may be one of + (all-target-specs-json|calling-conventions|cfg|check-cfg|code-models|crate-name|crate-root-lint-levels|deployment-target|file-names|host-tuple|link-args|native-static-libs|relocation-models|split-debuginfo|stack-protector-strategies|supported-crate-types|sysroot|target-cpus|target-features|target-libdir|target-list|target-spec-json|tls-models). From 3da0a19a291e62d1bb315b233a5fb74bcccb12ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Mon, 14 Apr 2025 16:27:33 +0200 Subject: [PATCH 443/606] Improve wording of post-merge report --- src/ci/citool/src/analysis.rs | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/ci/citool/src/analysis.rs b/src/ci/citool/src/analysis.rs index 208a494183c0..9fc7c309bfbd 100644 --- a/src/ci/citool/src/analysis.rs +++ b/src/ci/citool/src/analysis.rs @@ -520,23 +520,27 @@ fn report_test_diffs( } if doctest_count > 0 { + let prefix = + if doctest_count < original_diff_count { "Additionally, " } else { "" }; println!( - "\nAdditionally, {doctest_count} doctest {} were found. These are ignored, as they are noisy.", + "\n{prefix}{doctest_count} doctest {} were found. These are ignored, as they are noisy.", pluralize("diff", doctest_count) ); } // Now print the job group index - println!("\n**Job group index**\n"); - for (group, jobs) in job_index.into_iter().enumerate() { - println!( - "- {}: {}", - format_job_group(group as u64), - jobs.iter() - .map(|j| format_job_link(job_info_resolver, job_metrics, j)) - .collect::>() - .join(", ") - ); + if !job_index.is_empty() { + println!("\n**Job group index**\n"); + for (group, jobs) in job_index.into_iter().enumerate() { + println!( + "- {}: {}", + format_job_group(group as u64), + jobs.iter() + .map(|j| format_job_link(job_info_resolver, job_metrics, j)) + .collect::>() + .join(", ") + ); + } } }, ); From 7ad16974b995746b9156d90b8b80fb137afcd1e9 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 24 Jan 2025 15:57:13 +0000 Subject: [PATCH 444/606] Allow const patterns of matches to contain pattern types --- compiler/rustc_borrowck/src/type_check/mod.rs | 14 ++-- .../src/builder/matches/test.rs | 29 +++++++- tests/ui/type/pattern_types/derives.rs | 3 +- tests/ui/type/pattern_types/derives.stderr | 2 +- tests/ui/type/pattern_types/derives_fail.rs | 26 +++++++ .../ui/type/pattern_types/derives_fail.stderr | 74 +++++++++++++++++++ tests/ui/type/pattern_types/matching.rs | 26 +++++++ tests/ui/type/pattern_types/matching_fail.rs | 25 +++++++ .../type/pattern_types/matching_fail.stderr | 43 +++++++++++ 9 files changed, 233 insertions(+), 9 deletions(-) create mode 100644 tests/ui/type/pattern_types/derives_fail.rs create mode 100644 tests/ui/type/pattern_types/derives_fail.stderr create mode 100644 tests/ui/type/pattern_types/matching.rs create mode 100644 tests/ui/type/pattern_types/matching_fail.rs create mode 100644 tests/ui/type/pattern_types/matching_fail.stderr diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index f6144a25938c..65e16260b569 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1568,11 +1568,15 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } } CastKind::Transmute => { - span_mirbug!( - self, - rvalue, - "Unexpected CastKind::Transmute, which is not permitted in Analysis MIR", - ); + let ty_from = op.ty(self.body, tcx); + match ty_from.kind() { + ty::Pat(base, _) if base == ty => {} + _ => span_mirbug!( + self, + rvalue, + "Unexpected CastKind::Transmute {ty_from:?} -> {ty:?}, which is not permitted in Analysis MIR", + ), + } } } } diff --git a/compiler/rustc_mir_build/src/builder/matches/test.rs b/compiler/rustc_mir_build/src/builder/matches/test.rs index d1f9d4c34fe1..57cf8fa719c2 100644 --- a/compiler/rustc_mir_build/src/builder/matches/test.rs +++ b/compiler/rustc_mir_build/src/builder/matches/test.rs @@ -140,8 +140,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let success_block = target_block(TestBranch::Success); let fail_block = target_block(TestBranch::Failure); - let expect_ty = value.ty(); - let expect = self.literal_operand(test.span, value); + let mut expect_ty = value.ty(); + let mut expect = self.literal_operand(test.span, value); let mut place = place; let mut block = block; @@ -174,6 +174,31 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { place = ref_str; ty = ref_str_ty; } + &ty::Pat(base, _) => { + assert_eq!(ty, value.ty()); + assert!(base.is_trivially_pure_clone_copy()); + + let transmuted_place = self.temp(base, test.span); + self.cfg.push_assign( + block, + self.source_info(scrutinee_span), + transmuted_place, + Rvalue::Cast(CastKind::Transmute, Operand::Copy(place), base), + ); + + let transmuted_expect = self.temp(base, test.span); + self.cfg.push_assign( + block, + self.source_info(test.span), + transmuted_expect, + Rvalue::Cast(CastKind::Transmute, expect, base), + ); + + place = transmuted_place; + expect = Operand::Copy(transmuted_expect); + ty = base; + expect_ty = base; + } _ => {} } diff --git a/tests/ui/type/pattern_types/derives.rs b/tests/ui/type/pattern_types/derives.rs index 3878c47554d9..a3959b383177 100644 --- a/tests/ui/type/pattern_types/derives.rs +++ b/tests/ui/type/pattern_types/derives.rs @@ -1,4 +1,5 @@ -//! Check that pattern types don't implement traits of their base automatically +//! Check that pattern types don't implement traits of their base automatically. +//! Exceptions are `Clone` and `Copy`, which have builtin impls for pattern types. #![feature(pattern_types)] #![feature(pattern_type_macro)] diff --git a/tests/ui/type/pattern_types/derives.stderr b/tests/ui/type/pattern_types/derives.stderr index f59617ebc456..2d83684b152e 100644 --- a/tests/ui/type/pattern_types/derives.stderr +++ b/tests/ui/type/pattern_types/derives.stderr @@ -1,5 +1,5 @@ error[E0369]: binary operation `==` cannot be applied to type `(i32) is 0..=999999999` - --> $DIR/derives.rs:10:20 + --> $DIR/derives.rs:11:20 | LL | #[derive(Clone, Copy, PartialEq)] | --------- in this derive macro expansion diff --git a/tests/ui/type/pattern_types/derives_fail.rs b/tests/ui/type/pattern_types/derives_fail.rs new file mode 100644 index 000000000000..a3fbad667207 --- /dev/null +++ b/tests/ui/type/pattern_types/derives_fail.rs @@ -0,0 +1,26 @@ +//! Check that pattern types don't implement traits of their base automatically. +//! Exceptions are `Clone` and `Copy`, which have bultin impls for pattern types. + +#![feature(pattern_types)] +#![feature(pattern_type_macro)] + +use std::pat::pattern_type; + +#[derive(Clone, Copy, PartialEq, Eq, Debug, Ord, PartialOrd, Hash, Default)] +#[repr(transparent)] +struct Nanoseconds(NanoI32); +//~^ ERROR: the trait bound `(i32) is 0..=999999999: Eq` is not satisfied +//~| ERROR: `(i32) is 0..=999999999` doesn't implement `Debug` +//~| ERROR: the trait bound `(i32) is 0..=999999999: Ord` is not satisfied +//~| ERROR: the trait bound `(i32) is 0..=999999999: Hash` is not satisfied +//~| ERROR: the trait bound `(i32) is 0..=999999999: Default` is not satisfied +//~| ERROR: can't compare `(i32) is 0..=999999999` with `_` +//~| ERROR: `==` cannot be applied + +type NanoI32 = crate::pattern_type!(i32 is 0..=999_999_999); + +fn main() { + let x = Nanoseconds(unsafe { std::mem::transmute(42) }); + let y = x.clone(); + if y == x {} +} diff --git a/tests/ui/type/pattern_types/derives_fail.stderr b/tests/ui/type/pattern_types/derives_fail.stderr new file mode 100644 index 000000000000..78bef726341d --- /dev/null +++ b/tests/ui/type/pattern_types/derives_fail.stderr @@ -0,0 +1,74 @@ +error[E0369]: binary operation `==` cannot be applied to type `(i32) is 0..=999999999` + --> $DIR/derives_fail.rs:11:20 + | +LL | #[derive(Clone, Copy, PartialEq, Eq, Debug, Ord, PartialOrd, Hash, Default)] + | --------- in this derive macro expansion +LL | #[repr(transparent)] +LL | struct Nanoseconds(NanoI32); + | ^^^^^^^ + +error[E0277]: the trait bound `(i32) is 0..=999999999: Eq` is not satisfied + --> $DIR/derives_fail.rs:11:20 + | +LL | #[derive(Clone, Copy, PartialEq, Eq, Debug, Ord, PartialOrd, Hash, Default)] + | -- in this derive macro expansion +LL | #[repr(transparent)] +LL | struct Nanoseconds(NanoI32); + | ^^^^^^^ the trait `Eq` is not implemented for `(i32) is 0..=999999999` + | +note: required by a bound in `AssertParamIsEq` + --> $SRC_DIR/core/src/cmp.rs:LL:COL + +error[E0277]: `(i32) is 0..=999999999` doesn't implement `Debug` + --> $DIR/derives_fail.rs:11:20 + | +LL | #[derive(Clone, Copy, PartialEq, Eq, Debug, Ord, PartialOrd, Hash, Default)] + | ----- in this derive macro expansion +LL | #[repr(transparent)] +LL | struct Nanoseconds(NanoI32); + | ^^^^^^^ `(i32) is 0..=999999999` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | + = help: the trait `Debug` is not implemented for `(i32) is 0..=999999999` + +error[E0277]: the trait bound `(i32) is 0..=999999999: Ord` is not satisfied + --> $DIR/derives_fail.rs:11:20 + | +LL | #[derive(Clone, Copy, PartialEq, Eq, Debug, Ord, PartialOrd, Hash, Default)] + | --- in this derive macro expansion +LL | #[repr(transparent)] +LL | struct Nanoseconds(NanoI32); + | ^^^^^^^ the trait `Ord` is not implemented for `(i32) is 0..=999999999` + +error[E0277]: can't compare `(i32) is 0..=999999999` with `_` + --> $DIR/derives_fail.rs:11:20 + | +LL | #[derive(Clone, Copy, PartialEq, Eq, Debug, Ord, PartialOrd, Hash, Default)] + | ---------- in this derive macro expansion +LL | #[repr(transparent)] +LL | struct Nanoseconds(NanoI32); + | ^^^^^^^ no implementation for `(i32) is 0..=999999999 < _` and `(i32) is 0..=999999999 > _` + | + = help: the trait `PartialOrd<_>` is not implemented for `(i32) is 0..=999999999` + +error[E0277]: the trait bound `(i32) is 0..=999999999: Hash` is not satisfied + --> $DIR/derives_fail.rs:11:20 + | +LL | #[derive(Clone, Copy, PartialEq, Eq, Debug, Ord, PartialOrd, Hash, Default)] + | ---- in this derive macro expansion +LL | #[repr(transparent)] +LL | struct Nanoseconds(NanoI32); + | ^^^^^^^ the trait `Hash` is not implemented for `(i32) is 0..=999999999` + +error[E0277]: the trait bound `(i32) is 0..=999999999: Default` is not satisfied + --> $DIR/derives_fail.rs:11:20 + | +LL | #[derive(Clone, Copy, PartialEq, Eq, Debug, Ord, PartialOrd, Hash, Default)] + | ------- in this derive macro expansion +LL | #[repr(transparent)] +LL | struct Nanoseconds(NanoI32); + | ^^^^^^^ the trait `Default` is not implemented for `(i32) is 0..=999999999` + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0277, E0369. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/type/pattern_types/matching.rs b/tests/ui/type/pattern_types/matching.rs new file mode 100644 index 000000000000..b8463a8e8229 --- /dev/null +++ b/tests/ui/type/pattern_types/matching.rs @@ -0,0 +1,26 @@ +#![feature(pattern_types, pattern_type_macro, structural_match)] + +//@ check-pass + +use std::marker::StructuralPartialEq; +use std::pat::pattern_type; + +struct Thing(pattern_type!(u32 is 1..)); + +impl StructuralPartialEq for Thing {} +impl PartialEq for Thing { + fn eq(&self, other: &Thing) -> bool { + unsafe { std::mem::transmute::<_, u32>(self.0) == std::mem::transmute::<_, u32>(other.0) } + } +} + +impl Eq for Thing {} + +const TWO: Thing = Thing(2); + +const _: () = match TWO { + TWO => {} + _ => unreachable!(), +}; + +fn main() {} diff --git a/tests/ui/type/pattern_types/matching_fail.rs b/tests/ui/type/pattern_types/matching_fail.rs new file mode 100644 index 000000000000..8e2c741e3e0a --- /dev/null +++ b/tests/ui/type/pattern_types/matching_fail.rs @@ -0,0 +1,25 @@ +#![feature(pattern_types, pattern_type_macro, structural_match)] + +use std::pat::pattern_type; + +const THREE: pattern_type!(u32 is 1..) = 3; + +const _: () = match THREE { + THREE => {} + //~^ ERROR non-structural type + _ => unreachable!(), +}; + +const _: () = match THREE { + 3 => {} + //~^ ERROR mismatched types + _ => unreachable!(), +}; + +const _: () = match 3 { + THREE => {} + //~^ ERROR mismatched types + _ => unreachable!(), +}; + +fn main() {} diff --git a/tests/ui/type/pattern_types/matching_fail.stderr b/tests/ui/type/pattern_types/matching_fail.stderr new file mode 100644 index 000000000000..446180d80f24 --- /dev/null +++ b/tests/ui/type/pattern_types/matching_fail.stderr @@ -0,0 +1,43 @@ +error: constant of non-structural type `(u32) is 1..` in a pattern + --> $DIR/matching_fail.rs:8:5 + | +LL | const THREE: pattern_type!(u32 is 1..) = 3; + | -------------------------------------- constant defined here +... +LL | THREE => {} + | ^^^^^ constant of non-structural type + | + = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details + +error[E0308]: mismatched types + --> $DIR/matching_fail.rs:14:5 + | +LL | const _: () = match THREE { + | ----- this expression has type `(u32) is 1..` +LL | 3 => {} + | ^ expected `(u32) is 1..`, found integer + | + = note: expected pattern type `(u32) is 1..` + found type `{integer}` + +error[E0308]: mismatched types + --> $DIR/matching_fail.rs:20:5 + | +LL | const THREE: pattern_type!(u32 is 1..) = 3; + | -------------------------------------- constant defined here +... +LL | const _: () = match 3 { + | - this expression has type `{integer}` +LL | THREE => {} + | ^^^^^ + | | + | expected integer, found `(u32) is 1..` + | `THREE` is interpreted as a constant, not a new binding + | help: introduce a new binding instead: `other_three` + | + = note: expected type `{integer}` + found pattern type `(u32) is 1..` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. From 13b4734e3102b4fd5ad99b98a8cc46744faf5d68 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 13 Apr 2025 22:43:16 +0000 Subject: [PATCH 445/606] Derive Obligation's fold impls --- compiler/rustc_infer/src/traits/mod.rs | 7 +++- .../src/traits/structural_impls.rs | 32 +------------------ 2 files changed, 7 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs index b537750f1b51..6d5ad96e31c9 100644 --- a/compiler/rustc_infer/src/traits/mod.rs +++ b/compiler/rustc_infer/src/traits/mod.rs @@ -12,6 +12,7 @@ use std::hash::{Hash, Hasher}; use hir::def_id::LocalDefId; use rustc_hir as hir; +use rustc_macros::{TypeFoldable, TypeVisitable}; use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::solve::Certainty; pub use rustc_middle::traits::*; @@ -35,9 +36,11 @@ use crate::infer::InferCtxt; /// either identifying an `impl` (e.g., `impl Eq for i32`) that /// satisfies the obligation, or else finding a bound that is in /// scope. The eventual result is usually a `Selection` (defined below). -#[derive(Clone)] +#[derive(Clone, TypeFoldable, TypeVisitable)] pub struct Obligation<'tcx, T> { /// The reason we have to prove this thing. + #[type_foldable(identity)] + #[type_visitable(ignore)] pub cause: ObligationCause<'tcx>, /// The environment in which we should prove this thing. @@ -51,6 +54,8 @@ pub struct Obligation<'tcx, T> { /// If this goes over a certain threshold, we abort compilation -- /// in such cases, we can not say whether or not the predicate /// holds for certain. Stupid halting problem; such a drag. + #[type_foldable(identity)] + #[type_visitable(ignore)] pub recursion_depth: usize, } diff --git a/compiler/rustc_infer/src/traits/structural_impls.rs b/compiler/rustc_infer/src/traits/structural_impls.rs index 4335073d9bc6..03661ebf7ec5 100644 --- a/compiler/rustc_infer/src/traits/structural_impls.rs +++ b/compiler/rustc_infer/src/traits/structural_impls.rs @@ -1,8 +1,6 @@ use std::fmt; -use rustc_middle::ty::{ - self, FallibleTypeFolder, TyCtxt, TypeFoldable, TypeVisitable, TypeVisitor, try_visit, -}; +use rustc_middle::ty; use crate::traits; use crate::traits::project::Normalized; @@ -34,31 +32,3 @@ impl<'tcx> fmt::Debug for traits::MismatchedProjectionTypes<'tcx> { write!(f, "MismatchedProjectionTypes({:?})", self.err) } } - -/////////////////////////////////////////////////////////////////////////// -// TypeFoldable implementations. - -impl<'tcx, O: TypeFoldable>> TypeFoldable> - for traits::Obligation<'tcx, O> -{ - fn try_fold_with>>( - self, - folder: &mut F, - ) -> Result { - Ok(traits::Obligation { - cause: self.cause, - recursion_depth: self.recursion_depth, - predicate: self.predicate.try_fold_with(folder)?, - param_env: self.param_env.try_fold_with(folder)?, - }) - } -} - -impl<'tcx, O: TypeVisitable>> TypeVisitable> - for traits::Obligation<'tcx, O> -{ - fn visit_with>>(&self, visitor: &mut V) -> V::Result { - try_visit!(self.predicate.visit_with(visitor)); - self.param_env.visit_with(visitor) - } -} From 1f3199c89995ee7ae5cbdaa81d1df5138660d61a Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Mon, 14 Apr 2025 16:53:24 +0200 Subject: [PATCH 446/606] Disable some r-a tests in bootstrap. --- src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs index 15de88ea656d..4bd365be7ca8 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs @@ -97,6 +97,7 @@ fn test_fn_like_macro_clone_raw_ident() { } #[test] +#[cfg(not(bootstrap))] fn test_fn_like_fn_like_span_join() { assert_expand( "fn_like_span_join", @@ -111,6 +112,7 @@ fn test_fn_like_fn_like_span_join() { } #[test] +#[cfg(not(bootstrap))] fn test_fn_like_fn_like_span_ops() { assert_expand( "fn_like_span_ops", From 83ea3454dfaf7ff54171035a70a89d03085d2a9d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 14 Apr 2025 02:08:35 +0000 Subject: [PATCH 447/606] Remove define_debug_via_print for ExistentialProjection --- compiler/rustc_type_ir/src/ir_print.rs | 2 +- compiler/rustc_type_ir/src/predicate.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_type_ir/src/ir_print.rs b/compiler/rustc_type_ir/src/ir_print.rs index c259a9747f0d..388ad09cb200 100644 --- a/compiler/rustc_type_ir/src/ir_print.rs +++ b/compiler/rustc_type_ir/src/ir_print.rs @@ -60,7 +60,7 @@ define_display_via_print!( PatternKind, ); -define_debug_via_print!(TraitRef, ExistentialTraitRef, ExistentialProjection, PatternKind); +define_debug_via_print!(TraitRef, ExistentialTraitRef, PatternKind); impl fmt::Display for OutlivesPredicate where diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs index 22d0fa23d0c5..8e10636ff657 100644 --- a/compiler/rustc_type_ir/src/predicate.rs +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -374,7 +374,7 @@ impl ty::Binder> { } /// A `ProjectionPredicate` for an `ExistentialTraitRef`. -#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)] +#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] #[cfg_attr( feature = "nightly", From 758e99a8004cf30c35a5dc17d9f8c626fc4ae2c9 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 14 Apr 2025 17:43:14 +0200 Subject: [PATCH 448/606] update lockfile --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 41288c55fe59..0e5d6281d672 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2046,9 +2046,9 @@ dependencies = [ [[package]] name = "libffi" -version = "3.2.0" +version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce826c243048e3d5cec441799724de52e2d42f820468431fc3fceee2341871e2" +checksum = "4a9434b6fc77375fb624698d5f8c49d7e80b10d59eb1219afda27d1f824d4074" dependencies = [ "libc", "libffi-sys", @@ -2056,9 +2056,9 @@ dependencies = [ [[package]] name = "libffi-sys" -version = "2.3.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f36115160c57e8529781b4183c2bb51fdc1f6d6d1ed345591d84be7703befb3c" +checksum = "ead36a2496acfc8edd6cc32352110e9478ac5b9b5f5b9856ebd3d28019addb84" dependencies = [ "cc", ] From 4b63362f3d0a455707f64ce345ca3a5467b04764 Mon Sep 17 00:00:00 2001 From: Yotam Ofek Date: Mon, 14 Apr 2025 15:52:25 +0000 Subject: [PATCH 449/606] Use `newtype_index!`-generated types more idiomatically --- compiler/rustc_ast_lowering/src/path.rs | 3 +-- .../rustc_borrowck/src/region_infer/mod.rs | 3 +-- .../src/debuginfo/create_scope_map.rs | 4 +-- compiler/rustc_hir/src/definitions.rs | 9 +++---- .../src/check/compare_impl_item.rs | 7 ++--- .../src/infer/region_constraints/mod.rs | 4 +-- .../rustc_infer/src/infer/snapshot/fudge.rs | 7 ++--- compiler/rustc_middle/src/mir/pretty.rs | 6 ++--- compiler/rustc_middle/src/ty/fold.rs | 2 +- compiler/rustc_middle/src/ty/visit.rs | 12 +++------ compiler/rustc_mir_build/src/thir/cx/expr.rs | 4 +-- compiler/rustc_mir_transform/src/coroutine.rs | 4 +-- .../rustc_mir_transform/src/elaborate_drop.rs | 17 ++++++------ compiler/rustc_mir_transform/src/inline.rs | 12 ++++----- compiler/rustc_mir_transform/src/patch.rs | 2 +- .../rustc_mir_transform/src/promote_consts.rs | 14 ++++++---- .../src/solve/eval_ctxt/canonical.rs | 2 +- compiler/rustc_passes/src/liveness.rs | 7 +++-- compiler/rustc_resolve/src/late.rs | 2 +- .../rustc_trait_selection/src/traits/mod.rs | 27 ++++++------------- 20 files changed, 61 insertions(+), 87 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index c464c159c34c..0bd65aec10f4 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -448,8 +448,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { generic_args.args.insert_many( 0, - (start.as_u32()..end.as_u32()).map(|i| { - let id = NodeId::from_u32(i); + (start..end).map(|id| { let l = self.lower_lifetime_anon_in_path(id, elided_lifetime_span); GenericArg::Lifetime(l) }), diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index c82c7341f028..f8af9e59f635 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -338,8 +338,7 @@ fn sccs_info<'tcx>(infcx: &BorrowckInferCtxt<'tcx>, sccs: &ConstraintSccs) { let num_components = sccs.num_sccs(); let mut components = vec![FxIndexSet::default(); num_components]; - for (reg_var_idx, scc_idx) in sccs.scc_indices().iter().enumerate() { - let reg_var = ty::RegionVid::from_usize(reg_var_idx); + for (reg_var, scc_idx) in sccs.scc_indices().iter_enumerated() { let origin = var_to_origin.get(®_var).unwrap_or(&RegionCtxt::Unknown); components[scc_idx.as_usize()].insert((reg_var, *origin)); } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs index f52991b36979..d2591139d6ed 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs @@ -3,7 +3,6 @@ use std::collections::hash_map::Entry; use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext}; use rustc_codegen_ssa::traits::*; use rustc_data_structures::fx::FxHashMap; -use rustc_index::Idx; use rustc_index::bit_set::DenseBitSet; use rustc_middle::mir::{Body, SourceScope}; use rustc_middle::ty::layout::{FnAbiOf, HasTypingEnv}; @@ -43,8 +42,7 @@ pub(crate) fn compute_mir_scopes<'ll, 'tcx>( let mut instantiated = DenseBitSet::new_empty(mir.source_scopes.len()); let mut discriminators = FxHashMap::default(); // Instantiate all scopes. - for idx in 0..mir.source_scopes.len() { - let scope = SourceScope::new(idx); + for scope in mir.source_scopes.indices() { make_mir_scope( cx, instance, diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs index 34f3c169505f..bf7b1eefcf68 100644 --- a/compiler/rustc_hir/src/definitions.rs +++ b/compiler/rustc_hir/src/definitions.rs @@ -47,12 +47,9 @@ impl DefPathTable { debug_assert_eq!(self.stable_crate_id, def_path_hash.stable_crate_id()); let local_hash = def_path_hash.local_hash(); - let index = { - let index = DefIndex::from(self.index_to_key.len()); - debug!("DefPathTable::insert() - {:?} <-> {:?}", key, index); - self.index_to_key.push(key); - index - }; + let index = self.index_to_key.push(key); + debug!("DefPathTable::insert() - {key:?} <-> {index:?}"); + self.def_path_hashes.push(local_hash); debug_assert!(self.def_path_hashes.len() == self.index_to_key.len()); diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 29a9931696ff..106e9ca15548 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -606,7 +606,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( // with placeholders, which imply nothing about outlives bounds, and then // prove below that the hidden types are well formed. let universe = infcx.create_next_universe(); - let mut idx = 0; + let mut idx = ty::BoundVar::ZERO; let mapping: FxIndexMap<_, _> = collector .types .iter() @@ -623,10 +623,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( tcx, ty::Placeholder { universe, - bound: ty::BoundTy { - var: ty::BoundVar::from_usize(idx), - kind: ty::BoundTyKind::Anon, - }, + bound: ty::BoundTy { var: idx, kind: ty::BoundTyKind::Anon }, }, ), ) diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index 8366aa6ec422..40e2e654b2ea 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -618,9 +618,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { RegionVid::from(value_count)..RegionVid::from(self.storage.unification_table.len()); ( range.clone(), - (range.start.index()..range.end.index()) - .map(|index| self.storage.var_infos[ty::RegionVid::from(index)].origin) - .collect(), + (range.start..range.end).map(|index| self.storage.var_infos[index].origin).collect(), ) } diff --git a/compiler/rustc_infer/src/infer/snapshot/fudge.rs b/compiler/rustc_infer/src/infer/snapshot/fudge.rs index b5d3c26b05e0..39c8c40ea7d8 100644 --- a/compiler/rustc_infer/src/infer/snapshot/fudge.rs +++ b/compiler/rustc_infer/src/infer/snapshot/fudge.rs @@ -30,11 +30,12 @@ fn const_vars_since_snapshot<'tcx>( snapshot_var_len: usize, ) -> (Range, Vec) { let range = vars_since_snapshot(table, snapshot_var_len); + let range = range.start.vid..range.end.vid; ( - range.start.vid..range.end.vid, - (range.start.index()..range.end.index()) - .map(|index| match table.probe_value(ConstVid::from_u32(index)) { + range.clone(), + range + .map(|index| match table.probe_value(index) { ConstVariableValue::Known { value: _ } => { ConstVariableOrigin { param_def_id: None, span: rustc_span::DUMMY_SP } } diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 5a038b27337c..e7bd2cb27fa7 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -531,12 +531,12 @@ fn write_mir_intro<'tcx>( // construct a scope tree and write it out let mut scope_tree: FxHashMap> = Default::default(); - for (index, scope_data) in body.source_scopes.iter().enumerate() { + for (index, scope_data) in body.source_scopes.iter_enumerated() { if let Some(parent) = scope_data.parent_scope { - scope_tree.entry(parent).or_default().push(SourceScope::new(index)); + scope_tree.entry(parent).or_default().push(index); } else { // Only the argument scope has no parent, because it's the root. - assert_eq!(index, OUTERMOST_SOURCE_SCOPE.index()); + assert_eq!(index, OUTERMOST_SOURCE_SCOPE); } } diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 8dc73e4ce85e..8d6871d2f1fe 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -278,7 +278,7 @@ impl<'tcx> TyCtxt<'tcx> { where T: TypeFoldable>, { - let shift_bv = |bv: ty::BoundVar| ty::BoundVar::from_usize(bv.as_usize() + bound_vars); + let shift_bv = |bv: ty::BoundVar| bv + bound_vars; self.replace_escaping_bound_vars_uncached( value, FnMutDelegate { diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index b341b30af6ac..44c7b6a7c9e8 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -231,9 +231,7 @@ impl MaxUniverse { impl<'tcx> TypeVisitor> for MaxUniverse { fn visit_ty(&mut self, t: Ty<'tcx>) { if let ty::Placeholder(placeholder) = t.kind() { - self.max_universe = ty::UniverseIndex::from_u32( - self.max_universe.as_u32().max(placeholder.universe.as_u32()), - ); + self.max_universe = self.max_universe.max(placeholder.universe); } t.super_visit_with(self) @@ -241,9 +239,7 @@ impl<'tcx> TypeVisitor> for MaxUniverse { fn visit_const(&mut self, c: ty::consts::Const<'tcx>) { if let ty::ConstKind::Placeholder(placeholder) = c.kind() { - self.max_universe = ty::UniverseIndex::from_u32( - self.max_universe.as_u32().max(placeholder.universe.as_u32()), - ); + self.max_universe = self.max_universe.max(placeholder.universe); } c.super_visit_with(self) @@ -251,9 +247,7 @@ impl<'tcx> TypeVisitor> for MaxUniverse { fn visit_region(&mut self, r: ty::Region<'tcx>) { if let ty::RePlaceholder(placeholder) = r.kind() { - self.max_universe = ty::UniverseIndex::from_u32( - self.max_universe.as_u32().max(placeholder.universe.as_u32()), - ); + self.max_universe = self.max_universe.max(placeholder.universe); } } } diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 31e22e69111b..fde23413972b 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -191,7 +191,7 @@ impl<'tcx> ThirBuildCx<'tcx> { let pointer_target = ExprKind::Field { lhs: self.thir.exprs.push(expr), variant_index: FIRST_VARIANT, - name: FieldIdx::from(0u32), + name: FieldIdx::ZERO, }; let arg = Expr { temp_lifetime, ty: pin_ty, span, kind: pointer_target }; let arg = self.thir.exprs.push(arg); @@ -226,7 +226,7 @@ impl<'tcx> ThirBuildCx<'tcx> { adt_def: self.tcx.adt_def(pin_did), variant_index: FIRST_VARIANT, args, - fields: Box::new([FieldExpr { name: FieldIdx::from(0u32), expr }]), + fields: Box::new([FieldExpr { name: FieldIdx::ZERO, expr }]), user_ty: None, base: AdtExprBase::None, })); diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 4405bd82410e..92d5e152f58e 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -203,7 +203,7 @@ struct TransformVisitor<'tcx> { impl<'tcx> TransformVisitor<'tcx> { fn insert_none_ret_block(&self, body: &mut Body<'tcx>) -> BasicBlock { - let block = BasicBlock::new(body.basic_blocks.len()); + let block = body.basic_blocks.next_index(); let source_info = SourceInfo::outermost(body.span); let none_value = match self.coroutine_kind { @@ -1193,7 +1193,7 @@ fn insert_panic_block<'tcx>( body: &mut Body<'tcx>, message: AssertMessage<'tcx>, ) -> BasicBlock { - let assert_block = BasicBlock::new(body.basic_blocks.len()); + let assert_block = body.basic_blocks.next_index(); let kind = TerminatorKind::Assert { cond: Operand::Constant(Box::new(ConstOperand { span: body.span, diff --git a/compiler/rustc_mir_transform/src/elaborate_drop.rs b/compiler/rustc_mir_transform/src/elaborate_drop.rs index fa476f961235..e3057a2f648f 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drop.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drop.rs @@ -258,17 +258,16 @@ where ) -> Vec<(Place<'tcx>, Option)> { variant .fields - .iter() - .enumerate() - .map(|(i, f)| { - let field = FieldIdx::new(i); - let subpath = self.elaborator.field_subpath(variant_path, field); + .iter_enumerated() + .map(|(field_idx, field)| { + let subpath = self.elaborator.field_subpath(variant_path, field_idx); let tcx = self.tcx(); assert_eq!(self.elaborator.typing_env().typing_mode, ty::TypingMode::PostAnalysis); - let field_ty = match tcx - .try_normalize_erasing_regions(self.elaborator.typing_env(), f.ty(tcx, args)) - { + let field_ty = match tcx.try_normalize_erasing_regions( + self.elaborator.typing_env(), + field.ty(tcx, args), + ) { Ok(t) => t, Err(_) => Ty::new_error( self.tcx(), @@ -279,7 +278,7 @@ where ), }; - (tcx.mk_place_field(base_place, field, field_ty), subpath) + (tcx.mk_place_field(base_place, field_idx, field_ty), subpath) }) .collect() } diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 0ab24e48d443..69e80ed54eae 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -903,9 +903,9 @@ fn inline_call<'tcx, I: Inliner<'tcx>>( let mut integrator = Integrator { args: &args, - new_locals: Local::new(caller_body.local_decls.len()).., - new_scopes: SourceScope::new(caller_body.source_scopes.len()).., - new_blocks: BasicBlock::new(caller_body.basic_blocks.len()).., + new_locals: caller_body.local_decls.next_index().., + new_scopes: caller_body.source_scopes.next_index().., + new_blocks: caller_body.basic_blocks.next_index().., destination: destination_local, callsite_scope: caller_body.source_scopes[callsite.source_info.scope].clone(), callsite, @@ -1169,7 +1169,7 @@ impl Integrator<'_, '_> { if idx < self.args.len() { self.args[idx] } else { - Local::new(self.new_locals.start.index() + (idx - self.args.len())) + self.new_locals.start + (idx - self.args.len()) } }; trace!("mapping local `{:?}` to `{:?}`", local, new); @@ -1177,13 +1177,13 @@ impl Integrator<'_, '_> { } fn map_scope(&self, scope: SourceScope) -> SourceScope { - let new = SourceScope::new(self.new_scopes.start.index() + scope.index()); + let new = self.new_scopes.start + scope.index(); trace!("mapping scope `{:?}` to `{:?}`", scope, new); new } fn map_block(&self, block: BasicBlock) -> BasicBlock { - let new = BasicBlock::new(self.new_blocks.start.index() + block.index()); + let new = self.new_blocks.start + block.index(); trace!("mapping block `{:?}` to `{:?}`", block, new); new } diff --git a/compiler/rustc_mir_transform/src/patch.rs b/compiler/rustc_mir_transform/src/patch.rs index 6a177faeac81..12ace04c5e26 100644 --- a/compiler/rustc_mir_transform/src/patch.rs +++ b/compiler/rustc_mir_transform/src/patch.rs @@ -181,7 +181,7 @@ impl<'tcx> MirPatch<'tcx> { /// Queues the addition of a new basic block. pub(crate) fn new_block(&mut self, data: BasicBlockData<'tcx>) -> BasicBlock { - let block = BasicBlock::new(self.term_patch_map.len()); + let block = self.term_patch_map.next_index(); debug!("MirPatch: new_block: {:?}: {:?}", block, data); self.new_blocks.push(data); self.term_patch_map.push(None); diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs index c8d8dc147e94..47d438309700 100644 --- a/compiler/rustc_mir_transform/src/promote_consts.rs +++ b/compiler/rustc_mir_transform/src/promote_consts.rs @@ -18,7 +18,7 @@ use either::{Left, Right}; use rustc_const_eval::check_consts::{ConstCx, qualifs}; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; -use rustc_index::{Idx, IndexSlice, IndexVec}; +use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::{self, GenericArgs, List, Ty, TyCtxt, TypeVisitableExt}; @@ -864,17 +864,21 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { new_temp } - fn promote_candidate(mut self, candidate: Candidate, next_promoted_id: usize) -> Body<'tcx> { + fn promote_candidate( + mut self, + candidate: Candidate, + next_promoted_index: Promoted, + ) -> Body<'tcx> { let def = self.source.source.def_id(); let (mut rvalue, promoted_op) = { let promoted = &mut self.promoted; - let promoted_id = Promoted::new(next_promoted_id); let tcx = self.tcx; let mut promoted_operand = |ty, span| { promoted.span = span; promoted.local_decls[RETURN_PLACE] = LocalDecl::new(ty, span); let args = tcx.erase_regions(GenericArgs::identity_for_item(tcx, def)); - let uneval = mir::UnevaluatedConst { def, args, promoted: Some(promoted_id) }; + let uneval = + mir::UnevaluatedConst { def, args, promoted: Some(next_promoted_index) }; ConstOperand { span, user_ty: None, const_: Const::Unevaluated(uneval, ty) } }; @@ -1034,7 +1038,7 @@ fn promote_candidates<'tcx>( required_consts: Vec::new(), }; - let mut promoted = promoter.promote_candidate(candidate, promotions.len()); + let mut promoted = promoter.promote_candidate(candidate, promotions.next_index()); promoted.source.promoted = Some(promotions.next_index()); promotions.push(promoted); } diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs index 4edc293ad807..d56b0e5847e5 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs @@ -355,7 +355,7 @@ where // exist at all (see the FIXME at the start of this method), we have to deal with // them for now. delegate.instantiate_canonical_var_with_infer(info, span, |idx| { - ty::UniverseIndex::from(prev_universe.index() + idx.index()) + prev_universe + idx.index() }) } else if info.is_existential() { // As an optimization we sometimes avoid creating a new inference variable here. diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index 06eb76c30c5f..7054bbf468b9 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -578,8 +578,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { where F: FnMut(Variable) -> bool, { - for var_idx in 0..self.ir.var_kinds.len() { - let var = Variable::from(var_idx); + for var in self.ir.var_kinds.indices() { if test(var) { write!(wr, " {var:?}")?; } @@ -609,8 +608,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { debug!( "^^ liveness computation results for body {} (entry={:?})", { - for ln_idx in 0..self.ir.lnks.len() { - debug!("{:?}", self.ln_str(LiveNode::from(ln_idx))); + for ln_idx in self.ir.lnks.indices() { + debug!("{:?}", self.ln_str(ln_idx)); } hir_id }, diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index a7170edb9867..13de81684884 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1948,7 +1948,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.record_lifetime_res( anchor_id, - LifetimeRes::ElidedAnchor { start: id, end: NodeId::from_u32(id.as_u32() + 1) }, + LifetimeRes::ElidedAnchor { start: id, end: id + 1 }, LifetimeElisionCandidate::Ignore, ); self.resolve_anonymous_lifetime(<, anchor_id, true); diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index de337710b5ef..8ac8dc67fbd8 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -643,7 +643,7 @@ fn replace_param_and_infer_args_with_placeholder<'tcx>( ) -> GenericArgsRef<'tcx> { struct ReplaceParamAndInferWithPlaceholder<'tcx> { tcx: TyCtxt<'tcx>, - idx: u32, + idx: ty::BoundVar, } impl<'tcx> TypeFolder> for ReplaceParamAndInferWithPlaceholder<'tcx> { @@ -653,19 +653,13 @@ fn replace_param_and_infer_args_with_placeholder<'tcx>( fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { if let ty::Infer(_) = t.kind() { - let idx = { - let idx = self.idx; - self.idx += 1; - idx - }; + let idx = self.idx; + self.idx += 1; Ty::new_placeholder( self.tcx, ty::PlaceholderType { universe: ty::UniverseIndex::ROOT, - bound: ty::BoundTy { - var: ty::BoundVar::from_u32(idx), - kind: ty::BoundTyKind::Anon, - }, + bound: ty::BoundTy { var: idx, kind: ty::BoundTyKind::Anon }, }, ) } else { @@ -675,16 +669,11 @@ fn replace_param_and_infer_args_with_placeholder<'tcx>( fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> { if let ty::ConstKind::Infer(_) = c.kind() { + let idx = self.idx; + self.idx += 1; ty::Const::new_placeholder( self.tcx, - ty::PlaceholderConst { - universe: ty::UniverseIndex::ROOT, - bound: ty::BoundVar::from_u32({ - let idx = self.idx; - self.idx += 1; - idx - }), - }, + ty::PlaceholderConst { universe: ty::UniverseIndex::ROOT, bound: idx }, ) } else { c.super_fold_with(self) @@ -692,7 +681,7 @@ fn replace_param_and_infer_args_with_placeholder<'tcx>( } } - args.fold_with(&mut ReplaceParamAndInferWithPlaceholder { tcx, idx: 0 }) + args.fold_with(&mut ReplaceParamAndInferWithPlaceholder { tcx, idx: ty::BoundVar::ZERO }) } /// Normalizes the predicates and checks whether they hold in an empty environment. If this From 3df7882272c96a19bcff6269e4f9f0aba34b6c6f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 14 Apr 2025 16:49:56 +0000 Subject: [PATCH 450/606] Normalize ADT fields in find_tails_for_unsizing --- compiler/rustc_monomorphize/src/collector.rs | 65 ++++++++++--------- tests/crashes/74451.rs | 42 ------------ .../codegen-smart-pointer-with-alias.rs | 32 +++++++++ 3 files changed, 65 insertions(+), 74 deletions(-) delete mode 100644 tests/crashes/74451.rs create mode 100644 tests/ui/coercion/codegen-smart-pointer-with-alias.rs diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 1dbb35f92c2c..d1d0f7cacaee 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -688,7 +688,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> { let target_ty = self.monomorphize(target_ty); let source_ty = self.monomorphize(source_ty); let (source_ty, target_ty) = - find_vtable_types_for_unsizing(self.tcx.at(span), source_ty, target_ty); + find_tails_for_unsizing(self.tcx.at(span), source_ty, target_ty); // This could also be a different Unsize instruction, like // from a fixed sized array to a slice. But we are only // interested in things that produce a vtable. @@ -1037,36 +1037,35 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> /// /// Finally, there is also the case of custom unsizing coercions, e.g., for /// smart pointers such as `Rc` and `Arc`. -fn find_vtable_types_for_unsizing<'tcx>( +fn find_tails_for_unsizing<'tcx>( tcx: TyCtxtAt<'tcx>, source_ty: Ty<'tcx>, target_ty: Ty<'tcx>, ) -> (Ty<'tcx>, Ty<'tcx>) { - let ptr_vtable = |inner_source: Ty<'tcx>, inner_target: Ty<'tcx>| { - let typing_env = ty::TypingEnv::fully_monomorphized(); - if tcx.type_has_metadata(inner_source, typing_env) { - (inner_source, inner_target) - } else { - tcx.struct_lockstep_tails_for_codegen(inner_source, inner_target, typing_env) - } - }; + let typing_env = ty::TypingEnv::fully_monomorphized(); + debug_assert!(!source_ty.has_param(), "{source_ty} should be fully monomorphic"); + debug_assert!(!target_ty.has_param(), "{target_ty} should be fully monomorphic"); match (source_ty.kind(), target_ty.kind()) { - (&ty::Ref(_, a, _), &ty::Ref(_, b, _) | &ty::RawPtr(b, _)) - | (&ty::RawPtr(a, _), &ty::RawPtr(b, _)) => ptr_vtable(a, b), + ( + &ty::Ref(_, source_pointee, _), + &ty::Ref(_, target_pointee, _) | &ty::RawPtr(target_pointee, _), + ) + | (&ty::RawPtr(source_pointee, _), &ty::RawPtr(target_pointee, _)) => { + tcx.struct_lockstep_tails_for_codegen(source_pointee, target_pointee, typing_env) + } + + // `Box` could go through the ADT code below, b/c it'll unpeel to `Unique`, + // and eventually bottom out in a raw ref, but we can micro-optimize it here. (_, _) if let Some(source_boxed) = source_ty.boxed_ty() && let Some(target_boxed) = target_ty.boxed_ty() => { - ptr_vtable(source_boxed, target_boxed) + tcx.struct_lockstep_tails_for_codegen(source_boxed, target_boxed, typing_env) } - // T as dyn* Trait - (_, &ty::Dynamic(_, _, ty::DynStar)) => ptr_vtable(source_ty, target_ty), - (&ty::Adt(source_adt_def, source_args), &ty::Adt(target_adt_def, target_args)) => { assert_eq!(source_adt_def, target_adt_def); - let CustomCoerceUnsized::Struct(coerce_index) = match crate::custom_coerce_unsize_info(tcx, source_ty, target_ty) { Ok(ccu) => ccu, @@ -1075,21 +1074,23 @@ fn find_vtable_types_for_unsizing<'tcx>( return (e, e); } }; - - let source_fields = &source_adt_def.non_enum_variant().fields; - let target_fields = &target_adt_def.non_enum_variant().fields; - - assert!( - coerce_index.index() < source_fields.len() - && source_fields.len() == target_fields.len() - ); - - find_vtable_types_for_unsizing( - tcx, - source_fields[coerce_index].ty(*tcx, source_args), - target_fields[coerce_index].ty(*tcx, target_args), - ) + let coerce_field = &source_adt_def.non_enum_variant().fields[coerce_index]; + // We're getting a possibly unnormalized type, so normalize it. + let source_field = + tcx.normalize_erasing_regions(typing_env, coerce_field.ty(*tcx, source_args)); + let target_field = + tcx.normalize_erasing_regions(typing_env, coerce_field.ty(*tcx, target_args)); + find_tails_for_unsizing(tcx, source_field, target_field) } + + // `T` as `dyn* Trait` unsizes *directly*. + // + // FIXME(dyn_star): This case is a bit awkward, b/c we're not really computing + // a tail here. We probably should handle this separately in the *caller* of + // this function, rather than returning something that is semantically different + // than what we return above. + (_, &ty::Dynamic(_, _, ty::DynStar)) => (source_ty, target_ty), + _ => bug!( "find_vtable_types_for_unsizing: invalid coercion {:?} -> {:?}", source_ty, @@ -1308,7 +1309,7 @@ fn visit_mentioned_item<'tcx>( } MentionedItem::UnsizeCast { source_ty, target_ty } => { let (source_ty, target_ty) = - find_vtable_types_for_unsizing(tcx.at(span), source_ty, target_ty); + find_tails_for_unsizing(tcx.at(span), source_ty, target_ty); // This could also be a different Unsize instruction, like // from a fixed sized array to a slice. But we are only // interested in things that produce a vtable. diff --git a/tests/crashes/74451.rs b/tests/crashes/74451.rs deleted file mode 100644 index 8f9369946789..000000000000 --- a/tests/crashes/74451.rs +++ /dev/null @@ -1,42 +0,0 @@ -//@ known-bug: #74451 -//@ compile-flags: -Copt-level=0 - -#![feature(specialization)] -#![feature(unsize, coerce_unsized)] -#![allow(incomplete_features)] -#![crate_type = "lib"] - -use std::ops::CoerceUnsized; - -pub struct SmartassPtr(A::Data); - -pub trait Smartass { - type Data; - type Data2: CoerceUnsized<*const [u8]>; -} - -pub trait MaybeObjectSafe {} - -impl MaybeObjectSafe for () {} - -impl Smartass for T { - type Data = ::Data2; - default type Data2 = *const [u8; 0]; -} - -impl Smartass for () { - type Data2 = *const [u8; 1]; -} - -impl Smartass for dyn MaybeObjectSafe { - type Data = *const [u8]; - type Data2 = *const [u8; 0]; -} - -impl CoerceUnsized> for SmartassPtr - where ::Data: std::ops::CoerceUnsized<::Data> -{} - -pub fn conv(s: SmartassPtr<()>) -> SmartassPtr { - s // This shouldn't coerce -} diff --git a/tests/ui/coercion/codegen-smart-pointer-with-alias.rs b/tests/ui/coercion/codegen-smart-pointer-with-alias.rs new file mode 100644 index 000000000000..a68952bb70aa --- /dev/null +++ b/tests/ui/coercion/codegen-smart-pointer-with-alias.rs @@ -0,0 +1,32 @@ +//@ build-pass + +// Regression test for . + +// Make sure that the unsize coercion we collect in mono for `Signal -> Signal` +// doesn't choke on the fact that the inner unsized field of `Signal` is a (trivial) alias. +// This exercises a normalize call that is necessary since we're getting a type from the type +// system, which isn't guaranteed to be normalized after substitution. + +#![feature(coerce_unsized)] + +use std::ops::CoerceUnsized; + +trait Mirror { + type Assoc: ?Sized; +} +impl Mirror for T { + type Assoc = T; +} + +trait Any {} +impl Any for T {} + +struct Signal<'a, T: ?Sized>(<&'a T as Mirror>::Assoc); + +// This `CoerceUnsized` impl isn't special; it's a bit more restricted than we'd see in the wild, +// but this ICE also reproduces if we were to make it general over `Signal -> Signal`. +impl<'a> CoerceUnsized> for Signal<'a, i32> {} + +fn main() { + Signal(&1i32) as Signal; +} From 188d44dd6e4949606e31c8009dffa4773ea25214 Mon Sep 17 00:00:00 2001 From: 0x79de <0x79de@gmail.com> Date: Mon, 14 Apr 2025 21:25:48 +0300 Subject: [PATCH 451/606] Fix: Map EOPNOTSUPP to ErrorKind::Unsupported on Unix This change maps the EOPNOTSUPP errno value (95) to std::io::ErrorKind::Unsupported in the decode_error_kind function for Unix platforms. Previously, it was incorrectly mapped to ErrorKind::Uncategorized. Fixes #139803 --- library/std/src/sys/pal/unix/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs index f8733eb61198..3a790d9c868c 100644 --- a/library/std/src/sys/pal/unix/mod.rs +++ b/library/std/src/sys/pal/unix/mod.rs @@ -274,6 +274,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { libc::ETXTBSY => ExecutableFileBusy, libc::EXDEV => CrossesDevices, libc::EINPROGRESS => InProgress, + libc::EOPNOTSUPP => Unsupported, libc::EACCES | libc::EPERM => PermissionDenied, From cb22c1d5e949b64aafb99994befde4bd25a421e9 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Mon, 14 Apr 2025 14:36:53 +0200 Subject: [PATCH 452/606] Allow (but don't require) `#[unsafe(naked)]` so that `compiler-builtins` can upgrade to it --- compiler/rustc_parse/src/validate_attr.rs | 6 +++ tests/ui/asm/naked-functions.rs | 56 +++++++++++------------ 2 files changed, 34 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index 6a1c2af48ed5..b518fca7a658 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -194,6 +194,12 @@ pub fn check_attribute_safety(psess: &ParseSess, safety: AttributeSafety, attr: } } } else if let Safety::Unsafe(unsafe_span) = attr_item.unsafety { + // Allow (but don't require) `#[unsafe(naked)]` so that compiler-builtins can upgrade to it. + // FIXME(#139797): remove this special case when compiler-builtins has upgraded. + if attr.has_name(sym::naked) { + return; + } + psess.dcx().emit_err(errors::InvalidAttrUnsafe { span: unsafe_span, name: attr_item.path.clone(), diff --git a/tests/ui/asm/naked-functions.rs b/tests/ui/asm/naked-functions.rs index 5bf2e2a3abd0..8ba0eecb7b5c 100644 --- a/tests/ui/asm/naked-functions.rs +++ b/tests/ui/asm/naked-functions.rs @@ -8,7 +8,7 @@ use std::arch::{asm, naked_asm}; -#[naked] +#[unsafe(naked)] pub unsafe extern "C" fn inline_asm_macro() { asm!("", options(raw)); //~^ERROR the `asm!` macro is not allowed in naked functions @@ -20,7 +20,7 @@ pub struct P { y: u16, } -#[naked] +#[unsafe(naked)] pub unsafe extern "C" fn patterns( mut a: u32, //~^ ERROR patterns not allowed in naked function parameters @@ -34,27 +34,27 @@ pub unsafe extern "C" fn patterns( naked_asm!("") } -#[naked] +#[unsafe(naked)] pub unsafe extern "C" fn inc(a: u32) -> u32 { //~^ ERROR naked functions must contain a single `naked_asm!` invocation a + 1 //~^ ERROR referencing function parameters is not allowed in naked functions } -#[naked] +#[unsafe(naked)] #[allow(asm_sub_register)] pub unsafe extern "C" fn inc_asm(a: u32) -> u32 { naked_asm!("/* {0} */", in(reg) a) //~^ ERROR the `in` operand cannot be used with `naked_asm!` } -#[naked] +#[unsafe(naked)] pub unsafe extern "C" fn inc_closure(a: u32) -> u32 { //~^ ERROR naked functions must contain a single `naked_asm!` invocation (|| a + 1)() } -#[naked] +#[unsafe(naked)] pub unsafe extern "C" fn unsupported_operands() { //~^ ERROR naked functions must contain a single `naked_asm!` invocation let mut a = 0usize; @@ -76,12 +76,12 @@ pub unsafe extern "C" fn unsupported_operands() { ); } -#[naked] +#[unsafe(naked)] pub extern "C" fn missing_assembly() { //~^ ERROR naked functions must contain a single `naked_asm!` invocation } -#[naked] +#[unsafe(naked)] pub extern "C" fn too_many_asm_blocks() { //~^ ERROR naked functions must contain a single `naked_asm!` invocation unsafe { @@ -92,7 +92,7 @@ pub extern "C" fn too_many_asm_blocks() { } pub fn outer(x: u32) -> extern "C" fn(usize) -> usize { - #[naked] + #[unsafe(naked)] pub extern "C" fn inner(y: usize) -> usize { //~^ ERROR naked functions must contain a single `naked_asm!` invocation *&y @@ -101,14 +101,14 @@ pub fn outer(x: u32) -> extern "C" fn(usize) -> usize { inner } -#[naked] +#[unsafe(naked)] unsafe extern "C" fn invalid_options() { naked_asm!("", options(nomem, preserves_flags)); //~^ ERROR the `nomem` option cannot be used with `naked_asm!` //~| ERROR the `preserves_flags` option cannot be used with `naked_asm!` } -#[naked] +#[unsafe(naked)] unsafe extern "C" fn invalid_options_continued() { naked_asm!("", options(readonly, nostack), options(pure)); //~^ ERROR the `readonly` option cannot be used with `naked_asm!` @@ -116,20 +116,20 @@ unsafe extern "C" fn invalid_options_continued() { //~| ERROR the `pure` option cannot be used with `naked_asm!` } -#[naked] +#[unsafe(naked)] unsafe extern "C" fn invalid_may_unwind() { naked_asm!("", options(may_unwind)); //~^ ERROR the `may_unwind` option cannot be used with `naked_asm!` } -#[naked] +#[unsafe(naked)] pub extern "C" fn valid_a() -> T { unsafe { naked_asm!(""); } } -#[naked] +#[unsafe(naked)] pub extern "C" fn valid_b() { unsafe { { @@ -140,32 +140,32 @@ pub extern "C" fn valid_b() { } } -#[naked] +#[unsafe(naked)] pub unsafe extern "C" fn valid_c() { naked_asm!(""); } #[cfg(target_arch = "x86_64")] -#[naked] +#[unsafe(naked)] pub unsafe extern "C" fn valid_att_syntax() { naked_asm!("", options(att_syntax)); } -#[naked] -#[naked] +#[unsafe(naked)] +#[unsafe(naked)] pub unsafe extern "C" fn allow_compile_error(a: u32) -> u32 { compile_error!("this is a user specified error") //~^ ERROR this is a user specified error } -#[naked] +#[unsafe(naked)] pub unsafe extern "C" fn allow_compile_error_and_asm(a: u32) -> u32 { compile_error!("this is a user specified error"); //~^ ERROR this is a user specified error naked_asm!("") } -#[naked] +#[unsafe(naked)] pub unsafe extern "C" fn invalid_asm_syntax(a: u32) -> u32 { naked_asm!(invalid_syntax) //~^ ERROR asm template must be a string literal @@ -173,7 +173,7 @@ pub unsafe extern "C" fn invalid_asm_syntax(a: u32) -> u32 { #[cfg(target_arch = "x86_64")] #[cfg_attr(target_pointer_width = "64", no_mangle)] -#[naked] +#[unsafe(naked)] pub unsafe extern "C" fn compatible_cfg_attributes() { naked_asm!("", options(att_syntax)); } @@ -182,20 +182,20 @@ pub unsafe extern "C" fn compatible_cfg_attributes() { #[warn(dead_code)] #[deny(dead_code)] #[forbid(dead_code)] -#[naked] +#[unsafe(naked)] pub unsafe extern "C" fn compatible_diagnostic_attributes() { naked_asm!("", options(raw)); } #[deprecated = "test"] -#[naked] +#[unsafe(naked)] pub unsafe extern "C" fn compatible_deprecated_attributes() { naked_asm!("", options(raw)); } #[cfg(target_arch = "x86_64")] #[must_use] -#[naked] +#[unsafe(naked)] pub unsafe extern "C" fn compatible_must_use_attributes() -> u64 { naked_asm!( " @@ -207,13 +207,13 @@ pub unsafe extern "C" fn compatible_must_use_attributes() -> u64 { #[export_name = "exported_function_name"] #[link_section = ".custom_section"] -#[naked] +#[unsafe(naked)] pub unsafe extern "C" fn compatible_ffi_attributes_1() { naked_asm!("", options(raw)); } #[cold] -#[naked] +#[unsafe(naked)] pub unsafe extern "C" fn compatible_codegen_attributes() { naked_asm!("", options(raw)); } @@ -222,13 +222,13 @@ pub unsafe extern "C" fn compatible_codegen_attributes() { /// a doc comment // a normal comment #[doc(alias = "ADocAlias")] -#[naked] +#[unsafe(naked)] pub unsafe extern "C" fn compatible_doc_attributes() { naked_asm!("", options(raw)); } #[linkage = "external"] -#[naked] +#[unsafe(naked)] pub unsafe extern "C" fn compatible_linkage() { naked_asm!("", options(raw)); } From 1d757833c6aa126e468275c1cd7285dee53a1de6 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Mon, 14 Apr 2025 18:35:51 +0000 Subject: [PATCH 453/606] Remove safe remove --- compiler/rustc_incremental/src/persist/fs.rs | 34 ++++---------------- 1 file changed, 6 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs index 76a1ff3cf382..f0d24d27e85a 100644 --- a/compiler/rustc_incremental/src/persist/fs.rs +++ b/compiler/rustc_incremental/src/persist/fs.rs @@ -290,7 +290,7 @@ pub(crate) fn prepare_session_directory(sess: &Session, crate_name: Symbol) { // Try to remove the session directory we just allocated. We don't // know if there's any garbage in it from the failed copy action. - if let Err(err) = safe_remove_dir_all(&session_dir) { + if let Err(err) = std_fs::remove_dir_all(&session_dir) { sess.dcx().emit_warn(errors::DeletePartial { path: &session_dir, err }); } @@ -324,7 +324,7 @@ pub fn finalize_session_directory(sess: &Session, svh: Option) { incr_comp_session_dir.display() ); - if let Err(err) = safe_remove_dir_all(&*incr_comp_session_dir) { + if let Err(err) = std_fs::remove_dir_all(&*incr_comp_session_dir) { sess.dcx().emit_warn(errors::DeleteFull { path: &incr_comp_session_dir, err }); } @@ -715,7 +715,7 @@ pub(crate) fn garbage_collect_session_directories(sess: &Session) -> io::Result< for directory_name in session_directories { if !lock_file_to_session_dir.items().any(|(_, dir)| *dir == directory_name) { let path = crate_directory.join(directory_name); - if let Err(err) = safe_remove_dir_all(&path) { + if let Err(err) = std_fs::remove_dir_all(&path) { sess.dcx().emit_warn(errors::InvalidGcFailed { path: &path, err }); } } @@ -821,7 +821,7 @@ pub(crate) fn garbage_collect_session_directories(sess: &Session) -> io::Result< all_except_most_recent(deletion_candidates).into_items().all(|(path, lock)| { debug!("garbage_collect_session_directories() - deleting `{}`", path.display()); - if let Err(err) = safe_remove_dir_all(&path) { + if let Err(err) = std_fs::remove_dir_all(&path) { sess.dcx().emit_warn(errors::FinalizedGcFailed { path: &path, err }); } else { delete_session_dir_lock_file(sess, &lock_file_path(&path)); @@ -839,7 +839,7 @@ pub(crate) fn garbage_collect_session_directories(sess: &Session) -> io::Result< fn delete_old(sess: &Session, path: &Path) { debug!("garbage_collect_session_directories() - deleting `{}`", path.display()); - if let Err(err) = safe_remove_dir_all(path) { + if let Err(err) = std_fs::remove_dir_all(path) { sess.dcx().emit_warn(errors::SessionGcFailed { path, err }); } else { delete_session_dir_lock_file(sess, &lock_file_path(path)); @@ -862,30 +862,8 @@ fn all_except_most_recent( } } -/// Since paths of artifacts within session directories can get quite long, we -/// need to support deleting files with very long paths. The regular -/// WinApi functions only support paths up to 260 characters, however. In order -/// to circumvent this limitation, we canonicalize the path of the directory -/// before passing it to std::fs::remove_dir_all(). This will convert the path -/// into the '\\?\' format, which supports much longer paths. -fn safe_remove_dir_all(p: &Path) -> io::Result<()> { - let canonicalized = match try_canonicalize(p) { - Ok(canonicalized) => canonicalized, - Err(err) if err.kind() == io::ErrorKind::NotFound => return Ok(()), - Err(err) => return Err(err), - }; - - std_fs::remove_dir_all(canonicalized) -} - fn safe_remove_file(p: &Path) -> io::Result<()> { - let canonicalized = match try_canonicalize(p) { - Ok(canonicalized) => canonicalized, - Err(err) if err.kind() == io::ErrorKind::NotFound => return Ok(()), - Err(err) => return Err(err), - }; - - match std_fs::remove_file(canonicalized) { + match std_fs::remove_file(p) { Err(err) if err.kind() == io::ErrorKind::NotFound => Ok(()), result => result, } From b26f3d4347ca589305a19d10c6e651b071849716 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 11 Apr 2025 16:50:20 +1000 Subject: [PATCH 454/606] Move `opt_rpitit_info` field to `hir::AssocKind::Type`. From `hir::AssocItem`. --- .../rustc_hir_analysis/src/check/check.rs | 6 ++-- .../src/check/compare_impl_item.rs | 19 ++++++----- compiler/rustc_hir_analysis/src/check/mod.rs | 2 +- .../rustc_hir_analysis/src/check/wfcheck.rs | 6 ++-- .../src/collect/type_of/opaque.rs | 2 +- .../errors/wrong_number_of_generic_args.rs | 4 +-- .../src/hir_ty_lowering/dyn_compatibility.rs | 2 +- .../src/hir_ty_lowering/mod.rs | 2 +- .../rustc_hir_analysis/src/impl_wf_check.rs | 2 +- compiler/rustc_hir_typeck/src/method/probe.rs | 12 ++----- compiler/rustc_metadata/src/rmeta/decoder.rs | 12 ++++--- compiler/rustc_metadata/src/rmeta/encoder.rs | 4 +-- compiler/rustc_middle/src/ty/assoc.rs | 34 +++++++++++-------- compiler/rustc_middle/src/ty/context.rs | 2 +- compiler/rustc_middle/src/ty/mod.rs | 6 ++-- compiler/rustc_middle/src/ty/sty.rs | 2 +- .../cfi/typeid/itanium_cxx_abi/transform.rs | 2 +- .../rustc_smir/src/rustc_smir/convert/ty.rs | 7 ++-- .../rustc_smir/src/stable_mir/mir/pretty.rs | 2 +- compiler/rustc_smir/src/stable_mir/ty.rs | 18 +++++----- .../src/error_reporting/infer/mod.rs | 8 +++-- .../src/error_reporting/traits/ambiguity.rs | 2 +- .../src/error_reporting/traits/suggestions.rs | 2 +- .../src/traits/dyn_compatibility.rs | 4 +-- .../src/traits/select/confirmation.rs | 4 +-- compiler/rustc_ty_utils/src/assoc.rs | 24 +++++++------ src/librustdoc/clean/mod.rs | 2 +- .../src/implied_bounds_in_impls.rs | 2 +- 28 files changed, 103 insertions(+), 91 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index c2706a1d4013..12c36e0f4c26 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -449,7 +449,7 @@ fn best_definition_site_of_opaque<'tcx>( return Some(span); } } - ty::AssocKind::Type => {} + ty::AssocKind::Type { .. } => {} } } @@ -740,7 +740,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) { for &assoc_item in assoc_items.in_definition_order() { match assoc_item.kind { - ty::AssocKind::Type if assoc_item.defaultness(tcx).has_value() => { + ty::AssocKind::Type { .. } if assoc_item.defaultness(tcx).has_value() => { let trait_args = GenericArgs::identity_for_item(tcx, def_id); let _: Result<_, rustc_errors::ErrorGuaranteed> = check_type_bounds( tcx, @@ -953,7 +953,7 @@ fn check_impl_items_against_trait<'tcx>( ); } ty::AssocKind::Const => {} - ty::AssocKind::Type => {} + ty::AssocKind::Type { .. } => {} } } diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 7dfdf1ae237d..d208aa71971e 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -44,7 +44,7 @@ pub(super) fn compare_impl_item( match impl_item.kind { ty::AssocKind::Fn { .. } => compare_impl_method(tcx, impl_item, trait_item, impl_trait_ref), - ty::AssocKind::Type => compare_impl_ty(tcx, impl_item, trait_item, impl_trait_ref), + ty::AssocKind::Type { .. } => compare_impl_ty(tcx, impl_item, trait_item, impl_trait_ref), ty::AssocKind::Const => compare_impl_const(tcx, impl_item, trait_item, impl_trait_ref), } } @@ -1703,7 +1703,7 @@ fn compare_generic_param_kinds<'tcx>( trait_item: ty::AssocItem, delay: bool, ) -> Result<(), ErrorGuaranteed> { - assert_eq!(impl_item.kind, trait_item.kind); + assert_eq!(impl_item.as_tag(), trait_item.as_tag()); let ty_const_params_of = |def_id| { tcx.generics_of(def_id).own_params.iter().filter(|param| { @@ -2235,16 +2235,19 @@ fn param_env_with_gat_bounds<'tcx>( // of the RPITITs associated with the same body. This is because checking // the item bounds of RPITITs often involves nested RPITITs having to prove // bounds about themselves. - let impl_tys_to_install = match impl_ty.opt_rpitit_info { - None => vec![impl_ty], - Some( - ty::ImplTraitInTraitData::Impl { fn_def_id } - | ty::ImplTraitInTraitData::Trait { fn_def_id, .. }, - ) => tcx + let impl_tys_to_install = match impl_ty.kind { + ty::AssocKind::Type { + opt_rpitit_info: + Some( + ty::ImplTraitInTraitData::Impl { fn_def_id } + | ty::ImplTraitInTraitData::Trait { fn_def_id, .. }, + ), + } => tcx .associated_types_for_impl_traits_in_associated_fn(fn_def_id) .iter() .map(|def_id| tcx.associated_item(*def_id)) .collect(), + _ => vec![impl_ty], }; for impl_ty in impl_tys_to_install { diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 523db9440a41..ec934b1f620d 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -499,7 +499,7 @@ fn suggestion_signature<'tcx>( tcx.predicates_of(assoc.def_id).instantiate_own(tcx, args), assoc, ), - ty::AssocKind::Type => { + ty::AssocKind::Type { .. } => { let (generics, where_clauses) = bounds_from_generic_predicates( tcx, tcx.predicates_of(assoc.def_id).instantiate_own(tcx, args), diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index af7830fd6642..c6c370c4a846 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -408,7 +408,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, trait_def_id: LocalDefId) { let gat_def_id = gat_item.def_id.expect_local(); let gat_item = tcx.associated_item(gat_def_id); // If this item is not an assoc ty, or has no args, then it's not a GAT - if gat_item.kind != ty::AssocKind::Type { + if !gat_item.is_type() { continue; } let gat_generics = tcx.generics_of(gat_def_id); @@ -453,7 +453,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, trait_def_id: LocalDefId) { ) } // In our example, this corresponds to the `Iter` and `Item` associated types - ty::AssocKind::Type => { + ty::AssocKind::Type { .. } => { // If our associated item is a GAT with missing bounds, add them to // the param-env here. This allows this GAT to propagate missing bounds // to other GATs. @@ -1101,7 +1101,7 @@ fn check_associated_item( ); check_method_receiver(wfcx, hir_sig, item, self_ty) } - ty::AssocKind::Type => { + ty::AssocKind::Type { .. } => { if let ty::AssocItemContainer::Trait = item.container { check_associated_type_bounds(wfcx, item, span) } diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs index f06636447194..653adc6b3ba5 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs @@ -36,7 +36,7 @@ pub(super) fn find_opaque_ty_constraints_for_impl_trait_in_assoc_type( locator.check(assoc_id.expect_local()) } // Associated types don't have bodies, so they can't constrain hidden types - ty::AssocKind::Type => {} + ty::AssocKind::Type { .. } => {} } } diff --git a/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs index 610b293a114e..70d60bfcf2d2 100644 --- a/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs +++ b/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs @@ -4,7 +4,7 @@ use GenericArgsInfo::*; use rustc_errors::codes::*; use rustc_errors::{Applicability, Diag, Diagnostic, EmissionGuarantee, MultiSpan, pluralize}; use rustc_hir as hir; -use rustc_middle::ty::{self as ty, AssocItems, AssocKind, TyCtxt}; +use rustc_middle::ty::{self as ty, AssocItems, TyCtxt}; use rustc_span::def_id::DefId; use tracing::debug; @@ -486,7 +486,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { let items: &AssocItems = self.tcx.associated_items(self.def_id); items .in_definition_order() - .filter(|item| item.kind == AssocKind::Type) + .filter(|item| item.is_type()) .filter(|item| { !self .gen_args diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs index e64cd8ec302c..2e39beed8ae3 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs @@ -201,7 +201,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { tcx.associated_items(pred.trait_ref.def_id) .in_definition_order() // We only care about associated types. - .filter(|item| item.kind == ty::AssocKind::Type) + .filter(|item| item.is_type()) // No RPITITs -- they're not dyn-compatible for now. .filter(|item| !item.is_impl_trait_in_trait()) // If the associated type has a `where Self: Sized` bound, 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 0fb406d99080..0394dd20e28c 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -1733,7 +1733,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .any(|i| { i.kind.namespace() == Namespace::TypeNS && i.ident(tcx).normalize_to_macros_2_0() == assoc_ident - && matches!(i.kind, ty::AssocKind::Type) + && i.is_type() }) // Consider only accessible traits && tcx.visibility(*trait_def_id) diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs index 1ab36ce1dcb9..127ca846b9fe 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs @@ -112,7 +112,7 @@ pub(crate) fn enforce_impl_lifetime_params_are_constrained( .flat_map(|def_id| { let item = tcx.associated_item(def_id); match item.kind { - ty::AssocKind::Type => { + ty::AssocKind::Type { .. } => { if item.defaultness(tcx).has_value() { cgp::parameters_for(tcx, tcx.type_of(def_id).instantiate_identity(), true) } else { diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index d5d85c812b2d..07cb8c2a5bbb 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -1671,15 +1671,7 @@ impl<'tcx> Pick<'tcx> { /// Do not use for type checking. pub(crate) fn differs_from(&self, other: &Self) -> bool { let Self { - item: - AssocItem { - def_id, - name: _, - kind: _, - container: _, - trait_item_def_id: _, - opt_rpitit_info: _, - }, + item: AssocItem { def_id, name: _, kind: _, container: _, trait_item_def_id: _ }, kind: _, import_ids: _, autoderefs: _, @@ -2253,7 +2245,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { match self.mode { Mode::MethodCall => item.is_method(), Mode::Path => match item.kind { - ty::AssocKind::Type => false, + ty::AssocKind::Type { .. } => false, ty::AssocKind::Fn { .. } | ty::AssocKind::Const => true, }, } diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index cc3b2a241e4a..3cbe09280f69 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1342,12 +1342,17 @@ impl<'a> CrateMetadataRef<'a> { DefKind::AssocFn => { ty::AssocKind::Fn { has_self: self.get_fn_has_self_parameter(id, sess) } } - DefKind::AssocTy => ty::AssocKind::Type, + DefKind::AssocTy => ty::AssocKind::Type { + opt_rpitit_info: self + .root + .tables + .opt_rpitit_info + .get(self, id) + .map(|d| d.decode(self)), + }, _ => bug!("cannot get associated-item of `{:?}`", self.def_key(id)), }; let container = self.root.tables.assoc_container.get(self, id).unwrap(); - let opt_rpitit_info = - self.root.tables.opt_rpitit_info.get(self, id).map(|d| d.decode(self)); ty::AssocItem { name, @@ -1355,7 +1360,6 @@ impl<'a> CrateMetadataRef<'a> { def_id: self.local_def_id(id), trait_item_def_id: self.get_trait_item_def_id(id), container, - opt_rpitit_info, } } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index cc9da16ffdbb..b900100c3c01 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1691,7 +1691,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { match item.container { AssocItemContainer::Trait => { - if let ty::AssocKind::Type = item.kind { + if item.is_type() { self.encode_explicit_item_bounds(def_id); self.encode_explicit_item_self_bounds(def_id); if tcx.is_conditionally_const(def_id) { @@ -1706,7 +1706,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } } } - if let Some(rpitit_info) = item.opt_rpitit_info { + if let ty::AssocKind::Type { opt_rpitit_info: Some(rpitit_info) } = item.kind { record!(self.tables.opt_rpitit_info[def_id] <- rpitit_info); if matches!(rpitit_info, ty::ImplTraitInTraitData::Trait { .. }) { record_array!( diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs index 3c1e5ed9e114..eac8f04f84f9 100644 --- a/compiler/rustc_middle/src/ty/assoc.rs +++ b/compiler/rustc_middle/src/ty/assoc.rs @@ -25,11 +25,6 @@ pub struct AssocItem { /// If this is an item in an impl of a trait then this is the `DefId` of /// the associated item on the trait that this implements. pub trait_item_def_id: Option, - - /// `Some` if the associated item (an associated type) comes from the - /// return-position `impl Trait` in trait desugaring. The `ImplTraitInTraitData` - /// provides additional information about its source. - pub opt_rpitit_info: Option, } impl AssocItem { @@ -81,7 +76,7 @@ impl AssocItem { // regions just fine, showing `fn(&MyType)`. tcx.fn_sig(self.def_id).instantiate_identity().skip_binder().to_string() } - ty::AssocKind::Type => format!("type {};", self.name), + ty::AssocKind::Type { .. } => format!("type {};", self.name), ty::AssocKind::Const => { format!( "const {}: {:?};", @@ -97,10 +92,14 @@ impl AssocItem { ty::AssocKind::Const => "associated const", ty::AssocKind::Fn { has_self: true } => "method", ty::AssocKind::Fn { has_self: false } => "associated function", - ty::AssocKind::Type => "associated type", + ty::AssocKind::Type { .. } => "associated type", } } + pub fn is_type(&self) -> bool { + matches!(self.kind, ty::AssocKind::Type { .. }) + } + pub fn is_fn(&self) -> bool { matches!(self.kind, ty::AssocKind::Fn { .. }) } @@ -113,12 +112,12 @@ impl AssocItem { match self.kind { AssocKind::Const => AssocTag::Const, AssocKind::Fn { .. } => AssocTag::Fn, - AssocKind::Type => AssocTag::Type, + AssocKind::Type { .. } => AssocTag::Type, } } pub fn is_impl_trait_in_trait(&self) -> bool { - self.opt_rpitit_info.is_some() + matches!(self.kind, AssocKind::Type { opt_rpitit_info: Some(_) }) } /// Returns true if: @@ -143,14 +142,21 @@ impl AssocItem { #[derive(Copy, Clone, PartialEq, Debug, HashStable, Eq, Hash, Encodable, Decodable)] pub enum AssocKind { Const, - Fn { has_self: bool }, - Type, + Fn { + has_self: bool, + }, + Type { + /// `Some` if the associated type comes from an RPITIT. The + /// `ImplTraitInTraitData` provides additional information about its + /// source. + opt_rpitit_info: Option, + }, } impl AssocKind { pub fn namespace(&self) -> Namespace { match *self { - ty::AssocKind::Type => Namespace::TypeNS, + ty::AssocKind::Type { .. } => Namespace::TypeNS, ty::AssocKind::Const | ty::AssocKind::Fn { .. } => Namespace::ValueNS, } } @@ -159,7 +165,7 @@ impl AssocKind { match self { AssocKind::Const => DefKind::AssocConst, AssocKind::Fn { .. } => DefKind::AssocFn, - AssocKind::Type => DefKind::AssocTy, + AssocKind::Type { .. } => DefKind::AssocTy, } } } @@ -170,7 +176,7 @@ impl std::fmt::Display for AssocKind { AssocKind::Fn { has_self: true } => write!(f, "method"), AssocKind::Fn { has_self: false } => write!(f, "associated function"), AssocKind::Const => write!(f, "associated const"), - AssocKind::Type => write!(f, "associated type"), + AssocKind::Type { .. } => write!(f, "associated type"), } } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index abf6cbbcd877..fb25b8e130b5 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -464,7 +464,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { fn associated_type_def_ids(self, def_id: DefId) -> impl IntoIterator { self.associated_items(def_id) .in_definition_order() - .filter(|assoc_item| matches!(assoc_item.kind, ty::AssocKind::Type)) + .filter(|assoc_item| assoc_item.is_type()) .map(|assoc_item| assoc_item.def_id) } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 30c889c39d93..395d2ec48142 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1610,8 +1610,10 @@ impl<'tcx> TyCtxt<'tcx> { /// return-position `impl Trait` from a trait, then provide the source info /// about where that RPITIT came from. pub fn opt_rpitit_info(self, def_id: DefId) -> Option { - if let DefKind::AssocTy = self.def_kind(def_id) { - self.associated_item(def_id).opt_rpitit_info + if let DefKind::AssocTy = self.def_kind(def_id) + && let AssocKind::Type { opt_rpitit_info } = self.associated_item(def_id).kind + { + opt_rpitit_info } else { None } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 27ee363f1c14..bb178fe42538 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -734,7 +734,7 @@ impl<'tcx> Ty<'tcx> { .map(|principal| { tcx.associated_items(principal.def_id()) .in_definition_order() - .filter(|item| item.kind == ty::AssocKind::Type) + .filter(|item| item.is_type()) .filter(|item| !item.is_impl_trait_in_trait()) .filter(|item| !tcx.generics_require_sized_self(item.def_id)) .count() diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs index 718b9a4fa3b8..d2917478e4e4 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs @@ -240,7 +240,7 @@ fn trait_object_ty<'tcx>(tcx: TyCtxt<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tc .flat_map(|super_poly_trait_ref| { tcx.associated_items(super_poly_trait_ref.def_id()) .in_definition_order() - .filter(|item| item.kind == ty::AssocKind::Type) + .filter(|item| item.is_type()) .filter(|item| !tcx.generics_require_sized_self(item.def_id)) .map(move |assoc_ty| { super_poly_trait_ref.map_bound(|super_trait_ref| { diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index 94f3be9fef73..55f698b8f211 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -894,12 +894,14 @@ impl<'tcx> Stable<'tcx> for rustc_session::cstore::ForeignModule { impl<'tcx> Stable<'tcx> for ty::AssocKind { type T = stable_mir::ty::AssocKind; - fn stable(&self, _tables: &mut Tables<'_>) -> Self::T { + fn stable(&self, tables: &mut Tables<'_>) -> Self::T { use stable_mir::ty::AssocKind; match *self { ty::AssocKind::Const => AssocKind::Const, ty::AssocKind::Fn { has_self } => AssocKind::Fn { has_self }, - ty::AssocKind::Type => AssocKind::Type, + ty::AssocKind::Type { opt_rpitit_info } => AssocKind::Type { + opt_rpitit_info: opt_rpitit_info.map(|rpitit| rpitit.stable(tables)), + }, } } } @@ -926,7 +928,6 @@ impl<'tcx> Stable<'tcx> for ty::AssocItem { kind: self.kind.stable(tables), container: self.container.stable(tables), trait_item_def_id: self.trait_item_def_id.map(|did| tables.assoc_def(did)), - opt_rpitit_info: self.opt_rpitit_info.map(|rpitit| rpitit.stable(tables)), } } } diff --git a/compiler/rustc_smir/src/stable_mir/mir/pretty.rs b/compiler/rustc_smir/src/stable_mir/mir/pretty.rs index 60d9e122940b..9fa97763907f 100644 --- a/compiler/rustc_smir/src/stable_mir/mir/pretty.rs +++ b/compiler/rustc_smir/src/stable_mir/mir/pretty.rs @@ -25,7 +25,7 @@ impl Display for AssocKind { AssocKind::Fn { has_self: true } => write!(f, "method"), AssocKind::Fn { has_self: false } => write!(f, "associated function"), AssocKind::Const => write!(f, "associated const"), - AssocKind::Type => write!(f, "associated type"), + AssocKind::Type { .. } => write!(f, "associated type"), } } } diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs index 63ce756162a5..6eac0885d763 100644 --- a/compiler/rustc_smir/src/stable_mir/ty.rs +++ b/compiler/rustc_smir/src/stable_mir/ty.rs @@ -1585,18 +1585,20 @@ pub struct AssocItem { /// If this is an item in an impl of a trait then this is the `DefId` of /// the associated item on the trait that this implements. pub trait_item_def_id: Option, - - /// `Some` if the associated item (an associated type) comes from the - /// return-position `impl Trait` in trait desugaring. The `ImplTraitInTraitData` - /// provides additional information about its source. - pub opt_rpitit_info: Option, } #[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub enum AssocKind { Const, - Fn { has_self: bool }, - Type, + Fn { + has_self: bool, + }, + Type { + /// `Some` if the associated type comes from an RPITIT. The + /// `ImplTraitInTraitData` provides additional information about its + /// source. + opt_rpitit_info: Option, + }, } #[derive(Clone, Debug, Eq, PartialEq, Serialize)] @@ -1613,6 +1615,6 @@ pub enum ImplTraitInTraitData { impl AssocItem { pub fn is_impl_trait_in_trait(&self) -> bool { - self.opt_rpitit_info.is_some() + matches!(self.kind, AssocKind::Type { opt_rpitit_info: Some(_) }) } } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index cbadb46c17d9..1c71fe028d4d 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -2337,7 +2337,7 @@ impl<'tcx> ObligationCause<'tcx> { ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Fn { .. }, .. } => { ObligationCauseFailureCode::MethodCompat { span, subdiags } } - ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Type, .. } => { + ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Type { .. }, .. } => { ObligationCauseFailureCode::TypeCompat { span, subdiags } } ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Const, .. } => { @@ -2401,7 +2401,7 @@ impl<'tcx> ObligationCause<'tcx> { ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Fn { .. }, .. } => { "method type is compatible with trait" } - ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Type, .. } => { + ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Type { .. }, .. } => { "associated type is compatible with trait" } ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Const, .. } => { @@ -2425,7 +2425,9 @@ impl IntoDiagArg for ObligationCauseAsDiagArg<'_> { ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Fn { .. }, .. } => { "method_compat" } - ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Type, .. } => "type_compat", + ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Type { .. }, .. } => { + "type_compat" + } ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Const, .. } => { "const_compat" } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs index e3e1583a48fa..c4b0ca9cf8fc 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs @@ -352,7 +352,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ty::AssocKind::Fn { .. } => ("call", "function"), // This is already covered by E0223, but this following single match // arm doesn't hurt here. - ty::AssocKind::Type => ("refer to the", "type"), + ty::AssocKind::Type { .. } => ("refer to the", "type"), }; // Replace the more general E0283 with a more specific error diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 38aac8e70b52..084942cd8afd 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -2112,7 +2112,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { trait_ref: DefId, ) { if let Some(assoc_item) = self.tcx.opt_associated_item(item_def_id) { - if let ty::AssocKind::Const | ty::AssocKind::Type = assoc_item.kind { + if let ty::AssocKind::Const | ty::AssocKind::Type { .. } = assoc_item.kind { err.note(format!( "{}s cannot be accessed directly on a `trait`, they can only be \ accessed through a specific `impl`", diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index 76892db9ef7b..1ef16f34702e 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -188,7 +188,7 @@ fn bounds_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span tcx.associated_items(trait_def_id) .in_definition_order() // We're only looking at associated type bounds - .filter(|item| item.kind == ty::AssocKind::Type) + .filter(|item| item.is_type()) // Ignore GATs with `Self: Sized` .filter(|item| !tcx.generics_require_sized_self(item.def_id)) .flat_map(|item| tcx.explicit_item_bounds(item.def_id).iter_identity_copied()) @@ -320,7 +320,7 @@ pub fn dyn_compatibility_violations_for_assoc_item( }) .collect(), // Associated types can only be dyn-compatible if they have `Self: Sized` bounds. - ty::AssocKind::Type => { + ty::AssocKind::Type { .. } => { if !tcx.generics_of(item.def_id).is_own_empty() && !item.is_impl_trait_in_trait() { vec![DynCompatibilityViolation::GAT(item.name, item.ident(tcx).span)] } else { diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 69e7b2a43ff9..d71d1e9ae0fa 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -594,9 +594,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Associated types that require `Self: Sized` do not show up in the built-in // implementation of `Trait for dyn Trait`, and can be dropped here. .filter(|item| !tcx.generics_require_sized_self(item.def_id)) - .filter_map( - |item| if item.kind == ty::AssocKind::Type { Some(item.def_id) } else { None }, - ) + .filter_map(|item| if item.is_type() { Some(item.def_id) } else { None }) .collect(); for assoc_type in assoc_types { diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index 79de071b6878..2275fbb97923 100644 --- a/compiler/rustc_ty_utils/src/assoc.rs +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -132,7 +132,7 @@ fn associated_item_from_trait_item_ref(trait_item_ref: &hir::TraitItemRef) -> ty let kind = match trait_item_ref.kind { hir::AssocItemKind::Const => ty::AssocKind::Const, hir::AssocItemKind::Fn { has_self } => ty::AssocKind::Fn { has_self }, - hir::AssocItemKind::Type => ty::AssocKind::Type, + hir::AssocItemKind::Type => ty::AssocKind::Type { opt_rpitit_info: None }, }; ty::AssocItem { @@ -141,7 +141,6 @@ fn associated_item_from_trait_item_ref(trait_item_ref: &hir::TraitItemRef) -> ty def_id: owner_id.to_def_id(), trait_item_def_id: Some(owner_id.to_def_id()), container: ty::AssocItemContainer::Trait, - opt_rpitit_info: None, } } @@ -150,7 +149,7 @@ fn associated_item_from_impl_item_ref(impl_item_ref: &hir::ImplItemRef) -> ty::A let kind = match impl_item_ref.kind { hir::AssocItemKind::Const => ty::AssocKind::Const, hir::AssocItemKind::Fn { has_self } => ty::AssocKind::Fn { has_self }, - hir::AssocItemKind::Type => ty::AssocKind::Type, + hir::AssocItemKind::Type => ty::AssocKind::Type { opt_rpitit_info: None }, }; ty::AssocItem { @@ -159,7 +158,6 @@ fn associated_item_from_impl_item_ref(impl_item_ref: &hir::ImplItemRef) -> ty::A def_id: def_id.to_def_id(), trait_item_def_id: impl_item_ref.trait_item_def_id, container: ty::AssocItemContainer::Impl, - opt_rpitit_info: None, } } @@ -263,14 +261,15 @@ fn associated_type_for_impl_trait_in_trait( trait_assoc_ty.associated_item(ty::AssocItem { name: kw::Empty, - kind: ty::AssocKind::Type, + kind: ty::AssocKind::Type { + opt_rpitit_info: Some(ImplTraitInTraitData::Trait { + fn_def_id: fn_def_id.to_def_id(), + opaque_def_id: opaque_ty_def_id.to_def_id(), + }), + }, def_id, trait_item_def_id: None, container: ty::AssocItemContainer::Trait, - opt_rpitit_info: Some(ImplTraitInTraitData::Trait { - fn_def_id: fn_def_id.to_def_id(), - opaque_def_id: opaque_ty_def_id.to_def_id(), - }), }); // Copy visility of the containing function. @@ -315,11 +314,14 @@ fn associated_type_for_impl_trait_in_impl( impl_assoc_ty.associated_item(ty::AssocItem { name: kw::Empty, - kind: ty::AssocKind::Type, + kind: ty::AssocKind::Type { + opt_rpitit_info: Some(ImplTraitInTraitData::Impl { + fn_def_id: impl_fn_def_id.to_def_id(), + }), + }, def_id, trait_item_def_id: Some(trait_assoc_def_id), container: ty::AssocItemContainer::Impl, - opt_rpitit_info: Some(ImplTraitInTraitData::Impl { fn_def_id: impl_fn_def_id.to_def_id() }), }); // Copy visility of the containing function. diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 7cfd204aa137..74dbc7d06001 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1412,7 +1412,7 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo RequiredMethodItem(item) } } - ty::AssocKind::Type => { + ty::AssocKind::Type { .. } => { let my_name = assoc_item.name; fn param_eq_arg(param: &GenericParamDef, arg: &GenericArg) -> bool { diff --git a/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs b/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs index d02d9b2102bd..430f24111832 100644 --- a/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs +++ b/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs @@ -315,7 +315,7 @@ fn check<'tcx>(cx: &LateContext<'tcx>, bounds: GenericBounds<'tcx>) { assocs .filter_by_name_unhygienic(constraint.ident.name) .next() - .is_some_and(|assoc| assoc.kind == ty::AssocKind::Type) + .is_some_and(|assoc| assoc.is_type()) }) { emit_lint(cx, poly_trait, bounds, index, implied_constraints, bound); From 89e93a51c81b521a9601b365e3325d31e44e9198 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 14 Apr 2025 15:39:47 +1000 Subject: [PATCH 455/606] Move two methods from `AssocKind` to `AssocItem`. Because all the other similar methods are on `AssocItem`. --- .../src/coherence/inherent_impls_overlap.rs | 2 +- .../src/hir_ty_lowering/lint.rs | 2 +- .../src/hir_ty_lowering/mod.rs | 2 +- compiler/rustc_hir_typeck/src/method/mod.rs | 2 +- compiler/rustc_hir_typeck/src/method/probe.rs | 4 +-- .../rustc_hir_typeck/src/method/suggest.rs | 4 +-- compiler/rustc_middle/src/ty/assoc.rs | 33 +++++++++---------- .../src/error_reporting/traits/suggestions.rs | 2 +- .../passes/collect_intra_doc_links.rs | 4 +-- 9 files changed, 26 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs index dc616576c9c1..cbfad1f6883e 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs @@ -64,7 +64,7 @@ impl<'tcx> InherentOverlapChecker<'tcx> { fn compare_hygienically(&self, item1: ty::AssocItem, item2: ty::AssocItem) -> bool { // Symbols and namespace match, compare hygienically. - item1.kind.namespace() == item2.kind.namespace() + item1.namespace() == item2.namespace() && item1.ident(self.tcx).normalize_to_macros_2_0() == item2.ident(self.tcx).normalize_to_macros_2_0() } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs index 8e62dce21913..49fd55b03a25 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs @@ -501,7 +501,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let names: Vec<_> = tcx .associated_items(trait_def_id) .in_definition_order() - .filter(|assoc| assoc.kind.namespace() == Namespace::ValueNS) + .filter(|assoc| assoc.namespace() == Namespace::ValueNS) .map(|cand| cand.name) .collect(); if let Some(typo) = find_best_match_for_name(&names, segment.ident.name, None) { 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 0394dd20e28c..7605c6c6a420 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -1731,7 +1731,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { tcx.associated_items(*trait_def_id) .in_definition_order() .any(|i| { - i.kind.namespace() == Namespace::TypeNS + i.namespace() == Namespace::TypeNS && i.ident(tcx).normalize_to_macros_2_0() == assoc_ident && i.is_type() }) diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index 39cb139a199e..1b67e2306aa7 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -529,7 +529,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - let def_kind = pick.item.kind.as_def_kind(); + let def_kind = pick.item.as_def_kind(); tcx.check_stability(pick.item.def_id, Some(expr_id), span, Some(method_name.span)); Ok((def_kind, pick.item.def_id)) } diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 07cb8c2a5bbb..c14b7823e370 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -1583,7 +1583,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { }, None, ) { - self.private_candidate.set(Some((pick.item.kind.as_def_kind(), pick.item.def_id))); + self.private_candidate.set(Some((pick.item.as_def_kind(), pick.item.def_id))); } } None @@ -1694,7 +1694,7 @@ impl<'tcx> Pick<'tcx> { if self.unstable_candidates.is_empty() { return; } - let def_kind = self.item.kind.as_def_kind(); + let def_kind = self.item.as_def_kind(); tcx.node_span_lint(lint::builtin::UNSTABLE_NAME_COLLISIONS, scope_expr_id, span, |lint| { lint.primary_message(format!( "{} {} with this name may be added to the standard library in the future", diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 1b9771636a7d..962871ed2d11 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1819,7 +1819,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { mode: Mode, ) { let tcx = self.tcx; - let def_kind = similar_candidate.kind.as_def_kind(); + let def_kind = similar_candidate.as_def_kind(); let an = self.tcx.def_kind_descr_article(def_kind, similar_candidate.def_id); let msg = format!( "there is {an} {} `{}` with a similar name", @@ -4288,7 +4288,7 @@ fn print_disambiguation_help<'tcx>( && let SelfSource::MethodCall(receiver) = source && let Some(args) = args { - let def_kind_descr = tcx.def_kind_descr(item.kind.as_def_kind(), item.def_id); + let def_kind_descr = tcx.def_kind_descr(item.as_def_kind(), item.def_id); let item_name = item.ident(tcx); let first_input = tcx.fn_sig(item.def_id).instantiate_identity().skip_binder().inputs().get(0); diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs index eac8f04f84f9..6138157d8362 100644 --- a/compiler/rustc_middle/src/ty/assoc.rs +++ b/compiler/rustc_middle/src/ty/assoc.rs @@ -96,6 +96,20 @@ impl AssocItem { } } + pub fn namespace(&self) -> Namespace { + match self.kind { + ty::AssocKind::Type { .. } => Namespace::TypeNS, + ty::AssocKind::Const | ty::AssocKind::Fn { .. } => Namespace::ValueNS, + } + } + + pub fn as_def_kind(&self) -> DefKind { + match self.kind { + AssocKind::Const => DefKind::AssocConst, + AssocKind::Fn { .. } => DefKind::AssocFn, + AssocKind::Type { .. } => DefKind::AssocTy, + } + } pub fn is_type(&self) -> bool { matches!(self.kind, ty::AssocKind::Type { .. }) } @@ -153,23 +167,6 @@ pub enum AssocKind { }, } -impl AssocKind { - pub fn namespace(&self) -> Namespace { - match *self { - ty::AssocKind::Type { .. } => Namespace::TypeNS, - ty::AssocKind::Const | ty::AssocKind::Fn { .. } => Namespace::ValueNS, - } - } - - pub fn as_def_kind(&self) -> DefKind { - match self { - AssocKind::Const => DefKind::AssocConst, - AssocKind::Fn { .. } => DefKind::AssocFn, - AssocKind::Type { .. } => DefKind::AssocTy, - } - } -} - impl std::fmt::Display for AssocKind { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { @@ -250,7 +247,7 @@ impl AssocItems { parent_def_id: DefId, ) -> Option<&ty::AssocItem> { self.filter_by_name_unhygienic(ident.name) - .filter(|item| item.kind.namespace() == ns) + .filter(|item| item.namespace() == ns) .find(|item| tcx.hygienic_eq(ident, item.ident(tcx), parent_def_id)) } } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 084942cd8afd..08b95b450583 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -2116,7 +2116,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { err.note(format!( "{}s cannot be accessed directly on a `trait`, they can only be \ accessed through a specific `impl`", - self.tcx.def_kind_descr(assoc_item.kind.as_def_kind(), item_def_id) + self.tcx.def_kind_descr(assoc_item.as_def_kind(), item_def_id) )); err.span_suggestion( span, diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index fdbb792d25da..297597b3deac 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -60,7 +60,7 @@ fn filter_assoc_items_by_name_and_namespace( ns: Namespace, ) -> impl Iterator { tcx.associated_items(assoc_items_of).filter_by_name_unhygienic(ident.name).filter(move |item| { - item.kind.namespace() == ns && tcx.hygienic_eq(ident, item.ident(tcx), assoc_items_of) + item.namespace() == ns && tcx.hygienic_eq(ident, item.ident(tcx), assoc_items_of) }) } @@ -743,7 +743,7 @@ impl<'tcx> LinkCollector<'_, 'tcx> { ns, ) .map(|item| { - let res = Res::Def(item.kind.as_def_kind(), item.def_id); + let res = Res::Def(item.as_def_kind(), item.def_id); (res, item.def_id) }) .collect::>(), From 78599d83e7ab9f8cd4cbb9e982ddf12f258d6b18 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 14 Apr 2025 13:15:01 +1000 Subject: [PATCH 456/606] Move `name` field from `AssocItem` to `AssocKind` variants. To accurately reflect that RPITIT assoc items don't have a name. This avoids the use of `kw::Empty` to mean "no name", which is error prone. Helps with #137978. --- .../rustc_hir_analysis/src/check/check.rs | 4 +- .../src/check/compare_impl_item.rs | 32 +++--- compiler/rustc_hir_analysis/src/check/mod.rs | 10 +- .../rustc_hir_analysis/src/check/wfcheck.rs | 4 +- .../src/coherence/inherent_impls_overlap.rs | 8 +- .../src/collect/type_of/opaque.rs | 2 +- .../errors/wrong_number_of_generic_args.rs | 2 +- .../src/hir_ty_lowering/errors.rs | 38 ++++--- .../src/hir_ty_lowering/lint.rs | 2 +- .../rustc_hir_analysis/src/impl_wf_check.rs | 2 +- compiler/rustc_hir_typeck/src/expr.rs | 5 +- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 9 +- .../src/fn_ctxt/suggestions.rs | 11 +- compiler/rustc_hir_typeck/src/lib.rs | 2 +- compiler/rustc_hir_typeck/src/method/probe.rs | 25 ++--- .../rustc_hir_typeck/src/method/suggest.rs | 27 +++-- compiler/rustc_hir_typeck/src/op.rs | 2 +- compiler/rustc_metadata/src/rmeta/decoder.rs | 30 +++--- compiler/rustc_metadata/src/rmeta/encoder.rs | 2 +- compiler/rustc_middle/src/ty/assoc.rs | 101 ++++++++++++------ compiler/rustc_middle/src/ty/mod.rs | 5 +- compiler/rustc_middle/src/ty/print/pretty.rs | 6 +- .../src/check_undefined_transmutes.rs | 2 +- .../rustc_resolve/src/late/diagnostics.rs | 5 +- .../rustc_smir/src/rustc_smir/convert/ty.rs | 18 ++-- .../rustc_smir/src/stable_mir/mir/pretty.rs | 6 +- compiler/rustc_smir/src/stable_mir/ty.rs | 25 ++--- compiler/rustc_symbol_mangling/src/v0.rs | 2 +- .../src/error_reporting/infer/mod.rs | 6 +- .../error_reporting/infer/note_and_explain.rs | 2 +- .../src/error_reporting/infer/region.rs | 2 +- .../src/error_reporting/traits/ambiguity.rs | 2 +- .../src/error_reporting/traits/suggestions.rs | 8 +- .../src/traits/dyn_compatibility.rs | 42 ++++---- .../src/traits/project.rs | 9 +- compiler/rustc_ty_utils/src/assoc.rs | 23 ++-- src/librustdoc/clean/mod.rs | 12 +-- src/librustdoc/clean/types.rs | 2 +- .../clippy_lints/src/assigning_clones.rs | 4 +- .../src/methods/double_ended_iterator_last.rs | 2 +- .../clippy_lints/src/missing_trait_methods.rs | 2 +- .../clippy_lints/src/same_name_method.rs | 2 +- .../src/unconditional_recursion.rs | 2 +- 43 files changed, 276 insertions(+), 231 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 12c36e0f4c26..4f338c6a19e6 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -443,7 +443,7 @@ fn best_definition_site_of_opaque<'tcx>( let impl_def_id = tcx.local_parent(parent); for assoc in tcx.associated_items(impl_def_id).in_definition_order() { match assoc.kind { - ty::AssocKind::Const | ty::AssocKind::Fn { .. } => { + ty::AssocKind::Const { .. } | ty::AssocKind::Fn { .. } => { if let ControlFlow::Break(span) = locator.check(assoc.def_id.expect_local()) { return Some(span); @@ -952,7 +952,7 @@ fn check_impl_items_against_trait<'tcx>( .instantiate_identity(), ); } - ty::AssocKind::Const => {} + ty::AssocKind::Const { .. } => {} ty::AssocKind::Type { .. } => {} } } diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index d208aa71971e..af26d2ee00ca 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -45,7 +45,9 @@ pub(super) fn compare_impl_item( match impl_item.kind { ty::AssocKind::Fn { .. } => compare_impl_method(tcx, impl_item, trait_item, impl_trait_ref), ty::AssocKind::Type { .. } => compare_impl_ty(tcx, impl_item, trait_item, impl_trait_ref), - ty::AssocKind::Const => compare_impl_const(tcx, impl_item, trait_item, impl_trait_ref), + ty::AssocKind::Const { .. } => { + compare_impl_const(tcx, impl_item, trait_item, impl_trait_ref) + } } } @@ -654,7 +656,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( cause.span, E0053, "method `{}` has an incompatible return type for trait", - trait_m.name + trait_m.name() ); infcx.err_ctxt().note_type_err( &mut diag, @@ -1032,7 +1034,7 @@ fn report_trait_method_mismatch<'tcx>( impl_err_span, E0053, "method `{}` has an incompatible type for trait", - trait_m.name + trait_m.name() ); match &terr { TypeError::ArgumentMutability(0) | TypeError::ArgumentSorts(_, 0) @@ -1266,14 +1268,14 @@ fn compare_self_type<'tcx>( impl_m_span, E0185, "method `{}` has a `{}` declaration in the impl, but not in the trait", - trait_m.name, + trait_m.name(), self_descr ); err.span_label(impl_m_span, format!("`{self_descr}` used in impl")); if let Some(span) = tcx.hir_span_if_local(trait_m.def_id) { err.span_label(span, format!("trait method declared without `{self_descr}`")); } else { - err.note_trait_signature(trait_m.name, trait_m.signature(tcx)); + err.note_trait_signature(trait_m.name(), trait_m.signature(tcx)); } return Err(err.emit_unless(delay)); } @@ -1286,14 +1288,14 @@ fn compare_self_type<'tcx>( impl_m_span, E0186, "method `{}` has a `{}` declaration in the trait, but not in the impl", - trait_m.name, + trait_m.name(), self_descr ); err.span_label(impl_m_span, format!("expected `{self_descr}` in impl")); if let Some(span) = tcx.hir_span_if_local(trait_m.def_id) { err.span_label(span, format!("`{self_descr}` used in trait")); } else { - err.note_trait_signature(trait_m.name, trait_m.signature(tcx)); + err.note_trait_signature(trait_m.name(), trait_m.signature(tcx)); } return Err(err.emit_unless(delay)); @@ -1421,7 +1423,7 @@ fn compare_number_of_generics<'tcx>( "{} `{}` has {} {kind} parameter{} but its trait \ declaration has {} {kind} parameter{}", item_kind, - trait_.name, + trait_.name(), impl_count, pluralize!(impl_count), trait_count, @@ -1512,7 +1514,7 @@ fn compare_number_of_method_arguments<'tcx>( impl_span, E0050, "method `{}` has {} but the declaration in trait `{}` has {}", - trait_m.name, + trait_m.name(), potentially_plural_count(impl_number_args, "parameter"), tcx.def_path_str(trait_m.def_id), trait_number_args @@ -1527,7 +1529,7 @@ fn compare_number_of_method_arguments<'tcx>( ), ); } else { - err.note_trait_signature(trait_m.name, trait_m.signature(tcx)); + err.note_trait_signature(trait_m.name(), trait_m.signature(tcx)); } err.span_label( @@ -1581,7 +1583,7 @@ fn compare_synthetic_generics<'tcx>( impl_span, E0643, "method `{}` has incompatible signature for trait", - trait_m.name + trait_m.name() ); err.span_label(trait_span, "declaration in trait here"); if impl_synthetic { @@ -1741,7 +1743,7 @@ fn compare_generic_param_kinds<'tcx>( E0053, "{} `{}` has an incompatible generic parameter for trait `{}`", impl_item.descr(), - trait_item.name, + trait_item.name(), &tcx.def_path_str(tcx.parent(trait_item.def_id)) ); @@ -1877,7 +1879,7 @@ fn compare_const_predicate_entailment<'tcx>( cause.span, E0326, "implemented const `{}` has an incompatible type for trait", - trait_ct.name + trait_ct.name() ); let trait_c_span = trait_ct.def_id.as_local().map(|trait_ct_def_id| { @@ -2237,8 +2239,8 @@ fn param_env_with_gat_bounds<'tcx>( // bounds about themselves. let impl_tys_to_install = match impl_ty.kind { ty::AssocKind::Type { - opt_rpitit_info: - Some( + data: + ty::AssocTypeData::Rpitit( ty::ImplTraitInTraitData::Impl { fn_def_id } | ty::ImplTraitInTraitData::Trait { fn_def_id, .. }, ), diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index ec934b1f620d..5fbd771976bb 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -205,7 +205,7 @@ fn missing_items_err( let missing_items_msg = missing_items .clone() - .map(|trait_item| trait_item.name.to_string()) + .map(|trait_item| trait_item.name().to_string()) .collect::>() .join("`, `"); @@ -236,7 +236,7 @@ fn missing_items_err( let code = format!("{padding}{snippet}\n{padding}"); if let Some(span) = tcx.hir_span_if_local(trait_item.def_id) { missing_trait_item_label - .push(errors::MissingTraitItemLabel { span, item: trait_item.name }); + .push(errors::MissingTraitItemLabel { span, item: trait_item.name() }); missing_trait_item.push(errors::MissingTraitItemSuggestion { span: sugg_sp, code, @@ -504,9 +504,9 @@ fn suggestion_signature<'tcx>( tcx, tcx.predicates_of(assoc.def_id).instantiate_own(tcx, args), ); - format!("type {}{generics} = /* Type */{where_clauses};", assoc.name) + format!("type {}{generics} = /* Type */{where_clauses};", assoc.name()) } - ty::AssocKind::Const => { + ty::AssocKind::Const { name } => { let ty = tcx.type_of(assoc.def_id).instantiate_identity(); let val = tcx .infer_ctxt() @@ -514,7 +514,7 @@ fn suggestion_signature<'tcx>( .err_ctxt() .ty_kind_suggestion(tcx.param_env(assoc.def_id), ty) .unwrap_or_else(|| "value".to_string()); - format!("const {}: {} = {};", assoc.name, ty, val) + format!("const {}: {} = {};", name, ty, val) } } } diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index c6c370c4a846..33d5a86beb3b 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -474,7 +474,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, trait_def_id: LocalDefId) { gat_generics, ) } - ty::AssocKind::Const => None, + ty::AssocKind::Const { .. } => None, }; if let Some(item_required_bounds) = item_required_bounds { @@ -1076,7 +1076,7 @@ fn check_associated_item( }; match item.kind { - ty::AssocKind::Const => { + ty::AssocKind::Const { .. } => { let ty = tcx.type_of(item.def_id).instantiate_identity(); let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty); wfcx.register_wf_obligation(span, loc, ty.into()); diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs index cbfad1f6883e..242639125b19 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs @@ -51,7 +51,7 @@ impl<'tcx> InherentOverlapChecker<'tcx> { for &item1 in impl_items1.in_definition_order() { let collision = impl_items2 - .filter_by_name_unhygienic(item1.name) + .filter_by_name_unhygienic(item1.name()) .any(|&item2| self.compare_hygienically(item1, item2)); if collision { @@ -113,7 +113,7 @@ impl<'tcx> InherentOverlapChecker<'tcx> { let mut res = Ok(()); for &item1 in impl_items1.in_definition_order() { let collision = impl_items2 - .filter_by_name_unhygienic(item1.name) + .filter_by_name_unhygienic(item1.name()) .find(|&&item2| self.compare_hygienically(item1, item2)); if let Some(item2) = collision { @@ -230,11 +230,11 @@ impl<'tcx> InherentOverlapChecker<'tcx> { let mut ids = impl_items .in_definition_order() .filter_map(|item| { - let entry = connected_region_ids.entry(item.name); + let entry = connected_region_ids.entry(item.name()); if let IndexEntry::Occupied(e) = &entry { Some(*e.get()) } else { - idents_to_add.push(item.name); + idents_to_add.push(item.name()); None } }) diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs index 653adc6b3ba5..50e20a19edae 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs @@ -32,7 +32,7 @@ pub(super) fn find_opaque_ty_constraints_for_impl_trait_in_assoc_type( for &assoc_id in tcx.associated_item_def_ids(impl_def_id) { let assoc = tcx.associated_item(assoc_id); match assoc.kind { - ty::AssocKind::Const | ty::AssocKind::Fn { .. } => { + ty::AssocKind::Const { .. } | ty::AssocKind::Fn { .. } => { locator.check(assoc_id.expect_local()) } // Associated types don't have bodies, so they can't constrain hidden types diff --git a/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs index 70d60bfcf2d2..526ee30209c7 100644 --- a/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs +++ b/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs @@ -492,7 +492,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { .gen_args .constraints .iter() - .any(|constraint| constraint.ident.name == item.name) + .any(|constraint| constraint.ident.name == item.name()) }) .filter(|item| !item.is_impl_trait_in_trait()) .map(|item| self.tcx.item_ident(item.def_id).to_string()) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 4f8d5471b6f4..72f219bfeb80 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -168,7 +168,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let all_candidate_names: Vec<_> = all_candidates() .flat_map(|r| tcx.associated_items(r.def_id()).in_definition_order()) .filter_map(|item| { - (!item.is_impl_trait_in_trait() && item.as_tag() == assoc_tag).then_some(item.name) + if !item.is_impl_trait_in_trait() && item.as_tag() == assoc_tag { + item.opt_name() + } else { + None + } }) .collect(); @@ -200,7 +204,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .iter() .flat_map(|trait_def_id| tcx.associated_items(*trait_def_id).in_definition_order()) .filter_map(|item| { - (!item.is_impl_trait_in_trait() && item.as_tag() == assoc_tag).then_some(item.name) + (!item.is_impl_trait_in_trait() && item.as_tag() == assoc_tag) + .then_some(item.name()) }) .collect(); @@ -337,7 +342,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) -> ErrorGuaranteed { let tcx = self.tcx(); - let bound_on_assoc_const_label = if let ty::AssocKind::Const = assoc_item.kind + let bound_on_assoc_const_label = if let ty::AssocKind::Const { .. } = assoc_item.kind && let Some(constraint) = constraint && let hir::AssocItemConstraintKind::Bound { .. } = constraint.kind { @@ -761,7 +766,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // `issue-22560.rs`. let mut dyn_compatibility_violations = Ok(()); for (assoc_item, trait_ref) in &missing_assoc_types { - names.entry(trait_ref).or_default().push(assoc_item.name); + names.entry(trait_ref).or_default().push(assoc_item.name()); names_len += 1; let violations = @@ -852,16 +857,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let mut names: UnordMap<_, usize> = Default::default(); for (item, _) in &missing_assoc_types { types_count += 1; - *names.entry(item.name).or_insert(0) += 1; + *names.entry(item.name()).or_insert(0) += 1; } let mut dupes = false; let mut shadows = false; for (item, trait_ref) in &missing_assoc_types { - let prefix = if names[&item.name] > 1 { + let name = item.name(); + let prefix = if names[&name] > 1 { let trait_def_id = trait_ref.def_id(); dupes = true; format!("{}::", tcx.def_path_str(trait_def_id)) - } else if bound_names.get(&item.name).is_some_and(|x| *x != item) { + } else if bound_names.get(&name).is_some_and(|x| *x != item) { let trait_def_id = trait_ref.def_id(); shadows = true; format!("{}::", tcx.def_path_str(trait_def_id)) @@ -871,7 +877,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let mut is_shadowed = false; - if let Some(assoc_item) = bound_names.get(&item.name) + if let Some(assoc_item) = bound_names.get(&name) && *assoc_item != item { is_shadowed = true; @@ -880,17 +886,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { if assoc_item.def_id.is_local() { ", consider renaming it" } else { "" }; err.span_label( tcx.def_span(assoc_item.def_id), - format!("`{}{}` shadowed here{}", prefix, item.name, rename_message), + format!("`{}{}` shadowed here{}", prefix, name, rename_message), ); } let rename_message = if is_shadowed { ", consider renaming it" } else { "" }; if let Some(sp) = tcx.hir_span_if_local(item.def_id) { - err.span_label( - sp, - format!("`{}{}` defined here{}", prefix, item.name, rename_message), - ); + err.span_label(sp, format!("`{}{}` defined here{}", prefix, name, rename_message)); } } if potential_assoc_types.len() == missing_assoc_types.len() { @@ -903,7 +906,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { { let types: Vec<_> = missing_assoc_types .iter() - .map(|(item, _)| format!("{} = Type", item.name)) + .map(|(item, _)| format!("{} = Type", item.name())) .collect(); let code = if let Some(snippet) = snippet.strip_suffix('>') { // The user wrote `Trait<'a>` or similar and we don't have a type we can @@ -938,16 +941,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let mut names: FxIndexMap<_, usize> = FxIndexMap::default(); for (item, _) in &missing_assoc_types { types_count += 1; - *names.entry(item.name).or_insert(0) += 1; + *names.entry(item.name()).or_insert(0) += 1; } let mut label = vec![]; for (item, trait_ref) in &missing_assoc_types { - let postfix = if names[&item.name] > 1 { + let name = item.name(); + let postfix = if names[&name] > 1 { format!(" (from trait `{}`)", trait_ref.print_trait_sugared()) } else { String::new() }; - label.push(format!("`{}`{}", item.name, postfix)); + label.push(format!("`{}`{}", name, postfix)); } if !label.is_empty() { err.span_label( diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs index 49fd55b03a25..483b61add338 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs @@ -502,7 +502,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .associated_items(trait_def_id) .in_definition_order() .filter(|assoc| assoc.namespace() == Namespace::ValueNS) - .map(|cand| cand.name) + .map(|cand| cand.name()) .collect(); if let Some(typo) = find_best_match_for_name(&names, segment.ident.name, None) { diag.span_suggestion_verbose( diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs index 127ca846b9fe..cbdc501291bc 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs @@ -119,7 +119,7 @@ pub(crate) fn enforce_impl_lifetime_params_are_constrained( vec![] } } - ty::AssocKind::Fn { .. } | ty::AssocKind::Const => vec![], + ty::AssocKind::Fn { .. } | ty::AssocKind::Const { .. } => vec![], } }) .collect(); diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 56c205b6f879..532c5092a4e9 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -2601,8 +2601,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return None; } let input_len = fn_sig.inputs().skip_binder().len(); - let order = !item.name.as_str().starts_with("new"); - Some((order, item.name, input_len)) + let name = item.name(); + let order = !name.as_str().starts_with("new"); + Some((order, name, input_len)) }) .collect::>(); items.sort_by_key(|(order, _, _)| *order); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 3a0f3a4a5f0b..da0e8e362d66 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -683,10 +683,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .all(|(expected, found)| self.may_coerce(*expected, *found)) && fn_sig.inputs()[1..].len() == input_types.len() { + let assoc_name = assoc.name(); err.span_suggestion_verbose( call_name.span, - format!("you might have meant to use `{}`", assoc.name), - assoc.name, + format!("you might have meant to use `{}`", assoc_name), + assoc_name, Applicability::MaybeIncorrect, ); return; @@ -706,7 +707,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { tcx.def_span(assoc.def_id), format!( "there's is a method with similar name `{}`, but the arguments don't match", - assoc.name, + assoc.name(), ), ); return; @@ -718,7 +719,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { format!( "there's is a method with similar name `{}`, but their argument count \ doesn't match", - assoc.name, + assoc.name(), ), ); return; diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 912098c4e2d6..91eb1989864f 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -381,9 +381,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut suggestions = methods .iter() .filter_map(|conversion_method| { + let conversion_method_name = conversion_method.name(); let receiver_method_ident = expr.method_ident(); if let Some(method_ident) = receiver_method_ident - && method_ident.name == conversion_method.name + && method_ident.name == conversion_method_name { return None; // do not suggest code that is already there (#53348) } @@ -391,20 +392,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let method_call_list = [sym::to_vec, sym::to_string]; let mut sugg = if let ExprKind::MethodCall(receiver_method, ..) = expr.kind && receiver_method.ident.name == sym::clone - && method_call_list.contains(&conversion_method.name) + && method_call_list.contains(&conversion_method_name) // If receiver is `.clone()` and found type has one of those methods, // we guess that the user wants to convert from a slice type (`&[]` or `&str`) // to an owned type (`Vec` or `String`). These conversions clone internally, // so we remove the user's `clone` call. { - vec![(receiver_method.ident.span, conversion_method.name.to_string())] + vec![(receiver_method.ident.span, conversion_method_name.to_string())] } else if expr.precedence() < ExprPrecedence::Unambiguous { vec![ (expr.span.shrink_to_lo(), "(".to_string()), - (expr.span.shrink_to_hi(), format!(").{}()", conversion_method.name)), + (expr.span.shrink_to_hi(), format!(").{}()", conversion_method_name)), ] } else { - vec![(expr.span.shrink_to_hi(), format!(".{}()", conversion_method.name))] + vec![(expr.span.shrink_to_hi(), format!(".{}()", conversion_method_name))] }; let struct_pat_shorthand_field = self.tcx.hir_maybe_get_struct_pattern_shorthand_field(expr); diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 1d86ff14471a..0c6240d1f74b 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -266,7 +266,7 @@ fn infer_type_if_missing<'tcx>(fcx: &FnCtxt<'_, 'tcx>, node: Node<'tcx>) -> Opti let expected_type = if let Some(&hir::Ty { kind: hir::TyKind::Infer(()), span, .. }) = node.ty() { if let Some(item) = tcx.opt_associated_item(def_id.into()) - && let ty::AssocKind::Const = item.kind + && let ty::AssocKind::Const { .. } = item.kind && let ty::AssocItemContainer::Impl = item.container && let Some(trait_item_def_id) = item.trait_item_def_id { diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index c14b7823e370..ba4396a5ab35 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -1671,7 +1671,7 @@ impl<'tcx> Pick<'tcx> { /// Do not use for type checking. pub(crate) fn differs_from(&self, other: &Self) -> bool { let Self { - item: AssocItem { def_id, name: _, kind: _, container: _, trait_item_def_id: _ }, + item: AssocItem { def_id, kind: _, container: _, trait_item_def_id: _ }, kind: _, import_ids: _, autoderefs: _, @@ -1714,17 +1714,12 @@ impl<'tcx> Pick<'tcx> { tcx.def_path_str(self.item.def_id), )); } - (ty::AssocKind::Const, ty::AssocItemContainer::Trait) => { + (ty::AssocKind::Const { name }, ty::AssocItemContainer::Trait) => { let def_id = self.item.container_id(tcx); lint.span_suggestion( span, "use the fully qualified path to the associated const", - format!( - "<{} as {}>::{}", - self.self_ty, - tcx.def_path_str(def_id), - self.item.name - ), + format!("<{} as {}>::{}", self.self_ty, tcx.def_path_str(def_id), name), Applicability::MachineApplicable, ); } @@ -2213,7 +2208,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let best_name = { let names = applicable_close_candidates .iter() - .map(|cand| cand.name) + .map(|cand| cand.name()) .collect::>(); find_best_match_for_name_with_substrings( &names, @@ -2225,10 +2220,12 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { applicable_close_candidates .iter() .find(|cand| self.matches_by_doc_alias(cand.def_id)) - .map(|cand| cand.name) + .map(|cand| cand.name()) }); Ok(best_name.and_then(|best_name| { - applicable_close_candidates.into_iter().find(|method| method.name == best_name) + applicable_close_candidates + .into_iter() + .find(|method| method.name() == best_name) })) } }) @@ -2246,7 +2243,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { Mode::MethodCall => item.is_method(), Mode::Path => match item.kind { ty::AssocKind::Type { .. } => false, - ty::AssocKind::Fn { .. } | ty::AssocKind::Const => true, + ty::AssocKind::Fn { .. } | ty::AssocKind::Const { .. } => true, }, } // FIXME -- check for types that deref to `Self`, @@ -2320,7 +2317,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { fn is_relevant_kind_for_mode(&self, kind: ty::AssocKind) -> bool { match (self.mode, kind) { (Mode::MethodCall, ty::AssocKind::Fn { .. }) => true, - (Mode::Path, ty::AssocKind::Const | ty::AssocKind::Fn { .. }) => true, + (Mode::Path, ty::AssocKind::Const { .. } | ty::AssocKind::Fn { .. }) => true, _ => false, } } @@ -2402,7 +2399,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } match edit_distance_with_substrings( name.as_str(), - x.name.as_str(), + x.name().as_str(), max_dist, ) { Some(d) => d > 0, diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 962871ed2d11..6a9fd7cdd483 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1722,7 +1722,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // that had unsatisfied trait bounds if unsatisfied_predicates.is_empty() // ...or if we already suggested that name because of `rustc_confusable` annotation. - && Some(similar_candidate.name) != confusable_suggested + && Some(similar_candidate.name()) != confusable_suggested { self.find_likely_intended_associated_item( &mut err, @@ -1821,10 +1821,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let tcx = self.tcx; let def_kind = similar_candidate.as_def_kind(); let an = self.tcx.def_kind_descr_article(def_kind, similar_candidate.def_id); + let similar_candidate_name = similar_candidate.name(); let msg = format!( "there is {an} {} `{}` with a similar name", self.tcx.def_kind_descr(def_kind, similar_candidate.def_id), - similar_candidate.name, + similar_candidate_name, ); // Methods are defined within the context of a struct and their first parameter // is always `self`, which represents the instance of the struct the method is @@ -1843,7 +1844,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_suggestion_verbose( span, msg, - similar_candidate.name, + similar_candidate_name, Applicability::MaybeIncorrect, ); } else { @@ -1865,7 +1866,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_suggestion_verbose( span, msg, - similar_candidate.name, + similar_candidate_name, Applicability::MaybeIncorrect, ); } else { @@ -1878,7 +1879,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_suggestion_verbose( span, msg, - similar_candidate.name, + similar_candidate_name, Applicability::MaybeIncorrect, ); } else { @@ -1918,6 +1919,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { infer::FnCall, fn_sig, ); + let name = inherent_method.name(); if let Some(ref args) = call_args && fn_sig.inputs()[1..] .iter() @@ -1927,20 +1929,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { err.span_suggestion_verbose( item_name.span, - format!("you might have meant to use `{}`", inherent_method.name), - inherent_method.name, + format!("you might have meant to use `{}`", name), + name, Applicability::MaybeIncorrect, ); - return Some(inherent_method.name); + return Some(name); } else if let None = call_args { err.span_note( self.tcx.def_span(inherent_method.def_id), - format!( - "you might have meant to use method `{}`", - inherent_method.name, - ), + format!("you might have meant to use method `{}`", name), ); - return Some(inherent_method.name); + return Some(name); } } } @@ -2116,7 +2115,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Only assoc fn with no receivers and only if // they are resolvable .filter(|item| { - matches!(item.kind, ty::AssocKind::Fn { has_self: false }) + matches!(item.kind, ty::AssocKind::Fn { has_self: false, .. }) && self .probe_for_name( Mode::Path, diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index 93f77b8409f0..0e42a84ca32a 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -372,7 +372,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .associated_item_def_ids(def_id) .iter() .find(|item_def_id| { - self.tcx.associated_item(*item_def_id).name == sym::Output + self.tcx.associated_item(*item_def_id).name() == sym::Output }) .cloned() }); diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 3cbe09280f69..3c2245347f97 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1332,30 +1332,26 @@ impl<'a> CrateMetadataRef<'a> { } fn get_associated_item(self, id: DefIndex, sess: &'a Session) -> ty::AssocItem { - let name = if self.root.tables.opt_rpitit_info.get(self, id).is_some() { - kw::Empty - } else { - self.item_name(id) - }; let kind = match self.def_kind(id) { - DefKind::AssocConst => ty::AssocKind::Const, - DefKind::AssocFn => { - ty::AssocKind::Fn { has_self: self.get_fn_has_self_parameter(id, sess) } - } - DefKind::AssocTy => ty::AssocKind::Type { - opt_rpitit_info: self - .root - .tables - .opt_rpitit_info - .get(self, id) - .map(|d| d.decode(self)), + DefKind::AssocConst => ty::AssocKind::Const { name: self.item_name(id) }, + DefKind::AssocFn => ty::AssocKind::Fn { + name: self.item_name(id), + has_self: self.get_fn_has_self_parameter(id, sess), }, + DefKind::AssocTy => { + let data = if let Some(rpitit_info) = self.root.tables.opt_rpitit_info.get(self, id) + { + ty::AssocTypeData::Rpitit(rpitit_info.decode(self)) + } else { + ty::AssocTypeData::Normal(self.item_name(id)) + }; + ty::AssocKind::Type { data } + } _ => bug!("cannot get associated-item of `{:?}`", self.def_key(id)), }; let container = self.root.tables.assoc_container.get(self, id).unwrap(); ty::AssocItem { - name, kind, def_id: self.local_def_id(id), trait_item_def_id: self.get_trait_item_def_id(id), diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index b900100c3c01..177318bfe15e 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1706,7 +1706,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } } } - if let ty::AssocKind::Type { opt_rpitit_info: Some(rpitit_info) } = item.kind { + if let ty::AssocKind::Type { data: ty::AssocTypeData::Rpitit(rpitit_info) } = item.kind { record!(self.tables.opt_rpitit_info[def_id] <- rpitit_info); if matches!(rpitit_info, ty::ImplTraitInTraitData::Trait { .. }) { record_array!( diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs index 6138157d8362..0c44fd2758d5 100644 --- a/compiler/rustc_middle/src/ty/assoc.rs +++ b/compiler/rustc_middle/src/ty/assoc.rs @@ -18,7 +18,6 @@ pub enum AssocItemContainer { #[derive(Copy, Clone, Debug, PartialEq, HashStable, Eq, Hash, Encodable, Decodable)] pub struct AssocItem { pub def_id: DefId, - pub name: Symbol, pub kind: AssocKind, pub container: AssocItemContainer, @@ -28,8 +27,24 @@ pub struct AssocItem { } impl AssocItem { + // Gets the identifier, if it has one. + pub fn opt_name(&self) -> Option { + match self.kind { + ty::AssocKind::Type { data: AssocTypeData::Normal(name) } => Some(name), + ty::AssocKind::Type { data: AssocTypeData::Rpitit(_) } => None, + ty::AssocKind::Const { name } => Some(name), + ty::AssocKind::Fn { name, .. } => Some(name), + } + } + + // Gets the identifier name. Aborts if it lacks one, i.e. is an RPITIT + // associated type. + pub fn name(&self) -> Symbol { + self.opt_name().expect("name of non-Rpitit assoc item") + } + pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident { - Ident::new(self.name, tcx.def_ident_span(self.def_id).unwrap()) + Ident::new(self.name(), tcx.def_ident_span(self.def_id).unwrap()) } /// Gets the defaultness of the associated item. @@ -76,22 +91,18 @@ impl AssocItem { // regions just fine, showing `fn(&MyType)`. tcx.fn_sig(self.def_id).instantiate_identity().skip_binder().to_string() } - ty::AssocKind::Type { .. } => format!("type {};", self.name), - ty::AssocKind::Const => { - format!( - "const {}: {:?};", - self.name, - tcx.type_of(self.def_id).instantiate_identity() - ) + ty::AssocKind::Type { .. } => format!("type {};", self.name()), + ty::AssocKind::Const { name } => { + format!("const {}: {:?};", name, tcx.type_of(self.def_id).instantiate_identity()) } } } pub fn descr(&self) -> &'static str { match self.kind { - ty::AssocKind::Const => "associated const", - ty::AssocKind::Fn { has_self: true } => "method", - ty::AssocKind::Fn { has_self: false } => "associated function", + ty::AssocKind::Const { .. } => "associated const", + ty::AssocKind::Fn { has_self: true, .. } => "method", + ty::AssocKind::Fn { has_self: false, .. } => "associated function", ty::AssocKind::Type { .. } => "associated type", } } @@ -99,13 +110,13 @@ impl AssocItem { pub fn namespace(&self) -> Namespace { match self.kind { ty::AssocKind::Type { .. } => Namespace::TypeNS, - ty::AssocKind::Const | ty::AssocKind::Fn { .. } => Namespace::ValueNS, + ty::AssocKind::Const { .. } | ty::AssocKind::Fn { .. } => Namespace::ValueNS, } } pub fn as_def_kind(&self) -> DefKind { match self.kind { - AssocKind::Const => DefKind::AssocConst, + AssocKind::Const { .. } => DefKind::AssocConst, AssocKind::Fn { .. } => DefKind::AssocFn, AssocKind::Type { .. } => DefKind::AssocTy, } @@ -119,19 +130,19 @@ impl AssocItem { } pub fn is_method(&self) -> bool { - matches!(self.kind, ty::AssocKind::Fn { has_self: true }) + matches!(self.kind, ty::AssocKind::Fn { has_self: true, .. }) } pub fn as_tag(&self) -> AssocTag { match self.kind { - AssocKind::Const => AssocTag::Const, + AssocKind::Const { .. } => AssocTag::Const, AssocKind::Fn { .. } => AssocTag::Fn, AssocKind::Type { .. } => AssocTag::Type, } } pub fn is_impl_trait_in_trait(&self) -> bool { - matches!(self.kind, AssocKind::Type { opt_rpitit_info: Some(_) }) + matches!(self.kind, AssocKind::Type { data: AssocTypeData::Rpitit(_) }) } /// Returns true if: @@ -139,7 +150,7 @@ impl AssocItem { /// - If it is in a trait impl, the item from the original trait has this attribute, or /// - It is an inherent assoc const. pub fn is_type_const_capable(&self, tcx: TyCtxt<'_>) -> bool { - if self.kind != ty::AssocKind::Const { + if !matches!(self.kind, ty::AssocKind::Const { .. }) { return false; } @@ -153,26 +164,45 @@ impl AssocItem { } } +#[derive(Copy, Clone, PartialEq, Debug, HashStable, Eq, Hash, Encodable, Decodable)] +pub enum AssocTypeData { + Normal(Symbol), + /// The associated type comes from an RPITIT. It has no name, and the + /// `ImplTraitInTraitData` provides additional information about its + /// source. + Rpitit(ty::ImplTraitInTraitData), +} + #[derive(Copy, Clone, PartialEq, Debug, HashStable, Eq, Hash, Encodable, Decodable)] pub enum AssocKind { - Const, - Fn { - has_self: bool, - }, - Type { - /// `Some` if the associated type comes from an RPITIT. The - /// `ImplTraitInTraitData` provides additional information about its - /// source. - opt_rpitit_info: Option, - }, + Const { name: Symbol }, + Fn { name: Symbol, has_self: bool }, + Type { data: AssocTypeData }, +} + +impl AssocKind { + pub fn namespace(&self) -> Namespace { + match *self { + ty::AssocKind::Type { .. } => Namespace::TypeNS, + ty::AssocKind::Const { .. } | ty::AssocKind::Fn { .. } => Namespace::ValueNS, + } + } + + pub fn as_def_kind(&self) -> DefKind { + match self { + AssocKind::Const { .. } => DefKind::AssocConst, + AssocKind::Fn { .. } => DefKind::AssocFn, + AssocKind::Type { .. } => DefKind::AssocTy, + } + } } impl std::fmt::Display for AssocKind { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - AssocKind::Fn { has_self: true } => write!(f, "method"), - AssocKind::Fn { has_self: false } => write!(f, "associated function"), - AssocKind::Const => write!(f, "associated const"), + AssocKind::Fn { has_self: true, .. } => write!(f, "method"), + AssocKind::Fn { has_self: false, .. } => write!(f, "associated function"), + AssocKind::Const { .. } => write!(f, "associated const"), AssocKind::Type { .. } => write!(f, "associated type"), } } @@ -193,17 +223,17 @@ pub enum AssocTag { /// done only on items with the same name. #[derive(Debug, Clone, PartialEq, HashStable)] pub struct AssocItems { - items: SortedIndexMultiMap, + items: SortedIndexMultiMap, ty::AssocItem>, } impl AssocItems { /// Constructs an `AssociatedItems` map from a series of `ty::AssocItem`s in definition order. pub fn new(items_in_def_order: impl IntoIterator) -> Self { - let items = items_in_def_order.into_iter().map(|item| (item.name, item)).collect(); + let items = items_in_def_order.into_iter().map(|item| (item.opt_name(), item)).collect(); AssocItems { items } } - /// Returns a slice of associated items in the order they were defined. + /// Returns an iterator over associated items in the order they were defined. /// /// New code should avoid relying on definition order. If you need a particular associated item /// for a known trait, make that trait a lang item instead of indexing this array. @@ -220,7 +250,8 @@ impl AssocItems { &self, name: Symbol, ) -> impl '_ + Iterator { - self.items.get_by_key(name) + assert!(!name.is_empty()); + self.items.get_by_key(Some(name)) } /// Returns the associated item with the given identifier and `AssocKind`, if one exists. diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 395d2ec48142..1945538b1c2f 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1611,9 +1611,10 @@ impl<'tcx> TyCtxt<'tcx> { /// about where that RPITIT came from. pub fn opt_rpitit_info(self, def_id: DefId) -> Option { if let DefKind::AssocTy = self.def_kind(def_id) - && let AssocKind::Type { opt_rpitit_info } = self.associated_item(def_id).kind + && let AssocKind::Type { data: AssocTypeData::Rpitit(rpitit_info) } = + self.associated_item(def_id).kind { - opt_rpitit_info + Some(rpitit_info) } else { None } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 2f93197bcef1..d739218af5ee 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1214,7 +1214,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { && assoc .trait_container(tcx) .is_some_and(|def_id| tcx.is_lang_item(def_id, LangItem::Coroutine)) - && assoc.name == rustc_span::sym::Return + && assoc.opt_name() == Some(rustc_span::sym::Return) { if let ty::Coroutine(_, args) = args.type_at(0).kind() { let return_ty = args.as_coroutine().return_ty(); @@ -1237,7 +1237,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { p!(", "); } - p!(write("{} = ", tcx.associated_item(assoc_item_def_id).name)); + p!(write("{} = ", tcx.associated_item(assoc_item_def_id).name())); match term.unpack() { TermKind::Ty(ty) => p!(print(ty)), @@ -3291,7 +3291,7 @@ define_print! { } ty::ExistentialProjection<'tcx> { - let name = cx.tcx().associated_item(self.def_id).name; + let name = cx.tcx().associated_item(self.def_id).name(); // The args don't contain the self ty (as it has been erased) but the corresp. // generics do as the trait always has a self ty param. We need to offset. let args = &self.args[cx.tcx().generics_of(self.def_id).parent_count - 1..]; diff --git a/compiler/rustc_mir_transform/src/check_undefined_transmutes.rs b/compiler/rustc_mir_transform/src/check_undefined_transmutes.rs index ed3b1ae4f42f..daddb5dedbcf 100644 --- a/compiler/rustc_mir_transform/src/check_undefined_transmutes.rs +++ b/compiler/rustc_mir_transform/src/check_undefined_transmutes.rs @@ -42,7 +42,7 @@ impl<'a, 'tcx> UndefinedTransmutesChecker<'a, 'tcx> { if self.tcx.is_const_fn(def_id) || matches!( self.tcx.opt_associated_item(def_id), - Some(AssocItem { kind: AssocKind::Const, .. }) + Some(AssocItem { kind: AssocKind::Const { .. }, .. }) ) { let fn_sig = function.ty(self.body, self.tcx).fn_sig(self.tcx).skip_binder(); diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index ae81021e0bea..d4fe446cc9f7 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -2007,8 +2007,9 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { if def.did() != def_id { return None; } - let order = !item.name.as_str().starts_with("new"); - Some((order, item.name, input_len)) + let name = item.name(); + let order = !name.as_str().starts_with("new"); + Some((order, name, input_len)) }) .collect::>(); items.sort_by_key(|(order, _, _)| *order); diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index 55f698b8f211..a757329bcf2a 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -895,12 +895,19 @@ impl<'tcx> Stable<'tcx> for ty::AssocKind { type T = stable_mir::ty::AssocKind; fn stable(&self, tables: &mut Tables<'_>) -> Self::T { - use stable_mir::ty::AssocKind; + use stable_mir::ty::{AssocKind, AssocTypeData}; match *self { - ty::AssocKind::Const => AssocKind::Const, - ty::AssocKind::Fn { has_self } => AssocKind::Fn { has_self }, - ty::AssocKind::Type { opt_rpitit_info } => AssocKind::Type { - opt_rpitit_info: opt_rpitit_info.map(|rpitit| rpitit.stable(tables)), + ty::AssocKind::Const { name } => AssocKind::Const { name: name.to_string() }, + ty::AssocKind::Fn { name, has_self } => { + AssocKind::Fn { name: name.to_string(), has_self } + } + ty::AssocKind::Type { data } => AssocKind::Type { + data: match data { + ty::AssocTypeData::Normal(name) => AssocTypeData::Normal(name.to_string()), + ty::AssocTypeData::Rpitit(rpitit) => { + AssocTypeData::Rpitit(rpitit.stable(tables)) + } + }, }, } } @@ -924,7 +931,6 @@ impl<'tcx> Stable<'tcx> for ty::AssocItem { fn stable(&self, tables: &mut Tables<'_>) -> Self::T { stable_mir::ty::AssocItem { def_id: tables.assoc_def(self.def_id), - name: self.name.to_string(), kind: self.kind.stable(tables), container: self.container.stable(tables), trait_item_def_id: self.trait_item_def_id.map(|did| tables.assoc_def(did)), diff --git a/compiler/rustc_smir/src/stable_mir/mir/pretty.rs b/compiler/rustc_smir/src/stable_mir/mir/pretty.rs index 9fa97763907f..8a6be0cd37a0 100644 --- a/compiler/rustc_smir/src/stable_mir/mir/pretty.rs +++ b/compiler/rustc_smir/src/stable_mir/mir/pretty.rs @@ -22,9 +22,9 @@ impl Display for Ty { impl Display for AssocKind { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { - AssocKind::Fn { has_self: true } => write!(f, "method"), - AssocKind::Fn { has_self: false } => write!(f, "associated function"), - AssocKind::Const => write!(f, "associated const"), + AssocKind::Fn { has_self: true, .. } => write!(f, "method"), + AssocKind::Fn { has_self: false, .. } => write!(f, "associated function"), + AssocKind::Const { .. } => write!(f, "associated const"), AssocKind::Type { .. } => write!(f, "associated type"), } } diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs index 6eac0885d763..4b153007bd86 100644 --- a/compiler/rustc_smir/src/stable_mir/ty.rs +++ b/compiler/rustc_smir/src/stable_mir/ty.rs @@ -1578,7 +1578,6 @@ crate_def! { #[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct AssocItem { pub def_id: AssocDef, - pub name: Symbol, pub kind: AssocKind, pub container: AssocItemContainer, @@ -1587,18 +1586,20 @@ pub struct AssocItem { pub trait_item_def_id: Option, } +#[derive(Clone, PartialEq, Debug, Eq, Serialize)] +pub enum AssocTypeData { + Normal(Symbol), + /// The associated type comes from an RPITIT. It has no name, and the + /// `ImplTraitInTraitData` provides additional information about its + /// source. + Rpitit(ImplTraitInTraitData), +} + #[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub enum AssocKind { - Const, - Fn { - has_self: bool, - }, - Type { - /// `Some` if the associated type comes from an RPITIT. The - /// `ImplTraitInTraitData` provides additional information about its - /// source. - opt_rpitit_info: Option, - }, + Const { name: Symbol }, + Fn { name: Symbol, has_self: bool }, + Type { data: AssocTypeData }, } #[derive(Clone, Debug, Eq, PartialEq, Serialize)] @@ -1615,6 +1616,6 @@ pub enum ImplTraitInTraitData { impl AssocItem { pub fn is_impl_trait_in_trait(&self) -> bool { - matches!(self.kind, AssocKind::Type { opt_rpitit_info: Some(_) }) + matches!(self.kind, AssocKind::Type { data: AssocTypeData::Rpitit(_) }) } } diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index d28f10ba9e38..a4e1266e7643 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -615,7 +615,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { cx.print_def_path(trait_ref.def_id, trait_ref.args)?; } ty::ExistentialPredicate::Projection(projection) => { - let name = cx.tcx.associated_item(projection.def_id).name; + let name = cx.tcx.associated_item(projection.def_id).name(); cx.push("p"); cx.push_ident(name.as_str()); match projection.term.unpack() { diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index 1c71fe028d4d..fdd547448f00 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -2340,7 +2340,7 @@ impl<'tcx> ObligationCause<'tcx> { ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Type { .. }, .. } => { ObligationCauseFailureCode::TypeCompat { span, subdiags } } - ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Const, .. } => { + ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Const { .. }, .. } => { ObligationCauseFailureCode::ConstCompat { span, subdiags } } ObligationCauseCode::BlockTailExpression(.., hir::MatchSource::TryDesugar(_)) => { @@ -2404,7 +2404,7 @@ impl<'tcx> ObligationCause<'tcx> { ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Type { .. }, .. } => { "associated type is compatible with trait" } - ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Const, .. } => { + ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Const { .. }, .. } => { "const is compatible with trait" } ObligationCauseCode::MainFunctionType => "`main` function has the correct type", @@ -2428,7 +2428,7 @@ impl IntoDiagArg for ObligationCauseAsDiagArg<'_> { ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Type { .. }, .. } => { "type_compat" } - ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Const, .. } => { + ObligationCauseCode::CompareImplItem { kind: ty::AssocKind::Const { .. }, .. } => { "const_compat" } ObligationCauseCode::MainFunctionType => "fn_main_correct_type", diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs index 02f21b5465c6..be508c8cee13 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs @@ -783,7 +783,7 @@ fn foo(&self) -> Self::T { String::new() } .in_definition_order() .filter(|item| { item.is_fn() - && Some(item.name) != current_method_ident + && Some(item.name()) != current_method_ident && !tcx.is_doc_hidden(item.def_id) }) .filter_map(|item| { diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs index 49c6acedcfa4..df3cce880dd4 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -1017,7 +1017,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { infer::BoundRegion(_, br, infer::AssocTypeProjection(def_id)) => format!( " for lifetime parameter {}in trait containing associated type `{}`", br_string(br), - self.tcx.associated_item(def_id).name + self.tcx.associated_item(def_id).name() ), infer::RegionParameterDefinition(_, name) => { format!(" for lifetime parameter `{name}`") diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs index c4b0ca9cf8fc..54b50851b74d 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs @@ -348,7 +348,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { && let None = self.tainted_by_errors() { let (verb, noun) = match self.tcx.associated_item(item_id).kind { - ty::AssocKind::Const => ("refer to the", "constant"), + ty::AssocKind::Const { .. } => ("refer to the", "constant"), ty::AssocKind::Fn { .. } => ("call", "function"), // This is already covered by E0223, but this following single match // arm doesn't hurt here. diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 08b95b450583..7d95a7b3fed2 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -2112,7 +2112,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { trait_ref: DefId, ) { if let Some(assoc_item) = self.tcx.opt_associated_item(item_def_id) { - if let ty::AssocKind::Const | ty::AssocKind::Type { .. } = assoc_item.kind { + if let ty::AssocKind::Const { .. } | ty::AssocKind::Type { .. } = assoc_item.kind { err.note(format!( "{}s cannot be accessed directly on a `trait`, they can only be \ accessed through a specific `impl`", @@ -2121,7 +2121,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { err.span_suggestion( span, "use the fully qualified path to an implementation", - format!("::{}", self.tcx.def_path_str(trait_ref), assoc_item.name), + format!( + "::{}", + self.tcx.def_path_str(trait_ref), + assoc_item.name() + ), Applicability::HasPlaceholders, ); } diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index 1ef16f34702e..519394685a8e 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -298,31 +298,33 @@ pub fn dyn_compatibility_violations_for_assoc_item( match item.kind { // Associated consts are never dyn-compatible, as they can't have `where` bounds yet at all, // and associated const bounds in trait objects aren't a thing yet either. - ty::AssocKind::Const => { - vec![DynCompatibilityViolation::AssocConst(item.name, item.ident(tcx).span)] + ty::AssocKind::Const { name } => { + vec![DynCompatibilityViolation::AssocConst(name, item.ident(tcx).span)] } - ty::AssocKind::Fn { .. } => virtual_call_violations_for_method(tcx, trait_def_id, item) - .into_iter() - .map(|v| { - let node = tcx.hir_get_if_local(item.def_id); - // Get an accurate span depending on the violation. - let span = match (&v, node) { - (MethodViolationCode::ReferencesSelfInput(Some(span)), _) => *span, - (MethodViolationCode::UndispatchableReceiver(Some(span)), _) => *span, - (MethodViolationCode::ReferencesImplTraitInTrait(span), _) => *span, - (MethodViolationCode::ReferencesSelfOutput, Some(node)) => { - node.fn_decl().map_or(item.ident(tcx).span, |decl| decl.output.span()) - } - _ => item.ident(tcx).span, - }; + ty::AssocKind::Fn { name, .. } => { + virtual_call_violations_for_method(tcx, trait_def_id, item) + .into_iter() + .map(|v| { + let node = tcx.hir_get_if_local(item.def_id); + // Get an accurate span depending on the violation. + let span = match (&v, node) { + (MethodViolationCode::ReferencesSelfInput(Some(span)), _) => *span, + (MethodViolationCode::UndispatchableReceiver(Some(span)), _) => *span, + (MethodViolationCode::ReferencesImplTraitInTrait(span), _) => *span, + (MethodViolationCode::ReferencesSelfOutput, Some(node)) => { + node.fn_decl().map_or(item.ident(tcx).span, |decl| decl.output.span()) + } + _ => item.ident(tcx).span, + }; - DynCompatibilityViolation::Method(item.name, v, span) - }) - .collect(), + DynCompatibilityViolation::Method(name, v, span) + }) + .collect() + } // Associated types can only be dyn-compatible if they have `Self: Sized` bounds. ty::AssocKind::Type { .. } => { if !tcx.generics_of(item.def_id).is_own_empty() && !item.is_impl_trait_in_trait() { - vec![DynCompatibilityViolation::GAT(item.name, item.ident(tcx).span)] + vec![DynCompatibilityViolation::GAT(item.name(), item.ident(tcx).span)] } else { // We will permit associated types if they are explicitly mentioned in the trait object. // We can't check this here, as here we only check if it is guaranteed to not be possible. diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 83591219b14d..0dce504903ca 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1393,7 +1393,7 @@ fn confirm_future_candidate<'cx, 'tcx>( coroutine_sig, ); - debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id).name, sym::Output); + debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id).name(), sym::Output); let predicate = ty::ProjectionPredicate { projection_term: ty::AliasTerm::new_from_args( @@ -1439,7 +1439,7 @@ fn confirm_iterator_candidate<'cx, 'tcx>( gen_sig, ); - debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id).name, sym::Item); + debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id).name(), sym::Item); let predicate = ty::ProjectionPredicate { projection_term: ty::AliasTerm::new_from_args( @@ -1485,7 +1485,7 @@ fn confirm_async_iterator_candidate<'cx, 'tcx>( gen_sig, ); - debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id).name, sym::Item); + debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id).name(), sym::Item); let ty::Adt(_poll_adt, args) = *yield_ty.kind() else { bug!(); @@ -2005,7 +2005,8 @@ fn confirm_impl_candidate<'cx, 'tcx>( if !assoc_ty.item.defaultness(tcx).has_value() { debug!( "confirm_impl_candidate: no associated type {:?} for {:?}", - assoc_ty.item.name, obligation.predicate + assoc_ty.item.name(), + obligation.predicate ); if tcx.impl_self_is_guaranteed_unsized(impl_def_id) { // We treat this projection as rigid here, which is represented via diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index 2275fbb97923..6cb9fdc6f931 100644 --- a/compiler/rustc_ty_utils/src/assoc.rs +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -6,7 +6,6 @@ use rustc_hir::{self as hir, AmbigArg}; use rustc_middle::query::Providers; use rustc_middle::ty::{self, ImplTraitInTraitData, TyCtxt}; use rustc_middle::{bug, span_bug}; -use rustc_span::kw; pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { @@ -129,14 +128,14 @@ fn associated_item(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AssocItem { fn associated_item_from_trait_item_ref(trait_item_ref: &hir::TraitItemRef) -> ty::AssocItem { let owner_id = trait_item_ref.id.owner_id; + let name = trait_item_ref.ident.name; let kind = match trait_item_ref.kind { - hir::AssocItemKind::Const => ty::AssocKind::Const, - hir::AssocItemKind::Fn { has_self } => ty::AssocKind::Fn { has_self }, - hir::AssocItemKind::Type => ty::AssocKind::Type { opt_rpitit_info: None }, + hir::AssocItemKind::Const => ty::AssocKind::Const { name }, + hir::AssocItemKind::Fn { has_self } => ty::AssocKind::Fn { name, has_self }, + hir::AssocItemKind::Type => ty::AssocKind::Type { data: ty::AssocTypeData::Normal(name) }, }; ty::AssocItem { - name: trait_item_ref.ident.name, kind, def_id: owner_id.to_def_id(), trait_item_def_id: Some(owner_id.to_def_id()), @@ -146,14 +145,14 @@ fn associated_item_from_trait_item_ref(trait_item_ref: &hir::TraitItemRef) -> ty fn associated_item_from_impl_item_ref(impl_item_ref: &hir::ImplItemRef) -> ty::AssocItem { let def_id = impl_item_ref.id.owner_id; + let name = impl_item_ref.ident.name; let kind = match impl_item_ref.kind { - hir::AssocItemKind::Const => ty::AssocKind::Const, - hir::AssocItemKind::Fn { has_self } => ty::AssocKind::Fn { has_self }, - hir::AssocItemKind::Type => ty::AssocKind::Type { opt_rpitit_info: None }, + hir::AssocItemKind::Const => ty::AssocKind::Const { name }, + hir::AssocItemKind::Fn { has_self } => ty::AssocKind::Fn { name, has_self }, + hir::AssocItemKind::Type => ty::AssocKind::Type { data: ty::AssocTypeData::Normal(name) }, }; ty::AssocItem { - name: impl_item_ref.ident.name, kind, def_id: def_id.to_def_id(), trait_item_def_id: impl_item_ref.trait_item_def_id, @@ -260,9 +259,8 @@ fn associated_type_for_impl_trait_in_trait( trait_assoc_ty.def_ident_span(Some(span)); trait_assoc_ty.associated_item(ty::AssocItem { - name: kw::Empty, kind: ty::AssocKind::Type { - opt_rpitit_info: Some(ImplTraitInTraitData::Trait { + data: ty::AssocTypeData::Rpitit(ImplTraitInTraitData::Trait { fn_def_id: fn_def_id.to_def_id(), opaque_def_id: opaque_ty_def_id.to_def_id(), }), @@ -313,9 +311,8 @@ fn associated_type_for_impl_trait_in_impl( impl_assoc_ty.def_ident_span(Some(span)); impl_assoc_ty.associated_item(ty::AssocItem { - name: kw::Empty, kind: ty::AssocKind::Type { - opt_rpitit_info: Some(ImplTraitInTraitData::Impl { + data: ty::AssocTypeData::Rpitit(ImplTraitInTraitData::Impl { fn_def_id: impl_fn_def_id.to_def_id(), }), }, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 74dbc7d06001..2a95acc622ea 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -521,7 +521,7 @@ fn projection_to_path_segment<'tcx>( let item = cx.tcx.associated_item(def_id); let generics = cx.tcx.generics_of(def_id); PathSegment { - name: item.name, + name: item.name(), args: GenericArgs::AngleBracketed { args: clean_middle_generic_args( cx, @@ -1340,7 +1340,7 @@ pub(crate) fn clean_impl_item<'tcx>( pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocContext<'_>) -> Item { let tcx = cx.tcx; let kind = match assoc_item.kind { - ty::AssocKind::Const => { + ty::AssocKind::Const { .. } => { let ty = clean_middle_ty( ty::Binder::dummy(tcx.type_of(assoc_item.def_id).instantiate_identity()), cx, @@ -1374,7 +1374,7 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo } } } - ty::AssocKind::Fn { has_self } => { + ty::AssocKind::Fn { has_self, .. } => { let mut item = inline::build_function(cx, assoc_item.def_id); if has_self { @@ -1413,7 +1413,7 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo } } ty::AssocKind::Type { .. } => { - let my_name = assoc_item.name; + let my_name = assoc_item.name(); fn param_eq_arg(param: &GenericParamDef, arg: &GenericArg) -> bool { match (¶m.kind, arg) { @@ -1554,7 +1554,7 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo } }; - Item::from_def_id_and_parts(assoc_item.def_id, Some(assoc_item.name), kind, cx) + Item::from_def_id_and_parts(assoc_item.def_id, Some(assoc_item.name()), kind, cx) } fn first_non_private_clean_path<'tcx>( @@ -2223,7 +2223,7 @@ pub(crate) fn clean_middle_ty<'tcx>( Type::QPath(Box::new(QPathData { assoc: PathSegment { - name: cx.tcx.associated_item(def_id).name, + name: cx.tcx.associated_item(def_id).name(), args: GenericArgs::AngleBracketed { args: clean_middle_generic_args( cx, diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 06e75fe1764e..7786b216112b 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -2504,7 +2504,7 @@ impl Impl { self.trait_ .as_ref() .map(|t| t.def_id()) - .map(|did| tcx.provided_trait_methods(did).map(|meth| meth.name).collect()) + .map(|did| tcx.provided_trait_methods(did).map(|meth| meth.name()).collect()) .unwrap_or_default() } diff --git a/src/tools/clippy/clippy_lints/src/assigning_clones.rs b/src/tools/clippy/clippy_lints/src/assigning_clones.rs index ab34af7c3174..e5439a6d401b 100644 --- a/src/tools/clippy/clippy_lints/src/assigning_clones.rs +++ b/src/tools/clippy/clippy_lints/src/assigning_clones.rs @@ -111,8 +111,8 @@ impl<'tcx> LateLintPass<'tcx> for AssigningClones { // Only suggest if `clone_from`/`clone_into` is explicitly implemented && resolved_assoc_items.in_definition_order().any(|assoc| match which_trait { - CloneTrait::Clone => assoc.name == sym::clone_from, - CloneTrait::ToOwned => assoc.name.as_str() == "clone_into", + CloneTrait::Clone => assoc.name() == sym::clone_from, + CloneTrait::ToOwned => assoc.name().as_str() == "clone_into", } ) && !clone_source_borrows_from_dest(cx, lhs, rhs.span) diff --git a/src/tools/clippy/clippy_lints/src/methods/double_ended_iterator_last.rs b/src/tools/clippy/clippy_lints/src/methods/double_ended_iterator_last.rs index e82211bbf3ef..b5adc69e9a79 100644 --- a/src/tools/clippy/clippy_lints/src/methods/double_ended_iterator_last.rs +++ b/src/tools/clippy/clippy_lints/src/methods/double_ended_iterator_last.rs @@ -24,7 +24,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &'_ Expr<'_>, self_expr: &'_ Exp && let Ok(Some(fn_def)) = Instance::try_resolve(cx.tcx, cx.typing_env(), id, args) // find the provided definition of Iterator::last && let Some(item) = cx.tcx.get_diagnostic_item(sym::Iterator) - && let Some(last_def) = cx.tcx.provided_trait_methods(item).find(|m| m.name.as_str() == "last") + && let Some(last_def) = cx.tcx.provided_trait_methods(item).find(|m| m.name().as_str() == "last") // if the resolved method is the same as the provided definition && fn_def.def_id() == last_def.def_id { diff --git a/src/tools/clippy/clippy_lints/src/missing_trait_methods.rs b/src/tools/clippy/clippy_lints/src/missing_trait_methods.rs index 7ee746365d10..e266c36b6e73 100644 --- a/src/tools/clippy/clippy_lints/src/missing_trait_methods.rs +++ b/src/tools/clippy/clippy_lints/src/missing_trait_methods.rs @@ -81,7 +81,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingTraitMethods { cx, MISSING_TRAIT_METHODS, cx.tcx.def_span(item.owner_id), - format!("missing trait method provided by default: `{}`", assoc.name), + format!("missing trait method provided by default: `{}`", assoc.name()), |diag| { diag.span_help(cx.tcx.def_span(assoc.def_id), "implement the method"); }, diff --git a/src/tools/clippy/clippy_lints/src/same_name_method.rs b/src/tools/clippy/clippy_lints/src/same_name_method.rs index ae677e110af2..33815cc3bac1 100644 --- a/src/tools/clippy/clippy_lints/src/same_name_method.rs +++ b/src/tools/clippy/clippy_lints/src/same_name_method.rs @@ -85,7 +85,7 @@ impl<'tcx> LateLintPass<'tcx> for SameNameMethod { .associated_items(did) .in_definition_order() .filter(|assoc_item| assoc_item.is_fn()) - .map(|assoc_item| assoc_item.name) + .map(|assoc_item| assoc_item.name()) .collect() } else { BTreeSet::new() diff --git a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs index 2104eb302ab8..0c17cc5d8f66 100644 --- a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs +++ b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs @@ -322,7 +322,7 @@ impl UnconditionalRecursion { .in_definition_order() // We're not interested in foreign implementations of the `Default` trait. .find(|item| { - item.is_fn() && item.def_id.is_local() && item.name == kw::Default + item.is_fn() && item.def_id.is_local() && item.name() == kw::Default }) && let Some(body_node) = cx.tcx.hir_get_if_local(assoc_item.def_id) && let Some(body_id) = body_node.body_id() From c2712bcd2d8586a0c35f0d66a221f87aee3f6884 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 11 Mar 2025 17:36:27 -0700 Subject: [PATCH 457/606] ci: add runners for vanilla LLVM 20 Ubuntu 25.04 has `llvm-20` packages that we can start testing with. The `Dockerfile` is otherwise the same as the `llvm-18`/`19` runners. --- .../host-x86_64/x86_64-gnu-llvm-20/Dockerfile | 69 +++++++++++++++++++ src/ci/github-actions/jobs.yml | 25 +++++++ 2 files changed, 94 insertions(+) create mode 100644 src/ci/docker/host-x86_64/x86_64-gnu-llvm-20/Dockerfile diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-20/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-20/Dockerfile new file mode 100644 index 000000000000..408b87125e0c --- /dev/null +++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-20/Dockerfile @@ -0,0 +1,69 @@ +FROM ubuntu:25.04 + +ARG DEBIAN_FRONTEND=noninteractive + +RUN apt-get update && apt-get install -y --no-install-recommends \ + bzip2 \ + g++ \ + gcc-multilib \ + make \ + ninja-build \ + file \ + curl \ + ca-certificates \ + python3 \ + git \ + cmake \ + sudo \ + gdb \ + llvm-20-tools \ + llvm-20-dev \ + libedit-dev \ + libssl-dev \ + pkg-config \ + zlib1g-dev \ + xz-utils \ + nodejs \ + mingw-w64 \ + # libgccjit dependencies + flex \ + libmpfr-dev \ + libgmp-dev \ + libmpc3 \ + libmpc-dev \ + && rm -rf /var/lib/apt/lists/* + +# Install powershell (universal package) so we can test x.ps1 on Linux +# FIXME: need a "universal" version that supports libicu74, but for now it still works to ignore that dep. +RUN curl -sL "https://github.com/PowerShell/PowerShell/releases/download/v7.3.1/powershell_7.3.1-1.deb_amd64.deb" > powershell.deb && \ + dpkg --ignore-depends=libicu72 -i powershell.deb && \ + rm -f powershell.deb + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh + +# We are disabling CI LLVM since this builder is intentionally using a host +# LLVM, rather than the typical src/llvm-project LLVM. +ENV NO_DOWNLOAD_CI_LLVM 1 +ENV EXTERNAL_LLVM 1 + +# Using llvm-link-shared due to libffi issues -- see #34486 +ENV RUST_CONFIGURE_ARGS \ + --build=x86_64-unknown-linux-gnu \ + --llvm-root=/usr/lib/llvm-20 \ + --enable-llvm-link-shared \ + --set rust.randomize-layout=true \ + --set rust.thin-lto-import-instr-limit=10 + +COPY scripts/shared.sh /scripts/ + +ARG SCRIPT_ARG + +COPY scripts/add_dummy_commit.sh /tmp/ +COPY scripts/x86_64-gnu-llvm.sh /tmp/ +COPY scripts/x86_64-gnu-llvm2.sh /tmp/ +COPY scripts/x86_64-gnu-llvm3.sh /tmp/ +COPY scripts/stage_2_test_set1.sh /tmp/ +COPY scripts/stage_2_test_set2.sh /tmp/ + +ENV SCRIPT "/tmp/add_dummy_commit.sh && /tmp/${SCRIPT_ARG}" diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index fbda749b6a2a..fd4650ba2853 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -304,6 +304,31 @@ auto: - name: x86_64-gnu-distcheck <<: *job-linux-8c + # The x86_64-gnu-llvm-20 job is split into multiple jobs to run tests in parallel. + # x86_64-gnu-llvm-20-1 skips tests that run in x86_64-gnu-llvm-20-{2,3}. + - name: x86_64-gnu-llvm-20-1 + env: + RUST_BACKTRACE: 1 + IMAGE: x86_64-gnu-llvm-20 + DOCKER_SCRIPT: stage_2_test_set1.sh + <<: *job-linux-4c + + # Skip tests that run in x86_64-gnu-llvm-20-{1,3} + - name: x86_64-gnu-llvm-20-2 + env: + RUST_BACKTRACE: 1 + IMAGE: x86_64-gnu-llvm-20 + DOCKER_SCRIPT: x86_64-gnu-llvm2.sh + <<: *job-linux-4c + + # Skip tests that run in x86_64-gnu-llvm-20-{1,2} + - name: x86_64-gnu-llvm-20-3 + env: + RUST_BACKTRACE: 1 + IMAGE: x86_64-gnu-llvm-20 + DOCKER_SCRIPT: x86_64-gnu-llvm3.sh + <<: *job-linux-4c + # The x86_64-gnu-llvm-19 job is split into multiple jobs to run tests in parallel. # x86_64-gnu-llvm-19-1 skips tests that run in x86_64-gnu-llvm-19-{2,3}. - name: x86_64-gnu-llvm-19-1 From 9676d4aeb7d918179f4b5d39e10ad360ec5b2577 Mon Sep 17 00:00:00 2001 From: binarycat Date: Tue, 8 Apr 2025 14:58:28 -0500 Subject: [PATCH 458/606] std: add Output::exit_ok approved in ACP https://github.com/rust-lang/libs-team/issues/554 --- library/std/src/process.rs | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 3b765a9537bc..4562741e31cc 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -1286,6 +1286,40 @@ pub struct Output { pub stderr: Vec, } +impl Output { + /// Returns an error if a nonzero exit status was received. + /// + /// If the [`Command`] exited successfully, + /// `self` is returned. + /// + /// This is equivalent to calling [`exit_ok`](ExitStatus::exit_ok) + /// on [`Output.status`](Output::status). + /// + /// Note that this will throw away the [`Output::stderr`] field in the error case. + /// If the child process outputs useful informantion to stderr, you can: + /// * Use `cmd.stderr(Stdio::inherit())` to forward the + /// stderr child process to the parent's stderr, + /// usually printing it to console where the user can see it. + /// This is usually correct for command-line applications. + /// * Capture `stderr` using a custom error type. + /// This is usually correct for libraries. + /// + /// # Examples + /// + /// ``` + /// #![feature(exit_status_error)] + /// # #[cfg(unix)] { + /// use std::process::Command; + /// assert!(Command::new("false").output().unwrap().exit_ok().is_err()); + /// # } + /// ``` + #[unstable(feature = "exit_status_error", issue = "84908")] + pub fn exit_ok(self) -> Result { + self.status.exit_ok()?; + Ok(self) + } +} + // If either stderr or stdout are valid utf8 strings it prints the valid // strings, otherwise it prints the byte sequence instead #[stable(feature = "process_output_debug", since = "1.7.0")] From f8edc831caa53cd08879f93dcf11b6e6daf5d1a5 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 15 Apr 2025 10:05:20 +1000 Subject: [PATCH 459/606] Pretty-print `PatKind::Missing` as `_`. Printing "no pattern" as `_` isn't ideal, but better than crashing, and HIR pretty-printing already has plenty of imperfections. The added `f2` and `f6` examples are ones that triggered the crash. Note that some of the added examples are printed badly, e.g. `fn(, ...)`. The next commit will fix those. Fixes #139633. --- compiler/rustc_hir_pretty/src/lib.rs | 7 +++--- tests/pretty/hir-fn-variadic.pp | 36 ++++++++++++++++++++++++++++ tests/pretty/hir-fn-variadic.rs | 16 +++++++++++++ 3 files changed, 56 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index e5ab317685f9..9cae080aeb34 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1871,10 +1871,11 @@ impl<'a> State<'a> { fn print_pat(&mut self, pat: &hir::Pat<'_>) { self.maybe_print_comment(pat.span.lo()); self.ann.pre(self, AnnNode::Pat(pat)); - // Pat isn't normalized, but the beauty of it - // is that it doesn't matter + // Pat isn't normalized, but the beauty of it is that it doesn't matter. match pat.kind { - PatKind::Missing => unreachable!(), + // Printing `_` isn't ideal for a missing pattern, but it's easy and good enough. + // E.g. `fn(u32)` gets printed as `fn(_: u32)`. + PatKind::Missing => self.word("_"), PatKind::Wild => self.word("_"), PatKind::Never => self.word("!"), PatKind::Binding(BindingMode(by_ref, mutbl), _, ident, sub) => { diff --git a/tests/pretty/hir-fn-variadic.pp b/tests/pretty/hir-fn-variadic.pp index dfbaff696440..136e8b44ec20 100644 --- a/tests/pretty/hir-fn-variadic.pp +++ b/tests/pretty/hir-fn-variadic.pp @@ -13,3 +13,39 @@ extern "C" { } unsafe extern "C" fn bar(_: i32, mut va2: ...) -> usize { va2.arg::() } + +fn main() { + fn g1(_: extern "C" fn(_: u8, va: ...)) { } + fn g2(_: extern "C" fn(_: u8, ...)) { } + fn g3(_: extern "C" fn(u8, va: ...)) { } + fn g4(_: extern "C" fn(u8, ...)) { } + + fn g5(_: extern "C" fn(, va: ...)) { } + fn g6(_: extern "C" fn(, ...)) { } + + { + let _ = + { + unsafe extern "C" fn f1(_: u8, va: ...) { } + }; + }; + { + let _ = + { + unsafe extern "C" fn f2(_: u8, _: ...) { } + }; + }; + + { + let _ = + { + unsafe extern "C" fn f5(, va: ...) { } + }; + }; + { + let _ = + { + unsafe extern "C" fn f6(, _: ...) { } + }; + }; +} diff --git a/tests/pretty/hir-fn-variadic.rs b/tests/pretty/hir-fn-variadic.rs index 3d3f7ee18315..99aa402c480b 100644 --- a/tests/pretty/hir-fn-variadic.rs +++ b/tests/pretty/hir-fn-variadic.rs @@ -11,3 +11,19 @@ extern "C" { pub unsafe extern "C" fn bar(_: i32, mut va2: ...) -> usize { va2.arg::() } + +fn main() { + fn g1(_: extern "C" fn(_: u8, va: ...)) {} + fn g2(_: extern "C" fn(_: u8, ...)) {} + fn g3(_: extern "C" fn(u8, va: ...)) {} + fn g4(_: extern "C" fn(u8, ...)) {} + + fn g5(_: extern "C" fn(va: ...)) {} + fn g6(_: extern "C" fn(...)) {} + + _ = { unsafe extern "C" fn f1(_: u8, va: ...) {} }; + _ = { unsafe extern "C" fn f2(_: u8, ...) {} }; + + _ = { unsafe extern "C" fn f5(va: ...) {} }; + _ = { unsafe extern "C" fn f6(...) {} }; +} From 16670e167664e8ba7f2c1dcd6654988b37b4478e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 15 Apr 2025 10:17:32 +1000 Subject: [PATCH 460/606] Fix HIR pretty-printing of fns with just a variadic arg. Avoid the extraneous comma. --- compiler/rustc_hir_pretty/src/lib.rs | 4 +++- tests/pretty/hir-fn-variadic.pp | 8 ++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 9cae080aeb34..ff4385c3bcce 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -2165,7 +2165,9 @@ impl<'a> State<'a> { s.end(); }); if decl.c_variadic { - self.word(", "); + if !decl.inputs.is_empty() { + self.word(", "); + } print_arg(self, None); self.word("..."); } diff --git a/tests/pretty/hir-fn-variadic.pp b/tests/pretty/hir-fn-variadic.pp index 136e8b44ec20..b6bc8e95127f 100644 --- a/tests/pretty/hir-fn-variadic.pp +++ b/tests/pretty/hir-fn-variadic.pp @@ -20,8 +20,8 @@ fn main() { fn g3(_: extern "C" fn(u8, va: ...)) { } fn g4(_: extern "C" fn(u8, ...)) { } - fn g5(_: extern "C" fn(, va: ...)) { } - fn g6(_: extern "C" fn(, ...)) { } + fn g5(_: extern "C" fn(va: ...)) { } + fn g6(_: extern "C" fn(...)) { } { let _ = @@ -39,13 +39,13 @@ fn main() { { let _ = { - unsafe extern "C" fn f5(, va: ...) { } + unsafe extern "C" fn f5(va: ...) { } }; }; { let _ = { - unsafe extern "C" fn f6(, _: ...) { } + unsafe extern "C" fn f6(_: ...) { } }; }; } From 1376810d44d62dc7e8146f988e41aa2a9f641cf8 Mon Sep 17 00:00:00 2001 From: Glyn Normington Date: Tue, 15 Apr 2025 02:34:32 +0100 Subject: [PATCH 461/606] Basic tests of MPMC receiver cloning Ref: https://github.com/rust-lang/rust/issues/126840#issuecomment-2802321146 --- library/std/tests/sync/mpmc.rs | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/library/std/tests/sync/mpmc.rs b/library/std/tests/sync/mpmc.rs index 81b92297f76a..78abcb3bcbe1 100644 --- a/library/std/tests/sync/mpmc.rs +++ b/library/std/tests/sync/mpmc.rs @@ -63,6 +63,24 @@ fn smoke_port_gone() { assert!(tx.send(1).is_err()); } +#[test] +fn smoke_receiver_clone() { + let (tx, rx) = channel::(); + let rx2 = rx.clone(); + drop(rx); + tx.send(1).unwrap(); + assert_eq!(rx2.recv().unwrap(), 1); +} + +#[test] +fn smoke_receiver_clone_port_gone() { + let (tx, rx) = channel::(); + let rx2 = rx.clone(); + drop(rx); + drop(rx2); + assert!(tx.send(1).is_err()); +} + #[test] fn smoke_shared_port_gone() { let (tx, rx) = channel::(); @@ -124,6 +142,18 @@ fn chan_gone_concurrent() { while rx.recv().is_ok() {} } +#[test] +fn receiver_cloning() { + let (tx, rx) = channel::(); + let rx2 = rx.clone(); + + tx.send(1).unwrap(); + tx.send(2).unwrap(); + + assert_eq!(rx2.recv(), Ok(1)); + assert_eq!(rx.recv(), Ok(2)); +} + #[test] fn stress() { let count = if cfg!(miri) { 100 } else { 10000 }; From e53f2a01cea46bd7f9181e76353bde190255ea20 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 15 Apr 2025 12:26:37 +1000 Subject: [PATCH 462/606] Remove some `kw::Empty` uses in rustdoc. Some `unwrap` uses here, but they are on paths involving item kinds that are known to have an identifier. --- src/librustdoc/clean/mod.rs | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 45a915719e9f..736dd3a1d865 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -117,7 +117,7 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext< hir::ItemKind::Use(path, kind) => { let hir::UsePath { segments, span, .. } = *path; let path = hir::Path { segments, res: *res, span }; - clean_use_statement_inner(import, name, &path, kind, cx, &mut Default::default()) + clean_use_statement_inner(import, Some(name), &path, kind, cx, &mut Default::default()) } _ => unreachable!(), } @@ -125,8 +125,7 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext< items.extend(doc.items.values().flat_map(|(item, renamed, _)| { // Now we actually lower the imports, skipping everything else. if let hir::ItemKind::Use(path, hir::UseKind::Glob) = item.kind { - let name = renamed.unwrap_or(kw::Empty); // using kw::Empty is a bit of a hack - clean_use_statement(item, name, path, hir::UseKind::Glob, cx, &mut inserted) + clean_use_statement(item, *renamed, path, hir::UseKind::Glob, cx, &mut inserted) } else { // skip everything else Vec::new() @@ -2792,10 +2791,11 @@ fn clean_maybe_renamed_item<'tcx>( use hir::ItemKind; let def_id = item.owner_id.to_def_id(); - let mut name = renamed.unwrap_or_else(|| { - // FIXME: using kw::Empty is a bit of a hack - cx.tcx.hir_opt_name(item.hir_id()).unwrap_or(kw::Empty) - }); + let mut name = if renamed.is_some() { + renamed + } else { + cx.tcx.hir_opt_name(item.hir_id()) + }; cx.with_param_env(def_id, |cx| { let kind = match item.kind { @@ -2836,7 +2836,7 @@ fn clean_maybe_renamed_item<'tcx>( item_type: Some(type_), })), item.owner_id.def_id.to_def_id(), - name, + name.unwrap(), import_id, renamed, )); @@ -2861,13 +2861,15 @@ fn clean_maybe_renamed_item<'tcx>( }), ItemKind::Impl(impl_) => return clean_impl(impl_, item.owner_id.def_id, cx), ItemKind::Macro(_, macro_def, MacroKind::Bang) => MacroItem(Macro { - source: display_macro_source(cx, name, macro_def), + source: display_macro_source(cx, name.unwrap(), macro_def), macro_rules: macro_def.macro_rules, }), - ItemKind::Macro(_, _, macro_kind) => clean_proc_macro(item, &mut name, macro_kind, cx), + ItemKind::Macro(_, _, macro_kind) => { + clean_proc_macro(item, name.as_mut().unwrap(), macro_kind, cx) + } // proc macros can have a name set by attributes ItemKind::Fn { ref sig, generics, body: body_id, .. } => { - clean_fn_or_proc_macro(item, sig, generics, body_id, &mut name, cx) + clean_fn_or_proc_macro(item, sig, generics, body_id, name.as_mut().unwrap(), cx) } ItemKind::Trait(_, _, _, generics, bounds, item_ids) => { let items = item_ids @@ -2883,7 +2885,7 @@ fn clean_maybe_renamed_item<'tcx>( })) } ItemKind::ExternCrate(orig_name, _) => { - return clean_extern_crate(item, name, orig_name, cx); + return clean_extern_crate(item, name.unwrap(), orig_name, cx); } ItemKind::Use(path, kind) => { return clean_use_statement(item, name, path, kind, cx, &mut FxHashSet::default()); @@ -2895,7 +2897,7 @@ fn clean_maybe_renamed_item<'tcx>( cx, kind, item.owner_id.def_id.to_def_id(), - name, + name.unwrap(), import_id, renamed, )] @@ -3006,7 +3008,7 @@ fn clean_extern_crate<'tcx>( fn clean_use_statement<'tcx>( import: &hir::Item<'tcx>, - name: Symbol, + name: Option, path: &hir::UsePath<'tcx>, kind: hir::UseKind, cx: &mut DocContext<'tcx>, @@ -3023,7 +3025,7 @@ fn clean_use_statement<'tcx>( fn clean_use_statement_inner<'tcx>( import: &hir::Item<'tcx>, - name: Symbol, + name: Option, path: &hir::Path<'tcx>, kind: hir::UseKind, cx: &mut DocContext<'tcx>, @@ -3042,7 +3044,7 @@ fn clean_use_statement_inner<'tcx>( let visibility = cx.tcx.visibility(import.owner_id); let attrs = cx.tcx.hir_attrs(import.hir_id()); let inline_attr = hir_attr_lists(attrs, sym::doc).get_word_attr(sym::inline); - let pub_underscore = visibility.is_public() && name == kw::Underscore; + let pub_underscore = visibility.is_public() && name == Some(kw::Underscore); let current_mod = cx.tcx.parent_module_from_def_id(import.owner_id.def_id); let import_def_id = import.owner_id.def_id; @@ -3108,6 +3110,7 @@ fn clean_use_statement_inner<'tcx>( } Import::new_glob(resolve_use_source(cx, path), true) } else { + let name = name.unwrap(); if inline_attr.is_none() && let Res::Def(DefKind::Mod, did) = path.res && !did.is_local() From e21691529549152625a509e7e69af0b813420c53 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Wed, 12 Feb 2025 08:06:34 -0600 Subject: [PATCH 463/606] Stabilize `-Zdwarf-version` as `-Cdwarf-version` --- compiler/rustc_interface/src/tests.rs | 1 + compiler/rustc_session/src/options.rs | 3 +++ compiler/rustc_session/src/session.rs | 10 ++++++++-- src/doc/rustc/src/codegen-options/index.md | 13 +++++++++++++ .../src/compiler-flags/dwarf-version.md | 13 ------------- .../auxiliary/dwarf-mixed-versions-lto-aux.rs | 2 +- tests/assembly/dwarf-mixed-versions-lto.rs | 2 +- tests/assembly/dwarf4.rs | 4 ++-- tests/assembly/dwarf5.rs | 4 ++-- tests/run-make/embed-source-dwarf/rmake.rs | 2 +- tests/ui/debuginfo/dwarf-versions.rs | 16 ++++++++-------- .../auxiliary/dwarf-mixed-versions-lto-aux.rs | 2 +- tests/ui/lto/dwarf-mixed-versions-lto.rs | 2 +- 13 files changed, 42 insertions(+), 32 deletions(-) delete mode 100644 src/doc/unstable-book/src/compiler-flags/dwarf-version.md diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 75a1b61b4165..d405d044cae6 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -614,6 +614,7 @@ fn test_codegen_options_tracking_hash() { tracked!(control_flow_guard, CFGuard::Checks); tracked!(debug_assertions, Some(true)); tracked!(debuginfo, DebugInfo::Limited); + tracked!(dwarf_version, Some(5)); tracked!(embed_bitcode, false); tracked!(force_frame_pointers, FramePointer::Always); tracked!(force_unwind_tables, Some(true)); diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index c70f1500d393..ea3a1f8bd8cc 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1956,6 +1956,9 @@ options! { "allow the linker to link its default libraries (default: no)"), dlltool: Option = (None, parse_opt_pathbuf, [UNTRACKED], "import library generation tool (ignored except when targeting windows-gnu)"), + #[rustc_lint_opt_deny_field_access("use `Session::dwarf_version` instead of this field")] + dwarf_version: Option = (None, parse_opt_number, [TRACKED], + "version of DWARF debug information to emit (default: 2 or 4, depending on platform)"), embed_bitcode: bool = (true, parse_bool, [TRACKED], "emit bitcode in rlibs (default: yes)"), extra_filename: String = (String::new(), parse_string, [UNTRACKED], diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 1359f7eb7bb4..010ae42c2802 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -764,7 +764,11 @@ impl Session { /// Returns the DWARF version passed on the CLI or the default for the target. pub fn dwarf_version(&self) -> u32 { - self.opts.unstable_opts.dwarf_version.unwrap_or(self.target.default_dwarf_version) + self.opts + .cg + .dwarf_version + .or(self.opts.unstable_opts.dwarf_version) + .unwrap_or(self.target.default_dwarf_version) } pub fn stack_protector(&self) -> StackProtector { @@ -1327,7 +1331,9 @@ fn validate_commandline_args_with_session_available(sess: &Session) { sess.dcx().emit_err(errors::BranchProtectionRequiresAArch64); } - if let Some(dwarf_version) = sess.opts.unstable_opts.dwarf_version { + if let Some(dwarf_version) = + sess.opts.cg.dwarf_version.or(sess.opts.unstable_opts.dwarf_version) + { // DWARF 1 is not supported by LLVM and DWARF 6 is not yet finalized. if dwarf_version < 2 || dwarf_version > 5 { sess.dcx().emit_err(errors::UnsupportedDwarfVersion { dwarf_version }); diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index 8c1769a8c772..a3b70e7f9771 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -110,6 +110,19 @@ It takes a path to [the dlltool executable](https://sourceware.org/binutils/docs If this flag is not specified, a dlltool executable will be inferred based on the host environment and target. +## dwarf-version + +This option controls the version of DWARF that the compiler emits, on platforms +that use DWARF to encode debug information. It takes one of the following +values: + +* `2`: DWARF version 2 (the default on certain platforms, like Android). +* `3`: DWARF version 3 (the default on certain platforms, like AIX). +* `4`: DWARF version 4 (the default on most platforms, like Linux & macOS). +* `5`: DWARF version 5. + +DWARF version 1 is not supported. + ## embed-bitcode This flag controls whether or not the compiler embeds LLVM bitcode into object diff --git a/src/doc/unstable-book/src/compiler-flags/dwarf-version.md b/src/doc/unstable-book/src/compiler-flags/dwarf-version.md deleted file mode 100644 index e88799d2cf04..000000000000 --- a/src/doc/unstable-book/src/compiler-flags/dwarf-version.md +++ /dev/null @@ -1,13 +0,0 @@ -## `dwarf-version` - -The tracking issue for this feature is: - ----------------------------- - -This option controls the version of DWARF that the compiler emits, on platforms -that use DWARF to encode debug information. It takes one of the following -values: - -* `2`: DWARF version 2 (the default on certain platforms, like macOS). -* `4`: DWARF version 4 (the default on certain platforms, like Linux). -* `5`: DWARF version 5. diff --git a/tests/assembly/auxiliary/dwarf-mixed-versions-lto-aux.rs b/tests/assembly/auxiliary/dwarf-mixed-versions-lto-aux.rs index faff6e7e2d05..257608f881f1 100644 --- a/tests/assembly/auxiliary/dwarf-mixed-versions-lto-aux.rs +++ b/tests/assembly/auxiliary/dwarf-mixed-versions-lto-aux.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -g --crate-type=rlib -Zdwarf-version=4 +//@ compile-flags: -g --crate-type=rlib -Cdwarf-version=4 pub fn check_is_even(number: &u64) -> bool { number % 2 == 0 diff --git a/tests/assembly/dwarf-mixed-versions-lto.rs b/tests/assembly/dwarf-mixed-versions-lto.rs index f1fc0814c9db..9910a6e2f5fc 100644 --- a/tests/assembly/dwarf-mixed-versions-lto.rs +++ b/tests/assembly/dwarf-mixed-versions-lto.rs @@ -4,7 +4,7 @@ //@ only-linux //@ aux-build:dwarf-mixed-versions-lto-aux.rs -//@ compile-flags: -C lto -g -Zdwarf-version=5 +//@ compile-flags: -C lto -g -Cdwarf-version=5 //@ assembly-output: emit-asm //@ no-prefer-dynamic diff --git a/tests/assembly/dwarf4.rs b/tests/assembly/dwarf4.rs index 6013adf3386a..03a388603b44 100644 --- a/tests/assembly/dwarf4.rs +++ b/tests/assembly/dwarf4.rs @@ -1,7 +1,7 @@ -// Makes sure that `-Z dwarf-version=4` causes `rustc` to emit DWARF version 4. +// Makes sure that `-C dwarf-version=4` causes `rustc` to emit DWARF version 4. //@ assembly-output: emit-asm //@ add-core-stubs -//@ compile-flags: -g --target x86_64-unknown-linux-gnu -Z dwarf-version=4 -Copt-level=0 +//@ compile-flags: -g --target x86_64-unknown-linux-gnu -C dwarf-version=4 -Copt-level=0 //@ needs-llvm-components: x86 #![feature(no_core, lang_items)] diff --git a/tests/assembly/dwarf5.rs b/tests/assembly/dwarf5.rs index 9cd596e78345..9bd92cc0d097 100644 --- a/tests/assembly/dwarf5.rs +++ b/tests/assembly/dwarf5.rs @@ -1,7 +1,7 @@ -// Makes sure that `-Z dwarf-version=5` causes `rustc` to emit DWARF version 5. +// Makes sure that `-C dwarf-version=5` causes `rustc` to emit DWARF version 5. //@ add-core-stubs //@ assembly-output: emit-asm -//@ compile-flags: -g --target x86_64-unknown-linux-gnu -Z dwarf-version=5 -Copt-level=0 +//@ compile-flags: -g --target x86_64-unknown-linux-gnu -C dwarf-version=5 -Copt-level=0 //@ needs-llvm-components: x86 #![feature(no_core, lang_items)] diff --git a/tests/run-make/embed-source-dwarf/rmake.rs b/tests/run-make/embed-source-dwarf/rmake.rs index 0aae07ff2e64..550c8b9b3c90 100644 --- a/tests/run-make/embed-source-dwarf/rmake.rs +++ b/tests/run-make/embed-source-dwarf/rmake.rs @@ -21,7 +21,7 @@ fn main() { .output(&output) .arg("-g") .arg("-Zembed-source=yes") - .arg("-Zdwarf-version=5") + .arg("-Cdwarf-version=5") .run(); let output = rfs::read(output); let obj = object::File::parse(output.as_slice()).unwrap(); diff --git a/tests/ui/debuginfo/dwarf-versions.rs b/tests/ui/debuginfo/dwarf-versions.rs index bb18cadce435..8f731f10ead4 100644 --- a/tests/ui/debuginfo/dwarf-versions.rs +++ b/tests/ui/debuginfo/dwarf-versions.rs @@ -1,25 +1,25 @@ // This test verifies the expected behavior of various options passed to -// `-Zdwarf-version`: 2 - 5 (valid) with all other options being invalid. +// `-Cdwarf-version`: 2 - 5 (valid) with all other options being invalid. //@ revisions: zero one two three four five six -//@[zero] compile-flags: -Zdwarf-version=0 +//@[zero] compile-flags: -Cdwarf-version=0 -//@[one] compile-flags: -Zdwarf-version=1 +//@[one] compile-flags: -Cdwarf-version=1 -//@[two] compile-flags: -Zdwarf-version=2 +//@[two] compile-flags: -Cdwarf-version=2 //@[two] check-pass -//@[three] compile-flags: -Zdwarf-version=3 +//@[three] compile-flags: -Cdwarf-version=3 //@[three] check-pass -//@[four] compile-flags: -Zdwarf-version=4 +//@[four] compile-flags: -Cdwarf-version=4 //@[four] check-pass -//@[five] compile-flags: -Zdwarf-version=5 +//@[five] compile-flags: -Cdwarf-version=5 //@[five] check-pass -//@[six] compile-flags: -Zdwarf-version=6 +//@[six] compile-flags: -Cdwarf-version=6 //@ compile-flags: -g --target x86_64-unknown-linux-gnu --crate-type cdylib //@ needs-llvm-components: x86 diff --git a/tests/ui/lto/auxiliary/dwarf-mixed-versions-lto-aux.rs b/tests/ui/lto/auxiliary/dwarf-mixed-versions-lto-aux.rs index 3c81127ee65c..2f2bf57f42b4 100644 --- a/tests/ui/lto/auxiliary/dwarf-mixed-versions-lto-aux.rs +++ b/tests/ui/lto/auxiliary/dwarf-mixed-versions-lto-aux.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -g --crate-type=rlib -Zdwarf-version=4 +//@ compile-flags: -g --crate-type=rlib -Cdwarf-version=4 pub fn say_hi() { println!("hello there") diff --git a/tests/ui/lto/dwarf-mixed-versions-lto.rs b/tests/ui/lto/dwarf-mixed-versions-lto.rs index 14ef65a868e0..900274eb22f4 100644 --- a/tests/ui/lto/dwarf-mixed-versions-lto.rs +++ b/tests/ui/lto/dwarf-mixed-versions-lto.rs @@ -4,7 +4,7 @@ //@ ignore-msvc Platform must use DWARF //@ aux-build:dwarf-mixed-versions-lto-aux.rs -//@ compile-flags: -C lto -g -Zdwarf-version=5 +//@ compile-flags: -C lto -g -Cdwarf-version=5 //@ no-prefer-dynamic //@ build-pass From 4c23295dd9449d8feacdab476cd98ac7a7e27eec Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 3 Apr 2025 16:17:16 +1100 Subject: [PATCH 464/606] Use a constant for unstable features needed by compiletest --- src/bootstrap/src/core/build_steps/check.rs | 4 ++-- src/bootstrap/src/core/build_steps/test.rs | 4 ++-- src/bootstrap/src/core/build_steps/tool.rs | 13 ++++++++++--- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs index b191d0f6b306..ae9511b78674 100644 --- a/src/bootstrap/src/core/build_steps/check.rs +++ b/src/bootstrap/src/core/build_steps/check.rs @@ -3,7 +3,7 @@ use crate::core::build_steps::compile::{ add_to_sysroot, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo, std_crates_for_run_make, }; -use crate::core::build_steps::tool::{SourceType, prepare_tool_cargo}; +use crate::core::build_steps::tool::{COMPILETEST_ALLOW_FEATURES, SourceType, prepare_tool_cargo}; use crate::core::builder::{ self, Alias, Builder, Kind, RunConfig, ShouldRun, Step, crate_description, }; @@ -416,7 +416,7 @@ impl Step for Compiletest { &[], ); - cargo.allow_features("test"); + cargo.allow_features(COMPILETEST_ALLOW_FEATURES); // For ./x.py clippy, don't run with --all-targets because // linting tests and benchmarks can produce very noisy results diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index e23c1ab5a238..b1a3bba08871 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -15,7 +15,7 @@ use crate::core::build_steps::doc::DocumentationFormat; use crate::core::build_steps::gcc::{Gcc, add_cg_gcc_cargo_flags}; use crate::core::build_steps::llvm::get_llvm_version; use crate::core::build_steps::synthetic_targets::MirOptPanicAbortSyntheticTarget; -use crate::core::build_steps::tool::{self, SourceType, Tool}; +use crate::core::build_steps::tool::{self, COMPILETEST_ALLOW_FEATURES, SourceType, Tool}; use crate::core::build_steps::toolstate::ToolState; use crate::core::build_steps::{compile, dist, llvm}; use crate::core::builder::{ @@ -721,7 +721,7 @@ impl Step for CompiletestTest { SourceType::InTree, &[], ); - cargo.allow_features("test"); + cargo.allow_features(COMPILETEST_ALLOW_FEATURES); run_cargo_test(cargo, &[], &[], "compiletest self test", host, builder); } } diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index ded7220fcedc..528a45d215bf 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -444,7 +444,11 @@ macro_rules! bootstrap_tool { SourceType::InTree }, extra_features: vec![], - allow_features: concat!($($allow_features)*), + allow_features: { + let mut _value = ""; + $( _value = $allow_features; )? + _value + }, cargo_args: vec![], artifact_kind: if false $(|| $artifact_kind == ToolArtifactKind::Library)* { ToolArtifactKind::Library @@ -458,6 +462,8 @@ macro_rules! bootstrap_tool { } } +pub(crate) const COMPILETEST_ALLOW_FEATURES: &str = "test"; + bootstrap_tool!( // This is marked as an external tool because it includes dependencies // from submodules. Trying to keep the lints in sync between all the repos @@ -468,7 +474,7 @@ bootstrap_tool!( Tidy, "src/tools/tidy", "tidy"; Linkchecker, "src/tools/linkchecker", "linkchecker"; CargoTest, "src/tools/cargotest", "cargotest"; - Compiletest, "src/tools/compiletest", "compiletest", is_unstable_tool = true, allow_features = "test"; + Compiletest, "src/tools/compiletest", "compiletest", is_unstable_tool = true, allow_features = COMPILETEST_ALLOW_FEATURES; BuildManifest, "src/tools/build-manifest", "build-manifest"; RemoteTestClient, "src/tools/remote-test-client", "remote-test-client"; RustInstaller, "src/tools/rust-installer", "rust-installer"; @@ -483,7 +489,8 @@ bootstrap_tool!( GenerateCopyright, "src/tools/generate-copyright", "generate-copyright"; SuggestTests, "src/tools/suggest-tests", "suggest-tests"; GenerateWindowsSys, "src/tools/generate-windows-sys", "generate-windows-sys"; - RustdocGUITest, "src/tools/rustdoc-gui-test", "rustdoc-gui-test", is_unstable_tool = true, allow_features = "test"; + // rustdoc-gui-test has a crate dependency on compiletest, so it needs the same unstable features. + RustdocGUITest, "src/tools/rustdoc-gui-test", "rustdoc-gui-test", is_unstable_tool = true, allow_features = COMPILETEST_ALLOW_FEATURES; CoverageDump, "src/tools/coverage-dump", "coverage-dump"; WasmComponentLd, "src/tools/wasm-component-ld", "wasm-component-ld", is_unstable_tool = true, allow_features = "min_specialization"; UnicodeTableGenerator, "src/tools/unicode-table-generator", "unicode-table-generator"; From 6fda3e52c94d2b84678133ea339996629f47fcf2 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 11 Apr 2025 16:10:09 +1000 Subject: [PATCH 465/606] compiletest: Extract libtest-specific executor code to a submodule --- src/tools/compiletest/src/executor.rs | 103 +--------------- src/tools/compiletest/src/executor/libtest.rs | 111 ++++++++++++++++++ src/tools/compiletest/src/lib.rs | 2 +- 3 files changed, 113 insertions(+), 103 deletions(-) create mode 100644 src/tools/compiletest/src/executor/libtest.rs diff --git a/src/tools/compiletest/src/executor.rs b/src/tools/compiletest/src/executor.rs index 527d6b8a36eb..49764479dd69 100644 --- a/src/tools/compiletest/src/executor.rs +++ b/src/tools/compiletest/src/executor.rs @@ -4,20 +4,11 @@ //! This will hopefully make it easier to migrate away from libtest someday. use std::borrow::Cow; -use std::io; use std::sync::Arc; use crate::common::{Config, TestPaths}; -/// Delegates to libtest to run the list of collected tests. -/// -/// Returns `Ok(true)` if all tests passed, or `Ok(false)` if one or more tests failed. -pub(crate) fn execute_tests(config: &Config, tests: Vec) -> io::Result { - let opts = test_opts(config); - let tests = tests.into_iter().map(|t| t.into_libtest()).collect::>(); - - test::run_tests_console(&opts, tests) -} +pub(crate) mod libtest; /// Information needed to create a `test::TestDescAndFn`. pub(crate) struct CollectedTest { @@ -35,45 +26,6 @@ pub(crate) struct CollectedTestDesc { pub(crate) should_panic: ShouldPanic, } -impl CollectedTest { - fn into_libtest(self) -> test::TestDescAndFn { - let Self { desc, config, testpaths, revision } = self; - let CollectedTestDesc { name, ignore, ignore_message, should_panic } = desc; - - // Libtest requires the ignore message to be a &'static str, so we might - // have to leak memory to create it. This is fine, as we only do so once - // per test, so the leak won't grow indefinitely. - let ignore_message = ignore_message.map(|msg| match msg { - Cow::Borrowed(s) => s, - Cow::Owned(s) => &*String::leak(s), - }); - - let desc = test::TestDesc { - name: test::DynTestName(name), - ignore, - ignore_message, - source_file: "", - start_line: 0, - start_col: 0, - end_line: 0, - end_col: 0, - should_panic: should_panic.to_libtest(), - compile_fail: false, - no_run: false, - test_type: test::TestType::Unknown, - }; - - // This closure is invoked when libtest returns control to compiletest - // to execute the test. - let testfn = test::DynTestFn(Box::new(move || { - crate::runtest::run(config, &testpaths, revision.as_deref()); - Ok(()) - })); - - test::TestDescAndFn { desc, testfn } - } -} - /// Whether console output should be colored or not. #[derive(Copy, Clone, Default, Debug)] pub enum ColorConfig { @@ -83,16 +35,6 @@ pub enum ColorConfig { NeverColor, } -impl ColorConfig { - fn to_libtest(self) -> test::ColorConfig { - match self { - Self::AutoColor => test::ColorConfig::AutoColor, - Self::AlwaysColor => test::ColorConfig::AlwaysColor, - Self::NeverColor => test::ColorConfig::NeverColor, - } - } -} - /// Format of the test results output. #[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] pub enum OutputFormat { @@ -105,52 +47,9 @@ pub enum OutputFormat { Json, } -impl OutputFormat { - fn to_libtest(self) -> test::OutputFormat { - match self { - Self::Pretty => test::OutputFormat::Pretty, - Self::Terse => test::OutputFormat::Terse, - Self::Json => test::OutputFormat::Json, - } - } -} - /// Whether test is expected to panic or not. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub(crate) enum ShouldPanic { No, Yes, } - -impl ShouldPanic { - fn to_libtest(self) -> test::ShouldPanic { - match self { - Self::No => test::ShouldPanic::No, - Self::Yes => test::ShouldPanic::Yes, - } - } -} - -fn test_opts(config: &Config) -> test::TestOpts { - test::TestOpts { - exclude_should_panic: false, - filters: config.filters.clone(), - filter_exact: config.filter_exact, - run_ignored: if config.run_ignored { test::RunIgnored::Yes } else { test::RunIgnored::No }, - format: config.format.to_libtest(), - logfile: None, - run_tests: true, - bench_benchmarks: true, - nocapture: config.nocapture, - color: config.color.to_libtest(), - shuffle: false, - shuffle_seed: None, - test_threads: None, - skip: config.skip.clone(), - list: false, - options: test::Options::new(), - time_options: None, - force_run_in_process: false, - fail_fast: config.fail_fast, - } -} diff --git a/src/tools/compiletest/src/executor/libtest.rs b/src/tools/compiletest/src/executor/libtest.rs new file mode 100644 index 000000000000..032b3f4fa9a8 --- /dev/null +++ b/src/tools/compiletest/src/executor/libtest.rs @@ -0,0 +1,111 @@ +//! This submodule encapsulates all of the code that actually interacts with +//! libtest, so that it can be easily removed after the new executor becomes +//! the default. + +use std::borrow::Cow; +use std::io; + +use crate::common::Config; +use crate::executor::{CollectedTest, CollectedTestDesc, ColorConfig, OutputFormat, ShouldPanic}; + +/// Delegates to libtest to run the list of collected tests. +/// +/// Returns `Ok(true)` if all tests passed, or `Ok(false)` if one or more tests failed. +pub(crate) fn execute_tests(config: &Config, tests: Vec) -> io::Result { + let opts = test_opts(config); + let tests = tests.into_iter().map(|t| t.into_libtest()).collect::>(); + + test::run_tests_console(&opts, tests) +} + +impl CollectedTest { + fn into_libtest(self) -> test::TestDescAndFn { + let Self { desc, config, testpaths, revision } = self; + let CollectedTestDesc { name, ignore, ignore_message, should_panic } = desc; + + // Libtest requires the ignore message to be a &'static str, so we might + // have to leak memory to create it. This is fine, as we only do so once + // per test, so the leak won't grow indefinitely. + let ignore_message = ignore_message.map(|msg| match msg { + Cow::Borrowed(s) => s, + Cow::Owned(s) => &*String::leak(s), + }); + + let desc = test::TestDesc { + name: test::DynTestName(name), + ignore, + ignore_message, + source_file: "", + start_line: 0, + start_col: 0, + end_line: 0, + end_col: 0, + should_panic: should_panic.to_libtest(), + compile_fail: false, + no_run: false, + test_type: test::TestType::Unknown, + }; + + // This closure is invoked when libtest returns control to compiletest + // to execute the test. + let testfn = test::DynTestFn(Box::new(move || { + crate::runtest::run(config, &testpaths, revision.as_deref()); + Ok(()) + })); + + test::TestDescAndFn { desc, testfn } + } +} + +impl ColorConfig { + fn to_libtest(self) -> test::ColorConfig { + match self { + Self::AutoColor => test::ColorConfig::AutoColor, + Self::AlwaysColor => test::ColorConfig::AlwaysColor, + Self::NeverColor => test::ColorConfig::NeverColor, + } + } +} + +impl OutputFormat { + fn to_libtest(self) -> test::OutputFormat { + match self { + Self::Pretty => test::OutputFormat::Pretty, + Self::Terse => test::OutputFormat::Terse, + Self::Json => test::OutputFormat::Json, + } + } +} + +impl ShouldPanic { + fn to_libtest(self) -> test::ShouldPanic { + match self { + Self::No => test::ShouldPanic::No, + Self::Yes => test::ShouldPanic::Yes, + } + } +} + +fn test_opts(config: &Config) -> test::TestOpts { + test::TestOpts { + exclude_should_panic: false, + filters: config.filters.clone(), + filter_exact: config.filter_exact, + run_ignored: if config.run_ignored { test::RunIgnored::Yes } else { test::RunIgnored::No }, + format: config.format.to_libtest(), + logfile: None, + run_tests: true, + bench_benchmarks: true, + nocapture: config.nocapture, + color: config.color.to_libtest(), + shuffle: false, + shuffle_seed: None, + test_threads: None, + skip: config.skip.clone(), + list: false, + options: test::Options::new(), + time_options: None, + force_run_in_process: false, + fail_fast: config.fail_fast, + } +} diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index b969b22750bc..72bb4101dd20 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -573,7 +573,7 @@ pub fn run_tests(config: Arc) { // Delegate to libtest to filter and run the big list of structures created // during test discovery. When libtest decides to run a test, it will // return control to compiletest by invoking a closure. - let res = crate::executor::execute_tests(&config, tests); + let res = crate::executor::libtest::execute_tests(&config, tests); // Check the outcome reported by libtest. match res { From e3d68139200da0e5010321b286e3e15e4a9530e0 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sun, 6 Apr 2025 10:48:44 +1000 Subject: [PATCH 466/606] compiletest: Add an experimental new executor to replace libtest The new executor can be enabled by passing `--new-executor` or `-n` to compiletest. For example: `./x test ui -- -n` --- src/bootstrap/src/core/build_steps/tool.rs | 2 +- src/tools/compiletest/src/common.rs | 5 + src/tools/compiletest/src/executor.rs | 248 +++++++++++++++++- .../compiletest/src/executor/deadline.rs | 78 ++++++ src/tools/compiletest/src/executor/json.rs | 111 ++++++++ src/tools/compiletest/src/lib.rs | 20 +- 6 files changed, 452 insertions(+), 12 deletions(-) create mode 100644 src/tools/compiletest/src/executor/deadline.rs create mode 100644 src/tools/compiletest/src/executor/json.rs diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index 528a45d215bf..3426da51a808 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -462,7 +462,7 @@ macro_rules! bootstrap_tool { } } -pub(crate) const COMPILETEST_ALLOW_FEATURES: &str = "test"; +pub(crate) const COMPILETEST_ALLOW_FEATURES: &str = "test,internal_output_capture"; bootstrap_tool!( // This is marked as an external tool because it includes dependencies diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 604c5fcbddff..31c696ed41ff 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -414,6 +414,11 @@ pub struct Config { /// cross-compilation scenarios that do not otherwise want/need to `-Zbuild-std`. Used in e.g. /// ABI tests. pub minicore_path: Utf8PathBuf, + + /// If true, run tests with the "new" executor that was written to replace + /// compiletest's dependency on libtest. Eventually this will become the + /// default, and the libtest dependency will be removed. + pub new_executor: bool, } impl Config { diff --git a/src/tools/compiletest/src/executor.rs b/src/tools/compiletest/src/executor.rs index 49764479dd69..0c173d476aff 100644 --- a/src/tools/compiletest/src/executor.rs +++ b/src/tools/compiletest/src/executor.rs @@ -1,15 +1,253 @@ -//! This module encapsulates all of the code that interacts directly with -//! libtest, to execute the collected tests. -//! -//! This will hopefully make it easier to migrate away from libtest someday. +//! This module contains a reimplementation of the subset of libtest +//! functionality needed by compiletest. use std::borrow::Cow; -use std::sync::Arc; +use std::collections::HashMap; +use std::hash::{BuildHasherDefault, DefaultHasher}; +use std::num::NonZero; +use std::sync::{Arc, Mutex, mpsc}; +use std::{env, hint, io, mem, panic, thread}; use crate::common::{Config, TestPaths}; +mod deadline; +mod json; pub(crate) mod libtest; +pub(crate) fn run_tests(config: &Config, tests: Vec) -> bool { + let tests_len = tests.len(); + let filtered = filter_tests(config, tests); + // Iterator yielding tests that haven't been started yet. + let mut fresh_tests = (0..).map(TestId).zip(&filtered); + + let concurrency = get_concurrency(); + assert!(concurrency > 0); + let concurrent_capacity = concurrency.min(filtered.len()); + + let mut listener = json::Listener::new(); + let mut running_tests = HashMap::with_capacity_and_hasher( + concurrent_capacity, + BuildHasherDefault::::new(), + ); + let mut deadline_queue = deadline::DeadlineQueue::with_capacity(concurrent_capacity); + + let num_filtered_out = tests_len - filtered.len(); + listener.suite_started(filtered.len(), num_filtered_out); + + // Channel used by test threads to report the test outcome when done. + let (completion_tx, completion_rx) = mpsc::channel::(); + + // Unlike libtest, we don't have a separate code path for concurrency=1. + // In that case, the tests will effectively be run serially anyway. + loop { + // Spawn new test threads, up to the concurrency limit. + // FIXME(let_chains): Use a let-chain here when stable in bootstrap. + 'spawn: while running_tests.len() < concurrency { + let Some((id, test)) = fresh_tests.next() else { break 'spawn }; + listener.test_started(test); + deadline_queue.push(id, test); + let join_handle = spawn_test_thread(id, test, completion_tx.clone()); + running_tests.insert(id, RunningTest { test, join_handle }); + } + + // If all running tests have finished, and there weren't any unstarted + // tests to spawn, then we're done. + if running_tests.is_empty() { + break; + } + + let completion = deadline_queue + .read_channel_while_checking_deadlines(&completion_rx, |_id, test| { + listener.test_timed_out(test); + }) + .expect("receive channel should never be closed early"); + + let RunningTest { test, join_handle } = running_tests.remove(&completion.id).unwrap(); + if let Some(join_handle) = join_handle { + join_handle.join().unwrap_or_else(|_| { + panic!("thread for `{}` panicked after reporting completion", test.desc.name) + }); + } + + listener.test_finished(test, &completion); + + if completion.outcome.is_failed() && config.fail_fast { + // Prevent any other in-flight threads from panicking when they + // write to the completion channel. + mem::forget(completion_rx); + break; + } + } + + let suite_passed = listener.suite_finished(); + suite_passed +} + +/// Spawns a thread to run a single test, and returns the thread's join handle. +/// +/// Returns `None` if the test was ignored, so no thread was spawned. +fn spawn_test_thread( + id: TestId, + test: &CollectedTest, + completion_tx: mpsc::Sender, +) -> Option> { + if test.desc.ignore && !test.config.run_ignored { + completion_tx + .send(TestCompletion { id, outcome: TestOutcome::Ignored, stdout: None }) + .unwrap(); + return None; + } + + let runnable_test = RunnableTest::new(test); + let should_panic = test.desc.should_panic; + let run_test = move || run_test_inner(id, should_panic, runnable_test, completion_tx); + + let thread_builder = thread::Builder::new().name(test.desc.name.clone()); + let join_handle = thread_builder.spawn(run_test).unwrap(); + Some(join_handle) +} + +/// Runs a single test, within the dedicated thread spawned by the caller. +fn run_test_inner( + id: TestId, + should_panic: ShouldPanic, + runnable_test: RunnableTest, + completion_sender: mpsc::Sender, +) { + let is_capture = !runnable_test.config.nocapture; + let capture_buf = is_capture.then(|| Arc::new(Mutex::new(vec![]))); + + if let Some(capture_buf) = &capture_buf { + io::set_output_capture(Some(Arc::clone(capture_buf))); + } + + let panic_payload = panic::catch_unwind(move || runnable_test.run()).err(); + + if is_capture { + io::set_output_capture(None); + } + + let outcome = match (should_panic, panic_payload) { + (ShouldPanic::No, None) | (ShouldPanic::Yes, Some(_)) => TestOutcome::Succeeded, + (ShouldPanic::No, Some(_)) => TestOutcome::Failed { message: None }, + (ShouldPanic::Yes, None) => { + TestOutcome::Failed { message: Some("test did not panic as expected") } + } + }; + let stdout = capture_buf.map(|mutex| mutex.lock().unwrap_or_else(|e| e.into_inner()).to_vec()); + + completion_sender.send(TestCompletion { id, outcome, stdout }).unwrap(); +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +struct TestId(usize); + +struct RunnableTest { + config: Arc, + testpaths: TestPaths, + revision: Option, +} + +impl RunnableTest { + fn new(test: &CollectedTest) -> Self { + let config = Arc::clone(&test.config); + let testpaths = test.testpaths.clone(); + let revision = test.revision.clone(); + Self { config, testpaths, revision } + } + + fn run(&self) { + __rust_begin_short_backtrace(|| { + crate::runtest::run( + Arc::clone(&self.config), + &self.testpaths, + self.revision.as_deref(), + ); + }); + } +} + +/// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`. +#[inline(never)] +fn __rust_begin_short_backtrace T>(f: F) -> T { + let result = f(); + + // prevent this frame from being tail-call optimised away + hint::black_box(result) +} + +struct RunningTest<'a> { + test: &'a CollectedTest, + join_handle: Option>, +} + +/// Test completion message sent by individual test threads when their test +/// finishes (successfully or unsuccessfully). +struct TestCompletion { + id: TestId, + outcome: TestOutcome, + stdout: Option>, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +enum TestOutcome { + Succeeded, + Failed { message: Option<&'static str> }, + Ignored, +} + +impl TestOutcome { + fn is_failed(&self) -> bool { + matches!(self, Self::Failed { .. }) + } +} + +/// Applies command-line arguments for filtering/skipping tests by name. +/// +/// Adapted from `filter_tests` in libtest. +/// +/// FIXME(#139660): After the libtest dependency is removed, redesign the whole +/// filtering system to do a better job of understanding and filtering _paths_, +/// instead of being tied to libtest's substring/exact matching behaviour. +fn filter_tests(opts: &Config, tests: Vec) -> Vec { + let mut filtered = tests; + + let matches_filter = |test: &CollectedTest, filter_str: &str| { + let test_name = &test.desc.name; + if opts.filter_exact { test_name == filter_str } else { test_name.contains(filter_str) } + }; + + // Remove tests that don't match the test filter + if !opts.filters.is_empty() { + filtered.retain(|test| opts.filters.iter().any(|filter| matches_filter(test, filter))); + } + + // Skip tests that match any of the skip filters + if !opts.skip.is_empty() { + filtered.retain(|test| !opts.skip.iter().any(|sf| matches_filter(test, sf))); + } + + filtered +} + +/// Determines the number of tests to run concurrently. +/// +/// Copied from `get_concurrency` in libtest. +/// +/// FIXME(#139660): After the libtest dependency is removed, consider making +/// bootstrap specify the number of threads on the command-line, instead of +/// propagating the `RUST_TEST_THREADS` environment variable. +fn get_concurrency() -> usize { + if let Ok(value) = env::var("RUST_TEST_THREADS") { + match value.parse::>().ok() { + Some(n) => n.get(), + _ => panic!("RUST_TEST_THREADS is `{value}`, should be a positive integer."), + } + } else { + thread::available_parallelism().map(|n| n.get()).unwrap_or(1) + } +} + /// Information needed to create a `test::TestDescAndFn`. pub(crate) struct CollectedTest { pub(crate) desc: CollectedTestDesc, diff --git a/src/tools/compiletest/src/executor/deadline.rs b/src/tools/compiletest/src/executor/deadline.rs new file mode 100644 index 000000000000..83b8591a4164 --- /dev/null +++ b/src/tools/compiletest/src/executor/deadline.rs @@ -0,0 +1,78 @@ +use std::collections::VecDeque; +use std::sync::mpsc::{self, RecvError, RecvTimeoutError}; +use std::time::{Duration, Instant}; + +use crate::executor::{CollectedTest, TestId}; + +const TEST_WARN_TIMEOUT_S: u64 = 60; + +struct DeadlineEntry<'a> { + id: TestId, + test: &'a CollectedTest, + deadline: Instant, +} + +pub(crate) struct DeadlineQueue<'a> { + queue: VecDeque>, +} + +impl<'a> DeadlineQueue<'a> { + pub(crate) fn with_capacity(capacity: usize) -> Self { + Self { queue: VecDeque::with_capacity(capacity) } + } + + pub(crate) fn push(&mut self, id: TestId, test: &'a CollectedTest) { + let deadline = Instant::now() + Duration::from_secs(TEST_WARN_TIMEOUT_S); + self.queue.push_back(DeadlineEntry { id, test, deadline }); + } + + /// Equivalent to `rx.read()`, except that if any test exceeds its deadline + /// during the wait, the given callback will also be called for that test. + pub(crate) fn read_channel_while_checking_deadlines( + &mut self, + rx: &mpsc::Receiver, + mut on_deadline_passed: impl FnMut(TestId, &CollectedTest), + ) -> Result { + loop { + let Some(next_deadline) = self.next_deadline() else { + // All currently-running tests have already exceeded their + // deadline, so do a normal receive. + return rx.recv(); + }; + let wait_duration = next_deadline.saturating_duration_since(Instant::now()); + + let recv_result = rx.recv_timeout(wait_duration); + match recv_result { + Ok(value) => return Ok(value), + Err(RecvTimeoutError::Timeout) => { + // Notify the callback of tests that have exceeded their + // deadline, then loop and do annother channel read. + for DeadlineEntry { id, test, .. } in self.remove_tests_past_deadline() { + on_deadline_passed(id, test); + } + } + Err(RecvTimeoutError::Disconnected) => return Err(RecvError), + } + } + } + + fn next_deadline(&self) -> Option { + Some(self.queue.front()?.deadline) + } + + fn remove_tests_past_deadline(&mut self) -> Vec> { + let now = Instant::now(); + let mut timed_out = vec![]; + while let Some(deadline_entry) = pop_front_if(&mut self.queue, |entry| now < entry.deadline) + { + timed_out.push(deadline_entry); + } + timed_out + } +} + +/// FIXME(vec_deque_pop_if): Use `VecDeque::pop_front_if` when it is stable in bootstrap. +fn pop_front_if(queue: &mut VecDeque, predicate: impl FnOnce(&T) -> bool) -> Option { + let first = queue.front()?; + if predicate(first) { queue.pop_front() } else { None } +} diff --git a/src/tools/compiletest/src/executor/json.rs b/src/tools/compiletest/src/executor/json.rs new file mode 100644 index 000000000000..c74ed81a36b8 --- /dev/null +++ b/src/tools/compiletest/src/executor/json.rs @@ -0,0 +1,111 @@ +//! Collects statistics and emits suite/test events as JSON messages, using +//! the same JSON format as libtest's JSON formatter. +//! +//! These messages are then parsed by bootstrap, which replaces them with +//! user-friendly terminal output. + +use std::time::Instant; + +use serde_json::json; + +use crate::executor::{CollectedTest, TestCompletion, TestOutcome}; + +pub(crate) struct Listener { + suite_start: Option, + passed: usize, + failed: usize, + ignored: usize, + filtered_out: usize, +} + +impl Listener { + pub(crate) fn new() -> Self { + Self { suite_start: None, passed: 0, failed: 0, ignored: 0, filtered_out: 0 } + } + + fn print_message(&self, message: &serde_json::Value) { + println!("{message}"); + } + + fn now(&self) -> Instant { + Instant::now() + } + + pub(crate) fn suite_started(&mut self, test_count: usize, filtered_out: usize) { + self.suite_start = Some(self.now()); + self.filtered_out = filtered_out; + let message = json!({ "type": "suite", "event": "started", "test_count": test_count }); + self.print_message(&message); + } + + pub(crate) fn test_started(&mut self, test: &CollectedTest) { + let name = test.desc.name.as_str(); + let message = json!({ "type": "test", "event": "started", "name": name }); + self.print_message(&message); + } + + pub(crate) fn test_timed_out(&mut self, test: &CollectedTest) { + let name = test.desc.name.as_str(); + let message = json!({ "type": "test", "event": "timeout", "name": name }); + self.print_message(&message); + } + + pub(crate) fn test_finished(&mut self, test: &CollectedTest, completion: &TestCompletion) { + let event; + let name = test.desc.name.as_str(); + let mut maybe_message = None; + let maybe_stdout = completion.stdout.as_deref().map(String::from_utf8_lossy); + + match completion.outcome { + TestOutcome::Succeeded => { + self.passed += 1; + event = "ok"; + } + TestOutcome::Failed { message } => { + self.failed += 1; + maybe_message = message; + event = "failed"; + } + TestOutcome::Ignored => { + self.ignored += 1; + maybe_message = test.desc.ignore_message.as_deref(); + event = "ignored"; + } + }; + + // This emits optional fields as `null`, instead of omitting them + // completely as libtest does, but bootstrap can parse the result + // either way. + let json = json!({ + "type": "test", + "event": event, + "name": name, + "message": maybe_message, + "stdout": maybe_stdout, + }); + + self.print_message(&json); + } + + pub(crate) fn suite_finished(&mut self) -> bool { + let exec_time = self.suite_start.map(|start| (self.now() - start).as_secs_f64()); + let suite_passed = self.failed == 0; + + let event = if suite_passed { "ok" } else { "failed" }; + let message = json!({ + "type": "suite", + "event": event, + "passed": self.passed, + "failed": self.failed, + "ignored": self.ignored, + // Compiletest doesn't run any benchmarks, but we still need to set this + // field to 0 so that bootstrap's JSON parser can read our message. + "measured": 0, + "filtered_out": self.filtered_out, + "exec_time": exec_time, + }); + + self.print_message(&message); + suite_passed + } +} diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 72bb4101dd20..4bbd4ab4790d 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -1,7 +1,8 @@ #![crate_name = "compiletest"] -// The `test` crate is the only unstable feature -// allowed here, just to share similar code. +// Needed by the libtest-based test executor. #![feature(test)] +// Needed by the "new" test executor that does not depend on libtest. +#![feature(internal_output_capture)] extern crate test; @@ -202,6 +203,7 @@ pub fn parse_config(args: Vec) -> Config { "COMMAND", ) .reqopt("", "minicore-path", "path to minicore aux library", "PATH") + .optflag("n", "new-executor", "enables the new test executor instead of using libtest") .optopt( "", "debugger", @@ -447,6 +449,8 @@ pub fn parse_config(args: Vec) -> Config { diff_command: matches.opt_str("compiletest-diff-tool"), minicore_path: opt_path(matches, "minicore-path"), + + new_executor: matches.opt_present("new-executor"), } } @@ -570,10 +574,14 @@ pub fn run_tests(config: Arc) { tests.sort_by(|a, b| Ord::cmp(&a.desc.name, &b.desc.name)); - // Delegate to libtest to filter and run the big list of structures created - // during test discovery. When libtest decides to run a test, it will - // return control to compiletest by invoking a closure. - let res = crate::executor::libtest::execute_tests(&config, tests); + // Delegate to the executor to filter and run the big list of test structures + // created during test discovery. When the executor decides to run a test, + // it will return control to the rest of compiletest by calling `runtest::run`. + let res = if config.new_executor { + Ok(executor::run_tests(&config, tests)) + } else { + crate::executor::libtest::execute_tests(&config, tests) + }; // Check the outcome reported by libtest. match res { From 31320a925f53264a1905c5228392de9638bf2d52 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 15 Apr 2025 12:28:18 +1000 Subject: [PATCH 467/606] Remove another `kw::Empty` use in rustdoc. Again by using `Option` to represent "no name". --- src/librustdoc/clean/mod.rs | 35 ++++++++++++++++-------------- src/librustdoc/clean/types.rs | 4 ++-- src/librustdoc/html/format.rs | 8 ++++--- src/librustdoc/json/conversions.rs | 7 ++++-- 4 files changed, 31 insertions(+), 23 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 736dd3a1d865..1bba43cc45fd 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -117,7 +117,14 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext< hir::ItemKind::Use(path, kind) => { let hir::UsePath { segments, span, .. } = *path; let path = hir::Path { segments, res: *res, span }; - clean_use_statement_inner(import, Some(name), &path, kind, cx, &mut Default::default()) + clean_use_statement_inner( + import, + Some(name), + &path, + kind, + cx, + &mut Default::default(), + ) } _ => unreachable!(), } @@ -1071,10 +1078,10 @@ fn clean_fn_decl_legacy_const_generics(func: &mut Function, attrs: &[hir::Attrib .. } = param { - func.decl - .inputs - .values - .insert(a.get() as _, Argument { name, type_: *ty, is_const: true }); + func.decl.inputs.values.insert( + a.get() as _, + Argument { name: Some(name), type_: *ty, is_const: true }, + ); } else { panic!("unexpected non const in position {pos}"); } @@ -1131,9 +1138,9 @@ fn clean_args_from_types_and_names<'tcx>( // If at least one argument has a name, use `_` as the name of unnamed // arguments. Otherwise omit argument names. let default_name = if idents.iter().any(|ident| nonempty_name(ident).is_some()) { - kw::Underscore + Some(kw::Underscore) } else { - kw::Empty + None }; Arguments { @@ -1142,7 +1149,7 @@ fn clean_args_from_types_and_names<'tcx>( .enumerate() .map(|(i, ty)| Argument { type_: clean_ty(ty, cx), - name: idents.get(i).and_then(nonempty_name).unwrap_or(default_name), + name: idents.get(i).and_then(nonempty_name).or(default_name), is_const: false, }) .collect(), @@ -1161,7 +1168,7 @@ fn clean_args_from_types_and_body_id<'tcx>( .iter() .zip(body.params) .map(|(ty, param)| Argument { - name: name_from_pat(param.pat), + name: Some(name_from_pat(param.pat)), type_: clean_ty(ty, cx), is_const: false, }) @@ -1217,11 +1224,11 @@ fn clean_poly_fn_sig<'tcx>( .iter() .map(|t| Argument { type_: clean_middle_ty(t.map_bound(|t| *t), cx, None, None), - name: if let Some(Some(ident)) = names.next() { + name: Some(if let Some(Some(ident)) = names.next() { ident.name } else { kw::Underscore - }, + }), is_const: false, }) .collect(), @@ -2791,11 +2798,7 @@ fn clean_maybe_renamed_item<'tcx>( use hir::ItemKind; let def_id = item.owner_id.to_def_id(); - let mut name = if renamed.is_some() { - renamed - } else { - cx.tcx.hir_opt_name(item.hir_id()) - }; + let mut name = if renamed.is_some() { renamed } else { cx.tcx.hir_opt_name(item.hir_id()) }; cx.with_param_env(def_id, |cx| { let kind = match item.kind { diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 06e75fe1764e..1d398a6458fd 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1426,7 +1426,7 @@ pub(crate) struct Arguments { #[derive(Clone, PartialEq, Eq, Debug, Hash)] pub(crate) struct Argument { pub(crate) type_: Type, - pub(crate) name: Symbol, + pub(crate) name: Option, /// This field is used to represent "const" arguments from the `rustc_legacy_const_generics` /// feature. More information in . pub(crate) is_const: bool, @@ -1434,7 +1434,7 @@ pub(crate) struct Argument { impl Argument { pub(crate) fn to_receiver(&self) -> Option<&Type> { - if self.name == kw::SelfLower { Some(&self.type_) } else { None } + if self.name == Some(kw::SelfLower) { Some(&self.type_) } else { None } } } diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 41e9a5a66516..4d55df71a910 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -1238,8 +1238,8 @@ impl clean::Arguments { .iter() .map(|input| { fmt::from_fn(|f| { - if !input.name.is_empty() { - write!(f, "{}: ", input.name)?; + if let Some(name) = input.name { + write!(f, "{}: ", name)?; } input.type_.print(cx).fmt(f) }) @@ -1361,7 +1361,9 @@ impl clean::FnDecl { if input.is_const { write!(f, "const ")?; } - write!(f, "{}: ", input.name)?; + if let Some(name) = input.name { + write!(f, "{}: ", name)?; + } input.type_.print(cx).fmt(f)?; } match (line_wrapping_indent, last_input_index) { diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 9d8eb70fbe07..5d85a4676b7e 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -11,7 +11,7 @@ use rustc_hir::def::CtorKind; use rustc_hir::def_id::DefId; use rustc_metadata::rendered_const; use rustc_middle::{bug, ty}; -use rustc_span::{Pos, Symbol}; +use rustc_span::{Pos, Symbol, kw}; use rustdoc_json_types::*; use crate::clean::{self, ItemId}; @@ -611,7 +611,10 @@ impl FromClean for FunctionSignature { inputs: inputs .values .into_iter() - .map(|arg| (arg.name.to_string(), arg.type_.into_json(renderer))) + // `_` is the most sensible name for missing param names. + .map(|arg| { + (arg.name.unwrap_or(kw::Underscore).to_string(), arg.type_.into_json(renderer)) + }) .collect(), output: if output.is_unit() { None } else { Some(output.into_json(renderer)) }, is_c_variadic: c_variadic, From 5fb0f570f5d4b63db0bde517432b76099a2d683d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 15 Apr 2025 13:26:19 +1000 Subject: [PATCH 468/606] Avoid another `kw::Empty` use. `sym::dummy` also appears to work. --- src/librustdoc/clean/utils.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index afcca81a485f..8ee08edec199 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -234,7 +234,7 @@ pub(super) fn clean_middle_path<'tcx>( args: ty::Binder<'tcx, GenericArgsRef<'tcx>>, ) -> Path { let def_kind = cx.tcx.def_kind(did); - let name = cx.tcx.opt_item_name(did).unwrap_or(kw::Empty); + let name = cx.tcx.opt_item_name(did).unwrap_or(sym::dummy); Path { res: Res::Def(def_kind, did), segments: thin_vec![PathSegment { From 40978580ec3c4d6d32245e578979a745f310e9c3 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 15 Apr 2025 13:31:17 +1000 Subject: [PATCH 469/606] Avoid using `kw::Empty` when comparing names. --- src/librustdoc/html/render/print_item.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 96847f13f655..45cb0adecf3b 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -11,7 +11,7 @@ use rustc_hir::def_id::DefId; use rustc_index::IndexVec; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::hygiene::MacroKind; -use rustc_span::symbol::{Symbol, kw, sym}; +use rustc_span::symbol::{Symbol, sym}; use tracing::{debug, info}; use super::type_layout::document_type_layout; @@ -347,9 +347,12 @@ fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> i // but we actually want stable items to come first return is_stable2.cmp(&is_stable1); } - let lhs = i1.name.unwrap_or(kw::Empty); - let rhs = i2.name.unwrap_or(kw::Empty); - compare_names(lhs.as_str(), rhs.as_str()) + match (i1.name, i2.name) { + (Some(name1), Some(name2)) => compare_names(name1.as_str(), name2.as_str()), + (Some(_), None) => Ordering::Greater, + (None, Some(_)) => Ordering::Less, + (None, None) => Ordering::Equal, + } } let tcx = cx.tcx(); From 65942d19cdb722db4544c4fcdcc0f054ff048701 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 15 Apr 2025 15:01:48 +1000 Subject: [PATCH 470/606] Avoid using `kw::Empty` for param names in rustdoc. --- src/librustdoc/html/render/mod.rs | 2 +- src/librustdoc/html/render/search_index.rs | 17 ++++++++++------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 21c823f49d15..adf15018ad2d 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -208,7 +208,7 @@ pub(crate) struct IndexItemFunctionType { inputs: Vec, output: Vec, where_clause: Vec>, - param_names: Vec, + param_names: Vec>, } impl IndexItemFunctionType { diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index b39701fae1d6..1360ab94cb1c 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -709,8 +709,11 @@ pub(crate) fn build_index( let mut result = Vec::new(); for (index, item) in self.items.iter().enumerate() { if let Some(ty) = &item.search_type - && let my = - ty.param_names.iter().map(|sym| sym.as_str()).collect::>() + && let my = ty + .param_names + .iter() + .filter_map(|sym| sym.map(|sym| sym.to_string())) + .collect::>() && my != prev { result.push((index, my.join(","))); @@ -1372,7 +1375,7 @@ fn simplify_fn_constraint<'a>( /// Used to allow type-based search on constants and statics. fn make_nullary_fn( clean_type: &clean::Type, -) -> (Vec, Vec, Vec, Vec>) { +) -> (Vec, Vec, Vec>, Vec>) { let mut rgen: FxIndexMap)> = Default::default(); let output = get_index_type(clean_type, vec![], &mut rgen); (vec![], vec![output], vec![], vec![]) @@ -1387,7 +1390,7 @@ fn get_fn_inputs_and_outputs( tcx: TyCtxt<'_>, impl_or_trait_generics: Option<&(clean::Type, clean::Generics)>, cache: &Cache, -) -> (Vec, Vec, Vec, Vec>) { +) -> (Vec, Vec, Vec>, Vec>) { let decl = &func.decl; let mut rgen: FxIndexMap)> = Default::default(); @@ -1441,10 +1444,10 @@ fn get_fn_inputs_and_outputs( simplified_params .iter() .map(|(name, (_idx, _traits))| match name { - SimplifiedParam::Symbol(name) => *name, - SimplifiedParam::Anonymous(_) => kw::Empty, + SimplifiedParam::Symbol(name) => Some(*name), + SimplifiedParam::Anonymous(_) => None, SimplifiedParam::AssociatedType(def_id, name) => { - Symbol::intern(&format!("{}::{}", tcx.item_name(*def_id), name)) + Some(Symbol::intern(&format!("{}::{}", tcx.item_name(*def_id), name))) } }) .collect(), From f3847f0639c851224bb709444ae76865c0b1959b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 8 Apr 2025 13:50:01 +1000 Subject: [PATCH 471/606] Remove some "name isn't empty" assertions. These were low value even before #137978 resulted in empty names being used much less. (Why check for non-emptiness in these three places? There are thousands of places in the compiler you could check.) --- compiler/rustc_ast_lowering/src/lib.rs | 1 - compiler/rustc_hir_typeck/src/expr.rs | 10 ++-------- compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs | 3 +-- 3 files changed, 3 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index b1d1c35e64a1..5be740609c7c 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1765,7 +1765,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ident: Ident, is_anon_in_path: IsAnonInPath, ) -> &'hir hir::Lifetime { - debug_assert_ne!(ident.name, kw::Empty); let res = self.resolver.get_lifetime_res(id).unwrap_or(LifetimeRes::Error); let res = match res { LifetimeRes::Param { param, .. } => hir::LifetimeName::Param(param), diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index de2f039cb1c8..7964b5f17c5c 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1600,11 +1600,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Ok(method) } Err(error) => { - if segment.ident.name == kw::Empty { - span_bug!(rcvr.span, "empty method name") - } else { - Err(self.report_method_error(expr.hir_id, rcvr_t, error, expected, false)) - } + Err(self.report_method_error(expr.hir_id, rcvr_t, error, expected, false)) } }; @@ -2942,9 +2938,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return Ty::new_error(self.tcx(), guar); } - let guar = if field.name == kw::Empty { - self.dcx().span_bug(field.span, "field name with no name") - } else if self.method_exists_for_diagnostic( + let guar = if self.method_exists_for_diagnostic( field, base_ty, expr.hir_id, diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 91190a32ff54..87d92b3fbde8 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -27,9 +27,9 @@ use rustc_middle::ty::{ }; use rustc_middle::{bug, span_bug}; use rustc_session::lint; +use rustc_span::Span; use rustc_span::def_id::LocalDefId; use rustc_span::hygiene::DesugaringKind; -use rustc_span::{Span, kw}; use rustc_trait_selection::error_reporting::infer::need_type_info::TypeAnnotationNeeded; use rustc_trait_selection::traits::{ self, NormalizeExt, ObligationCauseCode, StructurallyNormalizeExt, @@ -833,7 +833,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let trait_missing_method = matches!(error, method::MethodError::NoMatch(_)) && ty.normalized.is_trait(); - assert_ne!(item_name.name, kw::Empty); self.report_method_error( hir_id, ty.normalized, From 2b43e664964bd6eeff6d0a1787ab2ef2a04f3e94 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 9 Apr 2025 07:16:57 +1000 Subject: [PATCH 472/606] Remove a `kw::Empty` usage in symbol mangling. Field names are never empty, so the unwrap is unnecessary. --- compiler/rustc_symbol_mangling/src/v0.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index d28f10ba9e38..789de471ddc0 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -776,7 +776,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { self.push_disambiguator( disambiguated_field.disambiguator as u64, ); - self.push_ident(field_name.unwrap_or(kw::Empty).as_str()); + self.push_ident(field_name.unwrap().as_str()); field.print(self)?; } From c12b4aade031e4ca4babb9cdfbe53f466ae76462 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 9 Apr 2025 15:45:25 +1000 Subject: [PATCH 473/606] Use a dummy ident for a `lint_if_path_starts_with_module` call. This is pretty weird code. As the `HACK` comment indicates, we push the empty ident here only to make the path longer, so certain checks to occur within `lint_if_path_starts_with_module`. `dummy` is a better choice because it explicitly communicates that the actual value doesn't matter. --- compiler/rustc_resolve/src/imports.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 3f3b455f4db2..762e08b2be5f 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -1012,7 +1012,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // HACK(eddyb) `lint_if_path_starts_with_module` needs at least // 2 segments, so the `resolve_path` above won't trigger it. let mut full_path = import.module_path.clone(); - full_path.push(Segment::from_ident(Ident::empty())); + full_path.push(Segment::from_ident(Ident::dummy())); self.lint_if_path_starts_with_module(Some(finalize), &full_path, None); } From 2009ca6d88a363b84b4733e253835fe13ec96540 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Mon, 14 Apr 2025 13:54:14 +0000 Subject: [PATCH 474/606] Remove #![feature(no_sanitize)] --- library/core/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index dc06aa4c38d5..c2d65f073640 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -169,7 +169,6 @@ #![feature(negative_impls)] #![feature(never_type)] #![feature(no_core)] -#![feature(no_sanitize)] #![feature(optimize_attribute)] #![feature(prelude_import)] #![feature(repr_simd)] From 1cbdfab75d6dbf9c383ece8fe2e2642e5db2f2e7 Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Mon, 14 Apr 2025 13:54:49 +0000 Subject: [PATCH 475/606] Use full path for core::mem::transmute Suggested-by: Tamir Duberstein Signed-off-by: Alice Ryhl --- library/core/src/fmt/mod.rs | 2 +- library/core/src/fmt/rt.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 7ca390941bcd..580f95eddce7 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -7,7 +7,7 @@ use crate::char::{EscapeDebugExtArgs, MAX_LEN_UTF8}; use crate::marker::PhantomData; use crate::num::fmt as numfmt; use crate::ops::Deref; -use crate::{iter, mem, result, str}; +use crate::{iter, result, str}; mod builders; #[cfg(not(no_fp_fmt_parse))] diff --git a/library/core/src/fmt/rt.rs b/library/core/src/fmt/rt.rs index c36feff0b62d..b9cae8645cd3 100644 --- a/library/core/src/fmt/rt.rs +++ b/library/core/src/fmt/rt.rs @@ -76,7 +76,7 @@ macro_rules! argument_new { formatter: { let f: fn(&$t, &mut Formatter<'_>) -> Result = $f; // SAFETY: This is only called with `value`, which has the right type. - unsafe { mem::transmute(f) } + unsafe { core::mem::transmute(f) } }, #[cfg(any(sanitize = "cfi", sanitize = "kcfi"))] formatter: |ptr: NonNull<()>, fmt: &mut Formatter<'_>| { From 6513df96525704d3c40f16faf2672adaaa3186ac Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Mon, 14 Apr 2025 06:52:32 +0000 Subject: [PATCH 476/606] Add comment Co-authored-by: Ralf Jung --- library/core/src/fmt/rt.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/library/core/src/fmt/rt.rs b/library/core/src/fmt/rt.rs index b9cae8645cd3..adcfdd309b7e 100644 --- a/library/core/src/fmt/rt.rs +++ b/library/core/src/fmt/rt.rs @@ -72,6 +72,25 @@ macro_rules! argument_new { // a `fn(&T, ...)`, so the invariant is maintained. ty: ArgumentType::Placeholder { value: NonNull::<$t>::from_ref($x).cast(), + // The Rust ABI considers all pointers to be equivalent, so transmuting a fn(&T) to + // fn(NonNull<()>) and calling it with a NonNull<()> that points at a T is allowed. + // However, the CFI sanitizer does not allow this, and triggers a crash when it + // happens. + // + // To avoid this crash, we use a helper function when CFI is enabled. To avoid the + // cost of this helper function (mainly code-size) when it is not needed, we + // transmute the function pointer otherwise. + // + // This is similar to what the Rust compiler does internally with vtables when KCFI + // is enabled, where it generates trampoline functions that only serve to adjust the + // expected type of the argument. `ArgumentType::Placeholder` is a bit like a + // manually constructed trait object, so it is not surprising that the same approach + // has to be applied here as well. + // + // It is still considered problematic (from the Rust side) that CFI rejects entirely + // legal Rust programs, so we do not consider anything done here a stable guarantee, + // but meanwhile we carry this work-around to keep Rust compatible with CFI and + // KCFI. #[cfg(not(any(sanitize = "cfi", sanitize = "kcfi")))] formatter: { let f: fn(&$t, &mut Formatter<'_>) -> Result = $f; From 4ac3877521084501c44d3bea1251398448cb7ecd Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Tue, 15 Apr 2025 09:28:04 +0200 Subject: [PATCH 477/606] unstable book; document `macro_metavar_expr_concat` --- .../macro-metavar-expr-concat.md | 133 ++++++++++++++++++ .../language-features/macro-metavar-expr.md | 10 ++ .../src/library-features/concat-idents.md | 2 + 3 files changed, 145 insertions(+) create mode 100644 src/doc/unstable-book/src/language-features/macro-metavar-expr-concat.md create mode 100644 src/doc/unstable-book/src/language-features/macro-metavar-expr.md diff --git a/src/doc/unstable-book/src/language-features/macro-metavar-expr-concat.md b/src/doc/unstable-book/src/language-features/macro-metavar-expr-concat.md new file mode 100644 index 000000000000..b6dbdb144077 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/macro-metavar-expr-concat.md @@ -0,0 +1,133 @@ +# `macro_metavar_expr_concat` + +The tracking issue for this feature is: [#124225] + +------------------------ + +In stable Rust, there is no way to create new identifiers by joining identifiers to literals or other identifiers without using procedural macros such as [`paste`]. + `#![feature(macro_metavar_expr_concat)]` introduces a way to do this, using the concat metavariable expression. + +> This feature uses the syntax from [`macro_metavar_expr`] but is otherwise +> independent. It replaces the old unstable feature [`concat_idents`]. + +> This is an experimental feature; it and its syntax will require a RFC before stabilization. + + +### Overview + +`#![feature(macro_metavar_expr_concat)]` provides the `concat` metavariable expression for creating new identifiers: + +```rust +#![feature(macro_metavar_expr_concat)] + +macro_rules! create_some_structs { + ($name:ident) => { + pub struct ${ concat(First, $name) }; + pub struct ${ concat(Second, $name) }; + pub struct ${ concat(Third, $name) }; + } +} + +create_some_structs!(Thing); +``` + +This macro invocation expands to: + +```rust +pub struct FirstThing; +pub struct SecondThing; +pub struct ThirdThing; +``` + +### Syntax + +This feature builds upon the metavariable expression syntax `${ .. }` as specified in [RFC 3086] ([`macro_metavar_expr`]). + `concat` is available like `${ concat(items) }`, where `items` is a comma separated sequence of idents and/or literals. + +### Examples + +#### Create a function or method with a concatenated name + +```rust +#![feature(macro_metavar_expr_concat)] + +macro_rules! make_getter { + ($name:ident, $field: ident, $ret:ty) => { + impl $name { + pub fn ${ concat(get_, $field) }(&self) -> &$ret { + &self.$field + } + } + } +} + +pub struct Thing { + description: String, +} + +make_getter!(Thing, description, String); +``` + +This expands to: + +```rust +pub struct Thing { + description: String, +} + +impl Thing { + pub fn get_description(&self) -> &String { + &self.description + } +} +``` + +#### Create names for macro generated tests + +```rust +#![feature(macro_metavar_expr_concat)] + +macro_rules! test_math { + ($integer:ident) => { + #[test] + fn ${ concat(test_, $integer, _, addition) } () { + let a: $integer = 73; + let b: $integer = 42; + assert_eq!(a + b, 115) + } + + #[test] + fn ${ concat(test_, $integer, _, subtraction) } () { + let a: $integer = 73; + let b: $integer = 42; + assert_eq!(a - b, 31) + } + } +} + +test_math!(i32); +test_math!(u64); +test_math!(u128); +``` + +Running this returns the following output: + +```text +running 6 tests +test test_i32_subtraction ... ok +test test_i32_addition ... ok +test test_u128_addition ... ok +test test_u128_subtraction ... ok +test test_u64_addition ... ok +test test_u64_subtraction ... ok + +test result: ok. 6 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s +``` + +[`paste`]: https://crates.io/crates/paste +[RFC 3086]: https://rust-lang.github.io/rfcs/3086-macro-metavar-expr.html +[`concat_idents!`]: https://doc.rust-lang.org/nightly/std/macro.concat_idents.html +[`macro_metavar_expr`]: ../language-features/macro-metavar-expr.md +[`concat_idents`]: ../library-features/concat-idents.md +[#124225]: https://github.com/rust-lang/rust/issues/124225 +[declarative macros]: https://doc.rust-lang.org/stable/reference/macros-by-example.html diff --git a/src/doc/unstable-book/src/language-features/macro-metavar-expr.md b/src/doc/unstable-book/src/language-features/macro-metavar-expr.md new file mode 100644 index 000000000000..7ce64c1a3549 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/macro-metavar-expr.md @@ -0,0 +1,10 @@ +# `macro_metavar_expr` + +The tracking issue for this feature is: [#83527] + +------------------------ + +> This feature is not to be confused with [`macro_metavar_expr_concat`]. + +[`macro_metavar_expr_concat`]: ./macro-metavar-expr-concat.md +[#83527]: https://github.com/rust-lang/rust/issues/83527 diff --git a/src/doc/unstable-book/src/library-features/concat-idents.md b/src/doc/unstable-book/src/library-features/concat-idents.md index 73f6cfa21787..4366172fb996 100644 --- a/src/doc/unstable-book/src/library-features/concat-idents.md +++ b/src/doc/unstable-book/src/library-features/concat-idents.md @@ -6,6 +6,8 @@ The tracking issue for this feature is: [#29599] ------------------------ +> This feature is expected to be superseded by [`macro_metavar_expr_concat`](../language-features/macro-metavar-expr-concat.md). + The `concat_idents` feature adds a macro for concatenating multiple identifiers into one identifier. From fc8df06f4feb6cc051e15e6596821d276b0797bb Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Mon, 14 Apr 2025 18:24:30 +0200 Subject: [PATCH 478/606] update submodules if the directory doesn't exist --- src/bootstrap/src/core/config/config.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 25ec64f90b53..2266e61bf608 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -2888,6 +2888,13 @@ impl Config { let absolute_path = self.src.join(relative_path); + // NOTE: This check is required because `jj git clone` doesn't create directories for + // submodules, they are completely ignored. The code below assumes this directory exists, + // so create it here. + if !absolute_path.exists() { + t!(fs::create_dir_all(&absolute_path)); + } + // NOTE: The check for the empty directory is here because when running x.py the first time, // the submodule won't be checked out. Check it out now so we can build it. if !GitInfo::new(false, &absolute_path).is_managed_git_subrepository() From 1397dabd1ec2e58f0cea27fd281dac7104083cca Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Mon, 14 Apr 2025 19:04:34 +0200 Subject: [PATCH 479/606] fix typo --- src/tools/compiletest/src/runtest.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 24fc2ddb7410..093dc7fa56ca 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2383,7 +2383,7 @@ impl<'test> TestCx<'test> { if json { // escaped newlines in json strings should be readable - // in the stderr files. There's no point int being correct, + // in the stderr files. There's no point in being correct, // since only humans process the stderr files. // Thus we just turn escaped newlines back into newlines. normalized = normalized.replace("\\n", "\n"); From 6c441cc7a53e3c9ca0dd1957b8055ccdd851b488 Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Mon, 14 Apr 2025 19:04:34 +0200 Subject: [PATCH 480/606] canonicalize test build dir before normalizing it Fix fixes failures of the following tests when build directory is a symlink: - `tests/ui/error-codes/E{0464,0523}.rs` - `tests/ui/crate-loading/crateresolve{1,2}.rs` (those are the same tests) --- src/tools/compiletest/src/runtest.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 093dc7fa56ca..fc83ea420430 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2375,9 +2375,13 @@ impl<'test> TestCx<'test> { let rust_src_dir = rust_src_dir.read_link_utf8().unwrap_or(rust_src_dir.to_path_buf()); normalize_path(&rust_src_dir.join("library"), "$SRC_DIR_REAL"); + // Canonicalize test build directory path. + // Without this some tests fail if build directory is a symlink. + let output_base_dir = self.output_base_dir().canonicalize_utf8().unwrap(); + // eg. // /home/user/rust/build/x86_64-unknown-linux-gnu/test/ui//$name.$revision.$mode/ - normalize_path(&self.output_base_dir(), "$TEST_BUILD_DIR"); + normalize_path(&output_base_dir, "$TEST_BUILD_DIR"); // eg. /home/user/rust/build normalize_path(&self.config.build_root, "$BUILD_DIR"); From c49b0bdb1ad82ec4dd28c616ab08c72b06c81019 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Mon, 14 Apr 2025 19:40:47 +0200 Subject: [PATCH 481/606] Use `rust-cache` to speed-up `citool` compilation --- .github/workflows/ci.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 51dd0f81ed14..2e83bbf643fe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -53,6 +53,13 @@ jobs: steps: - name: Checkout the source code uses: actions/checkout@v4 + # Cache citool to make its build faster, as it's in the critical path. + # The rust-cache doesn't bleed into the main `job`, so it should not affect any other + # Rust compilation. + - name: Cache citool + uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8 + with: + workspaces: src/ci/citool - name: Calculate the CI job matrix env: COMMIT_MESSAGE: ${{ github.event.head_commit.message }} From 8887af72a0b1f37a34b02d488ca3278576e2d73d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Mon, 14 Apr 2025 20:48:51 +0200 Subject: [PATCH 482/606] Improve parse errors for lifetimes in type position --- compiler/rustc_parse/messages.ftl | 4 +- compiler/rustc_parse/src/errors.rs | 2 + compiler/rustc_parse/src/parser/ty.rs | 63 +++++++++++++++++-- .../gat-trait-path-parenthesised-args.rs | 2 +- .../gat-trait-path-parenthesised-args.stderr | 7 ++- .../trait-object-macro-matcher.e2015.stderr | 32 ++++++++++ .../trait-object-macro-matcher.e2021.stderr | 16 +++++ .../macro/trait-object-macro-matcher.rs | 12 +++- .../macro/trait-object-macro-matcher.stderr | 23 ------- .../recover/recover-ampersand-less-ref-ty.rs | 13 ++++ .../recover-ampersand-less-ref-ty.stderr | 24 +++++++ ...trait-object-lifetime-parens.e2015.stderr} | 13 ++-- .../trait-object-lifetime-parens.e2021.stderr | 51 +++++++++++++++ .../ui/parser/trait-object-lifetime-parens.rs | 14 ++++- 14 files changed, 234 insertions(+), 42 deletions(-) create mode 100644 tests/ui/parser/macro/trait-object-macro-matcher.e2015.stderr create mode 100644 tests/ui/parser/macro/trait-object-macro-matcher.e2021.stderr delete mode 100644 tests/ui/parser/macro/trait-object-macro-matcher.stderr create mode 100644 tests/ui/parser/recover/recover-ampersand-less-ref-ty.rs create mode 100644 tests/ui/parser/recover/recover-ampersand-less-ref-ty.stderr rename tests/ui/parser/{trait-object-lifetime-parens.stderr => trait-object-lifetime-parens.e2015.stderr} (60%) create mode 100644 tests/ui/parser/trait-object-lifetime-parens.e2021.stderr diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 93fa89b68b97..e2b5e1cdd0ad 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -642,7 +642,9 @@ parse_mut_on_nested_ident_pattern = `mut` must be attached to each individual bi .suggestion = add `mut` to each binding parse_mut_on_non_ident_pattern = `mut` must be followed by a named binding .suggestion = remove the `mut` prefix -parse_need_plus_after_trait_object_lifetime = lifetime in trait object type must be followed by `+` + +parse_need_plus_after_trait_object_lifetime = lifetimes must be followed by `+` to form a trait object type + .suggestion = consider adding a trait bound after the potential lifetime bound parse_nested_adt = `{$kw_str}` definition cannot be nested inside `{$keyword}` .suggestion = consider creating a new `{$kw_str}` definition instead of nesting diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index dfdef018bc37..b28939e062af 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -2806,6 +2806,8 @@ pub(crate) struct ReturnTypesUseThinArrow { pub(crate) struct NeedPlusAfterTraitObjectLifetime { #[primary_span] pub span: Span, + #[suggestion(code = " + /* Trait */", applicability = "has-placeholders")] + pub suggestion: Span, } #[derive(Diagnostic)] diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 93705da22c45..f468d5433d93 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -7,7 +7,7 @@ use rustc_ast::{ Pinnedness, PolyTraitRef, PreciseCapturingArg, TraitBoundModifiers, TraitObjectSyntax, Ty, TyKind, UnsafeBinderTy, }; -use rustc_errors::{Applicability, PResult}; +use rustc_errors::{Applicability, Diag, PResult}; use rustc_span::{ErrorGuaranteed, Ident, Span, kw, sym}; use thin_vec::{ThinVec, thin_vec}; @@ -411,6 +411,9 @@ impl<'a> Parser<'a> { TyKind::Path(None, path) if maybe_bounds => { self.parse_remaining_bounds_path(ThinVec::new(), path, lo, true) } + // For `('a) + …`, we know that `'a` in type position already lead to an error being + // emitted. To reduce output, let's indirectly suppress E0178 (bad `+` in type) and + // other irrelevant consequential errors. TyKind::TraitObject(bounds, TraitObjectSyntax::None) if maybe_bounds && bounds.len() == 1 && !trailing_plus => { @@ -425,12 +428,60 @@ impl<'a> Parser<'a> { } fn parse_bare_trait_object(&mut self, lo: Span, allow_plus: AllowPlus) -> PResult<'a, TyKind> { - let lt_no_plus = self.check_lifetime() && !self.look_ahead(1, |t| t.is_like_plus()); - let bounds = self.parse_generic_bounds_common(allow_plus)?; - if lt_no_plus { - self.dcx().emit_err(NeedPlusAfterTraitObjectLifetime { span: lo }); + // A lifetime only begins a bare trait object type if it is followed by `+`! + if self.token.is_lifetime() && !self.look_ahead(1, |t| t.is_like_plus()) { + // In Rust 2021 and beyond, we assume that the user didn't intend to write a bare trait + // object type with a leading lifetime bound since that seems very unlikely given the + // fact that `dyn`-less trait objects are *semantically* invalid. + if self.psess.edition.at_least_rust_2021() { + let lt = self.expect_lifetime(); + let mut err = self.dcx().struct_span_err(lo, "expected type, found lifetime"); + err.span_label(lo, "expected type"); + return Ok(match self.maybe_recover_ref_ty_no_leading_ampersand(lt, lo, err) { + Ok(ref_ty) => ref_ty, + Err(err) => TyKind::Err(err.emit()), + }); + } + + self.dcx().emit_err(NeedPlusAfterTraitObjectLifetime { + span: lo, + suggestion: lo.shrink_to_hi(), + }); + } + Ok(TyKind::TraitObject( + self.parse_generic_bounds_common(allow_plus)?, + TraitObjectSyntax::None, + )) + } + + fn maybe_recover_ref_ty_no_leading_ampersand<'cx>( + &mut self, + lt: Lifetime, + lo: Span, + mut err: Diag<'cx>, + ) -> Result> { + if !self.may_recover() { + return Err(err); + } + let snapshot = self.create_snapshot_for_diagnostic(); + let mutbl = self.parse_mutability(); + match self.parse_ty_no_plus() { + Ok(ty) => { + err.span_suggestion_verbose( + lo.shrink_to_lo(), + "you might have meant to write a reference type here", + "&", + Applicability::MaybeIncorrect, + ); + err.emit(); + Ok(TyKind::Ref(Some(lt), MutTy { ty, mutbl })) + } + Err(diag) => { + diag.cancel(); + self.restore_snapshot(snapshot); + Err(err) + } } - Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None)) } fn parse_remaining_bounds_path( diff --git a/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs b/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs index 85661c1b8448..294fb6743fbc 100644 --- a/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs +++ b/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs @@ -3,7 +3,7 @@ trait X { } fn foo<'a>(arg: Box>) {} - //~^ ERROR: lifetime in trait object type must be followed by `+` + //~^ ERROR: lifetimes must be followed by `+` to form a trait object type //~| ERROR: parenthesized generic arguments cannot be used //~| ERROR associated type takes 0 generic arguments but 1 generic argument //~| ERROR associated type takes 1 lifetime argument but 0 lifetime arguments diff --git a/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr b/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr index 99300ea1cb7f..e18d8198c945 100644 --- a/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr +++ b/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr @@ -1,8 +1,13 @@ -error: lifetime in trait object type must be followed by `+` +error: lifetimes must be followed by `+` to form a trait object type --> $DIR/gat-trait-path-parenthesised-args.rs:5:29 | LL | fn foo<'a>(arg: Box>) {} | ^^ + | +help: consider adding a trait bound after the potential lifetime bound + | +LL | fn foo<'a>(arg: Box>) {} + | +++++++++++++ error: parenthesized generic arguments cannot be used in associated type constraints --> $DIR/gat-trait-path-parenthesised-args.rs:5:27 diff --git a/tests/ui/parser/macro/trait-object-macro-matcher.e2015.stderr b/tests/ui/parser/macro/trait-object-macro-matcher.e2015.stderr new file mode 100644 index 000000000000..f2db351de4a7 --- /dev/null +++ b/tests/ui/parser/macro/trait-object-macro-matcher.e2015.stderr @@ -0,0 +1,32 @@ +error: lifetimes must be followed by `+` to form a trait object type + --> $DIR/trait-object-macro-matcher.rs:17:8 + | +LL | m!('static); + | ^^^^^^^ + | +help: consider adding a trait bound after the potential lifetime bound + | +LL | m!('static + /* Trait */); + | +++++++++++++ + +error: lifetimes must be followed by `+` to form a trait object type + --> $DIR/trait-object-macro-matcher.rs:17:8 + | +LL | m!('static); + | ^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: consider adding a trait bound after the potential lifetime bound + | +LL | m!('static + /* Trait */); + | +++++++++++++ + +error[E0224]: at least one trait is required for an object type + --> $DIR/trait-object-macro-matcher.rs:17:8 + | +LL | m!('static); + | ^^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0224`. diff --git a/tests/ui/parser/macro/trait-object-macro-matcher.e2021.stderr b/tests/ui/parser/macro/trait-object-macro-matcher.e2021.stderr new file mode 100644 index 000000000000..7d9e8d795d18 --- /dev/null +++ b/tests/ui/parser/macro/trait-object-macro-matcher.e2021.stderr @@ -0,0 +1,16 @@ +error: expected type, found lifetime + --> $DIR/trait-object-macro-matcher.rs:17:8 + | +LL | m!('static); + | ^^^^^^^ expected type + +error: expected type, found lifetime + --> $DIR/trait-object-macro-matcher.rs:17:8 + | +LL | m!('static); + | ^^^^^^^ expected type + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/macro/trait-object-macro-matcher.rs b/tests/ui/parser/macro/trait-object-macro-matcher.rs index d4ec199070e7..ba61752fe402 100644 --- a/tests/ui/parser/macro/trait-object-macro-matcher.rs +++ b/tests/ui/parser/macro/trait-object-macro-matcher.rs @@ -1,6 +1,10 @@ // A single lifetime is not parsed as a type. // `ty` matcher in particular doesn't accept a single lifetime +//@ revisions: e2015 e2021 +//@[e2015] edition: 2015 +//@[e2021] edition: 2021 + macro_rules! m { ($t: ty) => { let _: $t; @@ -8,8 +12,10 @@ macro_rules! m { } fn main() { + //[e2021]~vv ERROR expected type, found lifetime + //[e2021]~v ERROR expected type, found lifetime m!('static); - //~^ ERROR lifetime in trait object type must be followed by `+` - //~| ERROR lifetime in trait object type must be followed by `+` - //~| ERROR at least one trait is required for an object type + //[e2015]~^ ERROR lifetimes must be followed by `+` to form a trait object type + //[e2015]~| ERROR lifetimes must be followed by `+` to form a trait object type + //[e2015]~| ERROR at least one trait is required for an object type } diff --git a/tests/ui/parser/macro/trait-object-macro-matcher.stderr b/tests/ui/parser/macro/trait-object-macro-matcher.stderr deleted file mode 100644 index 81dca6f71c43..000000000000 --- a/tests/ui/parser/macro/trait-object-macro-matcher.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error: lifetime in trait object type must be followed by `+` - --> $DIR/trait-object-macro-matcher.rs:11:8 - | -LL | m!('static); - | ^^^^^^^ - -error: lifetime in trait object type must be followed by `+` - --> $DIR/trait-object-macro-matcher.rs:11:8 - | -LL | m!('static); - | ^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0224]: at least one trait is required for an object type - --> $DIR/trait-object-macro-matcher.rs:11:8 - | -LL | m!('static); - | ^^^^^^^ - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0224`. diff --git a/tests/ui/parser/recover/recover-ampersand-less-ref-ty.rs b/tests/ui/parser/recover/recover-ampersand-less-ref-ty.rs new file mode 100644 index 000000000000..8f1a42473b5a --- /dev/null +++ b/tests/ui/parser/recover/recover-ampersand-less-ref-ty.rs @@ -0,0 +1,13 @@ +//@ edition: 2021 + +struct Entity<'a> { + name: 'a str, //~ ERROR expected type, found lifetime + //~^ HELP you might have meant to write a reference type here +} + +struct Buffer<'buf> { + bytes: 'buf mut [u8], //~ ERROR expected type, found lifetime + //~^ HELP you might have meant to write a reference type here +} + +fn main() {} diff --git a/tests/ui/parser/recover/recover-ampersand-less-ref-ty.stderr b/tests/ui/parser/recover/recover-ampersand-less-ref-ty.stderr new file mode 100644 index 000000000000..033348b2c405 --- /dev/null +++ b/tests/ui/parser/recover/recover-ampersand-less-ref-ty.stderr @@ -0,0 +1,24 @@ +error: expected type, found lifetime + --> $DIR/recover-ampersand-less-ref-ty.rs:4:11 + | +LL | name: 'a str, + | ^^ expected type + | +help: you might have meant to write a reference type here + | +LL | name: &'a str, + | + + +error: expected type, found lifetime + --> $DIR/recover-ampersand-less-ref-ty.rs:9:12 + | +LL | bytes: 'buf mut [u8], + | ^^^^ expected type + | +help: you might have meant to write a reference type here + | +LL | bytes: &'buf mut [u8], + | + + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/trait-object-lifetime-parens.stderr b/tests/ui/parser/trait-object-lifetime-parens.e2015.stderr similarity index 60% rename from tests/ui/parser/trait-object-lifetime-parens.stderr rename to tests/ui/parser/trait-object-lifetime-parens.e2015.stderr index 280c0e40c640..cf0b3d77f5b5 100644 --- a/tests/ui/parser/trait-object-lifetime-parens.stderr +++ b/tests/ui/parser/trait-object-lifetime-parens.e2015.stderr @@ -1,5 +1,5 @@ error: parenthesized lifetime bounds are not supported - --> $DIR/trait-object-lifetime-parens.rs:5:21 + --> $DIR/trait-object-lifetime-parens.rs:9:21 | LL | fn f<'a, T: Trait + ('a)>() {} | ^^^^ @@ -11,7 +11,7 @@ LL + fn f<'a, T: Trait + 'a>() {} | error: parenthesized lifetime bounds are not supported - --> $DIR/trait-object-lifetime-parens.rs:8:24 + --> $DIR/trait-object-lifetime-parens.rs:12:24 | LL | let _: Box; | ^^^^ @@ -22,11 +22,16 @@ LL - let _: Box; LL + let _: Box; | -error: lifetime in trait object type must be followed by `+` - --> $DIR/trait-object-lifetime-parens.rs:10:17 +error: lifetimes must be followed by `+` to form a trait object type + --> $DIR/trait-object-lifetime-parens.rs:16:17 | LL | let _: Box<('a) + Trait>; | ^^ + | +help: consider adding a trait bound after the potential lifetime bound + | +LL | let _: Box<('a + /* Trait */) + Trait>; + | +++++++++++++ error: aborting due to 3 previous errors diff --git a/tests/ui/parser/trait-object-lifetime-parens.e2021.stderr b/tests/ui/parser/trait-object-lifetime-parens.e2021.stderr new file mode 100644 index 000000000000..3518321ea201 --- /dev/null +++ b/tests/ui/parser/trait-object-lifetime-parens.e2021.stderr @@ -0,0 +1,51 @@ +error: parenthesized lifetime bounds are not supported + --> $DIR/trait-object-lifetime-parens.rs:9:21 + | +LL | fn f<'a, T: Trait + ('a)>() {} + | ^^^^ + | +help: remove the parentheses + | +LL - fn f<'a, T: Trait + ('a)>() {} +LL + fn f<'a, T: Trait + 'a>() {} + | + +error: parenthesized lifetime bounds are not supported + --> $DIR/trait-object-lifetime-parens.rs:12:24 + | +LL | let _: Box; + | ^^^^ + | +help: remove the parentheses + | +LL - let _: Box; +LL + let _: Box; + | + +error: expected type, found lifetime + --> $DIR/trait-object-lifetime-parens.rs:16:17 + | +LL | let _: Box<('a) + Trait>; + | ^^ expected type + +error[E0178]: expected a path on the left-hand side of `+`, not `((/*ERROR*/))` + --> $DIR/trait-object-lifetime-parens.rs:16:16 + | +LL | let _: Box<('a) + Trait>; + | ^^^^^^^^^^^^ expected a path + +error[E0782]: expected a type, found a trait + --> $DIR/trait-object-lifetime-parens.rs:12:16 + | +LL | let _: Box; + | ^^^^^^^^^^^^ + | +help: you can add the `dyn` keyword if you want a trait object + | +LL | let _: Box; + | +++ + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0178, E0782. +For more information about an error, try `rustc --explain E0178`. diff --git a/tests/ui/parser/trait-object-lifetime-parens.rs b/tests/ui/parser/trait-object-lifetime-parens.rs index f44ebe5ba5bf..0ff4660bb0d5 100644 --- a/tests/ui/parser/trait-object-lifetime-parens.rs +++ b/tests/ui/parser/trait-object-lifetime-parens.rs @@ -1,4 +1,8 @@ -#![allow(bare_trait_objects)] +//@ revisions: e2015 e2021 +//@[e2015] edition: 2015 +//@[e2021] edition: 2021 + +#![cfg_attr(e2015, allow(bare_trait_objects))] trait Trait {} @@ -6,8 +10,12 @@ fn f<'a, T: Trait + ('a)>() {} //~ ERROR parenthesized lifetime bounds are not s fn check<'a>() { let _: Box; //~ ERROR parenthesized lifetime bounds are not supported - // FIXME: It'd be great if we could add suggestion to the following case. - let _: Box<('a) + Trait>; //~ ERROR lifetime in trait object type must be followed by `+` + //[e2021]~^ ERROR expected a type, found a trait + // FIXME: It'd be great if we could suggest removing the parentheses here too. + //[e2015]~v ERROR lifetimes must be followed by `+` to form a trait object type + let _: Box<('a) + Trait>; + //[e2021]~^ ERROR expected type, found lifetime + //[e2021]~| ERROR expected a path on the left-hand side of `+` } fn main() {} From 6242335fdb7444876abf1c3669b6aab1649a0a64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Tue, 15 Apr 2025 07:44:24 +0200 Subject: [PATCH 483/606] Improve diagnostic for E0178 (bad `+` in type) Namely, use a more sensical primary span. Don't pretty-print AST nodes for the diagnostic message. Why: * It's lossy (e.g., it doesn't replicate trailing `+`s in trait objects. * It's prone to leak error nodes (printed as `(/*ERROR*/)`) since the LHS can easily represent recovered code (e.g., `fn(i32?) + T`). --- compiler/rustc_parse/messages.ftl | 2 +- compiler/rustc_parse/src/errors.rs | 1 - .../rustc_parse/src/parser/diagnostics.rs | 10 ++++----- tests/ui/did_you_mean/E0178.stderr | 18 ++++++++------- ...reference-without-parens-suggestion.stderr | 8 +++---- .../ui/impl-trait/impl-trait-plus-priority.rs | 4 ++-- .../impl-trait-plus-priority.stderr | 10 +++++---- .../issues/issue-73568-lifetime-after-mut.rs | 2 +- .../issue-73568-lifetime-after-mut.stderr | 4 ++-- tests/ui/parser/trait-object-bad-parens.rs | 12 ++++------ .../ui/parser/trait-object-bad-parens.stderr | 22 +++++++++---------- .../trait-object-lifetime-parens.e2021.stderr | 4 ++-- .../parser/trait-object-polytrait-priority.rs | 2 +- .../trait-object-polytrait-priority.stderr | 4 ++-- 14 files changed, 51 insertions(+), 52 deletions(-) diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index e2b5e1cdd0ad..80cd87a69f78 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -543,7 +543,7 @@ parse_maybe_recover_from_bad_qpath_stage_2 = .suggestion = types that don't start with an identifier need to be surrounded with angle brackets in qualified paths parse_maybe_recover_from_bad_type_plus = - expected a path on the left-hand side of `+`, not `{$ty}` + expected a path on the left-hand side of `+` parse_maybe_report_ambiguous_plus = ambiguous `+` in a type diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index b28939e062af..aad8a8bc2052 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -30,7 +30,6 @@ pub(crate) struct AmbiguousPlus { #[derive(Diagnostic)] #[diag(parse_maybe_recover_from_bad_type_plus, code = E0178)] pub(crate) struct BadTypePlus { - pub ty: String, #[primary_span] pub span: Span, #[subdiagnostic] diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index ef044fe9d638..40246ed78be3 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -1636,19 +1636,19 @@ impl<'a> Parser<'a> { self.bump(); // `+` let _bounds = self.parse_generic_bounds()?; - let sum_span = ty.span.to(self.prev_token.span); - let sub = match &ty.kind { TyKind::Ref(_lifetime, mut_ty) => { let lo = mut_ty.ty.span.shrink_to_lo(); let hi = self.prev_token.span.shrink_to_hi(); BadTypePlusSub::AddParen { suggestion: AddParen { lo, hi } } } - TyKind::Ptr(..) | TyKind::BareFn(..) => BadTypePlusSub::ForgotParen { span: sum_span }, - _ => BadTypePlusSub::ExpectPath { span: sum_span }, + TyKind::Ptr(..) | TyKind::BareFn(..) => { + BadTypePlusSub::ForgotParen { span: ty.span.to(self.prev_token.span) } + } + _ => BadTypePlusSub::ExpectPath { span: ty.span }, }; - self.dcx().emit_err(BadTypePlus { ty: pprust::ty_to_string(ty), span: sum_span, sub }); + self.dcx().emit_err(BadTypePlus { span: ty.span, sub }); Ok(()) } diff --git a/tests/ui/did_you_mean/E0178.stderr b/tests/ui/did_you_mean/E0178.stderr index 5f289da8a6c3..36e4dbdf7c45 100644 --- a/tests/ui/did_you_mean/E0178.stderr +++ b/tests/ui/did_you_mean/E0178.stderr @@ -1,41 +1,43 @@ -error[E0178]: expected a path on the left-hand side of `+`, not `&'a Foo` +error[E0178]: expected a path on the left-hand side of `+` --> $DIR/E0178.rs:6:8 | LL | w: &'a Foo + Copy, - | ^^^^^^^^^^^^^^ + | ^^^^^^^ | help: try adding parentheses | LL | w: &'a (Foo + Copy), | + + -error[E0178]: expected a path on the left-hand side of `+`, not `&'a Foo` +error[E0178]: expected a path on the left-hand side of `+` --> $DIR/E0178.rs:7:8 | LL | x: &'a Foo + 'a, - | ^^^^^^^^^^^^ + | ^^^^^^^ | help: try adding parentheses | LL | x: &'a (Foo + 'a), | + + -error[E0178]: expected a path on the left-hand side of `+`, not `&'a mut Foo` +error[E0178]: expected a path on the left-hand side of `+` --> $DIR/E0178.rs:8:8 | LL | y: &'a mut Foo + 'a, - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ | help: try adding parentheses | LL | y: &'a mut (Foo + 'a), | + + -error[E0178]: expected a path on the left-hand side of `+`, not `fn() -> Foo` +error[E0178]: expected a path on the left-hand side of `+` --> $DIR/E0178.rs:9:8 | LL | z: fn() -> Foo + 'a, - | ^^^^^^^^^^^^^^^^ perhaps you forgot parentheses? + | ^^^^^^^^^^^----- + | | + | perhaps you forgot parentheses? error: aborting due to 4 previous errors diff --git a/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr b/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr index 4fee6cc9a222..762b37b9e9d6 100644 --- a/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr +++ b/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr @@ -1,19 +1,19 @@ -error[E0178]: expected a path on the left-hand side of `+`, not `&Copy` +error[E0178]: expected a path on the left-hand side of `+` --> $DIR/trait-object-reference-without-parens-suggestion.rs:4:12 | LL | let _: &Copy + 'static; - | ^^^^^^^^^^^^^^^ + | ^^^^^ | help: try adding parentheses | LL | let _: &(Copy + 'static); | + + -error[E0178]: expected a path on the left-hand side of `+`, not `&'static Copy` +error[E0178]: expected a path on the left-hand side of `+` --> $DIR/trait-object-reference-without-parens-suggestion.rs:6:12 | LL | let _: &'static Copy + 'static; - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ | help: try adding parentheses | diff --git a/tests/ui/impl-trait/impl-trait-plus-priority.rs b/tests/ui/impl-trait/impl-trait-plus-priority.rs index 5575493a17d3..8f76d4126622 100644 --- a/tests/ui/impl-trait/impl-trait-plus-priority.rs +++ b/tests/ui/impl-trait/impl-trait-plus-priority.rs @@ -27,7 +27,7 @@ type A = fn() -> impl A + B; type A = fn() -> dyn A + B; //~^ ERROR ambiguous `+` in a type type A = fn() -> A + B; -//~^ ERROR expected a path on the left-hand side of `+`, not `fn() -> A` +//~^ ERROR expected a path on the left-hand side of `+` type A = Fn() -> impl A +; //~^ ERROR ambiguous `+` in a type @@ -44,6 +44,6 @@ type A = &impl A + B; type A = &dyn A + B; //~^ ERROR ambiguous `+` in a type type A = &A + B; -//~^ ERROR expected a path on the left-hand side of `+`, not `&A` +//~^ ERROR expected a path on the left-hand side of `+` fn main() {} diff --git a/tests/ui/impl-trait/impl-trait-plus-priority.stderr b/tests/ui/impl-trait/impl-trait-plus-priority.stderr index 03e7910095a9..161206579603 100644 --- a/tests/ui/impl-trait/impl-trait-plus-priority.stderr +++ b/tests/ui/impl-trait/impl-trait-plus-priority.stderr @@ -31,11 +31,13 @@ help: try adding parentheses LL | type A = fn() -> (dyn A + B); | + + -error[E0178]: expected a path on the left-hand side of `+`, not `fn() -> A` +error[E0178]: expected a path on the left-hand side of `+` --> $DIR/impl-trait-plus-priority.rs:29:10 | LL | type A = fn() -> A + B; - | ^^^^^^^^^^^^^ perhaps you forgot parentheses? + | ^^^^^^^^^---- + | | + | perhaps you forgot parentheses? error: ambiguous `+` in a type --> $DIR/impl-trait-plus-priority.rs:32:18 @@ -103,11 +105,11 @@ help: try adding parentheses LL | type A = &(dyn A + B); | + + -error[E0178]: expected a path on the left-hand side of `+`, not `&A` +error[E0178]: expected a path on the left-hand side of `+` --> $DIR/impl-trait-plus-priority.rs:46:10 | LL | type A = &A + B; - | ^^^^^^ + | ^^ | help: try adding parentheses | diff --git a/tests/ui/parser/issues/issue-73568-lifetime-after-mut.rs b/tests/ui/parser/issues/issue-73568-lifetime-after-mut.rs index cf754a6854ec..782a46ab060e 100644 --- a/tests/ui/parser/issues/issue-73568-lifetime-after-mut.rs +++ b/tests/ui/parser/issues/issue-73568-lifetime-after-mut.rs @@ -12,7 +12,7 @@ mac!('a); // avoid false positives fn y<'a>(y: &mut 'a + Send) { - //~^ ERROR expected a path on the left-hand side of `+`, not `&mut 'a` + //~^ ERROR expected a path on the left-hand side of `+` //~| ERROR at least one trait is required for an object type let z = y as &mut 'a + Send; //~^ ERROR expected value, found trait `Send` diff --git a/tests/ui/parser/issues/issue-73568-lifetime-after-mut.stderr b/tests/ui/parser/issues/issue-73568-lifetime-after-mut.stderr index 6b8f8e4fe4ee..ae1ed72853de 100644 --- a/tests/ui/parser/issues/issue-73568-lifetime-after-mut.stderr +++ b/tests/ui/parser/issues/issue-73568-lifetime-after-mut.stderr @@ -10,11 +10,11 @@ LL - fn x<'a>(x: &mut 'a i32){} LL + fn x<'a>(x: &'a mut i32){} | -error[E0178]: expected a path on the left-hand side of `+`, not `&mut 'a` +error[E0178]: expected a path on the left-hand side of `+` --> $DIR/issue-73568-lifetime-after-mut.rs:14:13 | LL | fn y<'a>(y: &mut 'a + Send) { - | ^^^^^^^^^^^^^^ + | ^^^^^^^ | help: try adding parentheses | diff --git a/tests/ui/parser/trait-object-bad-parens.rs b/tests/ui/parser/trait-object-bad-parens.rs index 8e267c7448fe..bb047a4b4314 100644 --- a/tests/ui/parser/trait-object-bad-parens.rs +++ b/tests/ui/parser/trait-object-bad-parens.rs @@ -5,12 +5,8 @@ auto trait Auto {} fn main() { - let _: Box<((Auto)) + Auto>; - //~^ ERROR expected a path on the left-hand side of `+`, not `((Auto))` - let _: Box<(Auto + Auto) + Auto>; - //~^ ERROR expected a path on the left-hand side of `+`, not `(Auto + Auto)` - let _: Box<(Auto +) + Auto>; - //~^ ERROR expected a path on the left-hand side of `+`, not `(Auto)` - let _: Box<(dyn Auto) + Auto>; - //~^ ERROR expected a path on the left-hand side of `+`, not `(dyn Auto)` + let _: Box<((Auto)) + Auto>; //~ ERROR expected a path on the left-hand side of `+` + let _: Box<(Auto + Auto) + Auto>; //~ ERROR expected a path on the left-hand side of `+` + let _: Box<(Auto +) + Auto>; //~ ERROR expected a path on the left-hand side of `+` + let _: Box<(dyn Auto) + Auto>; //~ ERROR expected a path on the left-hand side of `+` } diff --git a/tests/ui/parser/trait-object-bad-parens.stderr b/tests/ui/parser/trait-object-bad-parens.stderr index 74e484eebee1..7c2559ce89fd 100644 --- a/tests/ui/parser/trait-object-bad-parens.stderr +++ b/tests/ui/parser/trait-object-bad-parens.stderr @@ -1,26 +1,26 @@ -error[E0178]: expected a path on the left-hand side of `+`, not `((Auto))` +error[E0178]: expected a path on the left-hand side of `+` --> $DIR/trait-object-bad-parens.rs:8:16 | LL | let _: Box<((Auto)) + Auto>; - | ^^^^^^^^^^^^^^^ expected a path + | ^^^^^^^^ expected a path -error[E0178]: expected a path on the left-hand side of `+`, not `(Auto + Auto)` - --> $DIR/trait-object-bad-parens.rs:10:16 +error[E0178]: expected a path on the left-hand side of `+` + --> $DIR/trait-object-bad-parens.rs:9:16 | LL | let _: Box<(Auto + Auto) + Auto>; - | ^^^^^^^^^^^^^^^^^^^^ expected a path + | ^^^^^^^^^^^^^ expected a path -error[E0178]: expected a path on the left-hand side of `+`, not `(Auto)` - --> $DIR/trait-object-bad-parens.rs:12:16 +error[E0178]: expected a path on the left-hand side of `+` + --> $DIR/trait-object-bad-parens.rs:10:16 | LL | let _: Box<(Auto +) + Auto>; - | ^^^^^^^^^^^^^^^ expected a path + | ^^^^^^^^ expected a path -error[E0178]: expected a path on the left-hand side of `+`, not `(dyn Auto)` - --> $DIR/trait-object-bad-parens.rs:14:16 +error[E0178]: expected a path on the left-hand side of `+` + --> $DIR/trait-object-bad-parens.rs:11:16 | LL | let _: Box<(dyn Auto) + Auto>; - | ^^^^^^^^^^^^^^^^^ expected a path + | ^^^^^^^^^^ expected a path error: aborting due to 4 previous errors diff --git a/tests/ui/parser/trait-object-lifetime-parens.e2021.stderr b/tests/ui/parser/trait-object-lifetime-parens.e2021.stderr index 3518321ea201..b65c079788a9 100644 --- a/tests/ui/parser/trait-object-lifetime-parens.e2021.stderr +++ b/tests/ui/parser/trait-object-lifetime-parens.e2021.stderr @@ -28,11 +28,11 @@ error: expected type, found lifetime LL | let _: Box<('a) + Trait>; | ^^ expected type -error[E0178]: expected a path on the left-hand side of `+`, not `((/*ERROR*/))` +error[E0178]: expected a path on the left-hand side of `+` --> $DIR/trait-object-lifetime-parens.rs:16:16 | LL | let _: Box<('a) + Trait>; - | ^^^^^^^^^^^^ expected a path + | ^^^^ expected a path error[E0782]: expected a type, found a trait --> $DIR/trait-object-lifetime-parens.rs:12:16 diff --git a/tests/ui/parser/trait-object-polytrait-priority.rs b/tests/ui/parser/trait-object-polytrait-priority.rs index e7f085104ae9..85568f0fe1b1 100644 --- a/tests/ui/parser/trait-object-polytrait-priority.rs +++ b/tests/ui/parser/trait-object-polytrait-priority.rs @@ -4,6 +4,6 @@ trait Trait<'a> {} fn main() { let _: &for<'a> Trait<'a> + 'static; - //~^ ERROR expected a path on the left-hand side of `+`, not `&for<'a> Trait<'a>` + //~^ ERROR expected a path on the left-hand side of `+` //~| HELP try adding parentheses } diff --git a/tests/ui/parser/trait-object-polytrait-priority.stderr b/tests/ui/parser/trait-object-polytrait-priority.stderr index 8cb564e79300..a291a8e229c4 100644 --- a/tests/ui/parser/trait-object-polytrait-priority.stderr +++ b/tests/ui/parser/trait-object-polytrait-priority.stderr @@ -1,8 +1,8 @@ -error[E0178]: expected a path on the left-hand side of `+`, not `&for<'a> Trait<'a>` +error[E0178]: expected a path on the left-hand side of `+` --> $DIR/trait-object-polytrait-priority.rs:6:12 | LL | let _: &for<'a> Trait<'a> + 'static; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ | help: try adding parentheses | From 1dd77cd24acd5a960c4ddaa7a368d1518a995407 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Thu, 27 Mar 2025 18:30:51 +0100 Subject: [PATCH 484/606] Implement `pin!()` using `super let`. --- compiler/rustc_span/src/symbol.rs | 1 - library/core/src/pin.rs | 137 +++++------------- library/coretests/tests/pin_macro.rs | 1 + .../feature-gate-unsafe_pin_internals.rs | 16 -- .../feature-gate-unsafe_pin_internals.stderr | 15 -- tests/ui/pin-macro/cant_access_internals.rs | 12 -- .../ui/pin-macro/cant_access_internals.stderr | 12 -- 7 files changed, 36 insertions(+), 158 deletions(-) delete mode 100644 tests/ui/feature-gates/feature-gate-unsafe_pin_internals.rs delete mode 100644 tests/ui/feature-gates/feature-gate-unsafe_pin_internals.stderr delete mode 100644 tests/ui/pin-macro/cant_access_internals.rs delete mode 100644 tests/ui/pin-macro/cant_access_internals.stderr diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index d1f3eb16e4e4..4f6e64dc1271 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -2215,7 +2215,6 @@ symbols! { unsafe_extern_blocks, unsafe_fields, unsafe_no_drop_flag, - unsafe_pin_internals, unsafe_pinned, unsafe_unpin, unsize, diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index 48ed5ae451e4..9e6acf04bf72 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -1092,24 +1092,15 @@ pub use self::unsafe_pinned::UnsafePinned; #[rustc_pub_transparent] #[derive(Copy, Clone)] pub struct Pin { - // FIXME(#93176): this field is made `#[unstable] #[doc(hidden)] pub` to: - // - deter downstream users from accessing it (which would be unsound!), - // - let the `pin!` macro access it (such a macro requires using struct - // literal syntax in order to benefit from lifetime extension). - // - // However, if the `Deref` impl exposes a field with the same name as this - // field, then the two will collide, resulting in a confusing error when the - // user attempts to access the field through a `Pin`. Therefore, the - // name `__pointer` is designed to be unlikely to collide with any other - // field. Long-term, macro hygiene is expected to offer a more robust - // alternative, alongside `unsafe` fields. - #[unstable(feature = "unsafe_pin_internals", issue = "none")] - #[doc(hidden)] - pub __pointer: Ptr, + /// Only public for bootstrap. + #[cfg(bootstrap)] + pub pointer: Ptr, + #[cfg(not(bootstrap))] + pointer: Ptr, } // The following implementations aren't derived in order to avoid soundness -// issues. `&self.__pointer` should not be accessible to untrusted trait +// issues. `&self.pointer` should not be accessible to untrusted trait // implementations. // // See for more details. @@ -1223,7 +1214,7 @@ impl> Pin { #[rustc_const_stable(feature = "const_pin", since = "1.84.0")] #[stable(feature = "pin_into_inner", since = "1.39.0")] pub const fn into_inner(pin: Pin) -> Ptr { - pin.__pointer + pin.pointer } } @@ -1360,7 +1351,7 @@ impl Pin { #[rustc_const_stable(feature = "const_pin", since = "1.84.0")] #[stable(feature = "pin", since = "1.33.0")] pub const unsafe fn new_unchecked(pointer: Ptr) -> Pin { - Pin { __pointer: pointer } + Pin { pointer } } /// Gets a shared reference to the pinned value this [`Pin`] points to. @@ -1374,7 +1365,7 @@ impl Pin { #[inline(always)] pub fn as_ref(&self) -> Pin<&Ptr::Target> { // SAFETY: see documentation on this function - unsafe { Pin::new_unchecked(&*self.__pointer) } + unsafe { Pin::new_unchecked(&*self.pointer) } } } @@ -1418,7 +1409,7 @@ impl Pin { #[inline(always)] pub fn as_mut(&mut self) -> Pin<&mut Ptr::Target> { // SAFETY: see documentation on this function - unsafe { Pin::new_unchecked(&mut *self.__pointer) } + unsafe { Pin::new_unchecked(&mut *self.pointer) } } /// Gets `Pin<&mut T>` to the underlying pinned value from this nested `Pin`-pointer. @@ -1485,7 +1476,7 @@ impl Pin { where Ptr::Target: Sized, { - *(self.__pointer) = value; + *(self.pointer) = value; } } @@ -1513,7 +1504,7 @@ impl Pin { #[rustc_const_stable(feature = "const_pin", since = "1.84.0")] #[stable(feature = "pin_into_inner", since = "1.39.0")] pub const unsafe fn into_inner_unchecked(pin: Pin) -> Ptr { - pin.__pointer + pin.pointer } } @@ -1539,7 +1530,7 @@ impl<'a, T: ?Sized> Pin<&'a T> { U: ?Sized, F: FnOnce(&T) -> &U, { - let pointer = &*self.__pointer; + let pointer = &*self.pointer; let new_pointer = func(pointer); // SAFETY: the safety contract for `new_unchecked` must be @@ -1569,7 +1560,7 @@ impl<'a, T: ?Sized> Pin<&'a T> { #[rustc_const_stable(feature = "const_pin", since = "1.84.0")] #[stable(feature = "pin", since = "1.33.0")] pub const fn get_ref(self) -> &'a T { - self.__pointer + self.pointer } } @@ -1580,7 +1571,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { #[rustc_const_stable(feature = "const_pin", since = "1.84.0")] #[stable(feature = "pin", since = "1.33.0")] pub const fn into_ref(self) -> Pin<&'a T> { - Pin { __pointer: self.__pointer } + Pin { pointer: self.pointer } } /// Gets a mutable reference to the data inside of this `Pin`. @@ -1600,7 +1591,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { where T: Unpin, { - self.__pointer + self.pointer } /// Gets a mutable reference to the data inside of this `Pin`. @@ -1618,7 +1609,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { #[stable(feature = "pin", since = "1.33.0")] #[rustc_const_stable(feature = "const_pin", since = "1.84.0")] pub const unsafe fn get_unchecked_mut(self) -> &'a mut T { - self.__pointer + self.pointer } /// Constructs a new pin by mapping the interior value. @@ -1705,21 +1696,21 @@ impl LegacyReceiver for Pin {} #[stable(feature = "pin", since = "1.33.0")] impl fmt::Debug for Pin { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&self.__pointer, f) + fmt::Debug::fmt(&self.pointer, f) } } #[stable(feature = "pin", since = "1.33.0")] impl fmt::Display for Pin { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(&self.__pointer, f) + fmt::Display::fmt(&self.pointer, f) } } #[stable(feature = "pin", since = "1.33.0")] impl fmt::Pointer for Pin { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Pointer::fmt(&self.__pointer, f) + fmt::Pointer::fmt(&self.pointer, f) } } @@ -1945,80 +1936,22 @@ unsafe impl PinCoerceUnsized for *mut T {} /// constructor. /// /// [`Box::pin`]: ../../std/boxed/struct.Box.html#method.pin +#[cfg(not(bootstrap))] #[stable(feature = "pin_macro", since = "1.68.0")] #[rustc_macro_transparency = "semitransparent"] -#[allow_internal_unstable(unsafe_pin_internals)] -#[rustc_macro_edition_2021] +#[allow_internal_unstable(super_let)] pub macro pin($value:expr $(,)?) { - // This is `Pin::new_unchecked(&mut { $value })`, so, for starters, let's - // review such a hypothetical macro (that any user-code could define): - // - // ```rust - // macro_rules! pin {( $value:expr ) => ( - // match &mut { $value } { at_value => unsafe { // Do not wrap `$value` in an `unsafe` block. - // $crate::pin::Pin::<&mut _>::new_unchecked(at_value) - // }} - // )} - // ``` - // - // Safety: - // - `type P = &mut _`. There are thus no pathological `Deref{,Mut}` impls - // that would break `Pin`'s invariants. - // - `{ $value }` is braced, making it a _block expression_, thus **moving** - // the given `$value`, and making it _become an **anonymous** temporary_. - // By virtue of being anonymous, it can no longer be accessed, thus - // preventing any attempts to `mem::replace` it or `mem::forget` it, _etc._ - // - // This gives us a `pin!` definition that is sound, and which works, but only - // in certain scenarios: - // - If the `pin!(value)` expression is _directly_ fed to a function call: - // `let poll = pin!(fut).poll(cx);` - // - If the `pin!(value)` expression is part of a scrutinee: - // ```rust - // match pin!(fut) { pinned_fut => { - // pinned_fut.as_mut().poll(...); - // pinned_fut.as_mut().poll(...); - // }} // <- `fut` is dropped here. - // ``` - // Alas, it doesn't work for the more straight-forward use-case: `let` bindings. - // ```rust - // let pinned_fut = pin!(fut); // <- temporary value is freed at the end of this statement - // pinned_fut.poll(...) // error[E0716]: temporary value dropped while borrowed - // // note: consider using a `let` binding to create a longer lived value - // ``` - // - Issues such as this one are the ones motivating https://github.com/rust-lang/rfcs/pull/66 - // - // This makes such a macro incredibly unergonomic in practice, and the reason most macros - // out there had to take the path of being a statement/binding macro (_e.g._, `pin!(future);`) - // instead of featuring the more intuitive ergonomics of an expression macro. - // - // Luckily, there is a way to avoid the problem. Indeed, the problem stems from the fact that a - // temporary is dropped at the end of its enclosing statement when it is part of the parameters - // given to function call, which has precisely been the case with our `Pin::new_unchecked()`! - // For instance, - // ```rust - // let p = Pin::new_unchecked(&mut ); - // ``` - // becomes: - // ```rust - // let p = { let mut anon = ; &mut anon }; - // ``` - // - // However, when using a literal braced struct to construct the value, references to temporaries - // can then be taken. This makes Rust change the lifespan of such temporaries so that they are, - // instead, dropped _at the end of the enscoping block_. - // For instance, - // ```rust - // let p = Pin { __pointer: &mut }; - // ``` - // becomes: - // ```rust - // let mut anon = ; - // let p = Pin { __pointer: &mut anon }; - // ``` - // which is *exactly* what we want. - // - // See https://doc.rust-lang.org/1.58.1/reference/destructors.html#temporary-lifetime-extension - // for more info. - $crate::pin::Pin::<&mut _> { __pointer: &mut { $value } } + { + super let mut pinned = $value; + // SAFETY: The value is pinned: it is the local above which cannot be named outside this macro. + unsafe { $crate::pin::Pin::new_unchecked(&mut pinned) } + } +} + +/// Only for bootstrap. +#[cfg(bootstrap)] +#[stable(feature = "pin_macro", since = "1.68.0")] +#[rustc_macro_transparency = "semitransparent"] +pub macro pin($value:expr $(,)?) { + $crate::pin::Pin::<&mut _> { pointer: &mut { $value } } } diff --git a/library/coretests/tests/pin_macro.rs b/library/coretests/tests/pin_macro.rs index bfbfa8d280fa..3174c91a6498 100644 --- a/library/coretests/tests/pin_macro.rs +++ b/library/coretests/tests/pin_macro.rs @@ -38,6 +38,7 @@ fn rust_2024_expr() { } #[test] +#[cfg(not(bootstrap))] fn temp_lifetime() { // Check that temporary lifetimes work as in Rust 2021. // Regression test for https://github.com/rust-lang/rust/issues/138596 diff --git a/tests/ui/feature-gates/feature-gate-unsafe_pin_internals.rs b/tests/ui/feature-gates/feature-gate-unsafe_pin_internals.rs deleted file mode 100644 index deb5a2f691b8..000000000000 --- a/tests/ui/feature-gates/feature-gate-unsafe_pin_internals.rs +++ /dev/null @@ -1,16 +0,0 @@ -//@ edition:2018 -#![forbid(internal_features, unsafe_code)] -#![feature(unsafe_pin_internals)] -//~^ ERROR the feature `unsafe_pin_internals` is internal to the compiler or standard library - -use core::{marker::PhantomPinned, pin::Pin}; - -/// The `unsafe_pin_internals` is indeed unsound. -fn non_unsafe_pin_new_unchecked(pointer: &mut T) -> Pin<&mut T> { - Pin { __pointer: pointer } -} - -fn main() { - let mut self_referential = PhantomPinned; - let _: Pin<&mut PhantomPinned> = non_unsafe_pin_new_unchecked(&mut self_referential); -} diff --git a/tests/ui/feature-gates/feature-gate-unsafe_pin_internals.stderr b/tests/ui/feature-gates/feature-gate-unsafe_pin_internals.stderr deleted file mode 100644 index fc9bcd90e52e..000000000000 --- a/tests/ui/feature-gates/feature-gate-unsafe_pin_internals.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error: the feature `unsafe_pin_internals` is internal to the compiler or standard library - --> $DIR/feature-gate-unsafe_pin_internals.rs:3:12 - | -LL | #![feature(unsafe_pin_internals)] - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: using it is strongly discouraged -note: the lint level is defined here - --> $DIR/feature-gate-unsafe_pin_internals.rs:2:11 - | -LL | #![forbid(internal_features, unsafe_code)] - | ^^^^^^^^^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/pin-macro/cant_access_internals.rs b/tests/ui/pin-macro/cant_access_internals.rs deleted file mode 100644 index 36a47d0fdf93..000000000000 --- a/tests/ui/pin-macro/cant_access_internals.rs +++ /dev/null @@ -1,12 +0,0 @@ -//@ edition:2018 - -use core::{ - marker::PhantomPinned, - mem, - pin::{pin, Pin}, -}; - -fn main() { - let mut phantom_pinned = pin!(PhantomPinned); - mem::take(phantom_pinned.__pointer); //~ ERROR use of unstable library feature `unsafe_pin_internals` -} diff --git a/tests/ui/pin-macro/cant_access_internals.stderr b/tests/ui/pin-macro/cant_access_internals.stderr deleted file mode 100644 index 8ad897bbbb95..000000000000 --- a/tests/ui/pin-macro/cant_access_internals.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0658]: use of unstable library feature `unsafe_pin_internals` - --> $DIR/cant_access_internals.rs:11:15 - | -LL | mem::take(phantom_pinned.__pointer); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(unsafe_pin_internals)]` 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 d20b270b4e431a010e9149a64e816a9ff2b3dec9 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Fri, 28 Mar 2025 09:41:31 +0100 Subject: [PATCH 485/606] Don't name macro internals in "does not live long enough" errors. --- .../src/diagnostics/conflict_errors.rs | 16 +++++++++++----- .../src/diagnostics/explain_borrow.rs | 4 +++- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 8a8ecc3b96e3..2853ae0239e7 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -2959,21 +2959,27 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } } - let mut err = self.path_does_not_live_long_enough(borrow_span, &format!("`{name}`")); + let name = if borrow_span.in_external_macro(self.infcx.tcx.sess.source_map()) { + // Don't name local variables in external macros. + "value".to_string() + } else { + format!("`{name}`") + }; + + let mut err = self.path_does_not_live_long_enough(borrow_span, &name); if let Some(annotation) = self.annotate_argument_and_return_for_borrow(borrow) { let region_name = annotation.emit(self, &mut err); err.span_label( borrow_span, - format!("`{name}` would have to be valid for `{region_name}`..."), + format!("{name} would have to be valid for `{region_name}`..."), ); err.span_label( drop_span, format!( - "...but `{}` will be dropped here, when the {} returns", - name, + "...but {name} will be dropped here, when the {} returns", self.infcx .tcx .opt_item_name(self.mir_def_id().to_def_id()) @@ -3011,7 +3017,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } } else { err.span_label(borrow_span, "borrowed value does not live long enough"); - err.span_label(drop_span, format!("`{name}` dropped here while still borrowed")); + err.span_label(drop_span, format!("{name} dropped here while still borrowed")); borrow_spans.args_subdiag(&mut err, |args_span| { crate::session_diagnostics::CaptureArgLabel::Capture { diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index f77dda0d386a..a845431facac 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -95,7 +95,9 @@ impl<'tcx> BorrowExplanation<'tcx> { && let hir::def::Res::Local(hir_id) = p.res && let hir::Node::Pat(pat) = tcx.hir_node(hir_id) { - err.span_label(pat.span, format!("binding `{ident}` declared here")); + if !ident.span.in_external_macro(tcx.sess.source_map()) { + err.span_label(pat.span, format!("binding `{ident}` declared here")); + } } } } From 1ca930098911d5059b810b473941a94185cb29ff Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Thu, 27 Mar 2025 18:32:53 +0100 Subject: [PATCH 486/606] Update tests. --- ...ine_coroutine.main.Inline.panic-abort.diff | 2 +- ...ne_coroutine.main.Inline.panic-unwind.diff | 2 +- ...y.run2-{closure#0}.Inline.panic-abort.diff | 6 +++--- ....run2-{closure#0}.Inline.panic-unwind.diff | 6 +++--- tests/pretty/postfix-yield.rs | 3 ++- .../pin-ergonomics/reborrow-once.stderr | 2 +- tests/ui/coroutine/postfix-yield.rs | 2 +- .../lifetime_errors_on_promotion_misusage.rs | 4 ++-- ...fetime_errors_on_promotion_misusage.stderr | 20 +++++++------------ tests/ui/pin-macro/pin_move.stderr | 5 +++++ 10 files changed, 26 insertions(+), 26 deletions(-) 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 56d4d50e967e..151580da19e0 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 @@ -33,7 +33,7 @@ - _4 = g() -> [return: bb1, unwind unreachable]; + _4 = {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8 (#0)}; + _3 = &mut _4; -+ _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}> { __pointer: copy _3 }; ++ _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}> { pointer: copy _3 }; + StorageDead(_3); + StorageLive(_5); + _5 = const false; 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 751916a00f14..6196fc0d0c6b 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 @@ -33,7 +33,7 @@ - _4 = g() -> [return: bb1, unwind continue]; + _4 = {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8 (#0)}; + _3 = &mut _4; -+ _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}> { __pointer: copy _3 }; ++ _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}> { pointer: copy _3 }; + StorageDead(_3); + StorageLive(_5); + _5 = const false; diff --git a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff index e49d7cea28e5..1e9a6dd4f5c8 100644 --- a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff +++ b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff @@ -121,7 +121,7 @@ - } - - bb2: { -+ _4 = Pin::<&mut {async fn body of ActionPermit<'_, T>::perform()}> { __pointer: copy _5 }; ++ _4 = Pin::<&mut {async fn body of ActionPermit<'_, T>::perform()}> { pointer: copy _5 }; StorageDead(_5); StorageLive(_6); StorageLive(_7); @@ -218,7 +218,7 @@ + _37 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); + _21 = &mut (((*_37) as variant#3).1: std::future::Ready<()>); + _20 = &mut (*_21); -+ _19 = Pin::<&mut std::future::Ready<()>> { __pointer: copy _20 }; ++ _19 = Pin::<&mut std::future::Ready<()>> { pointer: copy _20 }; + StorageDead(_20); + StorageLive(_22); + StorageLive(_23); @@ -239,7 +239,7 @@ + _48 = &mut (_19.0: &mut std::future::Ready<()>); + _45 = copy (_19.0: &mut std::future::Ready<()>); + StorageDead(_48); -+ _47 = Pin::<&mut std::future::Ready<()>> { __pointer: copy _45 }; ++ _47 = Pin::<&mut std::future::Ready<()>> { pointer: copy _45 }; + StorageDead(_47); + _44 = &mut ((*_45).0: std::option::Option<()>); + StorageLive(_49); diff --git a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff index e7aed556f2d7..94b89a310baa 100644 --- a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff @@ -123,7 +123,7 @@ - } - - bb2: { -+ _4 = Pin::<&mut {async fn body of ActionPermit<'_, T>::perform()}> { __pointer: copy _5 }; ++ _4 = Pin::<&mut {async fn body of ActionPermit<'_, T>::perform()}> { pointer: copy _5 }; StorageDead(_5); StorageLive(_6); StorageLive(_7); @@ -235,7 +235,7 @@ + _37 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); + _21 = &mut (((*_37) as variant#3).1: std::future::Ready<()>); + _20 = &mut (*_21); -+ _19 = Pin::<&mut std::future::Ready<()>> { __pointer: copy _20 }; ++ _19 = Pin::<&mut std::future::Ready<()>> { pointer: copy _20 }; + StorageDead(_20); + StorageLive(_22); + StorageLive(_23); @@ -256,7 +256,7 @@ + _50 = &mut (_19.0: &mut std::future::Ready<()>); + _47 = copy (_19.0: &mut std::future::Ready<()>); + StorageDead(_50); -+ _49 = Pin::<&mut std::future::Ready<()>> { __pointer: copy _47 }; ++ _49 = Pin::<&mut std::future::Ready<()>> { pointer: copy _47 }; + StorageDead(_49); + _46 = &mut ((*_47).0: std::option::Option<()>); + StorageLive(_51); diff --git a/tests/pretty/postfix-yield.rs b/tests/pretty/postfix-yield.rs index f76e8142ae86..60380a4071c5 100644 --- a/tests/pretty/postfix-yield.rs +++ b/tests/pretty/postfix-yield.rs @@ -2,7 +2,8 @@ //@ edition: 2024 //@ pp-exact -#![feature(gen_blocks, coroutines, coroutine_trait, yield_expr)] +#![feature(gen_blocks, coroutines, coroutine_trait, yield_expr, +stmt_expr_attributes)] use std::ops::{Coroutine, CoroutineState}; use std::pin::pin; diff --git a/tests/ui/async-await/pin-ergonomics/reborrow-once.stderr b/tests/ui/async-await/pin-ergonomics/reborrow-once.stderr index a1ea2b4a57a7..dc8e424ad2a4 100644 --- a/tests/ui/async-await/pin-ergonomics/reborrow-once.stderr +++ b/tests/ui/async-await/pin-ergonomics/reborrow-once.stderr @@ -1,4 +1,4 @@ -error[E0499]: cannot borrow `*x.__pointer` as mutable more than once at a time +error[E0499]: cannot borrow `*x.pointer` as mutable more than once at a time --> $DIR/reborrow-once.rs:12:14 | LL | twice(x, x); diff --git a/tests/ui/coroutine/postfix-yield.rs b/tests/ui/coroutine/postfix-yield.rs index ff843138c8c2..f2fdcebdaa9a 100644 --- a/tests/ui/coroutine/postfix-yield.rs +++ b/tests/ui/coroutine/postfix-yield.rs @@ -3,7 +3,7 @@ //@ run-pass //@ edition: 2024 -#![feature(gen_blocks, coroutines, coroutine_trait, yield_expr)] +#![feature(gen_blocks, coroutines, coroutine_trait, yield_expr, stmt_expr_attributes)] use std::ops::{Coroutine, CoroutineState}; use std::pin::pin; diff --git a/tests/ui/pin-macro/lifetime_errors_on_promotion_misusage.rs b/tests/ui/pin-macro/lifetime_errors_on_promotion_misusage.rs index 8a0244e8145a..e505fe435207 100644 --- a/tests/ui/pin-macro/lifetime_errors_on_promotion_misusage.rs +++ b/tests/ui/pin-macro/lifetime_errors_on_promotion_misusage.rs @@ -9,14 +9,14 @@ use core::{ fn function_call_stops_borrow_extension() { let phantom_pinned = identity(pin!(PhantomPinned)); - //~^ ERROR temporary value dropped while borrowed + //~^ ERROR does not live long enough stuff(phantom_pinned) } fn promotion_only_works_for_the_innermost_block() { let phantom_pinned = { let phantom_pinned = pin!(PhantomPinned); - //~^ ERROR temporary value dropped while borrowed + //~^ ERROR does not live long enough phantom_pinned }; stuff(phantom_pinned) diff --git a/tests/ui/pin-macro/lifetime_errors_on_promotion_misusage.stderr b/tests/ui/pin-macro/lifetime_errors_on_promotion_misusage.stderr index 9df7f0ffd0c3..43fb82be7c2f 100644 --- a/tests/ui/pin-macro/lifetime_errors_on_promotion_misusage.stderr +++ b/tests/ui/pin-macro/lifetime_errors_on_promotion_misusage.stderr @@ -1,35 +1,29 @@ -error[E0716]: temporary value dropped while borrowed +error[E0597]: value does not live long enough --> $DIR/lifetime_errors_on_promotion_misusage.rs:11:35 | LL | let phantom_pinned = identity(pin!(PhantomPinned)); - | ^^^^^^^^^^^^^^^^^^^ - temporary value is freed at the end of this statement + | ^^^^^^^^^^^^^^^^^^^ - value dropped here while still borrowed | | - | creates a temporary value which is freed while still in use + | borrowed value does not live long enough LL | LL | stuff(phantom_pinned) | -------------- borrow later used here | = note: this error originates in the macro `pin` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider using a `let` binding to create a longer lived value - | -LL ~ let binding = pin!(PhantomPinned); -LL ~ let phantom_pinned = identity(binding); - | -error[E0716]: temporary value dropped while borrowed +error[E0597]: value does not live long enough --> $DIR/lifetime_errors_on_promotion_misusage.rs:18:30 | LL | let phantom_pinned = { | -------------- borrow later stored here LL | let phantom_pinned = pin!(PhantomPinned); - | ^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | ^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough ... LL | }; - | - temporary value is freed at the end of this statement + | - value dropped here while still borrowed | - = note: consider using a `let` binding to create a longer lived value = note: this error originates in the macro `pin` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0716`. +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/pin-macro/pin_move.stderr b/tests/ui/pin-macro/pin_move.stderr index c9b8ad9b2021..3f4660209885 100644 --- a/tests/ui/pin-macro/pin_move.stderr +++ b/tests/ui/pin-macro/pin_move.stderr @@ -31,6 +31,11 @@ LL | struct NotCopy(T); LL | let mut pointee = NotCopy(PhantomPinned); LL | pin!(*&mut pointee); | ------------- you could clone this value +help: consider removing the dereference here + | +LL - pin!(*&mut pointee); +LL + pin!(&mut pointee); + | error: aborting due to 2 previous errors From 73065b9484aa844bd4a26aa3cbf03e3f4c7ec4cb Mon Sep 17 00:00:00 2001 From: MarcoIeni <11428655+MarcoIeni@users.noreply.github.com> Date: Tue, 15 Apr 2025 12:28:32 +0200 Subject: [PATCH 487/606] CI: rename MacOS runner --- src/ci/github-actions/jobs.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index fbda749b6a2a..9ee3e06fa727 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -23,8 +23,8 @@ runners: os: ubuntu-24.04-16core-64gb <<: *base-job - - &job-macos-xl - os: macos-13 # We use the standard runner for now + - &job-macos + os: macos-13 <<: *base-job - &job-macos-m1 @@ -355,7 +355,7 @@ auto: NO_OVERFLOW_CHECKS: 1 DIST_REQUIRE_ALL_TOOLS: 1 CODEGEN_BACKENDS: llvm,cranelift - <<: *job-macos-xl + <<: *job-macos - name: dist-apple-various env: @@ -372,18 +372,18 @@ auto: NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 - <<: *job-macos-xl + <<: *job-macos - name: x86_64-apple-1 env: <<: *env-x86_64-apple-tests - <<: *job-macos-xl + <<: *job-macos - name: x86_64-apple-2 env: SCRIPT: ./x.py --stage 2 test tests/ui tests/rustdoc <<: *env-x86_64-apple-tests - <<: *job-macos-xl + <<: *job-macos - name: dist-aarch64-apple env: From ee53c26b41a74eb0ecf785e8cfac98e5aa980756 Mon Sep 17 00:00:00 2001 From: Obei Sideg Date: Tue, 8 Apr 2025 05:29:19 +0300 Subject: [PATCH 488/606] Add `explicit_extern_abis` unstable feature also add `explicit-extern-abis` feature section to the unstable book. --- compiler/rustc_feature/src/unstable.rs | 2 ++ compiler/rustc_span/src/symbol.rs | 1 + .../language-features/explicit-extern-abis.md | 23 +++++++++++++++++++ 3 files changed, 26 insertions(+) create mode 100644 src/doc/unstable-book/src/language-features/explicit-extern-abis.md diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 36e375c778d3..d0ac822ba26e 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -477,6 +477,8 @@ declare_features! ( (incomplete, ergonomic_clones, "1.87.0", Some(132290)), /// Allows exhaustive pattern matching on types that contain uninhabited types. (unstable, exhaustive_patterns, "1.13.0", Some(51085)), + /// Disallows `extern` without an explicit ABI. + (unstable, explicit_extern_abis, "CURRENT_RUSTC_VERSION", Some(134986)), /// Allows explicit tail calls via `become` expression. (incomplete, explicit_tail_calls, "1.72.0", Some(112788)), /// Allows using `aapcs`, `efiapi`, `sysv64` and `win64` as calling conventions diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index d1f3eb16e4e4..0a2e4e4977f3 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -916,6 +916,7 @@ symbols! { expf16, expf32, expf64, + explicit_extern_abis, explicit_generic_args_with_impl_trait, explicit_tail_calls, export_name, diff --git a/src/doc/unstable-book/src/language-features/explicit-extern-abis.md b/src/doc/unstable-book/src/language-features/explicit-extern-abis.md new file mode 100644 index 000000000000..ba622466ba74 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/explicit-extern-abis.md @@ -0,0 +1,23 @@ +# `explicit_extern_abis` + +The tracking issue for this feature is: #134986 + +------ + +Disallow `extern` without an explicit ABI. We should write `extern "C"` +(or another ABI) instead of just `extern`. + +By making the ABI explicit, it becomes much clearer that "C" is just one of the +possible choices, rather than the "standard" way for external functions. +Removing the default makes it easier to add a new ABI on equal footing as "C". + +```rust,editionfuture,compile_fail +#![feature(explicit_extern_abis)] + +extern fn function1() {} // ERROR `extern` declarations without an explicit ABI + // are disallowed + +extern "C" fn function2() {} // compiles + +extern "aapcs" fn function3() {} // compiles +``` From 2907ab5bf9583bec1acb389637ed300ef333b273 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 15 Apr 2025 12:13:11 +0200 Subject: [PATCH 489/606] Move `is_builder_target`, `is_system_llvm` and `is_rust_llvm` from `Builder` to `Config` --- src/bootstrap/src/core/build_steps/compile.rs | 10 +++-- src/bootstrap/src/core/build_steps/dist.rs | 10 +++-- src/bootstrap/src/core/build_steps/llvm.rs | 6 +-- src/bootstrap/src/core/build_steps/test.rs | 4 +- src/bootstrap/src/core/config/config.rs | 36 ++++++++++++++++ src/bootstrap/src/core/sanity.rs | 2 +- src/bootstrap/src/lib.rs | 42 ++----------------- 7 files changed, 57 insertions(+), 53 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index dab58fccf5e6..30ab142b53bd 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -155,7 +155,7 @@ impl Step for Std { // When using `download-rustc`, we already have artifacts for the host available. Don't // recompile them. - if builder.download_rustc() && builder.is_builder_target(target) + if builder.download_rustc() && builder.config.is_builder_target(target) // NOTE: the beta compiler may generate different artifacts than the downloaded compiler, so // its artifacts can't be reused. && compiler.stage != 0 @@ -229,7 +229,7 @@ impl Step for Std { // The LLD wrappers and `rust-lld` are self-contained linking components that can be // necessary to link the stdlib on some targets. We'll also need to copy these binaries to // the `stage0-sysroot` to ensure the linker is found when bootstrapping on such a target. - if compiler.stage == 0 && builder.is_builder_target(compiler.host) { + if compiler.stage == 0 && builder.config.is_builder_target(compiler.host) { trace!( "(build == host) copying linking components to `stage0-sysroot` for bootstrapping" ); @@ -1374,7 +1374,7 @@ pub fn rustc_cargo_env( /// Pass down configuration from the LLVM build into the build of /// rustc_llvm and rustc_codegen_llvm. fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) { - if builder.is_rust_llvm(target) { + if builder.config.is_rust_llvm(target) { cargo.env("LLVM_RUSTLLVM", "1"); } if builder.config.llvm_enzyme { @@ -2532,7 +2532,9 @@ pub fn strip_debug(builder: &Builder<'_>, target: TargetSelection, path: &Path) // FIXME: to make things simpler for now, limit this to the host and target where we know // `strip -g` is both available and will fix the issue, i.e. on a x64 linux host that is not // cross-compiling. Expand this to other appropriate targets in the future. - if target != "x86_64-unknown-linux-gnu" || !builder.is_builder_target(target) || !path.exists() + if target != "x86_64-unknown-linux-gnu" + || !builder.config.is_builder_target(target) + || !path.exists() { return; } diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 83f71aeed720..00043cfc2047 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -612,7 +612,7 @@ impl Step for DebuggerScripts { fn skip_host_target_lib(builder: &Builder<'_>, compiler: Compiler) -> bool { // The only true set of target libraries came from the build triple, so // let's reduce redundant work by only producing archives from that host. - if !builder.is_builder_target(compiler.host) { + if !builder.config.is_builder_target(compiler.host) { builder.info("\tskipping, not a build host"); true } else { @@ -671,7 +671,9 @@ fn copy_target_libs( &self_contained_dst.join(path.file_name().unwrap()), FileType::NativeLibrary, ); - } else if dependency_type == DependencyType::Target || builder.is_builder_target(target) { + } else if dependency_type == DependencyType::Target + || builder.config.is_builder_target(target) + { builder.copy_link(&path, &dst.join(path.file_name().unwrap()), FileType::NativeLibrary); } } @@ -824,7 +826,7 @@ impl Step for Analysis { fn run(self, builder: &Builder<'_>) -> Option { let compiler = self.compiler; let target = self.target; - if !builder.is_builder_target(compiler.host) { + if !builder.config.is_builder_target(compiler.host) { return None; } @@ -2118,7 +2120,7 @@ fn maybe_install_llvm( // // If the LLVM is coming from ourselves (just from CI) though, we // still want to install it, as it otherwise won't be available. - if builder.is_system_llvm(target) { + if builder.config.is_system_llvm(target) { trace!("system LLVM requested, no install"); return false; } diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index 69a8bd59f16c..f29520d25cf8 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -485,7 +485,7 @@ impl Step for Llvm { } // https://llvm.org/docs/HowToCrossCompileLLVM.html - if !builder.is_builder_target(target) { + if !builder.config.is_builder_target(target) { let LlvmResult { llvm_config, .. } = builder.ensure(Llvm { target: builder.config.build }); if !builder.config.dry_run() { @@ -637,7 +637,7 @@ fn configure_cmake( } cfg.target(&target.triple).host(&builder.config.build.triple); - if !builder.is_builder_target(target) { + if !builder.config.is_builder_target(target) { cfg.define("CMAKE_CROSSCOMPILING", "True"); // NOTE: Ideally, we wouldn't have to do this, and `cmake-rs` would just handle it for us. @@ -1098,7 +1098,7 @@ impl Step for Lld { .define("LLVM_CMAKE_DIR", llvm_cmake_dir) .define("LLVM_INCLUDE_TESTS", "OFF"); - if !builder.is_builder_target(target) { + if !builder.config.is_builder_target(target) { // Use the host llvm-tblgen binary. cfg.define( "LLVM_TABLEGEN_EXE", diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index b1a3bba08871..ad62651cc694 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -1894,7 +1894,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the .arg(llvm_components.trim()); llvm_components_passed = true; } - if !builder.is_rust_llvm(target) { + if !builder.config.is_rust_llvm(target) { cmd.arg("--system-llvm"); } @@ -2668,7 +2668,7 @@ impl Step for Crate { cargo } else { // Also prepare a sysroot for the target. - if !builder.is_builder_target(target) { + if !builder.config.is_builder_target(target) { builder.ensure(compile::Std::new(compiler, target).force_recompile(true)); builder.ensure(RemoteCopyLibs { compiler, target }); } diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 25ec64f90b53..57015797a629 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -3233,6 +3233,42 @@ impl Config { Some(commit.to_string()) } + + /// Checks if the given target is the same as the builder target. + pub fn is_builder_target(&self, target: TargetSelection) -> bool { + self.build == target + } + + /// Returns `true` if this is an external version of LLVM not managed by bootstrap. + /// In particular, we expect llvm sources to be available when this is false. + /// + /// NOTE: this is not the same as `!is_rust_llvm` when `llvm_has_patches` is set. + pub fn is_system_llvm(&self, target: TargetSelection) -> bool { + match self.target_config.get(&target) { + Some(Target { llvm_config: Some(_), .. }) => { + let ci_llvm = self.llvm_from_ci && self.is_builder_target(target); + !ci_llvm + } + // We're building from the in-tree src/llvm-project sources. + Some(Target { llvm_config: None, .. }) => false, + None => false, + } + } + + /// Returns `true` if this is our custom, patched, version of LLVM. + /// + /// This does not necessarily imply that we're managing the `llvm-project` submodule. + pub fn is_rust_llvm(&self, target: TargetSelection) -> bool { + match self.target_config.get(&target) { + // We're using a user-controlled version of LLVM. The user has explicitly told us whether the version has our patches. + // (They might be wrong, but that's not a supported use-case.) + // In particular, this tries to support `submodules = false` and `patches = false`, for using a newer version of LLVM that's not through `rust-lang/llvm-project`. + Some(Target { llvm_has_rust_patches: Some(patched), .. }) => *patched, + // The user hasn't promised the patches match. + // This only has our patches if it's downloaded from CI or built from source. + _ => !self.is_system_llvm(target), + } + } } /// Compares the current `Llvm` options against those in the CI LLVM builder and detects any incompatible options. diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index 891340add908..0310937e60c1 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -325,7 +325,7 @@ than building it. if target.contains("musl") && !target.contains("unikraft") { // If this is a native target (host is also musl) and no musl-root is given, // fall back to the system toolchain in /usr before giving up - if build.musl_root(*target).is_none() && build.is_builder_target(*target) { + if build.musl_root(*target).is_none() && build.config.is_builder_target(*target) { let target = build.config.target_config.entry(*target).or_default(); target.musl_root = Some("/usr".into()); } diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 1a513a240e17..e088cf52073c 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -35,7 +35,7 @@ use utils::channel::GitInfo; use crate::core::builder; use crate::core::builder::Kind; -use crate::core::config::{DryRun, LldMode, LlvmLibunwind, Target, TargetSelection, flags}; +use crate::core::config::{DryRun, LldMode, LlvmLibunwind, TargetSelection, flags}; use crate::utils::exec::{BehaviorOnFailure, BootstrapCommand, CommandOutput, OutputMode, command}; use crate::utils::helpers::{ self, dir_is_empty, exe, libdir, output, set_file_times, split_debuginfo, symlink_dir, @@ -803,7 +803,7 @@ impl Build { /// Note that if LLVM is configured externally then the directory returned /// will likely be empty. fn llvm_out(&self, target: TargetSelection) -> PathBuf { - if self.config.llvm_from_ci && self.is_builder_target(target) { + if self.config.llvm_from_ci && self.config.is_builder_target(target) { self.config.ci_llvm_root() } else { self.out.join(target).join("llvm") @@ -851,37 +851,6 @@ impl Build { if self.config.vendor { Some(self.src.join(VENDOR_DIR)) } else { None } } - /// Returns `true` if this is an external version of LLVM not managed by bootstrap. - /// In particular, we expect llvm sources to be available when this is false. - /// - /// NOTE: this is not the same as `!is_rust_llvm` when `llvm_has_patches` is set. - fn is_system_llvm(&self, target: TargetSelection) -> bool { - match self.config.target_config.get(&target) { - Some(Target { llvm_config: Some(_), .. }) => { - let ci_llvm = self.config.llvm_from_ci && self.is_builder_target(target); - !ci_llvm - } - // We're building from the in-tree src/llvm-project sources. - Some(Target { llvm_config: None, .. }) => false, - None => false, - } - } - - /// Returns `true` if this is our custom, patched, version of LLVM. - /// - /// This does not necessarily imply that we're managing the `llvm-project` submodule. - fn is_rust_llvm(&self, target: TargetSelection) -> bool { - match self.config.target_config.get(&target) { - // We're using a user-controlled version of LLVM. The user has explicitly told us whether the version has our patches. - // (They might be wrong, but that's not a supported use-case.) - // In particular, this tries to support `submodules = false` and `patches = false`, for using a newer version of LLVM that's not through `rust-lang/llvm-project`. - Some(Target { llvm_has_rust_patches: Some(patched), .. }) => *patched, - // The user hasn't promised the patches match. - // This only has our patches if it's downloaded from CI or built from source. - _ => !self.is_system_llvm(target), - } - } - /// Returns the path to `FileCheck` binary for the specified target fn llvm_filecheck(&self, target: TargetSelection) -> PathBuf { let target_config = self.config.target_config.get(&target); @@ -1356,7 +1325,7 @@ Executed at: {executed_at}"#, // need to use CXX compiler as linker to resolve the exception functions // that are only existed in CXX libraries Some(self.cxx.borrow()[&target].path().into()) - } else if !self.is_builder_target(target) + } else if !self.config.is_builder_target(target) && helpers::use_host_linker(target) && !target.is_msvc() { @@ -2025,11 +1994,6 @@ to download LLVM rather than building it. stream.reset().unwrap(); result } - - /// Checks if the given target is the same as the builder target. - fn is_builder_target(&self, target: TargetSelection) -> bool { - self.config.build == target - } } #[cfg(unix)] From 3c01dfe2ae09aef9ee42223f492764717e152cde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 15 Apr 2025 12:15:10 +0200 Subject: [PATCH 490/606] Rename `is_builder_target` to `is_host_target` --- src/bootstrap/src/core/build_steps/compile.rs | 6 +++--- src/bootstrap/src/core/build_steps/dist.rs | 7 +++---- src/bootstrap/src/core/build_steps/llvm.rs | 6 +++--- src/bootstrap/src/core/build_steps/test.rs | 2 +- src/bootstrap/src/core/builder/tests.rs | 4 ++-- src/bootstrap/src/core/config/config.rs | 6 +++--- src/bootstrap/src/core/sanity.rs | 2 +- src/bootstrap/src/lib.rs | 4 ++-- 8 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 30ab142b53bd..f78539b47816 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -229,7 +229,7 @@ impl Step for Std { // The LLD wrappers and `rust-lld` are self-contained linking components that can be // necessary to link the stdlib on some targets. We'll also need to copy these binaries to // the `stage0-sysroot` to ensure the linker is found when bootstrapping on such a target. - if compiler.stage == 0 && builder.config.is_builder_target(compiler.host) { + if compiler.stage == 0 && builder.config.is_host_target(compiler.host) { trace!( "(build == host) copying linking components to `stage0-sysroot` for bootstrapping" ); @@ -2182,7 +2182,7 @@ impl Step for Assemble { debug!("copying codegen backends to sysroot"); copy_codegen_backends_to_sysroot(builder, build_compiler, target_compiler); - if builder.config.lld_enabled { + if builder.config.lld_enabled && !builder.config.is_system_llvm(target_compiler.host) { builder.ensure(crate::core::build_steps::tool::LldWrapper { build_compiler, target_compiler, @@ -2533,7 +2533,7 @@ pub fn strip_debug(builder: &Builder<'_>, target: TargetSelection, path: &Path) // `strip -g` is both available and will fix the issue, i.e. on a x64 linux host that is not // cross-compiling. Expand this to other appropriate targets in the future. if target != "x86_64-unknown-linux-gnu" - || !builder.config.is_builder_target(target) + || !builder.config.is_host_target(target) || !path.exists() { return; diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 00043cfc2047..ed90ede79362 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -612,7 +612,7 @@ impl Step for DebuggerScripts { fn skip_host_target_lib(builder: &Builder<'_>, compiler: Compiler) -> bool { // The only true set of target libraries came from the build triple, so // let's reduce redundant work by only producing archives from that host. - if !builder.config.is_builder_target(compiler.host) { + if !builder.config.is_host_target(compiler.host) { builder.info("\tskipping, not a build host"); true } else { @@ -671,8 +671,7 @@ fn copy_target_libs( &self_contained_dst.join(path.file_name().unwrap()), FileType::NativeLibrary, ); - } else if dependency_type == DependencyType::Target - || builder.config.is_builder_target(target) + } else if dependency_type == DependencyType::Target || builder.config.is_host_target(target) { builder.copy_link(&path, &dst.join(path.file_name().unwrap()), FileType::NativeLibrary); } @@ -826,7 +825,7 @@ impl Step for Analysis { fn run(self, builder: &Builder<'_>) -> Option { let compiler = self.compiler; let target = self.target; - if !builder.config.is_builder_target(compiler.host) { + if !builder.config.is_host_target(compiler.host) { return None; } diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index f29520d25cf8..0c82cb16348e 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -485,7 +485,7 @@ impl Step for Llvm { } // https://llvm.org/docs/HowToCrossCompileLLVM.html - if !builder.config.is_builder_target(target) { + if !builder.config.is_host_target(target) { let LlvmResult { llvm_config, .. } = builder.ensure(Llvm { target: builder.config.build }); if !builder.config.dry_run() { @@ -637,7 +637,7 @@ fn configure_cmake( } cfg.target(&target.triple).host(&builder.config.build.triple); - if !builder.config.is_builder_target(target) { + if !builder.config.is_host_target(target) { cfg.define("CMAKE_CROSSCOMPILING", "True"); // NOTE: Ideally, we wouldn't have to do this, and `cmake-rs` would just handle it for us. @@ -1098,7 +1098,7 @@ impl Step for Lld { .define("LLVM_CMAKE_DIR", llvm_cmake_dir) .define("LLVM_INCLUDE_TESTS", "OFF"); - if !builder.config.is_builder_target(target) { + if !builder.config.is_host_target(target) { // Use the host llvm-tblgen binary. cfg.define( "LLVM_TABLEGEN_EXE", diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index ad62651cc694..096f7de65975 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -2668,7 +2668,7 @@ impl Step for Crate { cargo } else { // Also prepare a sysroot for the target. - if !builder.config.is_builder_target(target) { + if !builder.config.is_host_target(target) { builder.ensure(compile::Std::new(compiler, target).force_recompile(true)); builder.ensure(RemoteCopyLibs { compiler, target }); } diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index fd3b28e4e6ab..5de824ebab23 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -1107,8 +1107,8 @@ fn test_is_builder_target() { let build = Build::new(config); let builder = Builder::new(&build); - assert!(builder.is_builder_target(target1)); - assert!(!builder.is_builder_target(target2)); + assert!(builder.config.is_host_target(target1)); + assert!(!builder.config.is_host_target(target2)); } } diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 57015797a629..12e157a34ae3 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -3234,8 +3234,8 @@ impl Config { Some(commit.to_string()) } - /// Checks if the given target is the same as the builder target. - pub fn is_builder_target(&self, target: TargetSelection) -> bool { + /// Checks if the given target is the same as the host target. + pub fn is_host_target(&self, target: TargetSelection) -> bool { self.build == target } @@ -3246,7 +3246,7 @@ impl Config { pub fn is_system_llvm(&self, target: TargetSelection) -> bool { match self.target_config.get(&target) { Some(Target { llvm_config: Some(_), .. }) => { - let ci_llvm = self.llvm_from_ci && self.is_builder_target(target); + let ci_llvm = self.llvm_from_ci && self.is_host_target(target); !ci_llvm } // We're building from the in-tree src/llvm-project sources. diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index 0310937e60c1..4b020a7edb7b 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -325,7 +325,7 @@ than building it. if target.contains("musl") && !target.contains("unikraft") { // If this is a native target (host is also musl) and no musl-root is given, // fall back to the system toolchain in /usr before giving up - if build.musl_root(*target).is_none() && build.config.is_builder_target(*target) { + if build.musl_root(*target).is_none() && build.config.is_host_target(*target) { let target = build.config.target_config.entry(*target).or_default(); target.musl_root = Some("/usr".into()); } diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index e088cf52073c..88d181532a7f 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -803,7 +803,7 @@ impl Build { /// Note that if LLVM is configured externally then the directory returned /// will likely be empty. fn llvm_out(&self, target: TargetSelection) -> PathBuf { - if self.config.llvm_from_ci && self.config.is_builder_target(target) { + if self.config.llvm_from_ci && self.config.is_host_target(target) { self.config.ci_llvm_root() } else { self.out.join(target).join("llvm") @@ -1325,7 +1325,7 @@ Executed at: {executed_at}"#, // need to use CXX compiler as linker to resolve the exception functions // that are only existed in CXX libraries Some(self.cxx.borrow()[&target].path().into()) - } else if !self.config.is_builder_target(target) + } else if !self.config.is_host_target(target) && helpers::use_host_linker(target) && !target.is_msvc() { From 502b630cd1042d8b2b613a12278a01c641cf096a Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Tue, 15 Apr 2025 13:11:14 +0200 Subject: [PATCH 491/606] tidy: don't crush on non-existent submodules --- src/tools/tidy/src/deps.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 88c2a02798ac..46e55859a578 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -682,8 +682,10 @@ pub static CRATES: &[&str] = &[ pub fn has_missing_submodule(root: &Path, submodules: &[&str]) -> bool { !CiEnv::is_ci() && submodules.iter().any(|submodule| { + let path = root.join(submodule); + !path.exists() // If the directory is empty, we can consider it as an uninitialized submodule. - read_dir(root.join(submodule)).unwrap().next().is_none() + || read_dir(path).unwrap().next().is_none() }) } From 52f4b16075bf01d2c8f8539c26fb9b135967713f Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Tue, 15 Apr 2025 14:06:51 +0200 Subject: [PATCH 492/606] use helper function instead of writing rustfmt stamp by hand --- src/bootstrap/src/core/build_steps/format.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs index b1a97bde97b5..43b831adf1f7 100644 --- a/src/bootstrap/src/core/build_steps/format.rs +++ b/src/bootstrap/src/core/build_steps/format.rs @@ -81,7 +81,8 @@ fn update_rustfmt_version(build: &Builder<'_>) { let Some((version, stamp_file)) = get_rustfmt_version(build) else { return; }; - t!(std::fs::write(stamp_file.path(), version)) + + t!(stamp_file.add_stamp(version).write()); } /// Returns the Rust files modified between the `merge-base` of HEAD and From dda4d7bc44aa4909aae72cd38965a11ccf46c02e Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Tue, 15 Apr 2025 14:06:51 +0200 Subject: [PATCH 493/606] slightly correct comments and diagnostics about checking modifications I feel like they are still wrong, but maybe less so .-. The `info:` was unhelpful -- we only use upstream in CI nowdays. --- src/bootstrap/src/core/build_steps/format.rs | 17 +++++++++-------- src/build_helper/src/git.rs | 6 ++++-- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs index 43b831adf1f7..25d5f97d7eec 100644 --- a/src/bootstrap/src/core/build_steps/format.rs +++ b/src/bootstrap/src/core/build_steps/format.rs @@ -85,11 +85,15 @@ fn update_rustfmt_version(build: &Builder<'_>) { t!(stamp_file.add_stamp(version).write()); } -/// Returns the Rust files modified between the `merge-base` of HEAD and -/// rust-lang/master and what is now on the disk. Does not include removed files. +/// Returns the Rust files modified between the last merge commit and what is now on the disk. +/// Does not include removed files. /// /// Returns `None` if all files should be formatted. fn get_modified_rs_files(build: &Builder<'_>) -> Result>, String> { + // In CI `get_git_modified_files` returns something different to normal environment. + // This shouldn't be called in CI anyway. + assert!(!build.config.is_running_on_ci); + if !verify_rustfmt_version(build) { return Ok(None); } @@ -104,7 +108,7 @@ struct RustfmtConfig { // Prints output describing a collection of paths, with lines such as "formatted modified file // foo/bar/baz" or "skipped 20 untracked files". -fn print_paths(build: &Builder<'_>, verb: &str, adjective: Option<&str>, paths: &[String]) { +fn print_paths(verb: &str, adjective: Option<&str>, paths: &[String]) { let len = paths.len(); let adjective = if let Some(adjective) = adjective { format!("{adjective} ") } else { String::new() }; @@ -115,9 +119,6 @@ fn print_paths(build: &Builder<'_>, verb: &str, adjective: Option<&str>, paths: } else { println!("fmt: {verb} {len} {adjective}files"); } - if len > 1000 && !build.config.is_running_on_ci { - println!("hint: if this number seems too high, try running `git fetch origin master`"); - } } pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) { @@ -190,7 +191,7 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) { ) .map(|x| x.to_string()) .collect(); - print_paths(build, "skipped", Some("untracked"), &untracked_paths); + print_paths("skipped", Some("untracked"), &untracked_paths); for untracked_path in untracked_paths { // The leading `/` makes it an exact match against the @@ -319,7 +320,7 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) { }); let mut paths = formatted_paths.into_inner().unwrap(); paths.sort(); - print_paths(build, if check { "checked" } else { "formatted" }, adjective, &paths); + print_paths(if check { "checked" } else { "formatted" }, adjective, &paths); drop(tx); diff --git a/src/build_helper/src/git.rs b/src/build_helper/src/git.rs index 693e0fc8f46d..f5347c308241 100644 --- a/src/build_helper/src/git.rs +++ b/src/build_helper/src/git.rs @@ -114,7 +114,9 @@ fn git_upstream_merge_base( Ok(output_result(git.arg("merge-base").arg(&updated_master).arg("HEAD"))?.trim().to_owned()) } -/// Searches for the nearest merge commit in the repository that also exists upstream. +/// Searches for the nearest merge commit in the repository. +/// +/// **In CI** finds the nearest merge commit that *also exists upstream*. /// /// It looks for the most recent commit made by the merge bot by matching the author's email /// address with the merge bot's email. @@ -165,7 +167,7 @@ pub fn get_closest_merge_commit( Ok(output_result(&mut git)?.trim().to_owned()) } -/// Returns the files that have been modified in the current branch compared to the master branch. +/// Returns the files that have been modified in the current branch compared to the last merge. /// The `extensions` parameter can be used to filter the files by their extension. /// Does not include removed files. /// If `extensions` is empty, all files will be returned. From 8934ac575988f2c15b7910d2f683b2792e5916cb Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Tue, 15 Apr 2025 14:06:51 +0200 Subject: [PATCH 494/606] add a comment for code that isn't --- src/bootstrap/src/core/build_steps/format.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs index 25d5f97d7eec..6641c4b4e139 100644 --- a/src/bootstrap/src/core/build_steps/format.rs +++ b/src/bootstrap/src/core/build_steps/format.rs @@ -214,7 +214,13 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) { override_builder.add(&format!("/{file}")).expect(&file); } } - Ok(None) => {} + Ok(None) => { + // NOTE: `Ok(None)` signifies that we need to format all files. + // The tricky part here is that if `override_builder` isn't given any white + // list files (i.e. files to be formatted, added without leading `!`), it + // will instead look for *all* files. So, by doing nothing here, we are + // actually making it so we format all files. + } Err(err) => { eprintln!("fmt warning: Something went wrong running git commands:"); eprintln!("fmt warning: {err}"); From 52694034ba0e3261fb53c97ca4da7743db4945e7 Mon Sep 17 00:00:00 2001 From: Jason Newcomb Date: Sun, 2 Mar 2025 02:23:14 -0500 Subject: [PATCH 495/606] Add `copy_within` to `IndexSlice` --- compiler/rustc_index/src/slice.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_index/src/slice.rs b/compiler/rustc_index/src/slice.rs index 67ac805c2bfe..d2702bdb0571 100644 --- a/compiler/rustc_index/src/slice.rs +++ b/compiler/rustc_index/src/slice.rs @@ -1,6 +1,6 @@ use std::fmt; use std::marker::PhantomData; -use std::ops::{Index, IndexMut}; +use std::ops::{Index, IndexMut, RangeBounds}; use std::slice::GetDisjointMutError::*; use std::slice::{self, SliceIndex}; @@ -104,6 +104,17 @@ impl IndexSlice { self.raw.swap(a.index(), b.index()) } + #[inline] + pub fn copy_within( + &mut self, + src: impl IntoSliceIdx>, + dest: I, + ) where + T: Copy, + { + self.raw.copy_within(src.into_slice_idx(), dest.index()); + } + #[inline] pub fn get>( &self, From 812095031b82b5974e03dafd6bf33d69de712474 Mon Sep 17 00:00:00 2001 From: reddevilmidzy Date: Tue, 15 Apr 2025 23:51:10 +0900 Subject: [PATCH 496/606] Add test for issue 125668 --- tests/ui/consts/const-blocks/const-block-in-array-size.rs | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 tests/ui/consts/const-blocks/const-block-in-array-size.rs diff --git a/tests/ui/consts/const-blocks/const-block-in-array-size.rs b/tests/ui/consts/const-blocks/const-block-in-array-size.rs new file mode 100644 index 000000000000..ecab24322869 --- /dev/null +++ b/tests/ui/consts/const-blocks/const-block-in-array-size.rs @@ -0,0 +1,5 @@ +//@ check-pass + +type A = [u32; const { 2 }]; + +fn main() {} From 043c5ff98262409a9c338001200c4cf2a66e72c8 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Tue, 15 Apr 2025 10:54:08 -0700 Subject: [PATCH 497/606] Add warning comment to `Take::get_ref` and `Chain::get_ref` The methods `Take::get_mut` and `Chain::get_mut` include comments warning about modifying the I/O state of the underlying reader. However, many readers (e.g. `File`) allow I/O using a shared reference (e.g. `&File`). So, add the same caveat to the `get_ref` methods. --- library/std/src/io/mod.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index b6545eada86a..5242261cf93f 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -2658,6 +2658,10 @@ impl Chain { /// Gets references to the underlying readers in this `Chain`. /// + /// Care should be taken to avoid modifying the internal I/O state of the + /// underlying readers as doing so may corrupt the internal state of this + /// `Chain`. + /// /// # Examples /// /// ```no_run @@ -2915,6 +2919,10 @@ impl Take { /// Gets a reference to the underlying reader. /// + /// Care should be taken to avoid modifying the internal I/O state of the + /// underlying reader as doing so may corrupt the internal limit of this + /// `Take`. + /// /// # Examples /// /// ```no_run From 38f7060a73acd5ec6ed7d4820dccbf2aa584fc68 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 15 Apr 2025 21:00:11 +0300 Subject: [PATCH 498/606] Revert "Deduplicate template parameter creation" This reverts commit 6adc2c1fd6ecde7bf83c8b8fbc71f402ced87054. --- .../src/debuginfo/metadata.rs | 36 +++++++------------ .../src/debuginfo/metadata/enums/mod.rs | 1 - .../rustc_codegen_llvm/src/debuginfo/mod.rs | 34 ++++++++++++++++-- 3 files changed, 45 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 1eb8f367c544..7f3e486ca310 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -1315,31 +1315,21 @@ fn build_generic_type_param_di_nodes<'ll, 'tcx>( ty: Ty<'tcx>, ) -> SmallVec> { if let ty::Adt(def, args) = *ty.kind() { - let generics = cx.tcx.generics_of(def.did()); - return get_template_parameters(cx, generics, args); - } - - return smallvec![]; -} - -pub(super) fn get_template_parameters<'ll, 'tcx>( - cx: &CodegenCx<'ll, 'tcx>, - generics: &ty::Generics, - args: ty::GenericArgsRef<'tcx>, -) -> SmallVec> { - if args.types().next().is_some() { - let names = get_parameter_names(cx, generics); - let template_params: SmallVec<_> = iter::zip(args, names) - .filter_map(|(kind, name)| { - kind.as_type().map(|ty| { - let actual_type = cx.tcx.normalize_erasing_regions(cx.typing_env(), ty); - let actual_type_di_node = type_di_node(cx, actual_type); - Some(cx.create_template_type_parameter(name.as_str(), actual_type_di_node)) + if args.types().next().is_some() { + let generics = cx.tcx.generics_of(def.did()); + let names = get_parameter_names(cx, generics); + let template_params: SmallVec<_> = iter::zip(args, names) + .filter_map(|(kind, name)| { + kind.as_type().map(|ty| { + let actual_type = cx.tcx.normalize_erasing_regions(cx.typing_env(), ty); + let actual_type_di_node = type_di_node(cx, actual_type); + Some(cx.create_template_type_parameter(name.as_str(), actual_type_di_node)) + }) }) - }) - .collect(); + .collect(); - return template_params; + return template_params; + } } return smallvec![]; diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs index 6792c307fdc4..7c701926d2c5 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs @@ -363,7 +363,6 @@ fn build_coroutine_variant_struct_type_di_node<'ll, 'tcx>( state_specific_fields.into_iter().chain(common_fields).collect() }, - // FIXME: this is a no-op. `build_generic_type_param_di_nodes` only works for Adts. |cx| build_generic_type_param_di_nodes(cx, coroutine_type_and_layout.ty), ) .di_node diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index ae7d080db66f..0f94a1dbb0d5 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -2,8 +2,8 @@ use std::cell::{OnceCell, RefCell}; use std::ops::Range; -use std::ptr; use std::sync::Arc; +use std::{iter, ptr}; use libc::c_uint; use metadata::create_subroutine_type; @@ -486,10 +486,40 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { generics: &ty::Generics, args: GenericArgsRef<'tcx>, ) -> &'ll DIArray { - let template_params = metadata::get_template_parameters(cx, generics, args); + if args.types().next().is_none() { + return create_DIArray(DIB(cx), &[]); + } + + // Again, only create type information if full debuginfo is enabled + let template_params: Vec<_> = if cx.sess().opts.debuginfo == DebugInfo::Full { + let names = get_parameter_names(cx, generics); + iter::zip(args, names) + .filter_map(|(kind, name)| { + kind.as_type().map(|ty| { + let actual_type = cx.tcx.normalize_erasing_regions(cx.typing_env(), ty); + let actual_type_metadata = type_di_node(cx, actual_type); + Some(cx.create_template_type_parameter( + name.as_str(), + actual_type_metadata, + )) + }) + }) + .collect() + } else { + vec![] + }; + create_DIArray(DIB(cx), &template_params) } + fn get_parameter_names(cx: &CodegenCx<'_, '_>, generics: &ty::Generics) -> Vec { + let mut names = generics.parent.map_or_else(Vec::new, |def_id| { + get_parameter_names(cx, cx.tcx.generics_of(def_id)) + }); + names.extend(generics.own_params.iter().map(|param| param.name)); + names + } + /// Returns a scope, plus `true` if that's a type scope for "class" methods, /// otherwise `false` for plain namespace scopes. fn get_containing_scope<'ll, 'tcx>( From c774adcbb535e69bffe5be329af006959f897fbd Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 14 Apr 2025 15:10:43 +0000 Subject: [PATCH 499/606] Split TypeFolder and FallibleTypeFolder --- compiler/rustc_macros/src/type_foldable.rs | 60 ++++-- compiler/rustc_middle/src/infer/canonical.rs | 9 - compiler/rustc_middle/src/mir/syntax.rs | 4 + compiler/rustc_middle/src/ty/generic_args.rs | 47 ++++- compiler/rustc_middle/src/ty/mod.rs | 7 + .../rustc_middle/src/ty/structural_impls.rs | 191 ++++++++++------- compiler/rustc_middle/src/ty/util.rs | 36 ++++ compiler/rustc_type_ir/src/binder.rs | 10 +- compiler/rustc_type_ir/src/fold.rs | 192 ++++++++++-------- compiler/rustc_type_ir_macros/src/lib.rs | 27 ++- 10 files changed, 396 insertions(+), 187 deletions(-) diff --git a/compiler/rustc_macros/src/type_foldable.rs b/compiler/rustc_macros/src/type_foldable.rs index c4f584dca430..85051311bee9 100644 --- a/compiler/rustc_macros/src/type_foldable.rs +++ b/compiler/rustc_macros/src/type_foldable.rs @@ -14,31 +14,33 @@ pub(super) fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_m s.add_bounds(synstructure::AddBounds::Generics); s.bind_with(|_| synstructure::BindStyle::Move); + let try_body_fold = s.each_variant(|vi| { + let bindings = vi.bindings(); + vi.construct(|_, index| { + let bind = &bindings[index]; + + // retain value of fields with #[type_foldable(identity)] + if has_ignore_attr(&bind.ast().attrs, "type_foldable", "identity") { + bind.to_token_stream() + } else { + quote! { + ::rustc_middle::ty::TypeFoldable::try_fold_with(#bind, __folder)? + } + } + }) + }); + let body_fold = s.each_variant(|vi| { let bindings = vi.bindings(); vi.construct(|_, index| { let bind = &bindings[index]; - let mut fixed = false; - // retain value of fields with #[type_foldable(identity)] - bind.ast().attrs.iter().for_each(|x| { - if !x.path().is_ident("type_foldable") { - return; - } - let _ = x.parse_nested_meta(|nested| { - if nested.path.is_ident("identity") { - fixed = true; - } - Ok(()) - }); - }); - - if fixed { + if has_ignore_attr(&bind.ast().attrs, "type_foldable", "identity") { bind.to_token_stream() } else { quote! { - ::rustc_middle::ty::TypeFoldable::try_fold_with(#bind, __folder)? + ::rustc_middle::ty::TypeFoldable::fold_with(#bind, __folder) } } }) @@ -51,8 +53,32 @@ pub(super) fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_m self, __folder: &mut __F ) -> Result { - Ok(match self { #body_fold }) + Ok(match self { #try_body_fold }) + } + + fn fold_with<__F: ::rustc_middle::ty::TypeFolder<::rustc_middle::ty::TyCtxt<'tcx>>>( + self, + __folder: &mut __F + ) -> Self { + match self { #body_fold } } }, ) } + +fn has_ignore_attr(attrs: &[syn::Attribute], name: &'static str, meta: &'static str) -> bool { + let mut ignored = false; + attrs.iter().for_each(|attr| { + if !attr.path().is_ident(name) { + return; + } + let _ = attr.parse_nested_meta(|nested| { + if nested.path.is_ident(meta) { + ignored = true; + } + Ok(()) + }); + }); + + ignored +} diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index 3cd148cd4427..5b8603744961 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -39,15 +39,6 @@ pub type CanonicalVarInfo<'tcx> = ir::CanonicalVarInfo>; pub type CanonicalVarValues<'tcx> = ir::CanonicalVarValues>; pub type CanonicalVarInfos<'tcx> = &'tcx List>; -impl<'tcx> ty::TypeFoldable> for CanonicalVarInfos<'tcx> { - fn try_fold_with>>( - self, - folder: &mut F, - ) -> Result { - ty::util::fold_list(self, folder, |tcx, v| tcx.mk_canonical_var_infos(v)) - } -} - /// When we canonicalize a value to form a query, we wind up replacing /// various parts of it with canonical variables. This struct stores /// those replaced bits to remember for when we process the query diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index ff9d32ebb719..c7561f8afef9 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -931,6 +931,8 @@ pub enum TerminatorKind<'tcx> { asm_macro: InlineAsmMacro, /// The template for the inline assembly, with placeholders. + #[type_foldable(identity)] + #[type_visitable(ignore)] template: &'tcx [InlineAsmTemplatePiece], /// The operands for the inline assembly, as `Operand`s or `Place`s. @@ -941,6 +943,8 @@ pub enum TerminatorKind<'tcx> { /// Source spans for each line of the inline assembly code. These are /// used to map assembler errors back to the line in the source code. + #[type_foldable(identity)] + #[type_visitable(ignore)] line_spans: &'tcx [Span], /// Valid targets for the inline assembly. diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index 1f04937232dd..8de64b3bfac6 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -17,7 +17,7 @@ use smallvec::SmallVec; use crate::ty::codec::{TyDecoder, TyEncoder}; use crate::ty::{ self, ClosureArgs, CoroutineArgs, CoroutineClosureArgs, FallibleTypeFolder, InlineConstArgs, - Lift, List, Ty, TyCtxt, TypeFoldable, TypeVisitable, TypeVisitor, VisitorResult, + Lift, List, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeVisitable, TypeVisitor, VisitorResult, walk_visitable_list, }; @@ -337,6 +337,14 @@ impl<'tcx> TypeFoldable> for GenericArg<'tcx> { GenericArgKind::Const(ct) => ct.try_fold_with(folder).map(Into::into), } } + + fn fold_with>>(self, folder: &mut F) -> Self { + match self.unpack() { + GenericArgKind::Lifetime(lt) => lt.fold_with(folder).into(), + GenericArgKind::Type(ty) => ty.fold_with(folder).into(), + GenericArgKind::Const(ct) => ct.fold_with(folder).into(), + } + } } impl<'tcx> TypeVisitable> for GenericArg<'tcx> { @@ -606,6 +614,27 @@ impl<'tcx> TypeFoldable> for GenericArgsRef<'tcx> { } } 0 => Ok(self), + _ => ty::util::try_fold_list(self, folder, |tcx, v| tcx.mk_args(v)), + } + } + + fn fold_with>>(self, folder: &mut F) -> Self { + // See justification for this behavior in `try_fold_with`. + match self.len() { + 1 => { + let param0 = self[0].fold_with(folder); + if param0 == self[0] { self } else { folder.cx().mk_args(&[param0]) } + } + 2 => { + let param0 = self[0].fold_with(folder); + let param1 = self[1].fold_with(folder); + if param0 == self[0] && param1 == self[1] { + self + } else { + folder.cx().mk_args(&[param0, param1]) + } + } + 0 => self, _ => ty::util::fold_list(self, folder, |tcx, v| tcx.mk_args(v)), } } @@ -641,6 +670,22 @@ impl<'tcx> TypeFoldable> for &'tcx ty::List> { Ok(folder.cx().mk_type_list(&[param0, param1])) } } + _ => ty::util::try_fold_list(self, folder, |tcx, v| tcx.mk_type_list(v)), + } + } + + fn fold_with>>(self, folder: &mut F) -> Self { + // See comment justifying behavior in `try_fold_with`. + match self.len() { + 2 => { + let param0 = self[0].fold_with(folder); + let param1 = self[1].fold_with(folder); + if param0 == self[0] && param1 == self[1] { + self + } else { + folder.cx().mk_type_list(&[param0, param1]) + } + } _ => ty::util::fold_list(self, folder, |tcx, v| tcx.mk_type_list(v)), } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 61e869f5de41..673e1cafa9df 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -537,6 +537,13 @@ impl<'tcx> TypeFoldable> for Term<'tcx> { ty::TermKind::Const(ct) => ct.try_fold_with(folder).map(Into::into), } } + + fn fold_with>>(self, folder: &mut F) -> Self { + match self.unpack() { + ty::TermKind::Ty(ty) => ty.fold_with(folder).into(), + ty::TermKind::Const(ct) => ct.fold_with(folder).into(), + } + } } impl<'tcx> TypeVisitable> for Term<'tcx> { diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 798ef352c408..40eef541423c 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -6,20 +6,19 @@ use std::fmt::{self, Debug}; use rustc_abi::TyAndLayout; -use rustc_ast::InlineAsmTemplatePiece; use rustc_hir::def::Namespace; use rustc_hir::def_id::LocalDefId; -use rustc_span::Span; use rustc_span::source_map::Spanned; -use rustc_type_ir::{ConstKind, VisitorResult, try_visit}; +use rustc_type_ir::{ConstKind, TypeFolder, VisitorResult, try_visit}; use super::print::PrettyPrinter; use super::{GenericArg, GenericArgKind, Pattern, Region}; +use crate::infer::canonical::CanonicalVarInfos; use crate::mir::PlaceElem; use crate::ty::print::{FmtPrinter, Printer, with_no_trimmed_paths}; use crate::ty::{ - self, FallibleTypeFolder, InferConst, Lift, Term, TermKind, Ty, TyCtxt, TypeFoldable, - TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitor, + self, FallibleTypeFolder, Lift, Term, TermKind, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, + TypeSuperVisitable, TypeVisitable, TypeVisitor, }; impl fmt::Debug for ty::TraitDef { @@ -271,6 +270,7 @@ TrivialTypeTraversalImpls! { crate::ty::AssocKind, crate::ty::BoundRegion, crate::ty::BoundVar, + crate::ty::InferConst, crate::ty::Placeholder, crate::ty::Placeholder, crate::ty::Placeholder, @@ -337,24 +337,6 @@ impl<'tcx> TypeVisitable> for ty::AdtDef<'tcx> { } } -impl<'tcx> TypeFoldable> for &'tcx ty::List> { - fn try_fold_with>>( - self, - folder: &mut F, - ) -> Result { - ty::util::fold_list(self, folder, |tcx, v| tcx.mk_poly_existential_predicates(v)) - } -} - -impl<'tcx> TypeFoldable> for &'tcx ty::List> { - fn try_fold_with>>( - self, - folder: &mut F, - ) -> Result { - ty::util::fold_list(self, folder, |tcx, v| tcx.mk_const_list(v)) - } -} - impl<'tcx> TypeFoldable> for Pattern<'tcx> { fn try_fold_with>>( self, @@ -363,6 +345,11 @@ impl<'tcx> TypeFoldable> for Pattern<'tcx> { let pat = (*self).clone().try_fold_with(folder)?; Ok(if pat == *self { self } else { folder.cx().mk_pat(pat) }) } + + fn fold_with>>(self, folder: &mut F) -> Self { + let pat = (*self).clone().fold_with(folder); + if pat == *self { self } else { folder.cx().mk_pat(pat) } + } } impl<'tcx> TypeVisitable> for Pattern<'tcx> { @@ -378,6 +365,10 @@ impl<'tcx> TypeFoldable> for Ty<'tcx> { ) -> Result { folder.try_fold_ty(self) } + + fn fold_with>>(self, folder: &mut F) -> Self { + folder.fold_ty(self) + } } impl<'tcx> TypeVisitable> for Ty<'tcx> { @@ -436,6 +427,45 @@ impl<'tcx> TypeSuperFoldable> for Ty<'tcx> { Ok(if *self.kind() == kind { self } else { folder.cx().mk_ty_from_kind(kind) }) } + + fn super_fold_with>>(self, folder: &mut F) -> Self { + let kind = match *self.kind() { + ty::RawPtr(ty, mutbl) => ty::RawPtr(ty.fold_with(folder), mutbl), + ty::Array(typ, sz) => ty::Array(typ.fold_with(folder), sz.fold_with(folder)), + ty::Slice(typ) => ty::Slice(typ.fold_with(folder)), + ty::Adt(tid, args) => ty::Adt(tid, args.fold_with(folder)), + ty::Dynamic(trait_ty, region, representation) => { + ty::Dynamic(trait_ty.fold_with(folder), region.fold_with(folder), representation) + } + ty::Tuple(ts) => ty::Tuple(ts.fold_with(folder)), + ty::FnDef(def_id, args) => ty::FnDef(def_id, args.fold_with(folder)), + ty::FnPtr(sig_tys, hdr) => ty::FnPtr(sig_tys.fold_with(folder), hdr), + ty::UnsafeBinder(f) => ty::UnsafeBinder(f.fold_with(folder)), + ty::Ref(r, ty, mutbl) => ty::Ref(r.fold_with(folder), ty.fold_with(folder), mutbl), + ty::Coroutine(did, args) => ty::Coroutine(did, args.fold_with(folder)), + ty::CoroutineWitness(did, args) => ty::CoroutineWitness(did, args.fold_with(folder)), + ty::Closure(did, args) => ty::Closure(did, args.fold_with(folder)), + ty::CoroutineClosure(did, args) => ty::CoroutineClosure(did, args.fold_with(folder)), + ty::Alias(kind, data) => ty::Alias(kind, data.fold_with(folder)), + ty::Pat(ty, pat) => ty::Pat(ty.fold_with(folder), pat.fold_with(folder)), + + ty::Bool + | ty::Char + | ty::Str + | ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Error(_) + | ty::Infer(_) + | ty::Param(..) + | ty::Bound(..) + | ty::Placeholder(..) + | ty::Never + | ty::Foreign(..) => return self, + }; + + if *self.kind() == kind { self } else { folder.cx().mk_ty_from_kind(kind) } + } } impl<'tcx> TypeSuperVisitable> for Ty<'tcx> { @@ -496,6 +526,10 @@ impl<'tcx> TypeFoldable> for ty::Region<'tcx> { ) -> Result { folder.try_fold_region(self) } + + fn fold_with>>(self, folder: &mut F) -> Self { + folder.fold_region(self) + } } impl<'tcx> TypeVisitable> for ty::Region<'tcx> { @@ -511,6 +545,10 @@ impl<'tcx> TypeFoldable> for ty::Predicate<'tcx> { ) -> Result { folder.try_fold_predicate(self) } + + fn fold_with>>(self, folder: &mut F) -> Self { + folder.fold_predicate(self) + } } // FIXME(clause): This is wonky @@ -521,6 +559,10 @@ impl<'tcx> TypeFoldable> for ty::Clause<'tcx> { ) -> Result { Ok(folder.try_fold_predicate(self.as_predicate())?.expect_clause()) } + + fn fold_with>>(self, folder: &mut F) -> Self { + folder.fold_predicate(self.as_predicate()).expect_clause() + } } impl<'tcx> TypeVisitable> for ty::Predicate<'tcx> { @@ -543,6 +585,11 @@ impl<'tcx> TypeSuperFoldable> for ty::Predicate<'tcx> { let new = self.kind().try_fold_with(folder)?; Ok(folder.cx().reuse_or_mk_predicate(self, new)) } + + fn super_fold_with>>(self, folder: &mut F) -> Self { + let new = self.kind().fold_with(folder); + folder.cx().reuse_or_mk_predicate(self, new) + } } impl<'tcx> TypeSuperVisitable> for ty::Predicate<'tcx> { @@ -563,15 +610,6 @@ impl<'tcx> TypeSuperVisitable> for ty::Clauses<'tcx> { } } -impl<'tcx> TypeFoldable> for ty::Clauses<'tcx> { - fn try_fold_with>>( - self, - folder: &mut F, - ) -> Result { - ty::util::fold_list(self, folder, |tcx, v| tcx.mk_clauses(v)) - } -} - impl<'tcx> TypeFoldable> for ty::Const<'tcx> { fn try_fold_with>>( self, @@ -579,6 +617,10 @@ impl<'tcx> TypeFoldable> for ty::Const<'tcx> { ) -> Result { folder.try_fold_const(self) } + + fn fold_with>>(self, folder: &mut F) -> Self { + folder.fold_const(self) + } } impl<'tcx> TypeVisitable> for ty::Const<'tcx> { @@ -606,6 +648,20 @@ impl<'tcx> TypeSuperFoldable> for ty::Const<'tcx> { }; if kind != self.kind() { Ok(folder.cx().mk_ct_from_kind(kind)) } else { Ok(self) } } + + fn super_fold_with>>(self, folder: &mut F) -> Self { + let kind = match self.kind() { + ConstKind::Param(p) => ConstKind::Param(p.fold_with(folder)), + ConstKind::Infer(i) => ConstKind::Infer(i.fold_with(folder)), + ConstKind::Bound(d, b) => ConstKind::Bound(d.fold_with(folder), b.fold_with(folder)), + ConstKind::Placeholder(p) => ConstKind::Placeholder(p.fold_with(folder)), + ConstKind::Unevaluated(uv) => ConstKind::Unevaluated(uv.fold_with(folder)), + ConstKind::Value(v) => ConstKind::Value(v.fold_with(folder)), + ConstKind::Error(e) => ConstKind::Error(e.fold_with(folder)), + ConstKind::Expr(e) => ConstKind::Expr(e.fold_with(folder)), + }; + if kind != self.kind() { folder.cx().mk_ct_from_kind(kind) } else { self } + } } impl<'tcx> TypeSuperVisitable> for ty::Const<'tcx> { @@ -639,20 +695,9 @@ impl<'tcx> TypeFoldable> for rustc_span::ErrorGuaranteed { ) -> Result { Ok(self) } -} -impl<'tcx> TypeFoldable> for InferConst { - fn try_fold_with>>( - self, - _folder: &mut F, - ) -> Result { - Ok(self) - } -} - -impl<'tcx> TypeVisitable> for InferConst { - fn visit_with>>(&self, _visitor: &mut V) -> V::Result { - V::Result::output() + fn fold_with>>(self, _folder: &mut F) -> Self { + self } } @@ -683,23 +728,9 @@ impl<'tcx, T: TypeFoldable> + Debug + Clone> TypeFoldable TypeFoldable> for &'tcx [InlineAsmTemplatePiece] { - fn try_fold_with>>( - self, - _folder: &mut F, - ) -> Result { - Ok(self) - } -} - -impl<'tcx> TypeFoldable> for &'tcx [Span] { - fn try_fold_with>>( - self, - _folder: &mut F, - ) -> Result { - Ok(self) + fn fold_with>>(self, folder: &mut F) -> Self { + Spanned { node: self.node.fold_with(folder), span: self.span.fold_with(folder) } } } @@ -710,13 +741,37 @@ impl<'tcx> TypeFoldable> for &'tcx ty::List { ) -> Result { Ok(self) } -} -impl<'tcx> TypeFoldable> for &'tcx ty::List> { - fn try_fold_with>>( - self, - folder: &mut F, - ) -> Result { - ty::util::fold_list(self, folder, |tcx, v| tcx.mk_place_elems(v)) + fn fold_with>>(self, _folder: &mut F) -> Self { + self } } + +macro_rules! list_fold { + ($($ty:ty : $mk:ident),+ $(,)?) => { + $( + impl<'tcx> TypeFoldable> for $ty { + fn try_fold_with>>( + self, + folder: &mut F, + ) -> Result { + ty::util::try_fold_list(self, folder, |tcx, v| tcx.$mk(v)) + } + + fn fold_with>>( + self, + folder: &mut F, + ) -> Self { + ty::util::fold_list(self, folder, |tcx, v| tcx.$mk(v)) + } + } + )* + } +} + +list_fold! { + ty::Clauses<'tcx> : mk_clauses, + &'tcx ty::List> : mk_poly_existential_predicates, + &'tcx ty::List> : mk_place_elems, + CanonicalVarInfos<'tcx> : mk_canonical_var_infos, +} diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 857b462b9eb1..e7140720b1c7 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -1647,6 +1647,42 @@ pub fn fold_list<'tcx, F, L, T>( list: L, folder: &mut F, intern: impl FnOnce(TyCtxt<'tcx>, &[T]) -> L, +) -> L +where + F: TypeFolder>, + L: AsRef<[T]>, + T: TypeFoldable> + PartialEq + Copy, +{ + let slice = list.as_ref(); + let mut iter = slice.iter().copied(); + // Look for the first element that changed + match iter.by_ref().enumerate().find_map(|(i, t)| { + let new_t = t.fold_with(folder); + if new_t != t { Some((i, new_t)) } else { None } + }) { + Some((i, new_t)) => { + // An element changed, prepare to intern the resulting list + let mut new_list = SmallVec::<[_; 8]>::with_capacity(slice.len()); + new_list.extend_from_slice(&slice[..i]); + new_list.push(new_t); + for t in iter { + new_list.push(t.fold_with(folder)) + } + intern(folder.cx(), &new_list) + } + None => list, + } +} + +/// Does the equivalent of +/// ```ignore (illustrative) +/// let v = self.iter().map(|p| p.try_fold_with(folder)).collect::>(); +/// folder.tcx().intern_*(&v) +/// ``` +pub fn try_fold_list<'tcx, F, L, T>( + list: L, + folder: &mut F, + intern: impl FnOnce(TyCtxt<'tcx>, &[T]) -> L, ) -> Result where F: FallibleTypeFolder>, diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs index e9055940310d..27ea4e211fef 100644 --- a/compiler/rustc_type_ir/src/binder.rs +++ b/compiler/rustc_type_ir/src/binder.rs @@ -122,6 +122,10 @@ impl> TypeFoldable for Binder { fn try_fold_with>(self, folder: &mut F) -> Result { folder.try_fold_binder(self) } + + fn fold_with>(self, folder: &mut F) -> Self { + folder.fold_binder(self) + } } impl> TypeVisitable for Binder { @@ -135,7 +139,11 @@ impl> TypeSuperFoldable for Binder { self, folder: &mut F, ) -> Result { - self.try_map_bound(|ty| ty.try_fold_with(folder)) + self.try_map_bound(|t| t.try_fold_with(folder)) + } + + fn super_fold_with>(self, folder: &mut F) -> Self { + self.map_bound(|t| t.fold_with(folder)) } } diff --git a/compiler/rustc_type_ir/src/fold.rs b/compiler/rustc_type_ir/src/fold.rs index e58f25f4ce78..ce1188070ca7 100644 --- a/compiler/rustc_type_ir/src/fold.rs +++ b/compiler/rustc_type_ir/src/fold.rs @@ -45,6 +45,7 @@ //! - u.fold_with(folder) //! ``` +use std::convert::Infallible; use std::mem; use std::sync::Arc; @@ -56,12 +57,6 @@ use crate::inherent::*; use crate::visit::{TypeVisitable, TypeVisitableExt as _}; use crate::{self as ty, Interner, TypeFlags}; -#[cfg(feature = "nightly")] -type Never = !; - -#[cfg(not(feature = "nightly"))] -type Never = std::convert::Infallible; - /// This trait is implemented for every type that can be folded, /// providing the skeleton of the traversal. /// @@ -82,18 +77,24 @@ pub trait TypeFoldable: TypeVisitable + Clone { /// /// For types of interest (such as `Ty`), the implementation of this method /// calls a folder method specifically for that type (such as - /// `F::try_fold_ty`). This is where control transfers from `TypeFoldable` - /// to `TypeFolder`. + /// `F::try_fold_ty`). This is where control transfers from [`TypeFoldable`] + /// to [`FallibleTypeFolder`]. fn try_fold_with>(self, folder: &mut F) -> Result; - /// A convenient alternative to `try_fold_with` for use with infallible - /// folders. Do not override this method, to ensure coherence with - /// `try_fold_with`. - fn fold_with>(self, folder: &mut F) -> Self { - match self.try_fold_with(folder) { - Ok(t) => t, - } - } + /// The entry point for folding. To fold a value `t` with a folder `f` + /// call: `t.fold_with(f)`. + /// + /// For most types, this just traverses the value, calling `fold_with` + /// on each field/element. + /// + /// For types of interest (such as `Ty`), the implementation of this method + /// calls a folder method specifically for that type (such as + /// `F::fold_ty`). This is where control transfers from `TypeFoldable` + /// to `TypeFolder`. + /// + /// Same as [`TypeFoldable::try_fold_with`], but not fallible. Make sure to keep + /// the behavior in sync across functions. + fn fold_with>(self, folder: &mut F) -> Self; } // This trait is implemented for types of interest. @@ -112,11 +113,7 @@ pub trait TypeSuperFoldable: TypeFoldable { /// A convenient alternative to `try_super_fold_with` for use with /// infallible folders. Do not override this method, to ensure coherence /// with `try_super_fold_with`. - fn super_fold_with>(self, folder: &mut F) -> Self { - match self.try_super_fold_with(folder) { - Ok(t) => t, - } - } + fn super_fold_with>(self, folder: &mut F) -> Self; } /// This trait is implemented for every infallible folding traversal. There is @@ -128,7 +125,7 @@ pub trait TypeSuperFoldable: TypeFoldable { /// A blanket implementation of [`FallibleTypeFolder`] will defer to /// the infallible methods of this trait to ensure that the two APIs /// are coherent. -pub trait TypeFolder: FallibleTypeFolder { +pub trait TypeFolder: Sized { fn cx(&self) -> I; fn fold_binder(&mut self, t: ty::Binder) -> ty::Binder @@ -195,42 +192,6 @@ pub trait FallibleTypeFolder: Sized { } } -// This blanket implementation of the fallible trait for infallible folders -// delegates to infallible methods to ensure coherence. -impl FallibleTypeFolder for F -where - F: TypeFolder, -{ - type Error = Never; - - fn cx(&self) -> I { - TypeFolder::cx(self) - } - - fn try_fold_binder(&mut self, t: ty::Binder) -> Result, Never> - where - T: TypeFoldable, - { - Ok(self.fold_binder(t)) - } - - fn try_fold_ty(&mut self, t: I::Ty) -> Result { - Ok(self.fold_ty(t)) - } - - fn try_fold_region(&mut self, r: I::Region) -> Result { - Ok(self.fold_region(r)) - } - - fn try_fold_const(&mut self, c: I::Const) -> Result { - Ok(self.fold_const(c)) - } - - fn try_fold_predicate(&mut self, p: I::Predicate) -> Result { - Ok(self.fold_predicate(p)) - } -} - /////////////////////////////////////////////////////////////////////////// // Traversal implementations. @@ -238,6 +199,10 @@ impl, U: TypeFoldable> TypeFoldable for (T fn try_fold_with>(self, folder: &mut F) -> Result<(T, U), F::Error> { Ok((self.0.try_fold_with(folder)?, self.1.try_fold_with(folder)?)) } + + fn fold_with>(self, folder: &mut F) -> Self { + (self.0.fold_with(folder), self.1.fold_with(folder)) + } } impl, B: TypeFoldable, C: TypeFoldable> TypeFoldable @@ -253,6 +218,10 @@ impl, B: TypeFoldable, C: TypeFoldable> Ty self.2.try_fold_with(folder)?, )) } + + fn fold_with>(self, folder: &mut F) -> Self { + (self.0.fold_with(folder), self.1.fold_with(folder), self.2.fold_with(folder)) + } } impl> TypeFoldable for Option { @@ -262,6 +231,10 @@ impl> TypeFoldable for Option { None => None, }) } + + fn fold_with>(self, folder: &mut F) -> Self { + Some(self?.fold_with(folder)) + } } impl, E: TypeFoldable> TypeFoldable for Result { @@ -271,41 +244,61 @@ impl, E: TypeFoldable> TypeFoldable for Re Err(e) => Err(e.try_fold_with(folder)?), }) } + + fn fold_with>(self, folder: &mut F) -> Self { + match self { + Ok(v) => Ok(v.fold_with(folder)), + Err(e) => Err(e.fold_with(folder)), + } + } +} + +fn fold_arc( + mut arc: Arc, + fold: impl FnOnce(T) -> Result, +) -> Result, E> { + // We merely want to replace the contained `T`, if at all possible, + // so that we don't needlessly allocate a new `Arc` or indeed clone + // the contained type. + unsafe { + // First step is to ensure that we have a unique reference to + // the contained type, which `Arc::make_mut` will accomplish (by + // allocating a new `Arc` and cloning the `T` only if required). + // This is done *before* casting to `Arc>` so that + // panicking during `make_mut` does not leak the `T`. + Arc::make_mut(&mut arc); + + // Casting to `Arc>` is safe because `ManuallyDrop` + // is `repr(transparent)`. + let ptr = Arc::into_raw(arc).cast::>(); + let mut unique = Arc::from_raw(ptr); + + // Call to `Arc::make_mut` above guarantees that `unique` is the + // sole reference to the contained value, so we can avoid doing + // a checked `get_mut` here. + let slot = Arc::get_mut(&mut unique).unwrap_unchecked(); + + // Semantically move the contained type out from `unique`, fold + // it, then move the folded value back into `unique`. Should + // folding fail, `ManuallyDrop` ensures that the "moved-out" + // value is not re-dropped. + let owned = mem::ManuallyDrop::take(slot); + let folded = fold(owned)?; + *slot = mem::ManuallyDrop::new(folded); + + // Cast back to `Arc`. + Ok(Arc::from_raw(Arc::into_raw(unique).cast())) + } } impl> TypeFoldable for Arc { - fn try_fold_with>(mut self, folder: &mut F) -> Result { - // We merely want to replace the contained `T`, if at all possible, - // so that we don't needlessly allocate a new `Arc` or indeed clone - // the contained type. - unsafe { - // First step is to ensure that we have a unique reference to - // the contained type, which `Arc::make_mut` will accomplish (by - // allocating a new `Arc` and cloning the `T` only if required). - // This is done *before* casting to `Arc>` so that - // panicking during `make_mut` does not leak the `T`. - Arc::make_mut(&mut self); + fn try_fold_with>(self, folder: &mut F) -> Result { + fold_arc(self, |t| t.try_fold_with(folder)) + } - // Casting to `Arc>` is safe because `ManuallyDrop` - // is `repr(transparent)`. - let ptr = Arc::into_raw(self).cast::>(); - let mut unique = Arc::from_raw(ptr); - - // Call to `Arc::make_mut` above guarantees that `unique` is the - // sole reference to the contained value, so we can avoid doing - // a checked `get_mut` here. - let slot = Arc::get_mut(&mut unique).unwrap_unchecked(); - - // Semantically move the contained type out from `unique`, fold - // it, then move the folded value back into `unique`. Should - // folding fail, `ManuallyDrop` ensures that the "moved-out" - // value is not re-dropped. - let owned = mem::ManuallyDrop::take(slot); - let folded = owned.try_fold_with(folder)?; - *slot = mem::ManuallyDrop::new(folded); - - // Cast back to `Arc`. - Ok(Arc::from_raw(Arc::into_raw(unique).cast())) + fn fold_with>(self, folder: &mut F) -> Self { + match fold_arc::(self, |t| Ok(t.fold_with(folder))) { + Ok(t) => t, } } } @@ -315,30 +308,51 @@ impl> TypeFoldable for Box { *self = (*self).try_fold_with(folder)?; Ok(self) } + + fn fold_with>(mut self, folder: &mut F) -> Self { + *self = (*self).fold_with(folder); + self + } } impl> TypeFoldable for Vec { fn try_fold_with>(self, folder: &mut F) -> Result { self.into_iter().map(|t| t.try_fold_with(folder)).collect() } + + fn fold_with>(self, folder: &mut F) -> Self { + self.into_iter().map(|t| t.fold_with(folder)).collect() + } } impl> TypeFoldable for ThinVec { fn try_fold_with>(self, folder: &mut F) -> Result { self.into_iter().map(|t| t.try_fold_with(folder)).collect() } + + fn fold_with>(self, folder: &mut F) -> Self { + self.into_iter().map(|t| t.fold_with(folder)).collect() + } } impl> TypeFoldable for Box<[T]> { fn try_fold_with>(self, folder: &mut F) -> Result { Vec::from(self).try_fold_with(folder).map(Vec::into_boxed_slice) } + + fn fold_with>(self, folder: &mut F) -> Self { + Vec::into_boxed_slice(Vec::from(self).fold_with(folder)) + } } impl, Ix: Idx> TypeFoldable for IndexVec { fn try_fold_with>(self, folder: &mut F) -> Result { self.raw.try_fold_with(folder).map(IndexVec::from_raw) } + + fn fold_with>(self, folder: &mut F) -> Self { + IndexVec::from_raw(self.raw.fold_with(folder)) + } } /////////////////////////////////////////////////////////////////////////// diff --git a/compiler/rustc_type_ir_macros/src/lib.rs b/compiler/rustc_type_ir_macros/src/lib.rs index 8eefecdc980e..3a10d0d41ef3 100644 --- a/compiler/rustc_type_ir_macros/src/lib.rs +++ b/compiler/rustc_type_ir_macros/src/lib.rs @@ -83,7 +83,7 @@ fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::Toke s.add_where_predicate(parse_quote! { I: Interner }); s.add_bounds(synstructure::AddBounds::Fields); s.bind_with(|_| synstructure::BindStyle::Move); - let body_fold = s.each_variant(|vi| { + let body_try_fold = s.each_variant(|vi| { let bindings = vi.bindings(); vi.construct(|_, index| { let bind = &bindings[index]; @@ -99,6 +99,22 @@ fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::Toke }) }); + let body_fold = s.each_variant(|vi| { + let bindings = vi.bindings(); + vi.construct(|_, index| { + let bind = &bindings[index]; + + // retain value of fields with #[type_foldable(identity)] + if has_ignore_attr(&bind.ast().attrs, "type_foldable", "identity") { + bind.to_token_stream() + } else { + quote! { + ::rustc_type_ir::TypeFoldable::fold_with(#bind, __folder) + } + } + }) + }); + // We filter fields which get ignored and don't require them to implement // `TypeFoldable`. We do so after generating `body_fold` as we still need // to generate code for them. @@ -111,7 +127,14 @@ fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::Toke self, __folder: &mut __F ) -> Result { - Ok(match self { #body_fold }) + Ok(match self { #body_try_fold }) + } + + fn fold_with<__F: ::rustc_type_ir::TypeFolder>( + self, + __folder: &mut __F + ) -> Self { + match self { #body_fold } } }, ) From 11e5987d017b4ab8dfc522d674aea704aad8605a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 15 Apr 2025 18:46:07 +0000 Subject: [PATCH 500/606] Don't compute name of associated item if it's an RPITIT --- .../rustc_hir_analysis/src/hir_ty_lowering/errors.rs | 3 +-- .../in-trait/dont-probe-missing-item-name.rs | 12 ++++++++++++ .../in-trait/dont-probe-missing-item-name.stderr | 9 +++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 tests/ui/impl-trait/in-trait/dont-probe-missing-item-name.rs create mode 100644 tests/ui/impl-trait/in-trait/dont-probe-missing-item-name.stderr diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 72f219bfeb80..3759a224ff75 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -204,8 +204,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .iter() .flat_map(|trait_def_id| tcx.associated_items(*trait_def_id).in_definition_order()) .filter_map(|item| { - (!item.is_impl_trait_in_trait() && item.as_tag() == assoc_tag) - .then_some(item.name()) + (!item.is_impl_trait_in_trait() && item.as_tag() == assoc_tag).then(|| item.name()) }) .collect(); diff --git a/tests/ui/impl-trait/in-trait/dont-probe-missing-item-name.rs b/tests/ui/impl-trait/in-trait/dont-probe-missing-item-name.rs new file mode 100644 index 000000000000..450f41e209df --- /dev/null +++ b/tests/ui/impl-trait/in-trait/dont-probe-missing-item-name.rs @@ -0,0 +1,12 @@ +// Regression test for . + +// Test that we don't try to get the (nonexistent) name of the RPITIT in `Trait::foo` +// when emitting an error for a missing associated item `Trait::Output`. + +trait Trait { + fn foo() -> impl Sized; + fn bar() -> Self::Output; + //~^ ERROR associated type `Output` not found for `Self` +} + +fn main() {} diff --git a/tests/ui/impl-trait/in-trait/dont-probe-missing-item-name.stderr b/tests/ui/impl-trait/in-trait/dont-probe-missing-item-name.stderr new file mode 100644 index 000000000000..74e15785af19 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/dont-probe-missing-item-name.stderr @@ -0,0 +1,9 @@ +error[E0220]: associated type `Output` not found for `Self` + --> $DIR/dont-probe-missing-item-name.rs:8:23 + | +LL | fn bar() -> Self::Output; + | ^^^^^^ associated type `Output` not found + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0220`. From 2020adba86cb2852b11ab11a440975fb331e8424 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 15 Apr 2025 16:59:16 +0200 Subject: [PATCH 501/606] Fix wrong suggestion for async gen block and add regression ui test for #139839 --- .../src/diagnostics/conflict_errors.rs | 13 +++-- .../async-gen-move-suggestion.fixed | 35 ++++++++++++++ .../async-await/async-gen-move-suggestion.rs | 35 ++++++++++++++ .../async-gen-move-suggestion.stderr | 47 +++++++++++++++++++ 4 files changed, 126 insertions(+), 4 deletions(-) create mode 100644 tests/ui/async-await/async-gen-move-suggestion.fixed create mode 100644 tests/ui/async-await/async-gen-move-suggestion.rs create mode 100644 tests/ui/async-await/async-gen-move-suggestion.stderr diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index fe6dff7ff1b6..959cf9fa5139 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -3376,10 +3376,15 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { let (sugg_span, suggestion) = match tcx.sess.source_map().span_to_snippet(args_span) { Ok(string) => { - let coro_prefix = if string.starts_with("async") { - // `async` is 5 chars long. Not using `.len()` to avoid the cast from `usize` - // to `u32`. - Some(5) + let coro_prefix = if let Some(sub) = string.strip_prefix("async") { + let trimmed_sub = sub.trim_end(); + if trimmed_sub.ends_with("gen") { + // `async` is 5 chars long. + Some((trimmed_sub.len() + 5) as _) + } else { + // `async` is 5 chars long. + Some(5) + } } else if string.starts_with("gen") { // `gen` is 3 chars long Some(3) diff --git a/tests/ui/async-await/async-gen-move-suggestion.fixed b/tests/ui/async-await/async-gen-move-suggestion.fixed new file mode 100644 index 000000000000..d80207655289 --- /dev/null +++ b/tests/ui/async-await/async-gen-move-suggestion.fixed @@ -0,0 +1,35 @@ +// This is a regression test for . +// It ensures that the "add `move` keyword" suggestion is valid. + +//@ run-rustfix +//@ edition:2024 + +#![feature(coroutines)] +#![feature(gen_blocks)] +#![feature(async_iterator)] + +use std::async_iter::AsyncIterator; + +#[allow(dead_code)] +fn moved() -> impl AsyncIterator { + let mut x = "foo".to_string(); + + async gen move { //~ ERROR + x.clear(); + for x in 3..6 { yield x } + } +} + +#[allow(dead_code)] +fn check_with_whitespace_chars() -> impl AsyncIterator { + let mut x = "foo".to_string(); + + async // Just to check that whitespace characters are correctly handled + gen move { //~^ ERROR + x.clear(); + for x in 3..6 { yield x } + } +} + +fn main() { +} diff --git a/tests/ui/async-await/async-gen-move-suggestion.rs b/tests/ui/async-await/async-gen-move-suggestion.rs new file mode 100644 index 000000000000..825fb0fd1898 --- /dev/null +++ b/tests/ui/async-await/async-gen-move-suggestion.rs @@ -0,0 +1,35 @@ +// This is a regression test for . +// It ensures that the "add `move` keyword" suggestion is valid. + +//@ run-rustfix +//@ edition:2024 + +#![feature(coroutines)] +#![feature(gen_blocks)] +#![feature(async_iterator)] + +use std::async_iter::AsyncIterator; + +#[allow(dead_code)] +fn moved() -> impl AsyncIterator { + let mut x = "foo".to_string(); + + async gen { //~ ERROR + x.clear(); + for x in 3..6 { yield x } + } +} + +#[allow(dead_code)] +fn check_with_whitespace_chars() -> impl AsyncIterator { + let mut x = "foo".to_string(); + + async // Just to check that whitespace characters are correctly handled + gen { //~^ ERROR + x.clear(); + for x in 3..6 { yield x } + } +} + +fn main() { +} diff --git a/tests/ui/async-await/async-gen-move-suggestion.stderr b/tests/ui/async-await/async-gen-move-suggestion.stderr new file mode 100644 index 000000000000..b8cdb8be7a4a --- /dev/null +++ b/tests/ui/async-await/async-gen-move-suggestion.stderr @@ -0,0 +1,47 @@ +error[E0373]: async gen block may outlive the current function, but it borrows `x`, which is owned by the current function + --> $DIR/async-gen-move-suggestion.rs:17:5 + | +LL | async gen { + | ^^^^^^^^^ may outlive borrowed value `x` +LL | x.clear(); + | - `x` is borrowed here + | +note: async gen block is returned here + --> $DIR/async-gen-move-suggestion.rs:17:5 + | +LL | / async gen { +LL | | x.clear(); +LL | | for x in 3..6 { yield x } +LL | | } + | |_____^ +help: to force the async gen block to take ownership of `x` (and any other referenced variables), use the `move` keyword + | +LL | async gen move { + | ++++ + +error[E0373]: async gen block may outlive the current function, but it borrows `x`, which is owned by the current function + --> $DIR/async-gen-move-suggestion.rs:27:5 + | +LL | / async // Just to check that whitespace characters are correctly handled +LL | | gen { + | |_______^ may outlive borrowed value `x` +LL | x.clear(); + | - `x` is borrowed here + | +note: async gen block is returned here + --> $DIR/async-gen-move-suggestion.rs:27:5 + | +LL | / async // Just to check that whitespace characters are correctly handled +LL | | gen { +LL | | x.clear(); +LL | | for x in 3..6 { yield x } +LL | | } + | |_____^ +help: to force the async gen block to take ownership of `x` (and any other referenced variables), use the `move` keyword + | +LL | gen move { + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0373`. From 90aec1367481ab05c78fefad314e03b26e84564f Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Tue, 15 Apr 2025 14:06:51 +0200 Subject: [PATCH 502/606] commit rustfmt stump in `x t tidy` even on `check` If checking succeeded, it's equivalent to successfully formatting. --- src/bootstrap/src/core/build_steps/format.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs index 6641c4b4e139..9da8b27a9177 100644 --- a/src/bootstrap/src/core/build_steps/format.rs +++ b/src/bootstrap/src/core/build_steps/format.rs @@ -336,7 +336,10 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) { crate::exit!(1); } - if !check { - update_rustfmt_version(build); - } + // Update `build/.rustfmt-stamp`, allowing this code to ignore files which have not been changed + // since last merge. + // + // NOTE: Because of the exit above, this is only reachable if formatting / format checking + // succeeded. So we are not commiting the version if formatting was not good. + update_rustfmt_version(build); } From 89b4eba49cc15e0a4e53f7816473201d12be5f4f Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Tue, 15 Apr 2025 10:09:31 +0200 Subject: [PATCH 503/606] normalize canonical and non-canonical paths in compiletest Apparently there are tests that print canonical paths *and* tests which print non-canonical paths. An example of the latter is `tests/ui/type_length_limit.rs`. --- src/tools/compiletest/src/runtest.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index fc83ea420430..eb298060b2ec 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2375,13 +2375,16 @@ impl<'test> TestCx<'test> { let rust_src_dir = rust_src_dir.read_link_utf8().unwrap_or(rust_src_dir.to_path_buf()); normalize_path(&rust_src_dir.join("library"), "$SRC_DIR_REAL"); - // Canonicalize test build directory path. - // Without this some tests fail if build directory is a symlink. - let output_base_dir = self.output_base_dir().canonicalize_utf8().unwrap(); - // eg. // /home/user/rust/build/x86_64-unknown-linux-gnu/test/ui//$name.$revision.$mode/ - normalize_path(&output_base_dir, "$TEST_BUILD_DIR"); + normalize_path(&self.output_base_dir(), "$TEST_BUILD_DIR"); + // Same as above, but with a canonicalized path. + // This is required because some tests print canonical paths inside test build directory, + // so if the build directory is a symlink, normalization doesn't help. + // + // NOTE: There are also tests which print the non-canonical name, so we need both this and + // the above normalizations. + normalize_path(&self.output_base_dir().canonicalize_utf8().unwrap(), "$TEST_BUILD_DIR"); // eg. /home/user/rust/build normalize_path(&self.config.build_root, "$BUILD_DIR"); From f35c85f72fc1249f0553d97482ca29fe3fa0a165 Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Tue, 8 Apr 2025 16:11:28 -0700 Subject: [PATCH 504/606] Add unstable foo::bar extern command line arguments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also refactors some of the crate name parsing code and adds unit tests Issue #122349 Co-authored-by: León Orell Valerian Liehr --- compiler/rustc_session/src/config.rs | 39 +------- compiler/rustc_session/src/config/externs.rs | 79 ++++++++++++++++ .../rustc_session/src/config/externs/tests.rs | 92 +++++++++++++++++++ compiler/rustc_session/src/options.rs | 2 + 4 files changed, 178 insertions(+), 34 deletions(-) create mode 100644 compiler/rustc_session/src/config/externs.rs create mode 100644 compiler/rustc_session/src/config/externs/tests.rs diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index fc05470d941c..202378560eed 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -14,6 +14,7 @@ use std::str::{self, FromStr}; use std::sync::LazyLock; use std::{cmp, fmt, fs, iter}; +use externs::{ExternOpt, split_extern_opt}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_data_structures::stable_hasher::{StableOrd, ToStableHashKey}; use rustc_errors::emitter::HumanReadableErrorType; @@ -39,6 +40,7 @@ use crate::utils::CanonicalizedPath; use crate::{EarlyDiagCtxt, HashStableContext, Session, filesearch, lint}; mod cfg; +mod externs; mod native_libs; pub mod sigpipe; @@ -2205,44 +2207,13 @@ pub fn parse_externs( matches: &getopts::Matches, unstable_opts: &UnstableOptions, ) -> Externs { - fn is_ascii_ident(string: &str) -> bool { - let mut chars = string.chars(); - if let Some(start) = chars.next() - && (start.is_ascii_alphabetic() || start == '_') - { - chars.all(|char| char.is_ascii_alphanumeric() || char == '_') - } else { - false - } - } - let is_unstable_enabled = unstable_opts.unstable_options; let mut externs: BTreeMap = BTreeMap::new(); for arg in matches.opt_strs("extern") { - let (name, path) = match arg.split_once('=') { - None => (arg, None), - Some((name, path)) => (name.to_string(), Some(Path::new(path))), - }; - let (options, name) = match name.split_once(':') { - None => (None, name), - Some((opts, name)) => (Some(opts), name.to_string()), - }; + let ExternOpt { crate_name: name, path, options } = + split_extern_opt(early_dcx, unstable_opts, &arg).unwrap_or_else(|e| e.emit()); - if !is_ascii_ident(&name) { - let mut error = early_dcx.early_struct_fatal(format!( - "crate name `{name}` passed to `--extern` is not a valid ASCII identifier" - )); - let adjusted_name = name.replace('-', "_"); - if is_ascii_ident(&adjusted_name) { - #[allow(rustc::diagnostic_outside_of_impl)] // FIXME - error.help(format!( - "consider replacing the dashes with underscores: `{adjusted_name}`" - )); - } - error.emit(); - } - - let path = path.map(|p| CanonicalizedPath::new(p)); + let path = path.map(|p| CanonicalizedPath::new(p.as_path())); let entry = externs.entry(name.to_owned()); diff --git a/compiler/rustc_session/src/config/externs.rs b/compiler/rustc_session/src/config/externs.rs new file mode 100644 index 000000000000..1420ee38bf21 --- /dev/null +++ b/compiler/rustc_session/src/config/externs.rs @@ -0,0 +1,79 @@ +//! This module contains code to help parse and manipulate `--extern` arguments. + +use std::path::PathBuf; + +use rustc_errors::{Diag, FatalAbort}; + +use super::UnstableOptions; +use crate::EarlyDiagCtxt; + +#[cfg(test)] +mod tests; + +/// Represents the pieces of an `--extern` argument. +pub(crate) struct ExternOpt { + pub(crate) crate_name: String, + pub(crate) path: Option, + pub(crate) options: Option, +} + +/// Breaks out the major components of an `--extern` argument. +/// +/// The options field will be a string containing comma-separated options that will need further +/// parsing and processing. +pub(crate) fn split_extern_opt<'a>( + early_dcx: &'a EarlyDiagCtxt, + unstable_opts: &UnstableOptions, + extern_opt: &str, +) -> Result> { + let (name, path) = match extern_opt.split_once('=') { + None => (extern_opt.to_string(), None), + Some((name, path)) => (name.to_string(), Some(PathBuf::from(path))), + }; + let (options, crate_name) = match name.split_once(':') { + None => (None, name), + Some((opts, crate_name)) => { + if unstable_opts.namespaced_crates && crate_name.starts_with(':') { + // If the name starts with `:`, we know this was actually something like `foo::bar` and + // not a set of options. We can just use the original name as the crate name. + (None, name) + } else { + (Some(opts.to_string()), crate_name.to_string()) + } + } + }; + + if !valid_crate_name(&crate_name, unstable_opts) { + let mut error = early_dcx.early_struct_fatal(format!( + "crate name `{crate_name}` passed to `--extern` is not a valid ASCII identifier" + )); + let adjusted_name = crate_name.replace('-', "_"); + if is_ascii_ident(&adjusted_name) { + #[allow(rustc::diagnostic_outside_of_impl)] // FIXME + error + .help(format!("consider replacing the dashes with underscores: `{adjusted_name}`")); + } + return Err(error); + } + + Ok(ExternOpt { crate_name, path, options }) +} + +fn valid_crate_name(name: &str, unstable_opts: &UnstableOptions) -> bool { + match name.split_once("::") { + Some((a, b)) if unstable_opts.namespaced_crates => is_ascii_ident(a) && is_ascii_ident(b), + Some(_) => false, + None => is_ascii_ident(name), + } +} + +fn is_ascii_ident(string: &str) -> bool { + let mut chars = string.chars(); + if let Some(start) = chars.next() + && (start.is_ascii_alphabetic() || start == '_') + { + chars.all(|char| char.is_ascii_alphanumeric() || char == '_') + } else { + false + } +} diff --git a/compiler/rustc_session/src/config/externs/tests.rs b/compiler/rustc_session/src/config/externs/tests.rs new file mode 100644 index 000000000000..654488695157 --- /dev/null +++ b/compiler/rustc_session/src/config/externs/tests.rs @@ -0,0 +1,92 @@ +use std::path::PathBuf; + +use super::split_extern_opt; +use crate::EarlyDiagCtxt; +use crate::config::UnstableOptions; + +/// Verifies split_extern_opt handles the supported cases. +#[test] +fn test_split_extern_opt() { + let early_dcx = EarlyDiagCtxt::new(<_>::default()); + let unstable_opts = &UnstableOptions::default(); + + let extern_opt = + split_extern_opt(&early_dcx, unstable_opts, "priv,noprelude:foo=libbar.rlib").unwrap(); + assert_eq!(extern_opt.crate_name, "foo"); + assert_eq!(extern_opt.path, Some(PathBuf::from("libbar.rlib"))); + assert_eq!(extern_opt.options, Some("priv,noprelude".to_string())); + + let extern_opt = split_extern_opt(&early_dcx, unstable_opts, "priv,noprelude:foo").unwrap(); + assert_eq!(extern_opt.crate_name, "foo"); + assert_eq!(extern_opt.path, None); + assert_eq!(extern_opt.options, Some("priv,noprelude".to_string())); + + let extern_opt = split_extern_opt(&early_dcx, unstable_opts, "foo=libbar.rlib").unwrap(); + assert_eq!(extern_opt.crate_name, "foo"); + assert_eq!(extern_opt.path, Some(PathBuf::from("libbar.rlib"))); + assert_eq!(extern_opt.options, None); + + let extern_opt = split_extern_opt(&early_dcx, unstable_opts, "foo").unwrap(); + assert_eq!(extern_opt.crate_name, "foo"); + assert_eq!(extern_opt.path, None); + assert_eq!(extern_opt.options, None); +} + +/// Tests some invalid cases for split_extern_opt. +#[test] +fn test_split_extern_opt_invalid() { + let early_dcx = EarlyDiagCtxt::new(<_>::default()); + let unstable_opts = &UnstableOptions::default(); + + // too many `:`s + let result = split_extern_opt(&early_dcx, unstable_opts, "priv:noprelude:foo=libbar.rlib"); + assert!(result.is_err()); + let _ = result.map_err(|e| e.cancel()); + + // can't nest externs without the unstable flag + let result = split_extern_opt(&early_dcx, unstable_opts, "noprelude:foo::bar=libbar.rlib"); + assert!(result.is_err()); + let _ = result.map_err(|e| e.cancel()); +} + +/// Tests some cases for split_extern_opt with nested crates like `foo::bar`. +#[test] +fn test_split_extern_opt_nested() { + let early_dcx = EarlyDiagCtxt::new(<_>::default()); + let unstable_opts = &UnstableOptions { namespaced_crates: true, ..Default::default() }; + + let extern_opt = + split_extern_opt(&early_dcx, unstable_opts, "priv,noprelude:foo::bar=libbar.rlib").unwrap(); + assert_eq!(extern_opt.crate_name, "foo::bar"); + assert_eq!(extern_opt.path, Some(PathBuf::from("libbar.rlib"))); + assert_eq!(extern_opt.options, Some("priv,noprelude".to_string())); + + let extern_opt = + split_extern_opt(&early_dcx, unstable_opts, "priv,noprelude:foo::bar").unwrap(); + assert_eq!(extern_opt.crate_name, "foo::bar"); + assert_eq!(extern_opt.path, None); + assert_eq!(extern_opt.options, Some("priv,noprelude".to_string())); + + let extern_opt = split_extern_opt(&early_dcx, unstable_opts, "foo::bar=libbar.rlib").unwrap(); + assert_eq!(extern_opt.crate_name, "foo::bar"); + assert_eq!(extern_opt.path, Some(PathBuf::from("libbar.rlib"))); + assert_eq!(extern_opt.options, None); + + let extern_opt = split_extern_opt(&early_dcx, unstable_opts, "foo::bar").unwrap(); + assert_eq!(extern_opt.crate_name, "foo::bar"); + assert_eq!(extern_opt.path, None); + assert_eq!(extern_opt.options, None); +} + +/// Tests some invalid cases for split_extern_opt with nested crates like `foo::bar`. +#[test] +fn test_split_extern_opt_nested_invalid() { + let early_dcx = EarlyDiagCtxt::new(<_>::default()); + let unstable_opts = &UnstableOptions { namespaced_crates: true, ..Default::default() }; + + // crates can only be nested one deep. + let result = + split_extern_opt(&early_dcx, unstable_opts, "priv,noprelude:foo::bar::baz=libbar.rlib"); + assert!(result.is_err()); + let _ = result.map_err(|e| e.cancel()); +} diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index c70f1500d393..bd66f835f120 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2331,6 +2331,8 @@ options! { "the size at which the `large_assignments` lint starts to be emitted"), mutable_noalias: bool = (true, parse_bool, [TRACKED], "emit noalias metadata for mutable references (default: yes)"), + namespaced_crates: bool = (false, parse_bool, [TRACKED], + "allow crates to be namespaced by other crates (default: no)"), next_solver: NextSolverConfig = (NextSolverConfig::default(), parse_next_solver_config, [TRACKED], "enable and configure the next generation trait solver used by rustc"), nll_facts: bool = (false, parse_bool, [UNTRACKED], From f3f53d2183a4980f36ee6836f172a01a8b92c44a Mon Sep 17 00:00:00 2001 From: rustbot <47979223+rustbot@users.noreply.github.com> Date: Tue, 15 Apr 2025 22:48:28 +0200 Subject: [PATCH 505/606] Update books --- src/doc/book | 2 +- src/doc/edition-guide | 2 +- src/doc/nomicon | 2 +- src/doc/reference | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/doc/book b/src/doc/book index 45f05367360f..d33916341d48 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 45f05367360f033f89235eacbbb54e8d73ce6b70 +Subproject commit d33916341d480caede1d0ae57cbeae23aab23e88 diff --git a/src/doc/edition-guide b/src/doc/edition-guide index 1e27e5e6d513..467f45637b73 160000 --- a/src/doc/edition-guide +++ b/src/doc/edition-guide @@ -1 +1 @@ -Subproject commit 1e27e5e6d5133ae4612f5cc195c15fc8d51b1c9c +Subproject commit 467f45637b73ec6aa70fb36bc3054bb50b8967ea diff --git a/src/doc/nomicon b/src/doc/nomicon index b4448fa406a6..0c10c30cc547 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit b4448fa406a6dccde62d1e2f34f70fc51814cdcc +Subproject commit 0c10c30cc54736c5c194ce98c50e2de84eeb6e79 diff --git a/src/doc/reference b/src/doc/reference index 46435cd4eba1..3340922df189 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 46435cd4eba11b66acaa42c01da5c80ad88aee4b +Subproject commit 3340922df189bddcbaad17dc3927d51a76bcd5ed From fe882bf330f00f7bc07327430fdded4164dac25e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 27 Mar 2025 15:52:33 +1100 Subject: [PATCH 506/606] Rename `LifetimeName` as `LifetimeKind`. It's a much better name, more consistent with how we name such things. Also rename `Lifetime::res` as `Lifetime::kind` to match. I suspect this field used to have the type `LifetimeRes` and then the type was changed but the field name remained the same. --- compiler/rustc_ast_lowering/src/lib.rs | 12 ++--- .../src/diagnostics/region_errors.rs | 2 +- compiler/rustc_hir/src/hir.rs | 20 ++++---- compiler/rustc_hir/src/hir/tests.rs | 2 +- .../src/collect/resolve_bound_vars.rs | 46 +++++++++---------- .../src/hir_ty_lowering/dyn_compatibility.rs | 2 +- compiler/rustc_middle/src/ty/diagnostics.rs | 4 +- .../nice_region_error/static_impl_trait.rs | 8 ++-- .../src/error_reporting/infer/region.rs | 6 +-- src/doc/rustc-dev-guide/src/ty.md | 8 ++-- .../clippy/clippy_lints/src/lifetimes.rs | 14 +++--- src/tools/clippy/clippy_lints/src/ptr.rs | 4 +- .../clippy/clippy_utils/src/hir_utils.rs | 8 ++-- 13 files changed, 68 insertions(+), 68 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index b1d1c35e64a1..b091847fa7e2 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1768,21 +1768,21 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { debug_assert_ne!(ident.name, kw::Empty); let res = self.resolver.get_lifetime_res(id).unwrap_or(LifetimeRes::Error); let res = match res { - LifetimeRes::Param { param, .. } => hir::LifetimeName::Param(param), + LifetimeRes::Param { param, .. } => hir::LifetimeKind::Param(param), LifetimeRes::Fresh { param, .. } => { debug_assert_eq!(ident.name, kw::UnderscoreLifetime); let param = self.local_def_id(param); - hir::LifetimeName::Param(param) + hir::LifetimeKind::Param(param) } LifetimeRes::Infer => { debug_assert_eq!(ident.name, kw::UnderscoreLifetime); - hir::LifetimeName::Infer + hir::LifetimeKind::Infer } LifetimeRes::Static { .. } => { debug_assert!(matches!(ident.name, kw::StaticLifetime | kw::UnderscoreLifetime)); - hir::LifetimeName::Static + hir::LifetimeKind::Static } - LifetimeRes::Error => hir::LifetimeName::Error, + LifetimeRes::Error => hir::LifetimeKind::Error, LifetimeRes::ElidedAnchor { .. } => { panic!("Unexpected `ElidedAnchar` {:?} at {:?}", ident, ident.span); } @@ -2389,7 +2389,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let r = hir::Lifetime::new( self.next_id(), Ident::new(kw::UnderscoreLifetime, self.lower_span(span)), - hir::LifetimeName::ImplicitObjectLifetimeDefault, + hir::LifetimeKind::ImplicitObjectLifetimeDefault, IsAnonInPath::No, ); debug!("elided_dyn_bound: r={:?}", r); diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 8d530b51636a..4423edb06051 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -888,7 +888,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { // Skip `async` desugaring `impl Future`. } if let TyKind::TraitObject(_, lt) = alias_ty.kind { - if lt.res == hir::LifetimeName::ImplicitObjectLifetimeDefault { + if lt.kind == hir::LifetimeKind::ImplicitObjectLifetimeDefault { spans_suggs.push((lt.ident.span.shrink_to_hi(), " + 'a".to_string())); } else { spans_suggs.push((lt.ident.span, "'a".to_string())); diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 6455f33b9d15..3f5269eeb9b9 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -42,7 +42,7 @@ pub enum IsAnonInPath { } /// A lifetime. The valid field combinations are non-obvious. The following -/// example shows some of them. See also the comments on `LifetimeName`. +/// example shows some of them. See also the comments on `LifetimeKind`. /// ``` /// #[repr(C)] /// struct S<'a>(&'a u32); // res=Param, name='a, IsAnonInPath::No @@ -84,7 +84,7 @@ pub struct Lifetime { pub ident: Ident, /// Semantics of this lifetime. - pub res: LifetimeName, + pub kind: LifetimeKind, /// Is the lifetime anonymous and in a path? Used only for error /// suggestions. See `Lifetime::suggestion` for example use. @@ -130,7 +130,7 @@ impl ParamName { } #[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable_Generic)] -pub enum LifetimeName { +pub enum LifetimeKind { /// User-given names or fresh (synthetic) names. Param(LocalDefId), @@ -160,16 +160,16 @@ pub enum LifetimeName { Static, } -impl LifetimeName { +impl LifetimeKind { fn is_elided(&self) -> bool { match self { - LifetimeName::ImplicitObjectLifetimeDefault | LifetimeName::Infer => true, + LifetimeKind::ImplicitObjectLifetimeDefault | LifetimeKind::Infer => true, // It might seem surprising that `Fresh` counts as not *elided* // -- but this is because, as far as the code in the compiler is // concerned -- `Fresh` variants act equivalently to "some fresh name". // They correspond to early-bound regions on an impl, in other words. - LifetimeName::Error | LifetimeName::Param(..) | LifetimeName::Static => false, + LifetimeKind::Error | LifetimeKind::Param(..) | LifetimeKind::Static => false, } } } @@ -184,10 +184,10 @@ impl Lifetime { pub fn new( hir_id: HirId, ident: Ident, - res: LifetimeName, + kind: LifetimeKind, is_anon_in_path: IsAnonInPath, ) -> Lifetime { - let lifetime = Lifetime { hir_id, ident, res, is_anon_in_path }; + let lifetime = Lifetime { hir_id, ident, kind, is_anon_in_path }; // Sanity check: elided lifetimes form a strict subset of anonymous lifetimes. #[cfg(debug_assertions)] @@ -202,7 +202,7 @@ impl Lifetime { } pub fn is_elided(&self) -> bool { - self.res.is_elided() + self.kind.is_elided() } pub fn is_anonymous(&self) -> bool { @@ -1014,7 +1014,7 @@ pub struct WhereRegionPredicate<'hir> { impl<'hir> WhereRegionPredicate<'hir> { /// Returns `true` if `param_def_id` matches the `lifetime` of this predicate. fn is_param_bound(&self, param_def_id: LocalDefId) -> bool { - self.lifetime.res == LifetimeName::Param(param_def_id) + self.lifetime.kind == LifetimeKind::Param(param_def_id) } } diff --git a/compiler/rustc_hir/src/hir/tests.rs b/compiler/rustc_hir/src/hir/tests.rs index 62ef02d2f500..fcd0eafa4613 100644 --- a/compiler/rustc_hir/src/hir/tests.rs +++ b/compiler/rustc_hir/src/hir/tests.rs @@ -57,7 +57,7 @@ fn trait_object_roundtrips_impl(syntax: TraitObjectSyntax) { Lifetime { hir_id: HirId::INVALID, ident: Ident::new(sym::name, DUMMY_SP), - res: LifetimeName::Static, + kind: LifetimeKind::Static, is_anon_in_path: IsAnonInPath::No, } }, diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 1c477755e5ac..59ab36d98fda 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -16,7 +16,7 @@ use rustc_errors::ErrorGuaranteed; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::{self, InferKind, Visitor, VisitorExt}; use rustc_hir::{ - self as hir, AmbigArg, GenericArg, GenericParam, GenericParamKind, HirId, LifetimeName, Node, + self as hir, AmbigArg, GenericArg, GenericParam, GenericParamKind, HirId, LifetimeKind, Node, }; use rustc_macros::extension; use rustc_middle::hir::nested_filter; @@ -646,14 +646,14 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { arg: &'tcx hir::PreciseCapturingArg<'tcx>, ) -> Self::Result { match *arg { - hir::PreciseCapturingArg::Lifetime(lt) => match lt.res { - LifetimeName::Param(def_id) => { + hir::PreciseCapturingArg::Lifetime(lt) => match lt.kind { + LifetimeKind::Param(def_id) => { self.resolve_lifetime_ref(def_id, lt); } - LifetimeName::Error => {} - LifetimeName::ImplicitObjectLifetimeDefault - | LifetimeName::Infer - | LifetimeName::Static => { + LifetimeKind::Error => {} + LifetimeKind::ImplicitObjectLifetimeDefault + | LifetimeKind::Infer + | LifetimeKind::Static => { self.tcx.dcx().emit_err(errors::BadPreciseCapture { span: lt.ident.span, kind: "lifetime", @@ -774,26 +774,26 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { ); } }); - match lifetime.res { - LifetimeName::ImplicitObjectLifetimeDefault => { + match lifetime.kind { + LifetimeKind::ImplicitObjectLifetimeDefault => { // If the user does not write *anything*, we // use the object lifetime defaulting // rules. So e.g., `Box` becomes // `Box`. self.resolve_object_lifetime_default(&*lifetime) } - LifetimeName::Infer => { + LifetimeKind::Infer => { // If the user writes `'_`, we use the *ordinary* elision // rules. So the `'_` in e.g., `Box` will be // resolved the same as the `'_` in `&'_ Foo`. // // cc #48468 } - LifetimeName::Param(..) | LifetimeName::Static => { + LifetimeKind::Param(..) | LifetimeKind::Static => { // If the user wrote an explicit name, use that. self.visit_lifetime(&*lifetime); } - LifetimeName::Error => {} + LifetimeKind::Error => {} } } hir::TyKind::Ref(lifetime_ref, ref mt) => { @@ -873,17 +873,17 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { #[instrument(level = "debug", skip(self))] fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) { - match lifetime_ref.res { - hir::LifetimeName::Static => { + match lifetime_ref.kind { + hir::LifetimeKind::Static => { self.insert_lifetime(lifetime_ref, ResolvedArg::StaticLifetime) } - hir::LifetimeName::Param(param_def_id) => { + hir::LifetimeKind::Param(param_def_id) => { self.resolve_lifetime_ref(param_def_id, lifetime_ref) } // If we've already reported an error, just ignore `lifetime_ref`. - hir::LifetimeName::Error => {} + hir::LifetimeKind::Error => {} // Those will be resolved by typechecking. - hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Infer => {} + hir::LifetimeKind::ImplicitObjectLifetimeDefault | hir::LifetimeKind::Infer => {} } } @@ -1063,15 +1063,15 @@ fn object_lifetime_default(tcx: TyCtxt<'_>, param_def_id: LocalDefId) -> ObjectL for bound in bound.bounds { if let hir::GenericBound::Outlives(lifetime) = bound { - set.insert(lifetime.res); + set.insert(lifetime.kind); } } } match set { Set1::Empty => ObjectLifetimeDefault::Empty, - Set1::One(hir::LifetimeName::Static) => ObjectLifetimeDefault::Static, - Set1::One(hir::LifetimeName::Param(param_def_id)) => { + Set1::One(hir::LifetimeKind::Static) => ObjectLifetimeDefault::Static, + Set1::One(hir::LifetimeKind::Param(param_def_id)) => { ObjectLifetimeDefault::Param(param_def_id.to_def_id()) } _ => ObjectLifetimeDefault::Ambiguous, @@ -1241,7 +1241,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { // Fresh lifetimes in APIT used to be allowed in async fns and forbidden in // regular fns. if let Some(hir::PredicateOrigin::ImplTrait) = where_bound_origin - && let hir::LifetimeName::Param(param_id) = lifetime_ref.res + && let hir::LifetimeKind::Param(param_id) = lifetime_ref.kind && let Some(generics) = self.tcx.hir_get_generics(self.tcx.local_parent(param_id)) && let Some(param) = generics.params.iter().find(|p| p.def_id == param_id) @@ -2440,7 +2440,7 @@ fn is_late_bound_map( } fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) { - if let hir::LifetimeName::Param(def_id) = lifetime_ref.res { + if let hir::LifetimeKind::Param(def_id) = lifetime_ref.kind { self.regions.insert(def_id); } } @@ -2453,7 +2453,7 @@ fn is_late_bound_map( impl<'tcx> Visitor<'tcx> for AllCollector { fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) { - if let hir::LifetimeName::Param(def_id) = lifetime_ref.res { + if let hir::LifetimeKind::Param(def_id) = lifetime_ref.kind { self.regions.insert(def_id); } } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs index 2e39beed8ae3..88f745892048 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs @@ -415,7 +415,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { self.lower_lifetime(lifetime, RegionInferReason::ExplicitObjectLifetime) } else { let reason = - if let hir::LifetimeName::ImplicitObjectLifetimeDefault = lifetime.res { + if let hir::LifetimeKind::ImplicitObjectLifetimeDefault = lifetime.kind { if let hir::Node::Ty(hir::Ty { kind: hir::TyKind::Ref(parent_lifetime, _), .. diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 09db6eee2c9e..fbb57b8df6bb 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -578,8 +578,8 @@ impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor<'v> { match ty.kind { hir::TyKind::TraitObject(_, tagged_ptr) if let hir::Lifetime { - res: - hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Static, + kind: + hir::LifetimeKind::ImplicitObjectLifetimeDefault | hir::LifetimeKind::Static, .. } = tagged_ptr.pointer() => { diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs index 3559c660ee27..eaa06d8e8b0a 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs @@ -6,7 +6,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{Visitor, VisitorExt, walk_ty}; use rustc_hir::{ self as hir, AmbigArg, GenericBound, GenericParam, GenericParamKind, Item, ItemKind, Lifetime, - LifetimeName, LifetimeParamKind, MissingLifetimeKind, Node, TyKind, + LifetimeKind, LifetimeParamKind, MissingLifetimeKind, Node, TyKind, }; use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor}; use rustc_span::def_id::LocalDefId; @@ -165,7 +165,7 @@ pub fn suggest_new_region_bound( if let Some(span) = opaque.bounds.iter().find_map(|arg| match arg { GenericBound::Outlives(Lifetime { - res: LifetimeName::Static, ident, .. + kind: LifetimeKind::Static, ident, .. }) => Some(ident.span), _ => None, }) { @@ -253,7 +253,7 @@ pub fn suggest_new_region_bound( } } TyKind::TraitObject(_, lt) => { - if let LifetimeName::ImplicitObjectLifetimeDefault = lt.res { + if let LifetimeKind::ImplicitObjectLifetimeDefault = lt.kind { err.span_suggestion_verbose( fn_return.span.shrink_to_hi(), format!("{declare} the trait object {captures}, {explicit}",), @@ -414,7 +414,7 @@ pub struct HirTraitObjectVisitor<'a>(pub &'a mut Vec, pub DefId); impl<'a, 'tcx> Visitor<'tcx> for HirTraitObjectVisitor<'a> { fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx, AmbigArg>) { if let TyKind::TraitObject(poly_trait_refs, lifetime_ptr) = t.kind - && let Lifetime { res: LifetimeName::ImplicitObjectLifetimeDefault, .. } = + && let Lifetime { kind: LifetimeKind::ImplicitObjectLifetimeDefault, .. } = lifetime_ptr.pointer() { for ptr in poly_trait_refs { diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs index df3cce880dd4..1cf1ac5403f0 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -850,14 +850,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { add_lt_suggs: &mut Vec<(Span, String)>, ) -> String { struct LifetimeReplaceVisitor<'a> { - needle: hir::LifetimeName, + needle: hir::LifetimeKind, new_lt: &'a str, add_lt_suggs: &'a mut Vec<(Span, String)>, } impl<'hir> hir::intravisit::Visitor<'hir> for LifetimeReplaceVisitor<'_> { fn visit_lifetime(&mut self, lt: &'hir hir::Lifetime) { - if lt.res == self.needle { + if lt.kind == self.needle { self.add_lt_suggs.push(lt.suggestion(self.new_lt)); } } @@ -894,7 +894,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }; let mut visitor = LifetimeReplaceVisitor { - needle: hir::LifetimeName::Param(lifetime_def_id), + needle: hir::LifetimeKind::Param(lifetime_def_id), add_lt_suggs, new_lt: &new_lt, }; diff --git a/src/doc/rustc-dev-guide/src/ty.md b/src/doc/rustc-dev-guide/src/ty.md index b33d54035864..ce6cffec1adb 100644 --- a/src/doc/rustc-dev-guide/src/ty.md +++ b/src/doc/rustc-dev-guide/src/ty.md @@ -61,11 +61,11 @@ Here is a summary: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Describe the *syntax* of a type: what the user wrote (with some desugaring). | Describe the *semantics* of a type: the meaning of what the user wrote. | | Each `rustc_hir::Ty` has its own spans corresponding to the appropriate place in the program. | Doesn’t correspond to a single place in the user’s program. | -| `rustc_hir::Ty` has generics and lifetimes; however, some of those lifetimes are special markers like [`LifetimeName::Implicit`][implicit]. | `ty::Ty` has the full type, including generics and lifetimes, even if the user left them out | +| `rustc_hir::Ty` has generics and lifetimes; however, some of those lifetimes are special markers like [`LifetimeKind::Implicit`][implicit]. | `ty::Ty` has the full type, including generics and lifetimes, even if the user left them out | | `fn foo(x: u32) → u32 { }` - Two `rustc_hir::Ty` representing each usage of `u32`, each has its own `Span`s, and `rustc_hir::Ty` doesn’t tell us that both are the same type | `fn foo(x: u32) → u32 { }` - One `ty::Ty` for all instances of `u32` throughout the program, and `ty::Ty` tells us that both usages of `u32` mean the same type. | -| `fn foo(x: &u32) -> &u32)` - Two `rustc_hir::Ty` again. Lifetimes for the references show up in the `rustc_hir::Ty`s using a special marker, [`LifetimeName::Implicit`][implicit]. | `fn foo(x: &u32) -> &u32)`- A single `ty::Ty`. The `ty::Ty` has the hidden lifetime param. | +| `fn foo(x: &u32) -> &u32)` - Two `rustc_hir::Ty` again. Lifetimes for the references show up in the `rustc_hir::Ty`s using a special marker, [`LifetimeKind::Implicit`][implicit]. | `fn foo(x: &u32) -> &u32)`- A single `ty::Ty`. The `ty::Ty` has the hidden lifetime param. | -[implicit]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir/enum.LifetimeName.html#variant.Implicit +[implicit]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir/enum.LifetimeKind.html#variant.Implicit **Order** @@ -323,4 +323,4 @@ When looking at the debug output of `Ty` or simply talking about different types - Generic parameters: `{name}/#{index}` e.g. `T/#0`, where `index` corresponds to its position in the list of generic parameters - Inference variables: `?{id}` e.g. `?x`/`?0`, where `id` identifies the inference variable - Variables from binders: `^{binder}_{index}` e.g. `^0_x`/`^0_2`, where `binder` and `index` identify which variable from which binder is being referred to -- Placeholders: `!{id}` or `!{id}_{universe}` e.g. `!x`/`!0`/`!x_2`/`!0_2`, representing some unique type in the specified universe. The universe is often elided when it is `0` \ No newline at end of file +- Placeholders: `!{id}` or `!{id}_{universe}` e.g. `!x`/`!0`/`!x_2`/`!0_2`, representing some unique type in the specified universe. The universe is often elided when it is `0` diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs index 8d47c756fc53..dabef18b98a9 100644 --- a/src/tools/clippy/clippy_lints/src/lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs @@ -14,7 +14,7 @@ use rustc_hir::intravisit::{ }; use rustc_hir::{ AmbigArg, BareFnTy, BodyId, FnDecl, FnSig, GenericArg, GenericArgs, GenericBound, GenericParam, GenericParamKind, - Generics, HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, LifetimeParamKind, Node, + Generics, HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind, Lifetime, LifetimeKind, LifetimeParamKind, Node, PolyTraitRef, PredicateOrigin, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WhereBoundPredicate, WherePredicate, WherePredicateKind, lang_items, }; @@ -218,7 +218,7 @@ fn check_fn_inner<'tcx>( for bound in pred.bounds { let mut visitor = RefVisitor::new(cx); walk_param_bound(&mut visitor, bound); - if visitor.lts.iter().any(|lt| matches!(lt.res, LifetimeName::Param(_))) { + if visitor.lts.iter().any(|lt| matches!(lt.kind, LifetimeKind::Param(_))) { return; } if let GenericBound::Trait(ref trait_ref) = *bound { @@ -235,7 +235,7 @@ fn check_fn_inner<'tcx>( _ => None, }); for bound in lifetimes { - if bound.res != LifetimeName::Static && !bound.is_elided() { + if bound.kind != LifetimeKind::Static && !bound.is_elided() { return; } } @@ -421,8 +421,8 @@ fn named_lifetime_occurrences(lts: &[Lifetime]) -> Vec<(LocalDefId, usize)> { } fn named_lifetime(lt: &Lifetime) -> Option { - match lt.res { - LifetimeName::Param(id) if !lt.is_anonymous() => Some(id), + match lt.kind { + LifetimeKind::Param(id) if !lt.is_anonymous() => Some(id), _ => None, } } @@ -614,7 +614,7 @@ where // for lifetimes as parameters of generics fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) { - if let LifetimeName::Param(def_id) = lifetime.res + if let LifetimeKind::Param(def_id) = lifetime.kind && let Some(usages) = self.map.get_mut(&def_id) { usages.push(Usage { @@ -826,7 +826,7 @@ fn report_elidable_lifetimes( .iter() .map(|<| cx.tcx.def_span(lt)) .chain(usages.iter().filter_map(|usage| { - if let LifetimeName::Param(def_id) = usage.res + if let LifetimeKind::Param(def_id) = usage.kind && elidable_lts.contains(&def_id) { return Some(usage.ident.span); diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs index 50ef56db167c..901a1634ddc8 100644 --- a/src/tools/clippy/clippy_lints/src/ptr.rs +++ b/src/tools/clippy/clippy_lints/src/ptr.rs @@ -3,7 +3,7 @@ use clippy_utils::source::SpanRangeExt; use clippy_utils::sugg::Sugg; use clippy_utils::visitors::contains_unsafe_block; use clippy_utils::{get_expr_use_or_unification_node, is_lint_allowed, path_def_id, path_to_local, std_or_core}; -use hir::LifetimeName; +use hir::LifetimeKind; use rustc_abi::ExternAbi; use rustc_errors::{Applicability, MultiSpan}; use rustc_hir::hir_id::{HirId, HirIdMap}; @@ -432,7 +432,7 @@ fn check_fn_args<'cx, 'tcx: 'cx>( } None }) { - if let LifetimeName::Param(param_def_id) = lifetime.res + if let LifetimeKind::Param(param_def_id) = lifetime.kind && !lifetime.is_anonymous() && fn_sig .output() diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index b813cd361ed8..be295b59f609 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -8,7 +8,7 @@ use rustc_hir::MatchSource::TryDesugar; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{ AssocItemConstraint, BinOpKind, BindingMode, Block, BodyId, Closure, ConstArg, ConstArgKind, Expr, ExprField, - ExprKind, FnRetTy, GenericArg, GenericArgs, HirId, HirIdMap, InlineAsmOperand, LetExpr, Lifetime, LifetimeName, + ExprKind, FnRetTy, GenericArg, GenericArgs, HirId, HirIdMap, InlineAsmOperand, LetExpr, Lifetime, LifetimeKind, Pat, PatExpr, PatExprKind, PatField, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, StructTailExpr, TraitBoundModifiers, Ty, TyKind, TyPat, TyPatKind, }; @@ -483,7 +483,7 @@ impl HirEqInterExpr<'_, '_, '_> { } fn eq_lifetime(left: &Lifetime, right: &Lifetime) -> bool { - left.res == right.res + left.kind == right.kind } fn eq_pat_field(&mut self, left: &PatField<'_>, right: &PatField<'_>) -> bool { @@ -1245,8 +1245,8 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { pub fn hash_lifetime(&mut self, lifetime: &Lifetime) { lifetime.ident.name.hash(&mut self.s); - std::mem::discriminant(&lifetime.res).hash(&mut self.s); - if let LifetimeName::Param(param_id) = lifetime.res { + std::mem::discriminant(&lifetime.kind).hash(&mut self.s); + if let LifetimeKind::Param(param_id) = lifetime.kind { param_id.hash(&mut self.s); } } From c4d35635545ba9fb6d5f4a1652b4520c7da3fca0 Mon Sep 17 00:00:00 2001 From: Bastian Kersting Date: Wed, 16 Apr 2025 00:14:10 +0200 Subject: [PATCH 507/606] Also remove the no_sanitize feature for std --- library/std/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 5c381181218d..3a52b7790376 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -312,7 +312,6 @@ #![feature(needs_panic_runtime)] #![feature(negative_impls)] #![feature(never_type)] -#![feature(no_sanitize)] #![feature(optimize_attribute)] #![feature(prelude_import)] #![feature(rustc_attrs)] From ea1b230170c36ddf95cb24a8542316df9f786e5a Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 15 Apr 2025 15:20:27 -0700 Subject: [PATCH 508/606] Update Cargo.lock for rustbook --- src/tools/rustbook/Cargo.lock | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/tools/rustbook/Cargo.lock b/src/tools/rustbook/Cargo.lock index e0939afc09bb..c14372dd6aec 100644 --- a/src/tools/rustbook/Cargo.lock +++ b/src/tools/rustbook/Cargo.lock @@ -951,6 +951,7 @@ dependencies = [ "once_cell", "pathdiff", "pulldown-cmark 0.10.3", + "railroad", "regex", "semver", "serde_json", @@ -1300,6 +1301,15 @@ version = "5.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" +[[package]] +name = "railroad" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ecedffc46c1b2cb04f4b80e094eae6b3f3f470a9635f1f396dd5206428f6b58" +dependencies = [ + "unicode-width", +] + [[package]] name = "rand" version = "0.8.5" From 766cd3a58320f2ec9e30573f39e377513f1a4443 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 16 Apr 2025 08:35:34 +1000 Subject: [PATCH 509/606] Remove support for `#[rustc_mir(borrowck_graphviz_format="gen_kill")]`. Because it's equivalent to `#[rustc_mir(borrowck_graphviz_format)]`. It used to be distinct, but the distinction was removed in https://github.com/rust-lang/rust/pull/76044/commits/3233fb18a891363a2da36ce69ca16fbb219c96be. --- compiler/rustc_mir_dataflow/src/framework/graphviz.rs | 2 +- compiler/rustc_span/src/symbol.rs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs index 448fad2dc3ec..c436b8c0fb01 100644 --- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs +++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs @@ -122,7 +122,7 @@ impl RustcMirAttrs { }) } else if attr.has_name(sym::borrowck_graphviz_format) { Self::set_field(&mut ret.formatter, tcx, &attr, |s| match s { - sym::gen_kill | sym::two_phase => Ok(s), + sym::two_phase => Ok(s), _ => { tcx.dcx().emit_err(UnknownFormatter { span: attr.span() }); Err(()) diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index d1f3eb16e4e4..2af567f2ec50 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1068,7 +1068,6 @@ symbols! { ge, gen_blocks, gen_future, - gen_kill, generator_clone, generators, generic_arg_infer, From 62882f355e50f9af3ddb84661dfad0559848a3f5 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 16 Apr 2025 08:57:15 +1000 Subject: [PATCH 510/606] Improve `borrowck_graphviz_*` documentation. In particular, `borrowck_graphviz_preflow` no longer exists. --- src/doc/rustc-dev-guide/src/compiler-debugging.md | 3 ++- tests/ui/mir-dataflow/README.md | 9 --------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/compiler-debugging.md b/src/doc/rustc-dev-guide/src/compiler-debugging.md index 47f397620222..102e20207792 100644 --- a/src/doc/rustc-dev-guide/src/compiler-debugging.md +++ b/src/doc/rustc-dev-guide/src/compiler-debugging.md @@ -301,7 +301,8 @@ Right below you can find elaborate explainers on a selected few. Some compiler options for debugging specific features yield graphviz graphs - e.g. the `#[rustc_mir(borrowck_graphviz_postflow="suffix.dot")]` attribute -dumps various borrow-checker dataflow graphs. +on a function dumps various borrow-checker dataflow graphs in conjunction with +`-Zdump-mir-dataflow`. These all produce `.dot` files. To view these files, install graphviz (e.g. `apt-get install graphviz`) and then run the following commands: diff --git a/tests/ui/mir-dataflow/README.md b/tests/ui/mir-dataflow/README.md index a3ab14b23c7d..886020226d03 100644 --- a/tests/ui/mir-dataflow/README.md +++ b/tests/ui/mir-dataflow/README.md @@ -42,12 +42,3 @@ each generated output path. on *entry* to each block, as well as the gen- and kill-sets that were so-called "transfer functions" summarizing the effect of each basic block. - - * (In addition to the `borrowck_graphviz_postflow` attribute-key - noted above, there is also `borrowck_graphviz_preflow`; it has the - same interface and generates the same set of files, but it renders - the dataflow state after building the gen- and kill-sets but - *before* running the dataflow analysis itself, so each entry-set is - just the initial default state for that dataflow analysis. This is - less useful for understanding the error message output in these - tests.) From 6999305926b4199d6a33ae4f82002e72115223a8 Mon Sep 17 00:00:00 2001 From: blyxyas Date: Tue, 15 Apr 2025 19:01:35 +0200 Subject: [PATCH 511/606] Make CodeStat's type sizes a public field --- compiler/rustc_session/src/code_stats.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_session/src/code_stats.rs b/compiler/rustc_session/src/code_stats.rs index b4597ae2515d..6b18d450e9e5 100644 --- a/compiler/rustc_session/src/code_stats.rs +++ b/compiler/rustc_session/src/code_stats.rs @@ -72,7 +72,7 @@ pub struct TypeSizeInfo { #[derive(Default)] pub struct CodeStats { - type_sizes: Lock>, + pub type_sizes: Lock>, } impl CodeStats { From b084603c631cf4cea540a35aca0ad7b2d8599ef2 Mon Sep 17 00:00:00 2001 From: Tsukasa OI Date: Sun, 6 Apr 2025 03:36:45 +0000 Subject: [PATCH 512/606] rustc_target: RISC-V: feature addition batch 2 This commit adds unprivileged ratified extensions that are either dicoverable from the `riscv_hwprobe` syscall of the Linux kernel (as of version 6.14) plus 1 minus 3 extensions. Plus 1: * "B" This is a combination of "Zba", "Zbb" and "Zbs". Note: Although not required by the RISC-V specification, it is convenient to imply "B" from its three members (will be implemented in LLVM 21/22) but this is not yet implemented in Rust due to current implication handling. It still implies three members *from* "B". Minus 2: * "Zcf" (target_arch = "riscv32" only) This is the compression instruction subset corresponding "F". This is implied from RV32 + "C" + "F" but this complex handling is not yet supported by Rust's feature handling. * "Zcd" This is the compression instruction subset corresponding "D". This is implied from "C" + "D" but this complex handling is not yet supported by Rust's feature handling. * "Supm" Unlike regular RISC-V extensions, "Supm" and "Sspm" extensions do not provide any specific architectural features / constraints but requires *some* mechanisms to control pointer masking for the current mode. For instance, reported existence of the "Supm" extension in Linux means that `prctl` system call to control pointer masking is available and there are alternative ways to detect the existence. Notes: * Because this commit adds the "Zca" extension (an integer subset of the "C" extension), the "C" extension is modified to imply "Zca". --- compiler/rustc_target/src/target_features.rs | 12 +++++++++++- tests/ui/check-cfg/target_feature.stderr | 10 ++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index b4ec1879fed5..aeace6a40c72 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -491,7 +491,8 @@ const MIPS_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ static RISCV_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-start ("a", Stable, &["zaamo", "zalrsc"]), - ("c", Stable, &[]), + ("b", Unstable(sym::riscv_target_feature), &["zba", "zbb", "zbs"]), + ("c", Stable, &["zca"]), ("d", Unstable(sym::riscv_target_feature), &["f"]), ("e", Unstable(sym::riscv_target_feature), &[]), ("f", Unstable(sym::riscv_target_feature), &["zicsr"]), @@ -520,17 +521,25 @@ static RISCV_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("zbkc", Stable, &[]), ("zbkx", Stable, &[]), ("zbs", Stable, &[]), + ("zca", Unstable(sym::riscv_target_feature), &[]), + ("zcb", Unstable(sym::riscv_target_feature), &["zca"]), + ("zcmop", Unstable(sym::riscv_target_feature), &["zca"]), ("zdinx", Unstable(sym::riscv_target_feature), &["zfinx"]), + ("zfa", Unstable(sym::riscv_target_feature), &["f"]), ("zfh", Unstable(sym::riscv_target_feature), &["zfhmin"]), ("zfhmin", Unstable(sym::riscv_target_feature), &["f"]), ("zfinx", Unstable(sym::riscv_target_feature), &["zicsr"]), ("zhinx", Unstable(sym::riscv_target_feature), &["zhinxmin"]), ("zhinxmin", Unstable(sym::riscv_target_feature), &["zfinx"]), + ("zicboz", Unstable(sym::riscv_target_feature), &[]), ("zicntr", Unstable(sym::riscv_target_feature), &["zicsr"]), + ("zicond", Unstable(sym::riscv_target_feature), &[]), ("zicsr", Unstable(sym::riscv_target_feature), &[]), ("zifencei", Unstable(sym::riscv_target_feature), &[]), + ("zihintntl", Unstable(sym::riscv_target_feature), &[]), ("zihintpause", Unstable(sym::riscv_target_feature), &[]), ("zihpm", Unstable(sym::riscv_target_feature), &["zicsr"]), + ("zimop", Unstable(sym::riscv_target_feature), &[]), ("zk", Stable, &["zkn", "zkr", "zkt"]), ("zkn", Stable, &["zbkb", "zbkc", "zbkx", "zkne", "zknd", "zknh"]), ("zknd", Stable, &[]), @@ -541,6 +550,7 @@ static RISCV_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("zksed", Stable, &[]), ("zksh", Stable, &[]), ("zkt", Stable, &[]), + ("ztso", Unstable(sym::riscv_target_feature), &[]), ("zvbb", Unstable(sym::riscv_target_feature), &["zvkb"]), ("zvbc", Unstable(sym::riscv_target_feature), &["zve64x"]), ("zve32f", Unstable(sym::riscv_target_feature), &["zve32x", "f"]), diff --git a/tests/ui/check-cfg/target_feature.stderr b/tests/ui/check-cfg/target_feature.stderr index aa5fd09c0c7b..4f7b8345e86a 100644 --- a/tests/ui/check-cfg/target_feature.stderr +++ b/tests/ui/check-cfg/target_feature.stderr @@ -49,6 +49,7 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE"); `avxvnni` `avxvnniint16` `avxvnniint8` +`b` `backchain` `bf16` `bmi1` @@ -318,17 +319,25 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE"); `zbkc` `zbkx` `zbs` +`zca` +`zcb` +`zcmop` `zdinx` +`zfa` `zfh` `zfhmin` `zfinx` `zhinx` `zhinxmin` +`zicboz` `zicntr` +`zicond` `zicsr` `zifencei` +`zihintntl` `zihintpause` `zihpm` +`zimop` `zk` `zkn` `zknd` @@ -339,6 +348,7 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE"); `zksed` `zksh` `zkt` +`ztso` `zvbb` `zvbc` `zve32f` From 52392ec9e1ebc5bf794583e2b2b146367d36b663 Mon Sep 17 00:00:00 2001 From: Tsukasa OI Date: Sun, 6 Apr 2025 04:21:01 +0000 Subject: [PATCH 513/606] rustc_target: Use "B" shorthand on the RISC-V Android target The "B" extension is ratified as a combination of three extensions: "Zba", "Zbb" and "Zbs". To maximize discoverability of the RISC-V target features, this commit makes use of the "B" extension instead of its three members. This way, `#[cfg(target_feature = "b")]` can also be used instead of: `#[cfg(all(target_feature = "zba", target_feature = "zbb", target_feature = "zbs"))]` --- compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs b/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs index 9f02ed4bcbe9..b9176c939f80 100644 --- a/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs +++ b/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs @@ -19,7 +19,7 @@ pub(crate) fn target() -> Target { options: TargetOptions { code_model: Some(CodeModel::Medium), cpu: "generic-rv64".into(), - features: "+m,+a,+f,+d,+c,+zicsr,+zifencei,+zba,+zbb,+zbs,+v".into(), + features: "+m,+a,+f,+d,+c,+b,+v,+zicsr,+zifencei".into(), llvm_abiname: "lp64d".into(), supported_sanitizers: SanitizerSet::ADDRESS, max_atomic_width: Some(64), From 8c50f95cf088c6ccf882a152bd46c090efa3a1c7 Mon Sep 17 00:00:00 2001 From: Will Glynn Date: Fri, 4 Apr 2025 17:46:35 -0500 Subject: [PATCH 514/606] rustdoc: Output target feature information `#[target_feature]` attributes refer to a target-specific list of features. Enabling certain features can imply enabling other features. Certain features are always enabled on certain targets, since they are required by the target's ABI. Features can also be enabled indirectly based on other compiler flags. Feature information is ultimately known to `rustc`. Rather than force external tools to track it -- which may be wildly impractical due to `-C target-cpu` -- have `rustdoc` output `rustc`'s feature data. --- src/librustdoc/json/mod.rs | 60 +++++++++++++++++++ src/rustdoc-json-types/lib.rs | 58 +++++++++++++++++- src/tools/compiletest/src/directive-list.rs | 3 + src/tools/jsondocck/src/main.rs | 2 +- src/tools/jsondoclint/src/validator/tests.rs | 4 ++ .../targets/aarch64_apple_darwin.rs | 14 +++++ .../aarch64_reflects_compiler_options.rs | 10 ++++ .../targets/aarch64_unknown_linux_gnu.rs | 14 +++++ .../targets/i686_pc_windows_msvc.rs | 14 +++++ .../targets/i686_unknown_linux_gnu.rs | 14 +++++ .../targets/x86_64_apple_darwin.rs | 14 +++++ .../targets/x86_64_pc_windows_gnu.rs | 14 +++++ .../targets/x86_64_pc_windows_msvc.rs | 14 +++++ .../x86_64_reflects_compiler_options.rs | 10 ++++ .../targets/x86_64_unknown_linux_gnu.rs | 14 +++++ 15 files changed, 257 insertions(+), 2 deletions(-) create mode 100644 tests/rustdoc-json/targets/aarch64_apple_darwin.rs create mode 100644 tests/rustdoc-json/targets/aarch64_reflects_compiler_options.rs create mode 100644 tests/rustdoc-json/targets/aarch64_unknown_linux_gnu.rs create mode 100644 tests/rustdoc-json/targets/i686_pc_windows_msvc.rs create mode 100644 tests/rustdoc-json/targets/i686_unknown_linux_gnu.rs create mode 100644 tests/rustdoc-json/targets/x86_64_apple_darwin.rs create mode 100644 tests/rustdoc-json/targets/x86_64_pc_windows_gnu.rs create mode 100644 tests/rustdoc-json/targets/x86_64_pc_windows_msvc.rs create mode 100644 tests/rustdoc-json/targets/x86_64_reflects_compiler_options.rs create mode 100644 tests/rustdoc-json/targets/x86_64_unknown_linux_gnu.rs diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index ba27eed7c113..131a12ce228f 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -14,6 +14,7 @@ use std::io::{BufWriter, Write, stdout}; use std::path::PathBuf; use std::rc::Rc; +use rustc_data_structures::fx::FxHashSet; use rustc_hir::def_id::{DefId, DefIdSet}; use rustc_middle::ty::TyCtxt; use rustc_session::Session; @@ -123,6 +124,58 @@ impl<'tcx> JsonRenderer<'tcx> { } } +fn target(sess: &rustc_session::Session) -> types::Target { + // Build a set of which features are enabled on this target + let globally_enabled_features: FxHashSet<&str> = + sess.unstable_target_features.iter().map(|name| name.as_str()).collect(); + + // Build a map of target feature stability by feature name + use rustc_target::target_features::Stability; + let feature_stability: FxHashMap<&str, Stability> = sess + .target + .rust_target_features() + .into_iter() + .copied() + .map(|(name, stability, _)| (name, stability)) + .collect(); + + types::Target { + triple: sess.opts.target_triple.tuple().into(), + target_features: sess + .target + .rust_target_features() + .into_iter() + .copied() + .filter(|(_, stability, _)| { + // Describe only target features which the user can toggle + stability.toggle_allowed().is_ok() + }) + .map(|(name, stability, implied_features)| { + types::TargetFeature { + name: name.into(), + unstable_feature_gate: match stability { + Stability::Unstable(feature_gate) => Some(feature_gate.as_str().into()), + _ => None, + }, + implies_features: implied_features + .into_iter() + .copied() + .filter(|name| { + // Imply only target features which the user can toggle + feature_stability + .get(name) + .map(|stability| stability.toggle_allowed().is_ok()) + .unwrap_or(false) + }) + .map(String::from) + .collect(), + globally_enabled: globally_enabled_features.contains(name), + } + }) + .collect(), + } +} + impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { fn descr() -> &'static str { "json" @@ -248,6 +301,12 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { let e = ExternalCrate { crate_num: LOCAL_CRATE }; let index = (*self.index).clone().into_inner(); + // Note that tcx.rust_target_features is inappropriate here because rustdoc tries to run for + // multiple targets: https://github.com/rust-lang/rust/pull/137632 + // + // We want to describe a single target, so pass tcx.sess rather than tcx. + let target = target(self.tcx.sess); + debug!("Constructing Output"); let output_crate = types::Crate { root: self.id_from_item_default(e.def_id().into()), @@ -288,6 +347,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { ) }) .collect(), + target, format_version: types::FORMAT_VERSION, }; if let Some(ref out_dir) = self.out_dir { diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index 137fe4c4c354..7247950545ad 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -30,7 +30,7 @@ pub type FxHashMap = HashMap; // re-export for use in src/librustdoc /// This integer is incremented with every breaking change to the API, /// and is returned along with the JSON blob as [`Crate::format_version`]. /// Consuming code should assert that this value matches the format version(s) that it supports. -pub const FORMAT_VERSION: u32 = 43; +pub const FORMAT_VERSION: u32 = 44; /// The root of the emitted JSON blob. /// @@ -52,11 +52,67 @@ pub struct Crate { pub paths: HashMap, /// Maps `crate_id` of items to a crate name and html_root_url if it exists. pub external_crates: HashMap, + /// Information about the target for which this documentation was generated + pub target: Target, /// A single version number to be used in the future when making backwards incompatible changes /// to the JSON output. pub format_version: u32, } +/// Information about a target +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct Target { + /// The target triple for which this documentation was generated + pub triple: String, + /// A list of features valid for use in `#[target_feature]` attributes + /// for the target where this rustdoc JSON was generated. + pub target_features: Vec, +} + +/// Information about a target feature. +/// +/// Rust target features are used to influence code generation, especially around selecting +/// instructions which are not universally supported by the target architecture. +/// +/// Target features are commonly enabled by the [`#[target_feature]` attribute][1] to influence code +/// generation for a particular function, and less commonly enabled by compiler options like +/// `-Ctarget-feature` or `-Ctarget-cpu`. Targets themselves automatically enable certain target +/// features by default, for example because the target's ABI specification requires saving specific +/// registers which only exist in an architectural extension. +/// +/// Target features can imply other target features: for example, x86-64 `avx2` implies `avx`, and +/// aarch64 `sve2` implies `sve`, since both of these architectural extensions depend on their +/// predecessors. +/// +/// Target features can be probed at compile time by [`#[cfg(target_feature)]`][2] or `cfg!(…)` +/// conditional compilation to determine whether a target feature is enabled in a particular +/// context. +/// +/// [1]: https://doc.rust-lang.org/stable/reference/attributes/codegen.html#the-target_feature-attribute +/// [2]: https://doc.rust-lang.org/reference/conditional-compilation.html#target_feature +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct TargetFeature { + /// The name of this target feature. + pub name: String, + /// Other target features which are implied by this target feature, if any. + pub implies_features: Vec, + /// If this target feature is unstable, the name of the associated language feature gate. + pub unstable_feature_gate: Option, + /// Whether this feature is globally enabled for this compilation session. + /// + /// Target features can be globally enabled implicitly as a result of the target's definition. + /// For example, x86-64 hardware floating point ABIs require saving x87 and SSE2 registers, + /// which in turn requires globally enabling the `x87` and `sse2` target features so that the + /// generated machine code conforms to the target's ABI. + /// + /// Target features can also be globally enabled explicitly as a result of compiler flags like + /// [`-Ctarget-feature`][1] or [`-Ctarget-cpu`][2]. + /// + /// [1]: https://doc.rust-lang.org/beta/rustc/codegen-options/index.html#target-feature + /// [2]: https://doc.rust-lang.org/beta/rustc/codegen-options/index.html#target-cpu + pub globally_enabled: bool, +} + /// Metadata of a crate, either the same crate on which `rustdoc` was invoked, or its dependency. #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct ExternalCrate { diff --git a/src/tools/compiletest/src/directive-list.rs b/src/tools/compiletest/src/directive-list.rs index 44d9c0330f76..f8b92f11bdee 100644 --- a/src/tools/compiletest/src/directive-list.rs +++ b/src/tools/compiletest/src/directive-list.rs @@ -176,6 +176,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "only-32bit", "only-64bit", "only-aarch64", + "only-aarch64-apple-darwin", "only-aarch64-unknown-linux-gnu", "only-apple", "only-arm", @@ -189,6 +190,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "only-gnu", "only-i686-pc-windows-gnu", "only-i686-pc-windows-msvc", + "only-i686-unknown-linux-gnu", "only-ios", "only-linux", "only-loongarch64", @@ -220,6 +222,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "only-windows-msvc", "only-x86", "only-x86_64", + "only-x86_64-apple-darwin", "only-x86_64-fortanix-unknown-sgx", "only-x86_64-pc-windows-gnu", "only-x86_64-pc-windows-msvc", diff --git a/src/tools/jsondocck/src/main.rs b/src/tools/jsondocck/src/main.rs index 54249fbd9ae7..79e419884c68 100644 --- a/src/tools/jsondocck/src/main.rs +++ b/src/tools/jsondocck/src/main.rs @@ -156,7 +156,7 @@ static LINE_PATTERN: LazyLock = LazyLock::new(|| { r#" //@\s+ (?P!?) - (?P[A-Za-z]+(?:-[A-Za-z]+)*) + (?P[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*) (?P.*)$ "#, ) diff --git a/src/tools/jsondoclint/src/validator/tests.rs b/src/tools/jsondoclint/src/validator/tests.rs index 28deb7e7ceef..dd0b4ac5601a 100644 --- a/src/tools/jsondoclint/src/validator/tests.rs +++ b/src/tools/jsondoclint/src/validator/tests.rs @@ -42,6 +42,7 @@ fn errors_on_missing_links() { )]), paths: FxHashMap::default(), external_crates: FxHashMap::default(), + target: rustdoc_json_types::Target { triple: "".to_string(), target_features: vec![] }, format_version: rustdoc_json_types::FORMAT_VERSION, }; @@ -112,6 +113,7 @@ fn errors_on_local_in_paths_and_not_index() { }, )]), external_crates: FxHashMap::default(), + target: rustdoc_json_types::Target { triple: "".to_string(), target_features: vec![] }, format_version: rustdoc_json_types::FORMAT_VERSION, }; @@ -216,6 +218,7 @@ fn errors_on_missing_path() { ItemSummary { crate_id: 0, path: vec!["foo".to_owned()], kind: ItemKind::Module }, )]), external_crates: FxHashMap::default(), + target: rustdoc_json_types::Target { triple: "".to_string(), target_features: vec![] }, format_version: rustdoc_json_types::FORMAT_VERSION, }; @@ -259,6 +262,7 @@ fn checks_local_crate_id_is_correct() { )]), paths: FxHashMap::default(), external_crates: FxHashMap::default(), + target: rustdoc_json_types::Target { triple: "".to_string(), target_features: vec![] }, format_version: FORMAT_VERSION, }; check(&krate, &[]); diff --git a/tests/rustdoc-json/targets/aarch64_apple_darwin.rs b/tests/rustdoc-json/targets/aarch64_apple_darwin.rs new file mode 100644 index 000000000000..c6ae5517d476 --- /dev/null +++ b/tests/rustdoc-json/targets/aarch64_apple_darwin.rs @@ -0,0 +1,14 @@ +//@ only-aarch64-apple-darwin + +//@ is "$.target.triple" \"aarch64-apple-darwin\" +//@ is "$.target.target_features[?(@.name=='vh')].globally_enabled" true +//@ is "$.target.target_features[?(@.name=='sve')].globally_enabled" false +//@ has "$.target.target_features[?(@.name=='sve2')].implies_features" '["sve"]' +//@ is "$.target.target_features[?(@.name=='sve2')].unstable_feature_gate" null + +// If this breaks due to stabilization, check rustc_target::target_features for a replacement +//@ is "$.target.target_features[?(@.name=='cssc')].unstable_feature_gate" '"aarch64_unstable_target_feature"' +//@ is "$.target.target_features[?(@.name=='v9a')].unstable_feature_gate" '"aarch64_ver_target_feature"' + +// Ensure we don't look like x86-64 +//@ !has "$.target.target_features[?(@.name=='avx2')]" diff --git a/tests/rustdoc-json/targets/aarch64_reflects_compiler_options.rs b/tests/rustdoc-json/targets/aarch64_reflects_compiler_options.rs new file mode 100644 index 000000000000..f91221eb23c6 --- /dev/null +++ b/tests/rustdoc-json/targets/aarch64_reflects_compiler_options.rs @@ -0,0 +1,10 @@ +//@ only-aarch64 + +// If we enable SVE Bit Permute, we should see that it is enabled +//@ compile-flags: -Ctarget-feature=+sve2-bitperm +//@ is "$.target.target_features[?(@.name=='sve2-bitperm')].globally_enabled" true + +// As well as its dependency chain +//@ is "$.target.target_features[?(@.name=='sve2')].globally_enabled" true +//@ is "$.target.target_features[?(@.name=='sve')].globally_enabled" true +//@ is "$.target.target_features[?(@.name=='neon')].globally_enabled" true diff --git a/tests/rustdoc-json/targets/aarch64_unknown_linux_gnu.rs b/tests/rustdoc-json/targets/aarch64_unknown_linux_gnu.rs new file mode 100644 index 000000000000..9139b00a1285 --- /dev/null +++ b/tests/rustdoc-json/targets/aarch64_unknown_linux_gnu.rs @@ -0,0 +1,14 @@ +//@ only-aarch64-unknown-linux-gnu + +//@ is "$.target.triple" \"aarch64-unknown-linux-gnu\" +//@ is "$.target.target_features[?(@.name=='neon')].globally_enabled" true +//@ is "$.target.target_features[?(@.name=='sve')].globally_enabled" false +//@ has "$.target.target_features[?(@.name=='sve2')].implies_features" '["sve"]' +//@ is "$.target.target_features[?(@.name=='sve2')].unstable_feature_gate" null + +// If this breaks due to stabilization, check rustc_target::target_features for a replacement +//@ is "$.target.target_features[?(@.name=='cssc')].unstable_feature_gate" '"aarch64_unstable_target_feature"' +//@ is "$.target.target_features[?(@.name=='v9a')].unstable_feature_gate" '"aarch64_ver_target_feature"' + +// Ensure we don't look like x86-64 +//@ !has "$.target.target_features[?(@.name=='avx2')]" diff --git a/tests/rustdoc-json/targets/i686_pc_windows_msvc.rs b/tests/rustdoc-json/targets/i686_pc_windows_msvc.rs new file mode 100644 index 000000000000..088c741d1138 --- /dev/null +++ b/tests/rustdoc-json/targets/i686_pc_windows_msvc.rs @@ -0,0 +1,14 @@ +//@ only-i686-pc-windows-msvc + +//@ is "$.target.triple" \"i686-pc-windows-msvc\" +//@ is "$.target.target_features[?(@.name=='sse2')].globally_enabled" true +//@ is "$.target.target_features[?(@.name=='avx2')].globally_enabled" false +//@ has "$.target.target_features[?(@.name=='avx2')].implies_features" '["avx"]' +//@ is "$.target.target_features[?(@.name=='avx2')].unstable_feature_gate" null + +// If this breaks due to stabilization, check rustc_target::target_features for a replacement +//@ is "$.target.target_features[?(@.name=='amx-tile')].unstable_feature_gate" '"x86_amx_intrinsics"' +//@ is "$.target.target_features[?(@.name=='x87')].unstable_feature_gate" '"x87_target_feature"' + +// Ensure we don't look like aarch64 +//@ !has "$.target.target_features[?(@.name=='sve2')]" diff --git a/tests/rustdoc-json/targets/i686_unknown_linux_gnu.rs b/tests/rustdoc-json/targets/i686_unknown_linux_gnu.rs new file mode 100644 index 000000000000..03788b000f12 --- /dev/null +++ b/tests/rustdoc-json/targets/i686_unknown_linux_gnu.rs @@ -0,0 +1,14 @@ +//@ only-i686-unknown-linux-gnu + +//@ is "$.target.triple" \"i686-unknown-linux-gnu\" +//@ is "$.target.target_features[?(@.name=='sse2')].globally_enabled" true +//@ is "$.target.target_features[?(@.name=='avx2')].globally_enabled" false +//@ has "$.target.target_features[?(@.name=='avx2')].implies_features" '["avx"]' +//@ is "$.target.target_features[?(@.name=='avx2')].unstable_feature_gate" null + +// If this breaks due to stabilization, check rustc_target::target_features for a replacement +//@ is "$.target.target_features[?(@.name=='amx-tile')].unstable_feature_gate" '"x86_amx_intrinsics"' +//@ is "$.target.target_features[?(@.name=='x87')].unstable_feature_gate" '"x87_target_feature"' + +// Ensure we don't look like aarch64 +//@ !has "$.target.target_features[?(@.name=='sve2')]" diff --git a/tests/rustdoc-json/targets/x86_64_apple_darwin.rs b/tests/rustdoc-json/targets/x86_64_apple_darwin.rs new file mode 100644 index 000000000000..a46f9138e867 --- /dev/null +++ b/tests/rustdoc-json/targets/x86_64_apple_darwin.rs @@ -0,0 +1,14 @@ +//@ only-x86_64-apple-darwin + +//@ is "$.target.triple" \"x86_64-apple-darwin\" +//@ is "$.target.target_features[?(@.name=='sse2')].globally_enabled" true +//@ is "$.target.target_features[?(@.name=='avx2')].globally_enabled" false +//@ has "$.target.target_features[?(@.name=='avx2')].implies_features" '["avx"]' +//@ is "$.target.target_features[?(@.name=='avx2')].unstable_feature_gate" null + +// If this breaks due to stabilization, check rustc_target::target_features for a replacement +//@ is "$.target.target_features[?(@.name=='amx-tile')].unstable_feature_gate" '"x86_amx_intrinsics"' +//@ is "$.target.target_features[?(@.name=='x87')].unstable_feature_gate" '"x87_target_feature"' + +// Ensure we don't look like aarch64 +//@ !has "$.target.target_features[?(@.name=='sve2')]" diff --git a/tests/rustdoc-json/targets/x86_64_pc_windows_gnu.rs b/tests/rustdoc-json/targets/x86_64_pc_windows_gnu.rs new file mode 100644 index 000000000000..7da12eb4d580 --- /dev/null +++ b/tests/rustdoc-json/targets/x86_64_pc_windows_gnu.rs @@ -0,0 +1,14 @@ +//@ only-x86_64-pc-windows-gnu + +//@ is "$.target.triple" \"x86_64-pc-windows-gnu\" +//@ is "$.target.target_features[?(@.name=='sse2')].globally_enabled" true +//@ is "$.target.target_features[?(@.name=='avx2')].globally_enabled" false +//@ has "$.target.target_features[?(@.name=='avx2')].implies_features" '["avx"]' +//@ is "$.target.target_features[?(@.name=='avx2')].unstable_feature_gate" null + +// If this breaks due to stabilization, check rustc_target::target_features for a replacement +//@ is "$.target.target_features[?(@.name=='amx-tile')].unstable_feature_gate" '"x86_amx_intrinsics"' +//@ is "$.target.target_features[?(@.name=='x87')].unstable_feature_gate" '"x87_target_feature"' + +// Ensure we don't look like aarch64 +//@ !has "$.target.target_features[?(@.name=='sve2')]" diff --git a/tests/rustdoc-json/targets/x86_64_pc_windows_msvc.rs b/tests/rustdoc-json/targets/x86_64_pc_windows_msvc.rs new file mode 100644 index 000000000000..d55f5776e85e --- /dev/null +++ b/tests/rustdoc-json/targets/x86_64_pc_windows_msvc.rs @@ -0,0 +1,14 @@ +//@ only-x86_64-pc-windows-msvc + +//@ is "$.target.triple" \"x86_64-pc-windows-msvc\" +//@ is "$.target.target_features[?(@.name=='sse2')].globally_enabled" true +//@ is "$.target.target_features[?(@.name=='avx2')].globally_enabled" false +//@ has "$.target.target_features[?(@.name=='avx2')].implies_features" '["avx"]' +//@ is "$.target.target_features[?(@.name=='avx2')].unstable_feature_gate" null + +// If this breaks due to stabilization, check rustc_target::target_features for a replacement +//@ is "$.target.target_features[?(@.name=='amx-tile')].unstable_feature_gate" '"x86_amx_intrinsics"' +//@ is "$.target.target_features[?(@.name=='x87')].unstable_feature_gate" '"x87_target_feature"' + +// Ensure we don't look like aarch64 +//@ !has "$.target.target_features[?(@.name=='sve2')]" diff --git a/tests/rustdoc-json/targets/x86_64_reflects_compiler_options.rs b/tests/rustdoc-json/targets/x86_64_reflects_compiler_options.rs new file mode 100644 index 000000000000..ba029b099963 --- /dev/null +++ b/tests/rustdoc-json/targets/x86_64_reflects_compiler_options.rs @@ -0,0 +1,10 @@ +//@ only-x86_64 + +// If we enable AVX2, we should see that it is enabled +//@ compile-flags: -Ctarget-feature=+avx2 +//@ is "$.target.target_features[?(@.name=='avx2')].globally_enabled" true + +// As well as its dependency chain +//@ is "$.target.target_features[?(@.name=='avx')].globally_enabled" true +//@ is "$.target.target_features[?(@.name=='sse4.2')].globally_enabled" true +//@ is "$.target.target_features[?(@.name=='sse4.1')].globally_enabled" true diff --git a/tests/rustdoc-json/targets/x86_64_unknown_linux_gnu.rs b/tests/rustdoc-json/targets/x86_64_unknown_linux_gnu.rs new file mode 100644 index 000000000000..3372fe7eb9dd --- /dev/null +++ b/tests/rustdoc-json/targets/x86_64_unknown_linux_gnu.rs @@ -0,0 +1,14 @@ +//@ only-x86_64-unknown-linux-gnu + +//@ is "$.target.triple" \"x86_64-unknown-linux-gnu\" +//@ is "$.target.target_features[?(@.name=='sse2')].globally_enabled" true +//@ is "$.target.target_features[?(@.name=='avx2')].globally_enabled" false +//@ has "$.target.target_features[?(@.name=='avx2')].implies_features" '["avx"]' +//@ is "$.target.target_features[?(@.name=='avx2')].unstable_feature_gate" null + +// If this breaks due to stabilization, check rustc_target::target_features for a replacement +//@ is "$.target.target_features[?(@.name=='amx-tile')].unstable_feature_gate" '"x86_amx_intrinsics"' +//@ is "$.target.target_features[?(@.name=='x87')].unstable_feature_gate" '"x87_target_feature"' + +// Ensure we don't look like aarch64 +//@ !has "$.target.target_features[?(@.name=='sve2')]" From 9dbd2bb85cd0de44b4cec80c17b5c767e960553d Mon Sep 17 00:00:00 2001 From: Christian Poveda Date: Tue, 15 Apr 2025 22:18:10 -0500 Subject: [PATCH 515/606] Include optional dso_local marker for functions in `enum-match.rs` --- tests/codegen/enum/enum-match.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/codegen/enum/enum-match.rs b/tests/codegen/enum/enum-match.rs index 6e185cf89329..6da6ad1f078d 100644 --- a/tests/codegen/enum/enum-match.rs +++ b/tests/codegen/enum/enum-match.rs @@ -15,7 +15,7 @@ pub enum Enum0 { B, } -// CHECK-LABEL: define noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @match0(i8{{.+}}%0) +// CHECK-LABEL: define{{( dso_local)?}} noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @match0(i8{{.+}}%0) // CHECK-NEXT: start: // CHECK-NEXT: %[[IS_B:.+]] = icmp eq i8 %0, 2 // CHECK-NEXT: %[[TRUNC:.+]] = and i8 %0, 1 @@ -37,7 +37,7 @@ pub enum Enum1 { C, } -// CHECK-LABEL: define noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @match1(i8{{.+}}%0) +// CHECK-LABEL: define{{( dso_local)?}} noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @match1(i8{{.+}}%0) // CHECK-NEXT: start: // CHECK-NEXT: %[[REL_VAR:.+]] = add{{( nsw)?}} i8 %0, -2 // CHECK-NEXT: %[[REL_VAR_WIDE:.+]] = zext i8 %[[REL_VAR]] to i64 @@ -98,7 +98,7 @@ pub enum Enum2 { E, } -// CHECK-LABEL: define noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @match2(i8{{.+}}%0) +// CHECK-LABEL: define{{( dso_local)?}} noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @match2(i8{{.+}}%0) // CHECK-NEXT: start: // CHECK-NEXT: %[[REL_VAR:.+]] = add i8 %0, 2 // CHECK-NEXT: %[[REL_VAR_WIDE:.+]] = zext i8 %[[REL_VAR]] to i64 @@ -121,7 +121,7 @@ pub fn match2(e: Enum2) -> u8 { // And make sure it works even if the niched scalar is a pointer. // (For example, that we don't try to `sub` on pointers.) -// CHECK-LABEL: define noundef{{( range\(i16 -?[0-9]+, -?[0-9]+\))?}} i16 @match3(ptr{{.+}}%0) +// CHECK-LABEL: define{{( dso_local)?}} noundef{{( range\(i16 -?[0-9]+, -?[0-9]+\))?}} i16 @match3(ptr{{.+}}%0) // CHECK-NEXT: start: // CHECK-NEXT: %[[IS_NULL:.+]] = icmp eq ptr %0, null // CHECK-NEXT: br i1 %[[IS_NULL]] @@ -145,7 +145,7 @@ pub enum MiddleNiche { E, } -// CHECK-LABEL: define noundef{{( range\(i8 -?[0-9]+, -?[0-9]+\))?}} i8 @match4(i8{{.+}}%0) +// CHECK-LABEL: define{{( dso_local)?}} noundef{{( range\(i8 -?[0-9]+, -?[0-9]+\))?}} i8 @match4(i8{{.+}}%0) // CHECK-NEXT: start: // CHECK-NEXT: %[[REL_VAR:.+]] = add{{( nsw)?}} i8 %0, -2 // CHECK-NEXT: %[[IS_NICHE:.+]] = icmp ult i8 %[[REL_VAR]], 5 @@ -449,7 +449,7 @@ pub enum HugeVariantIndex { Possible259, } -// CHECK-LABEL: define noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @match5(i8{{.+}}%0) +// CHECK-LABEL: define{{( dso_local)?}} noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @match5(i8{{.+}}%0) // CHECK-NEXT: start: // CHECK-NEXT: %[[REL_VAR:.+]] = add{{( nsw)?}} i8 %0, -2 // CHECK-NEXT: %[[REL_VAR_WIDE:.+]] = zext i8 %[[REL_VAR]] to i64 From bd9bd388fcba2d68b9eab6ff8a051bd07bcde525 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Wed, 16 Apr 2025 08:14:36 +0200 Subject: [PATCH 516/606] Allow disabling `--llvm-shared` in opt-dist --- src/tools/opt-dist/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/opt-dist/src/main.rs b/src/tools/opt-dist/src/main.rs index ac5d294f07ed..ff4ddbaea49b 100644 --- a/src/tools/opt-dist/src/main.rs +++ b/src/tools/opt-dist/src/main.rs @@ -76,7 +76,7 @@ enum EnvironmentCmd { rustc_perf_checkout_dir: Option, /// Is LLVM for `rustc` built in shared library mode? - #[arg(long, default_value_t = true)] + #[arg(long, default_value_t = true, action(clap::ArgAction::Set))] llvm_shared: bool, /// Should BOLT optimization be used? If yes, host LLVM must have BOLT binaries From 6f386e7a9c5224a37e02d627c3e12bee59dee519 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Wed, 16 Apr 2025 08:15:04 +0200 Subject: [PATCH 517/606] Only delete the lld directory if it exists --- src/tools/opt-dist/src/utils/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/tools/opt-dist/src/utils/mod.rs b/src/tools/opt-dist/src/utils/mod.rs index 32d88a59af92..fb4f14ea41ae 100644 --- a/src/tools/opt-dist/src/utils/mod.rs +++ b/src/tools/opt-dist/src/utils/mod.rs @@ -36,7 +36,9 @@ pub fn clear_llvm_files(env: &Environment) -> anyhow::Result<()> { // directories ourselves. log::info!("Clearing LLVM build files"); delete_directory(&env.build_artifacts().join("llvm"))?; - delete_directory(&env.build_artifacts().join("lld"))?; + if env.build_artifacts().join("lld").is_dir() { + delete_directory(&env.build_artifacts().join("lld"))?; + } Ok(()) } From 48e119ef5a8b46ce8db8d362a6d94668c6deb541 Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 16 Apr 2025 10:19:14 +0200 Subject: [PATCH 518/606] stepping into impls for norm is unproductive --- .../src/solve/eval_ctxt/mod.rs | 21 +++++--- .../normalizes-to-is-not-productive-2.rs | 24 +++++++++ ...alizes-to-is-not-productive.current.stderr | 48 +++++++++++++++++ ...ormalizes-to-is-not-productive.next.stderr | 31 +++++++++++ .../cycles/normalizes-to-is-not-productive.rs | 54 +++++++++++++++++++ .../normalizes-to-is-not-productive.stderr | 31 +++++++++++ 6 files changed, 201 insertions(+), 8 deletions(-) create mode 100644 tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive-2.rs create mode 100644 tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.current.stderr create mode 100644 tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.next.stderr create mode 100644 tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.rs create mode 100644 tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.stderr diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 148ba02252d9..9994c85d0d0d 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -286,18 +286,23 @@ where // fixing it may cause inference breakage or introduce ambiguity. GoalSource::Misc => PathKind::Unknown, GoalSource::NormalizeGoal(path_kind) => path_kind, - GoalSource::ImplWhereBound => { + GoalSource::ImplWhereBound => match self.current_goal_kind { // We currently only consider a cycle coinductive if it steps // into a where-clause of a coinductive trait. + CurrentGoalKind::CoinductiveTrait => PathKind::Coinductive, + // While normalizing via an impl does step into a where-clause of + // an impl, accessing the associated item immediately steps out of + // it again. This means cycles/recursive calls are not guarded + // by impls used for normalization. // + // See tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.rs + // for how this can go wrong. + CurrentGoalKind::NormalizesTo => PathKind::Inductive, // We probably want to make all traits coinductive in the future, - // so we treat cycles involving their where-clauses as ambiguous. - if let CurrentGoalKind::CoinductiveTrait = self.current_goal_kind { - PathKind::Coinductive - } else { - PathKind::Unknown - } - } + // so we treat cycles involving where-clauses of not-yet coinductive + // traits as ambiguous for now. + CurrentGoalKind::Misc => PathKind::Unknown, + }, // Relating types is always unproductive. If we were to map proof trees to // corecursive functions as explained in #136824, relating types never // introduces a constructor which could cause the recursion to be guarded. diff --git a/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive-2.rs b/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive-2.rs new file mode 100644 index 000000000000..bb3540f9a214 --- /dev/null +++ b/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive-2.rs @@ -0,0 +1,24 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@ check-pass + +// Regression test for trait-system-refactor-initiative#176. +// +// Normalizing ` as IntoIterator>::IntoIter` has two candidates +// inside of the function: +// - `impl IntoIterator for Vec` which trivially applies +// - `impl IntoIterator for I` +// - requires `Vec: Iterator` +// - where-clause requires ` as IntoIterator>::IntoIter eq Vec` +// - normalize ` as IntoIterator>::IntoIter` again, cycle +// +// We need to treat this cycle as an error to be able to use the actual impl. + +fn test() +where + as IntoIterator>::IntoIter: Iterator, +{ +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.current.stderr b/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.current.stderr new file mode 100644 index 000000000000..0a5b90f3d12b --- /dev/null +++ b/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.current.stderr @@ -0,0 +1,48 @@ +error[E0277]: the trait bound `Foo: Bound` is not satisfied + --> $DIR/normalizes-to-is-not-productive.rs:41:1 + | +LL | / fn generic() +LL | | where +LL | | >::Assoc: Bound, + | |____________________________________^ the trait `Bound` is not implemented for `Foo` + | + = help: the trait `Bound` is implemented for `u32` +note: required for `Foo` to implement `Trait` + --> $DIR/normalizes-to-is-not-productive.rs:24:19 + | +LL | impl Trait for T { + | ----- ^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here + +error[E0277]: the trait bound `Foo: Bound` is not satisfied + --> $DIR/normalizes-to-is-not-productive.rs:41:4 + | +LL | fn generic() + | ^^^^^^^ the trait `Bound` is not implemented for `Foo` + | + = help: the trait `Bound` is implemented for `u32` +note: required for `Foo` to implement `Trait` + --> $DIR/normalizes-to-is-not-productive.rs:24:19 + | +LL | impl Trait for T { + | ----- ^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here + +error[E0277]: the trait bound `Foo: Bound` is not satisfied + --> $DIR/normalizes-to-is-not-productive.rs:48:19 + | +LL | impls_bound::(); + | ^^^ the trait `Bound` is not implemented for `Foo` + | + = help: the trait `Bound` is implemented for `u32` +note: required by a bound in `impls_bound` + --> $DIR/normalizes-to-is-not-productive.rs:28:19 + | +LL | fn impls_bound() { + | ^^^^^ required by this bound in `impls_bound` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.next.stderr b/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.next.stderr new file mode 100644 index 000000000000..d888fbf9db18 --- /dev/null +++ b/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.next.stderr @@ -0,0 +1,31 @@ +error[E0277]: the trait bound `Foo: Bound` is not satisfied + --> $DIR/normalizes-to-is-not-productive.rs:43:31 + | +LL | >::Assoc: Bound, + | ^^^^^ the trait `Bound` is not implemented for `Foo` + | + = help: the trait `Bound` is implemented for `u32` +note: required for `Foo` to implement `Trait` + --> $DIR/normalizes-to-is-not-productive.rs:24:19 + | +LL | impl Trait for T { + | ----- ^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here + +error[E0277]: the trait bound `Foo: Bound` is not satisfied + --> $DIR/normalizes-to-is-not-productive.rs:48:19 + | +LL | impls_bound::(); + | ^^^ the trait `Bound` is not implemented for `Foo` + | + = help: the trait `Bound` is implemented for `u32` +note: required by a bound in `impls_bound` + --> $DIR/normalizes-to-is-not-productive.rs:28:19 + | +LL | fn impls_bound() { + | ^^^^^ required by this bound in `impls_bound` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.rs b/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.rs new file mode 100644 index 000000000000..ffbbecaf8957 --- /dev/null +++ b/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.rs @@ -0,0 +1,54 @@ +//@ ignore-compare-mode-next-solver (explicit) +//@ compile-flags: -Znext-solver + +// Make sure that stepping into impl where-clauses of `NormalizesTo` +// goals is unproductive. This must not compile, see the inline +// comments. + +trait Bound { + fn method(); +} +impl Bound for u32 { + fn method() {} +} +trait Trait { + type Assoc: Bound; +} + +struct Foo; + +impl Trait for Foo { + type Assoc = u32; +} +impl Trait for T { + type Assoc = T; +} + +fn impls_bound() { + T::method(); +} + +// The where-clause requires `Foo: Trait` to hold to be wf. +// If stepping into where-clauses during normalization is considered +// to be productive, this would be the case: +// +// - `Foo: Trait` +// - via blanket impls, requires `Foo: Bound` +// - via where-bound, requires `Foo eq >::Assoc` +// - normalize `>::Assoc` +// - via blanket impl, requires where-clause `Foo: Bound` -> cycle +fn generic() +where + >::Assoc: Bound, + //~^ ERROR the trait bound `Foo: Bound` is not satisfied +{ + // Requires proving `Foo: Bound` by normalizing + // `>::Assoc` to `Foo`. + impls_bound::(); + //~^ ERROR the trait bound `Foo: Bound` is not satisfied +} +fn main() { + // Requires proving `>::Assoc: Bound`. + // This is trivially true. + generic::(); +} diff --git a/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.stderr b/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.stderr new file mode 100644 index 000000000000..8901805a20f5 --- /dev/null +++ b/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.stderr @@ -0,0 +1,31 @@ +error[E0277]: the trait bound `Foo: Bound` is not satisfied + --> $DIR/normalizes-to-is-not-productive.rs:42:31 + | +LL | >::Assoc: Bound, + | ^^^^^ the trait `Bound` is not implemented for `Foo` + | + = help: the trait `Bound` is implemented for `u32` +note: required for `Foo` to implement `Trait` + --> $DIR/normalizes-to-is-not-productive.rs:23:19 + | +LL | impl Trait for T { + | ----- ^^^^^^^^ ^ + | | + | unsatisfied trait bound introduced here + +error[E0277]: the trait bound `Foo: Bound` is not satisfied + --> $DIR/normalizes-to-is-not-productive.rs:47:19 + | +LL | impls_bound::(); + | ^^^ the trait `Bound` is not implemented for `Foo` + | + = help: the trait `Bound` is implemented for `u32` +note: required by a bound in `impls_bound` + --> $DIR/normalizes-to-is-not-productive.rs:27:19 + | +LL | fn impls_bound() { + | ^^^^^ required by this bound in `impls_bound` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. From 20ab952b4dd994aa6e22ff56df5314eee5ff415c Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 16 Apr 2025 10:45:03 +0200 Subject: [PATCH 519/606] Explicitly annotate edition for `unpretty=expanded` and `unpretty=hir` tests These emit prelude imports which means they are always edition dependent --- diff | 0 tests/ui/asm/unpretty-expanded.rs | 1 + tests/ui/asm/unpretty-expanded.stdout | 1 + tests/ui/codemap_tests/unicode.expanded.stdout | 1 + tests/ui/codemap_tests/unicode.normal.stderr | 2 +- tests/ui/codemap_tests/unicode.rs | 1 + tests/ui/const-generics/defaults/pretty-printing-ast.rs | 1 + .../const-generics/defaults/pretty-printing-ast.stdout | 1 + tests/ui/deriving/built-in-proc-macro-scope.rs | 1 + tests/ui/deriving/built-in-proc-macro-scope.stdout | 1 + tests/ui/deriving/deriving-coerce-pointee-expanded.rs | 1 + .../ui/deriving/deriving-coerce-pointee-expanded.stdout | 1 + tests/ui/deriving/proc-macro-attribute-mixing.rs | 1 + tests/ui/deriving/proc-macro-attribute-mixing.stdout | 1 + .../no_ice_for_partial_compiler_runs.rs | 1 + .../no_ice_for_partial_compiler_runs.stdout | 1 + tests/ui/macros/genercs-in-path-with-prettry-hir.rs | 1 + tests/ui/macros/genercs-in-path-with-prettry-hir.stderr | 2 +- tests/ui/macros/genercs-in-path-with-prettry-hir.stdout | 1 + .../non-consuming-methods-have-optimized-codegen.rs | 1 + .../non-consuming-methods-have-optimized-codegen.stdout | 1 + tests/ui/match/issue-82392.rs | 1 + tests/ui/match/issue-82392.stdout | 1 + tests/ui/proc-macro/nonterminal-token-hygiene.rs | 1 + tests/ui/proc-macro/nonterminal-token-hygiene.stdout | 9 +++++---- tests/ui/proc-macro/quote/debug.rs | 1 + tests/ui/proc-macro/quote/debug.stdout | 1 + tests/ui/rfcs/rfc-2497-if-let-chains/ast-pretty-check.rs | 1 + .../rfcs/rfc-2497-if-let-chains/ast-pretty-check.stdout | 1 + tests/ui/type-alias-impl-trait/issue-60662.rs | 1 + tests/ui/type-alias-impl-trait/issue-60662.stdout | 1 + tests/ui/unpretty/bad-literal.rs | 1 + tests/ui/unpretty/bad-literal.stderr | 2 +- tests/ui/unpretty/bad-literal.stdout | 1 + tests/ui/unpretty/debug-fmt-hir.rs | 1 + tests/ui/unpretty/debug-fmt-hir.stdout | 1 + tests/ui/unpretty/deprecated-attr.rs | 1 + tests/ui/unpretty/deprecated-attr.stdout | 1 + tests/ui/unpretty/diagnostic-attr.rs | 1 + tests/ui/unpretty/diagnostic-attr.stdout | 1 + tests/ui/unpretty/expanded-interpolation.rs | 1 + tests/ui/unpretty/expanded-interpolation.stdout | 1 + tests/ui/unpretty/flattened-format-args.rs | 1 + tests/ui/unpretty/flattened-format-args.stdout | 1 + tests/ui/unpretty/let-else-hir.rs | 1 + tests/ui/unpretty/let-else-hir.stdout | 1 + tests/ui/unpretty/self-hir.rs | 1 + tests/ui/unpretty/self-hir.stdout | 1 + tests/ui/unpretty/unpretty-expr-fn-arg.rs | 1 + tests/ui/unpretty/unpretty-expr-fn-arg.stdout | 1 + 50 files changed, 53 insertions(+), 7 deletions(-) create mode 100644 diff diff --git a/diff b/diff new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/tests/ui/asm/unpretty-expanded.rs b/tests/ui/asm/unpretty-expanded.rs index 1da2c7704f41..3eb46fe4889c 100644 --- a/tests/ui/asm/unpretty-expanded.rs +++ b/tests/ui/asm/unpretty-expanded.rs @@ -1,4 +1,5 @@ //@ needs-asm-support //@ check-pass //@ compile-flags: -Zunpretty=expanded +//@ edition: 2015 core::arch::global_asm!("x: .byte 42"); diff --git a/tests/ui/asm/unpretty-expanded.stdout b/tests/ui/asm/unpretty-expanded.stdout index 80ccd127d506..7ba1702dfed8 100644 --- a/tests/ui/asm/unpretty-expanded.stdout +++ b/tests/ui/asm/unpretty-expanded.stdout @@ -7,4 +7,5 @@ extern crate std; //@ needs-asm-support //@ check-pass //@ compile-flags: -Zunpretty=expanded +//@ edition: 2015 global_asm! ("x: .byte 42"); diff --git a/tests/ui/codemap_tests/unicode.expanded.stdout b/tests/ui/codemap_tests/unicode.expanded.stdout index eb53d12e94f3..c88035de0449 100644 --- a/tests/ui/codemap_tests/unicode.expanded.stdout +++ b/tests/ui/codemap_tests/unicode.expanded.stdout @@ -7,6 +7,7 @@ extern crate std; //@ revisions: normal expanded //@[expanded] check-pass //@[expanded]compile-flags: -Zunpretty=expanded +//@ edition: 2015 extern "路濫狼á́́" fn foo() {} diff --git a/tests/ui/codemap_tests/unicode.normal.stderr b/tests/ui/codemap_tests/unicode.normal.stderr index 0f254e0246f4..10cb34f48326 100644 --- a/tests/ui/codemap_tests/unicode.normal.stderr +++ b/tests/ui/codemap_tests/unicode.normal.stderr @@ -1,5 +1,5 @@ error[E0703]: invalid ABI: found `路濫狼á́́` - --> $DIR/unicode.rs:5:8 + --> $DIR/unicode.rs:6:8 | LL | extern "路濫狼á́́" fn foo() {} | ^^^^^^^^^ invalid ABI diff --git a/tests/ui/codemap_tests/unicode.rs b/tests/ui/codemap_tests/unicode.rs index 73023e3c669d..4b93ef094069 100644 --- a/tests/ui/codemap_tests/unicode.rs +++ b/tests/ui/codemap_tests/unicode.rs @@ -1,6 +1,7 @@ //@ revisions: normal expanded //@[expanded] check-pass //@[expanded]compile-flags: -Zunpretty=expanded +//@ edition: 2015 extern "路濫狼á́́" fn foo() {} //[normal]~ ERROR invalid ABI diff --git a/tests/ui/const-generics/defaults/pretty-printing-ast.rs b/tests/ui/const-generics/defaults/pretty-printing-ast.rs index 20bf900d9f3e..f7a166d00d55 100644 --- a/tests/ui/const-generics/defaults/pretty-printing-ast.rs +++ b/tests/ui/const-generics/defaults/pretty-printing-ast.rs @@ -1,6 +1,7 @@ // Test the AST pretty printer correctly handles default values for const generics //@ check-pass //@ compile-flags: -Z unpretty=expanded +//@ edition: 2015 #![crate_type = "lib"] diff --git a/tests/ui/const-generics/defaults/pretty-printing-ast.stdout b/tests/ui/const-generics/defaults/pretty-printing-ast.stdout index f1cd1451700f..b6cb7fa09c88 100644 --- a/tests/ui/const-generics/defaults/pretty-printing-ast.stdout +++ b/tests/ui/const-generics/defaults/pretty-printing-ast.stdout @@ -3,6 +3,7 @@ // Test the AST pretty printer correctly handles default values for const generics //@ check-pass //@ compile-flags: -Z unpretty=expanded +//@ edition: 2015 #![crate_type = "lib"] #[prelude_import] diff --git a/tests/ui/deriving/built-in-proc-macro-scope.rs b/tests/ui/deriving/built-in-proc-macro-scope.rs index e67197b7e205..69128a08b997 100644 --- a/tests/ui/deriving/built-in-proc-macro-scope.rs +++ b/tests/ui/deriving/built-in-proc-macro-scope.rs @@ -1,6 +1,7 @@ //@ check-pass //@ proc-macro: another-proc-macro.rs //@ compile-flags: -Zunpretty=expanded +//@ edition:2015 #![feature(derive_coerce_pointee)] diff --git a/tests/ui/deriving/built-in-proc-macro-scope.stdout b/tests/ui/deriving/built-in-proc-macro-scope.stdout index fa4e50968f4d..2697618ab003 100644 --- a/tests/ui/deriving/built-in-proc-macro-scope.stdout +++ b/tests/ui/deriving/built-in-proc-macro-scope.stdout @@ -3,6 +3,7 @@ //@ check-pass //@ proc-macro: another-proc-macro.rs //@ compile-flags: -Zunpretty=expanded +//@ edition:2015 #![feature(derive_coerce_pointee)] #[prelude_import] diff --git a/tests/ui/deriving/deriving-coerce-pointee-expanded.rs b/tests/ui/deriving/deriving-coerce-pointee-expanded.rs index 94be7031fb77..9394ae4efe5a 100644 --- a/tests/ui/deriving/deriving-coerce-pointee-expanded.rs +++ b/tests/ui/deriving/deriving-coerce-pointee-expanded.rs @@ -1,5 +1,6 @@ //@ check-pass //@ compile-flags: -Zunpretty=expanded +//@ edition: 2015 #![feature(derive_coerce_pointee)] use std::marker::CoercePointee; diff --git a/tests/ui/deriving/deriving-coerce-pointee-expanded.stdout b/tests/ui/deriving/deriving-coerce-pointee-expanded.stdout index a774efbbe354..84f8e9a3195a 100644 --- a/tests/ui/deriving/deriving-coerce-pointee-expanded.stdout +++ b/tests/ui/deriving/deriving-coerce-pointee-expanded.stdout @@ -2,6 +2,7 @@ #![no_std] //@ check-pass //@ compile-flags: -Zunpretty=expanded +//@ edition: 2015 #![feature(derive_coerce_pointee)] #[prelude_import] use ::std::prelude::rust_2015::*; diff --git a/tests/ui/deriving/proc-macro-attribute-mixing.rs b/tests/ui/deriving/proc-macro-attribute-mixing.rs index 2c11c3f72ca5..c9e123d7e8a1 100644 --- a/tests/ui/deriving/proc-macro-attribute-mixing.rs +++ b/tests/ui/deriving/proc-macro-attribute-mixing.rs @@ -7,6 +7,7 @@ //@ check-pass //@ proc-macro: another-proc-macro.rs //@ compile-flags: -Zunpretty=expanded +//@ edition: 2015 #![feature(derive_coerce_pointee)] diff --git a/tests/ui/deriving/proc-macro-attribute-mixing.stdout b/tests/ui/deriving/proc-macro-attribute-mixing.stdout index ad743d013d25..faa9c0218a33 100644 --- a/tests/ui/deriving/proc-macro-attribute-mixing.stdout +++ b/tests/ui/deriving/proc-macro-attribute-mixing.stdout @@ -9,6 +9,7 @@ //@ check-pass //@ proc-macro: another-proc-macro.rs //@ compile-flags: -Zunpretty=expanded +//@ edition: 2015 #![feature(derive_coerce_pointee)] #[prelude_import] diff --git a/tests/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.rs b/tests/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.rs index 9e38b94b76ce..11ee2bc852ab 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.rs +++ b/tests/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.rs @@ -1,6 +1,7 @@ // This ensures that ICEs like rust#94953 don't happen //@ check-pass //@ compile-flags: -Z unpretty=expanded +//@ edition: 2015 // This `expect` will create an expectation with an unstable expectation id #[expect(while_true)] diff --git a/tests/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.stdout b/tests/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.stdout index d804c1d2d200..d63abea92302 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.stdout +++ b/tests/ui/lint/rfc-2383-lint-reason/no_ice_for_partial_compiler_runs.stdout @@ -7,6 +7,7 @@ extern crate std; // This ensures that ICEs like rust#94953 don't happen //@ check-pass //@ compile-flags: -Z unpretty=expanded +//@ edition: 2015 // This `expect` will create an expectation with an unstable expectation id #[expect(while_true)] diff --git a/tests/ui/macros/genercs-in-path-with-prettry-hir.rs b/tests/ui/macros/genercs-in-path-with-prettry-hir.rs index 84370fcebbcb..e6773f610da3 100644 --- a/tests/ui/macros/genercs-in-path-with-prettry-hir.rs +++ b/tests/ui/macros/genercs-in-path-with-prettry-hir.rs @@ -1,4 +1,5 @@ //@ compile-flags: -Zunpretty=hir +//@ edition: 2015 // issue#97006 diff --git a/tests/ui/macros/genercs-in-path-with-prettry-hir.stderr b/tests/ui/macros/genercs-in-path-with-prettry-hir.stderr index 8fcc7c6fbff0..173e77569a80 100644 --- a/tests/ui/macros/genercs-in-path-with-prettry-hir.stderr +++ b/tests/ui/macros/genercs-in-path-with-prettry-hir.stderr @@ -1,5 +1,5 @@ error: unexpected generic arguments in path - --> $DIR/genercs-in-path-with-prettry-hir.rs:12:10 + --> $DIR/genercs-in-path-with-prettry-hir.rs:13:10 | LL | m!(inline); | ^^^^ diff --git a/tests/ui/macros/genercs-in-path-with-prettry-hir.stdout b/tests/ui/macros/genercs-in-path-with-prettry-hir.stdout index e8c88d2dcdf2..6b41eb530dbc 100644 --- a/tests/ui/macros/genercs-in-path-with-prettry-hir.stdout +++ b/tests/ui/macros/genercs-in-path-with-prettry-hir.stdout @@ -3,6 +3,7 @@ use ::std::prelude::rust_2015::*; #[macro_use] extern crate std; //@ compile-flags: -Zunpretty=hir +//@ edition: 2015 // issue#97006 diff --git a/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.rs b/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.rs index cf47a1e67aed..29f71d10719b 100644 --- a/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.rs +++ b/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.rs @@ -1,5 +1,6 @@ //@ check-pass //@ compile-flags: -Z unpretty=expanded +//@ edition: 2015 #![feature(core_intrinsics, generic_assert)] diff --git a/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout b/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout index 8065d0dff8fc..9300f610f8e2 100644 --- a/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout +++ b/tests/ui/macros/rfc-2011-nicer-assert-messages/non-consuming-methods-have-optimized-codegen.stdout @@ -2,6 +2,7 @@ #![no_std] //@ check-pass //@ compile-flags: -Z unpretty=expanded +//@ edition: 2015 #![feature(core_intrinsics, generic_assert)] #[prelude_import] diff --git a/tests/ui/match/issue-82392.rs b/tests/ui/match/issue-82392.rs index 6f9527fb337b..4ae08fed93a2 100644 --- a/tests/ui/match/issue-82392.rs +++ b/tests/ui/match/issue-82392.rs @@ -1,6 +1,7 @@ // https://github.com/rust-lang/rust/issues/82329 //@ compile-flags: -Zunpretty=hir,typed //@ check-pass +//@ edition:2015 pub fn main() { if true { diff --git a/tests/ui/match/issue-82392.stdout b/tests/ui/match/issue-82392.stdout index 8949611ac12f..8b7edabf004e 100644 --- a/tests/ui/match/issue-82392.stdout +++ b/tests/ui/match/issue-82392.stdout @@ -5,6 +5,7 @@ extern crate std; // https://github.com/rust-lang/rust/issues/82329 //@ compile-flags: -Zunpretty=hir,typed //@ check-pass +//@ edition:2015 fn main() ({ (if (true as bool) diff --git a/tests/ui/proc-macro/nonterminal-token-hygiene.rs b/tests/ui/proc-macro/nonterminal-token-hygiene.rs index e2aedb245d07..b7b0d1ea3dd7 100644 --- a/tests/ui/proc-macro/nonterminal-token-hygiene.rs +++ b/tests/ui/proc-macro/nonterminal-token-hygiene.rs @@ -8,6 +8,7 @@ //@ normalize-stdout: "expn\d{3,}" -> "expnNNN" //@ normalize-stdout: "extern crate compiler_builtins /\* \d+ \*/" -> "extern crate compiler_builtins /* NNN */" //@ proc-macro: test-macros.rs +//@ edition: 2015 #![feature(decl_macro)] #![no_std] // Don't load unnecessary hygiene information from std diff --git a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout index 6fd6cb474693..2ebfb47d9815 100644 --- a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout +++ b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout @@ -5,19 +5,19 @@ PRINT-BANG INPUT (DEBUG): TokenStream [ stream: TokenStream [ Ident { ident: "struct", - span: $DIR/nonterminal-token-hygiene.rs:32:5: 32:11 (#5), + span: $DIR/nonterminal-token-hygiene.rs:33:5: 33:11 (#5), }, Ident { ident: "S", - span: $DIR/nonterminal-token-hygiene.rs:32:12: 32:13 (#5), + span: $DIR/nonterminal-token-hygiene.rs:33:12: 33:13 (#5), }, Punct { ch: ';', spacing: Alone, - span: $DIR/nonterminal-token-hygiene.rs:32:13: 32:14 (#5), + span: $DIR/nonterminal-token-hygiene.rs:33:13: 33:14 (#5), }, ], - span: $DIR/nonterminal-token-hygiene.rs:22:27: 22:32 (#4), + span: $DIR/nonterminal-token-hygiene.rs:23:27: 23:32 (#4), }, ] #![feature /* 0#0 */(prelude_import)] @@ -32,6 +32,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [ //@ normalize-stdout: "expn\d{3,}" -> "expnNNN" //@ normalize-stdout: "extern crate compiler_builtins /\* \d+ \*/" -> "extern crate compiler_builtins /* NNN */" //@ proc-macro: test-macros.rs +//@ edition: 2015 #![feature /* 0#0 */(decl_macro)] #![no_std /* 0#0 */] diff --git a/tests/ui/proc-macro/quote/debug.rs b/tests/ui/proc-macro/quote/debug.rs index ce113079e567..ce1ef81bedaf 100644 --- a/tests/ui/proc-macro/quote/debug.rs +++ b/tests/ui/proc-macro/quote/debug.rs @@ -3,6 +3,7 @@ //@ no-prefer-dynamic //@ compile-flags: -Z unpretty=expanded //@ needs-unwind compiling proc macros with panic=abort causes a warning +//@ edition: 2015 // // This file is not actually used as a proc-macro - instead, // it's just used to show the output of the `quote!` macro diff --git a/tests/ui/proc-macro/quote/debug.stdout b/tests/ui/proc-macro/quote/debug.stdout index 3eaad9eb9699..6ebb3a379511 100644 --- a/tests/ui/proc-macro/quote/debug.stdout +++ b/tests/ui/proc-macro/quote/debug.stdout @@ -5,6 +5,7 @@ //@ no-prefer-dynamic //@ compile-flags: -Z unpretty=expanded //@ needs-unwind compiling proc macros with panic=abort causes a warning +//@ edition: 2015 // // This file is not actually used as a proc-macro - instead, // it's just used to show the output of the `quote!` macro diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/ast-pretty-check.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/ast-pretty-check.rs index 8d7826463336..16165c4a42cc 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/ast-pretty-check.rs +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/ast-pretty-check.rs @@ -1,5 +1,6 @@ //@ check-pass //@ compile-flags: -Z unpretty=expanded +//@ edition: 2015 fn main() { if let 0 = 1 {} diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/ast-pretty-check.stdout b/tests/ui/rfcs/rfc-2497-if-let-chains/ast-pretty-check.stdout index 1c103f03c354..e2e45ae94ea6 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/ast-pretty-check.stdout +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/ast-pretty-check.stdout @@ -6,5 +6,6 @@ use ::std::prelude::rust_2015::*; extern crate std; //@ check-pass //@ compile-flags: -Z unpretty=expanded +//@ edition: 2015 fn main() { if let 0 = 1 {} } diff --git a/tests/ui/type-alias-impl-trait/issue-60662.rs b/tests/ui/type-alias-impl-trait/issue-60662.rs index 35d96e52fd61..7ecdd2647355 100644 --- a/tests/ui/type-alias-impl-trait/issue-60662.rs +++ b/tests/ui/type-alias-impl-trait/issue-60662.rs @@ -1,5 +1,6 @@ //@ check-pass //@ compile-flags: -Z unpretty=hir +//@ edition: 2015 #![feature(type_alias_impl_trait)] diff --git a/tests/ui/type-alias-impl-trait/issue-60662.stdout b/tests/ui/type-alias-impl-trait/issue-60662.stdout index b541cbeb2279..56fef852e37b 100644 --- a/tests/ui/type-alias-impl-trait/issue-60662.stdout +++ b/tests/ui/type-alias-impl-trait/issue-60662.stdout @@ -1,5 +1,6 @@ //@ check-pass //@ compile-flags: -Z unpretty=hir +//@ edition: 2015 #![feature(type_alias_impl_trait)] #[prelude_import] diff --git a/tests/ui/unpretty/bad-literal.rs b/tests/ui/unpretty/bad-literal.rs index 37377898b14f..0ec1d7b07f1f 100644 --- a/tests/ui/unpretty/bad-literal.rs +++ b/tests/ui/unpretty/bad-literal.rs @@ -1,5 +1,6 @@ //@ compile-flags: -Zunpretty=hir //@ check-fail +//@ edition: 2015 // In #100948 this caused an ICE with -Zunpretty=hir. fn main() { diff --git a/tests/ui/unpretty/bad-literal.stderr b/tests/ui/unpretty/bad-literal.stderr index b6259484f67d..fd1801a87f20 100644 --- a/tests/ui/unpretty/bad-literal.stderr +++ b/tests/ui/unpretty/bad-literal.stderr @@ -1,5 +1,5 @@ error: invalid suffix `u` for number literal - --> $DIR/bad-literal.rs:6:5 + --> $DIR/bad-literal.rs:7:5 | LL | 1u; | ^^ invalid suffix `u` diff --git a/tests/ui/unpretty/bad-literal.stdout b/tests/ui/unpretty/bad-literal.stdout index c5272711d6e9..06116a4ab553 100644 --- a/tests/ui/unpretty/bad-literal.stdout +++ b/tests/ui/unpretty/bad-literal.stdout @@ -4,6 +4,7 @@ use ::std::prelude::rust_2015::*; extern crate std; //@ compile-flags: -Zunpretty=hir //@ check-fail +//@ edition: 2015 // In #100948 this caused an ICE with -Zunpretty=hir. fn main() { diff --git a/tests/ui/unpretty/debug-fmt-hir.rs b/tests/ui/unpretty/debug-fmt-hir.rs index c19f3c4c0c57..c79349de4442 100644 --- a/tests/ui/unpretty/debug-fmt-hir.rs +++ b/tests/ui/unpretty/debug-fmt-hir.rs @@ -1,5 +1,6 @@ //@ compile-flags: -Zunpretty=hir //@ check-pass +//@ edition: 2015 use std::fmt; diff --git a/tests/ui/unpretty/debug-fmt-hir.stdout b/tests/ui/unpretty/debug-fmt-hir.stdout index 2c9c96de9d14..dc18675ea803 100644 --- a/tests/ui/unpretty/debug-fmt-hir.stdout +++ b/tests/ui/unpretty/debug-fmt-hir.stdout @@ -4,6 +4,7 @@ use ::std::prelude::rust_2015::*; extern crate std; //@ compile-flags: -Zunpretty=hir //@ check-pass +//@ edition: 2015 use std::fmt; diff --git a/tests/ui/unpretty/deprecated-attr.rs b/tests/ui/unpretty/deprecated-attr.rs index dda362a595e2..0c80203e9652 100644 --- a/tests/ui/unpretty/deprecated-attr.rs +++ b/tests/ui/unpretty/deprecated-attr.rs @@ -1,5 +1,6 @@ //@ compile-flags: -Zunpretty=hir //@ check-pass +//@ edition: 2015 #[deprecated] pub struct PlainDeprecated; diff --git a/tests/ui/unpretty/deprecated-attr.stdout b/tests/ui/unpretty/deprecated-attr.stdout index 42de7b4533e5..97d863b2e943 100644 --- a/tests/ui/unpretty/deprecated-attr.stdout +++ b/tests/ui/unpretty/deprecated-attr.stdout @@ -4,6 +4,7 @@ use ::std::prelude::rust_2015::*; extern crate std; //@ compile-flags: -Zunpretty=hir //@ check-pass +//@ edition: 2015 #[attr = Deprecation {deprecation: Deprecation {since: Unspecified}}] struct PlainDeprecated; diff --git a/tests/ui/unpretty/diagnostic-attr.rs b/tests/ui/unpretty/diagnostic-attr.rs index 27f5b693e691..4ef85c71f90e 100644 --- a/tests/ui/unpretty/diagnostic-attr.rs +++ b/tests/ui/unpretty/diagnostic-attr.rs @@ -1,5 +1,6 @@ //@ compile-flags: -Zunpretty=hir //@ check-pass +//@ edition: 2015 #[diagnostic::on_unimplemented( message = "My Message for `ImportantTrait<{A}>` implemented for `{Self}`", diff --git a/tests/ui/unpretty/diagnostic-attr.stdout b/tests/ui/unpretty/diagnostic-attr.stdout index e8696d04d38a..81d71b91d815 100644 --- a/tests/ui/unpretty/diagnostic-attr.stdout +++ b/tests/ui/unpretty/diagnostic-attr.stdout @@ -4,6 +4,7 @@ use ::std::prelude::rust_2015::*; extern crate std; //@ compile-flags: -Zunpretty=hir //@ check-pass +//@ edition: 2015 #[diagnostic::on_unimplemented(message = "My Message for `ImportantTrait<{A}>` implemented for `{Self}`", label = diff --git a/tests/ui/unpretty/expanded-interpolation.rs b/tests/ui/unpretty/expanded-interpolation.rs index 1dc72c67f511..0c447ae669dd 100644 --- a/tests/ui/unpretty/expanded-interpolation.rs +++ b/tests/ui/unpretty/expanded-interpolation.rs @@ -1,5 +1,6 @@ //@ compile-flags: -Zunpretty=expanded //@ check-pass +//@ edition: 2015 // This test covers the AST pretty-printer's insertion of parentheses in some // macro metavariable edge cases. Synthetic parentheses (i.e. not appearing in diff --git a/tests/ui/unpretty/expanded-interpolation.stdout b/tests/ui/unpretty/expanded-interpolation.stdout index 556e57dbd921..10729a96ef59 100644 --- a/tests/ui/unpretty/expanded-interpolation.stdout +++ b/tests/ui/unpretty/expanded-interpolation.stdout @@ -2,6 +2,7 @@ #![no_std] //@ compile-flags: -Zunpretty=expanded //@ check-pass +//@ edition: 2015 // This test covers the AST pretty-printer's insertion of parentheses in some // macro metavariable edge cases. Synthetic parentheses (i.e. not appearing in diff --git a/tests/ui/unpretty/flattened-format-args.rs b/tests/ui/unpretty/flattened-format-args.rs index 772f44cc268e..ab065f494dc0 100644 --- a/tests/ui/unpretty/flattened-format-args.rs +++ b/tests/ui/unpretty/flattened-format-args.rs @@ -1,5 +1,6 @@ //@ compile-flags: -Zunpretty=hir -Zflatten-format-args=yes //@ check-pass +//@ edition: 2015 fn main() { let x = 1; diff --git a/tests/ui/unpretty/flattened-format-args.stdout b/tests/ui/unpretty/flattened-format-args.stdout index 2de1cdd96b5b..a5d943281ad8 100644 --- a/tests/ui/unpretty/flattened-format-args.stdout +++ b/tests/ui/unpretty/flattened-format-args.stdout @@ -4,6 +4,7 @@ use ::std::prelude::rust_2015::*; extern crate std; //@ compile-flags: -Zunpretty=hir -Zflatten-format-args=yes //@ check-pass +//@ edition: 2015 fn main() { let x = 1; diff --git a/tests/ui/unpretty/let-else-hir.rs b/tests/ui/unpretty/let-else-hir.rs index 9c231189659a..786c84a09ddd 100644 --- a/tests/ui/unpretty/let-else-hir.rs +++ b/tests/ui/unpretty/let-else-hir.rs @@ -1,5 +1,6 @@ //@ compile-flags: -Zunpretty=hir //@ check-pass +//@ edition: 2015 diff --git a/tests/ui/unpretty/let-else-hir.stdout b/tests/ui/unpretty/let-else-hir.stdout index a2ffa5de5673..a6dd943ec1b7 100644 --- a/tests/ui/unpretty/let-else-hir.stdout +++ b/tests/ui/unpretty/let-else-hir.stdout @@ -4,6 +4,7 @@ use ::std::prelude::rust_2015::*; extern crate std; //@ compile-flags: -Zunpretty=hir //@ check-pass +//@ edition: 2015 diff --git a/tests/ui/unpretty/self-hir.rs b/tests/ui/unpretty/self-hir.rs index 448d828d4446..70e0ba589fb8 100644 --- a/tests/ui/unpretty/self-hir.rs +++ b/tests/ui/unpretty/self-hir.rs @@ -1,5 +1,6 @@ //@ compile-flags: -Zunpretty=hir //@ check-pass +//@ edition: 2015 pub struct Bar { a: String, diff --git a/tests/ui/unpretty/self-hir.stdout b/tests/ui/unpretty/self-hir.stdout index 4da080dc611e..a9e80b1f5920 100644 --- a/tests/ui/unpretty/self-hir.stdout +++ b/tests/ui/unpretty/self-hir.stdout @@ -4,6 +4,7 @@ use ::std::prelude::rust_2015::*; extern crate std; //@ compile-flags: -Zunpretty=hir //@ check-pass +//@ edition: 2015 struct Bar { a: String, diff --git a/tests/ui/unpretty/unpretty-expr-fn-arg.rs b/tests/ui/unpretty/unpretty-expr-fn-arg.rs index 7f496e773c28..b2ab2e0911e5 100644 --- a/tests/ui/unpretty/unpretty-expr-fn-arg.rs +++ b/tests/ui/unpretty/unpretty-expr-fn-arg.rs @@ -6,6 +6,7 @@ //@ check-pass //@ compile-flags: -Zunpretty=hir,typed +//@ edition: 2015 #![allow(dead_code)] fn main() {} diff --git a/tests/ui/unpretty/unpretty-expr-fn-arg.stdout b/tests/ui/unpretty/unpretty-expr-fn-arg.stdout index 43aa93c83bd3..fd2e794fcac8 100644 --- a/tests/ui/unpretty/unpretty-expr-fn-arg.stdout +++ b/tests/ui/unpretty/unpretty-expr-fn-arg.stdout @@ -6,6 +6,7 @@ //@ check-pass //@ compile-flags: -Zunpretty=hir,typed +//@ edition: 2015 #![allow(dead_code)] #[prelude_import] use ::std::prelude::rust_2015::*; From a6dcd519f325e8e3bce6b59461d6f073a9f5c18b Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Wed, 16 Apr 2025 12:16:40 +0200 Subject: [PATCH 520/606] fix multiple `#[repr(align(N))]` on functions --- .../rustc_codegen_ssa/src/codegen_attrs.rs | 3 ++- tests/codegen/align-fn.rs | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index ddb611889833..8f23a5f21cdf 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -114,7 +114,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { AttributeKind::Repr(reprs) => { codegen_fn_attrs.alignment = reprs .iter() - .find_map(|(r, _)| if let ReprAlign(x) = r { Some(*x) } else { None }); + .filter_map(|(r, _)| if let ReprAlign(x) = r { Some(*x) } else { None }) + .max(); } _ => {} diff --git a/tests/codegen/align-fn.rs b/tests/codegen/align-fn.rs index 97f23cc04230..660d8cd2bbf4 100644 --- a/tests/codegen/align-fn.rs +++ b/tests/codegen/align-fn.rs @@ -47,3 +47,22 @@ impl T for () {} pub fn foo() { ().trait_method(); } + +// CHECK-LABEL: align_specified_twice_1 +// CHECK-SAME: align 64 +#[no_mangle] +#[repr(align(32), align(64))] +pub fn align_specified_twice_1() {} + +// CHECK-LABEL: align_specified_twice_2 +// CHECK-SAME: align 128 +#[no_mangle] +#[repr(align(128), align(32))] +pub fn align_specified_twice_2() {} + +// CHECK-LABEL: align_specified_twice_3 +// CHECK-SAME: align 256 +#[no_mangle] +#[repr(align(32))] +#[repr(align(256))] +pub fn align_specified_twice_3() {} From 4d6ae78fa22d04b2c255cb43faabc1ada36cd2c1 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 16 Apr 2025 20:03:18 +1000 Subject: [PATCH 521/606] Remove old diagnostic notes for type ascription syntax Type ascription syntax was removed in 2023. --- compiler/rustc_parse/messages.ftl | 3 --- compiler/rustc_parse/src/errors.rs | 6 ------ compiler/rustc_parse/src/parser/diagnostics.rs | 5 +---- compiler/rustc_parse/src/parser/path.rs | 2 -- compiler/rustc_parse/src/parser/stmt.rs | 4 ---- ...492-tuple-destructure-missing-parens.stderr | 1 - ...single-colon-path-not-const-generics.stderr | 1 - .../or-patterns-syntactic-fail.stderr | 1 - .../issue-35813-postfix-after-cast.stderr | 18 ------------------ .../turbofish-arg-with-stray-colon.stderr | 1 - tests/ui/parser/ternary_operator.stderr | 2 -- ...ype-ascription-syntactically-invalid.stderr | 2 -- ...ment-list-from-path-sep-error-129273.stderr | 1 - .../ui/suggestions/many-type-ascription.stderr | 2 -- ...ct-field-type-including-single-colon.stderr | 2 -- .../type-ascription-instead-of-method.stderr | 1 - .../type-ascription-instead-of-path-2.stderr | 1 - .../type-ascription-instead-of-path.stderr | 1 - .../type-ascription-instead-of-variant.stderr | 1 - tests/ui/type/ascription/issue-47666.stderr | 1 - tests/ui/type/ascription/issue-54516.stderr | 1 - tests/ui/type/ascription/issue-60933.stderr | 1 - tests/ui/type/missing-let-in-binding.stderr | 1 - ...-ascription-instead-of-statement-end.stderr | 1 - .../ui/type/type-ascription-precedence.stderr | 2 -- .../type/type-ascription-with-fn-call.stderr | 1 - 26 files changed, 1 insertion(+), 62 deletions(-) diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 93fa89b68b97..5837f5de5ee8 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -806,9 +806,6 @@ parse_trait_alias_cannot_be_unsafe = trait aliases cannot be `unsafe` parse_transpose_dyn_or_impl = `for<...>` expected after `{$kw}`, not before .suggestion = move `{$kw}` before the `for<...>` -parse_type_ascription_removed = - if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 - parse_unclosed_unicode_escape = unterminated unicode escape .label = missing a closing `{"}"}` .terminate = terminate the unicode escape diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index dfdef018bc37..bca2f1daaf62 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1598,9 +1598,6 @@ pub(crate) struct PathSingleColon { #[suggestion(applicability = "machine-applicable", code = ":", style = "verbose")] pub suggestion: Span, - - #[note(parse_type_ascription_removed)] - pub type_ascription: bool, } #[derive(Diagnostic)] @@ -1617,9 +1614,6 @@ pub(crate) struct ColonAsSemi { #[primary_span] #[suggestion(applicability = "machine-applicable", code = ";", style = "verbose")] pub span: Span, - - #[note(parse_type_ascription_removed)] - pub type_ascription: bool, } #[derive(Diagnostic)] diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index a4978b5a0fe1..b6945c6f7dbd 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -1943,10 +1943,7 @@ impl<'a> Parser<'a> { && self.token == token::Colon && self.look_ahead(1, |next| line_idx(self.token.span) < line_idx(next.span)) { - self.dcx().emit_err(ColonAsSemi { - span: self.token.span, - type_ascription: self.psess.unstable_features.is_nightly_build(), - }); + self.dcx().emit_err(ColonAsSemi { span: self.token.span }); self.bump(); return true; } diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 30fb96c6ea90..028836556623 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -273,7 +273,6 @@ impl<'a> Parser<'a> { self.dcx().emit_err(PathSingleColon { span: self.prev_token.span, suggestion: self.prev_token.span.shrink_to_hi(), - type_ascription: self.psess.unstable_features.is_nightly_build(), }); } continue; @@ -348,7 +347,6 @@ impl<'a> Parser<'a> { err = self.dcx().create_err(PathSingleColon { span: self.token.span, suggestion: self.prev_token.span.shrink_to_hi(), - type_ascription: self.psess.unstable_features.is_nightly_build(), }); } // Attempt to find places where a missing `>` might belong. diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 551b9e2f1371..0cc8b6050186 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -771,10 +771,6 @@ impl<'a> Parser<'a> { Applicability::MaybeIncorrect, ); } - if self.psess.unstable_features.is_nightly_build() { - // FIXME(Nilstrieb): Remove this again after a few months. - err.note("type ascription syntax has been removed, see issue #101728 "); - } } } diff --git a/tests/ui/did_you_mean/issue-48492-tuple-destructure-missing-parens.stderr b/tests/ui/did_you_mean/issue-48492-tuple-destructure-missing-parens.stderr index d4812d4831b0..c74cb89f85cb 100644 --- a/tests/ui/did_you_mean/issue-48492-tuple-destructure-missing-parens.stderr +++ b/tests/ui/did_you_mean/issue-48492-tuple-destructure-missing-parens.stderr @@ -66,7 +66,6 @@ error: unexpected `,` in pattern LL | let women, men: (Vec, Vec) = genomes.iter().cloned() | ^ | - = note: type ascription syntax has been removed, see issue #101728 help: try adding parentheses to match on a tuple | LL | let (women, men): (Vec, Vec) = genomes.iter().cloned() diff --git a/tests/ui/generics/single-colon-path-not-const-generics.stderr b/tests/ui/generics/single-colon-path-not-const-generics.stderr index c14a5e62a0c8..9eb62de27561 100644 --- a/tests/ui/generics/single-colon-path-not-const-generics.stderr +++ b/tests/ui/generics/single-colon-path-not-const-generics.stderr @@ -4,7 +4,6 @@ error: path separator must be a double colon LL | a: Vec, | ^ | - = note: if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 help: use a double colon instead | LL | a: Vec, diff --git a/tests/ui/or-patterns/or-patterns-syntactic-fail.stderr b/tests/ui/or-patterns/or-patterns-syntactic-fail.stderr index 5608138078fb..74e4ceab80e8 100644 --- a/tests/ui/or-patterns/or-patterns-syntactic-fail.stderr +++ b/tests/ui/or-patterns/or-patterns-syntactic-fail.stderr @@ -6,7 +6,6 @@ LL | let _ = |A | B: E| (); | | | while parsing the body of this closure | - = note: type ascription syntax has been removed, see issue #101728 help: you might have meant to open the body of the closure | LL | let _ = |A | { B: E| (); diff --git a/tests/ui/parser/issues/issue-35813-postfix-after-cast.stderr b/tests/ui/parser/issues/issue-35813-postfix-after-cast.stderr index e34371be3d26..64cf8baf9a5d 100644 --- a/tests/ui/parser/issues/issue-35813-postfix-after-cast.stderr +++ b/tests/ui/parser/issues/issue-35813-postfix-after-cast.stderr @@ -49,24 +49,18 @@ error: expected one of `.`, `;`, `?`, `else`, or an operator, found `:` | LL | let _ = 0i32: i32: i32.count_ones(); | ^ expected one of `.`, `;`, `?`, `else`, or an operator - | - = note: type ascription syntax has been removed, see issue #101728 error: expected one of `!`, `(`, `.`, `::`, `;`, `<`, `?`, or `else`, found `:` --> $DIR/issue-35813-postfix-after-cast.rs:43:21 | LL | let _ = 0 as i32: i32.count_ones(); | ^ expected one of 8 possible tokens - | - = note: type ascription syntax has been removed, see issue #101728 error: expected one of `.`, `;`, `?`, `else`, or an operator, found `:` --> $DIR/issue-35813-postfix-after-cast.rs:47:17 | LL | let _ = 0i32: i32 as i32.count_ones(); | ^ expected one of `.`, `;`, `?`, `else`, or an operator - | - = note: type ascription syntax has been removed, see issue #101728 error: cast cannot be followed by a method call --> $DIR/issue-35813-postfix-after-cast.rs:51:13 @@ -84,16 +78,12 @@ error: expected one of `.`, `;`, `?`, `else`, or an operator, found `:` | LL | let _ = 0i32: i32: i32 as u32 as i32.count_ones(); | ^ expected one of `.`, `;`, `?`, `else`, or an operator - | - = note: type ascription syntax has been removed, see issue #101728 error: expected one of `.`, `;`, `?`, `else`, or an operator, found `:` --> $DIR/issue-35813-postfix-after-cast.rs:60:17 | LL | let _ = 0i32: i32.count_ones(): u32; | ^ expected one of `.`, `;`, `?`, `else`, or an operator - | - = note: type ascription syntax has been removed, see issue #101728 error: cast cannot be followed by a method call --> $DIR/issue-35813-postfix-after-cast.rs:64:13 @@ -111,16 +101,12 @@ error: expected one of `.`, `;`, `?`, or `else`, found `:` | LL | let _ = 0 as i32.count_ones(): u32; | ^ expected one of `.`, `;`, `?`, or `else` - | - = note: type ascription syntax has been removed, see issue #101728 error: expected one of `.`, `;`, `?`, `else`, or an operator, found `:` --> $DIR/issue-35813-postfix-after-cast.rs:69:17 | LL | let _ = 0i32: i32.count_ones() as u32; | ^ expected one of `.`, `;`, `?`, `else`, or an operator - | - = note: type ascription syntax has been removed, see issue #101728 error: cast cannot be followed by a method call --> $DIR/issue-35813-postfix-after-cast.rs:73:13 @@ -138,8 +124,6 @@ error: expected one of `.`, `;`, `?`, `else`, or an operator, found `:` | LL | let _ = 0i32: i32: i32.count_ones() as u32 as i32; | ^ expected one of `.`, `;`, `?`, `else`, or an operator - | - = note: type ascription syntax has been removed, see issue #101728 error: cast cannot be followed by a method call --> $DIR/issue-35813-postfix-after-cast.rs:82:13 @@ -262,8 +246,6 @@ error: expected identifier, found `:` | LL | drop_ptr: F(); | ^ expected identifier - | - = note: type ascription syntax has been removed, see issue #101728 error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `:` --> $DIR/issue-35813-postfix-after-cast.rs:160:13 diff --git a/tests/ui/parser/recover/turbofish-arg-with-stray-colon.stderr b/tests/ui/parser/recover/turbofish-arg-with-stray-colon.stderr index 583b98c650f0..c0f9db9184c0 100644 --- a/tests/ui/parser/recover/turbofish-arg-with-stray-colon.stderr +++ b/tests/ui/parser/recover/turbofish-arg-with-stray-colon.stderr @@ -4,7 +4,6 @@ error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, fo LL | let x = Tr; | ^ expected one of 8 possible tokens | - = note: type ascription syntax has been removed, see issue #101728 help: maybe write a path separator here | LL | let x = Tr; diff --git a/tests/ui/parser/ternary_operator.stderr b/tests/ui/parser/ternary_operator.stderr index 6635e1672f78..e12a7ff3718e 100644 --- a/tests/ui/parser/ternary_operator.stderr +++ b/tests/ui/parser/ternary_operator.stderr @@ -33,8 +33,6 @@ error: expected one of `.`, `;`, `?`, `else`, or an operator, found `:` | LL | let x = 5 > 2 ? { let x = vec![]: Vec; x } : { false }; | ^ expected one of `.`, `;`, `?`, `else`, or an operator - | - = note: type ascription syntax has been removed, see issue #101728 error: Rust has no ternary operator --> $DIR/ternary_operator.rs:26:19 diff --git a/tests/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.stderr b/tests/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.stderr index 6ce8f6d31a03..1847e407f6ba 100644 --- a/tests/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.stderr +++ b/tests/ui/pattern/bindings-after-at/nested-type-ascription-syntactically-invalid.stderr @@ -11,8 +11,6 @@ error: expected one of `)`, `,`, `@`, `if`, or `|`, found `:` | LL | let a @ (b: u8); | ^ expected one of `)`, `,`, `@`, `if`, or `|` - | - = note: type ascription syntax has been removed, see issue #101728 error: expected one of `!`, `(`, `+`, `::`, `;`, `<`, or `=`, found `@` --> $DIR/nested-type-ascription-syntactically-invalid.rs:30:15 diff --git a/tests/ui/suggestions/argument-list-from-path-sep-error-129273.stderr b/tests/ui/suggestions/argument-list-from-path-sep-error-129273.stderr index 92947e3b177f..713b071a625a 100644 --- a/tests/ui/suggestions/argument-list-from-path-sep-error-129273.stderr +++ b/tests/ui/suggestions/argument-list-from-path-sep-error-129273.stderr @@ -4,7 +4,6 @@ error: path separator must be a double colon LL | fn fmt(&self, f: &mut fmt:Formatter) -> fmt::Result { | ^ | - = note: if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 help: use a double colon instead | LL | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { diff --git a/tests/ui/suggestions/many-type-ascription.stderr b/tests/ui/suggestions/many-type-ascription.stderr index feddc7d62a75..47e19c508ef9 100644 --- a/tests/ui/suggestions/many-type-ascription.stderr +++ b/tests/ui/suggestions/many-type-ascription.stderr @@ -3,8 +3,6 @@ error: expected one of `.`, `;`, `?`, `else`, or an operator, found `:` | LL | let _ = 0: i32; | ^ expected one of `.`, `;`, `?`, `else`, or an operator - | - = note: type ascription syntax has been removed, see issue #101728 error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/struct-field-type-including-single-colon.stderr b/tests/ui/suggestions/struct-field-type-including-single-colon.stderr index ce16aca1e14a..b9302b0453d5 100644 --- a/tests/ui/suggestions/struct-field-type-including-single-colon.stderr +++ b/tests/ui/suggestions/struct-field-type-including-single-colon.stderr @@ -4,7 +4,6 @@ error: path separator must be a double colon LL | a: foo:A, | ^ | - = note: if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 help: use a double colon instead | LL | a: foo::A, @@ -16,7 +15,6 @@ error: path separator must be a double colon LL | b: foo::bar:B, | ^ | - = note: if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 help: use a double colon instead | LL | b: foo::bar::B, diff --git a/tests/ui/suggestions/type-ascription-instead-of-method.stderr b/tests/ui/suggestions/type-ascription-instead-of-method.stderr index 0bef1c185db6..6dc7b5e18ef8 100644 --- a/tests/ui/suggestions/type-ascription-instead-of-method.stderr +++ b/tests/ui/suggestions/type-ascription-instead-of-method.stderr @@ -4,7 +4,6 @@ error: path separator must be a double colon LL | let _ = Box:new("foo".to_string()); | ^ | - = note: if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 help: use a double colon instead | LL | let _ = Box::new("foo".to_string()); diff --git a/tests/ui/suggestions/type-ascription-instead-of-path-2.stderr b/tests/ui/suggestions/type-ascription-instead-of-path-2.stderr index 0b37bf9a57bb..79dffc0cf9b0 100644 --- a/tests/ui/suggestions/type-ascription-instead-of-path-2.stderr +++ b/tests/ui/suggestions/type-ascription-instead-of-path-2.stderr @@ -4,7 +4,6 @@ error: expected one of `(`, `.`, `::`, `;`, `?`, `else`, or an operator, found ` LL | let _ = vec![Ok(2)].into_iter().collect:,_>>()?; | ^ expected one of 7 possible tokens | - = note: type ascription syntax has been removed, see issue #101728 help: maybe write a path separator here | LL | let _ = vec![Ok(2)].into_iter().collect::,_>>()?; diff --git a/tests/ui/suggestions/type-ascription-instead-of-path.stderr b/tests/ui/suggestions/type-ascription-instead-of-path.stderr index 8c16acff7994..a8364611b50c 100644 --- a/tests/ui/suggestions/type-ascription-instead-of-path.stderr +++ b/tests/ui/suggestions/type-ascription-instead-of-path.stderr @@ -4,7 +4,6 @@ error: path separator must be a double colon LL | std:io::stdin(); | ^ | - = note: if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 help: use a double colon instead | LL | std::io::stdin(); diff --git a/tests/ui/suggestions/type-ascription-instead-of-variant.stderr b/tests/ui/suggestions/type-ascription-instead-of-variant.stderr index f0b31722e40e..e836b37c100d 100644 --- a/tests/ui/suggestions/type-ascription-instead-of-variant.stderr +++ b/tests/ui/suggestions/type-ascription-instead-of-variant.stderr @@ -4,7 +4,6 @@ error: path separator must be a double colon LL | let _ = Option:Some(""); | ^ | - = note: if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 help: use a double colon instead | LL | let _ = Option::Some(""); diff --git a/tests/ui/type/ascription/issue-47666.stderr b/tests/ui/type/ascription/issue-47666.stderr index fd825e86675d..6568845fe5de 100644 --- a/tests/ui/type/ascription/issue-47666.stderr +++ b/tests/ui/type/ascription/issue-47666.stderr @@ -4,7 +4,6 @@ error: path separator must be a double colon LL | let _ = Option:Some(vec![0, 1]); | ^ | - = note: if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 help: use a double colon instead | LL | let _ = Option::Some(vec![0, 1]); diff --git a/tests/ui/type/ascription/issue-54516.stderr b/tests/ui/type/ascription/issue-54516.stderr index 64fdc1fa24a6..925080e9050b 100644 --- a/tests/ui/type/ascription/issue-54516.stderr +++ b/tests/ui/type/ascription/issue-54516.stderr @@ -4,7 +4,6 @@ error: path separator must be a double colon LL | println!("{}", std::mem:size_of::>()); | ^ | - = note: if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 help: use a double colon instead | LL | println!("{}", std::mem::size_of::>()); diff --git a/tests/ui/type/ascription/issue-60933.stderr b/tests/ui/type/ascription/issue-60933.stderr index c68394d0504a..7b55935b35ba 100644 --- a/tests/ui/type/ascription/issue-60933.stderr +++ b/tests/ui/type/ascription/issue-60933.stderr @@ -4,7 +4,6 @@ error: path separator must be a double colon LL | let _: usize = std::mem:size_of::(); | ^ | - = note: if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 help: use a double colon instead | LL | let _: usize = std::mem::size_of::(); diff --git a/tests/ui/type/missing-let-in-binding.stderr b/tests/ui/type/missing-let-in-binding.stderr index a9d766e4c3cf..dee3d56dc51e 100644 --- a/tests/ui/type/missing-let-in-binding.stderr +++ b/tests/ui/type/missing-let-in-binding.stderr @@ -4,7 +4,6 @@ error: expected identifier, found `:` LL | _foo: i32 = 4; | ^ expected identifier | - = note: type ascription syntax has been removed, see issue #101728 help: you might have meant to introduce a new binding | LL | let _foo: i32 = 4; diff --git a/tests/ui/type/type-ascription-instead-of-statement-end.stderr b/tests/ui/type/type-ascription-instead-of-statement-end.stderr index 34759b413d89..82b7fd23a4d9 100644 --- a/tests/ui/type/type-ascription-instead-of-statement-end.stderr +++ b/tests/ui/type/type-ascription-instead-of-statement-end.stderr @@ -4,7 +4,6 @@ error: statements are terminated with a semicolon LL | println!("test"): | ^ | - = note: if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 help: use a semicolon instead | LL - println!("test"): diff --git a/tests/ui/type/type-ascription-precedence.stderr b/tests/ui/type/type-ascription-precedence.stderr index 09cdc370309d..f7ae612ef60f 100644 --- a/tests/ui/type/type-ascription-precedence.stderr +++ b/tests/ui/type/type-ascription-precedence.stderr @@ -33,8 +33,6 @@ error: expected identifier, found `:` | LL | S .. S: S; | ^ expected identifier - | - = note: type ascription syntax has been removed, see issue #101728 error: expected one of `.`, `;`, `?`, `}`, or an operator, found `:` --> $DIR/type-ascription-precedence.rs:53:13 diff --git a/tests/ui/type/type-ascription-with-fn-call.stderr b/tests/ui/type/type-ascription-with-fn-call.stderr index 4222762373dc..803c9f1c302e 100644 --- a/tests/ui/type/type-ascription-with-fn-call.stderr +++ b/tests/ui/type/type-ascription-with-fn-call.stderr @@ -4,7 +4,6 @@ error: statements are terminated with a semicolon LL | f() : | ^ | - = note: if you meant to annotate an expression with a type, the type ascription syntax has been removed, see issue #101728 help: use a semicolon instead | LL - f() : From face4716ee0015c489c3108b9180d81865aca4b6 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 16 Apr 2025 14:48:20 +0200 Subject: [PATCH 522/606] replace some #[rustc_intrinsic] usage with use of the libcore declarations --- tests/codegen/intrinsic-no-unnamed-attr.rs | 5 +-- tests/ui/intrinsics/intrinsic-atomics.rs | 51 +--------------------- 2 files changed, 4 insertions(+), 52 deletions(-) diff --git a/tests/codegen/intrinsic-no-unnamed-attr.rs b/tests/codegen/intrinsic-no-unnamed-attr.rs index 35eb025ab6bb..4bec579831dc 100644 --- a/tests/codegen/intrinsic-no-unnamed-attr.rs +++ b/tests/codegen/intrinsic-no-unnamed-attr.rs @@ -1,9 +1,8 @@ //@ compile-flags: -C no-prepopulate-passes -#![feature(intrinsics)] +#![feature(core_intrinsics)] -#[rustc_intrinsic] -unsafe fn sqrtf32(x: f32) -> f32; +use std::intrinsics::sqrtf32; // CHECK: @llvm.sqrt.f32(float) #{{[0-9]*}} diff --git a/tests/ui/intrinsics/intrinsic-atomics.rs b/tests/ui/intrinsics/intrinsic-atomics.rs index 6bc3f8d884db..9127cc649e66 100644 --- a/tests/ui/intrinsics/intrinsic-atomics.rs +++ b/tests/ui/intrinsics/intrinsic-atomics.rs @@ -1,53 +1,6 @@ //@ run-pass -#![feature(intrinsics)] - -mod rusti { - - #[rustc_intrinsic] - pub unsafe fn atomic_cxchg_seqcst_seqcst(dst: *mut T, old: T, src: T) -> (T, bool); - #[rustc_intrinsic] - pub unsafe fn atomic_cxchg_acquire_acquire(dst: *mut T, old: T, src: T) -> (T, bool); - #[rustc_intrinsic] - pub unsafe fn atomic_cxchg_release_relaxed(dst: *mut T, old: T, src: T) -> (T, bool); - - #[rustc_intrinsic] - pub unsafe fn atomic_cxchgweak_seqcst_seqcst(dst: *mut T, old: T, src: T) -> (T, bool); - #[rustc_intrinsic] - pub unsafe fn atomic_cxchgweak_acquire_acquire(dst: *mut T, old: T, src: T) -> (T, bool); - #[rustc_intrinsic] - pub unsafe fn atomic_cxchgweak_release_relaxed(dst: *mut T, old: T, src: T) -> (T, bool); - - #[rustc_intrinsic] - pub unsafe fn atomic_load_seqcst(src: *const T) -> T; - #[rustc_intrinsic] - pub unsafe fn atomic_load_acquire(src: *const T) -> T; - - #[rustc_intrinsic] - pub unsafe fn atomic_store_seqcst(dst: *mut T, val: T); - #[rustc_intrinsic] - pub unsafe fn atomic_store_release(dst: *mut T, val: T); - - #[rustc_intrinsic] - pub unsafe fn atomic_xchg_seqcst(dst: *mut T, src: T) -> T; - #[rustc_intrinsic] - pub unsafe fn atomic_xchg_acquire(dst: *mut T, src: T) -> T; - #[rustc_intrinsic] - pub unsafe fn atomic_xchg_release(dst: *mut T, src: T) -> T; - - #[rustc_intrinsic] - pub unsafe fn atomic_xadd_seqcst(dst: *mut T, src: T) -> T; - #[rustc_intrinsic] - pub unsafe fn atomic_xadd_acquire(dst: *mut T, src: T) -> T; - #[rustc_intrinsic] - pub unsafe fn atomic_xadd_release(dst: *mut T, src: T) -> T; - - #[rustc_intrinsic] - pub unsafe fn atomic_xsub_seqcst(dst: *mut T, src: T) -> T; - #[rustc_intrinsic] - pub unsafe fn atomic_xsub_acquire(dst: *mut T, src: T) -> T; - #[rustc_intrinsic] - pub unsafe fn atomic_xsub_release(dst: *mut T, src: T) -> T; -} +#![feature(core_intrinsics)] +use std::intrinsics as rusti; pub fn main() { unsafe { From 299877e280bbe02f0170742396c38ab0b20bab59 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 16 Apr 2025 14:52:08 +0200 Subject: [PATCH 523/606] Update stdarch submodule --- library/stdarch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/stdarch b/library/stdarch index 9426bb56586c..4666c7376f25 160000 --- a/library/stdarch +++ b/library/stdarch @@ -1 +1 @@ -Subproject commit 9426bb56586c6ae4095a2dcbd66c570253e6fb32 +Subproject commit 4666c7376f25a265c74535585d622da3da6dfeb1 From 7ce21e4fb39e9d288f3fe96ad48f8bc8ec973588 Mon Sep 17 00:00:00 2001 From: Spencer Date: Tue, 15 Apr 2025 20:04:04 -0600 Subject: [PATCH 524/606] Cleaned up base tests for `isize` and `usize` in `tests/ui/numbers-arithmetic` --- tests/ui/numbers-arithmetic/int.rs | 6 ------ tests/ui/numbers-arithmetic/isize-base.rs | 25 +++++++++++++++++++++++ tests/ui/numbers-arithmetic/uint.rs | 6 ------ tests/ui/numbers-arithmetic/usize-base.rs | 25 +++++++++++++++++++++++ 4 files changed, 50 insertions(+), 12 deletions(-) delete mode 100644 tests/ui/numbers-arithmetic/int.rs create mode 100644 tests/ui/numbers-arithmetic/isize-base.rs delete mode 100644 tests/ui/numbers-arithmetic/uint.rs create mode 100644 tests/ui/numbers-arithmetic/usize-base.rs diff --git a/tests/ui/numbers-arithmetic/int.rs b/tests/ui/numbers-arithmetic/int.rs deleted file mode 100644 index 42f8e50d6efa..000000000000 --- a/tests/ui/numbers-arithmetic/int.rs +++ /dev/null @@ -1,6 +0,0 @@ -//@ run-pass - - - - -pub fn main() { let _x: isize = 10; } diff --git a/tests/ui/numbers-arithmetic/isize-base.rs b/tests/ui/numbers-arithmetic/isize-base.rs new file mode 100644 index 000000000000..412e7ac7a2e9 --- /dev/null +++ b/tests/ui/numbers-arithmetic/isize-base.rs @@ -0,0 +1,25 @@ +//! Tests basic `isize` functionality + +//@ run-pass + +pub fn main() { + // Literal matches assignment type + let a: isize = 42isize; + // Literal cast + let b: isize = 42 as isize; + // Literal type inference from assignment type + let c: isize = 42; + // Assignment type inference from literal (and later comparison) + let d = 42isize; + // Function return value type inference + let e = return_val(); + + assert_eq!(a, b); + assert_eq!(a, c); + assert_eq!(a, d); + assert_eq!(a, e); +} + +fn return_val() -> isize { + 42 +} diff --git a/tests/ui/numbers-arithmetic/uint.rs b/tests/ui/numbers-arithmetic/uint.rs deleted file mode 100644 index c2087b5a06c6..000000000000 --- a/tests/ui/numbers-arithmetic/uint.rs +++ /dev/null @@ -1,6 +0,0 @@ -//@ run-pass - - - - -pub fn main() { let _x: usize = 10 as usize; } diff --git a/tests/ui/numbers-arithmetic/usize-base.rs b/tests/ui/numbers-arithmetic/usize-base.rs new file mode 100644 index 000000000000..833fc0497989 --- /dev/null +++ b/tests/ui/numbers-arithmetic/usize-base.rs @@ -0,0 +1,25 @@ +//! Tests basic `usize` functionality + +//@ run-pass + +pub fn main() { + // Literal matches assignment type + let a: usize = 42usize; + // Literal cast + let b: usize = 42 as usize; + // Literal type inference from assignment type + let c: usize = 42; + // Assignment type inference from literal (and later comparison) + let d = 42usize; + // Function return value type inference + let e = return_val(); + + assert_eq!(a, b); + assert_eq!(a, c); + assert_eq!(a, d); + assert_eq!(a, e); +} + +fn return_val() -> usize { + 42 +} From a870bba0d6b7b304e819ab820900496425ace96b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Wed, 16 Apr 2025 17:38:37 +0200 Subject: [PATCH 525/606] Add a warning when combining LLD with external LLVM config --- src/bootstrap/src/core/build_steps/compile.rs | 2 +- src/bootstrap/src/core/config/config.rs | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index f78539b47816..6a5b38dd5043 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -155,7 +155,7 @@ impl Step for Std { // When using `download-rustc`, we already have artifacts for the host available. Don't // recompile them. - if builder.download_rustc() && builder.config.is_builder_target(target) + if builder.download_rustc() && builder.config.is_host_target(target) // NOTE: the beta compiler may generate different artifacts than the downloaded compiler, so // its artifacts can't be reused. && compiler.stage != 0 diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 12e157a34ae3..1668443b04d8 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -2397,6 +2397,12 @@ impl Config { ); } + if config.lld_enabled && config.is_system_llvm(config.build) { + eprintln!( + "Warning: LLD is enabled when using external llvm-config. LLD will not be built and copied to the sysroot." + ); + } + let default_std_features = BTreeSet::from([String::from("panic-unwind")]); config.rust_std_features = std_features.unwrap_or(default_std_features); From 96984c014962cbdb760dfbf12fddec51fe0a722b Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Tue, 15 Apr 2025 18:26:16 +0530 Subject: [PATCH 526/606] add retry support to recursive_remove --- src/build_helper/src/fs/mod.rs | 50 +++++++++++++++++++++++++------- src/build_helper/src/fs/tests.rs | 2 +- 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/src/build_helper/src/fs/mod.rs b/src/build_helper/src/fs/mod.rs index 02029846fd14..a7ddc0dba864 100644 --- a/src/build_helper/src/fs/mod.rs +++ b/src/build_helper/src/fs/mod.rs @@ -22,21 +22,27 @@ where /// A wrapper around [`std::fs::remove_dir_all`] that can also be used on *non-directory entries*, /// including files and symbolic links. /// -/// - This will produce an error if the target path is not found. +/// - This will not produce an error if the target path is not found. /// - Like [`std::fs::remove_dir_all`], this helper does not traverse symbolic links, will remove /// symbolic link itself. /// - This helper is **not** robust against races on the underlying filesystem, behavior is /// unspecified if this helper is called concurrently. /// - This helper is not robust against TOCTOU problems. /// -/// FIXME: this implementation is insufficiently robust to replace bootstrap's clean `rm_rf` -/// implementation: -/// -/// - This implementation currently does not perform retries. +/// FIXME: Audit whether this implementation is robust enough to replace bootstrap's clean `rm_rf`. #[track_caller] pub fn recursive_remove>(path: P) -> io::Result<()> { let path = path.as_ref(); - let metadata = fs::symlink_metadata(path)?; + + // If the path doesn't exist, we treat it as a successful no-op. + // From the caller's perspective, the goal is simply "ensure this file/dir is gone" — + // if it's already not there, that's a success, not an error. + let metadata = match fs::symlink_metadata(path) { + Ok(m) => m, + Err(e) if e.kind() == io::ErrorKind::NotFound => return Ok(()), + Err(e) => return Err(e), + }; + #[cfg(windows)] let is_dir_like = |meta: &fs::Metadata| { use std::os::windows::fs::FileTypeExt; @@ -45,11 +51,35 @@ pub fn recursive_remove>(path: P) -> io::Result<()> { #[cfg(not(windows))] let is_dir_like = fs::Metadata::is_dir; - if is_dir_like(&metadata) { - fs::remove_dir_all(path) - } else { - try_remove_op_set_perms(fs::remove_file, path, metadata) + const MAX_RETRIES: usize = 5; + const RETRY_DELAY_MS: u64 = 100; + + let try_remove = || { + if is_dir_like(&metadata) { + fs::remove_dir_all(path) + } else { + try_remove_op_set_perms(fs::remove_file, path, metadata.clone()) + } + }; + + // Retry deletion a few times to handle transient filesystem errors. + // This is unusual for local file operations, but it's a mitigation + // against unlikely events where malware scanners may be holding a + // file beyond our control, to give the malware scanners some opportunity + // to release their hold. + for attempt in 0..MAX_RETRIES { + match try_remove() { + Ok(()) => return Ok(()), + Err(e) if e.kind() == io::ErrorKind::NotFound => return Ok(()), + Err(_) if attempt < MAX_RETRIES - 1 => { + std::thread::sleep(std::time::Duration::from_millis(RETRY_DELAY_MS)); + continue; + } + Err(e) => return Err(e), + } } + + Ok(()) } fn try_remove_op_set_perms<'p, Op>(mut op: Op, path: &'p Path, metadata: Metadata) -> io::Result<()> diff --git a/src/build_helper/src/fs/tests.rs b/src/build_helper/src/fs/tests.rs index 1e694393127c..7ce1d8928d1c 100644 --- a/src/build_helper/src/fs/tests.rs +++ b/src/build_helper/src/fs/tests.rs @@ -14,7 +14,7 @@ mod recursive_remove_tests { let tmpdir = env::temp_dir(); let path = tmpdir.join("__INTERNAL_BOOTSTRAP_nonexistent_path"); assert!(fs::symlink_metadata(&path).is_err_and(|e| e.kind() == io::ErrorKind::NotFound)); - assert!(recursive_remove(&path).is_err_and(|e| e.kind() == io::ErrorKind::NotFound)); + assert!(recursive_remove(&path).is_ok()); } #[test] From 003d633dde66d9b3d3045cf60d9ee90e34452752 Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Tue, 15 Apr 2025 18:26:42 +0530 Subject: [PATCH 527/606] add remove_and_create_dir_all in build_helper --- src/build_helper/src/fs/mod.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/build_helper/src/fs/mod.rs b/src/build_helper/src/fs/mod.rs index a7ddc0dba864..123df76e6a2e 100644 --- a/src/build_helper/src/fs/mod.rs +++ b/src/build_helper/src/fs/mod.rs @@ -97,3 +97,9 @@ where Err(e) => Err(e), } } + +pub fn remove_and_create_dir_all>(path: P) -> io::Result<()> { + let path = path.as_ref(); + recursive_remove(path)?; + fs::create_dir_all(path) +} From d4eab8a3732cd2154b79d42fc0f1e059c6883475 Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Tue, 15 Apr 2025 19:31:16 +0530 Subject: [PATCH 528/606] remove old remove_and_create_dir_all and use build_helpers remove_and_create_dir_all --- src/tools/compiletest/src/runtest.rs | 31 ++++++++++++------- src/tools/compiletest/src/runtest/rustdoc.rs | 4 ++- .../compiletest/src/runtest/rustdoc_json.rs | 4 ++- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 24fc2ddb7410..e1a5fe523fe1 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -9,6 +9,7 @@ use std::process::{Child, Command, ExitStatus, Output, Stdio}; use std::sync::Arc; use std::{env, iter, str}; +use build_helper::fs::remove_and_create_dir_all; use camino::{Utf8Path, Utf8PathBuf}; use colored::Colorize; use regex::{Captures, Regex}; @@ -207,12 +208,6 @@ pub fn compute_stamp_hash(config: &Config) -> String { format!("{:x}", hash.finish()) } -fn remove_and_create_dir_all(path: &Utf8Path) { - let path = path.as_std_path(); - let _ = fs::remove_dir_all(path); - fs::create_dir_all(path).unwrap(); -} - #[derive(Copy, Clone, Debug)] struct TestCx<'test> { config: &'test Config, @@ -523,7 +518,9 @@ impl<'test> TestCx<'test> { let mut rustc = Command::new(&self.config.rustc_path); let out_dir = self.output_base_name().with_extension("pretty-out"); - remove_and_create_dir_all(&out_dir); + remove_and_create_dir_all(&out_dir).unwrap_or_else(|e| { + panic!("failed to remove and recreate output directory `{out_dir}`: {e}") + }); let target = if self.props.force_host { &*self.config.host } else { &*self.config.target }; @@ -1098,13 +1095,19 @@ impl<'test> TestCx<'test> { let aux_dir = self.aux_output_dir_name(); if !self.props.aux.builds.is_empty() { - remove_and_create_dir_all(&aux_dir); + remove_and_create_dir_all(&aux_dir).unwrap_or_else(|e| { + panic!("failed to remove and recreate output directory `{aux_dir}`: {e}") + }); } if !self.props.aux.bins.is_empty() { let aux_bin_dir = self.aux_bin_output_dir_name(); - remove_and_create_dir_all(&aux_dir); - remove_and_create_dir_all(&aux_bin_dir); + remove_and_create_dir_all(&aux_dir).unwrap_or_else(|e| { + panic!("failed to remove and recreate output directory `{aux_dir}`: {e}") + }); + remove_and_create_dir_all(&aux_bin_dir).unwrap_or_else(|e| { + panic!("failed to remove and recreate output directory `{aux_bin_dir}`: {e}") + }); } aux_dir @@ -1509,7 +1512,9 @@ impl<'test> TestCx<'test> { let set_mir_dump_dir = |rustc: &mut Command| { let mir_dump_dir = self.get_mir_dump_dir(); - remove_and_create_dir_all(&mir_dump_dir); + remove_and_create_dir_all(&mir_dump_dir).unwrap_or_else(|e| { + panic!("failed to remove and recreate output directory `{mir_dump_dir}`: {e}") + }); let mut dir_opt = "-Zdump-mir-dir=".to_string(); dir_opt.push_str(mir_dump_dir.as_str()); debug!("dir_opt: {:?}", dir_opt); @@ -1969,7 +1974,9 @@ impl<'test> TestCx<'test> { let suffix = self.safe_revision().map_or("nightly".into(), |path| path.to_owned() + "-nightly"); let compare_dir = output_base_dir(self.config, self.testpaths, Some(&suffix)); - remove_and_create_dir_all(&compare_dir); + remove_and_create_dir_all(&compare_dir).unwrap_or_else(|e| { + panic!("failed to remove and recreate output directory `{compare_dir}`: {e}") + }); // We need to create a new struct for the lifetimes on `config` to work. let new_rustdoc = TestCx { diff --git a/src/tools/compiletest/src/runtest/rustdoc.rs b/src/tools/compiletest/src/runtest/rustdoc.rs index 2583ae96a678..637ea833357a 100644 --- a/src/tools/compiletest/src/runtest/rustdoc.rs +++ b/src/tools/compiletest/src/runtest/rustdoc.rs @@ -7,7 +7,9 @@ impl TestCx<'_> { assert!(self.revision.is_none(), "revisions not relevant here"); let out_dir = self.output_base_dir(); - remove_and_create_dir_all(&out_dir); + remove_and_create_dir_all(&out_dir).unwrap_or_else(|e| { + panic!("failed to remove and recreate output directory `{out_dir}`: {e}") + }); let proc_res = self.document(&out_dir, &self.testpaths); if !proc_res.status.success() { diff --git a/src/tools/compiletest/src/runtest/rustdoc_json.rs b/src/tools/compiletest/src/runtest/rustdoc_json.rs index bf7eb2e109a4..9f88faca8926 100644 --- a/src/tools/compiletest/src/runtest/rustdoc_json.rs +++ b/src/tools/compiletest/src/runtest/rustdoc_json.rs @@ -9,7 +9,9 @@ impl TestCx<'_> { assert!(self.revision.is_none(), "revisions not relevant here"); let out_dir = self.output_base_dir(); - remove_and_create_dir_all(&out_dir); + remove_and_create_dir_all(&out_dir).unwrap_or_else(|e| { + panic!("failed to remove and recreate output directory `{out_dir}`: {e}") + }); let proc_res = self.document(&out_dir, &self.testpaths); if !proc_res.status.success() { From b4b9cfbbd3d06b3b025205837a6e602dcf1e311b Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 16 Apr 2025 12:40:59 -0700 Subject: [PATCH 529/606] Upgrade to `rustc-rayon-core` 0.5.1 * [Fix a race with deadlock detection](https://github.com/rust-lang/rustc-rayon/pull/15) * [Cherry-pick changes from upstream rayon-core](https://github.com/rust-lang/rustc-rayon/pull/16) - This also removes a few dependencies from rustc's tidy list. --- Cargo.lock | 6 ++---- src/tools/tidy/src/deps.rs | 3 --- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3d0e29421791..684dfbca6f15 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3199,14 +3199,12 @@ dependencies = [ [[package]] name = "rustc-rayon-core" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67668daaf00e359c126f6dcb40d652d89b458a008c8afa727a42a2d20fca0b7f" +checksum = "2f42932dcd3bcbe484b38a3ccf79b7906fac41c02d408b5b1bac26da3416efdb" dependencies = [ - "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "num_cpus", ] [[package]] diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 88c2a02798ac..13f85da46f78 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -259,7 +259,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "constant_time_eq", "cpufeatures", "crc32fast", - "crossbeam-channel", "crossbeam-deque", "crossbeam-epoch", "crossbeam-utils", @@ -294,7 +293,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "gimli", "gsgdt", "hashbrown", - "hermit-abi", "icu_list", "icu_list_data", "icu_locid", @@ -328,7 +326,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "miniz_oxide", "nix", "nu-ansi-term", - "num_cpus", "object", "odht", "once_cell", From 01cfa9aad5d8de34f968f41ef196e0cb0292a942 Mon Sep 17 00:00:00 2001 From: Obei Sideg Date: Tue, 8 Apr 2025 05:30:21 +0300 Subject: [PATCH 530/606] Add hard error for `extern` without explicit ABI --- compiler/rustc_ast_passes/messages.ftl | 4 ++++ compiler/rustc_ast_passes/src/ast_validation.rs | 12 +++++++----- compiler/rustc_ast_passes/src/errors.rs | 9 +++++++++ compiler/rustc_lint/messages.ftl | 2 +- 4 files changed, 21 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index 25944392a52a..80754a8f65a6 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -79,6 +79,10 @@ ast_passes_extern_types_cannot = `type`s inside `extern` blocks cannot have {$de .suggestion = remove the {$remove_descr} .label = `extern` block begins here +ast_passes_extern_without_abi = `extern` declarations without an explicit ABI are disallowed + .suggestion = specify an ABI + .help = prior to Rust 2024, a default ABI was inferred + ast_passes_feature_on_non_nightly = `#![feature]` may not be used on the {$channel} release channel .suggestion = remove the attribute .stable_since = the feature `{$name}` has been stable since `{$since}` and no longer requires an attribute to enable diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index dc77e7b28344..9a7b7daabbf1 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -684,7 +684,7 @@ impl<'a> AstValidator<'a> { self.dcx().emit_err(errors::PatternFnPointer { span }); }); if let Extern::Implicit(extern_span) = bfty.ext { - self.maybe_lint_missing_abi(extern_span, ty.id); + self.handle_missing_abi(extern_span, ty.id); } } TyKind::TraitObject(bounds, ..) => { @@ -717,10 +717,12 @@ impl<'a> AstValidator<'a> { } } - fn maybe_lint_missing_abi(&mut self, span: Span, id: NodeId) { + fn handle_missing_abi(&mut self, span: Span, id: NodeId) { // FIXME(davidtwco): This is a hack to detect macros which produce spans of the // call site which do not have a macro backtrace. See #61963. - if self + if span.edition().at_least_edition_future() && self.features.explicit_extern_abis() { + self.dcx().emit_err(errors::MissingAbi { span }); + } else if self .sess .source_map() .span_to_snippet(span) @@ -996,7 +998,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } if abi.is_none() { - self.maybe_lint_missing_abi(*extern_span, item.id); + self.handle_missing_abi(*extern_span, item.id); } self.with_in_extern_mod(*safety, |this| { visit::walk_item(this, item); @@ -1370,7 +1372,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { }, ) = fk { - self.maybe_lint_missing_abi(*extern_span, id); + self.handle_missing_abi(*extern_span, id); } // Functions without bodies cannot have patterns. diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 8e53e600f7ac..2373a7d223e8 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -823,3 +823,12 @@ pub(crate) struct DuplicatePreciseCapturing { #[label] pub bound2: Span, } + +#[derive(Diagnostic)] +#[diag(ast_passes_extern_without_abi)] +#[help] +pub(crate) struct MissingAbi { + #[primary_span] + #[suggestion(code = "extern \"\"", applicability = "has-placeholders")] + pub span: Span, +} diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 782d328a9510..60c183bd56b1 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -271,7 +271,7 @@ lint_expectation = this lint expectation is unfulfilled lint_extern_crate_not_idiomatic = `extern crate` is not idiomatic in the new edition .suggestion = convert it to a `use` -lint_extern_without_abi = extern declarations without an explicit ABI are deprecated +lint_extern_without_abi = `extern` declarations without an explicit ABI are deprecated .label = ABI should be specified here .suggestion = explicitly specify the {$default_abi} ABI From d17c04e4a220d6f7bf170eeb0f90498e215555fa Mon Sep 17 00:00:00 2001 From: Obei Sideg Date: Tue, 8 Apr 2025 05:31:24 +0300 Subject: [PATCH 531/606] Add test for `extern` without explicit ABI --- ...re-gate-explicit-extern-abis.current.fixed | 45 +++++++++++++++++++ ...e-gate-explicit-extern-abis.current.stderr | 22 +++++++++ ...explicit-extern-abis.current_feature.fixed | 45 +++++++++++++++++++ ...xplicit-extern-abis.current_feature.stderr | 22 +++++++++ ...ure-gate-explicit-extern-abis.future.fixed | 45 +++++++++++++++++++ ...re-gate-explicit-extern-abis.future.stderr | 22 +++++++++ ...explicit-extern-abis.future_feature.stderr | 26 +++++++++++ .../feature-gate-explicit-extern-abis.rs | 45 +++++++++++++++++++ .../suggest-libname-only-1.rs | 2 +- .../suggest-libname-only-1.stderr | 2 +- .../suggest-libname-only-2.rs | 2 +- .../suggest-libname-only-2.stderr | 2 +- .../lint/cli-lint-override.forbid_warn.stderr | 2 +- .../cli-lint-override.force_warn_deny.stderr | 2 +- tests/ui/lint/cli-lint-override.rs | 6 +-- .../lint/cli-lint-override.warn_deny.stderr | 2 +- tests/ui/parser/bad-lit-suffixes.stderr | 4 +- tests/ui/parser/lit-err-in-macro.stderr | 2 +- tests/ui/proc-macro/inner-attrs.rs | 2 +- tests/ui/proc-macro/inner-attrs.stderr | 2 +- 20 files changed, 287 insertions(+), 15 deletions(-) create mode 100644 tests/ui/feature-gates/feature-gate-explicit-extern-abis.current.fixed create mode 100644 tests/ui/feature-gates/feature-gate-explicit-extern-abis.current.stderr create mode 100644 tests/ui/feature-gates/feature-gate-explicit-extern-abis.current_feature.fixed create mode 100644 tests/ui/feature-gates/feature-gate-explicit-extern-abis.current_feature.stderr create mode 100644 tests/ui/feature-gates/feature-gate-explicit-extern-abis.future.fixed create mode 100644 tests/ui/feature-gates/feature-gate-explicit-extern-abis.future.stderr create mode 100644 tests/ui/feature-gates/feature-gate-explicit-extern-abis.future_feature.stderr create mode 100644 tests/ui/feature-gates/feature-gate-explicit-extern-abis.rs diff --git a/tests/ui/feature-gates/feature-gate-explicit-extern-abis.current.fixed b/tests/ui/feature-gates/feature-gate-explicit-extern-abis.current.fixed new file mode 100644 index 000000000000..525f78d162fc --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-explicit-extern-abis.current.fixed @@ -0,0 +1,45 @@ +// The purpose of this feature gate is to make something into a hard error in a +// future edition. Consequently, this test differs from most other feature gate +// tests. Instead of verifying that an error occurs when the feature gate is +// missing, it ensures that the hard error is only produced with the feature +// gate is present in the `future` edition -- and otherwise that only a warning +// is emitted. + +//@ revisions: current current_feature future future_feature + +//@ [current] run-rustfix +//@ [current] check-pass + +//@ [current_feature] run-rustfix +//@ [current_feature] check-pass + +//@ [future] edition: future +//@ [future] compile-flags: -Z unstable-options +//@ [future] run-rustfix +//@ [future] check-pass + +//@ [future_feature] edition: future +//@ [future_feature] compile-flags: -Z unstable-options + +#![cfg_attr(future_feature, feature(explicit_extern_abis))] +#![cfg_attr(current_feature, feature(explicit_extern_abis))] + +extern "C" fn _foo() {} +//[current]~^ WARN `extern` declarations without an explicit ABI are deprecated +//[current_feature]~^^ WARN `extern` declarations without an explicit ABI are deprecated +//[future]~^^^ WARN `extern` declarations without an explicit ABI are deprecated +//[future_feature]~^^^^ ERROR `extern` declarations without an explicit ABI are disallowed + +unsafe extern "C" fn _bar() {} +//[current]~^ WARN `extern` declarations without an explicit ABI are deprecated +//[current_feature]~^^ WARN `extern` declarations without an explicit ABI are deprecated +//[future]~^^^ WARN `extern` declarations without an explicit ABI are deprecated +//[future_feature]~^^^^ ERROR `extern` declarations without an explicit ABI are disallowed + +unsafe extern "C" {} +//[current]~^ WARN `extern` declarations without an explicit ABI are deprecated +//[current_feature]~^^ WARN `extern` declarations without an explicit ABI are deprecated +//[future]~^^^ WARN `extern` declarations without an explicit ABI are deprecated +//[future_feature]~^^^^ ERROR `extern` declarations without an explicit ABI are disallowed + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-explicit-extern-abis.current.stderr b/tests/ui/feature-gates/feature-gate-explicit-extern-abis.current.stderr new file mode 100644 index 000000000000..cf927807c7c3 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-explicit-extern-abis.current.stderr @@ -0,0 +1,22 @@ +warning: `extern` declarations without an explicit ABI are deprecated + --> $DIR/feature-gate-explicit-extern-abis.rs:27:1 + | +LL | extern fn _foo() {} + | ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"` + | + = note: `#[warn(missing_abi)]` on by default + +warning: `extern` declarations without an explicit ABI are deprecated + --> $DIR/feature-gate-explicit-extern-abis.rs:33:8 + | +LL | unsafe extern fn _bar() {} + | ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"` + +warning: `extern` declarations without an explicit ABI are deprecated + --> $DIR/feature-gate-explicit-extern-abis.rs:39:8 + | +LL | unsafe extern {} + | ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"` + +warning: 3 warnings emitted + diff --git a/tests/ui/feature-gates/feature-gate-explicit-extern-abis.current_feature.fixed b/tests/ui/feature-gates/feature-gate-explicit-extern-abis.current_feature.fixed new file mode 100644 index 000000000000..525f78d162fc --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-explicit-extern-abis.current_feature.fixed @@ -0,0 +1,45 @@ +// The purpose of this feature gate is to make something into a hard error in a +// future edition. Consequently, this test differs from most other feature gate +// tests. Instead of verifying that an error occurs when the feature gate is +// missing, it ensures that the hard error is only produced with the feature +// gate is present in the `future` edition -- and otherwise that only a warning +// is emitted. + +//@ revisions: current current_feature future future_feature + +//@ [current] run-rustfix +//@ [current] check-pass + +//@ [current_feature] run-rustfix +//@ [current_feature] check-pass + +//@ [future] edition: future +//@ [future] compile-flags: -Z unstable-options +//@ [future] run-rustfix +//@ [future] check-pass + +//@ [future_feature] edition: future +//@ [future_feature] compile-flags: -Z unstable-options + +#![cfg_attr(future_feature, feature(explicit_extern_abis))] +#![cfg_attr(current_feature, feature(explicit_extern_abis))] + +extern "C" fn _foo() {} +//[current]~^ WARN `extern` declarations without an explicit ABI are deprecated +//[current_feature]~^^ WARN `extern` declarations without an explicit ABI are deprecated +//[future]~^^^ WARN `extern` declarations without an explicit ABI are deprecated +//[future_feature]~^^^^ ERROR `extern` declarations without an explicit ABI are disallowed + +unsafe extern "C" fn _bar() {} +//[current]~^ WARN `extern` declarations without an explicit ABI are deprecated +//[current_feature]~^^ WARN `extern` declarations without an explicit ABI are deprecated +//[future]~^^^ WARN `extern` declarations without an explicit ABI are deprecated +//[future_feature]~^^^^ ERROR `extern` declarations without an explicit ABI are disallowed + +unsafe extern "C" {} +//[current]~^ WARN `extern` declarations without an explicit ABI are deprecated +//[current_feature]~^^ WARN `extern` declarations without an explicit ABI are deprecated +//[future]~^^^ WARN `extern` declarations without an explicit ABI are deprecated +//[future_feature]~^^^^ ERROR `extern` declarations without an explicit ABI are disallowed + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-explicit-extern-abis.current_feature.stderr b/tests/ui/feature-gates/feature-gate-explicit-extern-abis.current_feature.stderr new file mode 100644 index 000000000000..cf927807c7c3 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-explicit-extern-abis.current_feature.stderr @@ -0,0 +1,22 @@ +warning: `extern` declarations without an explicit ABI are deprecated + --> $DIR/feature-gate-explicit-extern-abis.rs:27:1 + | +LL | extern fn _foo() {} + | ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"` + | + = note: `#[warn(missing_abi)]` on by default + +warning: `extern` declarations without an explicit ABI are deprecated + --> $DIR/feature-gate-explicit-extern-abis.rs:33:8 + | +LL | unsafe extern fn _bar() {} + | ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"` + +warning: `extern` declarations without an explicit ABI are deprecated + --> $DIR/feature-gate-explicit-extern-abis.rs:39:8 + | +LL | unsafe extern {} + | ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"` + +warning: 3 warnings emitted + diff --git a/tests/ui/feature-gates/feature-gate-explicit-extern-abis.future.fixed b/tests/ui/feature-gates/feature-gate-explicit-extern-abis.future.fixed new file mode 100644 index 000000000000..525f78d162fc --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-explicit-extern-abis.future.fixed @@ -0,0 +1,45 @@ +// The purpose of this feature gate is to make something into a hard error in a +// future edition. Consequently, this test differs from most other feature gate +// tests. Instead of verifying that an error occurs when the feature gate is +// missing, it ensures that the hard error is only produced with the feature +// gate is present in the `future` edition -- and otherwise that only a warning +// is emitted. + +//@ revisions: current current_feature future future_feature + +//@ [current] run-rustfix +//@ [current] check-pass + +//@ [current_feature] run-rustfix +//@ [current_feature] check-pass + +//@ [future] edition: future +//@ [future] compile-flags: -Z unstable-options +//@ [future] run-rustfix +//@ [future] check-pass + +//@ [future_feature] edition: future +//@ [future_feature] compile-flags: -Z unstable-options + +#![cfg_attr(future_feature, feature(explicit_extern_abis))] +#![cfg_attr(current_feature, feature(explicit_extern_abis))] + +extern "C" fn _foo() {} +//[current]~^ WARN `extern` declarations without an explicit ABI are deprecated +//[current_feature]~^^ WARN `extern` declarations without an explicit ABI are deprecated +//[future]~^^^ WARN `extern` declarations without an explicit ABI are deprecated +//[future_feature]~^^^^ ERROR `extern` declarations without an explicit ABI are disallowed + +unsafe extern "C" fn _bar() {} +//[current]~^ WARN `extern` declarations without an explicit ABI are deprecated +//[current_feature]~^^ WARN `extern` declarations without an explicit ABI are deprecated +//[future]~^^^ WARN `extern` declarations without an explicit ABI are deprecated +//[future_feature]~^^^^ ERROR `extern` declarations without an explicit ABI are disallowed + +unsafe extern "C" {} +//[current]~^ WARN `extern` declarations without an explicit ABI are deprecated +//[current_feature]~^^ WARN `extern` declarations without an explicit ABI are deprecated +//[future]~^^^ WARN `extern` declarations without an explicit ABI are deprecated +//[future_feature]~^^^^ ERROR `extern` declarations without an explicit ABI are disallowed + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-explicit-extern-abis.future.stderr b/tests/ui/feature-gates/feature-gate-explicit-extern-abis.future.stderr new file mode 100644 index 000000000000..cf927807c7c3 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-explicit-extern-abis.future.stderr @@ -0,0 +1,22 @@ +warning: `extern` declarations without an explicit ABI are deprecated + --> $DIR/feature-gate-explicit-extern-abis.rs:27:1 + | +LL | extern fn _foo() {} + | ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"` + | + = note: `#[warn(missing_abi)]` on by default + +warning: `extern` declarations without an explicit ABI are deprecated + --> $DIR/feature-gate-explicit-extern-abis.rs:33:8 + | +LL | unsafe extern fn _bar() {} + | ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"` + +warning: `extern` declarations without an explicit ABI are deprecated + --> $DIR/feature-gate-explicit-extern-abis.rs:39:8 + | +LL | unsafe extern {} + | ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"` + +warning: 3 warnings emitted + diff --git a/tests/ui/feature-gates/feature-gate-explicit-extern-abis.future_feature.stderr b/tests/ui/feature-gates/feature-gate-explicit-extern-abis.future_feature.stderr new file mode 100644 index 000000000000..096a6f434169 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-explicit-extern-abis.future_feature.stderr @@ -0,0 +1,26 @@ +error: `extern` declarations without an explicit ABI are disallowed + --> $DIR/feature-gate-explicit-extern-abis.rs:27:1 + | +LL | extern fn _foo() {} + | ^^^^^^ help: specify an ABI: `extern ""` + | + = help: prior to Rust 2024, a default ABI was inferred + +error: `extern` declarations without an explicit ABI are disallowed + --> $DIR/feature-gate-explicit-extern-abis.rs:33:8 + | +LL | unsafe extern fn _bar() {} + | ^^^^^^ help: specify an ABI: `extern ""` + | + = help: prior to Rust 2024, a default ABI was inferred + +error: `extern` declarations without an explicit ABI are disallowed + --> $DIR/feature-gate-explicit-extern-abis.rs:39:8 + | +LL | unsafe extern {} + | ^^^^^^ help: specify an ABI: `extern ""` + | + = help: prior to Rust 2024, a default ABI was inferred + +error: aborting due to 3 previous errors + diff --git a/tests/ui/feature-gates/feature-gate-explicit-extern-abis.rs b/tests/ui/feature-gates/feature-gate-explicit-extern-abis.rs new file mode 100644 index 000000000000..379c45f58990 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-explicit-extern-abis.rs @@ -0,0 +1,45 @@ +// The purpose of this feature gate is to make something into a hard error in a +// future edition. Consequently, this test differs from most other feature gate +// tests. Instead of verifying that an error occurs when the feature gate is +// missing, it ensures that the hard error is only produced with the feature +// gate is present in the `future` edition -- and otherwise that only a warning +// is emitted. + +//@ revisions: current current_feature future future_feature + +//@ [current] run-rustfix +//@ [current] check-pass + +//@ [current_feature] run-rustfix +//@ [current_feature] check-pass + +//@ [future] edition: future +//@ [future] compile-flags: -Z unstable-options +//@ [future] run-rustfix +//@ [future] check-pass + +//@ [future_feature] edition: future +//@ [future_feature] compile-flags: -Z unstable-options + +#![cfg_attr(future_feature, feature(explicit_extern_abis))] +#![cfg_attr(current_feature, feature(explicit_extern_abis))] + +extern fn _foo() {} +//[current]~^ WARN `extern` declarations without an explicit ABI are deprecated +//[current_feature]~^^ WARN `extern` declarations without an explicit ABI are deprecated +//[future]~^^^ WARN `extern` declarations without an explicit ABI are deprecated +//[future_feature]~^^^^ ERROR `extern` declarations without an explicit ABI are disallowed + +unsafe extern fn _bar() {} +//[current]~^ WARN `extern` declarations without an explicit ABI are deprecated +//[current_feature]~^^ WARN `extern` declarations without an explicit ABI are deprecated +//[future]~^^^ WARN `extern` declarations without an explicit ABI are deprecated +//[future_feature]~^^^^ ERROR `extern` declarations without an explicit ABI are disallowed + +unsafe extern {} +//[current]~^ WARN `extern` declarations without an explicit ABI are deprecated +//[current_feature]~^^ WARN `extern` declarations without an explicit ABI are deprecated +//[future]~^^^ WARN `extern` declarations without an explicit ABI are deprecated +//[future_feature]~^^^^ ERROR `extern` declarations without an explicit ABI are disallowed + +fn main() {} diff --git a/tests/ui/link-native-libs/suggest-libname-only-1.rs b/tests/ui/link-native-libs/suggest-libname-only-1.rs index c69949d1fdb3..8699e4819e62 100644 --- a/tests/ui/link-native-libs/suggest-libname-only-1.rs +++ b/tests/ui/link-native-libs/suggest-libname-only-1.rs @@ -2,7 +2,7 @@ //@ compile-flags: --crate-type rlib #[link(name = "libfoo.a", kind = "static")] -extern { } //~ WARN extern declarations without an explicit ABI are deprecated +extern { } //~ WARN `extern` declarations without an explicit ABI are deprecated //~| HELP explicitly specify the "C" ABI pub fn main() { } diff --git a/tests/ui/link-native-libs/suggest-libname-only-1.stderr b/tests/ui/link-native-libs/suggest-libname-only-1.stderr index 0320294a8004..59bd99f619a0 100644 --- a/tests/ui/link-native-libs/suggest-libname-only-1.stderr +++ b/tests/ui/link-native-libs/suggest-libname-only-1.stderr @@ -1,4 +1,4 @@ -warning: extern declarations without an explicit ABI are deprecated +warning: `extern` declarations without an explicit ABI are deprecated --> $DIR/suggest-libname-only-1.rs:5:1 | LL | extern { } diff --git a/tests/ui/link-native-libs/suggest-libname-only-2.rs b/tests/ui/link-native-libs/suggest-libname-only-2.rs index d5150c327cd5..87373f563d09 100644 --- a/tests/ui/link-native-libs/suggest-libname-only-2.rs +++ b/tests/ui/link-native-libs/suggest-libname-only-2.rs @@ -2,7 +2,7 @@ //@ compile-flags: --crate-type rlib #[link(name = "bar.lib", kind = "static")] -extern { } //~ WARN extern declarations without an explicit ABI are deprecated +extern { } //~ WARN `extern` declarations without an explicit ABI are deprecated //~| HELP explicitly specify the "C" ABI pub fn main() { } diff --git a/tests/ui/link-native-libs/suggest-libname-only-2.stderr b/tests/ui/link-native-libs/suggest-libname-only-2.stderr index e492aea27b45..298a9ced1707 100644 --- a/tests/ui/link-native-libs/suggest-libname-only-2.stderr +++ b/tests/ui/link-native-libs/suggest-libname-only-2.stderr @@ -1,4 +1,4 @@ -warning: extern declarations without an explicit ABI are deprecated +warning: `extern` declarations without an explicit ABI are deprecated --> $DIR/suggest-libname-only-2.rs:5:1 | LL | extern { } diff --git a/tests/ui/lint/cli-lint-override.forbid_warn.stderr b/tests/ui/lint/cli-lint-override.forbid_warn.stderr index fb8779ad4f15..fe3437ae3d75 100644 --- a/tests/ui/lint/cli-lint-override.forbid_warn.stderr +++ b/tests/ui/lint/cli-lint-override.forbid_warn.stderr @@ -1,4 +1,4 @@ -error: extern declarations without an explicit ABI are deprecated +error: `extern` declarations without an explicit ABI are deprecated --> $DIR/cli-lint-override.rs:12:1 | LL | extern fn foo() {} diff --git a/tests/ui/lint/cli-lint-override.force_warn_deny.stderr b/tests/ui/lint/cli-lint-override.force_warn_deny.stderr index 10fc13e3f52f..f48fca4bd9f3 100644 --- a/tests/ui/lint/cli-lint-override.force_warn_deny.stderr +++ b/tests/ui/lint/cli-lint-override.force_warn_deny.stderr @@ -1,4 +1,4 @@ -warning: extern declarations without an explicit ABI are deprecated +warning: `extern` declarations without an explicit ABI are deprecated --> $DIR/cli-lint-override.rs:12:1 | LL | extern fn foo() {} diff --git a/tests/ui/lint/cli-lint-override.rs b/tests/ui/lint/cli-lint-override.rs index 4b3fd0d9c01c..b733872166aa 100644 --- a/tests/ui/lint/cli-lint-override.rs +++ b/tests/ui/lint/cli-lint-override.rs @@ -10,8 +10,8 @@ extern fn foo() {} -//[warn_deny]~^ ERROR extern declarations without an explicit ABI are deprecated -//[forbid_warn]~^^ ERROR extern declarations without an explicit ABI are deprecated -//[force_warn_deny]~^^^ WARN extern declarations without an explicit ABI are deprecated +//[warn_deny]~^ ERROR `extern` declarations without an explicit ABI are deprecated +//[forbid_warn]~^^ ERROR `extern` declarations without an explicit ABI are deprecated +//[force_warn_deny]~^^^ WARN `extern` declarations without an explicit ABI are deprecated fn main() {} diff --git a/tests/ui/lint/cli-lint-override.warn_deny.stderr b/tests/ui/lint/cli-lint-override.warn_deny.stderr index 979ca22324f1..91baad1f9f87 100644 --- a/tests/ui/lint/cli-lint-override.warn_deny.stderr +++ b/tests/ui/lint/cli-lint-override.warn_deny.stderr @@ -1,4 +1,4 @@ -error: extern declarations without an explicit ABI are deprecated +error: `extern` declarations without an explicit ABI are deprecated --> $DIR/cli-lint-override.rs:12:1 | LL | extern fn foo() {} diff --git a/tests/ui/parser/bad-lit-suffixes.stderr b/tests/ui/parser/bad-lit-suffixes.stderr index d6b50b0e0d1f..86ef35bf7833 100644 --- a/tests/ui/parser/bad-lit-suffixes.stderr +++ b/tests/ui/parser/bad-lit-suffixes.stderr @@ -51,7 +51,7 @@ LL | #[rustc_layout_scalar_valid_range_start(0suffix)] | = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.) -warning: extern declarations without an explicit ABI are deprecated +warning: `extern` declarations without an explicit ABI are deprecated --> $DIR/bad-lit-suffixes.rs:3:1 | LL | extern @@ -59,7 +59,7 @@ LL | extern | = note: `#[warn(missing_abi)]` on by default -warning: extern declarations without an explicit ABI are deprecated +warning: `extern` declarations without an explicit ABI are deprecated --> $DIR/bad-lit-suffixes.rs:7:1 | LL | extern diff --git a/tests/ui/parser/lit-err-in-macro.stderr b/tests/ui/parser/lit-err-in-macro.stderr index 9422f22f9c8f..08fe58643d40 100644 --- a/tests/ui/parser/lit-err-in-macro.stderr +++ b/tests/ui/parser/lit-err-in-macro.stderr @@ -4,7 +4,7 @@ error: suffixes on string literals are invalid LL | f!("Foo"__); | ^^^^^^^ invalid suffix `__` -warning: extern declarations without an explicit ABI are deprecated +warning: `extern` declarations without an explicit ABI are deprecated --> $DIR/lit-err-in-macro.rs:3:9 | LL | extern $abi fn f() {} diff --git a/tests/ui/proc-macro/inner-attrs.rs b/tests/ui/proc-macro/inner-attrs.rs index c541e93f9041..ca4b2029a338 100644 --- a/tests/ui/proc-macro/inner-attrs.rs +++ b/tests/ui/proc-macro/inner-attrs.rs @@ -82,7 +82,7 @@ fn bar() { } -extern { //~ WARN extern declarations without an explicit ABI are deprecated +extern { //~ WARN `extern` declarations without an explicit ABI are deprecated fn weird_extern() { #![print_target_and_args_consume(tenth)] } diff --git a/tests/ui/proc-macro/inner-attrs.stderr b/tests/ui/proc-macro/inner-attrs.stderr index 4e7825c0d007..54cccae8da08 100644 --- a/tests/ui/proc-macro/inner-attrs.stderr +++ b/tests/ui/proc-macro/inner-attrs.stderr @@ -22,7 +22,7 @@ error: expected non-macro inner attribute, found attribute macro `print_attr` LL | #![print_attr] | ^^^^^^^^^^ not a non-macro inner attribute -warning: extern declarations without an explicit ABI are deprecated +warning: `extern` declarations without an explicit ABI are deprecated --> $DIR/inner-attrs.rs:85:1 | LL | extern { From 3863018d960ad8bf6dd631f31f9d487e4a9880f1 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 16 Apr 2025 19:47:56 +0000 Subject: [PATCH 532/606] Fix replacing supertrait aliases in ReplaceProjectionWith --- .../src/solve/assembly/mod.rs | 24 +-- .../src/solve/assembly/structural_traits.rs | 157 ++++++++++++------ .../src/solve/trait_goals.rs | 2 +- .../src/solve/inspect/analyse.rs | 8 +- .../rustc_trait_selection/src/solve/select.rs | 2 +- compiler/rustc_type_ir/src/solve/inspect.rs | 10 +- .../traits/next-solver/supertrait-alias-1.rs | 22 +++ .../traits/next-solver/supertrait-alias-2.rs | 25 +++ .../traits/next-solver/supertrait-alias-3.rs | 32 ++++ .../traits/next-solver/supertrait-alias-4.rs | 24 +++ 10 files changed, 238 insertions(+), 68 deletions(-) create mode 100644 tests/ui/traits/next-solver/supertrait-alias-1.rs create mode 100644 tests/ui/traits/next-solver/supertrait-alias-2.rs create mode 100644 tests/ui/traits/next-solver/supertrait-alias-3.rs create mode 100644 tests/ui/traits/next-solver/supertrait-alias-4.rs diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index ee000b117486..83b2465d05aa 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -92,16 +92,20 @@ where let ty::Dynamic(bounds, _, _) = goal.predicate.self_ty().kind() else { panic!("expected object type in `probe_and_consider_object_bound_candidate`"); }; - ecx.add_goals( - GoalSource::ImplWhereBound, - structural_traits::predicates_for_object_candidate( - ecx, - goal.param_env, - goal.predicate.trait_ref(cx), - bounds, - ), - ); - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + match structural_traits::predicates_for_object_candidate( + ecx, + goal.param_env, + goal.predicate.trait_ref(cx), + bounds, + ) { + Ok(requirements) => { + ecx.add_goals(GoalSource::ImplWhereBound, requirements); + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + } + Err(_) => { + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) + } + } }) } diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs index c2fb592c3f3a..46ec8897fa5e 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs @@ -5,9 +5,10 @@ use derive_where::derive_where; use rustc_type_ir::data_structures::HashMap; use rustc_type_ir::inherent::*; use rustc_type_ir::lang_items::TraitSolverLangItem; +use rustc_type_ir::solve::inspect::ProbeKind; use rustc_type_ir::{ - self as ty, Interner, Movability, Mutability, TypeFoldable, TypeFolder, TypeSuperFoldable, - Upcast as _, elaborate, + self as ty, FallibleTypeFolder, Interner, Movability, Mutability, TypeFoldable, + TypeSuperFoldable, Upcast as _, elaborate, }; use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic}; use tracing::instrument; @@ -822,7 +823,7 @@ pub(in crate::solve) fn const_conditions_for_destruct( /// impl Baz for dyn Foo {} /// ``` /// -/// However, in order to make such impls well-formed, we need to do an +/// However, in order to make such impls non-cyclical, we need to do an /// additional step of eagerly folding the associated types in the where /// clauses of the impl. In this example, that means replacing /// `::Bar` with `Ty` in the first impl. @@ -833,11 +834,11 @@ pub(in crate::solve) fn const_conditions_for_destruct( // normalize eagerly here. See https://github.com/lcnr/solver-woes/issues/9 // for more details. pub(in crate::solve) fn predicates_for_object_candidate( - ecx: &EvalCtxt<'_, D>, + ecx: &mut EvalCtxt<'_, D>, param_env: I::ParamEnv, trait_ref: ty::TraitRef, object_bounds: I::BoundExistentialPredicates, -) -> Vec> +) -> Result>, Ambiguous> where D: SolverDelegate, I: Interner, @@ -871,72 +872,130 @@ where .extend(cx.item_bounds(associated_type_def_id).iter_instantiated(cx, trait_ref.args)); } - let mut replace_projection_with = HashMap::default(); + let mut replace_projection_with: HashMap<_, Vec<_>> = HashMap::default(); for bound in object_bounds.iter() { if let ty::ExistentialPredicate::Projection(proj) = bound.skip_binder() { + // FIXME: We *probably* should replace this with a dummy placeholder, + // b/c don't want to replace literal instances of this dyn type that + // show up in the bounds, but just ones that come from substituting + // `Self` with the dyn type. let proj = proj.with_self_ty(cx, trait_ref.self_ty()); - let old_ty = replace_projection_with.insert(proj.def_id(), bound.rebind(proj)); - assert_eq!( - old_ty, - None, - "{:?} has two generic parameters: {:?} and {:?}", - proj.projection_term, - proj.term, - old_ty.unwrap() - ); + replace_projection_with.entry(proj.def_id()).or_default().push(bound.rebind(proj)); } } - let mut folder = - ReplaceProjectionWith { ecx, param_env, mapping: replace_projection_with, nested: vec![] }; - let folded_requirements = requirements.fold_with(&mut folder); + let mut folder = ReplaceProjectionWith { + ecx, + param_env, + self_ty: trait_ref.self_ty(), + mapping: &replace_projection_with, + nested: vec![], + }; - folder + let requirements = requirements.try_fold_with(&mut folder)?; + Ok(folder .nested .into_iter() - .chain(folded_requirements.into_iter().map(|clause| Goal::new(cx, param_env, clause))) - .collect() + .chain(requirements.into_iter().map(|clause| Goal::new(cx, param_env, clause))) + .collect()) } -struct ReplaceProjectionWith<'a, D: SolverDelegate, I: Interner> { - ecx: &'a EvalCtxt<'a, D>, +struct ReplaceProjectionWith<'a, 'b, I: Interner, D: SolverDelegate> { + ecx: &'a mut EvalCtxt<'b, D>, param_env: I::ParamEnv, - mapping: HashMap>>, + self_ty: I::Ty, + mapping: &'a HashMap>>>, nested: Vec>, } -impl, I: Interner> TypeFolder - for ReplaceProjectionWith<'_, D, I> +impl ReplaceProjectionWith<'_, '_, I, D> +where + D: SolverDelegate, + I: Interner, { + fn projection_may_match( + &mut self, + source_projection: ty::Binder>, + target_projection: ty::AliasTerm, + ) -> bool { + source_projection.item_def_id() == target_projection.def_id + && self + .ecx + .probe(|_| ProbeKind::ProjectionCompatibility) + .enter(|ecx| -> Result<_, NoSolution> { + let source_projection = ecx.instantiate_binder_with_infer(source_projection); + ecx.eq(self.param_env, source_projection.projection_term, target_projection)?; + ecx.try_evaluate_added_goals() + }) + .is_ok() + } + + /// Try to replace an alias with the term present in the projection bounds of the self type. + /// Returns `Ok` if this alias is not eligible to be replaced, or bail with + /// `Err(Ambiguous)` if it's uncertain which projection bound to replace the term with due + /// to multiple bounds applying. + fn try_eagerly_replace_alias( + &mut self, + alias_term: ty::AliasTerm, + ) -> Result, Ambiguous> { + if alias_term.self_ty() != self.self_ty { + return Ok(None); + } + + let Some(replacements) = self.mapping.get(&alias_term.def_id) else { + return Ok(None); + }; + + // This is quite similar to the `projection_may_match` we use in unsizing, + // but here we want to unify a projection predicate against an alias term + // so we can replace it with the the projection predicate's term. + let mut matching_projections = replacements + .iter() + .filter(|source_projection| self.projection_may_match(**source_projection, alias_term)); + let Some(replacement) = matching_projections.next() else { + // This shouldn't happen. + panic!("could not replace {alias_term:?} with term from from {:?}", self.self_ty); + }; + // FIXME: This *may* have issues with duplicated projections. + if matching_projections.next().is_some() { + // If there's more than one projection that we can unify here, then we + // need to stall until inference constrains things so that there's only + // one choice. + return Err(Ambiguous); + } + + let replacement = self.ecx.instantiate_binder_with_infer(*replacement); + self.nested.extend( + self.ecx + .eq_and_get_goals(self.param_env, alias_term, replacement.projection_term) + .expect("expected to be able to unify goal projection with dyn's projection"), + ); + + Ok(Some(replacement.term)) + } +} + +/// Marker for bailing with ambiguity. +pub(crate) struct Ambiguous; + +impl FallibleTypeFolder for ReplaceProjectionWith<'_, '_, I, D> +where + D: SolverDelegate, + I: Interner, +{ + type Error = Ambiguous; + fn cx(&self) -> I { self.ecx.cx() } - fn fold_ty(&mut self, ty: I::Ty) -> I::Ty { + fn try_fold_ty(&mut self, ty: I::Ty) -> Result { if let ty::Alias(ty::Projection, alias_ty) = ty.kind() { - if let Some(replacement) = self.mapping.get(&alias_ty.def_id) { - // We may have a case where our object type's projection bound is higher-ranked, - // but the where clauses we instantiated are not. We can solve this by instantiating - // the binder at the usage site. - let proj = self.ecx.instantiate_binder_with_infer(*replacement); - // FIXME: Technically this equate could be fallible... - self.nested.extend( - self.ecx - .eq_and_get_goals( - self.param_env, - alias_ty, - proj.projection_term.expect_ty(self.ecx.cx()), - ) - .expect( - "expected to be able to unify goal projection with dyn's projection", - ), - ); - proj.term.expect_ty() - } else { - ty.super_fold_with(self) + if let Some(term) = self.try_eagerly_replace_alias(alias_ty.into())? { + return Ok(term.expect_ty()); } - } else { - ty.super_fold_with(self) } + + ty.try_super_fold_with(self) } } diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 9262da2906d0..409af8568d7a 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -944,7 +944,7 @@ where target_projection: ty::Binder>| { source_projection.item_def_id() == target_projection.item_def_id() && ecx - .probe(|_| ProbeKind::UpcastProjectionCompatibility) + .probe(|_| ProbeKind::ProjectionCompatibility) .enter(|ecx| -> Result<_, NoSolution> { ecx.enter_forall(target_projection, |ecx, target_projection| { let source_projection = diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index 48a05ad29fbd..24b87000e32b 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -292,7 +292,7 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { inspect::ProbeStep::NestedProbe(ref probe) => { match probe.kind { // These never assemble candidates for the goal we're trying to solve. - inspect::ProbeKind::UpcastProjectionCompatibility + inspect::ProbeKind::ProjectionCompatibility | inspect::ProbeKind::ShadowedEnvProbing => continue, inspect::ProbeKind::NormalizedSelfTyAssembly @@ -314,8 +314,10 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { } match probe.kind { - inspect::ProbeKind::UpcastProjectionCompatibility - | inspect::ProbeKind::ShadowedEnvProbing => bug!(), + inspect::ProbeKind::ProjectionCompatibility + | inspect::ProbeKind::ShadowedEnvProbing => { + bug!() + } inspect::ProbeKind::NormalizedSelfTyAssembly | inspect::ProbeKind::UnsizeAssembly => {} diff --git a/compiler/rustc_trait_selection/src/solve/select.rs b/compiler/rustc_trait_selection/src/solve/select.rs index 4437fc5b0295..4fdaf740287b 100644 --- a/compiler/rustc_trait_selection/src/solve/select.rs +++ b/compiler/rustc_trait_selection/src/solve/select.rs @@ -177,7 +177,7 @@ fn to_selection<'tcx>( }, ProbeKind::NormalizedSelfTyAssembly | ProbeKind::UnsizeAssembly - | ProbeKind::UpcastProjectionCompatibility + | ProbeKind::ProjectionCompatibility | ProbeKind::OpaqueTypeStorageLookup { result: _ } | ProbeKind::Root { result: _ } | ProbeKind::ShadowedEnvProbing diff --git a/compiler/rustc_type_ir/src/solve/inspect.rs b/compiler/rustc_type_ir/src/solve/inspect.rs index 18fb71dd290e..b10641b287d4 100644 --- a/compiler/rustc_type_ir/src/solve/inspect.rs +++ b/compiler/rustc_type_ir/src/solve/inspect.rs @@ -118,10 +118,12 @@ pub enum ProbeKind { /// Used in the probe that wraps normalizing the non-self type for the unsize /// trait, which is also structurally matched on. UnsizeAssembly, - /// During upcasting from some source object to target object type, used to - /// do a probe to find out what projection type(s) may be used to prove that - /// the source type upholds all of the target type's object bounds. - UpcastProjectionCompatibility, + /// Used to do a probe to find out what projection type(s) match a given + /// alias bound or projection predicate. For trait upcasting, this is used + /// to prove that the source type upholds all of the target type's object + /// bounds. For object type bounds, this is used when eagerly replacing + /// supertrait aliases. + ProjectionCompatibility, /// Looking for param-env candidates that satisfy the trait ref for a projection. ShadowedEnvProbing, /// Try to unify an opaque type with an existing key in the storage. diff --git a/tests/ui/traits/next-solver/supertrait-alias-1.rs b/tests/ui/traits/next-solver/supertrait-alias-1.rs new file mode 100644 index 000000000000..579a44677c2e --- /dev/null +++ b/tests/ui/traits/next-solver/supertrait-alias-1.rs @@ -0,0 +1,22 @@ +//@ compile-flags: -Znext-solver +//@ check-pass + +// Regression test for . +// Tests that we don't try to replace `::Output` when replacing projections in the +// required bounds for `dyn Trait`, b/c `V` is not relevant to the dyn type, which we were +// previously encountering b/c we were walking into the existential projection bounds of the dyn +// type itself. + +pub trait Trait: Super {} + +pub trait Super { + type Output; +} + +fn bound() {} + +fn visit_simd_operator() { + bound::::Output>>(); +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/supertrait-alias-2.rs b/tests/ui/traits/next-solver/supertrait-alias-2.rs new file mode 100644 index 000000000000..a0f3e038dca6 --- /dev/null +++ b/tests/ui/traits/next-solver/supertrait-alias-2.rs @@ -0,0 +1,25 @@ +//@ compile-flags: -Znext-solver +//@ check-pass + +// Regression test for . +// Tests that we don't try to replace `::Assoc` when replacing projections in the +// required bounds for `dyn Foo`, b/c `T` is not relevant to the dyn type, which we were +// encountering when walking through the elaborated supertraits of `dyn Foo`. + +trait Other {} + +trait Foo>: Other<>::Assoc> { + type Assoc; +} + +impl Foo for T { + type Assoc = (); +} + +impl Other<()> for T {} + +fn is_foo + ?Sized>() {} + +fn main() { + is_foo::>(); +} diff --git a/tests/ui/traits/next-solver/supertrait-alias-3.rs b/tests/ui/traits/next-solver/supertrait-alias-3.rs new file mode 100644 index 000000000000..78182bbc4156 --- /dev/null +++ b/tests/ui/traits/next-solver/supertrait-alias-3.rs @@ -0,0 +1,32 @@ +//@ compile-flags: -Znext-solver +//@ check-pass + +// Regression test for . +// Exercises a case where structural equality is insufficient when replacing projections in a dyn's +// bounds. In this case, the bound will contain `:Assoc>::Assoc`, but +// the existential projections from the dyn will have `>::Assoc` because as an +// optimization we eagerly normalize aliases in goals. + +trait Other {} +impl Other for T {} + +trait Super { + type Assoc; +} + +trait Mirror { + type Assoc; +} +impl Mirror for T { + type Assoc = T; +} + +trait Foo: Super<::Assoc, Assoc = A> { + type FooAssoc: Other<::Assoc>>::Assoc>; +} + +fn is_foo + ?Sized, T, U>() {} + +fn main() { + is_foo::, _, _>(); +} diff --git a/tests/ui/traits/next-solver/supertrait-alias-4.rs b/tests/ui/traits/next-solver/supertrait-alias-4.rs new file mode 100644 index 000000000000..919a768fcf28 --- /dev/null +++ b/tests/ui/traits/next-solver/supertrait-alias-4.rs @@ -0,0 +1,24 @@ +//@ compile-flags: -Znext-solver +//@ check-pass + +// Exercises the ambiguity that comes from replacing the associated types within the bounds +// that are required for a `impl Trait for dyn Trait` built-in object impl to hold. + +trait Sup { + type Assoc; +} + +trait Foo: Sup + Sup { + type Other: Bar<>::Assoc>; +} + +trait Bar {} +impl Bar for () {} + +fn foo(x: &(impl Foo + ?Sized)) {} + +fn main() { + let x: &dyn Foo<_, _, Other = ()> = todo!(); + foo(x); + let y: &dyn Foo = x; +} From e1936d22ed6c686bc9f2c92634fba9246bd86b9d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 14 Apr 2025 20:57:46 +0000 Subject: [PATCH 533/606] Remove FIXME that is no longer relevant --- .../src/solve/assembly/structural_traits.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs index 46ec8897fa5e..1526049719ea 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs @@ -827,12 +827,6 @@ pub(in crate::solve) fn const_conditions_for_destruct( /// additional step of eagerly folding the associated types in the where /// clauses of the impl. In this example, that means replacing /// `::Bar` with `Ty` in the first impl. -/// -// FIXME: This is only necessary as `::Assoc: ItemBound` -// bounds in impls are trivially proven using the item bound candidates. -// This is unsound in general and once that is fixed, we don't need to -// normalize eagerly here. See https://github.com/lcnr/solver-woes/issues/9 -// for more details. pub(in crate::solve) fn predicates_for_object_candidate( ecx: &mut EvalCtxt<'_, D>, param_env: I::ParamEnv, From bb3c98165cca752ba93927f19fa3f78c48caccc7 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 16 Apr 2025 18:30:33 +0000 Subject: [PATCH 534/606] Don't require rigid alias's trait to hold --- .../src/solve/normalizes_to/mod.rs | 1 - tests/ui/coroutine/higher-ranked-rigid.rs | 41 +++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 tests/ui/coroutine/higher-ranked-rigid.rs diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index 2d027f16e5d9..fdeb276a58e6 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -45,7 +45,6 @@ where goal, goal.predicate.alias, ); - this.add_goal(GoalSource::AliasWellFormed, goal.with(cx, trait_ref)); this.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) }) diff --git a/tests/ui/coroutine/higher-ranked-rigid.rs b/tests/ui/coroutine/higher-ranked-rigid.rs new file mode 100644 index 000000000000..23a7d51300c9 --- /dev/null +++ b/tests/ui/coroutine/higher-ranked-rigid.rs @@ -0,0 +1,41 @@ +//@ edition: 2024 +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@ check-pass + +// Regression test for . +// Coroutines erase all free lifetimes from their interior types, replacing them with higher- +// ranked regions which act as universals, to properly represent the fact that we don't know what +// the value of the region is within the coroutine. +// +// In the future in `from_request`, that means that the `'r` lifetime is being replaced in +// `>::Assoc`, which is in present in the existential bounds of the +// `dyn Future` that it's awaiting. Normalizing this associated type, with its free lifetimes +// replaced, means proving `T: FromRequest<'!0>`, which doesn't hold without constraining the +// `'!0` lifetime, which we don't do today. + +// Proving `T: Trait` holds when `::Assoc` is rigid is not necessary for soundness, +// at least not *yet*, and it's not even necessary for diagnostics since we have other special +// casing for, e.g., AliasRelate goals failing in the BestObligation folder. + +// The old solver unintentioanlly avoids this by never checking that `T: Trait` holds when +// `::Assoc` is rigid. Introducing this additional requirement when projecting rigidly +// in the old solver causes this (and tons of production crates) to fail. See the fallout from the +// crater run at . + +use std::future::Future; +use std::pin::Pin; + +pub trait FromRequest<'r> { + type Assoc; + fn from_request() -> Pin + Send>>; +} + +fn test<'r, T: FromRequest<'r>>() -> Pin + Send>> { + Box::pin(async move { + T::from_request().await; + }) +} + +fn main() {} From a68ae0cbc1d923b69ef690f32b651ecf583ff27f Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Sat, 5 Apr 2025 03:10:19 -0400 Subject: [PATCH 535/606] working dupv and dupvonly for fwd mode --- .../rustc_ast/src/expand/autodiff_attrs.rs | 40 ++++++++++++------- compiler/rustc_builtin_macros/src/autodiff.rs | 23 ++++++++--- compiler/rustc_codegen_llvm/src/builder.rs | 2 +- .../src/builder/autodiff.rs | 38 +++++++++++++++--- .../src/partitioning/autodiff.rs | 32 ++++++++++++++- 5 files changed, 107 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_ast/src/expand/autodiff_attrs.rs b/compiler/rustc_ast/src/expand/autodiff_attrs.rs index 13a7c5a18057..2f918faaf752 100644 --- a/compiler/rustc_ast/src/expand/autodiff_attrs.rs +++ b/compiler/rustc_ast/src/expand/autodiff_attrs.rs @@ -50,8 +50,16 @@ pub enum DiffActivity { /// with it. Dual, /// Forward Mode, Compute derivatives for this input/output and *overwrite* the shadow argument + /// with it. It expects the shadow argument to be `width` times larger than the original + /// input/output. + Dualv, + /// Forward Mode, Compute derivatives for this input/output and *overwrite* the shadow argument /// with it. Drop the code which updates the original input/output for maximum performance. DualOnly, + /// Forward Mode, Compute derivatives for this input/output and *overwrite* the shadow argument + /// with it. Drop the code which updates the original input/output for maximum performance. + /// It expects the shadow argument to be `width` times larger than the original input/output. + DualvOnly, /// Reverse Mode, Compute derivatives for this &T or *T input and *add* it to the shadow argument. Duplicated, /// Reverse Mode, Compute derivatives for this &T or *T input and *add* it to the shadow argument. @@ -59,7 +67,15 @@ pub enum DiffActivity { DuplicatedOnly, /// All Integers must be Const, but these are used to mark the integer which represents the /// length of a slice/vec. This is used for safety checks on slices. - FakeActivitySize, + /// The integer (if given) specifies the size of the slice element in bytes. + FakeActivitySize(Option), +} + +impl DiffActivity { + pub fn is_dual_or_const(&self) -> bool { + use DiffActivity::*; + matches!(self, |Dual| DualOnly | Dualv | DualvOnly | Const) + } } /// We generate one of these structs for each `#[autodiff(...)]` attribute. #[derive(Clone, Eq, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] @@ -131,11 +147,7 @@ pub fn valid_ret_activity(mode: DiffMode, activity: DiffActivity) -> bool { match mode { DiffMode::Error => false, DiffMode::Source => false, - DiffMode::Forward => { - activity == DiffActivity::Dual - || activity == DiffActivity::DualOnly - || activity == DiffActivity::Const - } + DiffMode::Forward => activity.is_dual_or_const(), DiffMode::Reverse => { activity == DiffActivity::Const || activity == DiffActivity::Active @@ -153,10 +165,8 @@ pub fn valid_ret_activity(mode: DiffMode, activity: DiffActivity) -> bool { pub fn valid_ty_for_activity(ty: &P, activity: DiffActivity) -> bool { use DiffActivity::*; // It's always allowed to mark something as Const, since we won't compute derivatives wrt. it. - if matches!(activity, Const) { - return true; - } - if matches!(activity, Dual | DualOnly) { + // Dual variants also support all types. + if activity.is_dual_or_const() { return true; } // FIXME(ZuseZ4) We should make this more robust to also @@ -172,9 +182,7 @@ pub fn valid_input_activity(mode: DiffMode, activity: DiffActivity) -> bool { return match mode { DiffMode::Error => false, DiffMode::Source => false, - DiffMode::Forward => { - matches!(activity, Dual | DualOnly | Const) - } + DiffMode::Forward => activity.is_dual_or_const(), DiffMode::Reverse => { matches!(activity, Active | ActiveOnly | Duplicated | DuplicatedOnly | Const) } @@ -189,10 +197,12 @@ impl Display for DiffActivity { DiffActivity::Active => write!(f, "Active"), DiffActivity::ActiveOnly => write!(f, "ActiveOnly"), DiffActivity::Dual => write!(f, "Dual"), + DiffActivity::Dualv => write!(f, "Dualv"), DiffActivity::DualOnly => write!(f, "DualOnly"), + DiffActivity::DualvOnly => write!(f, "DualvOnly"), DiffActivity::Duplicated => write!(f, "Duplicated"), DiffActivity::DuplicatedOnly => write!(f, "DuplicatedOnly"), - DiffActivity::FakeActivitySize => write!(f, "FakeActivitySize"), + DiffActivity::FakeActivitySize(s) => write!(f, "FakeActivitySize({:?})", s), } } } @@ -220,7 +230,9 @@ impl FromStr for DiffActivity { "ActiveOnly" => Ok(DiffActivity::ActiveOnly), "Const" => Ok(DiffActivity::Const), "Dual" => Ok(DiffActivity::Dual), + "Dualv" => Ok(DiffActivity::Dualv), "DualOnly" => Ok(DiffActivity::DualOnly), + "DualvOnly" => Ok(DiffActivity::DualvOnly), "Duplicated" => Ok(DiffActivity::Duplicated), "DuplicatedOnly" => Ok(DiffActivity::DuplicatedOnly), _ => Err(()), diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs index 351413dea493..44ee78ebe688 100644 --- a/compiler/rustc_builtin_macros/src/autodiff.rs +++ b/compiler/rustc_builtin_macros/src/autodiff.rs @@ -799,8 +799,19 @@ mod llvm_enzyme { d_inputs.push(shadow_arg.clone()); } } - DiffActivity::Dual | DiffActivity::DualOnly => { - for i in 0..x.width { + DiffActivity::Dual + | DiffActivity::DualOnly + | DiffActivity::Dualv + | DiffActivity::DualvOnly => { + // the *v variants get lowered to enzyme_dupv and enzyme_dupnoneedv, which cause + // Enzyme to not expect N arguments, but one argument (which is instead larger). + let iterations = + if matches!(activity, DiffActivity::Dualv | DiffActivity::DualvOnly) { + 1 + } else { + x.width + }; + for i in 0..iterations { let mut shadow_arg = arg.clone(); let old_name = if let PatKind::Ident(_, ident, _) = arg.pat.kind { ident.name @@ -823,7 +834,7 @@ mod llvm_enzyme { DiffActivity::Const => { // Nothing to do here. } - DiffActivity::None | DiffActivity::FakeActivitySize => { + DiffActivity::None | DiffActivity::FakeActivitySize(_) => { panic!("Should not happen"); } } @@ -887,8 +898,8 @@ mod llvm_enzyme { } }; - if let DiffActivity::Dual = x.ret_activity { - let kind = if x.width == 1 { + if matches!(x.ret_activity, DiffActivity::Dual | DiffActivity::Dualv) { + let kind = if x.width == 1 || matches!(x.ret_activity, DiffActivity::Dualv) { // Dual can only be used for f32/f64 ret. // In that case we return now a tuple with two floats. TyKind::Tup(thin_vec![ty.clone(), ty.clone()]) @@ -903,7 +914,7 @@ mod llvm_enzyme { let ty = P(rustc_ast::Ty { kind, id: ty.id, span: ty.span, tokens: None }); d_decl.output = FnRetTy::Ty(ty); } - if let DiffActivity::DualOnly = x.ret_activity { + if matches!(x.ret_activity, DiffActivity::DualOnly | DiffActivity::DualvOnly) { // No need to change the return type, // we will just return the shadow in place of the primal return. // However, if we have a width > 1, then we don't return -> T, but -> [T; width] diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 35134e9f5a05..27f7f95f100e 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -123,7 +123,7 @@ impl<'a, 'll, CX: Borrow>> GenericBuilder<'a, 'll, CX> { /// Empty string, to be used where LLVM expects an instruction name, indicating /// that the instruction is to be left unnamed (i.e. numbered, in textual IR). // FIXME(eddyb) pass `&CStr` directly to FFI once it's a thin pointer. -const UNNAMED: *const c_char = c"".as_ptr(); +pub(crate) const UNNAMED: *const c_char = c"".as_ptr(); impl<'ll, CX: Borrow>> BackendTypes for GenericBuilder<'_, 'll, CX> { type Value = as BackendTypes>::Value; diff --git a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs index 5e7ef27143b1..e7c071d05aa8 100644 --- a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs +++ b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs @@ -10,7 +10,7 @@ use rustc_middle::bug; use tracing::{debug, trace}; use crate::back::write::llvm_err; -use crate::builder::SBuilder; +use crate::builder::{SBuilder, UNNAMED}; use crate::context::SimpleCx; use crate::declare::declare_simple_fn; use crate::errors::{AutoDiffWithoutEnable, LlvmError}; @@ -51,6 +51,7 @@ fn has_sret(fnc: &Value) -> bool { // using iterators and peek()? fn match_args_from_caller_to_enzyme<'ll>( cx: &SimpleCx<'ll>, + builder: &SBuilder<'ll, 'll>, width: u32, args: &mut Vec<&'ll llvm::Value>, inputs: &[DiffActivity], @@ -78,7 +79,9 @@ fn match_args_from_caller_to_enzyme<'ll>( let enzyme_const = cx.create_metadata("enzyme_const".to_string()).unwrap(); let enzyme_out = cx.create_metadata("enzyme_out".to_string()).unwrap(); let enzyme_dup = cx.create_metadata("enzyme_dup".to_string()).unwrap(); + let enzyme_dupv = cx.create_metadata("enzyme_dupv".to_string()).unwrap(); let enzyme_dupnoneed = cx.create_metadata("enzyme_dupnoneed".to_string()).unwrap(); + let enzyme_dupnoneedv = cx.create_metadata("enzyme_dupnoneedv".to_string()).unwrap(); while activity_pos < inputs.len() { let diff_activity = inputs[activity_pos as usize]; @@ -90,13 +93,34 @@ fn match_args_from_caller_to_enzyme<'ll>( DiffActivity::Active => (enzyme_out, false), DiffActivity::ActiveOnly => (enzyme_out, false), DiffActivity::Dual => (enzyme_dup, true), + DiffActivity::Dualv => (enzyme_dupv, true), DiffActivity::DualOnly => (enzyme_dupnoneed, true), + DiffActivity::DualvOnly => (enzyme_dupnoneedv, true), DiffActivity::Duplicated => (enzyme_dup, true), DiffActivity::DuplicatedOnly => (enzyme_dupnoneed, true), - DiffActivity::FakeActivitySize => (enzyme_const, false), + DiffActivity::FakeActivitySize(_) => (enzyme_const, false), }; let outer_arg = outer_args[outer_pos]; args.push(cx.get_metadata_value(activity)); + if matches!(diff_activity, DiffActivity::Dualv) { + let next_outer_arg = outer_args[outer_pos + 1]; + let elem_bytes_size: u64 = match inputs[activity_pos + 1] { + DiffActivity::FakeActivitySize(Some(s)) => s.into(), + _ => bug!("incorrect Dualv handling recognized."), + }; + // stride: sizeof(T) * n_elems. + // n_elems is the next integer. + // Now we multiply `4 * next_outer_arg` to get the stride. + let mul = unsafe { + llvm::LLVMBuildMul( + builder.llbuilder, + cx.get_const_i64(elem_bytes_size), + next_outer_arg, + UNNAMED, + ) + }; + args.push(mul); + } args.push(outer_arg); if duplicated { // We know that duplicated args by construction have a following argument, @@ -114,7 +138,7 @@ fn match_args_from_caller_to_enzyme<'ll>( } else { let next_activity = inputs[activity_pos + 1]; // We analyze the MIR types and add this dummy activity if we visit a slice. - next_activity == DiffActivity::FakeActivitySize + matches!(next_activity, DiffActivity::FakeActivitySize(_)) } }; if slice { @@ -125,7 +149,10 @@ fn match_args_from_caller_to_enzyme<'ll>( // int2 >= int1, which means the shadow vector is large enough to store the gradient. assert_eq!(cx.type_kind(next_outer_ty), TypeKind::Integer); - for i in 0..(width as usize) { + let iterations = + if matches!(diff_activity, DiffActivity::Dualv) { 1 } else { width as usize }; + + for i in 0..iterations { let next_outer_arg2 = outer_args[outer_pos + 2 * (i + 1)]; let next_outer_ty2 = cx.val_ty(next_outer_arg2); assert_eq!(cx.type_kind(next_outer_ty2), TypeKind::Pointer); @@ -136,7 +163,7 @@ fn match_args_from_caller_to_enzyme<'ll>( } args.push(cx.get_metadata_value(enzyme_const)); args.push(next_outer_arg); - outer_pos += 2 + 2 * width as usize; + outer_pos += 2 + 2 * iterations; activity_pos += 2; } else { // A duplicated pointer will have the following two outer_fn arguments: @@ -360,6 +387,7 @@ fn generate_enzyme_call<'ll>( let outer_args: Vec<&llvm::Value> = get_params(outer_fn); match_args_from_caller_to_enzyme( &cx, + &builder, attrs.width, &mut args, &attrs.input_activity, diff --git a/compiler/rustc_monomorphize/src/partitioning/autodiff.rs b/compiler/rustc_monomorphize/src/partitioning/autodiff.rs index ebe0b258c1b6..22d593b80b89 100644 --- a/compiler/rustc_monomorphize/src/partitioning/autodiff.rs +++ b/compiler/rustc_monomorphize/src/partitioning/autodiff.rs @@ -2,7 +2,7 @@ use rustc_ast::expand::autodiff_attrs::{AutoDiffItem, DiffActivity}; use rustc_hir::def_id::LOCAL_CRATE; use rustc_middle::bug; use rustc_middle::mir::mono::MonoItem; -use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; +use rustc_middle::ty::{self, Instance, PseudoCanonicalInput, Ty, TyCtxt, TypingEnv}; use rustc_symbol_mangling::symbol_name_for_instance_in_crate; use tracing::{debug, trace}; @@ -22,23 +22,51 @@ fn adjust_activity_to_abi<'tcx>(tcx: TyCtxt<'tcx>, fn_ty: Ty<'tcx>, da: &mut Vec for (i, ty) in sig.inputs().iter().enumerate() { if let Some(inner_ty) = ty.builtin_deref(true) { if inner_ty.is_slice() { + // Now we need to figure out the size of each slice element in memory to allow + // safety checks and usability improvements in the backend. + let sty = match inner_ty.builtin_index() { + Some(sty) => sty, + None => { + panic!("slice element type unknown"); + } + }; + let pci = PseudoCanonicalInput { + typing_env: TypingEnv::fully_monomorphized(), + value: sty, + }; + + let layout = tcx.layout_of(pci); + let elem_size = match layout { + Ok(layout) => layout.size, + Err(_) => { + bug!("autodiff failed to compute slice element size"); + } + }; + let elem_size: u32 = elem_size.bytes() as u32; + // We know that the length will be passed as extra arg. if !da.is_empty() { // We are looking at a slice. The length of that slice will become an // extra integer on llvm level. Integers are always const. // However, if the slice get's duplicated, we want to know to later check the // size. So we mark the new size argument as FakeActivitySize. + // There is one FakeActivitySize per slice, so for convenience we store the + // slice element size in bytes in it. We will use the size in the backend. let activity = match da[i] { DiffActivity::DualOnly | DiffActivity::Dual + | DiffActivity::Dualv | DiffActivity::DuplicatedOnly - | DiffActivity::Duplicated => DiffActivity::FakeActivitySize, + | DiffActivity::Duplicated => { + DiffActivity::FakeActivitySize(Some(elem_size)) + } DiffActivity::Const => DiffActivity::Const, _ => bug!("unexpected activity for ptr/ref"), }; new_activities.push(activity); new_positions.push(i + 1); } + continue; } } From d7c0c328275fdcd5b6bba7f9ed7c97528103aca8 Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Tue, 8 Apr 2025 20:59:17 -0400 Subject: [PATCH 536/606] passing test for dualv --- tests/codegen/autodiffv2.rs | 113 ++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 tests/codegen/autodiffv2.rs diff --git a/tests/codegen/autodiffv2.rs b/tests/codegen/autodiffv2.rs new file mode 100644 index 000000000000..a40d19d3be3a --- /dev/null +++ b/tests/codegen/autodiffv2.rs @@ -0,0 +1,113 @@ +//@ compile-flags: -Zautodiff=Enable -C opt-level=3 -Clto=fat +//@ no-prefer-dynamic +//@ needs-enzyme +// +// In Enzyme, we test against a large range of LLVM versions (5+) and don't have overly many +// breakages. One benefit is that we match the IR generated by Enzyme only after running it +// through LLVM's O3 pipeline, which will remove most of the noise. +// However, our integration test could also be affected by changes in how rustc lowers MIR into +// LLVM-IR, which could cause additional noise and thus breakages. If that's the case, we should +// reduce this test to only match the first lines and the ret instructions. +// +// The function tested here has 4 inputs and 5 outputs, so we could either call forward-mode +// autodiff 4 times, or reverse mode 5 times. Since a forward-mode call is usually faster than +// reverse mode, we prefer it here. This file also tests a new optimization (batch mode), which +// allows us to call forward-mode autodiff only once, and get all 5 outputs in a single call. +// +// We support 2 different batch modes. `d_square2` has the same interface as scalar forward-mode, +// but each shadow argument is `width` times larger (thus 16 and 20 elements here). +// `d_square3` instead takes `width` (4) shadow arguments, which are all the same size as the +// original function arguments. +// +// FIXME(autodiff): We currently can't test `d_square1` and `d_square3` in the same file, since they +// generate the same dummy functions which get merged by LLVM, breaking pieces of our pipeline which +// try to rewrite the dummy functions later. We should consider to change to pure declarations both +// in our frontend and in the llvm backend to avoid these issues. + +#![feature(autodiff)] + +use std::autodiff::autodiff; + +#[no_mangle] +//#[autodiff(d_square1, Forward, Dual, Dual)] +#[autodiff(d_square2, Forward, 4, Dualv, Dualv)] +#[autodiff(d_square3, Forward, 4, Dual, Dual)] +fn square(x: &[f32], y: &mut [f32]) { + assert!(x.len() >= 4); + assert!(y.len() >= 5); + y[0] = 4.3 * x[0] + 1.2 * x[1] + 3.4 * x[2] + 2.1 * x[3]; + y[1] = 2.3 * x[0] + 4.5 * x[1] + 1.7 * x[2] + 6.4 * x[3]; + y[2] = 1.1 * x[0] + 3.3 * x[1] + 2.5 * x[2] + 4.7 * x[3]; + y[3] = 5.2 * x[0] + 1.4 * x[1] + 2.6 * x[2] + 3.8 * x[3]; + y[4] = 1.0 * x[0] + 2.0 * x[1] + 3.0 * x[2] + 4.0 * x[3]; +} + +fn main() { + let x1 = std::hint::black_box(vec![0.0, 1.0, 2.0, 3.0]); + + let dx1 = std::hint::black_box(vec![1.0; 12]); + + let z1 = std::hint::black_box(vec![1.0, 0.0, 0.0, 0.0]); + let z2 = std::hint::black_box(vec![0.0, 1.0, 0.0, 0.0]); + let z3 = std::hint::black_box(vec![0.0, 0.0, 1.0, 0.0]); + let z4 = std::hint::black_box(vec![0.0, 0.0, 0.0, 1.0]); + + let z5 = std::hint::black_box(vec![ + 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, + ]); + + let mut y1 = std::hint::black_box(vec![0.0; 5]); + let mut y2 = std::hint::black_box(vec![0.0; 5]); + let mut y3 = std::hint::black_box(vec![0.0; 5]); + let mut y4 = std::hint::black_box(vec![0.0; 5]); + + let mut y5 = std::hint::black_box(vec![0.0; 5]); + + let mut y6 = std::hint::black_box(vec![0.0; 5]); + + let mut dy1_1 = std::hint::black_box(vec![0.0; 5]); + let mut dy1_2 = std::hint::black_box(vec![0.0; 5]); + let mut dy1_3 = std::hint::black_box(vec![0.0; 5]); + let mut dy1_4 = std::hint::black_box(vec![0.0; 5]); + + let mut dy2 = std::hint::black_box(vec![0.0; 20]); + + let mut dy3_1 = std::hint::black_box(vec![0.0; 5]); + let mut dy3_2 = std::hint::black_box(vec![0.0; 5]); + let mut dy3_3 = std::hint::black_box(vec![0.0; 5]); + let mut dy3_4 = std::hint::black_box(vec![0.0; 5]); + + // scalar. + //d_square1(&x1, &z1, &mut y1, &mut dy1_1); + //d_square1(&x1, &z2, &mut y2, &mut dy1_2); + //d_square1(&x1, &z3, &mut y3, &mut dy1_3); + //d_square1(&x1, &z4, &mut y4, &mut dy1_4); + + // assert y1 == y2 == y3 == y4 + //for i in 0..5 { + // assert_eq!(y1[i], y2[i]); + // assert_eq!(y1[i], y3[i]); + // assert_eq!(y1[i], y4[i]); + //} + + // batch mode A) + d_square2(&x1, &z5, &mut y5, &mut dy2); + + // assert y1 == y2 == y3 == y4 == y5 + //for i in 0..5 { + // assert_eq!(y1[i], y5[i]); + //} + + // batch mode B) + d_square3(&x1, &z1, &z2, &z3, &z4, &mut y6, &mut dy3_1, &mut dy3_2, &mut dy3_3, &mut dy3_4); + for i in 0..5 { + assert_eq!(y5[i], y6[i]); + } + + for i in 0..5 { + assert_eq!(dy2[0..5][i], dy3_1[i]); + assert_eq!(dy2[5..10][i], dy3_2[i]); + assert_eq!(dy2[10..15][i], dy3_3[i]); + assert_eq!(dy2[15..20][i], dy3_4[i]); + } +} From cb6c499bc98a8b6db85856f200ffba2f47b8b73a Mon Sep 17 00:00:00 2001 From: dianne Date: Sun, 23 Feb 2025 19:39:19 -0800 Subject: [PATCH 537/606] lower implicit deref patterns to THIR Since this uses `pat_adjustments`, I've also tweaked the documentation to mention implicit deref patterns and made sure the pattern migration diagnostic logic accounts for it. I'll adjust `ExprUseVisitor` in a later commit and add some tests there for closure capture inference. --- .../rustc_middle/src/ty/typeck_results.rs | 15 ++++++++--- .../src/thir/pattern/migration.rs | 16 +++++------- .../rustc_mir_build/src/thir/pattern/mod.rs | 26 ++++++++++++------- 3 files changed, 36 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index ee8113b0f762..4c5c669771fb 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -77,8 +77,8 @@ pub struct TypeckResults<'tcx> { /// to a form valid in all Editions, either as a lint diagnostic or hard error. rust_2024_migration_desugared_pats: ItemLocalMap, - /// Stores the types which were implicitly dereferenced in pattern binding modes - /// for later usage in THIR lowering. For example, + /// Stores the types which were implicitly dereferenced in pattern binding modes or deref + /// patterns for later usage in THIR lowering. For example, /// /// ``` /// match &&Some(5i32) { @@ -86,7 +86,16 @@ pub struct TypeckResults<'tcx> { /// _ => {}, /// } /// ``` - /// leads to a `vec![&&Option, &Option]`. Empty vectors are not stored. + /// leads to a `vec![&&Option, &Option]` and + /// + /// ``` + /// #![feature(deref_patterns)] + /// match &Box::new(Some(5i32)) { + /// Some(n) => {}, + /// _ => {}, + /// } + /// ``` + /// leads to a `vec![&Box>, Box>]`. Empty vectors are not stored. /// /// See: /// diff --git a/compiler/rustc_mir_build/src/thir/pattern/migration.rs b/compiler/rustc_mir_build/src/thir/pattern/migration.rs index c688b6f2848c..12c457f13fc1 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/migration.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/migration.rs @@ -4,7 +4,6 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_errors::MultiSpan; use rustc_hir::{BindingMode, ByRef, HirId, Mutability}; use rustc_lint as lint; -use rustc_middle::span_bug; use rustc_middle::ty::{self, Rust2024IncompatiblePatInfo, TyCtxt}; use rustc_span::{Ident, Span}; @@ -87,19 +86,18 @@ impl<'a> PatMigration<'a> { } /// Tracks when we're lowering a pattern that implicitly dereferences the scrutinee. - /// This should only be called when the pattern type adjustments list `adjustments` is - /// non-empty. Returns the prior default binding mode; this should be followed by a call to - /// [`PatMigration::leave_ref`] to restore it when we leave the pattern. + /// This should only be called when the pattern type adjustments list `adjustments` contains an + /// implicit deref of a reference type. Returns the prior default binding mode; this should be + /// followed by a call to [`PatMigration::leave_ref`] to restore it when we leave the pattern. pub(super) fn visit_implicit_derefs<'tcx>( &mut self, pat_span: Span, adjustments: &[ty::adjustment::PatAdjustment<'tcx>], ) -> Option<(Span, Mutability)> { - let implicit_deref_mutbls = adjustments.iter().map(|adjust| { - let &ty::Ref(_, _, mutbl) = adjust.source.kind() else { - span_bug!(pat_span, "pattern implicitly dereferences a non-ref type"); - }; - mutbl + // Implicitly dereferencing references changes the default binding mode, but implicit derefs + // of smart pointers do not. Thus, we only consider implicit derefs of reference types. + let implicit_deref_mutbls = adjustments.iter().filter_map(|adjust| { + if let &ty::Ref(_, _, mutbl) = adjust.source.kind() { Some(mutbl) } else { None } }); if !self.info.suggest_eliding_modes { diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index f682581d763b..8f058efdfacd 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -18,7 +18,7 @@ use rustc_middle::mir::interpret::LitToConstInput; use rustc_middle::thir::{ Ascription, FieldPat, LocalVarId, Pat, PatKind, PatRange, PatRangeBoundary, }; -use rustc_middle::ty::adjustment::PatAdjustment; +use rustc_middle::ty::adjustment::{PatAdjust, PatAdjustment}; use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt, TypingMode}; use rustc_middle::{bug, span_bug}; @@ -68,9 +68,11 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { self.typeck_results.pat_adjustments().get(pat.hir_id).map_or(&[], |v| &**v); // Track the default binding mode for the Rust 2024 migration suggestion. + // Implicitly dereferencing references changes the default binding mode, but implicit deref + // patterns do not. Only track binding mode changes if a ref type is in the adjustments. let mut opt_old_mode_span = None; if let Some(s) = &mut self.rust_2024_migration - && !adjustments.is_empty() + && adjustments.iter().any(|adjust| adjust.kind == PatAdjust::BuiltinDeref) { opt_old_mode_span = s.visit_implicit_derefs(pat.span, adjustments); } @@ -104,16 +106,22 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { }; let adjusted_pat = adjustments.iter().rev().fold(unadjusted_pat, |thir_pat, adjust| { - debug!("{:?}: wrapping pattern with type {:?}", thir_pat, adjust); - Box::new(Pat { - span: thir_pat.span, - ty: adjust.source, - kind: PatKind::Deref { subpattern: thir_pat }, - }) + debug!("{:?}: wrapping pattern with adjustment {:?}", thir_pat, adjust); + let span = thir_pat.span; + let kind = match adjust.kind { + PatAdjust::BuiltinDeref => PatKind::Deref { subpattern: thir_pat }, + PatAdjust::OverloadedDeref => { + let mutable = self.typeck_results.pat_has_ref_mut_binding(pat); + let mutability = + if mutable { hir::Mutability::Mut } else { hir::Mutability::Not }; + PatKind::DerefPattern { subpattern: thir_pat, mutability } + } + }; + Box::new(Pat { span, ty: adjust.source, kind }) }); if let Some(s) = &mut self.rust_2024_migration - && !adjustments.is_empty() + && adjustments.iter().any(|adjust| adjust.kind == PatAdjust::BuiltinDeref) { s.leave_ref(opt_old_mode_span); } From e4b7b3d820b6db4f4a37a1a09b700bc9a39d80ba Mon Sep 17 00:00:00 2001 From: dianne Date: Sat, 8 Mar 2025 21:07:11 -0800 Subject: [PATCH 538/606] pattern typing for immutable implicit deref patterns --- compiler/rustc_hir_typeck/src/pat.rs | 116 ++++++++++++++---- tests/ui/pattern/deref-patterns/bindings.rs | 27 ++++ tests/ui/pattern/deref-patterns/branch.rs | 22 ++++ .../cant_move_out_of_pattern.rs | 18 +++ .../cant_move_out_of_pattern.stderr | 36 +++++- tests/ui/pattern/deref-patterns/typeck.rs | 6 + .../ui/pattern/deref-patterns/typeck_fail.rs | 11 ++ .../pattern/deref-patterns/typeck_fail.stderr | 36 +++++- .../deref-patterns/unsatisfied-bounds.rs | 21 ++++ .../deref-patterns/unsatisfied-bounds.stderr | 9 ++ 10 files changed, 272 insertions(+), 30 deletions(-) create mode 100644 tests/ui/pattern/deref-patterns/unsatisfied-bounds.rs create mode 100644 tests/ui/pattern/deref-patterns/unsatisfied-bounds.stderr diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index c19d8cf6dc54..11ed7db9eb7f 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -162,12 +162,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Mode for adjusting the expected type and binding mode. #[derive(Clone, Copy, Debug, PartialEq, Eq)] enum AdjustMode { - /// Peel off all immediate reference types. - Peel, + /// Peel off all immediate reference types. If the `deref_patterns` feature is enabled, this + /// also peels smart pointer ADTs. + Peel { kind: PeelKind }, /// Pass on the input binding mode and expected type. Pass, } +/// Restrictions on what types to peel when adjusting the expected type and binding mode. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +enum PeelKind { + /// Only peel reference types. This is used for explicit `deref!(_)` patterns, which dereference + /// any number of `&`/`&mut` references, plus a single smart pointer. + ExplicitDerefPat, + /// Implicitly peel any number of references, and if `deref_patterns` is enabled, smart pointer + /// ADTs. In order to peel only as much as necessary for the pattern to match, the `until_adt` + /// field contains the ADT def that the pattern is a constructor for, if applicable, so that we + /// don't peel it. See [`ResolvedPat`] for more information. + // TODO: add `ResolvedPat` and `until_adt`. + Implicit, +} + /// `ref mut` bindings (explicit or match-ergonomics) are not allowed behind an `&` reference. /// Normally, the borrow checker enforces this, but for (currently experimental) match ergonomics, /// we track this when typing patterns for two purposes: @@ -390,7 +405,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } // Resolve type if needed. - let expected = if let AdjustMode::Peel = adjust_mode + let expected = if let AdjustMode::Peel { .. } = adjust_mode && pat.default_binding_modes { self.try_structurally_resolve_type(pat.span, expected) @@ -403,7 +418,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match pat.kind { // Peel off a `&` or `&mut` from the scrutinee type. See the examples in // `tests/ui/rfcs/rfc-2005-default-binding-mode`. - _ if let AdjustMode::Peel = adjust_mode + _ if let AdjustMode::Peel { .. } = adjust_mode && pat.default_binding_modes && let ty::Ref(_, inner_ty, inner_mutability) = *expected.kind() => { @@ -443,6 +458,45 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Recurse with the new expected type. self.check_pat_inner(pat, opt_path_res, adjust_mode, inner_ty, new_pat_info) } + // If `deref_patterns` is enabled, peel a smart pointer from the scrutinee type. See the + // examples in `tests/ui/pattern/deref_patterns/`. + _ if self.tcx.features().deref_patterns() + && let AdjustMode::Peel { kind: PeelKind::Implicit } = adjust_mode + && pat.default_binding_modes + // For simplicity, only apply overloaded derefs if `expected` is a known ADT. + // FIXME(deref_patterns): we'll get better diagnostics for users trying to + // implicitly deref generics if we allow them here, but primitives, tuples, and + // inference vars definitely should be stopped. Figure out what makes most sense. + // TODO: stop peeling if the pattern is a constructor for the scrutinee type + && expected.is_adt() + // At this point, the pattern isn't able to match `expected` without peeling. Check + // that it implements `Deref` before assuming it's a smart pointer, to get a normal + // type error instead of a missing impl error if not. This only checks for `Deref`, + // not `DerefPure`: we require that too, but we want a trait error if it's missing. + && let Some(deref_trait) = self.tcx.lang_items().deref_trait() + && self + .type_implements_trait(deref_trait, [expected], self.param_env) + .may_apply() => + { + debug!("scrutinee ty {expected:?} is a smart pointer, inserting overloaded deref"); + // The scrutinee is a smart pointer; implicitly dereference it. This adds a + // requirement that `expected: DerefPure`. + let inner_ty = self.deref_pat_target(pat.span, expected); + // Once we've checked `pat`, we'll add a `DerefMut` bound if it contains any + // `ref mut` bindings. TODO: implement that, then reference here. + + // Preserve the smart pointer type for THIR lowering and upvar analysis. + self.typeck_results + .borrow_mut() + .pat_adjustments_mut() + .entry(pat.hir_id) + .or_default() + .push(PatAdjustment { kind: PatAdjust::OverloadedDeref, source: expected }); + + // Recurse, using the old pat info to keep `current_depth` to its old value. + // Peeling smart pointers does not update the default binding mode. + self.check_pat_inner(pat, opt_path_res, adjust_mode, inner_ty, old_pat_info) + } PatKind::Missing | PatKind::Wild | PatKind::Err(_) => expected, // We allow any type here; we ensure that the type is uninhabited during match checking. PatKind::Never => expected, @@ -505,12 +559,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { PatKind::Struct(..) | PatKind::TupleStruct(..) | PatKind::Tuple(..) - | PatKind::Box(_) - | PatKind::Deref(_) | PatKind::Range(..) - | PatKind::Slice(..) => AdjustMode::Peel, + | PatKind::Slice(..) => AdjustMode::Peel { kind: PeelKind::Implicit }, + // When checking an explicit deref pattern, only peel reference types. + // FIXME(deref_patterns): If box patterns and deref patterns need to coexist, box + // patterns may want `PeelKind::Implicit`, stopping on encountering a box. + | PatKind::Box(_) + | PatKind::Deref(_) => AdjustMode::Peel { kind: PeelKind::ExplicitDerefPat }, // A never pattern behaves somewhat like a literal or unit variant. - PatKind::Never => AdjustMode::Peel, + PatKind::Never => AdjustMode::Peel { kind: PeelKind::Implicit }, PatKind::Expr(PatExpr { kind: PatExprKind::Path(_), .. }) => match opt_path_res.unwrap() { // These constants can be of a reference type, e.g. `const X: &u8 = &0;`. // Peeling the reference types too early will cause type checking failures. @@ -520,7 +577,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // could successfully compile. The former being `Self` requires a unit struct. // In either case, and unlike constants, the pattern itself cannot be // a reference type wherefore peeling doesn't give up any expressiveness. - _ => AdjustMode::Peel, + _ => AdjustMode::Peel { kind: PeelKind::Implicit }, }, // String and byte-string literals result in types `&str` and `&[u8]` respectively. @@ -530,7 +587,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Call `resolve_vars_if_possible` here for inline const blocks. PatKind::Expr(lt) => match self.resolve_vars_if_possible(self.check_pat_expr_unadjusted(lt)).kind() { ty::Ref(..) => AdjustMode::Pass, - _ => AdjustMode::Peel, + _ => AdjustMode::Peel { kind: PeelKind::Implicit }, }, // Ref patterns are complicated, we handle them in `check_pat_ref`. @@ -2256,31 +2313,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Ty<'tcx>, pat_info: PatInfo<'tcx>, ) -> Ty<'tcx> { - let tcx = self.tcx; - // Register a `DerefPure` bound, which is required by all `deref!()` pats. - self.register_bound( - expected, - tcx.require_lang_item(hir::LangItem::DerefPure, Some(span)), - self.misc(span), - ); - // ::Target - let ty = Ty::new_projection( - tcx, - tcx.require_lang_item(hir::LangItem::DerefTarget, Some(span)), - [expected], - ); - let ty = self.normalize(span, ty); - let ty = self.try_structurally_resolve_type(span, ty); - self.check_pat(inner, ty, pat_info); + let target_ty = self.deref_pat_target(span, expected); + self.check_pat(inner, target_ty, pat_info); // Check if the pattern has any `ref mut` bindings, which would require // `DerefMut` to be emitted in MIR building instead of just `Deref`. // We do this *after* checking the inner pattern, since we want to make // sure to apply any match-ergonomics adjustments. + // TODO: move this to a separate definition to share it with implicit deref pats if self.typeck_results.borrow().pat_has_ref_mut_binding(inner) { self.register_bound( expected, - tcx.require_lang_item(hir::LangItem::DerefMut, Some(span)), + self.tcx.require_lang_item(hir::LangItem::DerefMut, Some(span)), self.misc(span), ); } @@ -2288,6 +2332,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected } + fn deref_pat_target(&self, span: Span, source_ty: Ty<'tcx>) -> Ty<'tcx> { + // Register a `DerefPure` bound, which is required by all `deref!()` pats. + let tcx = self.tcx; + self.register_bound( + source_ty, + tcx.require_lang_item(hir::LangItem::DerefPure, Some(span)), + self.misc(span), + ); + // The expected type for the deref pat's inner pattern is `::Target`. + let target_ty = Ty::new_projection( + tcx, + tcx.require_lang_item(hir::LangItem::DerefTarget, Some(span)), + [source_ty], + ); + let target_ty = self.normalize(span, target_ty); + self.try_structurally_resolve_type(span, target_ty) + } + // Precondition: Pat is Ref(inner) fn check_pat_ref( &self, diff --git a/tests/ui/pattern/deref-patterns/bindings.rs b/tests/ui/pattern/deref-patterns/bindings.rs index 5881e4166a46..ce10cd5439e1 100644 --- a/tests/ui/pattern/deref-patterns/bindings.rs +++ b/tests/ui/pattern/deref-patterns/bindings.rs @@ -1,7 +1,9 @@ +//@ revisions: explicit implicit //@ run-pass #![feature(deref_patterns)] #![allow(incomplete_features)] +#[cfg(explicit)] fn simple_vec(vec: Vec) -> u32 { match vec { deref!([]) => 100, @@ -13,6 +15,19 @@ fn simple_vec(vec: Vec) -> u32 { } } +#[cfg(implicit)] +fn simple_vec(vec: Vec) -> u32 { + match vec { + [] => 100, + [x] if x == 4 => x + 4, + [x] => x, + [1, x] => x + 200, + deref!(ref slice) => slice.iter().sum(), + _ => 2000, + } +} + +#[cfg(explicit)] fn nested_vec(vecvec: Vec>) -> u32 { match vecvec { deref!([]) => 0, @@ -24,6 +39,18 @@ fn nested_vec(vecvec: Vec>) -> u32 { } } +#[cfg(implicit)] +fn nested_vec(vecvec: Vec>) -> u32 { + match vecvec { + [] => 0, + [[x]] => x, + [[0, x] | [1, x]] => x, + [ref x] => x.iter().sum(), + [[], [1, x, y]] => y - x, + _ => 2000, + } +} + fn ref_mut(val: u32) -> u32 { let mut b = Box::new(0u32); match &mut b { diff --git a/tests/ui/pattern/deref-patterns/branch.rs b/tests/ui/pattern/deref-patterns/branch.rs index 1bac1006d9dc..9d72b35fd2f1 100644 --- a/tests/ui/pattern/deref-patterns/branch.rs +++ b/tests/ui/pattern/deref-patterns/branch.rs @@ -1,8 +1,10 @@ +//@ revisions: explicit implicit //@ run-pass // Test the execution of deref patterns. #![feature(deref_patterns)] #![allow(incomplete_features)] +#[cfg(explicit)] fn branch(vec: Vec) -> u32 { match vec { deref!([]) => 0, @@ -12,6 +14,17 @@ fn branch(vec: Vec) -> u32 { } } +#[cfg(implicit)] +fn branch(vec: Vec) -> u32 { + match vec { + [] => 0, + [1, _, 3] => 1, + [2, ..] => 2, + _ => 1000, + } +} + +#[cfg(explicit)] fn nested(vec: Vec>) -> u32 { match vec { deref!([deref!([]), ..]) => 1, @@ -20,6 +33,15 @@ fn nested(vec: Vec>) -> u32 { } } +#[cfg(implicit)] +fn nested(vec: Vec>) -> u32 { + match vec { + [[], ..] => 1, + [[0, ..], [1, ..]] => 2, + _ => 1000, + } +} + fn main() { assert!(matches!(Vec::::new(), deref!([]))); assert!(matches!(vec![1], deref!([1]))); diff --git a/tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.rs b/tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.rs index 84b5ec09dc7d..791776be5aca 100644 --- a/tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.rs +++ b/tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.rs @@ -21,4 +21,22 @@ fn cant_move_out_rc(rc: Rc) -> Struct { } } +struct Container(Struct); + +fn cant_move_out_box_implicit(b: Box) -> Struct { + match b { + //~^ ERROR: cannot move out of a shared reference + Container(x) => x, + _ => unreachable!(), + } +} + +fn cant_move_out_rc_implicit(rc: Rc) -> Struct { + match rc { + //~^ ERROR: cannot move out of a shared reference + Container(x) => x, + _ => unreachable!(), + } +} + fn main() {} diff --git a/tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.stderr b/tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.stderr index 2cf435b11799..1887800fc38a 100644 --- a/tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.stderr +++ b/tests/ui/pattern/deref-patterns/cant_move_out_of_pattern.stderr @@ -32,6 +32,40 @@ help: consider borrowing the pattern binding LL | deref!(ref x) => x, | +++ -error: aborting due to 2 previous errors +error[E0507]: cannot move out of a shared reference + --> $DIR/cant_move_out_of_pattern.rs:27:11 + | +LL | match b { + | ^ +LL | +LL | Container(x) => x, + | - + | | + | data moved here + | move occurs because `x` has type `Struct`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | Container(ref x) => x, + | +++ + +error[E0507]: cannot move out of a shared reference + --> $DIR/cant_move_out_of_pattern.rs:35:11 + | +LL | match rc { + | ^^ +LL | +LL | Container(x) => x, + | - + | | + | data moved here + | move occurs because `x` has type `Struct`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | Container(ref x) => x, + | +++ + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/pattern/deref-patterns/typeck.rs b/tests/ui/pattern/deref-patterns/typeck.rs index f23f7042cd89..3a7ce9d1deb3 100644 --- a/tests/ui/pattern/deref-patterns/typeck.rs +++ b/tests/ui/pattern/deref-patterns/typeck.rs @@ -10,26 +10,32 @@ fn main() { let vec: Vec = Vec::new(); match vec { deref!([..]) => {} + [..] => {} _ => {} } match Box::new(true) { deref!(true) => {} + true => {} _ => {} } match &Box::new(true) { deref!(true) => {} + true => {} _ => {} } match &Rc::new(0) { deref!(1..) => {} + 1.. => {} _ => {} } let _: &Struct = match &Rc::new(Struct) { deref!(x) => x, + Struct => &Struct, _ => unreachable!(), }; let _: &[Struct] = match &Rc::new(vec![Struct]) { deref!(deref!(x)) => x, + [Struct] => &[Struct], _ => unreachable!(), }; } diff --git a/tests/ui/pattern/deref-patterns/typeck_fail.rs b/tests/ui/pattern/deref-patterns/typeck_fail.rs index 040118449ecc..4b9ad7d25f09 100644 --- a/tests/ui/pattern/deref-patterns/typeck_fail.rs +++ b/tests/ui/pattern/deref-patterns/typeck_fail.rs @@ -7,11 +7,22 @@ fn main() { match "foo".to_string() { deref!("foo") => {} //~^ ERROR: mismatched types + "foo" => {} + //~^ ERROR: mismatched types _ => {} } match &"foo".to_string() { deref!("foo") => {} //~^ ERROR: mismatched types + "foo" => {} + //~^ ERROR: mismatched types + _ => {} + } + + // Make sure we don't try implicitly dereferncing any ADT. + match Some(0) { + Ok(0) => {} + //~^ ERROR: mismatched types _ => {} } } diff --git a/tests/ui/pattern/deref-patterns/typeck_fail.stderr b/tests/ui/pattern/deref-patterns/typeck_fail.stderr index 1c14802745a0..3e2f35618822 100644 --- a/tests/ui/pattern/deref-patterns/typeck_fail.stderr +++ b/tests/ui/pattern/deref-patterns/typeck_fail.stderr @@ -7,13 +7,45 @@ LL | deref!("foo") => {} | ^^^^^ expected `str`, found `&str` error[E0308]: mismatched types - --> $DIR/typeck_fail.rs:13:16 + --> $DIR/typeck_fail.rs:10:9 + | +LL | match "foo".to_string() { + | ----------------- this expression has type `String` +... +LL | "foo" => {} + | ^^^^^ expected `String`, found `&str` + +error[E0308]: mismatched types + --> $DIR/typeck_fail.rs:15:16 | LL | match &"foo".to_string() { | ------------------ this expression has type `&String` LL | deref!("foo") => {} | ^^^^^ expected `str`, found `&str` -error: aborting due to 2 previous errors +error[E0308]: mismatched types + --> $DIR/typeck_fail.rs:17:9 + | +LL | match &"foo".to_string() { + | ------------------ this expression has type `&String` +... +LL | "foo" => {} + | ^^^^^ expected `&String`, found `&str` + | + = note: expected reference `&String` + found reference `&'static str` + +error[E0308]: mismatched types + --> $DIR/typeck_fail.rs:24:9 + | +LL | match Some(0) { + | ------- this expression has type `Option<{integer}>` +LL | Ok(0) => {} + | ^^^^^ expected `Option<{integer}>`, found `Result<_, _>` + | + = note: expected enum `Option<{integer}>` + found enum `Result<_, _>` + +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/deref-patterns/unsatisfied-bounds.rs b/tests/ui/pattern/deref-patterns/unsatisfied-bounds.rs new file mode 100644 index 000000000000..00064b2320c8 --- /dev/null +++ b/tests/ui/pattern/deref-patterns/unsatisfied-bounds.rs @@ -0,0 +1,21 @@ +#![feature(deref_patterns)] +#![allow(incomplete_features)] + +struct MyPointer; + +impl std::ops::Deref for MyPointer { + type Target = (); + fn deref(&self) -> &() { + &() + } +} + +fn main() { + // Test that we get a trait error if a user attempts implicit deref pats on their own impls. + // FIXME(deref_patterns): there should be a special diagnostic for missing `DerefPure`. + match MyPointer { + () => {} + //~^ the trait bound `MyPointer: DerefPure` is not satisfied + _ => {} + } +} diff --git a/tests/ui/pattern/deref-patterns/unsatisfied-bounds.stderr b/tests/ui/pattern/deref-patterns/unsatisfied-bounds.stderr new file mode 100644 index 000000000000..983ce27865c9 --- /dev/null +++ b/tests/ui/pattern/deref-patterns/unsatisfied-bounds.stderr @@ -0,0 +1,9 @@ +error[E0277]: the trait bound `MyPointer: DerefPure` is not satisfied + --> $DIR/unsatisfied-bounds.rs:17:9 + | +LL | () => {} + | ^^ the trait `DerefPure` is not implemented for `MyPointer` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. From 91d0b579f020964bfe6bcaa86fbfc8fd493ae4db Mon Sep 17 00:00:00 2001 From: dianne Date: Sun, 9 Mar 2025 00:06:00 -0800 Subject: [PATCH 539/606] register `DerefMut` bounds for implicit mutable derefs --- compiler/rustc_hir_typeck/src/pat.rs | 53 +++++++++++++------ tests/ui/pattern/deref-patterns/bindings.rs | 28 ++++++++++ .../ui/pattern/deref-patterns/fake_borrows.rs | 7 +++ .../deref-patterns/fake_borrows.stderr | 11 +++- tests/ui/pattern/deref-patterns/ref-mut.rs | 9 ++++ .../ui/pattern/deref-patterns/ref-mut.stderr | 10 +++- 6 files changed, 100 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 11ed7db9eb7f..f33e270c357e 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -344,6 +344,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty = self.check_pat_inner(pat, opt_path_res, adjust_mode, expected, pat_info); self.write_ty(pat.hir_id, ty); + // If we implicitly inserted overloaded dereferences before matching, check the pattern to + // see if the dereferenced types need `DerefMut` bounds. + if let Some(derefed_tys) = self.typeck_results.borrow().pat_adjustments().get(pat.hir_id) + && derefed_tys.iter().any(|adjust| adjust.kind == PatAdjust::OverloadedDeref) + { + self.register_deref_mut_bounds_if_needed( + pat.span, + pat, + derefed_tys.iter().filter_map(|adjust| match adjust.kind { + PatAdjust::OverloadedDeref => Some(adjust.source), + PatAdjust::BuiltinDeref => None, + }), + ); + } + // (note_1): In most of the cases where (note_1) is referenced // (literals and constants being the exception), we relate types // using strict equality, even though subtyping would be sufficient. @@ -483,7 +498,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // requirement that `expected: DerefPure`. let inner_ty = self.deref_pat_target(pat.span, expected); // Once we've checked `pat`, we'll add a `DerefMut` bound if it contains any - // `ref mut` bindings. TODO: implement that, then reference here. + // `ref mut` bindings. See `Self::register_deref_mut_bounds_if_needed`. // Preserve the smart pointer type for THIR lowering and upvar analysis. self.typeck_results @@ -2315,20 +2330,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Ty<'tcx> { let target_ty = self.deref_pat_target(span, expected); self.check_pat(inner, target_ty, pat_info); - - // Check if the pattern has any `ref mut` bindings, which would require - // `DerefMut` to be emitted in MIR building instead of just `Deref`. - // We do this *after* checking the inner pattern, since we want to make - // sure to apply any match-ergonomics adjustments. - // TODO: move this to a separate definition to share it with implicit deref pats - if self.typeck_results.borrow().pat_has_ref_mut_binding(inner) { - self.register_bound( - expected, - self.tcx.require_lang_item(hir::LangItem::DerefMut, Some(span)), - self.misc(span), - ); - } - + self.register_deref_mut_bounds_if_needed(span, inner, [expected]); expected } @@ -2350,6 +2352,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.try_structurally_resolve_type(span, target_ty) } + /// Check if the interior of a deref pattern (either explicit or implicit) has any `ref mut` + /// bindings, which would require `DerefMut` to be emitted in MIR building instead of just + /// `Deref`. We do this *after* checking the inner pattern, since we want to make sure to + /// account for `ref mut` binding modes inherited from implicitly dereferencing `&mut` refs. + fn register_deref_mut_bounds_if_needed( + &self, + span: Span, + inner: &'tcx Pat<'tcx>, + derefed_tys: impl IntoIterator>, + ) { + if self.typeck_results.borrow().pat_has_ref_mut_binding(inner) { + for mutably_derefed_ty in derefed_tys { + self.register_bound( + mutably_derefed_ty, + self.tcx.require_lang_item(hir::LangItem::DerefMut, Some(span)), + self.misc(span), + ); + } + } + } + // Precondition: Pat is Ref(inner) fn check_pat_ref( &self, diff --git a/tests/ui/pattern/deref-patterns/bindings.rs b/tests/ui/pattern/deref-patterns/bindings.rs index ce10cd5439e1..c14d57f3f24e 100644 --- a/tests/ui/pattern/deref-patterns/bindings.rs +++ b/tests/ui/pattern/deref-patterns/bindings.rs @@ -51,6 +51,7 @@ fn nested_vec(vecvec: Vec>) -> u32 { } } +#[cfg(explicit)] fn ref_mut(val: u32) -> u32 { let mut b = Box::new(0u32); match &mut b { @@ -64,6 +65,21 @@ fn ref_mut(val: u32) -> u32 { *x } +#[cfg(implicit)] +fn ref_mut(val: u32) -> u32 { + let mut b = Box::new((0u32,)); + match &mut b { + (_x,) if false => unreachable!(), + (x,) => { + *x = val; + } + _ => unreachable!(), + } + let (x,) = &b else { unreachable!() }; + *x +} + +#[cfg(explicit)] #[rustfmt::skip] fn or_and_guard(tuple: (u32, u32)) -> u32 { let mut sum = 0; @@ -75,6 +91,18 @@ fn or_and_guard(tuple: (u32, u32)) -> u32 { sum } +#[cfg(implicit)] +#[rustfmt::skip] +fn or_and_guard(tuple: (u32, u32)) -> u32 { + let mut sum = 0; + let b = Box::new(tuple); + match b { + (x, _) | (_, x) if { sum += x; false } => {}, + _ => {}, + } + sum +} + fn main() { assert_eq!(simple_vec(vec![1]), 1); assert_eq!(simple_vec(vec![1, 2]), 202); diff --git a/tests/ui/pattern/deref-patterns/fake_borrows.rs b/tests/ui/pattern/deref-patterns/fake_borrows.rs index 35fa9cbf7d85..bf614d7d66fd 100644 --- a/tests/ui/pattern/deref-patterns/fake_borrows.rs +++ b/tests/ui/pattern/deref-patterns/fake_borrows.rs @@ -11,4 +11,11 @@ fn main() { deref!(false) => {} _ => {}, } + match b { + true => {} + _ if { *b = true; false } => {} + //~^ ERROR cannot assign `*b` in match guard + false => {} + _ => {}, + } } diff --git a/tests/ui/pattern/deref-patterns/fake_borrows.stderr b/tests/ui/pattern/deref-patterns/fake_borrows.stderr index 6a591e6416c5..8c060236d0df 100644 --- a/tests/ui/pattern/deref-patterns/fake_borrows.stderr +++ b/tests/ui/pattern/deref-patterns/fake_borrows.stderr @@ -7,6 +7,15 @@ LL | deref!(true) => {} LL | _ if { *b = true; false } => {} | ^^^^^^^^^ cannot assign -error: aborting due to 1 previous error +error[E0510]: cannot assign `*b` in match guard + --> $DIR/fake_borrows.rs:16:16 + | +LL | match b { + | - value is immutable in match guard +LL | true => {} +LL | _ if { *b = true; false } => {} + | ^^^^^^^^^ cannot assign + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0510`. diff --git a/tests/ui/pattern/deref-patterns/ref-mut.rs b/tests/ui/pattern/deref-patterns/ref-mut.rs index 1918008a761a..43738671346d 100644 --- a/tests/ui/pattern/deref-patterns/ref-mut.rs +++ b/tests/ui/pattern/deref-patterns/ref-mut.rs @@ -8,10 +8,19 @@ fn main() { deref!(x) => {} _ => {} } + match &mut vec![1] { + [x] => {} + _ => {} + } match &mut Rc::new(1) { deref!(x) => {} //~^ ERROR the trait bound `Rc<{integer}>: DerefMut` is not satisfied _ => {} } + match &mut Rc::new((1,)) { + (x,) => {} + //~^ ERROR the trait bound `Rc<({integer},)>: DerefMut` is not satisfied + _ => {} + } } diff --git a/tests/ui/pattern/deref-patterns/ref-mut.stderr b/tests/ui/pattern/deref-patterns/ref-mut.stderr index 41f1c3061ce6..24a35b418e95 100644 --- a/tests/ui/pattern/deref-patterns/ref-mut.stderr +++ b/tests/ui/pattern/deref-patterns/ref-mut.stderr @@ -8,13 +8,19 @@ LL | #![feature(deref_patterns)] = note: `#[warn(incomplete_features)]` on by default error[E0277]: the trait bound `Rc<{integer}>: DerefMut` is not satisfied - --> $DIR/ref-mut.rs:13:9 + --> $DIR/ref-mut.rs:17:9 | LL | deref!(x) => {} | ^^^^^^^^^ the trait `DerefMut` is not implemented for `Rc<{integer}>` | = note: this error originates in the macro `deref` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 1 previous error; 1 warning emitted +error[E0277]: the trait bound `Rc<({integer},)>: DerefMut` is not satisfied + --> $DIR/ref-mut.rs:22:9 + | +LL | (x,) => {} + | ^^^^ the trait `DerefMut` is not implemented for `Rc<({integer},)>` + +error: aborting due to 2 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0277`. From d6df469c3d5d87bd5b853812bddae2ca2cbd1cb8 Mon Sep 17 00:00:00 2001 From: dianne Date: Mon, 7 Apr 2025 12:06:03 -0700 Subject: [PATCH 540/606] refactor path pattern checking to get info for peeling See the doc comment on `ResolvedPat` for more information. This and the next couple commits split resolution apart from checking for path, struct, and tuple struct patterns, in order to find the pattern's type before peeling the scrutinee. This helps us avoid peeling the scrutinee when the pattern could match it. The reason this handles errors from resolution after peeling is for struct and tuple struct patterns: we check their subpatterns even when they fail to resolve, to potentially catch more resolution errors. By doing this after peeling, we're able to use the updated `PatInfo`. I don't know if there's currently any observable difference from using the outdated `PatInfo`, but it could potentially be a source of subtle diagnostic bugs in the future, so I'm opting to peel first. --- compiler/rustc_hir_typeck/src/pat.rs | 137 +++++++++++++++++---------- 1 file changed, 89 insertions(+), 48 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index f33e270c357e..327b2736aab1 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -34,7 +34,7 @@ use ty::adjustment::{PatAdjust, PatAdjustment}; use super::report_unexpected_variant_res; use crate::expectation::Expectation; use crate::gather_locals::DeclOrigin; -use crate::{FnCtxt, LoweredTy, errors}; +use crate::{FnCtxt, errors}; const CANNOT_IMPLICITLY_DEREF_POINTER_TRAIT_OBJ: &str = "\ This error indicates that a pointer to a trait type cannot be implicitly dereferenced by a \ @@ -258,6 +258,44 @@ enum InheritedRefMatchRule { }, } +/// When checking patterns containing paths, we need to know the path's resolution to determine +/// whether to apply match ergonomics and implicitly dereference the scrutinee. For instance, when +/// the `deref_patterns` feature is enabled and we're matching against a scrutinee of type +/// `Cow<'a, Option>`, we insert an implicit dereference to allow the pattern `Some(_)` to type, +/// but we must not dereference it when checking the pattern `Cow::Borrowed(_)`. +/// +/// `ResolvedPat` contains the information from resolution needed to determine match ergonomics +/// adjustments, and to finish checking the pattern once we know its adjusted type. +#[derive(Clone, Copy, Debug)] +struct ResolvedPat<'tcx> { + /// The type of the pattern, to be checked against the type of the scrutinee after peeling. This + /// is also used to avoid peeling the scrutinee's constructors (see the `Cow` example above). + ty: Ty<'tcx>, + kind: ResolvedPatKind<'tcx>, +} + +#[derive(Clone, Copy, Debug)] +enum ResolvedPatKind<'tcx> { + Path { res: Res, pat_res: Res, segments: &'tcx [hir::PathSegment<'tcx>] }, +} + +impl<'tcx> ResolvedPat<'tcx> { + fn adjust_mode(&self) -> AdjustMode { + let ResolvedPatKind::Path { res, .. } = self.kind; + if matches!(res, Res::Def(DefKind::Const | DefKind::AssocConst, _)) { + // These constants can be of a reference type, e.g. `const X: &u8 = &0;`. + // Peeling the reference types too early will cause type checking failures. + // Although it would be possible to *also* peel the types of the constants too. + AdjustMode::Pass + } else { + // The remaining possible resolutions for path, struct, and tuple struct patterns are + // ADT constructors. As such, we may peel references freely, but we must not peel the + // ADT itself from the scrutinee if it's a smart pointer. + AdjustMode::Peel { kind: PeelKind::Implicit } + } + } +} + impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Experimental pattern feature: after matching against a shared reference, do we limit the /// default binding mode in subpatterns to be `ref` when it would otherwise be `ref mut`? @@ -334,13 +372,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Conversely, inside this module, `check_pat_top` should never be used. #[instrument(level = "debug", skip(self, pat_info))] fn check_pat(&self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo<'tcx>) { + // For patterns containing paths, we need the path's resolution to determine whether to + // implicitly dereference the scrutinee before matching. let opt_path_res = match pat.kind { PatKind::Expr(PatExpr { kind: PatExprKind::Path(qpath), hir_id, span }) => { - Some(self.resolve_ty_and_res_fully_qualified_call(qpath, *hir_id, *span)) + Some(self.resolve_pat_path(*hir_id, *span, qpath)) } _ => None, }; - let adjust_mode = self.calc_adjust_mode(pat, opt_path_res.map(|(res, ..)| res)); + let adjust_mode = self.calc_adjust_mode(pat, opt_path_res); let ty = self.check_pat_inner(pat, opt_path_res, adjust_mode, expected, pat_info); self.write_ty(pat.hir_id, ty); @@ -406,7 +446,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_pat_inner( &self, pat: &'tcx Pat<'tcx>, - opt_path_res: Option<(Res, Option>, &'tcx [hir::PathSegment<'tcx>])>, + opt_path_res: Option, ErrorGuaranteed>>, adjust_mode: AdjustMode, expected: Ty<'tcx>, pat_info: PatInfo<'tcx>, @@ -515,16 +555,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { PatKind::Missing | PatKind::Wild | PatKind::Err(_) => expected, // We allow any type here; we ensure that the type is uninhabited during match checking. PatKind::Never => expected, - PatKind::Expr(PatExpr { kind: PatExprKind::Path(qpath), hir_id, span }) => { - let ty = self.check_pat_path( - *hir_id, - pat.hir_id, - *span, - qpath, - opt_path_res.unwrap(), - expected, - &pat_info.top_info, - ); + PatKind::Expr(PatExpr { kind: PatExprKind::Path(_), hir_id, .. }) => { + let ty = match opt_path_res.unwrap() { + Ok(ref pr) => { + self.check_pat_path(pat.hir_id, pat.span, pr, expected, &pat_info.top_info) + } + Err(guar) => Ty::new_error(self.tcx, guar), + }; self.write_ty(*hir_id, ty); ty } @@ -566,8 +603,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// How should the binding mode and expected type be adjusted? /// - /// When the pattern is a path pattern, `opt_path_res` must be `Some(res)`. - fn calc_adjust_mode(&self, pat: &'tcx Pat<'tcx>, opt_path_res: Option) -> AdjustMode { + /// When the pattern contains a path, `opt_path_res` must be `Some(path_res)`. + fn calc_adjust_mode( + &self, + pat: &'tcx Pat<'tcx>, + opt_path_res: Option, ErrorGuaranteed>>, + ) -> AdjustMode { match &pat.kind { // Type checking these product-like types successfully always require // that the expected type be of those types and not reference types. @@ -583,17 +624,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | PatKind::Deref(_) => AdjustMode::Peel { kind: PeelKind::ExplicitDerefPat }, // A never pattern behaves somewhat like a literal or unit variant. PatKind::Never => AdjustMode::Peel { kind: PeelKind::Implicit }, - PatKind::Expr(PatExpr { kind: PatExprKind::Path(_), .. }) => match opt_path_res.unwrap() { - // These constants can be of a reference type, e.g. `const X: &u8 = &0;`. - // Peeling the reference types too early will cause type checking failures. - // Although it would be possible to *also* peel the types of the constants too. - Res::Def(DefKind::Const | DefKind::AssocConst, _) => AdjustMode::Pass, - // In the `ValueNS`, we have `SelfCtor(..) | Ctor(_, Const), _)` remaining which - // could successfully compile. The former being `Self` requires a unit struct. - // In either case, and unlike constants, the pattern itself cannot be - // a reference type wherefore peeling doesn't give up any expressiveness. - _ => AdjustMode::Peel { kind: PeelKind::Implicit }, - }, + // For patterns with paths, how we peel the scrutinee depends on the path's resolution. + PatKind::Expr(PatExpr { kind: PatExprKind::Path(_), .. }) => { + // If there was an error resolving the path, default to peeling everything. + opt_path_res.unwrap().map_or(AdjustMode::Peel { kind: PeelKind::Implicit }, |pr| pr.adjust_mode()) + } // String and byte-string literals result in types `&str` and `&[u8]` respectively. // All other literals result in non-reference types. @@ -1216,31 +1251,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - fn check_pat_path( + fn resolve_pat_path( &self, path_id: HirId, - pat_id_for_diag: HirId, span: Span, - qpath: &hir::QPath<'_>, - path_resolution: (Res, Option>, &'tcx [hir::PathSegment<'tcx>]), - expected: Ty<'tcx>, - ti: &TopInfo<'tcx>, - ) -> Ty<'tcx> { + qpath: &'tcx hir::QPath<'_>, + ) -> Result, ErrorGuaranteed> { let tcx = self.tcx; - // We have already resolved the path. - let (res, opt_ty, segments) = path_resolution; + let (res, opt_ty, segments) = + self.resolve_ty_and_res_fully_qualified_call(qpath, path_id, span); match res { Res::Err => { let e = self.dcx().span_delayed_bug(qpath.span(), "`Res::Err` but no error emitted"); self.set_tainted_by_errors(e); - return Ty::new_error(tcx, e); + return Err(e); } Res::Def(DefKind::AssocFn | DefKind::Ctor(_, CtorKind::Fn) | DefKind::Variant, _) => { let expected = "unit struct, unit variant or constant"; let e = report_unexpected_variant_res(tcx, res, None, qpath, span, E0533, expected); - return Ty::new_error(tcx, e); + return Err(e); } Res::SelfCtor(def_id) => { if let ty::Adt(adt_def, _) = *tcx.type_of(def_id).skip_binder().kind() @@ -1258,7 +1289,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { E0533, "unit struct", ); - return Ty::new_error(tcx, e); + return Err(e); } } Res::Def( @@ -1271,15 +1302,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => bug!("unexpected pattern resolution: {:?}", res), } - // Type-check the path. + // Find the type of the path pattern, for later checking. let (pat_ty, pat_res) = self.instantiate_value_path(segments, opt_ty, res, span, span, path_id); + Ok(ResolvedPat { ty: pat_ty, kind: ResolvedPatKind::Path { res, pat_res, segments } }) + } + + fn check_pat_path( + &self, + pat_id_for_diag: HirId, + span: Span, + resolved: &ResolvedPat<'tcx>, + expected: Ty<'tcx>, + ti: &TopInfo<'tcx>, + ) -> Ty<'tcx> { if let Err(err) = - self.demand_suptype_with_origin(&self.pattern_cause(ti, span), expected, pat_ty) + self.demand_suptype_with_origin(&self.pattern_cause(ti, span), expected, resolved.ty) { - self.emit_bad_pat_path(err, pat_id_for_diag, span, res, pat_res, pat_ty, segments); + self.emit_bad_pat_path(err, pat_id_for_diag, span, resolved); } - pat_ty + resolved.ty } fn maybe_suggest_range_literal( @@ -1322,11 +1364,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { mut e: Diag<'_>, hir_id: HirId, pat_span: Span, - res: Res, - pat_res: Res, - pat_ty: Ty<'tcx>, - segments: &'tcx [hir::PathSegment<'tcx>], + resolved_pat: &ResolvedPat<'tcx>, ) { + let ResolvedPatKind::Path { res, pat_res, segments } = resolved_pat.kind; + if let Some(span) = self.tcx.hir_res_span(pat_res) { e.span_label(span, format!("{} defined here", res.descr())); if let [hir::PathSegment { ident, .. }] = &*segments { @@ -1349,7 +1390,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } _ => { - let (type_def_id, item_def_id) = match pat_ty.kind() { + let (type_def_id, item_def_id) = match resolved_pat.ty.kind() { ty::Adt(def, _) => match res { Res::Def(DefKind::Const, def_id) => (Some(def.did()), Some(def_id)), _ => (None, None), From 9196048edddd9eb18294f3eab34453c0f7eb25b3 Mon Sep 17 00:00:00 2001 From: dianne Date: Mon, 3 Mar 2025 16:26:20 -0800 Subject: [PATCH 541/606] refactor struct pattern checking to get info for peeling See the previous commit for details. This doesn't yet extract the struct pat's type's ADT def before peeling, but it should now be possible. --- compiler/rustc_hir_typeck/src/pat.rs | 51 +++++++++++++++++----------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 327b2736aab1..c81965967f05 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -277,12 +277,14 @@ struct ResolvedPat<'tcx> { #[derive(Clone, Copy, Debug)] enum ResolvedPatKind<'tcx> { Path { res: Res, pat_res: Res, segments: &'tcx [hir::PathSegment<'tcx>] }, + Struct { variant: &'tcx VariantDef }, } impl<'tcx> ResolvedPat<'tcx> { fn adjust_mode(&self) -> AdjustMode { - let ResolvedPatKind::Path { res, .. } = self.kind; - if matches!(res, Res::Def(DefKind::Const | DefKind::AssocConst, _)) { + if let ResolvedPatKind::Path { res, .. } = self.kind + && matches!(res, Res::Def(DefKind::Const | DefKind::AssocConst, _)) + { // These constants can be of a reference type, e.g. `const X: &u8 = &0;`. // Peeling the reference types too early will cause type checking failures. // Although it would be possible to *also* peel the types of the constants too. @@ -378,6 +380,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { PatKind::Expr(PatExpr { kind: PatExprKind::Path(qpath), hir_id, span }) => { Some(self.resolve_pat_path(*hir_id, *span, qpath)) } + PatKind::Struct(ref qpath, ..) => Some(self.resolve_pat_struct(pat, qpath)), _ => None, }; let adjust_mode = self.calc_adjust_mode(pat, opt_path_res); @@ -575,9 +578,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { PatKind::TupleStruct(ref qpath, subpats, ddpos) => { self.check_pat_tuple_struct(pat, qpath, subpats, ddpos, expected, pat_info) } - PatKind::Struct(ref qpath, fields, has_rest_pat) => { - self.check_pat_struct(pat, qpath, fields, has_rest_pat, expected, pat_info) - } + PatKind::Struct(_, fields, has_rest_pat) => match opt_path_res.unwrap() { + Ok(ResolvedPat { ty, kind: ResolvedPatKind::Struct { variant } }) => self + .check_pat_struct(pat, fields, has_rest_pat, ty, variant, expected, pat_info), + Err(guar) => { + let ty_err = Ty::new_error(self.tcx, guar); + for field in fields { + self.check_pat(field.pat, ty_err, pat_info); + } + ty_err + } + Ok(pr) => span_bug!(pat.span, "struct pattern resolved to {pr:?}"), + }, PatKind::Guard(pat, cond) => { self.check_pat(pat, expected, pat_info); self.check_expr_has_type_or_error(cond, self.tcx.types.bool, |_| {}); @@ -1220,27 +1232,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Ok(()) } - fn check_pat_struct( + fn resolve_pat_struct( &self, pat: &'tcx Pat<'tcx>, qpath: &hir::QPath<'tcx>, + ) -> Result, ErrorGuaranteed> { + // Resolve the path and check the definition for errors. + let (variant, pat_ty) = self.check_struct_path(qpath, pat.hir_id)?; + Ok(ResolvedPat { ty: pat_ty, kind: ResolvedPatKind::Struct { variant } }) + } + + fn check_pat_struct( + &self, + pat: &'tcx Pat<'tcx>, fields: &'tcx [hir::PatField<'tcx>], has_rest_pat: bool, + pat_ty: Ty<'tcx>, + variant: &'tcx VariantDef, expected: Ty<'tcx>, pat_info: PatInfo<'tcx>, ) -> Ty<'tcx> { - // Resolve the path and check the definition for errors. - let (variant, pat_ty) = match self.check_struct_path(qpath, pat.hir_id) { - Ok(data) => data, - Err(guar) => { - let err = Ty::new_error(self.tcx, guar); - for field in fields { - self.check_pat(field.pat, err, pat_info); - } - return err; - } - }; - // Type-check the path. let _ = self.demand_eqtype_pat(pat.span, expected, pat_ty, &pat_info.top_info); @@ -1366,7 +1377,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pat_span: Span, resolved_pat: &ResolvedPat<'tcx>, ) { - let ResolvedPatKind::Path { res, pat_res, segments } = resolved_pat.kind; + let ResolvedPatKind::Path { res, pat_res, segments } = resolved_pat.kind else { + span_bug!(pat_span, "unexpected resolution for path pattern: {resolved_pat:?}"); + }; if let Some(span) = self.tcx.hir_res_span(pat_res) { e.span_label(span, format!("{} defined here", res.descr())); From 1f40e9aa6a0f0a8e6e4188f15f25d920892bca6a Mon Sep 17 00:00:00 2001 From: dianne Date: Mon, 3 Mar 2025 16:50:53 -0800 Subject: [PATCH 542/606] refactor tuple struct pattern checking to get info for peeling See the previous two commits. --- compiler/rustc_hir_typeck/src/pat.rs | 108 ++++++++++++++++----------- 1 file changed, 65 insertions(+), 43 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index c81965967f05..da5153bed12c 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -278,6 +278,7 @@ struct ResolvedPat<'tcx> { enum ResolvedPatKind<'tcx> { Path { res: Res, pat_res: Res, segments: &'tcx [hir::PathSegment<'tcx>] }, Struct { variant: &'tcx VariantDef }, + TupleStruct { res: Res, variant: &'tcx VariantDef }, } impl<'tcx> ResolvedPat<'tcx> { @@ -381,6 +382,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some(self.resolve_pat_path(*hir_id, *span, qpath)) } PatKind::Struct(ref qpath, ..) => Some(self.resolve_pat_struct(pat, qpath)), + PatKind::TupleStruct(ref qpath, ..) => Some(self.resolve_pat_tuple_struct(pat, qpath)), _ => None, }; let adjust_mode = self.calc_adjust_mode(pat, opt_path_res); @@ -575,9 +577,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { PatKind::Binding(ba, var_id, ident, sub) => { self.check_pat_ident(pat, ba, var_id, ident, sub, expected, pat_info) } - PatKind::TupleStruct(ref qpath, subpats, ddpos) => { - self.check_pat_tuple_struct(pat, qpath, subpats, ddpos, expected, pat_info) - } + PatKind::TupleStruct(ref qpath, subpats, ddpos) => match opt_path_res.unwrap() { + Ok(ResolvedPat { ty, kind: ResolvedPatKind::TupleStruct { res, variant } }) => self + .check_pat_tuple_struct( + pat, qpath, subpats, ddpos, res, ty, variant, expected, pat_info, + ), + Err(guar) => { + let ty_err = Ty::new_error(self.tcx, guar); + for subpat in subpats { + self.check_pat(subpat, ty_err, pat_info); + } + ty_err + } + Ok(pr) => span_bug!(pat.span, "tuple struct pattern resolved to {pr:?}"), + }, PatKind::Struct(_, fields, has_rest_pat) => match opt_path_res.unwrap() { Ok(ResolvedPat { ty, kind: ResolvedPatKind::Struct { variant } }) => self .check_pat_struct(pat, fields, has_rest_pat, ty, variant, expected, pat_info), @@ -1443,12 +1456,61 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { e.emit(); } + fn resolve_pat_tuple_struct( + &self, + pat: &'tcx Pat<'tcx>, + qpath: &'tcx hir::QPath<'tcx>, + ) -> Result, ErrorGuaranteed> { + let tcx = self.tcx; + let report_unexpected_res = |res: Res| { + let expected = "tuple struct or tuple variant"; + let e = report_unexpected_variant_res(tcx, res, None, qpath, pat.span, E0164, expected); + Err(e) + }; + + // Resolve the path and check the definition for errors. + let (res, opt_ty, segments) = + self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span); + if res == Res::Err { + let e = self.dcx().span_delayed_bug(pat.span, "`Res::Err` but no error emitted"); + self.set_tainted_by_errors(e); + return Err(e); + } + + // Type-check the path. + let (pat_ty, res) = + self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.span, pat.hir_id); + if !pat_ty.is_fn() { + return report_unexpected_res(res); + } + + let variant = match res { + Res::Err => { + self.dcx().span_bug(pat.span, "`Res::Err` but no error emitted"); + } + Res::Def(DefKind::AssocConst | DefKind::AssocFn, _) => { + return report_unexpected_res(res); + } + Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) => tcx.expect_variant_res(res), + _ => bug!("unexpected pattern resolution: {:?}", res), + }; + + // Replace constructor type with constructed type for tuple struct patterns. + let pat_ty = pat_ty.fn_sig(tcx).output(); + let pat_ty = pat_ty.no_bound_vars().expect("expected fn type"); + + Ok(ResolvedPat { ty: pat_ty, kind: ResolvedPatKind::TupleStruct { res, variant } }) + } + fn check_pat_tuple_struct( &self, pat: &'tcx Pat<'tcx>, qpath: &'tcx hir::QPath<'tcx>, subpats: &'tcx [Pat<'tcx>], ddpos: hir::DotDotPos, + res: Res, + pat_ty: Ty<'tcx>, + variant: &'tcx VariantDef, expected: Ty<'tcx>, pat_info: PatInfo<'tcx>, ) -> Ty<'tcx> { @@ -1458,46 +1520,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.check_pat(pat, Ty::new_error(tcx, e), pat_info); } }; - let report_unexpected_res = |res: Res| { - let expected = "tuple struct or tuple variant"; - let e = report_unexpected_variant_res(tcx, res, None, qpath, pat.span, E0164, expected); - on_error(e); - e - }; - - // Resolve the path and check the definition for errors. - let (res, opt_ty, segments) = - self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span); - if res == Res::Err { - let e = self.dcx().span_delayed_bug(pat.span, "`Res::Err` but no error emitted"); - self.set_tainted_by_errors(e); - on_error(e); - return Ty::new_error(tcx, e); - } - - // Type-check the path. - let (pat_ty, res) = - self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.span, pat.hir_id); - if !pat_ty.is_fn() { - let e = report_unexpected_res(res); - return Ty::new_error(tcx, e); - } - - let variant = match res { - Res::Err => { - self.dcx().span_bug(pat.span, "`Res::Err` but no error emitted"); - } - Res::Def(DefKind::AssocConst | DefKind::AssocFn, _) => { - let e = report_unexpected_res(res); - return Ty::new_error(tcx, e); - } - Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) => tcx.expect_variant_res(res), - _ => bug!("unexpected pattern resolution: {:?}", res), - }; - - // Replace constructor type with constructed type for tuple struct patterns. - let pat_ty = pat_ty.fn_sig(tcx).output(); - let pat_ty = pat_ty.no_bound_vars().expect("expected fn type"); // Type-check the tuple struct pattern against the expected type. let diag = self.demand_eqtype_pat_diag(pat.span, expected, pat_ty, &pat_info.top_info); From b7fbf20fe1a46c1d5443399f9c624abf00cfb021 Mon Sep 17 00:00:00 2001 From: Joshua Liebow-Feeser Date: Fri, 11 Apr 2025 16:16:12 -0700 Subject: [PATCH 543/606] transmutability: Refactor tests for simplicity --- .../src/maybe_transmutable/tests.rs | 140 +++++++++--------- 1 file changed, 74 insertions(+), 66 deletions(-) diff --git a/compiler/rustc_transmute/src/maybe_transmutable/tests.rs b/compiler/rustc_transmute/src/maybe_transmutable/tests.rs index 4d81382eba02..69a6b1b77f4b 100644 --- a/compiler/rustc_transmute/src/maybe_transmutable/tests.rs +++ b/compiler/rustc_transmute/src/maybe_transmutable/tests.rs @@ -1,93 +1,115 @@ use itertools::Itertools; use super::query_context::test::{Def, UltraMinimal}; -use crate::maybe_transmutable::MaybeTransmutableQuery; -use crate::{Reason, layout}; +use crate::{Answer, Assume, Reason, layout}; + +type Tree = layout::Tree; +type Dfa = layout::Dfa; + +trait Representation { + fn is_transmutable(src: Self, dst: Self, assume: Assume) -> Answer; +} + +impl Representation for Tree { + fn is_transmutable(src: Self, dst: Self, assume: Assume) -> Answer { + crate::maybe_transmutable::MaybeTransmutableQuery::new(src, dst, assume, UltraMinimal) + .answer() + } +} + +impl Representation for Dfa { + fn is_transmutable(src: Self, dst: Self, assume: Assume) -> Answer { + crate::maybe_transmutable::MaybeTransmutableQuery::new(src, dst, assume, UltraMinimal) + .answer() + } +} + +fn is_transmutable( + src: &R, + dst: &R, + assume: Assume, +) -> crate::Answer { + let src = src.clone(); + let dst = dst.clone(); + // The only dimension of the transmutability analysis we want to test + // here is the safety analysis. To ensure this, we disable all other + // toggleable aspects of the transmutability analysis. + R::is_transmutable(src, dst, assume) +} mod safety { use super::*; use crate::Answer; - type Tree = layout::Tree; - const DST_HAS_SAFETY_INVARIANTS: Answer = Answer::No(crate::Reason::DstMayHaveSafetyInvariants); - fn is_transmutable(src: &Tree, dst: &Tree, assume_safety: bool) -> crate::Answer { - let src = src.clone(); - let dst = dst.clone(); - // The only dimension of the transmutability analysis we want to test - // here is the safety analysis. To ensure this, we disable all other - // toggleable aspects of the transmutability analysis. - let assume = crate::Assume { - alignment: true, - lifetimes: true, - validity: true, - safety: assume_safety, - }; - crate::maybe_transmutable::MaybeTransmutableQuery::new(src, dst, assume, UltraMinimal) - .answer() - } - #[test] fn src_safe_dst_safe() { let src = Tree::Def(Def::NoSafetyInvariants).then(Tree::u8()); let dst = Tree::Def(Def::NoSafetyInvariants).then(Tree::u8()); - assert_eq!(is_transmutable(&src, &dst, false), Answer::Yes); - assert_eq!(is_transmutable(&src, &dst, true), Answer::Yes); + assert_eq!(is_transmutable(&src, &dst, Assume::default()), Answer::Yes); + assert_eq!( + is_transmutable(&src, &dst, Assume { safety: true, ..Assume::default() }), + Answer::Yes + ); } #[test] fn src_safe_dst_unsafe() { let src = Tree::Def(Def::NoSafetyInvariants).then(Tree::u8()); let dst = Tree::Def(Def::HasSafetyInvariants).then(Tree::u8()); - assert_eq!(is_transmutable(&src, &dst, false), DST_HAS_SAFETY_INVARIANTS); - assert_eq!(is_transmutable(&src, &dst, true), Answer::Yes); + assert_eq!(is_transmutable(&src, &dst, Assume::default()), DST_HAS_SAFETY_INVARIANTS); + assert_eq!( + is_transmutable(&src, &dst, Assume { safety: true, ..Assume::default() }), + Answer::Yes + ); } #[test] fn src_unsafe_dst_safe() { let src = Tree::Def(Def::HasSafetyInvariants).then(Tree::u8()); let dst = Tree::Def(Def::NoSafetyInvariants).then(Tree::u8()); - assert_eq!(is_transmutable(&src, &dst, false), Answer::Yes); - assert_eq!(is_transmutable(&src, &dst, true), Answer::Yes); + assert_eq!(is_transmutable(&src, &dst, Assume::default()), Answer::Yes); + assert_eq!( + is_transmutable(&src, &dst, Assume { safety: true, ..Assume::default() }), + Answer::Yes + ); } #[test] fn src_unsafe_dst_unsafe() { let src = Tree::Def(Def::HasSafetyInvariants).then(Tree::u8()); let dst = Tree::Def(Def::HasSafetyInvariants).then(Tree::u8()); - assert_eq!(is_transmutable(&src, &dst, false), DST_HAS_SAFETY_INVARIANTS); - assert_eq!(is_transmutable(&src, &dst, true), Answer::Yes); + assert_eq!(is_transmutable(&src, &dst, Assume::default()), DST_HAS_SAFETY_INVARIANTS); + assert_eq!( + is_transmutable(&src, &dst, Assume { safety: true, ..Assume::default() }), + Answer::Yes + ); } } mod bool { use super::*; - use crate::Answer; #[test] fn should_permit_identity_transmutation_tree() { - let answer = crate::maybe_transmutable::MaybeTransmutableQuery::new( - layout::Tree::::bool(), - layout::Tree::::bool(), - crate::Assume { alignment: false, lifetimes: false, validity: true, safety: false }, - UltraMinimal, - ) - .answer(); - assert_eq!(answer, Answer::Yes); + let src = Tree::bool(); + assert_eq!(is_transmutable(&src, &src, Assume::default()), Answer::Yes); + assert_eq!( + is_transmutable(&src, &src, Assume { validity: true, ..Assume::default() }), + Answer::Yes + ); } #[test] fn should_permit_identity_transmutation_dfa() { - let answer = crate::maybe_transmutable::MaybeTransmutableQuery::new( - layout::Dfa::::bool(), - layout::Dfa::::bool(), - crate::Assume { alignment: false, lifetimes: false, validity: true, safety: false }, - UltraMinimal, - ) - .answer(); - assert_eq!(answer, Answer::Yes); + let src = Dfa::bool(); + assert_eq!(is_transmutable(&src, &src, Assume::default()), Answer::Yes); + assert_eq!( + is_transmutable(&src, &src, Assume { validity: true, ..Assume::default() }), + Answer::Yes + ); } #[test] @@ -122,13 +144,7 @@ mod bool { if src_set.is_subset(&dst_set) { assert_eq!( Answer::Yes, - MaybeTransmutableQuery::new( - src_layout.clone(), - dst_layout.clone(), - crate::Assume { validity: false, ..crate::Assume::default() }, - UltraMinimal, - ) - .answer(), + is_transmutable(&src_layout, &dst_layout, Assume::default()), "{:?} SHOULD be transmutable into {:?}", src_layout, dst_layout @@ -136,13 +152,11 @@ mod bool { } else if !src_set.is_disjoint(&dst_set) { assert_eq!( Answer::Yes, - MaybeTransmutableQuery::new( - src_layout.clone(), - dst_layout.clone(), - crate::Assume { validity: true, ..crate::Assume::default() }, - UltraMinimal, - ) - .answer(), + is_transmutable( + &src_layout, + &dst_layout, + Assume { validity: true, ..Assume::default() } + ), "{:?} SHOULD be transmutable (assuming validity) into {:?}", src_layout, dst_layout @@ -150,13 +164,7 @@ mod bool { } else { assert_eq!( Answer::No(Reason::DstIsBitIncompatible), - MaybeTransmutableQuery::new( - src_layout.clone(), - dst_layout.clone(), - crate::Assume { validity: false, ..crate::Assume::default() }, - UltraMinimal, - ) - .answer(), + is_transmutable(&src_layout, &dst_layout, Assume::default()), "{:?} should NOT be transmutable into {:?}", src_layout, dst_layout From 8b09cbba210741a16bedb60d54b7b06b78021ba8 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Tue, 15 Apr 2025 16:27:14 -0400 Subject: [PATCH 544/606] Update cargo * The license exception of sha1_smol with BSD-3-Clause is no longer needed, as `gix-*` doesn't depend on it. * Cargo depends on zlib-rs, which is distributed under Zlib license --- src/tools/cargo | 2 +- src/tools/tidy/src/deps.rs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/tools/cargo b/src/tools/cargo index 864f74d4eadc..d811228b14ae 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 864f74d4eadcaea3eeda37a2e7f4d34de233d51e +Subproject commit d811228b14ae2707323f37346aee3f4147e247e6 diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 88c2a02798ac..8eca2eb45039 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -132,15 +132,16 @@ const EXCEPTIONS_CARGO: ExceptionList = &[ ("fiat-crypto", "MIT OR Apache-2.0 OR BSD-1-Clause"), ("foldhash", "Zlib"), ("im-rc", "MPL-2.0+"), + ("libz-rs-sys", "Zlib"), ("normalize-line-endings", "Apache-2.0"), ("openssl", "Apache-2.0"), ("ryu", "Apache-2.0 OR BSL-1.0"), // BSL is not acceptble, but we use it under Apache-2.0 - ("sha1_smol", "BSD-3-Clause"), ("similar", "Apache-2.0"), ("sized-chunks", "MPL-2.0+"), ("subtle", "BSD-3-Clause"), ("supports-hyperlinks", "Apache-2.0"), ("unicode-bom", "Apache-2.0"), + ("zlib-rs", "Zlib"), // tidy-alphabetical-end ]; From 923d95cc9f318a88cde9166dd44f785c8bcdadfb Mon Sep 17 00:00:00 2001 From: dianne Date: Sat, 8 Mar 2025 21:30:48 -0800 Subject: [PATCH 545/606] don't peel ADTs the pattern could match This is the use for the previous commits' refactors; see the messages there for more information. --- compiler/rustc_hir_typeck/src/pat.rs | 49 +++++++++++++------ .../deref-patterns/implicit-const-deref.rs | 19 +++++++ .../implicit-const-deref.stderr | 16 ++++++ .../deref-patterns/implicit-cow-deref.rs | 44 +++++++++++++++++ 4 files changed, 114 insertions(+), 14 deletions(-) create mode 100644 tests/ui/pattern/deref-patterns/implicit-const-deref.rs create mode 100644 tests/ui/pattern/deref-patterns/implicit-const-deref.stderr create mode 100644 tests/ui/pattern/deref-patterns/implicit-cow-deref.rs diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index da5153bed12c..46916f22d0e2 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -9,6 +9,7 @@ use rustc_errors::{ Applicability, Diag, ErrorGuaranteed, MultiSpan, pluralize, struct_span_code_err, }; use rustc_hir::def::{CtorKind, DefKind, Res}; +use rustc_hir::def_id::DefId; use rustc_hir::pat_util::EnumerateAndAdjustIterator; use rustc_hir::{ self as hir, BindingMode, ByRef, ExprKind, HirId, LangItem, Mutability, Pat, PatExpr, @@ -179,8 +180,16 @@ enum PeelKind { /// ADTs. In order to peel only as much as necessary for the pattern to match, the `until_adt` /// field contains the ADT def that the pattern is a constructor for, if applicable, so that we /// don't peel it. See [`ResolvedPat`] for more information. - // TODO: add `ResolvedPat` and `until_adt`. - Implicit, + Implicit { until_adt: Option }, +} + +impl AdjustMode { + const fn peel_until_adt(opt_adt_def: Option) -> AdjustMode { + AdjustMode::Peel { kind: PeelKind::Implicit { until_adt: opt_adt_def } } + } + const fn peel_all() -> AdjustMode { + AdjustMode::peel_until_adt(None) + } } /// `ref mut` bindings (explicit or match-ergonomics) are not allowed behind an `&` reference. @@ -294,7 +303,7 @@ impl<'tcx> ResolvedPat<'tcx> { // The remaining possible resolutions for path, struct, and tuple struct patterns are // ADT constructors. As such, we may peel references freely, but we must not peel the // ADT itself from the scrutinee if it's a smart pointer. - AdjustMode::Peel { kind: PeelKind::Implicit } + AdjustMode::peel_until_adt(self.ty.ty_adt_def().map(|adt| adt.did())) } } } @@ -521,14 +530,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If `deref_patterns` is enabled, peel a smart pointer from the scrutinee type. See the // examples in `tests/ui/pattern/deref_patterns/`. _ if self.tcx.features().deref_patterns() - && let AdjustMode::Peel { kind: PeelKind::Implicit } = adjust_mode + && let AdjustMode::Peel { kind: PeelKind::Implicit { until_adt } } = adjust_mode && pat.default_binding_modes // For simplicity, only apply overloaded derefs if `expected` is a known ADT. // FIXME(deref_patterns): we'll get better diagnostics for users trying to // implicitly deref generics if we allow them here, but primitives, tuples, and // inference vars definitely should be stopped. Figure out what makes most sense. - // TODO: stop peeling if the pattern is a constructor for the scrutinee type - && expected.is_adt() + && let ty::Adt(scrutinee_adt, _) = *expected.kind() + // Don't peel if the pattern type already matches the scrutinee. E.g., stop here if + // matching on a `Cow<'a, T>` scrutinee with a `Cow::Owned(_)` pattern. + && until_adt != Some(scrutinee_adt.did()) // At this point, the pattern isn't able to match `expected` without peeling. Check // that it implements `Deref` before assuming it's a smart pointer, to get a normal // type error instead of a missing impl error if not. This only checks for `Deref`, @@ -637,22 +648,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match &pat.kind { // Type checking these product-like types successfully always require // that the expected type be of those types and not reference types. - PatKind::Struct(..) - | PatKind::TupleStruct(..) - | PatKind::Tuple(..) + PatKind::Tuple(..) | PatKind::Range(..) - | PatKind::Slice(..) => AdjustMode::Peel { kind: PeelKind::Implicit }, + | PatKind::Slice(..) => AdjustMode::peel_all(), // When checking an explicit deref pattern, only peel reference types. // FIXME(deref_patterns): If box patterns and deref patterns need to coexist, box // patterns may want `PeelKind::Implicit`, stopping on encountering a box. | PatKind::Box(_) | PatKind::Deref(_) => AdjustMode::Peel { kind: PeelKind::ExplicitDerefPat }, // A never pattern behaves somewhat like a literal or unit variant. - PatKind::Never => AdjustMode::Peel { kind: PeelKind::Implicit }, + PatKind::Never => AdjustMode::peel_all(), // For patterns with paths, how we peel the scrutinee depends on the path's resolution. - PatKind::Expr(PatExpr { kind: PatExprKind::Path(_), .. }) => { + PatKind::Struct(..) + | PatKind::TupleStruct(..) + | PatKind::Expr(PatExpr { kind: PatExprKind::Path(_), .. }) => { // If there was an error resolving the path, default to peeling everything. - opt_path_res.unwrap().map_or(AdjustMode::Peel { kind: PeelKind::Implicit }, |pr| pr.adjust_mode()) + opt_path_res.unwrap().map_or(AdjustMode::peel_all(), |pr| pr.adjust_mode()) } // String and byte-string literals result in types `&str` and `&[u8]` respectively. @@ -662,7 +673,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Call `resolve_vars_if_possible` here for inline const blocks. PatKind::Expr(lt) => match self.resolve_vars_if_possible(self.check_pat_expr_unadjusted(lt)).kind() { ty::Ref(..) => AdjustMode::Pass, - _ => AdjustMode::Peel { kind: PeelKind::Implicit }, + _ => { + // Path patterns have already been handled, and inline const blocks currently + // aren't possible to write, so any handling for them would be untested. + if cfg!(debug_assertions) + && self.tcx.features().deref_patterns() + && !matches!(lt.kind, PatExprKind::Lit { .. }) + { + span_bug!(lt.span, "FIXME(deref_patterns): adjust mode unimplemented for {:?}", lt.kind); + } + AdjustMode::peel_all() + } }, // Ref patterns are complicated, we handle them in `check_pat_ref`. diff --git a/tests/ui/pattern/deref-patterns/implicit-const-deref.rs b/tests/ui/pattern/deref-patterns/implicit-const-deref.rs new file mode 100644 index 000000000000..70f89629bc22 --- /dev/null +++ b/tests/ui/pattern/deref-patterns/implicit-const-deref.rs @@ -0,0 +1,19 @@ +//! Test that we get an error about structural equality rather than a type error when attempting to +//! use const patterns of library pointer types. Currently there aren't any smart pointers that can +//! be used in constant patterns, but we still need to make sure we don't implicitly dereference the +//! scrutinee and end up with a type error; this would prevent us from reporting that only constants +//! supporting structural equality can be used as patterns. +#![feature(deref_patterns)] +#![allow(incomplete_features)] + +const EMPTY: Vec<()> = Vec::new(); + +fn main() { + // FIXME(inline_const_pat): if `inline_const_pat` is reinstated, there should be a case here for + // inline const block patterns as well; they're checked differently than named constants. + match vec![()] { + EMPTY => {} + //~^ ERROR: constant of non-structural type `Vec<()>` in a pattern + _ => {} + } +} diff --git a/tests/ui/pattern/deref-patterns/implicit-const-deref.stderr b/tests/ui/pattern/deref-patterns/implicit-const-deref.stderr new file mode 100644 index 000000000000..21d09ec44c4f --- /dev/null +++ b/tests/ui/pattern/deref-patterns/implicit-const-deref.stderr @@ -0,0 +1,16 @@ +error: constant of non-structural type `Vec<()>` in a pattern + --> $DIR/implicit-const-deref.rs:15:9 + | +LL | const EMPTY: Vec<()> = Vec::new(); + | -------------------- constant defined here +... +LL | EMPTY => {} + | ^^^^^ constant of non-structural type + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + | + = note: `Vec<()>` must be annotated with `#[derive(PartialEq)]` to be usable in patterns + | + = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details + +error: aborting due to 1 previous error + diff --git a/tests/ui/pattern/deref-patterns/implicit-cow-deref.rs b/tests/ui/pattern/deref-patterns/implicit-cow-deref.rs new file mode 100644 index 000000000000..6a363c58b633 --- /dev/null +++ b/tests/ui/pattern/deref-patterns/implicit-cow-deref.rs @@ -0,0 +1,44 @@ +//@ run-pass +//! Test that implicit deref patterns interact as expected with `Cow` constructor patterns. +#![feature(deref_patterns)] +#![allow(incomplete_features)] + +use std::borrow::Cow; + +fn main() { + let cow: Cow<'static, [u8]> = Cow::from(&[1, 2, 3]); + + match cow { + [..] => {} + _ => unreachable!(), + } + + match cow { + Cow::Borrowed(_) => {} + Cow::Owned(_) => unreachable!(), + } + + match Box::new(&cow) { + Cow::Borrowed { 0: _ } => {} + Cow::Owned { 0: _ } => unreachable!(), + _ => unreachable!(), + } + + let cow_of_cow: Cow<'_, Cow<'static, [u8]>> = Cow::Owned(cow); + + match cow_of_cow { + [..] => {} + _ => unreachable!(), + } + + match cow_of_cow { + Cow::Borrowed(_) => unreachable!(), + Cow::Owned(_) => {} + } + + match Box::new(&cow_of_cow) { + Cow::Borrowed { 0: _ } => unreachable!(), + Cow::Owned { 0: _ } => {} + _ => unreachable!(), + } +} From 977c9ab7a2ead006e06b1b78cc1b6ac63245560b Mon Sep 17 00:00:00 2001 From: dianne Date: Sun, 9 Mar 2025 17:02:34 -0700 Subject: [PATCH 546/606] respect the tcx's recursion limit when peeling --- compiler/rustc_hir_analysis/src/autoderef.rs | 10 +++++-- compiler/rustc_hir_typeck/src/pat.rs | 28 +++++++++++++------ .../pattern/deref-patterns/recursion-limit.rs | 23 +++++++++++++++ .../deref-patterns/recursion-limit.stderr | 18 ++++++++++++ 4 files changed, 68 insertions(+), 11 deletions(-) create mode 100644 tests/ui/pattern/deref-patterns/recursion-limit.rs create mode 100644 tests/ui/pattern/deref-patterns/recursion-limit.stderr diff --git a/compiler/rustc_hir_analysis/src/autoderef.rs b/compiler/rustc_hir_analysis/src/autoderef.rs index b3eade8c8ae4..99e495d92669 100644 --- a/compiler/rustc_hir_analysis/src/autoderef.rs +++ b/compiler/rustc_hir_analysis/src/autoderef.rs @@ -2,8 +2,8 @@ use rustc_infer::infer::InferCtxt; use rustc_infer::traits::PredicateObligations; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; use rustc_session::Limit; -use rustc_span::Span; use rustc_span::def_id::{LOCAL_CRATE, LocalDefId}; +use rustc_span::{ErrorGuaranteed, Span}; use rustc_trait_selection::traits::ObligationCtxt; use tracing::{debug, instrument}; @@ -259,7 +259,11 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { } } -pub fn report_autoderef_recursion_limit_error<'tcx>(tcx: TyCtxt<'tcx>, span: Span, ty: Ty<'tcx>) { +pub fn report_autoderef_recursion_limit_error<'tcx>( + tcx: TyCtxt<'tcx>, + span: Span, + ty: Ty<'tcx>, +) -> ErrorGuaranteed { // We've reached the recursion limit, error gracefully. let suggested_limit = match tcx.recursion_limit() { Limit(0) => Limit(2), @@ -270,5 +274,5 @@ pub fn report_autoderef_recursion_limit_error<'tcx>(tcx: TyCtxt<'tcx>, span: Spa ty, suggested_limit, crate_name: tcx.crate_name(LOCAL_CRATE), - }); + }) } diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 46916f22d0e2..e5e4fc7f8b77 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -15,6 +15,7 @@ use rustc_hir::{ self as hir, BindingMode, ByRef, ExprKind, HirId, LangItem, Mutability, Pat, PatExpr, PatExprKind, PatKind, expr_needs_parens, }; +use rustc_hir_analysis::autoderef::report_autoderef_recursion_limit_error; use rustc_infer::infer; use rustc_middle::traits::PatternOriginExpr; use rustc_middle::ty::{self, Ty, TypeVisitableExt}; @@ -552,17 +553,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { debug!("scrutinee ty {expected:?} is a smart pointer, inserting overloaded deref"); // The scrutinee is a smart pointer; implicitly dereference it. This adds a // requirement that `expected: DerefPure`. - let inner_ty = self.deref_pat_target(pat.span, expected); + let mut inner_ty = self.deref_pat_target(pat.span, expected); // Once we've checked `pat`, we'll add a `DerefMut` bound if it contains any // `ref mut` bindings. See `Self::register_deref_mut_bounds_if_needed`. - // Preserve the smart pointer type for THIR lowering and upvar analysis. - self.typeck_results - .borrow_mut() - .pat_adjustments_mut() - .entry(pat.hir_id) - .or_default() - .push(PatAdjustment { kind: PatAdjust::OverloadedDeref, source: expected }); + let mut typeck_results = self.typeck_results.borrow_mut(); + let mut pat_adjustments_table = typeck_results.pat_adjustments_mut(); + let pat_adjustments = pat_adjustments_table.entry(pat.hir_id).or_default(); + // We may reach the recursion limit if a user matches on a type `T` satisfying + // `T: Deref`; error gracefully in this case. + // FIXME(deref_patterns): If `deref_patterns` stabilizes, it may make sense to move + // this check out of this branch. Alternatively, this loop could be implemented with + // autoderef and this check removed. For now though, don't break code compiling on + // stable with lots of `&`s and a low recursion limit, if anyone's done that. + if self.tcx.recursion_limit().value_within_limit(pat_adjustments.len()) { + // Preserve the smart pointer type for THIR lowering and closure upvar analysis. + pat_adjustments + .push(PatAdjustment { kind: PatAdjust::OverloadedDeref, source: expected }); + } else { + let guar = report_autoderef_recursion_limit_error(self.tcx, pat.span, expected); + inner_ty = Ty::new_error(self.tcx, guar); + } + drop(typeck_results); // Recurse, using the old pat info to keep `current_depth` to its old value. // Peeling smart pointers does not update the default binding mode. diff --git a/tests/ui/pattern/deref-patterns/recursion-limit.rs b/tests/ui/pattern/deref-patterns/recursion-limit.rs new file mode 100644 index 000000000000..c5fe520f6f1a --- /dev/null +++ b/tests/ui/pattern/deref-patterns/recursion-limit.rs @@ -0,0 +1,23 @@ +//! Test that implicit deref patterns respect the recursion limit +#![feature(deref_patterns)] +#![allow(incomplete_features)] +#![recursion_limit = "8"] + +use std::ops::Deref; + +struct Cyclic; +impl Deref for Cyclic { + type Target = Cyclic; + fn deref(&self) -> &Cyclic { + &Cyclic + } +} + +fn main() { + match &Box::new(Cyclic) { + () => {} + //~^ ERROR: reached the recursion limit while auto-dereferencing `Cyclic` + //~| ERROR: the trait bound `Cyclic: DerefPure` is not satisfied + _ => {} + } +} diff --git a/tests/ui/pattern/deref-patterns/recursion-limit.stderr b/tests/ui/pattern/deref-patterns/recursion-limit.stderr new file mode 100644 index 000000000000..9a83d1eb5a4a --- /dev/null +++ b/tests/ui/pattern/deref-patterns/recursion-limit.stderr @@ -0,0 +1,18 @@ +error[E0055]: reached the recursion limit while auto-dereferencing `Cyclic` + --> $DIR/recursion-limit.rs:18:9 + | +LL | () => {} + | ^^ deref recursion limit reached + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "16"]` attribute to your crate (`recursion_limit`) + +error[E0277]: the trait bound `Cyclic: DerefPure` is not satisfied + --> $DIR/recursion-limit.rs:18:9 + | +LL | () => {} + | ^^ the trait `DerefPure` is not implemented for `Cyclic` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0055, E0277. +For more information about an error, try `rustc --explain E0055`. From ff0d4bc743086111c841812ec9925efb075d1243 Mon Sep 17 00:00:00 2001 From: dianne Date: Thu, 13 Mar 2025 22:34:26 -0700 Subject: [PATCH 547/606] upvar inference for implicit deref patterns --- .../rustc_hir_typeck/src/expr_use_visitor.rs | 54 +++++++++++++++---- .../pattern/deref-patterns/closure_capture.rs | 27 ++++++++++ 2 files changed, 70 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index f43f9b5187b6..c92aa228cc2c 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -1000,6 +1000,8 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx // determines whether to borrow *at the level of the deref pattern* rather than // borrowing the bound place (since that inner place is inside the temporary that // stores the result of calling `deref()`/`deref_mut()` so can't be captured). + // HACK: this could be a fake pattern corresponding to a deref inserted by match + // ergonomics, in which case `pat.hir_id` will be the id of the subpattern. let mutable = self.cx.typeck_results().pat_has_ref_mut_binding(subpattern); let mutability = if mutable { hir::Mutability::Mut } else { hir::Mutability::Not }; @@ -1675,12 +1677,31 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx // Then we see that to get the same result, we must start with // `deref { deref { place_foo }}` instead of `place_foo` since the pattern is now `Some(x,)` // and not `&&Some(x,)`, even though its assigned type is that of `&&Some(x,)`. - for _ in - 0..self.cx.typeck_results().pat_adjustments().get(pat.hir_id).map_or(0, |v| v.len()) - { + let typeck_results = self.cx.typeck_results(); + let adjustments: &[adjustment::PatAdjustment<'tcx>] = + typeck_results.pat_adjustments().get(pat.hir_id).map_or(&[], |v| &**v); + let mut adjusts = adjustments.iter().peekable(); + while let Some(adjust) = adjusts.next() { debug!("applying adjustment to place_with_id={:?}", place_with_id); - place_with_id = self.cat_deref(pat.hir_id, place_with_id)?; + place_with_id = match adjust.kind { + adjustment::PatAdjust::BuiltinDeref => self.cat_deref(pat.hir_id, place_with_id)?, + adjustment::PatAdjust::OverloadedDeref => { + // This adjustment corresponds to an overloaded deref; it borrows the scrutinee to + // call `Deref::deref` or `DerefMut::deref_mut`. Invoke the callback before setting + // `place_with_id` to the temporary storing the result of the deref. + // HACK(dianne): giving the callback a fake deref pattern makes sure it behaves the + // same as it would if this were an explicit deref pattern. + op(&place_with_id, &hir::Pat { kind: PatKind::Deref(pat), ..*pat })?; + let target_ty = match adjusts.peek() { + Some(&&next_adjust) => next_adjust.source, + // At the end of the deref chain, we get `pat`'s scrutinee. + None => self.pat_ty_unadjusted(pat)?, + }; + self.pat_deref_temp(pat.hir_id, pat, target_ty)? + } + }; } + drop(typeck_results); // explicitly release borrow of typeck results, just in case. let place_with_id = place_with_id; // lose mutability debug!("applied adjustment derefs to get place_with_id={:?}", place_with_id); @@ -1783,14 +1804,8 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx self.cat_pattern(subplace, subpat, op)?; } PatKind::Deref(subpat) => { - let mutable = self.cx.typeck_results().pat_has_ref_mut_binding(subpat); - let mutability = if mutable { hir::Mutability::Mut } else { hir::Mutability::Not }; - let re_erased = self.cx.tcx().lifetimes.re_erased; let ty = self.pat_ty_adjusted(subpat)?; - let ty = Ty::new_ref(self.cx.tcx(), re_erased, ty, mutability); - // A deref pattern generates a temporary. - let base = self.cat_rvalue(pat.hir_id, ty); - let place = self.cat_deref(pat.hir_id, base)?; + let place = self.pat_deref_temp(pat.hir_id, subpat, ty)?; self.cat_pattern(place, subpat, op)?; } @@ -1843,6 +1858,23 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx Ok(()) } + /// Represents the place of the temp that stores the scrutinee of a deref pattern's interior. + fn pat_deref_temp( + &self, + hir_id: HirId, + inner: &hir::Pat<'_>, + target_ty: Ty<'tcx>, + ) -> Result, Cx::Error> { + let mutable = self.cx.typeck_results().pat_has_ref_mut_binding(inner); + let mutability = if mutable { hir::Mutability::Mut } else { hir::Mutability::Not }; + let re_erased = self.cx.tcx().lifetimes.re_erased; + let ty = Ty::new_ref(self.cx.tcx(), re_erased, target_ty, mutability); + // A deref pattern stores the result of `Deref::deref` or `DerefMut::deref_mut` ... + let base = self.cat_rvalue(hir_id, ty); + // ... and the inner pattern matches on the place behind that reference. + self.cat_deref(hir_id, base) + } + fn is_multivariant_adt(&self, ty: Ty<'tcx>, span: Span) -> bool { if let ty::Adt(def, _) = self.cx.try_structurally_resolve_type(span, ty).kind() { // Note that if a non-exhaustive SingleVariant is defined in another crate, we need diff --git a/tests/ui/pattern/deref-patterns/closure_capture.rs b/tests/ui/pattern/deref-patterns/closure_capture.rs index fc0ddedac2b7..08586b6c7abd 100644 --- a/tests/ui/pattern/deref-patterns/closure_capture.rs +++ b/tests/ui/pattern/deref-patterns/closure_capture.rs @@ -11,6 +11,15 @@ fn main() { assert_eq!(b.len(), 3); f(); + let v = vec![1, 2, 3]; + let f = || { + // this should count as a borrow of `v` as a whole + let [.., x] = v else { unreachable!() }; + assert_eq!(x, 3); + }; + assert_eq!(v, [1, 2, 3]); + f(); + let mut b = Box::new("aaa".to_string()); let mut f = || { let deref!(ref mut s) = b else { unreachable!() }; @@ -18,4 +27,22 @@ fn main() { }; f(); assert_eq!(b.len(), 5); + + let mut v = vec![1, 2, 3]; + let mut f = || { + // this should count as a mutable borrow of `v` as a whole + let [.., ref mut x] = v else { unreachable!() }; + *x = 4; + }; + f(); + assert_eq!(v, [1, 2, 4]); + + let mut v = vec![1, 2, 3]; + let mut f = || { + // here, `[.., x]` is adjusted by both an overloaded deref and a builtin deref + let [.., x] = &mut v else { unreachable!() }; + *x = 4; + }; + f(); + assert_eq!(v, [1, 2, 4]); } From 4c4b61b730ee7b53918043ff403bbc8e2d6d0eb0 Mon Sep 17 00:00:00 2001 From: dianne Date: Fri, 14 Mar 2025 02:51:20 -0700 Subject: [PATCH 548/606] add a feature gate test Implicit deref patterns allow previously ill-typed programs. Make sure they're still ill-typed without the feature gate. I've thrown in a test for `deref!(_)` too, though it seems it refers to `deref_patterns` as a library feature. --- tests/ui/pattern/deref-patterns/needs-gate.rs | 15 ++++++++++ .../pattern/deref-patterns/needs-gate.stderr | 29 +++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 tests/ui/pattern/deref-patterns/needs-gate.rs create mode 100644 tests/ui/pattern/deref-patterns/needs-gate.stderr diff --git a/tests/ui/pattern/deref-patterns/needs-gate.rs b/tests/ui/pattern/deref-patterns/needs-gate.rs new file mode 100644 index 000000000000..2d5ec45217fb --- /dev/null +++ b/tests/ui/pattern/deref-patterns/needs-gate.rs @@ -0,0 +1,15 @@ +// gate-test-deref_patterns + +fn main() { + match Box::new(0) { + deref!(0) => {} + //~^ ERROR: use of unstable library feature `deref_patterns`: placeholder syntax for deref patterns + _ => {} + } + + match Box::new(0) { + 0 => {} + //~^ ERROR: mismatched types + _ => {} + } +} diff --git a/tests/ui/pattern/deref-patterns/needs-gate.stderr b/tests/ui/pattern/deref-patterns/needs-gate.stderr new file mode 100644 index 000000000000..8687b5dc977d --- /dev/null +++ b/tests/ui/pattern/deref-patterns/needs-gate.stderr @@ -0,0 +1,29 @@ +error[E0658]: use of unstable library feature `deref_patterns`: placeholder syntax for deref patterns + --> $DIR/needs-gate.rs:5:9 + | +LL | deref!(0) => {} + | ^^^^^ + | + = note: see issue #87121 for more information + = help: add `#![feature(deref_patterns)]` 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[E0308]: mismatched types + --> $DIR/needs-gate.rs:11:9 + | +LL | match Box::new(0) { + | ----------- this expression has type `Box<{integer}>` +LL | 0 => {} + | ^ expected `Box<{integer}>`, found integer + | + = note: expected struct `Box<{integer}>` + found type `{integer}` +help: consider dereferencing to access the inner value using the Deref trait + | +LL | match *Box::new(0) { + | + + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0308, E0658. +For more information about an error, try `rustc --explain E0308`. From 93d13e98069478ab286d28b42333f74b88308a99 Mon Sep 17 00:00:00 2001 From: dianne Date: Fri, 14 Mar 2025 03:51:54 -0700 Subject: [PATCH 549/606] add an unstable book chapter - Clarifies the uses of implicit and explicit deref patterns - Includes motivating examples for both syntaxes - Shows the interaction with match ergonomics for reference types - Cross-links with `string_deref_patterns` and `box_patterns` The examples are contrived, but hopefully the intent comes across. --- .../src/language-features/box-patterns.md | 4 ++ .../src/language-features/deref-patterns.md | 57 +++++++++++++++++++ .../string-deref-patterns.md | 3 + 3 files changed, 64 insertions(+) create mode 100644 src/doc/unstable-book/src/language-features/deref-patterns.md diff --git a/src/doc/unstable-book/src/language-features/box-patterns.md b/src/doc/unstable-book/src/language-features/box-patterns.md index a1ac09633b75..c8a15b8477ee 100644 --- a/src/doc/unstable-book/src/language-features/box-patterns.md +++ b/src/doc/unstable-book/src/language-features/box-patterns.md @@ -6,6 +6,8 @@ The tracking issue for this feature is: [#29641] ------------------------ +> **Note**: This feature will be superseded by [`deref_patterns`] in the future. + Box patterns let you match on `Box`s: @@ -28,3 +30,5 @@ fn main() { } } ``` + +[`deref_patterns`]: ./deref-patterns.md diff --git a/src/doc/unstable-book/src/language-features/deref-patterns.md b/src/doc/unstable-book/src/language-features/deref-patterns.md new file mode 100644 index 000000000000..d0102a665b0b --- /dev/null +++ b/src/doc/unstable-book/src/language-features/deref-patterns.md @@ -0,0 +1,57 @@ +# `deref_patterns` + +The tracking issue for this feature is: [#87121] + +[#87121]: https://github.com/rust-lang/rust/issues/87121 + +------------------------ + +> **Note**: This feature is incomplete. In the future, it is meant to supersede +> [`box_patterns`](./box-patterns.md) and [`string_deref_patterns`](./string-deref-patterns.md). + +This feature permits pattern matching on [smart pointers in the standard library] through their +`Deref` target types, either implicitly or with explicit `deref!(_)` patterns (the syntax of which +is currently a placeholder). + +```rust +#![feature(deref_patterns)] +#![allow(incomplete_features)] + +let mut v = vec![Box::new(Some(0))]; + +// Implicit dereferences are inserted when a pattern can match against the +// result of repeatedly dereferencing but can't match against a smart +// pointer itself. This works alongside match ergonomics for references. +if let [Some(x)] = &mut v { + *x += 1; +} + +// Explicit `deref!(_)` patterns may instead be used when finer control is +// needed, e.g. to dereference only a single smart pointer, or to bind the +// the result of dereferencing to a variable. +if let deref!([deref!(opt_x @ Some(1))]) = &mut v { + opt_x.as_mut().map(|x| *x += 1); +} + +assert_eq!(v, [Box::new(Some(2))]); +``` + +Without this feature, it may be necessary to introduce temporaries to represent dereferenced places +when matching on nested structures: + +```rust +let mut v = vec![Box::new(Some(0))]; +if let [b] = &mut *v { + if let Some(x) = &mut **b { + *x += 1; + } +} +if let [b] = &mut *v { + if let opt_x @ Some(1) = &mut **b { + opt_x.as_mut().map(|x| *x += 1); + } +} +assert_eq!(v, [Box::new(Some(2))]); +``` + +[smart pointers in the standard library]: https://doc.rust-lang.org/std/ops/trait.DerefPure.html#implementors diff --git a/src/doc/unstable-book/src/language-features/string-deref-patterns.md b/src/doc/unstable-book/src/language-features/string-deref-patterns.md index 3723830751e8..366bb15d4ea8 100644 --- a/src/doc/unstable-book/src/language-features/string-deref-patterns.md +++ b/src/doc/unstable-book/src/language-features/string-deref-patterns.md @@ -6,6 +6,8 @@ The tracking issue for this feature is: [#87121] ------------------------ +> **Note**: This feature will be superseded by [`deref_patterns`] in the future. + This feature permits pattern matching `String` to `&str` through [its `Deref` implementation]. ```rust @@ -42,4 +44,5 @@ pub fn is_it_the_answer(value: Value) -> bool { } ``` +[`deref_patterns`]: ./deref-patterns.md [its `Deref` implementation]: https://doc.rust-lang.org/std/string/struct.String.html#impl-Deref-for-String From 3b91b7ac57a534bbb1d4f39f679f86040a588903 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 16 Apr 2025 20:13:42 +0200 Subject: [PATCH 550/606] Make cow_of_cow test a teeny bit more explicit --- tests/ui/pattern/deref-patterns/implicit-cow-deref.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/ui/pattern/deref-patterns/implicit-cow-deref.rs b/tests/ui/pattern/deref-patterns/implicit-cow-deref.rs index 6a363c58b633..a9b8de860107 100644 --- a/tests/ui/pattern/deref-patterns/implicit-cow-deref.rs +++ b/tests/ui/pattern/deref-patterns/implicit-cow-deref.rs @@ -6,7 +6,7 @@ use std::borrow::Cow; fn main() { - let cow: Cow<'static, [u8]> = Cow::from(&[1, 2, 3]); + let cow: Cow<'static, [u8]> = Cow::Borrowed(&[1, 2, 3]); match cow { [..] => {} @@ -31,6 +31,7 @@ fn main() { _ => unreachable!(), } + // This matches on the outer `Cow` (the owned one). match cow_of_cow { Cow::Borrowed(_) => unreachable!(), Cow::Owned(_) => {} From 92ce44f372d081e4c548cdabeec4f580a5eb9642 Mon Sep 17 00:00:00 2001 From: Curtis D'Alves Date: Wed, 16 Apr 2025 19:26:26 -0400 Subject: [PATCH 551/606] ignore aix for tests/ui/erros/pic-linker.rs --- tests/ui/errors/pic-linker.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/ui/errors/pic-linker.rs b/tests/ui/errors/pic-linker.rs index d90989903048..36495ca8fe95 100644 --- a/tests/ui/errors/pic-linker.rs +++ b/tests/ui/errors/pic-linker.rs @@ -5,6 +5,7 @@ //@ ignore-windows //@ ignore-macos //@ ignore-cross-compile +//@ ignore-aix //@ compile-flags: -Clink-args=-Wl,-z,text //@ run-pass From 4be670f89b94aaeab04b0e52d0efd9c61f1bef9d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 9 Apr 2025 21:11:12 +1000 Subject: [PATCH 552/606] Warnings-as-errors in `check-builtin-attr-ice.rs`. This adds two new warnings, both of which print the attribute incorrectly as `#[]`. The next commit will fix this. --- tests/ui/attributes/check-builtin-attr-ice.rs | 4 +++ .../attributes/check-builtin-attr-ice.stderr | 26 ++++++++++++++++--- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/tests/ui/attributes/check-builtin-attr-ice.rs b/tests/ui/attributes/check-builtin-attr-ice.rs index 9ef5890601f6..e3a2ffc714d0 100644 --- a/tests/ui/attributes/check-builtin-attr-ice.rs +++ b/tests/ui/attributes/check-builtin-attr-ice.rs @@ -39,13 +39,17 @@ // Notably, `should_panic` is a `AttributeType::Normal` attribute that is checked separately. +#![deny(unused_attributes)] + struct Foo { #[should_panic::skip] //~^ ERROR failed to resolve + //~| ERROR `#[]` only has an effect on functions pub field: u8, #[should_panic::a::b::c] //~^ ERROR failed to resolve + //~| ERROR `#[]` only has an effect on functions pub field2: u8, } diff --git a/tests/ui/attributes/check-builtin-attr-ice.stderr b/tests/ui/attributes/check-builtin-attr-ice.stderr index 06a4769b2b42..487a0b6d680d 100644 --- a/tests/ui/attributes/check-builtin-attr-ice.stderr +++ b/tests/ui/attributes/check-builtin-attr-ice.stderr @@ -1,21 +1,39 @@ error[E0433]: failed to resolve: use of unresolved module or unlinked crate `should_panic` - --> $DIR/check-builtin-attr-ice.rs:43:7 + --> $DIR/check-builtin-attr-ice.rs:45:7 | LL | #[should_panic::skip] | ^^^^^^^^^^^^ use of unresolved module or unlinked crate `should_panic` error[E0433]: failed to resolve: use of unresolved module or unlinked crate `should_panic` - --> $DIR/check-builtin-attr-ice.rs:47:7 + --> $DIR/check-builtin-attr-ice.rs:50:7 | LL | #[should_panic::a::b::c] | ^^^^^^^^^^^^ use of unresolved module or unlinked crate `should_panic` error[E0433]: failed to resolve: use of unresolved module or unlinked crate `deny` - --> $DIR/check-builtin-attr-ice.rs:55:7 + --> $DIR/check-builtin-attr-ice.rs:59:7 | LL | #[deny::skip] | ^^^^ use of unresolved module or unlinked crate `deny` -error: aborting due to 3 previous errors +error: `#[]` only has an effect on functions + --> $DIR/check-builtin-attr-ice.rs:45:5 + | +LL | #[should_panic::skip] + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/check-builtin-attr-ice.rs:42:9 + | +LL | #![deny(unused_attributes)] + | ^^^^^^^^^^^^^^^^^ + +error: `#[]` only has an effect on functions + --> $DIR/check-builtin-attr-ice.rs:50:5 + | +LL | #[should_panic::a::b::c] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0433`. From 400e8e5dc819b1fa7f994fb60dbe8b5112ec3fd2 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 9 Apr 2025 21:15:45 +1000 Subject: [PATCH 553/606] Fix attribute printing in an error. The current code assumes that the attribute is just an identifier, and so misprints paths. --- compiler/rustc_passes/src/check_attr.rs | 5 ++++- compiler/rustc_passes/src/errors.rs | 2 +- tests/ui/attributes/check-builtin-attr-ice.rs | 4 ++-- tests/ui/attributes/check-builtin-attr-ice.stderr | 4 ++-- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 42279258e877..dcfecdc26ea2 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -561,12 +561,15 @@ impl<'tcx> CheckAttrVisitor<'tcx> { allowed_target: Target, ) { if target != allowed_target { + let path = attr.path(); + let path: Vec<_> = path.iter().map(|s| s.as_str()).collect(); + let attr_name = path.join("::"); self.tcx.emit_node_span_lint( UNUSED_ATTRIBUTES, hir_id, attr.span(), errors::OnlyHasEffectOn { - attr_name: attr.name_or_empty(), + attr_name, target_name: allowed_target.name().replace(' ', "_"), }, ); diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 85eddafefcd5..075927a54f80 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1433,7 +1433,7 @@ pub(crate) struct UselessAssignment<'a> { #[derive(LintDiagnostic)] #[diag(passes_only_has_effect_on)] pub(crate) struct OnlyHasEffectOn { - pub attr_name: Symbol, + pub attr_name: String, pub target_name: String, } diff --git a/tests/ui/attributes/check-builtin-attr-ice.rs b/tests/ui/attributes/check-builtin-attr-ice.rs index e3a2ffc714d0..7745849acd0b 100644 --- a/tests/ui/attributes/check-builtin-attr-ice.rs +++ b/tests/ui/attributes/check-builtin-attr-ice.rs @@ -44,12 +44,12 @@ struct Foo { #[should_panic::skip] //~^ ERROR failed to resolve - //~| ERROR `#[]` only has an effect on functions + //~| ERROR `#[should_panic::skip]` only has an effect on functions pub field: u8, #[should_panic::a::b::c] //~^ ERROR failed to resolve - //~| ERROR `#[]` only has an effect on functions + //~| ERROR `#[should_panic::a::b::c]` only has an effect on functions pub field2: u8, } diff --git a/tests/ui/attributes/check-builtin-attr-ice.stderr b/tests/ui/attributes/check-builtin-attr-ice.stderr index 487a0b6d680d..4f26f71efb7e 100644 --- a/tests/ui/attributes/check-builtin-attr-ice.stderr +++ b/tests/ui/attributes/check-builtin-attr-ice.stderr @@ -16,7 +16,7 @@ error[E0433]: failed to resolve: use of unresolved module or unlinked crate `den LL | #[deny::skip] | ^^^^ use of unresolved module or unlinked crate `deny` -error: `#[]` only has an effect on functions +error: `#[should_panic::skip]` only has an effect on functions --> $DIR/check-builtin-attr-ice.rs:45:5 | LL | #[should_panic::skip] @@ -28,7 +28,7 @@ note: the lint level is defined here LL | #![deny(unused_attributes)] | ^^^^^^^^^^^^^^^^^ -error: `#[]` only has an effect on functions +error: `#[should_panic::a::b::c]` only has an effect on functions --> $DIR/check-builtin-attr-ice.rs:50:5 | LL | #[should_panic::a::b::c] From 7e1f2f9c54338cbefddffcce725f89d271d2cbe8 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 10 Apr 2025 13:47:35 +1000 Subject: [PATCH 554/606] Augment some tests involving attributes. This shows places where the use of `name_or_empty` causes problems, i.e. we print empty identifiers in error messages: ``` error: unrecognized field name `` error: `` isn't a valid `#[macro_export]` argument `#[no_sanitize()]` should be applied to a function ``` (The last one is about an attribute `#[no_sanitize("address")]`.) The next commit will fix these. --- tests/ui/abi/debug.rs | 3 +++ tests/ui/abi/debug.stderr | 8 +++++++- .../invalid_macro_export_argument.deny.stderr | 8 +++++++- .../invalid_macro_export_argument.rs | 6 ++++++ tests/ui/attributes/no-sanitize.rs | 5 +++++ tests/ui/attributes/no-sanitize.stderr | 19 ++++++++++++++++++- 6 files changed, 46 insertions(+), 3 deletions(-) diff --git a/tests/ui/abi/debug.rs b/tests/ui/abi/debug.rs index 6dbc31614641..e3260191e5c8 100644 --- a/tests/ui/abi/debug.rs +++ b/tests/ui/abi/debug.rs @@ -52,3 +52,6 @@ type TestAbiNeSign = (fn(i32), fn(u32)); //~ ERROR: ABIs are not compatible #[rustc_abi(assert_eq)] type TestAbiEqNonsense = (fn((str, str)), fn((str, str))); //~ ERROR: cannot be known at compilation time + +#[rustc_abi("assert_eq")] //~ ERROR unrecognized field name `` +type Bad = u32; diff --git a/tests/ui/abi/debug.stderr b/tests/ui/abi/debug.stderr index 2239ba0e5880..717a95685cbe 100644 --- a/tests/ui/abi/debug.stderr +++ b/tests/ui/abi/debug.stderr @@ -906,6 +906,12 @@ LL | type TestAbiEqNonsense = (fn((str, str)), fn((str, str))); = help: the trait `Sized` is not implemented for `str` = note: only the last element of a tuple may have a dynamically sized type +error: unrecognized field name `` + --> $DIR/debug.rs:56:13 + | +LL | #[rustc_abi("assert_eq")] + | ^^^^^^^^^^^ + error: `#[rustc_abi]` can only be applied to function items, type aliases, and associated functions --> $DIR/debug.rs:29:5 | @@ -1004,6 +1010,6 @@ error: fn_abi_of(assoc_test) = FnAbi { LL | fn assoc_test(&self) { } | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 11 previous errors +error: aborting due to 12 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/attributes/invalid_macro_export_argument.deny.stderr b/tests/ui/attributes/invalid_macro_export_argument.deny.stderr index 644acc27b58e..897bcecc20e2 100644 --- a/tests/ui/attributes/invalid_macro_export_argument.deny.stderr +++ b/tests/ui/attributes/invalid_macro_export_argument.deny.stderr @@ -16,5 +16,11 @@ error: `not_local_inner_macros` isn't a valid `#[macro_export]` argument LL | #[macro_export(not_local_inner_macros)] | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: `` isn't a valid `#[macro_export]` argument + --> $DIR/invalid_macro_export_argument.rs:33:16 + | +LL | #[macro_export("blah")] + | ^^^^^^ + +error: aborting due to 3 previous errors diff --git a/tests/ui/attributes/invalid_macro_export_argument.rs b/tests/ui/attributes/invalid_macro_export_argument.rs index 96f66991e041..c0aa7df2e873 100644 --- a/tests/ui/attributes/invalid_macro_export_argument.rs +++ b/tests/ui/attributes/invalid_macro_export_argument.rs @@ -30,4 +30,10 @@ macro_rules! e { () => () } +#[macro_export("blah")] +//[deny]~^ ERROR `` isn't a valid `#[macro_export]` argument +macro_rules! f { + () => () +} + fn main() {} diff --git a/tests/ui/attributes/no-sanitize.rs b/tests/ui/attributes/no-sanitize.rs index 8c79866d5aa3..a7225efc7b80 100644 --- a/tests/ui/attributes/no-sanitize.rs +++ b/tests/ui/attributes/no-sanitize.rs @@ -38,3 +38,8 @@ fn valid() {} #[no_sanitize(address)] static VALID : i32 = 0; + +#[no_sanitize("address")] +//~^ ERROR `#[no_sanitize()]` should be applied to a function +//~| ERROR invalid argument for `no_sanitize` +static VALID2 : i32 = 0; diff --git a/tests/ui/attributes/no-sanitize.stderr b/tests/ui/attributes/no-sanitize.stderr index 9b0b76e3f4eb..1f24aa71af56 100644 --- a/tests/ui/attributes/no-sanitize.stderr +++ b/tests/ui/attributes/no-sanitize.stderr @@ -59,5 +59,22 @@ LL | #[no_sanitize(address, memory)] LL | static INVALID : i32 = 0; | ------------------------- not a function -error: aborting due to 7 previous errors +error: `#[no_sanitize()]` should be applied to a function + --> $DIR/no-sanitize.rs:42:15 + | +LL | #[no_sanitize("address")] + | ^^^^^^^^^ +... +LL | static VALID2 : i32 = 0; + | ------------------------ not a function + +error: invalid argument for `no_sanitize` + --> $DIR/no-sanitize.rs:42:15 + | +LL | #[no_sanitize("address")] + | ^^^^^^^^^ + | + = note: expected one of: `address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow-call-stack`, or `thread` + +error: aborting due to 9 previous errors From 2fef0a30ae6b2687dfb286cb544d2a542f7e2335 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 10 Apr 2025 14:33:59 +1000 Subject: [PATCH 555/606] Replace infallible `name_or_empty` methods with fallible `name` methods. I'm removing empty identifiers everywhere, because in practice they always mean "no identifier" rather than "empty identifier". (An empty identifier is impossible.) It's better to use `Option` to mean "no identifier" because you then can't forget about the "no identifier" possibility. Some specifics: - When testing an attribute for a single name, the commit uses the `has_name` method. - When testing an attribute for multiple names, the commit uses the new `has_any_name` method. - When using `match` on an attribute, the match arms now have `Some` on them. In the tests, we now avoid printing empty identifiers by not printing the identifier in the `error:` line at all, instead letting the carets point out the problem. --- compiler/rustc_ast/src/attr/mod.rs | 33 +++-- compiler/rustc_ast_lowering/src/item.rs | 2 +- .../rustc_ast_passes/src/ast_validation.rs | 5 +- .../rustc_attr_parsing/src/attributes/cfg.rs | 12 +- compiler/rustc_attr_parsing/src/context.rs | 6 +- .../src/deriving/generic/mod.rs | 5 +- .../rustc_codegen_ssa/src/codegen_attrs.rs | 33 ++--- compiler/rustc_expand/src/base.rs | 8 +- compiler/rustc_expand/src/expand.rs | 12 +- compiler/rustc_hir/src/hir.rs | 11 +- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 2 +- compiler/rustc_hir_typeck/src/method/probe.rs | 7 +- compiler/rustc_incremental/messages.ftl | 2 +- compiler/rustc_incremental/src/errors.rs | 5 +- .../src/persist/dirty_clean.rs | 3 +- compiler/rustc_lint_defs/src/lib.rs | 2 +- compiler/rustc_metadata/src/native_libs.rs | 14 +-- compiler/rustc_metadata/src/rmeta/encoder.rs | 4 +- .../rustc_mir_build/src/builder/custom/mod.rs | 3 +- compiler/rustc_mir_build/src/builder/mod.rs | 2 +- compiler/rustc_mir_build/src/thir/cx/mod.rs | 2 +- .../src/framework/graphviz.rs | 5 +- compiler/rustc_passes/messages.ftl | 6 +- compiler/rustc_passes/src/abi_test.rs | 20 +-- compiler/rustc_passes/src/check_attr.rs | 116 +++++++++--------- .../rustc_passes/src/debugger_visualizer.rs | 22 ++-- compiler/rustc_passes/src/errors.rs | 7 +- compiler/rustc_passes/src/layout_test.rs | 18 +-- compiler/rustc_span/src/symbol.rs | 1 + src/librustdoc/clean/types.rs | 2 +- src/librustdoc/core.rs | 4 +- src/librustdoc/doctest/make.rs | 14 +-- src/librustdoc/html/render/context.rs | 12 +- src/tools/clippy/clippy_utils/src/lib.rs | 4 +- tests/ui/abi/debug.rs | 2 +- tests/ui/abi/debug.stderr | 2 +- .../invalid_macro_export_argument.deny.stderr | 4 +- .../invalid_macro_export_argument.rs | 4 +- tests/ui/attributes/no-sanitize.rs | 2 +- tests/ui/attributes/no-sanitize.stderr | 2 +- 40 files changed, 217 insertions(+), 203 deletions(-) diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index d656d9b0b8af..f104400a572b 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -305,8 +305,8 @@ impl MetaItem { if let [PathSegment { ident, .. }] = self.path.segments[..] { Some(ident) } else { None } } - pub fn name_or_empty(&self) -> Symbol { - self.ident().unwrap_or_else(Ident::empty).name + pub fn name(&self) -> Option { + self.ident().map(|ident| ident.name) } pub fn has_name(&self, name: Symbol) -> bool { @@ -511,13 +511,14 @@ impl MetaItemInner { } } - /// For a single-segment meta item, returns its name; otherwise, returns `None`. + /// For a single-segment meta item, returns its identifier; otherwise, returns `None`. pub fn ident(&self) -> Option { self.meta_item().and_then(|meta_item| meta_item.ident()) } - pub fn name_or_empty(&self) -> Symbol { - self.ident().unwrap_or_else(Ident::empty).name + /// For a single-segment meta item, returns its name; otherwise, returns `None`. + pub fn name(&self) -> Option { + self.ident().map(|ident| ident.name) } /// Returns `true` if this list item is a MetaItem with a name of `name`. @@ -738,9 +739,9 @@ pub trait AttributeExt: Debug { fn id(&self) -> AttrId; /// For a single-segment attribute (i.e., `#[attr]` and not `#[path::atrr]`), - /// return the name of the attribute, else return the empty identifier. - fn name_or_empty(&self) -> Symbol { - self.ident().unwrap_or_else(Ident::empty).name + /// return the name of the attribute; otherwise, returns `None`. + fn name(&self) -> Option { + self.ident().map(|ident| ident.name) } /// Get the meta item list, `#[attr(meta item list)]` @@ -752,7 +753,7 @@ pub trait AttributeExt: Debug { /// Gets the span of the value literal, as string, when using `#[attr = value]` fn value_span(&self) -> Option; - /// For a single-segment attribute, returns its name; otherwise, returns `None`. + /// For a single-segment attribute, returns its ident; otherwise, returns `None`. fn ident(&self) -> Option; /// Checks whether the path of this attribute matches the name. @@ -770,6 +771,11 @@ pub trait AttributeExt: Debug { self.ident().map(|x| x.name == name).unwrap_or(false) } + #[inline] + fn has_any_name(&self, names: &[Symbol]) -> bool { + names.iter().any(|&name| self.has_name(name)) + } + /// get the span of the entire attribute fn span(&self) -> Span; @@ -813,8 +819,8 @@ impl Attribute { AttributeExt::id(self) } - pub fn name_or_empty(&self) -> Symbol { - AttributeExt::name_or_empty(self) + pub fn name(&self) -> Option { + AttributeExt::name(self) } pub fn meta_item_list(&self) -> Option> { @@ -846,6 +852,11 @@ impl Attribute { AttributeExt::has_name(self, name) } + #[inline] + pub fn has_any_name(&self, names: &[Symbol]) -> bool { + AttributeExt::has_any_name(self, names) + } + pub fn span(&self) -> Span { AttributeExt::span(self) } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index d8b55bea3d76..fc32c4efce56 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1310,7 +1310,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // create a fake body so that the entire rest of the compiler doesn't have to deal with // this as a special case. return self.lower_fn_body(decl, contract, |this| { - if attrs.iter().any(|a| a.name_or_empty() == sym::rustc_intrinsic) { + if attrs.iter().any(|a| a.has_name(sym::rustc_intrinsic)) { let span = this.lower_span(span); let empty_block = hir::Block { hir_id: this.next_id(), diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index dc77e7b28344..daf8ff5dc65b 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -347,7 +347,7 @@ impl<'a> AstValidator<'a> { sym::forbid, sym::warn, ]; - !arr.contains(&attr.name_or_empty()) && rustc_attr_parsing::is_builtin_attr(*attr) + !attr.has_any_name(&arr) && rustc_attr_parsing::is_builtin_attr(*attr) }) .for_each(|attr| { if attr.is_doc_comment() { @@ -945,8 +945,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.visit_attrs_vis_ident(&item.attrs, &item.vis, ident); self.check_defaultness(item.span, *defaultness); - let is_intrinsic = - item.attrs.iter().any(|a| a.name_or_empty() == sym::rustc_intrinsic); + let is_intrinsic = item.attrs.iter().any(|a| a.has_name(sym::rustc_intrinsic)); if body.is_none() && !is_intrinsic { self.dcx().emit_err(errors::FnWithoutBody { span: item.span, diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg.rs b/compiler/rustc_attr_parsing/src/attributes/cfg.rs index 0d6d521b40c6..a40112e27a23 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg.rs @@ -117,7 +117,7 @@ pub fn eval_condition( }; match &cfg.kind { - MetaItemKind::List(mis) if cfg.name_or_empty() == sym::version => { + MetaItemKind::List(mis) if cfg.has_name(sym::version) => { try_gate_cfg(sym::version, cfg.span, sess, features); let (min_version, span) = match &mis[..] { [MetaItemInner::Lit(MetaItemLit { kind: LitKind::Str(sym, ..), span, .. })] => { @@ -164,18 +164,18 @@ pub fn eval_condition( // The unwraps below may look dangerous, but we've already asserted // that they won't fail with the loop above. - match cfg.name_or_empty() { - sym::any => mis + match cfg.name() { + Some(sym::any) => mis .iter() // We don't use any() here, because we want to evaluate all cfg condition // as eval_condition can (and does) extra checks .fold(false, |res, mi| res | eval_condition(mi, sess, features, eval)), - sym::all => mis + Some(sym::all) => mis .iter() // We don't use all() here, because we want to evaluate all cfg condition // as eval_condition can (and does) extra checks .fold(true, |res, mi| res & eval_condition(mi, sess, features, eval)), - sym::not => { + Some(sym::not) => { let [mi] = mis.as_slice() else { dcx.emit_err(session_diagnostics::ExpectedOneCfgPattern { span: cfg.span }); return false; @@ -183,7 +183,7 @@ pub fn eval_condition( !eval_condition(mi, sess, features, eval) } - sym::target => { + Some(sym::target) => { if let Some(features) = features && !features.cfg_target_compact() { diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 3bf03f84ce8f..972614a3366c 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -222,7 +222,7 @@ impl<'sess> AttributeParser<'sess> { // if we're only looking for a single attribute, // skip all the ones we don't care about if let Some(expected) = self.parse_only { - if attr.name_or_empty() != expected { + if !attr.has_name(expected) { continue; } } @@ -232,7 +232,7 @@ impl<'sess> AttributeParser<'sess> { // that's expanded right? But no, sometimes, when parsing attributes on macros, // we already use the lowering logic and these are still there. So, when `omit_doc` // is set we *also* want to ignore these - if omit_doc == OmitDoc::Skip && attr.name_or_empty() == sym::doc { + if omit_doc == OmitDoc::Skip && attr.has_name(sym::doc) { continue; } @@ -250,7 +250,7 @@ impl<'sess> AttributeParser<'sess> { })) } // // FIXME: make doc attributes go through a proper attribute parser - // ast::AttrKind::Normal(n) if n.name_or_empty() == sym::doc => { + // ast::AttrKind::Normal(n) if n.has_name(sym::doc) => { // let p = GenericMetaItemParser::from_attr(&n, self.dcx()); // // attributes.push(Attribute::Parsed(AttributeKind::DocComment { diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index b9197be44426..d9aac54ee73c 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -527,15 +527,14 @@ impl<'a> TraitDef<'a> { item.attrs .iter() .filter(|a| { - [ + a.has_any_name(&[ sym::allow, sym::warn, sym::deny, sym::forbid, sym::stable, sym::unstable, - ] - .contains(&a.name_or_empty()) + ]) }) .cloned(), ); diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index ddb611889833..449336424dc5 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -345,20 +345,26 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { no_sanitize_span = Some(attr.span()); if let Some(list) = attr.meta_item_list() { for item in list.iter() { - match item.name_or_empty() { - sym::address => { + match item.name() { + Some(sym::address) => { codegen_fn_attrs.no_sanitize |= SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS } - sym::cfi => codegen_fn_attrs.no_sanitize |= SanitizerSet::CFI, - sym::kcfi => codegen_fn_attrs.no_sanitize |= SanitizerSet::KCFI, - sym::memory => codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMORY, - sym::memtag => codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMTAG, - sym::shadow_call_stack => { + Some(sym::cfi) => codegen_fn_attrs.no_sanitize |= SanitizerSet::CFI, + Some(sym::kcfi) => codegen_fn_attrs.no_sanitize |= SanitizerSet::KCFI, + Some(sym::memory) => { + codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMORY + } + Some(sym::memtag) => { + codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMTAG + } + Some(sym::shadow_call_stack) => { codegen_fn_attrs.no_sanitize |= SanitizerSet::SHADOWCALLSTACK } - sym::thread => codegen_fn_attrs.no_sanitize |= SanitizerSet::THREAD, - sym::hwaddress => { + Some(sym::thread) => { + codegen_fn_attrs.no_sanitize |= SanitizerSet::THREAD + } + Some(sym::hwaddress) => { codegen_fn_attrs.no_sanitize |= SanitizerSet::HWADDRESS } _ => { @@ -419,9 +425,9 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { continue; }; - let attrib_to_write = match meta_item.name_or_empty() { - sym::prefix_nops => &mut prefix, - sym::entry_nops => &mut entry, + let attrib_to_write = match meta_item.name() { + Some(sym::prefix_nops) => &mut prefix, + Some(sym::entry_nops) => &mut entry, _ => { tcx.dcx().emit_err(errors::UnexpectedParameterName { span: item.span(), @@ -785,8 +791,7 @@ impl<'a> MixedExportNameAndNoMangleState<'a> { fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option { let attrs = tcx.get_attrs(id, sym::rustc_autodiff); - let attrs = - attrs.filter(|attr| attr.name_or_empty() == sym::rustc_autodiff).collect::>(); + let attrs = attrs.filter(|attr| attr.has_name(sym::rustc_autodiff)).collect::>(); // check for exactly one autodiff attribute on placeholder functions. // There should only be one, since we generate a new placeholder per ad macro. diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 49f6d58172ff..f5eaf7d616b2 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -824,10 +824,10 @@ impl SyntaxExtension { return Err(item.span); } - match item.name_or_empty() { - sym::no => Ok(CollapseMacroDebuginfo::No), - sym::external => Ok(CollapseMacroDebuginfo::External), - sym::yes => Ok(CollapseMacroDebuginfo::Yes), + match item.name() { + Some(sym::no) => Ok(CollapseMacroDebuginfo::No), + Some(sym::external) => Ok(CollapseMacroDebuginfo::External), + Some(sym::yes) => Ok(CollapseMacroDebuginfo::Yes), _ => Err(item.path.span), } } diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 1b539477d51e..1e26d6681943 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -2053,8 +2053,8 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { ) -> Node::OutputTy { loop { return match self.take_first_attr(&mut node) { - Some((attr, pos, derives)) => match attr.name_or_empty() { - sym::cfg => { + Some((attr, pos, derives)) => match attr.name() { + Some(sym::cfg) => { let (res, meta_item) = self.expand_cfg_true(&mut node, attr, pos); if res { continue; @@ -2071,7 +2071,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { } Default::default() } - sym::cfg_attr => { + Some(sym::cfg_attr) => { self.expand_cfg_attr(&mut node, &attr, pos); continue; } @@ -2144,8 +2144,8 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { ) { loop { return match self.take_first_attr(node) { - Some((attr, pos, derives)) => match attr.name_or_empty() { - sym::cfg => { + Some((attr, pos, derives)) => match attr.name() { + Some(sym::cfg) => { let span = attr.span; if self.expand_cfg_true(node, attr, pos).0 { continue; @@ -2154,7 +2154,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { node.expand_cfg_false(self, pos, span); continue; } - sym::cfg_attr => { + Some(sym::cfg_attr) => { self.expand_cfg_attr(node, &attr, pos); continue; } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 6455f33b9d15..897831f62766 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1237,7 +1237,7 @@ impl AttributeExt for Attribute { Attribute::Parsed(AttributeKind::DocComment { kind, comment, .. }) => { Some((*comment, *kind)) } - Attribute::Unparsed(_) if self.name_or_empty() == sym::doc => { + Attribute::Unparsed(_) if self.has_name(sym::doc) => { self.value_str().map(|s| (s, CommentKind::Line)) } _ => None, @@ -1262,8 +1262,8 @@ impl Attribute { } #[inline] - pub fn name_or_empty(&self) -> Symbol { - AttributeExt::name_or_empty(self) + pub fn name(&self) -> Option { + AttributeExt::name(self) } #[inline] @@ -1301,6 +1301,11 @@ impl Attribute { AttributeExt::has_name(self, name) } + #[inline] + pub fn has_any_name(&self, names: &[Symbol]) -> bool { + AttributeExt::has_any_name(self, names) + } + #[inline] pub fn span(&self) -> Span { AttributeExt::span(self) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index 74cc8181418c..934820eb4daf 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -488,7 +488,7 @@ fn parse_never_type_options_attr( item.span(), format!( "unknown or duplicate never type option: `{}` (supported: `fallback`, `diverging_block_default`)", - item.name_or_empty() + item.name().unwrap() ), ); } diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index ba4396a5ab35..1d3a081cbb88 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -2334,8 +2334,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let hir_id = self.fcx.tcx.local_def_id_to_hir_id(local_def_id); let attrs = self.fcx.tcx.hir_attrs(hir_id); for attr in attrs { - if sym::doc == attr.name_or_empty() { - } else if sym::rustc_confusables == attr.name_or_empty() { + if attr.has_name(sym::doc) { + // do nothing + } else if attr.has_name(sym::rustc_confusables) { let Some(confusables) = attr.meta_item_list() else { continue; }; @@ -2355,7 +2356,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { continue; }; for v in values { - if v.name_or_empty() != sym::alias { + if !v.has_name(sym::alias) { continue; } if let Some(nested) = v.meta_item_list() { diff --git a/compiler/rustc_incremental/messages.ftl b/compiler/rustc_incremental/messages.ftl index 2a65101d360d..bbc1fab05dfe 100644 --- a/compiler/rustc_incremental/messages.ftl +++ b/compiler/rustc_incremental/messages.ftl @@ -93,7 +93,7 @@ incremental_undefined_clean_dirty_assertions = incremental_undefined_clean_dirty_assertions_item = clean/dirty auto-assertions not yet defined for Node::Item.node={$kind} -incremental_unknown_item = unknown item `{$name}` +incremental_unknown_rustc_clean_argument = unknown `rustc_clean` argument incremental_unrecognized_depnode = unrecognized `DepNode` variant: {$name} diff --git a/compiler/rustc_incremental/src/errors.rs b/compiler/rustc_incremental/src/errors.rs index b4a207386dc4..dbc72d085be9 100644 --- a/compiler/rustc_incremental/src/errors.rs +++ b/compiler/rustc_incremental/src/errors.rs @@ -107,11 +107,10 @@ pub(crate) struct NotLoaded<'a> { } #[derive(Diagnostic)] -#[diag(incremental_unknown_item)] -pub(crate) struct UnknownItem { +#[diag(incremental_unknown_rustc_clean_argument)] +pub(crate) struct UnknownRustcCleanArgument { #[primary_span] pub span: Span, - pub name: Symbol, } #[derive(Diagnostic)] diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs index d40a0d514f6f..64166255fa48 100644 --- a/compiler/rustc_incremental/src/persist/dirty_clean.rs +++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs @@ -405,8 +405,7 @@ fn check_config(tcx: TyCtxt<'_>, attr: &Attribute) -> bool { debug!("check_config: searching for cfg {:?}", value); cfg = Some(config.contains(&(value, None))); } else if !(item.has_name(EXCEPT) || item.has_name(LOADED_FROM_DISK)) { - tcx.dcx() - .emit_err(errors::UnknownItem { span: attr.span(), name: item.name_or_empty() }); + tcx.dcx().emit_err(errors::UnknownRustcCleanArgument { span: item.span() }); } } diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 7fdbae3a59d7..b4069b317bfa 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -249,7 +249,7 @@ impl Level { /// Converts an `Attribute` to a level. pub fn from_attr(attr: &impl AttributeExt) -> Option<(Self, Option)> { - Self::from_symbol(attr.name_or_empty(), || Some(attr.id())) + attr.name().and_then(|name| Self::from_symbol(name, || Some(attr.id()))) } /// Converts a `Symbol` to a level. diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index cfb0de8475c8..cee9cff07750 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -226,8 +226,8 @@ impl<'tcx> Collector<'tcx> { let mut wasm_import_module = None; let mut import_name_type = None; for item in items.iter() { - match item.name_or_empty() { - sym::name => { + match item.name() { + Some(sym::name) => { if name.is_some() { sess.dcx().emit_err(errors::MultipleNamesInLink { span: item.span() }); continue; @@ -242,7 +242,7 @@ impl<'tcx> Collector<'tcx> { } name = Some((link_name, span)); } - sym::kind => { + Some(sym::kind) => { if kind.is_some() { sess.dcx().emit_err(errors::MultipleKindsInLink { span: item.span() }); continue; @@ -304,7 +304,7 @@ impl<'tcx> Collector<'tcx> { }; kind = Some(link_kind); } - sym::modifiers => { + Some(sym::modifiers) => { if modifiers.is_some() { sess.dcx() .emit_err(errors::MultipleLinkModifiers { span: item.span() }); @@ -316,7 +316,7 @@ impl<'tcx> Collector<'tcx> { }; modifiers = Some((link_modifiers, item.name_value_literal_span().unwrap())); } - sym::cfg => { + Some(sym::cfg) => { if cfg.is_some() { sess.dcx().emit_err(errors::MultipleCfgs { span: item.span() }); continue; @@ -346,7 +346,7 @@ impl<'tcx> Collector<'tcx> { } cfg = Some(link_cfg.clone()); } - sym::wasm_import_module => { + Some(sym::wasm_import_module) => { if wasm_import_module.is_some() { sess.dcx().emit_err(errors::MultipleWasmImport { span: item.span() }); continue; @@ -357,7 +357,7 @@ impl<'tcx> Collector<'tcx> { }; wasm_import_module = Some((link_wasm_import_module, item.span())); } - sym::import_name_type => { + Some(sym::import_name_type) => { if import_name_type.is_some() { sess.dcx() .emit_err(errors::MultipleImportNameType { span: item.span() }); diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 177318bfe15e..3ea61d1b40a6 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -821,7 +821,9 @@ struct AnalyzeAttrState<'a> { #[inline] fn analyze_attr(attr: &impl AttributeExt, state: &mut AnalyzeAttrState<'_>) -> bool { let mut should_encode = false; - if !rustc_feature::encode_cross_crate(attr.name_or_empty()) { + if let Some(name) = attr.name() + && !rustc_feature::encode_cross_crate(name) + { // Attributes not marked encode-cross-crate don't need to be encoded for downstream crates. } else if attr.doc_str().is_some() { // We keep all doc comments reachable to rustdoc because they might be "imported" into diff --git a/compiler/rustc_mir_build/src/builder/custom/mod.rs b/compiler/rustc_mir_build/src/builder/custom/mod.rs index bfc16816e2e5..902a6e7f115b 100644 --- a/compiler/rustc_mir_build/src/builder/custom/mod.rs +++ b/compiler/rustc_mir_build/src/builder/custom/mod.rs @@ -103,8 +103,9 @@ fn parse_attribute(attr: &Attribute) -> MirPhase { let mut dialect: Option = None; let mut phase: Option = None; + // Not handling errors properly for this internal attribute; will just abort on errors. for nested in meta_items { - let name = nested.name_or_empty(); + let name = nested.name().unwrap(); let value = nested.value_str().unwrap().as_str().to_string(); match name.as_str() { "dialect" => { diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs index 8ca9ab58e457..59a52ae67cb1 100644 --- a/compiler/rustc_mir_build/src/builder/mod.rs +++ b/compiler/rustc_mir_build/src/builder/mod.rs @@ -485,7 +485,7 @@ fn construct_fn<'tcx>( }; if let Some(custom_mir_attr) = - tcx.hir_attrs(fn_id).iter().find(|attr| attr.name_or_empty() == sym::custom_mir) + tcx.hir_attrs(fn_id).iter().find(|attr| attr.has_name(sym::custom_mir)) { return custom::build_custom_mir( tcx, diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index b3daed8a7e01..2f593b9a0a74 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -113,7 +113,7 @@ impl<'tcx> ThirBuildCx<'tcx> { apply_adjustments: tcx .hir_attrs(hir_id) .iter() - .all(|attr| attr.name_or_empty() != rustc_span::sym::custom_mir), + .all(|attr| !attr.has_name(rustc_span::sym::custom_mir)), } } diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs index c436b8c0fb01..144fa8c6fddd 100644 --- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs +++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs @@ -144,9 +144,10 @@ impl RustcMirAttrs { attr: &ast::MetaItemInner, mapper: impl FnOnce(Symbol) -> Result, ) -> Result<(), ()> { + // Unwrapping the name is safe because this is only called when `has_name` has succeeded. if field.is_some() { tcx.dcx() - .emit_err(DuplicateValuesFor { span: attr.span(), name: attr.name_or_empty() }); + .emit_err(DuplicateValuesFor { span: attr.span(), name: attr.name().unwrap() }); return Err(()); } @@ -156,7 +157,7 @@ impl RustcMirAttrs { Ok(()) } else { tcx.dcx() - .emit_err(RequiresAnArgument { span: attr.span(), name: attr.name_or_empty() }); + .emit_err(RequiresAnArgument { span: attr.span(), name: attr.name().unwrap() }); Err(()) } } diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 6ee5e356435c..99789b74488c 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -404,7 +404,7 @@ passes_invalid_attr_at_crate_level = passes_invalid_attr_at_crate_level_item = the inner attribute doesn't annotate this {$kind} -passes_invalid_macro_export_arguments = `{$name}` isn't a valid `#[macro_export]` argument +passes_invalid_macro_export_arguments = invalid `#[macro_export]` argument passes_invalid_macro_export_arguments_too_many_items = `#[macro_export]` can only take 1 or 0 arguments @@ -771,8 +771,8 @@ passes_unreachable_due_to_uninhabited = unreachable {$descr} .label_orig = any code following this expression is unreachable .note = this expression has type `{$ty}`, which is uninhabited -passes_unrecognized_field = - unrecognized field name `{$name}` +passes_unrecognized_argument = + unrecognized argument passes_unstable_attr_for_already_stable_feature = can't mark as unstable using an already stable feature diff --git a/compiler/rustc_passes/src/abi_test.rs b/compiler/rustc_passes/src/abi_test.rs index 671b7d7ad76c..b139ed6a66c3 100644 --- a/compiler/rustc_passes/src/abi_test.rs +++ b/compiler/rustc_passes/src/abi_test.rs @@ -9,7 +9,7 @@ use rustc_span::sym; use rustc_target::callconv::FnAbi; use super::layout_test::ensure_wf; -use crate::errors::{AbiInvalidAttribute, AbiNe, AbiOf, UnrecognizedField}; +use crate::errors::{AbiInvalidAttribute, AbiNe, AbiOf, UnrecognizedArgument}; pub fn test_abi(tcx: TyCtxt<'_>) { if !tcx.features().rustc_attrs() { @@ -77,8 +77,8 @@ fn dump_abi_of_fn_item(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut // The `..` are the names of fields to dump. let meta_items = attr.meta_item_list().unwrap_or_default(); for meta_item in meta_items { - match meta_item.name_or_empty() { - sym::debug => { + match meta_item.name() { + Some(sym::debug) => { let fn_name = tcx.item_name(item_def_id.into()); tcx.dcx().emit_err(AbiOf { span: tcx.def_span(item_def_id), @@ -88,8 +88,8 @@ fn dump_abi_of_fn_item(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut }); } - name => { - tcx.dcx().emit_err(UnrecognizedField { span: meta_item.span(), name }); + _ => { + tcx.dcx().emit_err(UnrecognizedArgument { span: meta_item.span() }); } } } @@ -118,8 +118,8 @@ fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut } let meta_items = attr.meta_item_list().unwrap_or_default(); for meta_item in meta_items { - match meta_item.name_or_empty() { - sym::debug => { + match meta_item.name() { + Some(sym::debug) => { let ty::FnPtr(sig_tys, hdr) = ty.kind() else { span_bug!( meta_item.span(), @@ -138,7 +138,7 @@ fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut let fn_name = tcx.item_name(item_def_id.into()); tcx.dcx().emit_err(AbiOf { span, fn_name, fn_abi: format!("{:#?}", abi) }); } - sym::assert_eq => { + Some(sym::assert_eq) => { let ty::Tuple(fields) = ty.kind() else { span_bug!( meta_item.span(), @@ -188,8 +188,8 @@ fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut }); } } - name => { - tcx.dcx().emit_err(UnrecognizedField { span: meta_item.span(), name }); + _ => { + tcx.dcx().emit_err(UnrecognizedArgument { span: meta_item.span() }); } } } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index dcfecdc26ea2..cbe5058b5519 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -523,9 +523,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { fn check_no_sanitize(&self, attr: &Attribute, span: Span, target: Target) { if let Some(list) = attr.meta_item_list() { for item in list.iter() { - let sym = item.name_or_empty(); + let sym = item.name(); match sym { - sym::address | sym::hwaddress => { + Some(s @ sym::address | s @ sym::hwaddress) => { let is_valid = matches!(target, Target::Fn | Target::Method(..) | Target::Static); if !is_valid { @@ -533,7 +533,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { attr_span: item.span(), defn_span: span, accepted_kind: "a function or static", - attr_str: sym.as_str(), + attr_str: s.as_str(), }); } } @@ -544,7 +544,10 @@ impl<'tcx> CheckAttrVisitor<'tcx> { attr_span: item.span(), defn_span: span, accepted_kind: "a function", - attr_str: sym.as_str(), + attr_str: &match sym { + Some(name) => name.to_string(), + None => "...".to_string(), + }, }); } } @@ -592,7 +595,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> { // * `#[track_caller]` // * `#[test]`, `#[ignore]`, `#[should_panic]` // - // NOTE: when making changes to this list, check that `error_codes/E0736.md` remains accurate + // NOTE: when making changes to this list, check that `error_codes/E0736.md` remains + // accurate. const ALLOW_LIST: &[rustc_span::Symbol] = &[ // conditional compilation sym::cfg_trace, @@ -675,11 +679,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - if !ALLOW_LIST.iter().any(|name| other_attr.has_name(*name)) { + if !other_attr.has_any_name(ALLOW_LIST) { self.dcx().emit_err(errors::NakedFunctionIncompatibleAttribute { span: other_attr.span(), naked_span: attr.span(), - attr: other_attr.name_or_empty(), + attr: other_attr.name().unwrap(), }); return; @@ -1153,7 +1157,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { ) { match target { Target::Use | Target::ExternCrate => { - let do_inline = meta.name_or_empty() == sym::inline; + let do_inline = meta.has_name(sym::inline); if let Some((prev_inline, prev_span)) = *specified_inline { if do_inline != prev_inline { let mut spans = MultiSpan::from_spans(vec![prev_span, meta.span()]); @@ -1263,8 +1267,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> { fn check_test_attr(&self, meta: &MetaItemInner, hir_id: HirId) { if let Some(metas) = meta.meta_item_list() { for i_meta in metas { - match (i_meta.name_or_empty(), i_meta.meta_item()) { - (sym::attr | sym::no_crate_inject, _) => {} + match (i_meta.name(), i_meta.meta_item()) { + (Some(sym::attr | sym::no_crate_inject), _) => {} (_, Some(m)) => { self.tcx.emit_node_span_lint( INVALID_DOC_ATTRIBUTES, @@ -1325,61 +1329,63 @@ impl<'tcx> CheckAttrVisitor<'tcx> { if let Some(list) = attr.meta_item_list() { for meta in &list { if let Some(i_meta) = meta.meta_item() { - match i_meta.name_or_empty() { - sym::alias => { + match i_meta.name() { + Some(sym::alias) => { if self.check_attr_not_crate_level(meta, hir_id, "alias") { self.check_doc_alias(meta, hir_id, target, aliases); } } - sym::keyword => { + Some(sym::keyword) => { if self.check_attr_not_crate_level(meta, hir_id, "keyword") { self.check_doc_keyword(meta, hir_id); } } - sym::fake_variadic => { + Some(sym::fake_variadic) => { if self.check_attr_not_crate_level(meta, hir_id, "fake_variadic") { self.check_doc_fake_variadic(meta, hir_id); } } - sym::search_unbox => { + Some(sym::search_unbox) => { if self.check_attr_not_crate_level(meta, hir_id, "fake_variadic") { self.check_doc_search_unbox(meta, hir_id); } } - sym::test => { + Some(sym::test) => { if self.check_attr_crate_level(attr, meta, hir_id) { self.check_test_attr(meta, hir_id); } } - sym::html_favicon_url - | sym::html_logo_url - | sym::html_playground_url - | sym::issue_tracker_base_url - | sym::html_root_url - | sym::html_no_source => { + Some( + sym::html_favicon_url + | sym::html_logo_url + | sym::html_playground_url + | sym::issue_tracker_base_url + | sym::html_root_url + | sym::html_no_source, + ) => { self.check_attr_crate_level(attr, meta, hir_id); } - sym::cfg_hide => { + Some(sym::cfg_hide) => { if self.check_attr_crate_level(attr, meta, hir_id) { self.check_doc_cfg_hide(meta, hir_id); } } - sym::inline | sym::no_inline => { + Some(sym::inline | sym::no_inline) => { self.check_doc_inline(attr, meta, hir_id, target, specified_inline) } - sym::masked => self.check_doc_masked(attr, meta, hir_id, target), + Some(sym::masked) => self.check_doc_masked(attr, meta, hir_id, target), - sym::cfg | sym::hidden | sym::notable_trait => {} + Some(sym::cfg | sym::hidden | sym::notable_trait) => {} - sym::rust_logo => { + Some(sym::rust_logo) => { if self.check_attr_crate_level(attr, meta, hir_id) && !self.tcx.features().rustdoc_internals() { @@ -2302,7 +2308,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } fn check_macro_use(&self, hir_id: HirId, attr: &Attribute, target: Target) { - let name = attr.name_or_empty(); + let name = attr.name().unwrap(); match target { Target::ExternCrate | Target::Mod => {} _ => { @@ -2334,12 +2340,12 @@ impl<'tcx> CheckAttrVisitor<'tcx> { attr.span(), errors::MacroExport::TooManyItems, ); - } else if meta_item_list[0].name_or_empty() != sym::local_inner_macros { + } else if !meta_item_list[0].has_name(sym::local_inner_macros) { self.tcx.emit_node_span_lint( INVALID_MACRO_EXPORT_ARGUMENTS, hir_id, meta_item_list[0].span(), - errors::MacroExport::UnknownItem { name: meta_item_list[0].name_or_empty() }, + errors::MacroExport::InvalidArgument, ); } } else { @@ -2384,33 +2390,28 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } // Warn on useless empty attributes. - let note = if (matches!( - attr.name_or_empty(), - sym::macro_use - | sym::allow - | sym::expect - | sym::warn - | sym::deny - | sym::forbid - | sym::feature - | sym::target_feature - ) && attr.meta_item_list().is_some_and(|list| list.is_empty())) + let note = if attr.has_any_name(&[ + sym::macro_use, + sym::allow, + sym::expect, + sym::warn, + sym::deny, + sym::forbid, + sym::feature, + sym::target_feature, + ]) && attr.meta_item_list().is_some_and(|list| list.is_empty()) { - errors::UnusedNote::EmptyList { name: attr.name_or_empty() } - } else if matches!( - attr.name_or_empty(), - sym::allow | sym::warn | sym::deny | sym::forbid | sym::expect - ) && let Some(meta) = attr.meta_item_list() + errors::UnusedNote::EmptyList { name: attr.name().unwrap() } + } else if attr.has_any_name(&[sym::allow, sym::warn, sym::deny, sym::forbid, sym::expect]) + && let Some(meta) = attr.meta_item_list() && let [meta] = meta.as_slice() && let Some(item) = meta.meta_item() && let MetaItemKind::NameValue(_) = &item.kind && item.path == sym::reason { - errors::UnusedNote::NoLints { name: attr.name_or_empty() } - } else if matches!( - attr.name_or_empty(), - sym::allow | sym::warn | sym::deny | sym::forbid | sym::expect - ) && let Some(meta) = attr.meta_item_list() + errors::UnusedNote::NoLints { name: attr.name().unwrap() } + } else if attr.has_any_name(&[sym::allow, sym::warn, sym::deny, sym::forbid, sym::expect]) + && let Some(meta) = attr.meta_item_list() && meta.iter().any(|meta| { meta.meta_item().map_or(false, |item| item.path == sym::linker_messages) }) @@ -2443,7 +2444,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { return; } } - } else if attr.name_or_empty() == sym::default_method_body_is_const { + } else if attr.has_name(sym::default_method_body_is_const) { errors::UnusedNote::DefaultMethodBodyConst } else { return; @@ -2900,10 +2901,11 @@ fn check_duplicates( if matches!(duplicates, WarnFollowingWordOnly) && !attr.is_word() { return; } + let attr_name = attr.name().unwrap(); match duplicates { DuplicatesOk => {} WarnFollowing | FutureWarnFollowing | WarnFollowingWordOnly | FutureWarnPreceding => { - match seen.entry(attr.name_or_empty()) { + match seen.entry(attr_name) { Entry::Occupied(mut entry) => { let (this, other) = if matches!(duplicates, FutureWarnPreceding) { let to_remove = entry.insert(attr.span()); @@ -2930,7 +2932,7 @@ fn check_duplicates( } } } - ErrorFollowing | ErrorPreceding => match seen.entry(attr.name_or_empty()) { + ErrorFollowing | ErrorPreceding => match seen.entry(attr_name) { Entry::Occupied(mut entry) => { let (this, other) = if matches!(duplicates, ErrorPreceding) { let to_remove = entry.insert(attr.span()); @@ -2938,11 +2940,7 @@ fn check_duplicates( } else { (attr.span(), *entry.get()) }; - tcx.dcx().emit_err(errors::UnusedMultiple { - this, - other, - name: attr.name_or_empty(), - }); + tcx.dcx().emit_err(errors::UnusedMultiple { this, other, name: attr_name }); } Entry::Vacant(entry) => { entry.insert(attr.span()); diff --git a/compiler/rustc_passes/src/debugger_visualizer.rs b/compiler/rustc_passes/src/debugger_visualizer.rs index 062d56a79a0b..7a7a8175e556 100644 --- a/compiler/rustc_passes/src/debugger_visualizer.rs +++ b/compiler/rustc_passes/src/debugger_visualizer.rs @@ -28,17 +28,17 @@ impl DebuggerVisualizerCollector<'_> { return; }; - let (visualizer_type, visualizer_path) = - match (meta_item.name_or_empty(), meta_item.value_str()) { - (sym::natvis_file, Some(value)) => (DebuggerVisualizerType::Natvis, value), - (sym::gdb_script_file, Some(value)) => { - (DebuggerVisualizerType::GdbPrettyPrinter, value) - } - (_, _) => { - self.sess.dcx().emit_err(DebugVisualizerInvalid { span: meta_item.span }); - return; - } - }; + let (visualizer_type, visualizer_path) = match (meta_item.name(), meta_item.value_str()) + { + (Some(sym::natvis_file), Some(value)) => (DebuggerVisualizerType::Natvis, value), + (Some(sym::gdb_script_file), Some(value)) => { + (DebuggerVisualizerType::GdbPrettyPrinter, value) + } + (_, _) => { + self.sess.dcx().emit_err(DebugVisualizerInvalid { span: meta_item.span }); + return; + } + }; let file = match resolve_path(&self.sess, visualizer_path.as_str(), attr.span) { Ok(file) => file, diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 075927a54f80..26ee89a71640 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -756,7 +756,7 @@ pub(crate) enum MacroExport { OnDeclMacro, #[diag(passes_invalid_macro_export_arguments)] - UnknownItem { name: Symbol }, + InvalidArgument, #[diag(passes_invalid_macro_export_arguments_too_many_items)] TooManyItems, @@ -1045,11 +1045,10 @@ pub(crate) struct AbiInvalidAttribute { } #[derive(Diagnostic)] -#[diag(passes_unrecognized_field)] -pub(crate) struct UnrecognizedField { +#[diag(passes_unrecognized_argument)] +pub(crate) struct UnrecognizedArgument { #[primary_span] pub span: Span, - pub name: Symbol, } #[derive(Diagnostic)] diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs index d4512c9417eb..a19faf0fa836 100644 --- a/compiler/rustc_passes/src/layout_test.rs +++ b/compiler/rustc_passes/src/layout_test.rs @@ -13,7 +13,7 @@ use rustc_trait_selection::traits; use crate::errors::{ LayoutAbi, LayoutAlign, LayoutHomogeneousAggregate, LayoutInvalidAttribute, LayoutOf, - LayoutSize, UnrecognizedField, + LayoutSize, UnrecognizedArgument, }; pub fn test_layout(tcx: TyCtxt<'_>) { @@ -79,28 +79,28 @@ fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) { // The `..` are the names of fields to dump. let meta_items = attr.meta_item_list().unwrap_or_default(); for meta_item in meta_items { - match meta_item.name_or_empty() { + match meta_item.name() { // FIXME: this never was about ABI and now this dump arg is confusing - sym::abi => { + Some(sym::abi) => { tcx.dcx().emit_err(LayoutAbi { span, abi: format!("{:?}", ty_layout.backend_repr), }); } - sym::align => { + Some(sym::align) => { tcx.dcx().emit_err(LayoutAlign { span, align: format!("{:?}", ty_layout.align), }); } - sym::size => { + Some(sym::size) => { tcx.dcx() .emit_err(LayoutSize { span, size: format!("{:?}", ty_layout.size) }); } - sym::homogeneous_aggregate => { + Some(sym::homogeneous_aggregate) => { tcx.dcx().emit_err(LayoutHomogeneousAggregate { span, homogeneous_aggregate: format!( @@ -111,15 +111,15 @@ fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) { }); } - sym::debug => { + Some(sym::debug) => { let normalized_ty = tcx.normalize_erasing_regions(typing_env, ty); // FIXME: using the `Debug` impl here isn't ideal. let ty_layout = format!("{:#?}", *ty_layout); tcx.dcx().emit_err(LayoutOf { span, normalized_ty, ty_layout }); } - name => { - tcx.dcx().emit_err(UnrecognizedField { span: meta_item.span(), name }); + _ => { + tcx.dcx().emit_err(UnrecognizedArgument { span: meta_item.span() }); } } } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 2af567f2ec50..6b9ce92b183d 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1185,6 +1185,7 @@ symbols! { instruction_set, integer_: "integer", // underscore to avoid clashing with the function `sym::integer` below integral, + internal_features, into_async_iter_into_iter, into_future, into_iter, diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 31aa84535cc4..b084eded4035 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -788,7 +788,7 @@ impl Item { } _ => Some(rustc_hir_pretty::attribute_to_string(&tcx, attr)), } - } else if ALLOWED_ATTRIBUTES.contains(&attr.name_or_empty()) { + } else if attr.has_any_name(ALLOWED_ATTRIBUTES) { Some( rustc_hir_pretty::attribute_to_string(&tcx, attr) .replace("\\\n", "") diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index c4dea79370d1..f7695ac8635b 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -412,9 +412,7 @@ pub(crate) fn run_global_ctxt( // Process all of the crate attributes, extracting plugin metadata along // with the passes which we are supposed to run. for attr in krate.module.attrs.lists(sym::doc) { - let name = attr.name_or_empty(); - - if attr.is_word() && name == sym::document_private_items { + if attr.is_word() && attr.has_name(sym::document_private_items) { ctxt.render_options.document_private = true; } } diff --git a/src/librustdoc/doctest/make.rs b/src/librustdoc/doctest/make.rs index 4edd5433de6c..d5c965f7053e 100644 --- a/src/librustdoc/doctest/make.rs +++ b/src/librustdoc/doctest/make.rs @@ -345,7 +345,7 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result) -> bool { let mut is_extern_crate = false; if !info.has_global_allocator - && item.attrs.iter().any(|attr| attr.name_or_empty() == sym::global_allocator) + && item.attrs.iter().any(|attr| attr.has_name(sym::global_allocator)) { info.has_global_allocator = true; } @@ -377,7 +377,7 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result) -> Result { for attr in &item.attrs { - let attr_name = attr.name_or_empty(); - - if attr.style == AttrStyle::Outer || not_crate_attrs.contains(&attr_name) { + if attr.style == AttrStyle::Outer || attr.has_any_name(not_crate_attrs) { // There is one exception to these attributes: // `#![allow(internal_features)]`. If this attribute is used, we need to // consider it only as a crate-level attribute. - if attr_name == sym::allow + if attr.has_name(sym::allow) && let Some(list) = attr.meta_item_list() - && list.iter().any(|sub_attr| { - sub_attr.name_or_empty().as_str() == "internal_features" - }) + && list.iter().any(|sub_attr| sub_attr.has_name(sym::internal_features)) { push_to_s(&mut info.crate_attrs, source, attr.span, &mut prev_span_hi); } else { diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 596ac665fc31..f22935df96c8 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -521,23 +521,23 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { // Crawl the crate attributes looking for attributes which control how we're // going to emit HTML for attr in krate.module.attrs.lists(sym::doc) { - match (attr.name_or_empty(), attr.value_str()) { - (sym::html_favicon_url, Some(s)) => { + match (attr.name(), attr.value_str()) { + (Some(sym::html_favicon_url), Some(s)) => { layout.favicon = s.to_string(); } - (sym::html_logo_url, Some(s)) => { + (Some(sym::html_logo_url), Some(s)) => { layout.logo = s.to_string(); } - (sym::html_playground_url, Some(s)) => { + (Some(sym::html_playground_url), Some(s)) => { playground = Some(markdown::Playground { crate_name: Some(krate.name(tcx)), url: s.to_string(), }); } - (sym::issue_tracker_base_url, Some(s)) => { + (Some(sym::issue_tracker_base_url), Some(s)) => { issue_tracker_base_url = Some(s.to_string()); } - (sym::html_no_source, None) if attr.is_word() => { + (Some(sym::html_no_source), None) if attr.is_word() => { include_sources = false; } _ => {} diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 9f450d654d52..f715fc86e4e5 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -2363,14 +2363,14 @@ pub fn is_no_std_crate(cx: &LateContext<'_>) -> bool { cx.tcx .hir_attrs(hir::CRATE_HIR_ID) .iter() - .any(|attr| attr.name_or_empty() == sym::no_std) + .any(|attr| attr.has_name(sym::no_std)) } pub fn is_no_core_crate(cx: &LateContext<'_>) -> bool { cx.tcx .hir_attrs(hir::CRATE_HIR_ID) .iter() - .any(|attr| attr.name_or_empty() == sym::no_core) + .any(|attr| attr.has_name(sym::no_core)) } /// Check if parent of a hir node is a trait implementation block. diff --git a/tests/ui/abi/debug.rs b/tests/ui/abi/debug.rs index e3260191e5c8..c0d8de05fda5 100644 --- a/tests/ui/abi/debug.rs +++ b/tests/ui/abi/debug.rs @@ -53,5 +53,5 @@ type TestAbiNeSign = (fn(i32), fn(u32)); //~ ERROR: ABIs are not compatible #[rustc_abi(assert_eq)] type TestAbiEqNonsense = (fn((str, str)), fn((str, str))); //~ ERROR: cannot be known at compilation time -#[rustc_abi("assert_eq")] //~ ERROR unrecognized field name `` +#[rustc_abi("assert_eq")] //~ ERROR unrecognized argument type Bad = u32; diff --git a/tests/ui/abi/debug.stderr b/tests/ui/abi/debug.stderr index 717a95685cbe..480f3f04215e 100644 --- a/tests/ui/abi/debug.stderr +++ b/tests/ui/abi/debug.stderr @@ -906,7 +906,7 @@ LL | type TestAbiEqNonsense = (fn((str, str)), fn((str, str))); = help: the trait `Sized` is not implemented for `str` = note: only the last element of a tuple may have a dynamically sized type -error: unrecognized field name `` +error: unrecognized argument --> $DIR/debug.rs:56:13 | LL | #[rustc_abi("assert_eq")] diff --git a/tests/ui/attributes/invalid_macro_export_argument.deny.stderr b/tests/ui/attributes/invalid_macro_export_argument.deny.stderr index 897bcecc20e2..9d44bd162c7b 100644 --- a/tests/ui/attributes/invalid_macro_export_argument.deny.stderr +++ b/tests/ui/attributes/invalid_macro_export_argument.deny.stderr @@ -10,13 +10,13 @@ note: the lint level is defined here LL | #![cfg_attr(deny, deny(invalid_macro_export_arguments))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: `not_local_inner_macros` isn't a valid `#[macro_export]` argument +error: invalid `#[macro_export]` argument --> $DIR/invalid_macro_export_argument.rs:13:16 | LL | #[macro_export(not_local_inner_macros)] | ^^^^^^^^^^^^^^^^^^^^^^ -error: `` isn't a valid `#[macro_export]` argument +error: invalid `#[macro_export]` argument --> $DIR/invalid_macro_export_argument.rs:33:16 | LL | #[macro_export("blah")] diff --git a/tests/ui/attributes/invalid_macro_export_argument.rs b/tests/ui/attributes/invalid_macro_export_argument.rs index c0aa7df2e873..c5fe39d062a4 100644 --- a/tests/ui/attributes/invalid_macro_export_argument.rs +++ b/tests/ui/attributes/invalid_macro_export_argument.rs @@ -11,7 +11,7 @@ macro_rules! a { } #[macro_export(not_local_inner_macros)] -//[deny]~^ ERROR `not_local_inner_macros` isn't a valid `#[macro_export]` argument +//[deny]~^ ERROR invalid `#[macro_export]` argument macro_rules! b { () => () } @@ -31,7 +31,7 @@ macro_rules! e { } #[macro_export("blah")] -//[deny]~^ ERROR `` isn't a valid `#[macro_export]` argument +//[deny]~^ ERROR invalid `#[macro_export]` argument macro_rules! f { () => () } diff --git a/tests/ui/attributes/no-sanitize.rs b/tests/ui/attributes/no-sanitize.rs index a7225efc7b80..ddf909be63a8 100644 --- a/tests/ui/attributes/no-sanitize.rs +++ b/tests/ui/attributes/no-sanitize.rs @@ -40,6 +40,6 @@ fn valid() {} static VALID : i32 = 0; #[no_sanitize("address")] -//~^ ERROR `#[no_sanitize()]` should be applied to a function +//~^ ERROR `#[no_sanitize(...)]` should be applied to a function //~| ERROR invalid argument for `no_sanitize` static VALID2 : i32 = 0; diff --git a/tests/ui/attributes/no-sanitize.stderr b/tests/ui/attributes/no-sanitize.stderr index 1f24aa71af56..8d5fbb109ead 100644 --- a/tests/ui/attributes/no-sanitize.stderr +++ b/tests/ui/attributes/no-sanitize.stderr @@ -59,7 +59,7 @@ LL | #[no_sanitize(address, memory)] LL | static INVALID : i32 = 0; | ------------------------- not a function -error: `#[no_sanitize()]` should be applied to a function +error: `#[no_sanitize(...)]` should be applied to a function --> $DIR/no-sanitize.rs:42:15 | LL | #[no_sanitize("address")] From 846c10fecfdbda6e43073af226486ff7ec3f873d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 16 Apr 2025 09:19:52 +1000 Subject: [PATCH 556/606] Avoid an `unwrap` in `RustcMirAttrs::set_field`. --- .../src/framework/graphviz.rs | 45 ++++++++++--------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs index 144fa8c6fddd..95f488a925b2 100644 --- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs +++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs @@ -109,27 +109,29 @@ impl RustcMirAttrs { .flat_map(|attr| attr.meta_item_list().into_iter().flat_map(|v| v.into_iter())); for attr in rustc_mir_attrs { - let attr_result = if attr.has_name(sym::borrowck_graphviz_postflow) { - Self::set_field(&mut ret.basename_and_suffix, tcx, &attr, |s| { - let path = PathBuf::from(s.to_string()); - match path.file_name() { - Some(_) => Ok(path), - None => { - tcx.dcx().emit_err(PathMustEndInFilename { span: attr.span() }); + let attr_result = match attr.name() { + Some(name @ sym::borrowck_graphviz_postflow) => { + Self::set_field(&mut ret.basename_and_suffix, tcx, name, &attr, |s| { + let path = PathBuf::from(s.to_string()); + match path.file_name() { + Some(_) => Ok(path), + None => { + tcx.dcx().emit_err(PathMustEndInFilename { span: attr.span() }); + Err(()) + } + } + }) + } + Some(name @ sym::borrowck_graphviz_format) => { + Self::set_field(&mut ret.formatter, tcx, name, &attr, |s| match s { + sym::two_phase => Ok(s), + _ => { + tcx.dcx().emit_err(UnknownFormatter { span: attr.span() }); Err(()) } - } - }) - } else if attr.has_name(sym::borrowck_graphviz_format) { - Self::set_field(&mut ret.formatter, tcx, &attr, |s| match s { - sym::two_phase => Ok(s), - _ => { - tcx.dcx().emit_err(UnknownFormatter { span: attr.span() }); - Err(()) - } - }) - } else { - Ok(()) + }) + } + _ => Ok(()), }; result = result.and(attr_result); @@ -141,13 +143,12 @@ impl RustcMirAttrs { fn set_field( field: &mut Option, tcx: TyCtxt<'_>, + name: Symbol, attr: &ast::MetaItemInner, mapper: impl FnOnce(Symbol) -> Result, ) -> Result<(), ()> { - // Unwrapping the name is safe because this is only called when `has_name` has succeeded. if field.is_some() { - tcx.dcx() - .emit_err(DuplicateValuesFor { span: attr.span(), name: attr.name().unwrap() }); + tcx.dcx().emit_err(DuplicateValuesFor { span: attr.span(), name }); return Err(()); } From a114bcffe7c6cd4c7cf6dccac0a47ed49894ed2f Mon Sep 17 00:00:00 2001 From: jyn Date: Tue, 15 Apr 2025 17:01:58 -0400 Subject: [PATCH 557/606] document RUSTC_BOOTSTRAP, RUSTC_OVERRIDE_VERSION_STRING, and -Z allow-features in the unstable book --- .../src/compiler-flags/allow-features.md | 14 +++++ .../src/compiler-flags/rustc-bootstrap.md | 56 +++++++++++++++++++ .../rustc-override-version-string.md | 39 +++++++++++++ 3 files changed, 109 insertions(+) create mode 100644 src/doc/unstable-book/src/compiler-flags/allow-features.md create mode 100644 src/doc/unstable-book/src/compiler-flags/rustc-bootstrap.md create mode 100644 src/doc/unstable-book/src/compiler-flags/rustc-override-version-string.md diff --git a/src/doc/unstable-book/src/compiler-flags/allow-features.md b/src/doc/unstable-book/src/compiler-flags/allow-features.md new file mode 100644 index 000000000000..84fa465c89b4 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/allow-features.md @@ -0,0 +1,14 @@ +# `allow-features` + +This feature is perma-unstable and has no tracking issue. + +---- + +This flag allows limiting the features which can be enabled with `#![feature(...)]` attributes. +By default, all features are allowed on nightly and no features are allowed on stable or beta (but see [`RUSTC_BOOTSTRAP`]). + +Features are comma-separated, for example `-Z allow-features=ffi_pure,f16`. +If the flag is present, any feature listed will be allowed and any feature not listed will be disallowed. +Any unrecognized feature is ignored. + +[`RUSTC_BOOTSTRAP`]: ./rustc-bootstrap.html diff --git a/src/doc/unstable-book/src/compiler-flags/rustc-bootstrap.md b/src/doc/unstable-book/src/compiler-flags/rustc-bootstrap.md new file mode 100644 index 000000000000..6895f2322386 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/rustc-bootstrap.md @@ -0,0 +1,56 @@ +# `RUSTC_BOOTSTRAP` + +This feature is perma-unstable and has no tracking issue. + +---- + +The `RUSTC_BOOTSTRAP` environment variable tells rustc to act as if it is a nightly compiler; +in particular, it allows `#![feature(...)]` attributes and `-Z` flags even on the stable release channel. + +Setting `RUSTC_BOOTSTRAP=1` instructs rustc to enable this for all crates. +Setting `RUSTC_BOOTSTRAP=crate_name` instructs rustc to only apply this to crates named `crate_name`. +Setting `RUSTC_BOOTSTRAP=-1` instructs rustc to act as if it is a stable compiler, even on the nightly release channel. +Cargo disallows setting `cargo::rustc-env=RUSTC_BOOTSTRAP` in build scripts. +Build systems can limit the features they enable with [`-Z allow-features=feature1,feature2`][Z-allow-features]. +Crates can fully opt out of unstable features by using [`#![forbid(unstable_features)]`][unstable-features] at the crate root (or any other way of enabling lints, such as `-F unstable-features`). + +[Z-allow-features]: ./allow-features.html +[unstable-features]: ../../rustc/lints/listing/allowed-by-default.html#unstable-features + +## Why does this environment variable exist? + +`RUSTC_BOOTSTRAP`, as the name suggests, is used for bootstrapping the compiler from an earlier version. +In particular, nightly is built with beta, and beta is built with stable. +Since the standard library and compiler both use unstable features, `RUSTC_BOOTSTRAP` is required so that we can use the previous version to build them. + +## Why is this environment variable so easy to use for people not in the rust project? + +Originally, `RUSTC_BOOTSTRAP` required passing in a hash of the previous compiler version, to discourage using it for any purpose other than bootstrapping. +That constraint was later relaxed; see for the discussion that happened at that time. + +People have at various times proposed re-adding the technical constraints. +However, doing so is extremely disruptive for several major projects that we very much want to keep using the latest stable toolchain version, such as Firefox, Rust for Linux, and Chromium. +We continue to allow `RUSTC_BOOTSTRAP` until we can come up with an alternative that does not disrupt our largest constituents. + +## Stability policy + +Despite being usable on stable, this is an unstable feature. +Like any other unstable feature, we reserve the right to change or remove this feature in the future, as well as any other unstable feature that it enables. +Using this feature opts you out of the normal stability/backwards compatibility guarantee of stable. + +Although we do not take technical measures to prevent it from being used, we strongly discourage using this feature. +If at all possible, please contribute to stabilizing the features you care about instead of bypassing the Rust project's stability policy. + +For library crates, we especially discourage the use of this feature. +The crates depending on you do not know that you use this feature, have little recourse if it breaks, and can be used in contexts that are hard to predict. + +For libraries that do use this feature, please document the versions you support (including a *maximum* as well as minimum version), and a mechanism to disable it. +If you do not have a mechanism to disable the use of `RUSTC_BOOTSTRAP`, consider removing its use altogether, such that people can only use your library if they are already using a nightly toolchain. +This leaves the choice of whether to opt-out of Rust's stability guarantees up to the end user building their code. + +## History + +- [Allowed without a hash](https://github.com/rust-lang/rust/pull/37265) ([discussion](https://github.com/rust-lang/rust/issues/36548)) +- [Extended to crate names](https://github.com/rust-lang/rust/pull/77802) ([discussion](https://github.com/rust-lang/cargo/issues/7088)) +- [Disallowed for build scripts](https://github.com/rust-lang/cargo/pull/9181) ([discussion](https://github.com/rust-lang/compiler-team/issues/350)) +- [Extended to emulate stable](https://github.com/rust-lang/rust/pull/132993) ([discussion](https://github.com/rust-lang/rust/issues/123404)) diff --git a/src/doc/unstable-book/src/compiler-flags/rustc-override-version-string.md b/src/doc/unstable-book/src/compiler-flags/rustc-override-version-string.md new file mode 100644 index 000000000000..3d867b5f7146 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/rustc-override-version-string.md @@ -0,0 +1,39 @@ +# `RUSTC_OVERRIDE_VERSION_STRING` + +This feature is perma-unstable and has no tracking issue. + +---- + +The `RUSTC_OVERRIDE_VERSION_STRING` environment variable overrides the version reported by `rustc --version`. For example: + +```console +$ rustc --version +rustc 1.87.0-nightly (43f0014ef 2025-03-25) +$ env RUSTC_OVERRIDE_VERSION_STRING=1.81.0-nightly rustc --version +rustc 1.81.0-nightly +``` + +Note that the version string is completely overwritten; i.e. rustc discards commit hash and commit date information unless it is explicitly included in the environment variable. The string only applies to the "release" part of the version; for example: +```console +$ RUSTC_OVERRIDE_VERSION_STRING="1.81.0-nightly (aaaaaaaaa 2025-03-22)" rustc -vV +rustc 1.81.0-nightly (aaaaaaaaa 2025-03-22) +binary: rustc +commit-hash: 43f0014ef0f242418674f49052ed39b70f73bc1c +commit-date: 2025-03-25 +host: x86_64-unknown-linux-gnu +release: 1.81.0-nightly (aaaaaaaaa 2025-03-22) +LLVM version: 20.1.1 +``` + +Note here that `commit-hash` and `commit-date` do not match the values in the string, and `release` includes the fake hash and date. + +This variable has no effect on whether or not unstable features are allowed to be used. It only affects the output of `--version`. + +## Why does this environment variable exist? + +Various library crates have incomplete or incorrect feature detection. +This environment variable allows bisecting crates that do incorrect detection with `version_check::supports_feature`. + +This is not intended to be used for any other case (and, except for bisection, is not particularly useful). + +See for further discussion. From 9f548e298ddb0eaa546b68c976199a93635d6855 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Thu, 17 Apr 2025 02:24:28 +0200 Subject: [PATCH 558/606] Support inlined cross-crate re-exported trait aliases --- src/librustdoc/clean/inline.rs | 43 +++++----- src/librustdoc/core.rs | 4 +- src/librustdoc/html/render/print_item.rs | 5 +- tests/rustdoc/auxiliary/ext-trait-aliases.rs | 13 +++ .../rustdoc/auxiliary/trait-alias-mention.rs | 3 - tests/rustdoc/trait-alias-mention.rs | 10 --- tests/rustdoc/trait-aliases.rs | 82 +++++++++++++++++++ tests/rustdoc/trait_alias.rs | 26 ------ 8 files changed, 122 insertions(+), 64 deletions(-) create mode 100644 tests/rustdoc/auxiliary/ext-trait-aliases.rs delete mode 100644 tests/rustdoc/auxiliary/trait-alias-mention.rs delete mode 100644 tests/rustdoc/trait-alias-mention.rs create mode 100644 tests/rustdoc/trait-aliases.rs delete mode 100644 tests/rustdoc/trait_alias.rs diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 3a2b6974681b..2ea0fd8ad6c1 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -67,9 +67,13 @@ pub(crate) fn try_inline( record_extern_fqn(cx, did, ItemType::Trait); cx.with_param_env(did, |cx| { build_impls(cx, did, attrs_without_docs, &mut ret); - clean::TraitItem(Box::new(build_external_trait(cx, did))) + clean::TraitItem(Box::new(build_trait(cx, did))) }) } + Res::Def(DefKind::TraitAlias, did) => { + record_extern_fqn(cx, did, ItemType::TraitAlias); + cx.with_param_env(did, |cx| clean::TraitAliasItem(build_trait_alias(cx, did))) + } Res::Def(DefKind::Fn, did) => { record_extern_fqn(cx, did, ItemType::Function); cx.with_param_env(did, |cx| { @@ -251,7 +255,7 @@ pub(crate) fn record_extern_fqn(cx: &mut DocContext<'_>, did: DefId, kind: ItemT } } -pub(crate) fn build_external_trait(cx: &mut DocContext<'_>, did: DefId) -> clean::Trait { +pub(crate) fn build_trait(cx: &mut DocContext<'_>, did: DefId) -> clean::Trait { let trait_items = cx .tcx .associated_items(did) @@ -263,11 +267,18 @@ pub(crate) fn build_external_trait(cx: &mut DocContext<'_>, did: DefId) -> clean let predicates = cx.tcx.predicates_of(did); let generics = clean_ty_generics(cx, cx.tcx.generics_of(did), predicates); let generics = filter_non_trait_generics(did, generics); - let (generics, supertrait_bounds) = separate_supertrait_bounds(generics); + let (generics, supertrait_bounds) = separate_self_bounds(generics); clean::Trait { def_id: did, generics, items: trait_items, bounds: supertrait_bounds } } -pub(crate) fn build_function(cx: &mut DocContext<'_>, def_id: DefId) -> Box { +fn build_trait_alias(cx: &mut DocContext<'_>, did: DefId) -> clean::TraitAlias { + let predicates = cx.tcx.predicates_of(did); + let generics = clean_ty_generics(cx, cx.tcx.generics_of(did), predicates); + let (generics, bounds) = separate_self_bounds(generics); + clean::TraitAlias { generics, bounds } +} + +pub(super) fn build_function(cx: &mut DocContext<'_>, def_id: DefId) -> Box { let sig = cx.tcx.fn_sig(def_id).instantiate_identity(); // The generics need to be cleaned before the signature. let mut generics = @@ -788,12 +799,7 @@ fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean: g } -/// Supertrait bounds for a trait are also listed in the generics coming from -/// the metadata for a crate, so we want to separate those out and create a new -/// list of explicit supertrait bounds to render nicely. -fn separate_supertrait_bounds( - mut g: clean::Generics, -) -> (clean::Generics, Vec) { +fn separate_self_bounds(mut g: clean::Generics) -> (clean::Generics, Vec) { let mut ty_bounds = Vec::new(); g.where_predicates.retain(|pred| match *pred { clean::WherePredicate::BoundPredicate { ty: clean::SelfTy, ref bounds, .. } => { @@ -806,22 +812,17 @@ fn separate_supertrait_bounds( } pub(crate) fn record_extern_trait(cx: &mut DocContext<'_>, did: DefId) { - if did.is_local() { + if did.is_local() + || cx.external_traits.contains_key(&did) + || cx.active_extern_traits.contains(&did) + { return; } - { - if cx.external_traits.contains_key(&did) || cx.active_extern_traits.contains(&did) { - return; - } - } - - { - cx.active_extern_traits.insert(did); - } + cx.active_extern_traits.insert(did); debug!("record_extern_trait: {did:?}"); - let trait_ = build_external_trait(cx, did); + let trait_ = build_trait(cx, did); cx.external_traits.insert(did, trait_); cx.active_extern_traits.remove(&did); diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index c4dea79370d1..41688b41c6e7 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -27,7 +27,7 @@ use rustc_span::source_map; use rustc_span::symbol::sym; use tracing::{debug, info}; -use crate::clean::inline::build_external_trait; +use crate::clean::inline::build_trait; use crate::clean::{self, ItemId}; use crate::config::{Options as RustdocOptions, OutputFormat, RenderOptions}; use crate::formats::cache::Cache; @@ -385,7 +385,7 @@ pub(crate) fn run_global_ctxt( // // Note that in case of `#![no_core]`, the trait is not available. if let Some(sized_trait_did) = ctxt.tcx.lang_items().sized_trait() { - let sized_trait = build_external_trait(&mut ctxt, sized_trait_did); + let sized_trait = build_trait(&mut ctxt, sized_trait_did); ctxt.external_traits.insert(sized_trait_did, sized_trait); } diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 96847f13f655..da33fedaa319 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1229,12 +1229,13 @@ fn item_trait_alias( wrap_item(w, |w| { write!( w, - "{attrs}trait {name}{generics}{where_b} = {bounds};", + "{attrs}trait {name}{generics} = {bounds}{where_clause};", attrs = render_attributes_in_pre(it, "", cx), name = it.name.unwrap(), generics = t.generics.print(cx), - where_b = print_where_clause(&t.generics, cx, 0, Ending::Newline).maybe_display(), bounds = bounds(&t.bounds, true, cx), + where_clause = + print_where_clause(&t.generics, cx, 0, Ending::NoNewline).maybe_display(), ) })?; diff --git a/tests/rustdoc/auxiliary/ext-trait-aliases.rs b/tests/rustdoc/auxiliary/ext-trait-aliases.rs new file mode 100644 index 000000000000..8454c04063c1 --- /dev/null +++ b/tests/rustdoc/auxiliary/ext-trait-aliases.rs @@ -0,0 +1,13 @@ +#![feature(trait_alias)] + +pub trait ExtAlias0 = Copy + Iterator; + +pub trait ExtAlias1<'a, T: 'a + Clone, const N: usize> = From<[&'a T; N]>; + +pub trait ExtAlias2 = where T: From, String: Into; + +pub trait ExtAlias3 = Sized; + +pub trait ExtAlias4 = where Self: Sized; + +pub trait ExtAlias5 = ; diff --git a/tests/rustdoc/auxiliary/trait-alias-mention.rs b/tests/rustdoc/auxiliary/trait-alias-mention.rs deleted file mode 100644 index 6df06c87a09d..000000000000 --- a/tests/rustdoc/auxiliary/trait-alias-mention.rs +++ /dev/null @@ -1,3 +0,0 @@ -#![feature(trait_alias)] - -pub trait SomeAlias = std::fmt::Debug + std::marker::Copy; diff --git a/tests/rustdoc/trait-alias-mention.rs b/tests/rustdoc/trait-alias-mention.rs deleted file mode 100644 index b6ef926e644e..000000000000 --- a/tests/rustdoc/trait-alias-mention.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ aux-build:trait-alias-mention.rs -//@ build-aux-docs - -#![crate_name = "foo"] - -extern crate trait_alias_mention; - -//@ has foo/fn.mention_alias_in_bounds.html '//a[@href="../trait_alias_mention/traitalias.SomeAlias.html"]' 'SomeAlias' -pub fn mention_alias_in_bounds() { -} diff --git a/tests/rustdoc/trait-aliases.rs b/tests/rustdoc/trait-aliases.rs new file mode 100644 index 000000000000..1be93f72042c --- /dev/null +++ b/tests/rustdoc/trait-aliases.rs @@ -0,0 +1,82 @@ +// Basic testing for trait aliases. +#![feature(trait_alias)] +#![crate_name = "it"] + +// Check the "local case" (HIR cleaning) // + +//@ has it/all.html '//a[@href="traitalias.Alias0.html"]' 'Alias0' +//@ has it/index.html '//h2[@id="trait-aliases"]' 'Trait Aliases' +//@ has it/index.html '//a[@class="traitalias"]' 'Alias0' +//@ has it/traitalias.Alias0.html +//@ has - '//*[@class="rust item-decl"]//code' 'trait Alias0 = Copy + Iterator;' +pub trait Alias0 = Copy + Iterator; + +//@ has it/traitalias.Alias1.html +//@ has - '//pre[@class="rust item-decl"]' \ +// "trait Alias1<'a, T: 'a + Clone, const N: usize> = From<[&'a T; N]>;" +pub trait Alias1<'a, T: 'a + Clone, const N: usize> = From<[&'a T; N]>; + +//@ has it/traitalias.Alias2.html +//@ has - '//pre[@class="rust item-decl"]' \ +// 'trait Alias2 = where T: From, String: Into;' +pub trait Alias2 = where T: From, String: Into; + +//@ has it/traitalias.Alias3.html +//@ has - '//pre[@class="rust item-decl"]' 'trait Alias3 = ;' +pub trait Alias3 =; + +//@ has it/traitalias.Alias4.html +//@ has - '//pre[@class="rust item-decl"]' 'trait Alias4 = ;' +pub trait Alias4 = where; + +//@ has it/fn.usage0.html +//@ has - '//pre[@class="rust item-decl"]' "pub fn usage0(_: impl Alias0)" +//@ has - '//a[@href="traitalias.Alias0.html"]' 'Alias0' +pub fn usage0(_: impl Alias0) {} + +// FIXME: One can only "disambiguate" intra-doc links to trait aliases with `type@` but not with +// `trait@` (fails to resolve) or `traitalias@` (doesn't exist). We should make at least one of +// the latter two work, right? + +//@ has it/link0/index.html +//@ has - '//a/@href' 'traitalias.Alias0.html' +//@ has - '//a/@href' 'traitalias.Alias1.html' +/// [Alias0], [type@Alias1] +pub mod link0 {} + +// Check the "extern case" (middle cleaning) // + +//@ aux-build: ext-trait-aliases.rs +extern crate ext_trait_aliases as ext; + +//@ has it/traitalias.ExtAlias0.html +//@ has - '//pre[@class="rust item-decl"]' 'trait ExtAlias0 = Copy + Iterator;' +pub use ext::ExtAlias0; + +//@ has it/traitalias.ExtAlias1.html +//@ has - '//pre[@class="rust item-decl"]' \ +// "trait ExtAlias1<'a, T, const N: usize> = From<[&'a T; N]> where T: 'a + Clone;" +pub use ext::ExtAlias1; + +//@ has it/traitalias.ExtAlias2.html +//@ has - '//pre[@class="rust item-decl"]' \ +// 'trait ExtAlias2 = where T: From, String: Into;' +pub use ext::ExtAlias2; + +//@ has it/traitalias.ExtAlias3.html +//@ has - '//pre[@class="rust item-decl"]' 'trait ExtAlias3 = Sized;' +pub use ext::ExtAlias3; + +// NOTE: Middle cleaning can't discern `= Sized` and `= where Self: Sized` and that's okay. +//@ has it/traitalias.ExtAlias4.html +//@ has - '//pre[@class="rust item-decl"]' 'trait ExtAlias4 = Sized;' +pub use ext::ExtAlias4; + +//@ has it/traitalias.ExtAlias5.html +//@ has - '//pre[@class="rust item-decl"]' 'trait ExtAlias5 = ;' +pub use ext::ExtAlias5; + +//@ has it/fn.usage1.html +//@ has - '//pre[@class="rust item-decl"]' "pub fn usage1(_: impl ExtAlias0)" +//@ has - '//a[@href="traitalias.ExtAlias0.html"]' 'ExtAlias0' +pub fn usage1(_: impl ExtAlias0) {} diff --git a/tests/rustdoc/trait_alias.rs b/tests/rustdoc/trait_alias.rs deleted file mode 100644 index bfdb9d40e2d2..000000000000 --- a/tests/rustdoc/trait_alias.rs +++ /dev/null @@ -1,26 +0,0 @@ -#![feature(trait_alias)] - -#![crate_name = "foo"] - -use std::fmt::Debug; - -//@ has foo/all.html '//a[@href="traitalias.CopyAlias.html"]' 'CopyAlias' -//@ has foo/all.html '//a[@href="traitalias.Alias2.html"]' 'Alias2' -//@ has foo/all.html '//a[@href="traitalias.Foo.html"]' 'Foo' - -//@ has foo/index.html '//h2[@id="trait-aliases"]' 'Trait Aliases' -//@ has foo/index.html '//a[@class="traitalias"]' 'CopyAlias' -//@ has foo/index.html '//a[@class="traitalias"]' 'Alias2' -//@ has foo/index.html '//a[@class="traitalias"]' 'Foo' - -//@ has foo/traitalias.CopyAlias.html -//@ has - '//section[@id="main-content"]/pre[@class="rust item-decl"]' 'trait CopyAlias = Copy;' -pub trait CopyAlias = Copy; -//@ has foo/traitalias.Alias2.html -//@ has - '//section[@id="main-content"]/pre[@class="rust item-decl"]' 'trait Alias2 = Copy + Debug;' -pub trait Alias2 = Copy + Debug; -//@ has foo/traitalias.Foo.html -//@ has - '//section[@id="main-content"]/pre[@class="rust item-decl"]' 'trait Foo = Into + Debug;' -pub trait Foo = Into + Debug; -//@ has foo/fn.bar.html '//a[@href="traitalias.Alias2.html"]' 'Alias2' -pub fn bar() where T: Alias2 {} From 01178849174bdff3e3e951827d9ea4884c23b758 Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Fri, 21 Mar 2025 10:09:17 -0400 Subject: [PATCH 559/606] Move eager translation to a method on `Diag` This will allow us to eagerly translate messages on a top-level diagnostic, such as a `LintDiagnostic`. As a bonus, we can remove the awkward closure passed into Subdiagnostic and make better use of `Into`. --- compiler/rustc_ast_passes/src/errors.rs | 14 +--- compiler/rustc_builtin_macros/src/errors.rs | 10 +-- compiler/rustc_const_eval/src/errors.rs | 10 +-- compiler/rustc_errors/src/diagnostic.rs | 33 ++++---- compiler/rustc_errors/src/diagnostic_impls.rs | 8 +- compiler/rustc_errors/src/lib.rs | 2 +- compiler/rustc_hir_typeck/src/errors.rs | 32 ++------ compiler/rustc_lint/src/errors.rs | 8 +- compiler/rustc_lint/src/if_let_rescope.rs | 12 +-- compiler/rustc_lint/src/lints.rs | 44 ++--------- .../src/diagnostics/subdiagnostic.rs | 15 +--- compiler/rustc_mir_build/src/errors.rs | 20 +---- .../src/lint_tail_expr_drop_order.rs | 16 ++-- compiler/rustc_parse/src/errors.rs | 9 +-- compiler/rustc_passes/src/errors.rs | 8 +- compiler/rustc_pattern_analysis/src/errors.rs | 14 +--- compiler/rustc_trait_selection/src/errors.rs | 78 ++++--------------- .../src/errors/note_and_explain.rs | 10 +-- .../ui-fulldeps/internal-lints/diagnostics.rs | 8 +- .../internal-lints/diagnostics.stderr | 18 ++--- 20 files changed, 98 insertions(+), 271 deletions(-) diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 8e53e600f7ac..bd139e2eb3f1 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -2,7 +2,7 @@ use rustc_ast::ParamKindOrd; use rustc_errors::codes::*; -use rustc_errors::{Applicability, Diag, EmissionGuarantee, SubdiagMessageOp, Subdiagnostic}; +use rustc_errors::{Applicability, Diag, EmissionGuarantee, Subdiagnostic}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{Ident, Span, Symbol}; @@ -394,11 +394,7 @@ pub(crate) struct EmptyLabelManySpans(pub Vec); // The derive for `Vec` does multiple calls to `span_label`, adding commas between each impl Subdiagnostic for EmptyLabelManySpans { - fn add_to_diag_with>( - self, - diag: &mut Diag<'_, G>, - _: &F, - ) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { diag.span_labels(self.0, ""); } } @@ -749,11 +745,7 @@ pub(crate) struct StableFeature { } impl Subdiagnostic for StableFeature { - fn add_to_diag_with>( - self, - diag: &mut Diag<'_, G>, - _: &F, - ) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { diag.arg("name", self.name); diag.arg("since", self.since); diag.help(fluent::ast_passes_stable_since); diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index c2b1dff4cf1f..d14ad8f40144 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -1,7 +1,7 @@ use rustc_errors::codes::*; use rustc_errors::{ Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, MultiSpan, SingleLabelManySpans, - SubdiagMessageOp, Subdiagnostic, + Subdiagnostic, }; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{Ident, Span, Symbol}; @@ -684,13 +684,9 @@ pub(crate) struct FormatUnusedArg { // Allow the singular form to be a subdiagnostic of the multiple-unused // form of diagnostic. impl Subdiagnostic for FormatUnusedArg { - fn add_to_diag_with>( - self, - diag: &mut Diag<'_, G>, - f: &F, - ) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { diag.arg("named", self.named); - let msg = f(diag, crate::fluent_generated::builtin_macros_format_unused_arg.into()); + let msg = diag.eagerly_translate(crate::fluent_generated::builtin_macros_format_unused_arg); diag.span_label(self.span, msg); } } diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index e2675e2f4c90..6472aaa57581 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -6,7 +6,7 @@ use rustc_abi::WrappingRange; use rustc_errors::codes::*; use rustc_errors::{ Diag, DiagArgValue, DiagCtxtHandle, DiagMessage, Diagnostic, EmissionGuarantee, Level, - MultiSpan, SubdiagMessageOp, Subdiagnostic, + MultiSpan, Subdiagnostic, }; use rustc_hir::ConstContext; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; @@ -290,11 +290,7 @@ pub struct FrameNote { } impl Subdiagnostic for FrameNote { - fn add_to_diag_with>( - self, - diag: &mut Diag<'_, G>, - f: &F, - ) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { diag.arg("times", self.times); diag.arg("where_", self.where_); diag.arg("instance", self.instance); @@ -302,7 +298,7 @@ impl Subdiagnostic for FrameNote { if self.has_label && !self.span.is_dummy() { span.push_span_label(self.span, fluent::const_eval_frame_note_last); } - let msg = f(diag, fluent::const_eval_frame_note.into()); + let msg = diag.eagerly_translate(fluent::const_eval_frame_note); diag.span_note(span, msg); } } diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index bd13c413a4df..539ecfbb42e2 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -181,22 +181,9 @@ where Self: Sized, { /// Add a subdiagnostic to an existing diagnostic. - fn add_to_diag(self, diag: &mut Diag<'_, G>) { - self.add_to_diag_with(diag, &|_, m| m); - } - - /// Add a subdiagnostic to an existing diagnostic where `f` is invoked on every message used - /// (to optionally perform eager translation). - fn add_to_diag_with>( - self, - diag: &mut Diag<'_, G>, - f: &F, - ); + fn add_to_diag(self, diag: &mut Diag<'_, G>); } -pub trait SubdiagMessageOp = - Fn(&mut Diag<'_, G>, SubdiagMessage) -> SubdiagMessage; - /// Trait implemented by lint types. This should not be implemented manually. Instead, use /// `#[derive(LintDiagnostic)]` -- see [rustc_macros::LintDiagnostic]. #[rustc_diagnostic_item = "LintDiagnostic"] @@ -1227,15 +1214,21 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { /// interpolated variables). #[rustc_lint_diagnostics] pub fn subdiagnostic(&mut self, subdiagnostic: impl Subdiagnostic) -> &mut Self { - let dcx = self.dcx; - subdiagnostic.add_to_diag_with(self, &|diag, msg| { - let args = diag.args.iter(); - let msg = diag.subdiagnostic_message_to_diagnostic_message(msg); - dcx.eagerly_translate(msg, args) - }); + subdiagnostic.add_to_diag(self); self } + /// Fluent variables are not namespaced from each other, so when + /// `Diagnostic`s and `Subdiagnostic`s use the same variable name, + /// one value will clobber the other. Eagerly translating the + /// diagnostic uses the variables defined right then, before the + /// clobbering occurs. + pub fn eagerly_translate(&self, msg: impl Into) -> SubdiagMessage { + let args = self.args.iter(); + let msg = self.subdiagnostic_message_to_diagnostic_message(msg.into()); + self.dcx.eagerly_translate(msg, args) + } + with_fn! { with_span, /// Add a span. #[rustc_lint_diagnostics] diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index cb2e1769fa1c..8b59ba9984c1 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -19,7 +19,7 @@ use {rustc_ast as ast, rustc_hir as hir}; use crate::diagnostic::DiagLocation; use crate::{ Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, ErrCode, IntoDiagArg, Level, - SubdiagMessageOp, Subdiagnostic, fluent_generated as fluent, + Subdiagnostic, fluent_generated as fluent, }; pub struct DiagArgFromDisplay<'a>(pub &'a dyn fmt::Display); @@ -384,11 +384,7 @@ pub struct SingleLabelManySpans { pub label: &'static str, } impl Subdiagnostic for SingleLabelManySpans { - fn add_to_diag_with>( - self, - diag: &mut Diag<'_, G>, - _: &F, - ) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { diag.span_labels(self.spans, self.label); } } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 75bb0e8e7b43..c0c5dba46772 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -47,7 +47,7 @@ pub use codes::*; pub use diagnostic::{ BugAbort, Diag, DiagArg, DiagArgMap, DiagArgName, DiagArgValue, DiagInner, DiagStyledString, Diagnostic, EmissionGuarantee, FatalAbort, IntoDiagArg, LintDiagnostic, StringPart, Subdiag, - SubdiagMessageOp, Subdiagnostic, + Subdiagnostic, }; pub use diagnostic_impls::{ DiagArgFromDisplay, DiagSymbolList, ElidedLifetimeInPathSubdiag, ExpectedLifetimeParameter, diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index dfaa374592bc..9e7305430e5f 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -5,7 +5,7 @@ use std::borrow::Cow; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagArgValue, DiagSymbolList, EmissionGuarantee, IntoDiagArg, MultiSpan, - SubdiagMessageOp, Subdiagnostic, + Subdiagnostic, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::{self, Ty}; @@ -270,11 +270,7 @@ pub(crate) struct SuggestAnnotations { pub suggestions: Vec, } impl Subdiagnostic for SuggestAnnotations { - fn add_to_diag_with>( - self, - diag: &mut Diag<'_, G>, - _: &F, - ) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { if self.suggestions.is_empty() { return; } @@ -337,11 +333,7 @@ pub(crate) struct TypeMismatchFruTypo { } impl Subdiagnostic for TypeMismatchFruTypo { - fn add_to_diag_with>( - self, - diag: &mut Diag<'_, G>, - _f: &F, - ) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { diag.arg("expr", self.expr.as_deref().unwrap_or("NONE")); // Only explain that `a ..b` is a range if it's split up @@ -599,11 +591,7 @@ pub(crate) struct RemoveSemiForCoerce { } impl Subdiagnostic for RemoveSemiForCoerce { - fn add_to_diag_with>( - self, - diag: &mut Diag<'_, G>, - _f: &F, - ) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { let mut multispan: MultiSpan = self.semi.into(); multispan.push_span_label(self.expr, fluent::hir_typeck_remove_semi_for_coerce_expr); multispan.push_span_label(self.ret, fluent::hir_typeck_remove_semi_for_coerce_ret); @@ -778,20 +766,16 @@ pub(crate) enum CastUnknownPointerSub { } impl rustc_errors::Subdiagnostic for CastUnknownPointerSub { - fn add_to_diag_with>( - self, - diag: &mut Diag<'_, G>, - f: &F, - ) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { match self { CastUnknownPointerSub::To(span) => { - let msg = f(diag, crate::fluent_generated::hir_typeck_label_to); + let msg = diag.eagerly_translate(fluent::hir_typeck_label_to); diag.span_label(span, msg); - let msg = f(diag, crate::fluent_generated::hir_typeck_note); + let msg = diag.eagerly_translate(fluent::hir_typeck_note); diag.note(msg); } CastUnknownPointerSub::From(span) => { - let msg = f(diag, crate::fluent_generated::hir_typeck_label_from); + let msg = diag.eagerly_translate(fluent::hir_typeck_label_from); diag.span_label(span, msg); } } diff --git a/compiler/rustc_lint/src/errors.rs b/compiler/rustc_lint/src/errors.rs index d109a5c90305..586e55c8055c 100644 --- a/compiler/rustc_lint/src/errors.rs +++ b/compiler/rustc_lint/src/errors.rs @@ -1,5 +1,5 @@ use rustc_errors::codes::*; -use rustc_errors::{Diag, EmissionGuarantee, SubdiagMessageOp, Subdiagnostic}; +use rustc_errors::{Diag, EmissionGuarantee, Subdiagnostic}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_session::lint::Level; use rustc_span::{Span, Symbol}; @@ -26,11 +26,7 @@ pub(crate) enum OverruledAttributeSub { } impl Subdiagnostic for OverruledAttributeSub { - fn add_to_diag_with>( - self, - diag: &mut Diag<'_, G>, - _f: &F, - ) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { match self { OverruledAttributeSub::DefaultSource { id } => { diag.note(fluent::lint_default_source); diff --git a/compiler/rustc_lint/src/if_let_rescope.rs b/compiler/rustc_lint/src/if_let_rescope.rs index 39ea8d8e3246..a9b04511c6b4 100644 --- a/compiler/rustc_lint/src/if_let_rescope.rs +++ b/compiler/rustc_lint/src/if_let_rescope.rs @@ -3,9 +3,7 @@ use std::ops::ControlFlow; use hir::intravisit::{self, Visitor}; use rustc_ast::Recovered; -use rustc_errors::{ - Applicability, Diag, EmissionGuarantee, SubdiagMessageOp, Subdiagnostic, SuggestionStyle, -}; +use rustc_errors::{Applicability, Diag, EmissionGuarantee, Subdiagnostic, SuggestionStyle}; use rustc_hir::{self as hir, HirIdSet}; use rustc_macros::{LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::adjustment::Adjust; @@ -327,11 +325,7 @@ struct IfLetRescopeRewrite { } impl Subdiagnostic for IfLetRescopeRewrite { - fn add_to_diag_with>( - self, - diag: &mut Diag<'_, G>, - f: &F, - ) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { let mut suggestions = vec![]; for match_head in self.match_heads { match match_head { @@ -360,7 +354,7 @@ impl Subdiagnostic for IfLetRescopeRewrite { .chain(repeat('}').take(closing_brackets.count)) .collect(), )); - let msg = f(diag, crate::fluent_generated::lint_suggestion); + let msg = diag.eagerly_translate(crate::fluent_generated::lint_suggestion); diag.multipart_suggestion_with_style( msg, suggestions, diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 51214c8e8a4c..8ab64fbd127a 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -6,7 +6,7 @@ use rustc_abi::ExternAbi; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagArgValue, DiagMessage, DiagStyledString, ElidedLifetimeInPathSubdiag, - EmissionGuarantee, LintDiagnostic, MultiSpan, SubdiagMessageOp, Subdiagnostic, SuggestionStyle, + EmissionGuarantee, LintDiagnostic, MultiSpan, Subdiagnostic, SuggestionStyle, }; use rustc_hir::def::Namespace; use rustc_hir::def_id::DefId; @@ -449,11 +449,7 @@ pub(crate) struct BuiltinUnpermittedTypeInitSub { } impl Subdiagnostic for BuiltinUnpermittedTypeInitSub { - fn add_to_diag_with>( - self, - diag: &mut Diag<'_, G>, - _f: &F, - ) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { let mut err = self.err; loop { if let Some(span) = err.span { @@ -504,11 +500,7 @@ pub(crate) struct BuiltinClashingExternSub<'a> { } impl Subdiagnostic for BuiltinClashingExternSub<'_> { - fn add_to_diag_with>( - self, - diag: &mut Diag<'_, G>, - _f: &F, - ) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { let mut expected_str = DiagStyledString::new(); expected_str.push(self.expected.fn_sig(self.tcx).to_string(), false); let mut found_str = DiagStyledString::new(); @@ -824,11 +816,7 @@ pub(crate) struct HiddenUnicodeCodepointsDiagLabels { } impl Subdiagnostic for HiddenUnicodeCodepointsDiagLabels { - fn add_to_diag_with>( - self, - diag: &mut Diag<'_, G>, - _f: &F, - ) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { for (c, span) in self.spans { diag.span_label(span, format!("{c:?}")); } @@ -842,11 +830,7 @@ pub(crate) enum HiddenUnicodeCodepointsDiagSub { // Used because of multiple multipart_suggestion and note impl Subdiagnostic for HiddenUnicodeCodepointsDiagSub { - fn add_to_diag_with>( - self, - diag: &mut Diag<'_, G>, - _f: &F, - ) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { match self { HiddenUnicodeCodepointsDiagSub::Escape { spans } => { diag.multipart_suggestion_with_style( @@ -1015,11 +999,7 @@ pub(crate) struct NonBindingLetSub { } impl Subdiagnostic for NonBindingLetSub { - fn add_to_diag_with>( - self, - diag: &mut Diag<'_, G>, - _f: &F, - ) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { let can_suggest_binding = self.drop_fn_start_end.is_some() || !self.is_assign_desugar; if can_suggest_binding { @@ -1303,11 +1283,7 @@ pub(crate) enum NonSnakeCaseDiagSub { } impl Subdiagnostic for NonSnakeCaseDiagSub { - fn add_to_diag_with>( - self, - diag: &mut Diag<'_, G>, - _f: &F, - ) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { match self { NonSnakeCaseDiagSub::Label { span } => { diag.span_label(span, fluent::lint_label); @@ -1629,11 +1605,7 @@ pub(crate) enum OverflowingBinHexSign { } impl Subdiagnostic for OverflowingBinHexSign { - fn add_to_diag_with>( - self, - diag: &mut Diag<'_, G>, - _f: &F, - ) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { match self { OverflowingBinHexSign::Positive => { diag.note(fluent::lint_positive_note); diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index 909083d5e865..bc9516b2e0c6 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -20,14 +20,12 @@ use crate::diagnostics::utils::{ /// The central struct for constructing the `add_to_diag` method from an annotated struct. pub(crate) struct SubdiagnosticDerive { diag: syn::Ident, - f: syn::Ident, } impl SubdiagnosticDerive { pub(crate) fn new() -> Self { let diag = format_ident!("diag"); - let f = format_ident!("f"); - Self { diag, f } + Self { diag } } pub(crate) fn into_tokens(self, mut structure: Structure<'_>) -> TokenStream { @@ -86,19 +84,16 @@ impl SubdiagnosticDerive { }; let diag = &self.diag; - let f = &self.f; // FIXME(edition_2024): Fix the `keyword_idents_2024` lint to not trigger here? #[allow(keyword_idents_2024)] let ret = structure.gen_impl(quote! { gen impl rustc_errors::Subdiagnostic for @Self { - fn add_to_diag_with<__G, __F>( + fn add_to_diag<__G>( self, #diag: &mut rustc_errors::Diag<'_, __G>, - #f: &__F ) where __G: rustc_errors::EmissionGuarantee, - __F: rustc_errors::SubdiagMessageOp<__G>, { #implementation } @@ -384,11 +379,10 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { Ok(quote! {}) } "subdiagnostic" => { - let f = &self.parent.f; let diag = &self.parent.diag; let binding = &info.binding; self.has_subdiagnostic = true; - Ok(quote! { #binding.add_to_diag_with(#diag, #f); }) + Ok(quote! { #binding.add_to_diag(#diag); }) } _ => { let mut span_attrs = vec![]; @@ -531,12 +525,11 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { let span_field = self.span_field.value_ref(); let diag = &self.parent.diag; - let f = &self.parent.f; let mut calls = TokenStream::new(); for (kind, slug, no_span) in kind_slugs { let message = format_ident!("__message"); calls.extend( - quote! { let #message = #f(#diag, crate::fluent_generated::#slug.into()); }, + quote! { let #message = #diag.eagerly_translate(crate::fluent_generated::#slug); }, ); let name = format_ident!( diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 0e16f871b16f..ae09db502352 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -2,7 +2,7 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, - MultiSpan, SubdiagMessageOp, Subdiagnostic, pluralize, + MultiSpan, Subdiagnostic, pluralize, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::{self, Ty}; @@ -546,11 +546,7 @@ pub(crate) struct UnsafeNotInheritedLintNote { } impl Subdiagnostic for UnsafeNotInheritedLintNote { - fn add_to_diag_with>( - self, - diag: &mut Diag<'_, G>, - _f: &F, - ) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { diag.span_note(self.signature_span, fluent::mir_build_unsafe_fn_safe_body); let body_start = self.body_span.shrink_to_lo(); let body_end = self.body_span.shrink_to_hi(); @@ -1031,11 +1027,7 @@ pub(crate) struct Variant { } impl<'tcx> Subdiagnostic for AdtDefinedHere<'tcx> { - fn add_to_diag_with>( - self, - diag: &mut Diag<'_, G>, - _f: &F, - ) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { diag.arg("ty", self.ty); let mut spans = MultiSpan::from(self.adt_def_span); @@ -1117,11 +1109,7 @@ pub(crate) struct Rust2024IncompatiblePatSugg { } impl Subdiagnostic for Rust2024IncompatiblePatSugg { - fn add_to_diag_with>( - self, - diag: &mut Diag<'_, G>, - _f: &F, - ) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { // Format and emit explanatory notes about default binding modes. Reversing the spans' order // means if we have nested spans, the innermost ones will be visited first. for (span, def_br_mutbl) in self.default_mode_labels.into_iter().rev() { diff --git a/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs index 29a9133abe93..537f152938ef 100644 --- a/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs +++ b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs @@ -512,23 +512,17 @@ struct LocalLabel<'a> { /// A custom `Subdiagnostic` implementation so that the notes are delivered in a specific order impl Subdiagnostic for LocalLabel<'_> { - fn add_to_diag_with< - G: rustc_errors::EmissionGuarantee, - F: rustc_errors::SubdiagMessageOp, - >( - self, - diag: &mut rustc_errors::Diag<'_, G>, - f: &F, - ) { + fn add_to_diag(self, diag: &mut rustc_errors::Diag<'_, G>) { diag.arg("name", self.name); diag.arg("is_generated_name", self.is_generated_name); diag.arg("is_dropped_first_edition_2024", self.is_dropped_first_edition_2024); - let msg = f(diag, crate::fluent_generated::mir_transform_tail_expr_local.into()); + let msg = diag.eagerly_translate(crate::fluent_generated::mir_transform_tail_expr_local); diag.span_label(self.span, msg); for dtor in self.destructors { - dtor.add_to_diag_with(diag, f); + dtor.add_to_diag(diag); } - let msg = f(diag, crate::fluent_generated::mir_transform_label_local_epilogue); + let msg = + diag.eagerly_translate(crate::fluent_generated::mir_transform_label_local_epilogue); diag.span_label(self.span, msg); } } diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index dfdef018bc37..57534bc8c318 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -7,8 +7,7 @@ use rustc_ast::util::parser::ExprPrecedence; use rustc_ast::{Path, Visibility}; use rustc_errors::codes::*; use rustc_errors::{ - Applicability, Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, SubdiagMessageOp, - Subdiagnostic, + Applicability, Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, Subdiagnostic, }; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_session::errors::ExprParenthesesNeeded; @@ -1551,11 +1550,7 @@ pub(crate) struct FnTraitMissingParen { } impl Subdiagnostic for FnTraitMissingParen { - fn add_to_diag_with>( - self, - diag: &mut Diag<'_, G>, - _: &F, - ) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { diag.span_label(self.span, crate::fluent_generated::parse_fn_trait_missing_paren); diag.span_suggestion_short( self.span.shrink_to_hi(), diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 85eddafefcd5..995fc85676e8 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -5,7 +5,7 @@ use rustc_ast::Label; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagCtxtHandle, DiagSymbolList, Diagnostic, EmissionGuarantee, Level, - MultiSpan, SubdiagMessageOp, Subdiagnostic, + MultiSpan, Subdiagnostic, }; use rustc_hir::{self as hir, ExprKind, Target}; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; @@ -1852,11 +1852,7 @@ pub(crate) struct UnusedVariableStringInterp { } impl Subdiagnostic for UnusedVariableStringInterp { - fn add_to_diag_with>( - self, - diag: &mut Diag<'_, G>, - _f: &F, - ) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { diag.span_label(self.lit, crate::fluent_generated::passes_maybe_string_interpolation); diag.multipart_suggestion( crate::fluent_generated::passes_string_interpolation_only_works, diff --git a/compiler/rustc_pattern_analysis/src/errors.rs b/compiler/rustc_pattern_analysis/src/errors.rs index 1f7852e5190d..e60930d6cd21 100644 --- a/compiler/rustc_pattern_analysis/src/errors.rs +++ b/compiler/rustc_pattern_analysis/src/errors.rs @@ -1,4 +1,4 @@ -use rustc_errors::{Diag, EmissionGuarantee, SubdiagMessageOp, Subdiagnostic}; +use rustc_errors::{Diag, EmissionGuarantee, Subdiagnostic}; use rustc_macros::{LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::Ty; use rustc_span::Span; @@ -55,11 +55,7 @@ pub struct Overlap { } impl Subdiagnostic for Overlap { - fn add_to_diag_with>( - self, - diag: &mut Diag<'_, G>, - _: &F, - ) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { let Overlap { span, range } = self; // FIXME(mejrs) unfortunately `#[derive(LintDiagnostic)]` @@ -103,11 +99,7 @@ pub struct GappedRange { } impl Subdiagnostic for GappedRange { - fn add_to_diag_with>( - self, - diag: &mut Diag<'_, G>, - _: &F, - ) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { let GappedRange { span, gap, first_range } = self; // FIXME(mejrs) unfortunately `#[derive(LintDiagnostic)]` diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index 4e5581fb1da0..756d9a57b935 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -4,7 +4,7 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagCtxtHandle, DiagMessage, DiagStyledString, Diagnostic, - EmissionGuarantee, IntoDiagArg, Level, MultiSpan, SubdiagMessageOp, Subdiagnostic, + EmissionGuarantee, IntoDiagArg, Level, MultiSpan, Subdiagnostic, }; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -107,11 +107,7 @@ pub enum AdjustSignatureBorrow { } impl Subdiagnostic for AdjustSignatureBorrow { - fn add_to_diag_with>( - self, - diag: &mut Diag<'_, G>, - _f: &F, - ) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { match self { AdjustSignatureBorrow::Borrow { to_borrow } => { diag.arg("len", to_borrow.len()); @@ -381,11 +377,7 @@ pub enum RegionOriginNote<'a> { } impl Subdiagnostic for RegionOriginNote<'_> { - fn add_to_diag_with>( - self, - diag: &mut Diag<'_, G>, - _f: &F, - ) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { let mut label_or_note = |span, msg: DiagMessage| { let sub_count = diag.children.iter().filter(|d| d.span.is_dummy()).count(); let expanded_sub_count = diag.children.iter().filter(|d| !d.span.is_dummy()).count(); @@ -446,11 +438,7 @@ pub enum LifetimeMismatchLabels { } impl Subdiagnostic for LifetimeMismatchLabels { - fn add_to_diag_with>( - self, - diag: &mut Diag<'_, G>, - _f: &F, - ) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { match self { LifetimeMismatchLabels::InRet { param_span, ret_span, span, label_var1 } => { diag.span_label(param_span, fluent::trait_selection_declared_different); @@ -495,11 +483,7 @@ pub struct AddLifetimeParamsSuggestion<'a> { } impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> { - fn add_to_diag_with>( - self, - diag: &mut Diag<'_, G>, - _f: &F, - ) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { let mut mk_suggestion = || { let Some(anon_reg) = self.tcx.is_suitable_region(self.generic_param_scope, self.sub) else { @@ -689,11 +673,7 @@ pub struct IntroducesStaticBecauseUnmetLifetimeReq { } impl Subdiagnostic for IntroducesStaticBecauseUnmetLifetimeReq { - fn add_to_diag_with>( - mut self, - diag: &mut Diag<'_, G>, - _f: &F, - ) { + fn add_to_diag(mut self, diag: &mut Diag<'_, G>) { self.unmet_requirements .push_span_label(self.binding_span, fluent::trait_selection_msl_introduces_static); diag.span_note(self.unmet_requirements, fluent::trait_selection_msl_unmet_req); @@ -1008,17 +988,13 @@ pub struct ConsiderBorrowingParamHelp { } impl Subdiagnostic for ConsiderBorrowingParamHelp { - fn add_to_diag_with>( - self, - diag: &mut Diag<'_, G>, - f: &F, - ) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { let mut type_param_span: MultiSpan = self.spans.clone().into(); for &span in &self.spans { // Seems like we can't call f() here as Into is required type_param_span.push_span_label(span, fluent::trait_selection_tid_consider_borrowing); } - let msg = f(diag, fluent::trait_selection_tid_param_help.into()); + let msg = diag.eagerly_translate(fluent::trait_selection_tid_param_help); diag.span_help(type_param_span, msg); } } @@ -1053,18 +1029,14 @@ pub struct DynTraitConstraintSuggestion { } impl Subdiagnostic for DynTraitConstraintSuggestion { - fn add_to_diag_with>( - self, - diag: &mut Diag<'_, G>, - f: &F, - ) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { let mut multi_span: MultiSpan = vec![self.span].into(); multi_span.push_span_label(self.span, fluent::trait_selection_dtcs_has_lifetime_req_label); multi_span .push_span_label(self.ident.span, fluent::trait_selection_dtcs_introduces_requirement); - let msg = f(diag, fluent::trait_selection_dtcs_has_req_note.into()); + let msg = diag.eagerly_translate(fluent::trait_selection_dtcs_has_req_note); diag.span_note(multi_span, msg); - let msg = f(diag, fluent::trait_selection_dtcs_suggestion.into()); + let msg = diag.eagerly_translate(fluent::trait_selection_dtcs_suggestion); diag.span_suggestion_verbose( self.span.shrink_to_hi(), msg, @@ -1101,11 +1073,7 @@ pub struct ReqIntroducedLocations { } impl Subdiagnostic for ReqIntroducedLocations { - fn add_to_diag_with>( - mut self, - diag: &mut Diag<'_, G>, - f: &F, - ) { + fn add_to_diag(mut self, diag: &mut Diag<'_, G>) { for sp in self.spans { self.span.push_span_label(sp, fluent::trait_selection_ril_introduced_here); } @@ -1114,7 +1082,7 @@ impl Subdiagnostic for ReqIntroducedLocations { self.span.push_span_label(self.fn_decl_span, fluent::trait_selection_ril_introduced_by); } self.span.push_span_label(self.cause_span, fluent::trait_selection_ril_because_of); - let msg = f(diag, fluent::trait_selection_ril_static_introduced_by.into()); + let msg = diag.eagerly_translate(fluent::trait_selection_ril_static_introduced_by); diag.span_note(self.span, msg); } } @@ -1513,13 +1481,9 @@ pub struct SuggestTuplePatternMany { } impl Subdiagnostic for SuggestTuplePatternMany { - fn add_to_diag_with>( - self, - diag: &mut Diag<'_, G>, - f: &F, - ) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { diag.arg("path", self.path); - let message = f(diag, crate::fluent_generated::trait_selection_stp_wrap_many.into()); + let message = diag.eagerly_translate(fluent::trait_selection_stp_wrap_many); diag.multipart_suggestions( message, self.compatible_variants.into_iter().map(|variant| { @@ -1752,11 +1716,7 @@ pub struct AddPreciseCapturingAndParams { } impl Subdiagnostic for AddPreciseCapturingAndParams { - fn add_to_diag_with>( - self, - diag: &mut Diag<'_, G>, - _f: &F, - ) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { diag.arg("new_lifetime", self.new_lifetime); diag.multipart_suggestion_verbose( fluent::trait_selection_precise_capturing_new_but_apit, @@ -1896,11 +1856,7 @@ pub struct AddPreciseCapturingForOvercapture { } impl Subdiagnostic for AddPreciseCapturingForOvercapture { - fn add_to_diag_with>( - self, - diag: &mut Diag<'_, G>, - _f: &F, - ) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { let applicability = if self.apit_spans.is_empty() { Applicability::MachineApplicable } else { diff --git a/compiler/rustc_trait_selection/src/errors/note_and_explain.rs b/compiler/rustc_trait_selection/src/errors/note_and_explain.rs index e4ab78b62477..84e7686fdd3f 100644 --- a/compiler/rustc_trait_selection/src/errors/note_and_explain.rs +++ b/compiler/rustc_trait_selection/src/errors/note_and_explain.rs @@ -1,4 +1,4 @@ -use rustc_errors::{Diag, EmissionGuarantee, IntoDiagArg, SubdiagMessageOp, Subdiagnostic}; +use rustc_errors::{Diag, EmissionGuarantee, IntoDiagArg, Subdiagnostic}; use rustc_hir::def_id::LocalDefId; use rustc_middle::bug; use rustc_middle::ty::{self, TyCtxt}; @@ -162,17 +162,13 @@ impl RegionExplanation<'_> { } impl Subdiagnostic for RegionExplanation<'_> { - fn add_to_diag_with>( - self, - diag: &mut Diag<'_, G>, - f: &F, - ) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { diag.arg("pref_kind", self.prefix); diag.arg("suff_kind", self.suffix); diag.arg("desc_kind", self.desc.kind); diag.arg("desc_arg", self.desc.arg); - let msg = f(diag, fluent::trait_selection_region_explanation.into()); + let msg = diag.eagerly_translate(fluent::trait_selection_region_explanation); if let Some(span) = self.desc.span { diag.span_note(span, msg); } else { diff --git a/tests/ui-fulldeps/internal-lints/diagnostics.rs b/tests/ui-fulldeps/internal-lints/diagnostics.rs index 442f9d72c3f1..1238fefd5bc0 100644 --- a/tests/ui-fulldeps/internal-lints/diagnostics.rs +++ b/tests/ui-fulldeps/internal-lints/diagnostics.rs @@ -15,7 +15,7 @@ extern crate rustc_span; use rustc_errors::{ Diag, DiagCtxtHandle, DiagInner, DiagMessage, Diagnostic, EmissionGuarantee, Level, - LintDiagnostic, SubdiagMessage, SubdiagMessageOp, Subdiagnostic, + LintDiagnostic, SubdiagMessage, Subdiagnostic, }; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::Span; @@ -56,10 +56,9 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for TranslatableInDiagnostic { pub struct UntranslatableInAddtoDiag; impl Subdiagnostic for UntranslatableInAddtoDiag { - fn add_to_diag_with>( + fn add_to_diag( self, diag: &mut Diag<'_, G>, - f: &F, ) { diag.note("untranslatable diagnostic"); //~^ ERROR diagnostics should be created using translatable messages @@ -69,10 +68,9 @@ impl Subdiagnostic for UntranslatableInAddtoDiag { pub struct TranslatableInAddtoDiag; impl Subdiagnostic for TranslatableInAddtoDiag { - fn add_to_diag_with>( + fn add_to_diag( self, diag: &mut Diag<'_, G>, - f: &F, ) { diag.note(crate::fluent_generated::no_crate_note); } diff --git a/tests/ui-fulldeps/internal-lints/diagnostics.stderr b/tests/ui-fulldeps/internal-lints/diagnostics.stderr index 36dd3cf4be79..b260c4b7afef 100644 --- a/tests/ui-fulldeps/internal-lints/diagnostics.stderr +++ b/tests/ui-fulldeps/internal-lints/diagnostics.stderr @@ -11,19 +11,19 @@ LL | #![deny(rustc::untranslatable_diagnostic)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostics should be created using translatable messages - --> $DIR/diagnostics.rs:64:19 + --> $DIR/diagnostics.rs:63:19 | LL | diag.note("untranslatable diagnostic"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostics should be created using translatable messages - --> $DIR/diagnostics.rs:85:19 + --> $DIR/diagnostics.rs:83:19 | LL | diag.note("untranslatable diagnostic"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostics should only be created in `Diagnostic`/`Subdiagnostic`/`LintDiagnostic` impls - --> $DIR/diagnostics.rs:99:21 + --> $DIR/diagnostics.rs:97:21 | LL | let _diag = dcx.struct_err(crate::fluent_generated::no_crate_example); | ^^^^^^^^^^ @@ -35,37 +35,37 @@ LL | #![deny(rustc::diagnostic_outside_of_impl)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostics should only be created in `Diagnostic`/`Subdiagnostic`/`LintDiagnostic` impls - --> $DIR/diagnostics.rs:102:21 + --> $DIR/diagnostics.rs:100:21 | LL | let _diag = dcx.struct_err("untranslatable diagnostic"); | ^^^^^^^^^^ error: diagnostics should be created using translatable messages - --> $DIR/diagnostics.rs:102:32 + --> $DIR/diagnostics.rs:100:32 | LL | let _diag = dcx.struct_err("untranslatable diagnostic"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostics should be created using translatable messages - --> $DIR/diagnostics.rs:120:7 + --> $DIR/diagnostics.rs:118:7 | LL | f("untranslatable diagnostic", crate::fluent_generated::no_crate_example); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostics should be created using translatable messages - --> $DIR/diagnostics.rs:122:50 + --> $DIR/diagnostics.rs:120:50 | LL | f(crate::fluent_generated::no_crate_example, "untranslatable diagnostic"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostics should be created using translatable messages - --> $DIR/diagnostics.rs:124:7 + --> $DIR/diagnostics.rs:122:7 | LL | f("untranslatable diagnostic", "untranslatable diagnostic"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostics should be created using translatable messages - --> $DIR/diagnostics.rs:124:36 + --> $DIR/diagnostics.rs:122:36 | LL | f("untranslatable diagnostic", "untranslatable diagnostic"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ From 675360ae4e79b515a6645f98d7998507ad215164 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 22 Oct 2024 12:08:30 +1100 Subject: [PATCH 560/606] Remove some unnecessary lifetimes. `FlowSensitiveAnalysis` is only instantiated with the first two lifetimes being the same. --- .../src/check_consts/check.rs | 2 +- .../src/check_consts/resolver.rs | 24 +++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index 2b74c849f1ae..b600b8918dd0 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -34,7 +34,7 @@ use crate::check_consts::is_fn_or_trait_safe_to_expose_on_stable; use crate::errors; type QualifResults<'mir, 'tcx, Q> = - rustc_mir_dataflow::ResultsCursor<'mir, 'tcx, FlowSensitiveAnalysis<'mir, 'mir, 'tcx, Q>>; + rustc_mir_dataflow::ResultsCursor<'mir, 'tcx, FlowSensitiveAnalysis<'mir, 'tcx, Q>>; #[derive(Copy, Clone, PartialEq, Eq, Debug)] enum ConstConditionsHold { diff --git a/compiler/rustc_const_eval/src/check_consts/resolver.rs b/compiler/rustc_const_eval/src/check_consts/resolver.rs index 8cee282311f0..9f7fcc509a58 100644 --- a/compiler/rustc_const_eval/src/check_consts/resolver.rs +++ b/compiler/rustc_const_eval/src/check_consts/resolver.rs @@ -22,17 +22,17 @@ use super::{ConstCx, Qualif, qualifs}; /// qualified immediately after it is borrowed or its address escapes. The borrow must allow for /// mutation, which includes shared borrows of places with interior mutability. The type of /// borrowed place must contain the qualif. -struct TransferFunction<'a, 'mir, 'tcx, Q> { - ccx: &'a ConstCx<'mir, 'tcx>, - state: &'a mut State, +struct TransferFunction<'mir, 'tcx, Q> { + ccx: &'mir ConstCx<'mir, 'tcx>, + state: &'mir mut State, _qualif: PhantomData, } -impl<'a, 'mir, 'tcx, Q> TransferFunction<'a, 'mir, 'tcx, Q> +impl<'mir, 'tcx, Q> TransferFunction<'mir, 'tcx, Q> where Q: Qualif, { - fn new(ccx: &'a ConstCx<'mir, 'tcx>, state: &'a mut State) -> Self { + fn new(ccx: &'mir ConstCx<'mir, 'tcx>, state: &'mir mut State) -> Self { TransferFunction { ccx, state, _qualif: PhantomData } } @@ -124,7 +124,7 @@ where } } -impl<'tcx, Q> Visitor<'tcx> for TransferFunction<'_, '_, 'tcx, Q> +impl<'tcx, Q> Visitor<'tcx> for TransferFunction<'_, 'tcx, Q> where Q: Qualif, { @@ -228,20 +228,20 @@ where } /// The dataflow analysis used to propagate qualifs on arbitrary CFGs. -pub(super) struct FlowSensitiveAnalysis<'a, 'mir, 'tcx, Q> { - ccx: &'a ConstCx<'mir, 'tcx>, +pub(super) struct FlowSensitiveAnalysis<'mir, 'tcx, Q> { + ccx: &'mir ConstCx<'mir, 'tcx>, _qualif: PhantomData, } -impl<'a, 'mir, 'tcx, Q> FlowSensitiveAnalysis<'a, 'mir, 'tcx, Q> +impl<'mir, 'tcx, Q> FlowSensitiveAnalysis<'mir, 'tcx, Q> where Q: Qualif, { - pub(super) fn new(_: Q, ccx: &'a ConstCx<'mir, 'tcx>) -> Self { + pub(super) fn new(_: Q, ccx: &'mir ConstCx<'mir, 'tcx>) -> Self { FlowSensitiveAnalysis { ccx, _qualif: PhantomData } } - fn transfer_function(&self, state: &'a mut State) -> TransferFunction<'a, 'mir, 'tcx, Q> { + fn transfer_function(&self, state: &'mir mut State) -> TransferFunction<'mir, 'tcx, Q> { TransferFunction::::new(self.ccx, state) } } @@ -313,7 +313,7 @@ impl JoinSemiLattice for State { } } -impl<'tcx, Q> Analysis<'tcx> for FlowSensitiveAnalysis<'_, '_, 'tcx, Q> +impl<'tcx, Q> Analysis<'tcx> for FlowSensitiveAnalysis<'_, 'tcx, Q> where Q: Qualif, { From 99a60eb97f49bb63cb89f865ff1edd26decd7165 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 22 Oct 2024 13:41:09 +1100 Subject: [PATCH 561/606] `intern_with_temp_alloc` is for `DummyMachine` only. --- compiler/rustc_const_eval/src/interpret/intern.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs index e4b2fe5d153e..8f0cb197c445 100644 --- a/compiler/rustc_const_eval/src/interpret/intern.rs +++ b/compiler/rustc_const_eval/src/interpret/intern.rs @@ -30,6 +30,7 @@ use super::{ AllocId, Allocation, InterpCx, MPlaceTy, Machine, MemoryKind, PlaceTy, err_ub, interp_ok, }; use crate::const_eval; +use crate::const_eval::DummyMachine; use crate::errors::NestedStaticInThreadLocal; pub trait CompileTimeMachine<'tcx, T> = Machine< @@ -323,14 +324,17 @@ pub fn intern_const_alloc_for_constprop<'tcx, T, M: CompileTimeMachine<'tcx, T>> interp_ok(()) } -impl<'tcx, M: super::intern::CompileTimeMachine<'tcx, !>> InterpCx<'tcx, M> { +impl<'tcx> InterpCx<'tcx, DummyMachine> { /// A helper function that allocates memory for the layout given and gives you access to mutate /// it. Once your own mutation code is done, the backing `Allocation` is removed from the /// current `Memory` and interned as read-only into the global memory. pub fn intern_with_temp_alloc( &mut self, layout: TyAndLayout<'tcx>, - f: impl FnOnce(&mut InterpCx<'tcx, M>, &PlaceTy<'tcx, M::Provenance>) -> InterpResult<'tcx, ()>, + f: impl FnOnce( + &mut InterpCx<'tcx, DummyMachine>, + &PlaceTy<'tcx, CtfeProvenance>, + ) -> InterpResult<'tcx, ()>, ) -> InterpResult<'tcx, AllocId> { // `allocate` picks a fresh AllocId that we will associate with its data below. let dest = self.allocate(layout, MemoryKind::Stack)?; From 5636312c71e3e4eb7f1afc3e945bd7dc11697d4c Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Thu, 17 Apr 2025 11:50:24 +0800 Subject: [PATCH 562/606] git: ignore `60600a6fa403216bfd66e04f948b1822f6450af7` for blame purposes It was simply breaking up compiletest's `runtest.rs` and isn't very useful in git blame. --- .git-blame-ignore-revs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index d2a017bd2a02..af071c706856 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -31,3 +31,5 @@ ec2cc761bc7067712ecc7734502f703fe3b024c8 c682aa162b0d41e21cc6748f4fecfe01efb69d1f # reformat with updated edition 2024 1fcae03369abb4c2cc180cd5a49e1f4440a81300 +# Breaking up of compiletest runtest.rs +60600a6fa403216bfd66e04f948b1822f6450af7 From 62146748d8b422fcbeb4b0c6e02a8e7a576f4909 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Tue, 15 Apr 2025 20:15:54 +0200 Subject: [PATCH 563/606] rustdoc/clean: Change terminology of items pertaining to (formal) fn params from "argument" to "parameter" --- src/librustdoc/clean/mod.rs | 150 +++++++++------------ src/librustdoc/clean/types.rs | 16 +-- src/librustdoc/html/format.rs | 54 ++++---- src/librustdoc/html/render/search_index.rs | 12 +- src/librustdoc/json/conversions.rs | 9 +- 5 files changed, 107 insertions(+), 134 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index fe9dc9a9e214..249a822076ec 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1052,7 +1052,7 @@ fn clean_fn_or_proc_macro<'tcx>( match macro_kind { Some(kind) => clean_proc_macro(item, name, kind, cx), None => { - let mut func = clean_function(cx, sig, generics, FunctionArgs::Body(body_id)); + let mut func = clean_function(cx, sig, generics, ParamsSrc::Body(body_id)); clean_fn_decl_legacy_const_generics(&mut func, attrs); FunctionItem(func) } @@ -1071,16 +1071,11 @@ fn clean_fn_decl_legacy_const_generics(func: &mut Function, attrs: &[hir::Attrib for (pos, literal) in meta_item_list.iter().filter_map(|meta| meta.lit()).enumerate() { match literal.kind { ast::LitKind::Int(a, _) => { - let param = func.generics.params.remove(0); - if let GenericParamDef { - name, - kind: GenericParamDefKind::Const { ty, .. }, - .. - } = param - { - func.decl.inputs.values.insert( + let GenericParamDef { name, kind, .. } = func.generics.params.remove(0); + if let GenericParamDefKind::Const { ty, .. } = kind { + func.decl.inputs.insert( a.get() as _, - Argument { name: Some(name), type_: *ty, is_const: true }, + Parameter { name: Some(name), type_: *ty, is_const: true }, ); } else { panic!("unexpected non const in position {pos}"); @@ -1092,7 +1087,7 @@ fn clean_fn_decl_legacy_const_generics(func: &mut Function, attrs: &[hir::Attrib } } -enum FunctionArgs<'tcx> { +enum ParamsSrc<'tcx> { Body(hir::BodyId), Idents(&'tcx [Option]), } @@ -1101,30 +1096,26 @@ fn clean_function<'tcx>( cx: &mut DocContext<'tcx>, sig: &hir::FnSig<'tcx>, generics: &hir::Generics<'tcx>, - args: FunctionArgs<'tcx>, + params: ParamsSrc<'tcx>, ) -> Box { let (generics, decl) = enter_impl_trait(cx, |cx| { - // NOTE: generics must be cleaned before args + // NOTE: Generics must be cleaned before params. let generics = clean_generics(generics, cx); - let args = match args { - FunctionArgs::Body(body_id) => { - clean_args_from_types_and_body_id(cx, sig.decl.inputs, body_id) - } - FunctionArgs::Idents(idents) => { - clean_args_from_types_and_names(cx, sig.decl.inputs, idents) - } + let params = match params { + ParamsSrc::Body(body_id) => clean_params_via_body(cx, sig.decl.inputs, body_id), + ParamsSrc::Idents(idents) => clean_params(cx, sig.decl.inputs, idents), }; - let decl = clean_fn_decl_with_args(cx, sig.decl, Some(&sig.header), args); + let decl = clean_fn_decl_with_params(cx, sig.decl, Some(&sig.header), params); (generics, decl) }); Box::new(Function { decl, generics }) } -fn clean_args_from_types_and_names<'tcx>( +fn clean_params<'tcx>( cx: &mut DocContext<'tcx>, types: &[hir::Ty<'tcx>], idents: &[Option], -) -> Arguments { +) -> Vec { fn nonempty_name(ident: &Option) -> Option { if let Some(ident) = ident && ident.name != kw::Underscore @@ -1143,44 +1134,38 @@ fn clean_args_from_types_and_names<'tcx>( None }; - Arguments { - values: types - .iter() - .enumerate() - .map(|(i, ty)| Argument { - type_: clean_ty(ty, cx), - name: idents.get(i).and_then(nonempty_name).or(default_name), - is_const: false, - }) - .collect(), - } + types + .iter() + .enumerate() + .map(|(i, ty)| Parameter { + name: idents.get(i).and_then(nonempty_name).or(default_name), + type_: clean_ty(ty, cx), + is_const: false, + }) + .collect() } -fn clean_args_from_types_and_body_id<'tcx>( +fn clean_params_via_body<'tcx>( cx: &mut DocContext<'tcx>, types: &[hir::Ty<'tcx>], body_id: hir::BodyId, -) -> Arguments { - let body = cx.tcx.hir_body(body_id); - - Arguments { - values: types - .iter() - .zip(body.params) - .map(|(ty, param)| Argument { - name: Some(name_from_pat(param.pat)), - type_: clean_ty(ty, cx), - is_const: false, - }) - .collect(), - } +) -> Vec { + types + .iter() + .zip(cx.tcx.hir_body(body_id).params) + .map(|(ty, param)| Parameter { + name: Some(name_from_pat(param.pat)), + type_: clean_ty(ty, cx), + is_const: false, + }) + .collect() } -fn clean_fn_decl_with_args<'tcx>( +fn clean_fn_decl_with_params<'tcx>( cx: &mut DocContext<'tcx>, decl: &hir::FnDecl<'tcx>, header: Option<&hir::FnHeader>, - args: Arguments, + params: Vec, ) -> FnDecl { let mut output = match decl.output { hir::FnRetTy::Return(typ) => clean_ty(typ, cx), @@ -1191,7 +1176,7 @@ fn clean_fn_decl_with_args<'tcx>( { output = output.sugared_async_return_type(); } - FnDecl { inputs: args, output, c_variadic: decl.c_variadic } + FnDecl { inputs: params, output, c_variadic: decl.c_variadic } } fn clean_poly_fn_sig<'tcx>( @@ -1201,8 +1186,6 @@ fn clean_poly_fn_sig<'tcx>( ) -> FnDecl { let mut names = did.map_or(&[] as &[_], |did| cx.tcx.fn_arg_idents(did)).iter(); - // We assume all empty tuples are default return type. This theoretically can discard `-> ()`, - // but shouldn't change any code meaning. let mut output = clean_middle_ty(sig.output(), cx, None, None); // If the return type isn't an `impl Trait`, we can safely assume that this @@ -1215,25 +1198,21 @@ fn clean_poly_fn_sig<'tcx>( output = output.sugared_async_return_type(); } - FnDecl { - output, - c_variadic: sig.skip_binder().c_variadic, - inputs: Arguments { - values: sig - .inputs() - .iter() - .map(|t| Argument { - type_: clean_middle_ty(t.map_bound(|t| *t), cx, None, None), - name: Some(if let Some(Some(ident)) = names.next() { - ident.name - } else { - kw::Underscore - }), - is_const: false, - }) - .collect(), - }, - } + let params = sig + .inputs() + .iter() + .map(|t| Parameter { + type_: clean_middle_ty(t.map_bound(|t| *t), cx, None, None), + name: Some(if let Some(Some(ident)) = names.next() { + ident.name + } else { + kw::Underscore + }), + is_const: false, + }) + .collect(); + + FnDecl { inputs: params, output, c_variadic: sig.skip_binder().c_variadic } } fn clean_trait_ref<'tcx>(trait_ref: &hir::TraitRef<'tcx>, cx: &mut DocContext<'tcx>) -> Path { @@ -1273,11 +1252,11 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext RequiredAssocConstItem(generics, Box::new(clean_ty(ty, cx))) } hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => { - let m = clean_function(cx, sig, trait_item.generics, FunctionArgs::Body(body)); + let m = clean_function(cx, sig, trait_item.generics, ParamsSrc::Body(body)); MethodItem(m, None) } hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(idents)) => { - let m = clean_function(cx, sig, trait_item.generics, FunctionArgs::Idents(idents)); + let m = clean_function(cx, sig, trait_item.generics, ParamsSrc::Idents(idents)); RequiredMethodItem(m) } hir::TraitItemKind::Type(bounds, Some(default)) => { @@ -1318,7 +1297,7 @@ pub(crate) fn clean_impl_item<'tcx>( type_: clean_ty(ty, cx), })), hir::ImplItemKind::Fn(ref sig, body) => { - let m = clean_function(cx, sig, impl_.generics, FunctionArgs::Body(body)); + let m = clean_function(cx, sig, impl_.generics, ParamsSrc::Body(body)); let defaultness = cx.tcx.defaultness(impl_.owner_id); MethodItem(m, Some(defaultness)) } @@ -1390,14 +1369,14 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo } ty::AssocItemContainer::Trait => tcx.types.self_param, }; - let self_arg_ty = + let self_param_ty = tcx.fn_sig(assoc_item.def_id).instantiate_identity().input(0).skip_binder(); - if self_arg_ty == self_ty { - item.decl.inputs.values[0].type_ = SelfTy; - } else if let ty::Ref(_, ty, _) = *self_arg_ty.kind() + if self_param_ty == self_ty { + item.decl.inputs[0].type_ = SelfTy; + } else if let ty::Ref(_, ty, _) = *self_param_ty.kind() && ty == self_ty { - match item.decl.inputs.values[0].type_ { + match item.decl.inputs[0].type_ { BorrowedRef { ref mut type_, .. } => **type_ = SelfTy, _ => unreachable!(), } @@ -2611,15 +2590,15 @@ fn clean_bare_fn_ty<'tcx>( cx: &mut DocContext<'tcx>, ) -> BareFunctionDecl { let (generic_params, decl) = enter_impl_trait(cx, |cx| { - // NOTE: generics must be cleaned before args + // NOTE: Generics must be cleaned before params. let generic_params = bare_fn .generic_params .iter() .filter(|p| !is_elided_lifetime(p)) .map(|x| clean_generic_param(cx, None, x)) .collect(); - let args = clean_args_from_types_and_names(cx, bare_fn.decl.inputs, bare_fn.param_idents); - let decl = clean_fn_decl_with_args(cx, bare_fn.decl, None, args); + let params = clean_params(cx, bare_fn.decl.inputs, bare_fn.param_idents); + let decl = clean_fn_decl_with_params(cx, bare_fn.decl, None, params); (generic_params, decl) }); BareFunctionDecl { safety: bare_fn.safety, abi: bare_fn.abi, decl, generic_params } @@ -2629,7 +2608,6 @@ fn clean_unsafe_binder_ty<'tcx>( unsafe_binder_ty: &hir::UnsafeBinderTy<'tcx>, cx: &mut DocContext<'tcx>, ) -> UnsafeBinderTy { - // NOTE: generics must be cleaned before args let generic_params = unsafe_binder_ty .generic_params .iter() @@ -3155,7 +3133,7 @@ fn clean_maybe_renamed_foreign_item<'tcx>( cx.with_param_env(def_id, |cx| { let kind = match item.kind { hir::ForeignItemKind::Fn(sig, idents, generics) => ForeignFunctionItem( - clean_function(cx, &sig, generics, FunctionArgs::Idents(idents)), + clean_function(cx, &sig, generics, ParamsSrc::Idents(idents)), sig.header.safety(), ), hir::ForeignItemKind::Static(ty, mutability, safety) => ForeignStaticItem( diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index f58cdfc6b5ee..cceafcbbb228 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1407,32 +1407,28 @@ pub(crate) struct Function { #[derive(Clone, PartialEq, Eq, Debug, Hash)] pub(crate) struct FnDecl { - pub(crate) inputs: Arguments, + pub(crate) inputs: Vec, pub(crate) output: Type, pub(crate) c_variadic: bool, } impl FnDecl { pub(crate) fn receiver_type(&self) -> Option<&Type> { - self.inputs.values.first().and_then(|v| v.to_receiver()) + self.inputs.first().and_then(|v| v.to_receiver()) } } +/// A function parameter. #[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub(crate) struct Arguments { - pub(crate) values: Vec, -} - -#[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub(crate) struct Argument { - pub(crate) type_: Type, +pub(crate) struct Parameter { pub(crate) name: Option, + pub(crate) type_: Type, /// This field is used to represent "const" arguments from the `rustc_legacy_const_generics` /// feature. More information in . pub(crate) is_const: bool, } -impl Argument { +impl Parameter { pub(crate) fn to_receiver(&self) -> Option<&Type> { if self.name == Some(kw::SelfLower) { Some(&self.type_) } else { None } } diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 9ac328f7495d..299fd6b9adbb 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -1186,8 +1186,8 @@ impl clean::Impl { { primitive_link(f, PrimitiveType::Array, format_args!("[{name}; N]"), cx)?; } else if let clean::BareFunction(bare_fn) = &type_ - && let [clean::Argument { type_: clean::Type::Generic(name), .. }] = - &bare_fn.decl.inputs.values[..] + && let [clean::Parameter { type_: clean::Type::Generic(name), .. }] = + &bare_fn.decl.inputs[..] && (self.kind.is_fake_variadic() || self.kind.is_auto()) { // Hardcoded anchor library/core/src/primitive_docs.rs @@ -1234,22 +1234,20 @@ impl clean::Impl { } } -impl clean::Arguments { - pub(crate) fn print(&self, cx: &Context<'_>) -> impl Display { - fmt::from_fn(move |f| { - self.values - .iter() - .map(|input| { - fmt::from_fn(|f| { - if let Some(name) = input.name { - write!(f, "{}: ", name)?; - } - input.type_.print(cx).fmt(f) - }) +pub(crate) fn print_params(params: &[clean::Parameter], cx: &Context<'_>) -> impl Display { + fmt::from_fn(move |f| { + params + .iter() + .map(|param| { + fmt::from_fn(|f| { + if let Some(name) = param.name { + write!(f, "{}: ", name)?; + } + param.type_.print(cx).fmt(f) }) - .joined(", ", f) - }) - } + }) + .joined(", ", f) + }) } // Implements Write but only counts the bytes "written". @@ -1281,16 +1279,16 @@ impl clean::FnDecl { if f.alternate() { write!( f, - "({args:#}{ellipsis}){arrow:#}", - args = self.inputs.print(cx), + "({params:#}{ellipsis}){arrow:#}", + params = print_params(&self.inputs, cx), ellipsis = ellipsis, arrow = self.print_output(cx) ) } else { write!( f, - "({args}{ellipsis}){arrow}", - args = self.inputs.print(cx), + "({params}{ellipsis}){arrow}", + params = print_params(&self.inputs, cx), ellipsis = ellipsis, arrow = self.print_output(cx) ) @@ -1336,14 +1334,14 @@ impl clean::FnDecl { write!(f, "(")?; if let Some(n) = line_wrapping_indent - && !self.inputs.values.is_empty() + && !self.inputs.is_empty() { write!(f, "\n{}", Indent(n + 4))?; } - let last_input_index = self.inputs.values.len().checked_sub(1); - for (i, input) in self.inputs.values.iter().enumerate() { - if let Some(selfty) = input.to_receiver() { + let last_input_index = self.inputs.len().checked_sub(1); + for (i, param) in self.inputs.iter().enumerate() { + if let Some(selfty) = param.to_receiver() { match selfty { clean::SelfTy => { write!(f, "self")?; @@ -1361,13 +1359,13 @@ impl clean::FnDecl { } } } else { - if input.is_const { + if param.is_const { write!(f, "const ")?; } - if let Some(name) = input.name { + if let Some(name) = param.name { write!(f, "{}: ", name)?; } - input.type_.print(cx).fmt(f)?; + param.type_.print(cx).fmt(f)?; } match (line_wrapping_indent, last_input_index) { (_, None) => (), diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index 1360ab94cb1c..aff8684ee3a0 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -1112,7 +1112,7 @@ fn simplify_fn_type<'a, 'tcx>( } Type::BareFunction(ref bf) => { let mut ty_generics = Vec::new(); - for ty in bf.decl.inputs.values.iter().map(|arg| &arg.type_) { + for ty in bf.decl.inputs.iter().map(|arg| &arg.type_) { simplify_fn_type( self_, generics, @@ -1418,15 +1418,15 @@ fn get_fn_inputs_and_outputs( (None, &func.generics) }; - let mut arg_types = Vec::new(); - for arg in decl.inputs.values.iter() { + let mut param_types = Vec::new(); + for param in decl.inputs.iter() { simplify_fn_type( self_, generics, - &arg.type_, + ¶m.type_, tcx, 0, - &mut arg_types, + &mut param_types, &mut rgen, false, cache, @@ -1439,7 +1439,7 @@ fn get_fn_inputs_and_outputs( let mut simplified_params = rgen.into_iter().collect::>(); simplified_params.sort_by_key(|(_, (idx, _))| -idx); ( - arg_types, + param_types, ret_types, simplified_params .iter() diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 5d85a4676b7e..dab23f8e42a3 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -609,11 +609,12 @@ impl FromClean for FunctionSignature { let clean::FnDecl { inputs, output, c_variadic } = decl; FunctionSignature { inputs: inputs - .values .into_iter() - // `_` is the most sensible name for missing param names. - .map(|arg| { - (arg.name.unwrap_or(kw::Underscore).to_string(), arg.type_.into_json(renderer)) + .map(|param| { + // `_` is the most sensible name for missing param names. + let name = param.name.unwrap_or(kw::Underscore).to_string(); + let type_ = param.type_.into_json(renderer); + (name, type_) }) .collect(), output: if output.is_unit() { None } else { Some(output.into_json(renderer)) }, From 82ff0a0e6a4be3aab167446ef1529018aa3f1fd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Wed, 16 Apr 2025 12:56:49 +0200 Subject: [PATCH 564/606] rustdoc: Properly clean fn params in all contexts --- src/librustdoc/clean/mod.rs | 58 +++++++++---------- src/librustdoc/clean/utils.rs | 9 ++- tests/rustdoc/anon-fn-params.rs | 25 ++++++++ tests/rustdoc/assoc-fns.rs | 13 +++++ tests/rustdoc/auxiliary/ext-anon-fn-params.rs | 7 +++ tests/rustdoc/ffi.rs | 4 ++ .../auxiliary/{fn-type.rs => fn-ptr-ty.rs} | 0 .../inline_cross/default-generic-args.rs | 8 +-- .../inline_cross/{fn-type.rs => fn-ptr-ty.rs} | 6 +- tests/rustdoc/inline_cross/impl_trait.rs | 2 +- 10 files changed, 89 insertions(+), 43 deletions(-) create mode 100644 tests/rustdoc/anon-fn-params.rs create mode 100644 tests/rustdoc/assoc-fns.rs create mode 100644 tests/rustdoc/auxiliary/ext-anon-fn-params.rs rename tests/rustdoc/inline_cross/auxiliary/{fn-type.rs => fn-ptr-ty.rs} (100%) rename tests/rustdoc/inline_cross/{fn-type.rs => fn-ptr-ty.rs} (71%) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 249a822076ec..034ecb2f6c1a 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1103,7 +1103,10 @@ fn clean_function<'tcx>( let generics = clean_generics(generics, cx); let params = match params { ParamsSrc::Body(body_id) => clean_params_via_body(cx, sig.decl.inputs, body_id), - ParamsSrc::Idents(idents) => clean_params(cx, sig.decl.inputs, idents), + // Let's not perpetuate anon params from Rust 2015; use `_` for them. + ParamsSrc::Idents(idents) => clean_params(cx, sig.decl.inputs, idents, |ident| { + Some(ident.map_or(kw::Underscore, |ident| ident.name)) + }), }; let decl = clean_fn_decl_with_params(cx, sig.decl, Some(&sig.header), params); (generics, decl) @@ -1115,30 +1118,13 @@ fn clean_params<'tcx>( cx: &mut DocContext<'tcx>, types: &[hir::Ty<'tcx>], idents: &[Option], + postprocess: impl Fn(Option) -> Option, ) -> Vec { - fn nonempty_name(ident: &Option) -> Option { - if let Some(ident) = ident - && ident.name != kw::Underscore - { - Some(ident.name) - } else { - None - } - } - - // If at least one argument has a name, use `_` as the name of unnamed - // arguments. Otherwise omit argument names. - let default_name = if idents.iter().any(|ident| nonempty_name(ident).is_some()) { - Some(kw::Underscore) - } else { - None - }; - types .iter() .enumerate() .map(|(i, ty)| Parameter { - name: idents.get(i).and_then(nonempty_name).or(default_name), + name: postprocess(idents[i]), type_: clean_ty(ty, cx), is_const: false, }) @@ -1184,8 +1170,6 @@ fn clean_poly_fn_sig<'tcx>( did: Option, sig: ty::PolyFnSig<'tcx>, ) -> FnDecl { - let mut names = did.map_or(&[] as &[_], |did| cx.tcx.fn_arg_idents(did)).iter(); - let mut output = clean_middle_ty(sig.output(), cx, None, None); // If the return type isn't an `impl Trait`, we can safely assume that this @@ -1198,16 +1182,20 @@ fn clean_poly_fn_sig<'tcx>( output = output.sugared_async_return_type(); } + let mut idents = did.map(|did| cx.tcx.fn_arg_idents(did)).unwrap_or_default().iter().copied(); + + // If this comes from a fn item, let's not perpetuate anon params from Rust 2015; use `_` for them. + // If this comes from a fn ptr ty, we just keep params unnamed since it's more conventional stylistically. + // Since the param name is not part of the semantic type, these params never bear a name unlike + // in the HIR case, thus we can't peform any fancy fallback logic unlike `clean_bare_fn_ty`. + let fallback = did.map(|_| kw::Underscore); + let params = sig .inputs() .iter() - .map(|t| Parameter { - type_: clean_middle_ty(t.map_bound(|t| *t), cx, None, None), - name: Some(if let Some(Some(ident)) = names.next() { - ident.name - } else { - kw::Underscore - }), + .map(|ty| Parameter { + name: idents.next().flatten().map(|ident| ident.name).or(fallback), + type_: clean_middle_ty(ty.map_bound(|ty| *ty), cx, None, None), is_const: false, }) .collect(); @@ -2597,7 +2585,17 @@ fn clean_bare_fn_ty<'tcx>( .filter(|p| !is_elided_lifetime(p)) .map(|x| clean_generic_param(cx, None, x)) .collect(); - let params = clean_params(cx, bare_fn.decl.inputs, bare_fn.param_idents); + // Since it's more conventional stylistically, elide the name of all params called `_` + // unless there's at least one interestingly named param in which case don't elide any + // name since mixing named and unnamed params is less legible. + let filter = |ident: Option| { + ident.map(|ident| ident.name).filter(|&ident| ident != kw::Underscore) + }; + let fallback = + bare_fn.param_idents.iter().copied().find_map(filter).map(|_| kw::Underscore); + let params = clean_params(cx, bare_fn.decl.inputs, bare_fn.param_idents, |ident| { + filter(ident).or(fallback) + }); let decl = clean_fn_decl_with_params(cx, bare_fn.decl, None, params); (generic_params, decl) }); diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 8ee08edec199..af7986d030ee 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -303,13 +303,12 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol { debug!("trying to get a name from pattern: {p:?}"); Symbol::intern(&match &p.kind { - // FIXME(never_patterns): does this make sense? - PatKind::Missing => unreachable!(), - PatKind::Wild - | PatKind::Err(_) + PatKind::Err(_) + | PatKind::Missing // Let's not perpetuate anon params from Rust 2015; use `_` for them. | PatKind::Never + | PatKind::Range(..) | PatKind::Struct(..) - | PatKind::Range(..) => { + | PatKind::Wild => { return kw::Underscore; } PatKind::Binding(_, _, ident, _) => return ident.name, diff --git a/tests/rustdoc/anon-fn-params.rs b/tests/rustdoc/anon-fn-params.rs new file mode 100644 index 000000000000..9af1af3d3fa3 --- /dev/null +++ b/tests/rustdoc/anon-fn-params.rs @@ -0,0 +1,25 @@ +// Test that we render the deprecated anonymous trait function parameters from Rust 2015 as +// underscores in order not to perpetuate it and for legibility. + +//@ edition: 2015 +#![expect(anonymous_parameters)] + +// Check the "local case" (HIR cleaning) // + +//@ has anon_fn_params/trait.Trait.html +pub trait Trait { + //@ has - '//*[@id="tymethod.required"]' 'fn required(_: Option, _: impl Fn(&str) -> bool)' + fn required(Option, impl Fn(&str) -> bool); + //@ has - '//*[@id="method.provided"]' 'fn provided(_: [i32; 2])' + fn provided([i32; 2]) {} +} + +// Check the "extern case" (middle cleaning) // + +//@ aux-build: ext-anon-fn-params.rs +extern crate ext_anon_fn_params; + +//@ has anon_fn_params/trait.ExtTrait.html +//@ has - '//*[@id="tymethod.required"]' 'fn required(_: Option, _: impl Fn(&str) -> bool)' +//@ has - '//*[@id="method.provided"]' 'fn provided(_: [i32; 2])' +pub use ext_anon_fn_params::Trait as ExtTrait; diff --git a/tests/rustdoc/assoc-fns.rs b/tests/rustdoc/assoc-fns.rs new file mode 100644 index 000000000000..6ffbebc3d27e --- /dev/null +++ b/tests/rustdoc/assoc-fns.rs @@ -0,0 +1,13 @@ +// Basic testing for associated functions (in traits, trait impls & inherent impls). + +//@ has assoc_fns/trait.Trait.html +pub trait Trait { + //@ has - '//*[@id="tymethod.required"]' 'fn required(first: i32, second: &str)' + fn required(first: i32, second: &str); + + //@ has - '//*[@id="method.provided"]' 'fn provided(only: ())' + fn provided(only: ()) {} + + //@ has - '//*[@id="tymethod.params_are_unnamed"]' 'fn params_are_unnamed(_: i32, _: u32)' + fn params_are_unnamed(_: i32, _: u32); +} diff --git a/tests/rustdoc/auxiliary/ext-anon-fn-params.rs b/tests/rustdoc/auxiliary/ext-anon-fn-params.rs new file mode 100644 index 000000000000..1acb919ca64f --- /dev/null +++ b/tests/rustdoc/auxiliary/ext-anon-fn-params.rs @@ -0,0 +1,7 @@ +//@ edition: 2015 +#![expect(anonymous_parameters)] + +pub trait Trait { + fn required(Option, impl Fn(&str) -> bool); + fn provided([i32; 2]) {} +} diff --git a/tests/rustdoc/ffi.rs b/tests/rustdoc/ffi.rs index 5ba7cdba9109..524fb0edefb6 100644 --- a/tests/rustdoc/ffi.rs +++ b/tests/rustdoc/ffi.rs @@ -9,4 +9,8 @@ pub use lib::foreigner; extern "C" { //@ has ffi/fn.another.html //pre 'pub unsafe extern "C" fn another(cold_as_ice: u32)' pub fn another(cold_as_ice: u32); + + //@ has ffi/fn.params_are_unnamed.html //pre \ + // 'pub unsafe extern "C" fn params_are_unnamed(_: i32, _: u32)' + pub fn params_are_unnamed(_: i32, _: u32); } diff --git a/tests/rustdoc/inline_cross/auxiliary/fn-type.rs b/tests/rustdoc/inline_cross/auxiliary/fn-ptr-ty.rs similarity index 100% rename from tests/rustdoc/inline_cross/auxiliary/fn-type.rs rename to tests/rustdoc/inline_cross/auxiliary/fn-ptr-ty.rs diff --git a/tests/rustdoc/inline_cross/default-generic-args.rs b/tests/rustdoc/inline_cross/default-generic-args.rs index 0469221b3d85..5124fbdf8dae 100644 --- a/tests/rustdoc/inline_cross/default-generic-args.rs +++ b/tests/rustdoc/inline_cross/default-generic-args.rs @@ -53,17 +53,17 @@ pub use default_generic_args::R2; //@ has user/type.H0.html // Check that we handle higher-ranked regions correctly: -//@ has - '//*[@class="rust item-decl"]//code' "fn(_: for<'a> fn(_: Re<'a>))" +//@ has - '//*[@class="rust item-decl"]//code' "fn(for<'a> fn(Re<'a>))" pub use default_generic_args::H0; //@ has user/type.H1.html // Check that we don't conflate distinct universially quantified regions (#1): -//@ has - '//*[@class="rust item-decl"]//code' "for<'b> fn(_: for<'a> fn(_: Re<'a, &'b ()>))" +//@ has - '//*[@class="rust item-decl"]//code' "for<'b> fn(for<'a> fn(Re<'a, &'b ()>))" pub use default_generic_args::H1; //@ has user/type.H2.html // Check that we don't conflate distinct universially quantified regions (#2): -//@ has - '//*[@class="rust item-decl"]//code' "for<'a> fn(_: for<'b> fn(_: Re<'a, &'b ()>))" +//@ has - '//*[@class="rust item-decl"]//code' "for<'a> fn(for<'b> fn(Re<'a, &'b ()>))" pub use default_generic_args::H2; //@ has user/type.P0.html @@ -86,7 +86,7 @@ pub use default_generic_args::A0; // Demonstrates that we currently don't elide generic arguments that are alpha-equivalent to their // respective generic parameter (after instantiation) for perf reasons (it would require us to // create an inference context). -//@ has - '//*[@class="rust item-decl"]//code' "Alpha fn(_: &'arbitrary ())>" +//@ has - '//*[@class="rust item-decl"]//code' "Alpha fn(&'arbitrary ())>" pub use default_generic_args::A1; //@ has user/type.M0.html diff --git a/tests/rustdoc/inline_cross/fn-type.rs b/tests/rustdoc/inline_cross/fn-ptr-ty.rs similarity index 71% rename from tests/rustdoc/inline_cross/fn-type.rs rename to tests/rustdoc/inline_cross/fn-ptr-ty.rs index 8db6f65f421f..010596225217 100644 --- a/tests/rustdoc/inline_cross/fn-type.rs +++ b/tests/rustdoc/inline_cross/fn-ptr-ty.rs @@ -2,11 +2,11 @@ // They should be rendered exactly as the user wrote it, i.e., in source order and with unused // parameters present, not stripped. -//@ aux-crate:fn_type=fn-type.rs +//@ aux-crate:fn_ptr_ty=fn-ptr-ty.rs //@ edition: 2021 #![crate_name = "user"] //@ has user/type.F.html //@ has - '//*[@class="rust item-decl"]//code' \ -// "for<'z, 'a, '_unused> fn(_: &'z for<'b> fn(_: &'b str), _: &'a ()) -> &'a ();" -pub use fn_type::F; +// "for<'z, 'a, '_unused> fn(&'z for<'b> fn(&'b str), &'a ()) -> &'a ();" +pub use fn_ptr_ty::F; diff --git a/tests/rustdoc/inline_cross/impl_trait.rs b/tests/rustdoc/inline_cross/impl_trait.rs index e6baf33660ac..468ac0830619 100644 --- a/tests/rustdoc/inline_cross/impl_trait.rs +++ b/tests/rustdoc/inline_cross/impl_trait.rs @@ -29,7 +29,7 @@ pub use impl_trait_aux::func4; //@ has impl_trait/fn.func5.html //@ has - '//pre[@class="rust item-decl"]' "func5(" //@ has - '//pre[@class="rust item-decl"]' "_f: impl for<'any> Fn(&'any str, &'any str) -> bool + for<'r> Other = ()>," -//@ has - '//pre[@class="rust item-decl"]' "_a: impl for<'beta, 'alpha, '_gamma> Auxiliary<'alpha, Item<'beta> = fn(_: &'beta ())>" +//@ has - '//pre[@class="rust item-decl"]' "_a: impl for<'beta, 'alpha, '_gamma> Auxiliary<'alpha, Item<'beta> = fn(&'beta ())>" //@ !has - '//pre[@class="rust item-decl"]' 'where' pub use impl_trait_aux::func5; From bf2696311be53bed4fe976bb25bed81f0d7477ce Mon Sep 17 00:00:00 2001 From: Maksim Bondarenkov Date: Thu, 17 Apr 2025 12:53:17 +0300 Subject: [PATCH 565/606] bootstrap: enable zlib for LLVM when we compile it for profiling when compiling target LLVM with `opt-dist local` on Windows/MinGW, profraw files are being compressed with zlib, so compiling without it will make `llvm-profdata` complain about lacking of zlib support. this error is shown: `profile uses zlib compression but the profile reader was built without zlib support` example from llvm test suite: https://github.com/llvm/llvm-project/blob/76b5fcbf975547251faaeed8b567ea09d139a607/llvm/test/tools/llvm-profdata/nocompress.test#L15 --- src/bootstrap/download-ci-llvm-stamp | 2 +- src/bootstrap/src/core/build_steps/llvm.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/download-ci-llvm-stamp b/src/bootstrap/download-ci-llvm-stamp index e157ff233bbf..b70d452b427c 100644 --- a/src/bootstrap/download-ci-llvm-stamp +++ b/src/bootstrap/download-ci-llvm-stamp @@ -1,4 +1,4 @@ Change this file to make users of the `download-ci-llvm` configuration download a new version of LLVM from CI, even if the LLVM submodule hasn’t changed. -Last change is for: https://github.com/rust-lang/rust/pull/138784 +Last change is for: https://github.com/rust-lang/rust/pull/139931 diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index 69a8bd59f16c..6e84b83d17dc 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -370,8 +370,8 @@ impl Step for Llvm { cfg.define("LLVM_PROFDATA_FILE", path); } - // Libraries for ELF section compression. - if !target.is_windows() { + // Libraries for ELF section compression and profraw files merging. + if !target.is_msvc() { cfg.define("LLVM_ENABLE_ZLIB", "ON"); } else { cfg.define("LLVM_ENABLE_ZLIB", "OFF"); From 62a104d99e801f80c3740902ccc344dcf909f71d Mon Sep 17 00:00:00 2001 From: Maksim Bondarenkov Date: Thu, 17 Apr 2025 13:01:22 +0300 Subject: [PATCH 566/606] opt-dist: add a flag for running tests when using `opt-dist local` user probably won't need to run tests (for various reasons). currently the only way to disable them is to set `TRY_DIST_BUILD=1`, which is not obvious and can be bad for non-CI envronments (as I guess) --- src/tools/opt-dist/src/environment.rs | 5 +++++ src/tools/opt-dist/src/main.rs | 10 +++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/tools/opt-dist/src/environment.rs b/src/tools/opt-dist/src/environment.rs index 90d0ca717b25..9342d164be41 100644 --- a/src/tools/opt-dist/src/environment.rs +++ b/src/tools/opt-dist/src/environment.rs @@ -25,6 +25,7 @@ pub struct Environment { prebuilt_rustc_perf: Option, use_bolt: bool, shared_llvm: bool, + run_tests: bool, } impl Environment { @@ -101,6 +102,10 @@ impl Environment { pub fn benchmark_cargo_config(&self) -> &[String] { &self.benchmark_cargo_config } + + pub fn run_tests(&self) -> bool { + self.run_tests + } } /// What is the extension of binary executables on this platform? diff --git a/src/tools/opt-dist/src/main.rs b/src/tools/opt-dist/src/main.rs index ac5d294f07ed..4cc6a9a41f08 100644 --- a/src/tools/opt-dist/src/main.rs +++ b/src/tools/opt-dist/src/main.rs @@ -94,6 +94,10 @@ enum EnvironmentCmd { /// Arguments passed to `rustc-perf --cargo-config ` when running benchmarks. #[arg(long)] benchmark_cargo_config: Vec, + + /// Perform tests after final build if it's not a try build + #[arg(long)] + run_tests: bool, }, /// Perform an optimized build on Linux CI, from inside Docker. LinuxCi { @@ -125,6 +129,7 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec)> skipped_tests, benchmark_cargo_config, shared, + run_tests, } => { let env = EnvironmentBuilder::default() .host_tuple(target_triple) @@ -138,6 +143,7 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec)> .use_bolt(use_bolt) .skipped_tests(skipped_tests) .benchmark_cargo_config(benchmark_cargo_config) + .run_tests(run_tests) .build()?; (env, shared.build_args) @@ -160,6 +166,7 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec)> // FIXME: Enable bolt for aarch64 once it's fixed upstream. Broken as of December 2024. .use_bolt(!is_aarch64) .skipped_tests(vec![]) + .run_tests(true) .build()?; (env, shared.build_args) @@ -179,6 +186,7 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec)> .shared_llvm(false) .use_bolt(false) .skipped_tests(vec![]) + .run_tests(true) .build()?; (env, shared.build_args) @@ -344,7 +352,7 @@ fn execute_pipeline( // possible regressions. // The tests are not executed for try builds, which can be in various broken states, so we don't // want to gatekeep them with tests. - if !is_try_build() { + if !is_try_build() && env.run_tests() { timer.section("Run tests", |_| run_tests(env))?; } From 289a23e0e2691e2c4f14427d8495c1c78f3f0d7b Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 16 Apr 2025 10:45:59 +0200 Subject: [PATCH 567/606] do not emit `OpaqueCast` projections with `-Znext-solver` --- .../rustc_hir_typeck/src/expr_use_visitor.rs | 25 ++++++++++------- compiler/rustc_middle/src/hir/place.rs | 2 ++ compiler/rustc_middle/src/mir/syntax.rs | 2 ++ .../src/builder/matches/match_pair.rs | 25 +++++++++-------- .../src/post_analysis_normalize.rs | 28 ++++++++++--------- 5 files changed, 48 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 27df8f0e98a1..0511f4e25ad3 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -1502,16 +1502,21 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx let mut projections = base_place.place.projections; let node_ty = self.cx.typeck_results().node_type(node); - // Opaque types can't have field projections, but we can instead convert - // the current place in-place (heh) to the hidden type, and then apply all - // follow up projections on that. - if node_ty != place_ty - && self - .cx - .try_structurally_resolve_type(self.cx.tcx().hir_span(base_place.hir_id), place_ty) - .is_impl_trait() - { - projections.push(Projection { kind: ProjectionKind::OpaqueCast, ty: node_ty }); + if !self.cx.tcx().next_trait_solver_globally() { + // Opaque types can't have field projections, but we can instead convert + // the current place in-place (heh) to the hidden type, and then apply all + // follow up projections on that. + if node_ty != place_ty + && self + .cx + .try_structurally_resolve_type( + self.cx.tcx().hir_span(base_place.hir_id), + place_ty, + ) + .is_impl_trait() + { + projections.push(Projection { kind: ProjectionKind::OpaqueCast, ty: node_ty }); + } } projections.push(Projection { kind, ty }); PlaceWithHirId::new(node, base_place.place.base_ty, base_place.place.base, projections) diff --git a/compiler/rustc_middle/src/hir/place.rs b/compiler/rustc_middle/src/hir/place.rs index 60ce8544aa0e..c3d10615cf10 100644 --- a/compiler/rustc_middle/src/hir/place.rs +++ b/compiler/rustc_middle/src/hir/place.rs @@ -40,6 +40,8 @@ pub enum ProjectionKind { /// A conversion from an opaque type to its hidden type so we can /// do further projections on it. + /// + /// This is unused if `-Znext-solver` is enabled. OpaqueCast, } diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index c7561f8afef9..304b3caa6e19 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1242,6 +1242,8 @@ pub enum ProjectionElem { /// Like an explicit cast from an opaque type to a concrete type, but without /// requiring an intermediate variable. + /// + /// This is unused with `-Znext-solver`. OpaqueCast(T), /// A transmute from an unsafe binder to the type that it wraps. This is a projection diff --git a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs index 9670c1716f58..d66b38c5b005 100644 --- a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs +++ b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs @@ -101,18 +101,21 @@ impl<'tcx> MatchPairTree<'tcx> { place_builder = resolved; } - // Only add the OpaqueCast projection if the given place is an opaque type and the - // expected type from the pattern is not. - let may_need_cast = match place_builder.base() { - PlaceBase::Local(local) => { - let ty = - Place::ty_from(local, place_builder.projection(), &cx.local_decls, cx.tcx).ty; - ty != pattern.ty && ty.has_opaque_types() + if !cx.tcx.next_trait_solver_globally() { + // Only add the OpaqueCast projection if the given place is an opaque type and the + // expected type from the pattern is not. + let may_need_cast = match place_builder.base() { + PlaceBase::Local(local) => { + let ty = + Place::ty_from(local, place_builder.projection(), &cx.local_decls, cx.tcx) + .ty; + ty != pattern.ty && ty.has_opaque_types() + } + _ => true, + }; + if may_need_cast { + place_builder = place_builder.project(ProjectionElem::OpaqueCast(pattern.ty)); } - _ => true, - }; - if may_need_cast { - place_builder = place_builder.project(ProjectionElem::OpaqueCast(pattern.ty)); } let place = place_builder.try_to_place(cx); diff --git a/compiler/rustc_mir_transform/src/post_analysis_normalize.rs b/compiler/rustc_mir_transform/src/post_analysis_normalize.rs index 76c2f082c0bf..5599dee4ccad 100644 --- a/compiler/rustc_mir_transform/src/post_analysis_normalize.rs +++ b/compiler/rustc_mir_transform/src/post_analysis_normalize.rs @@ -39,20 +39,22 @@ impl<'tcx> MutVisitor<'tcx> for PostAnalysisNormalizeVisitor<'tcx> { _context: PlaceContext, _location: Location, ) { - // Performance optimization: don't reintern if there is no `OpaqueCast` to remove. - if place.projection.iter().all(|elem| !matches!(elem, ProjectionElem::OpaqueCast(_))) { - return; + if !self.tcx.next_trait_solver_globally() { + // `OpaqueCast` projections are only needed if there are opaque types on which projections + // are performed. After the `PostAnalysisNormalize` pass, all opaque types are replaced with their + // hidden types, so we don't need these projections anymore. + // + // Performance optimization: don't reintern if there is no `OpaqueCast` to remove. + if place.projection.iter().any(|elem| matches!(elem, ProjectionElem::OpaqueCast(_))) { + place.projection = self.tcx.mk_place_elems( + &place + .projection + .into_iter() + .filter(|elem| !matches!(elem, ProjectionElem::OpaqueCast(_))) + .collect::>(), + ); + }; } - // `OpaqueCast` projections are only needed if there are opaque types on which projections - // are performed. After the `PostAnalysisNormalize` pass, all opaque types are replaced with their - // hidden types, so we don't need these projections anymore. - place.projection = self.tcx.mk_place_elems( - &place - .projection - .into_iter() - .filter(|elem| !matches!(elem, ProjectionElem::OpaqueCast(_))) - .collect::>(), - ); self.super_place(place, _context, _location); } From c85b5fcd07907a82f158df31a4f36fea608dab42 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 17 Apr 2025 12:36:27 +0200 Subject: [PATCH 568/606] check OpaqueCast tests with next-solver --- .../cross_inference_pattern_bug_no_type.rs | 1 - tests/ui/type-alias-impl-trait/destructure_tait-ice-113594.rs | 2 ++ tests/ui/type-alias-impl-trait/tait-normalize.rs | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs b/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs index 736a9dfb4903..be8b7fa6a935 100644 --- a/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs +++ b/tests/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs @@ -1,6 +1,5 @@ //@ compile-flags: --crate-type=lib //@ edition: 2021 -//@ rustc-env:RUST_BACKTRACE=0 //@ check-pass // tracked in https://github.com/rust-lang/rust/issues/96572 diff --git a/tests/ui/type-alias-impl-trait/destructure_tait-ice-113594.rs b/tests/ui/type-alias-impl-trait/destructure_tait-ice-113594.rs index a3b1aba70411..a42ea083d740 100644 --- a/tests/ui/type-alias-impl-trait/destructure_tait-ice-113594.rs +++ b/tests/ui/type-alias-impl-trait/destructure_tait-ice-113594.rs @@ -1,3 +1,5 @@ +//@ revisions: current next +//@ [next] compile-flags: -Znext-solver //@ build-pass //@ edition: 2021 diff --git a/tests/ui/type-alias-impl-trait/tait-normalize.rs b/tests/ui/type-alias-impl-trait/tait-normalize.rs index 38e09b6087b6..a34d167bcc39 100644 --- a/tests/ui/type-alias-impl-trait/tait-normalize.rs +++ b/tests/ui/type-alias-impl-trait/tait-normalize.rs @@ -1,3 +1,5 @@ +//@ revisions: current next +//@ [next] compile-flags: -Znext-solver //@ check-pass #![feature(type_alias_impl_trait)] From d20f84847886389e25c0669dc48a8890491793df Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Thu, 17 Apr 2025 16:54:07 +0800 Subject: [PATCH 569/606] compiletest: add specific `//@ ignore-auxiliary` for test support files This is for files that *participate* in actual tests but should not be built by `compiletest` (i.e. these files are involved through `mod xxx;` or `include!()` or `#[path = "xxx"]`, etc.). A specialized directive like `//@ ignore-auxiliary` makes it way easier to audit disabled tests via `//@ ignore-test`. --- src/tools/compiletest/src/directive-list.rs | 1 + src/tools/compiletest/src/header/cfg.rs | 4 ++++ src/tools/compiletest/src/header/tests.rs | 6 ++++++ 3 files changed, 11 insertions(+) diff --git a/src/tools/compiletest/src/directive-list.rs b/src/tools/compiletest/src/directive-list.rs index 086a8a67456f..44c52c8c7663 100644 --- a/src/tools/compiletest/src/directive-list.rs +++ b/src/tools/compiletest/src/directive-list.rs @@ -44,6 +44,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "ignore-arm-unknown-linux-gnueabihf", "ignore-arm-unknown-linux-musleabi", "ignore-arm-unknown-linux-musleabihf", + "ignore-auxiliary", "ignore-avr", "ignore-beta", "ignore-cdb", diff --git a/src/tools/compiletest/src/header/cfg.rs b/src/tools/compiletest/src/header/cfg.rs index c369fff97f4f..f1f1384afb97 100644 --- a/src/tools/compiletest/src/header/cfg.rs +++ b/src/tools/compiletest/src/header/cfg.rs @@ -100,6 +100,10 @@ fn parse_cfg_name_directive<'a>( name: "test", message: "always" } + condition! { + name: "auxiliary", + message: "used by another main test file" + } condition! { name: &config.target, allowed_names: &target_cfgs.all_targets, diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 3a8c3748de99..2525e0adc838 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -940,3 +940,9 @@ fn test_supported_crate_types() { "//@ needs-crate-type: bin, cdylib, dylib, lib, proc-macro, rlib, staticlib" )); } + +#[test] +fn test_ignore_auxiliary() { + let config = cfg().build(); + assert!(check_ignore(&config, "//@ ignore-auxiliary")); +} From d1178faa9394579a1befd2cbf9e4ecc7aeb7432b Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Thu, 17 Apr 2025 17:01:14 +0800 Subject: [PATCH 570/606] tests: refine disable reason for `tests/debuginfo/drop-locations.rs` --- tests/debuginfo/drop-locations.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/debuginfo/drop-locations.rs b/tests/debuginfo/drop-locations.rs index a55cf7b50a81..91b3da5c34a8 100644 --- a/tests/debuginfo/drop-locations.rs +++ b/tests/debuginfo/drop-locations.rs @@ -1,5 +1,7 @@ //@ ignore-android -//@ ignore-test: #128971 + +// FIXME: stepping with "next" in a debugger skips past end-of-scope drops +//@ ignore-test (broken, see #128971) #![allow(unused)] From 6bbee334fd77aed1c5267b97fea0c8e458f84e22 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Thu, 17 Apr 2025 17:04:30 +0800 Subject: [PATCH 571/606] rustc-dev-guide: document `//@ ignore-auxiliary` --- src/doc/rustc-dev-guide/src/tests/best-practices.md | 2 ++ src/doc/rustc-dev-guide/src/tests/directives.md | 3 +++ 2 files changed, 5 insertions(+) diff --git a/src/doc/rustc-dev-guide/src/tests/best-practices.md b/src/doc/rustc-dev-guide/src/tests/best-practices.md index 6905ee13283a..2bdc7f3a2431 100644 --- a/src/doc/rustc-dev-guide/src/tests/best-practices.md +++ b/src/doc/rustc-dev-guide/src/tests/best-practices.md @@ -175,6 +175,8 @@ See [compiletest directives] for a listing of directives. - For `ignore-*`/`needs-*`/`only-*` directives, unless extremely obvious, provide a brief remark on why the directive is needed. E.g. `"//@ ignore-wasi (wasi codegens the main symbol differently)"`. +- When using `//@ ignore-auxiliary`, specify the corresponding main test files, + e.g. ``//@ ignore-auxiliary (used by `./foo.rs`)``. ## FileCheck best practices diff --git a/src/doc/rustc-dev-guide/src/tests/directives.md b/src/doc/rustc-dev-guide/src/tests/directives.md index 0aad8be982ff..dae659e6317b 100644 --- a/src/doc/rustc-dev-guide/src/tests/directives.md +++ b/src/doc/rustc-dev-guide/src/tests/directives.md @@ -124,6 +124,9 @@ means the test won't be compiled or run. * `ignore-X` where `X` is a target detail or other criteria on which to ignore the test (see below) * `only-X` is like `ignore-X`, but will *only* run the test on that target or stage +* `ignore-auxiliary` is intended for files that *participate* in one or more other + main test files but that `compiletest` should not try to build the file itself. + Please backlink to which main test is actually using the auxiliary file. * `ignore-test` always ignores the test. This can be used to temporarily disable a test if it is currently not working, but you want to keep it in tree to re-enable it later. From 35a4140723c7424da012b9eca5e38cd8325ccb12 Mon Sep 17 00:00:00 2001 From: petr sumbera - Sun Microsystems - Prague Czech Republic Date: Thu, 17 Apr 2025 13:39:46 +0200 Subject: [PATCH 572/606] update libc --- Cargo.lock | 4 ++-- src/tools/rust-analyzer/Cargo.lock | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3d0e29421791..a2f8511e170e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2022,9 +2022,9 @@ checksum = "9fa0e2a1fcbe2f6be6c42e342259976206b383122fc152e872795338b5a3f3a7" [[package]] name = "libc" -version = "0.2.171" +version = "0.2.172" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" +checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" [[package]] name = "libdbus-sys" diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index 745a8097c8a5..2dbb3f5d69ca 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -902,9 +902,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.169" +version = "0.2.172" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" +checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" [[package]] name = "libloading" From 89cac55bb85e91ad4d90f9e0bcf0c0e065b88a7d Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Thu, 17 Apr 2025 17:22:56 +0800 Subject: [PATCH 573/606] tests: use `//@ ignore-auxiliary` with backlinked primary test file --- tests/codegen/remap_path_prefix/aux_mod.rs | 2 +- tests/ui/borrowck/move-error-snippets-ext.rs | 2 +- tests/ui/codemap_tests/two_files_data.rs | 2 +- tests/ui/conditional-compilation/module_with_cfg.rs | 2 +- tests/ui/cross/cross-file-errors/underscore.rs | 2 +- .../directory_ownership/macro_expanded_mod_helper/foo/bar.rs | 2 +- .../directory_ownership/macro_expanded_mod_helper/foo/mod.rs | 2 +- tests/ui/lint/expansion-time-include.rs | 2 +- tests/ui/lint/known-tool-in-submodule/submodule.rs | 2 +- tests/ui/lint/lint_pre_expansion_extern_module_aux.rs | 2 +- tests/ui/lint/unknown-lints/other.rs | 4 +--- tests/ui/macros/auxiliary/macro-include-items-expr.rs | 2 -- tests/ui/macros/auxiliary/macro-include-items-item.rs | 2 -- tests/ui/macros/include-single-expr-helper-1.rs | 2 +- tests/ui/macros/include-single-expr-helper.rs | 2 +- tests/ui/macros/issue-69838-dir/bar.rs | 2 +- tests/ui/macros/issue-69838-dir/included.rs | 2 +- tests/ui/macros/macro-expanded-include/foo/mod.rs | 2 +- tests/ui/missing_non_modrs_mod/foo.rs | 3 +-- tests/ui/missing_non_modrs_mod/foo_inline.rs | 2 +- tests/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr | 2 +- tests/ui/modules/mod_file_aux.rs | 3 +-- tests/ui/modules_and_files_visibility/mod_file_aux.rs | 2 +- .../ui/modules_and_files_visibility/mod_file_disambig_aux.rs | 2 +- .../modules_and_files_visibility/mod_file_disambig_aux/mod.rs | 2 +- tests/ui/non_modrs_mods/foors_mod.rs | 4 +--- tests/ui/non_modrs_mods_and_inline_mods/x.rs | 2 +- tests/ui/non_modrs_mods_and_inline_mods/x/y/z/mod.rs | 2 +- tests/ui/numbers-arithmetic/saturating-float-casts-impl.rs | 2 +- tests/ui/parser/circular_modules_hello.rs | 2 +- .../circular-module-with-doc-comment-issue-97589/recursive.rs | 2 +- tests/ui/parser/issues/issue-48508-aux.rs | 3 +-- tests/ui/proc-macro/module.rs | 2 +- tests/ui/proc-macro/module_with_attrs.rs | 2 +- tests/ui/proc-macro/outer/inner.rs | 2 +- .../pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs | 2 +- tests/ui/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs | 2 +- tests/ui/proc-macro/pretty-print-hack/rental-0.5.6/src/lib.rs | 2 +- tests/ui/runtime/backtrace-debuginfo-aux.rs | 3 +-- 39 files changed, 37 insertions(+), 49 deletions(-) diff --git a/tests/codegen/remap_path_prefix/aux_mod.rs b/tests/codegen/remap_path_prefix/aux_mod.rs index c37e91c705cc..3217e9e51e75 100644 --- a/tests/codegen/remap_path_prefix/aux_mod.rs +++ b/tests/codegen/remap_path_prefix/aux_mod.rs @@ -1,4 +1,4 @@ -//@ ignore-test: this is not a test +//@ ignore-auxiliary (used by `./main.rs`) #[inline] pub fn some_aux_mod_function() -> i32 { diff --git a/tests/ui/borrowck/move-error-snippets-ext.rs b/tests/ui/borrowck/move-error-snippets-ext.rs index f8103228cf81..6dd68438f179 100644 --- a/tests/ui/borrowck/move-error-snippets-ext.rs +++ b/tests/ui/borrowck/move-error-snippets-ext.rs @@ -1,4 +1,4 @@ -//@ ignore-test (auxiliary, used by other tests) +//@ ignore-auxiliary (used by `./move-error-snippets.rs`) macro_rules! aaa { ($c:ident) => {{ diff --git a/tests/ui/codemap_tests/two_files_data.rs b/tests/ui/codemap_tests/two_files_data.rs index a4e4cf7e896e..82852f6cfbdf 100644 --- a/tests/ui/codemap_tests/two_files_data.rs +++ b/tests/ui/codemap_tests/two_files_data.rs @@ -1,4 +1,4 @@ -//@ ignore-test (auxiliary, used by other tests) +//@ ignore-auxiliary (used by `./two_files.rs`) trait Foo { } diff --git a/tests/ui/conditional-compilation/module_with_cfg.rs b/tests/ui/conditional-compilation/module_with_cfg.rs index 778379fa6ea7..b713689c63c8 100644 --- a/tests/ui/conditional-compilation/module_with_cfg.rs +++ b/tests/ui/conditional-compilation/module_with_cfg.rs @@ -1,3 +1,3 @@ -//@ ignore-test (auxiliary, used by other tests) +//@ ignore-auxiliary (used by `./inner-cfg-non-inline-mod.rs`) #![cfg_attr(all(), cfg(FALSE))] diff --git a/tests/ui/cross/cross-file-errors/underscore.rs b/tests/ui/cross/cross-file-errors/underscore.rs index 9d075735393d..73eb36cec24c 100644 --- a/tests/ui/cross/cross-file-errors/underscore.rs +++ b/tests/ui/cross/cross-file-errors/underscore.rs @@ -1,4 +1,4 @@ -//@ ignore-test (auxiliary, used by other tests) +//@ ignore-auxiliary (used by `./main.rs`) #![crate_type = "lib"] macro_rules! underscore { diff --git a/tests/ui/directory_ownership/macro_expanded_mod_helper/foo/bar.rs b/tests/ui/directory_ownership/macro_expanded_mod_helper/foo/bar.rs index 1d832a36ef50..2ccdd798c73d 100644 --- a/tests/ui/directory_ownership/macro_expanded_mod_helper/foo/bar.rs +++ b/tests/ui/directory_ownership/macro_expanded_mod_helper/foo/bar.rs @@ -1 +1 @@ -//@ ignore-test not a test, auxiliary +//@ ignore-auxiliary (used by `../../macro-expanded-mod.rs`) diff --git a/tests/ui/directory_ownership/macro_expanded_mod_helper/foo/mod.rs b/tests/ui/directory_ownership/macro_expanded_mod_helper/foo/mod.rs index 08349ba6747d..9009f80c6910 100644 --- a/tests/ui/directory_ownership/macro_expanded_mod_helper/foo/mod.rs +++ b/tests/ui/directory_ownership/macro_expanded_mod_helper/foo/mod.rs @@ -1,3 +1,3 @@ -//@ ignore-test not a test, auxiliary +//@ ignore-auxiliary (used by `../../macro-expanded-mod.rs`) mod_decl!(bar); diff --git a/tests/ui/lint/expansion-time-include.rs b/tests/ui/lint/expansion-time-include.rs index 3ecc01b045c4..cbe3510f04ae 100644 --- a/tests/ui/lint/expansion-time-include.rs +++ b/tests/ui/lint/expansion-time-include.rs @@ -1,4 +1,4 @@ -//@ ignore-test auxiliary file for expansion-time.rs +//@ ignore-auxiliary (used by `./expansion-time.rs`) 1 2 diff --git a/tests/ui/lint/known-tool-in-submodule/submodule.rs b/tests/ui/lint/known-tool-in-submodule/submodule.rs index 0bb2b93d53b7..9c24964e94f9 100644 --- a/tests/ui/lint/known-tool-in-submodule/submodule.rs +++ b/tests/ui/lint/known-tool-in-submodule/submodule.rs @@ -1,4 +1,4 @@ -//@ ignore-test: not a test +//@ ignore-auxiliary (used by `./root.rs`) #[allow(tool::lint)] pub fn foo() {} diff --git a/tests/ui/lint/lint_pre_expansion_extern_module_aux.rs b/tests/ui/lint/lint_pre_expansion_extern_module_aux.rs index 6e16a796ff19..10e3c0f95644 100644 --- a/tests/ui/lint/lint_pre_expansion_extern_module_aux.rs +++ b/tests/ui/lint/lint_pre_expansion_extern_module_aux.rs @@ -1,3 +1,3 @@ -//@ ignore-test: not a test +//@ ignore-auxiliary (used by `./lint-pre-expansion-extern-module.rs`) pub fn try() {} diff --git a/tests/ui/lint/unknown-lints/other.rs b/tests/ui/lint/unknown-lints/other.rs index 253335849161..7770bc59108d 100644 --- a/tests/ui/lint/unknown-lints/other.rs +++ b/tests/ui/lint/unknown-lints/other.rs @@ -1,6 +1,4 @@ -//@ ignore-test (auxiliary) - -// Companion to allow-in-other-module.rs +//@ ignore-auxiliary (used by `./allow-in-other-module.rs`) // This should not warn. #![allow(not_a_real_lint)] diff --git a/tests/ui/macros/auxiliary/macro-include-items-expr.rs b/tests/ui/macros/auxiliary/macro-include-items-expr.rs index 7394f194b80e..d00491fd7e5b 100644 --- a/tests/ui/macros/auxiliary/macro-include-items-expr.rs +++ b/tests/ui/macros/auxiliary/macro-include-items-expr.rs @@ -1,3 +1 @@ -// ignore-test: this is not a test - 1 diff --git a/tests/ui/macros/auxiliary/macro-include-items-item.rs b/tests/ui/macros/auxiliary/macro-include-items-item.rs index 7d54745e03bf..761cd0021897 100644 --- a/tests/ui/macros/auxiliary/macro-include-items-item.rs +++ b/tests/ui/macros/auxiliary/macro-include-items-item.rs @@ -1,3 +1 @@ -// ignore-test: this is not a test - fn foo() { bar() } diff --git a/tests/ui/macros/include-single-expr-helper-1.rs b/tests/ui/macros/include-single-expr-helper-1.rs index ddeeb982f64c..6802719afa1b 100644 --- a/tests/ui/macros/include-single-expr-helper-1.rs +++ b/tests/ui/macros/include-single-expr-helper-1.rs @@ -1,4 +1,4 @@ -//@ ignore-test auxiliary file for include-single-expr.rs +//@ ignore-auxiliary (used by `./include-single-expr.rs`) 0 diff --git a/tests/ui/macros/include-single-expr-helper.rs b/tests/ui/macros/include-single-expr-helper.rs index e8ad9746b02c..bd75bbbd583e 100644 --- a/tests/ui/macros/include-single-expr-helper.rs +++ b/tests/ui/macros/include-single-expr-helper.rs @@ -1,4 +1,4 @@ -//@ ignore-test auxiliary file for include-single-expr.rs +//@ ignore-auxiliary (used by `./include-single-expr.rs`) 0 10 diff --git a/tests/ui/macros/issue-69838-dir/bar.rs b/tests/ui/macros/issue-69838-dir/bar.rs index 4433005b85f1..6f91f8e2ffad 100644 --- a/tests/ui/macros/issue-69838-dir/bar.rs +++ b/tests/ui/macros/issue-69838-dir/bar.rs @@ -1,3 +1,3 @@ -//@ ignore-test -- this is an auxiliary file as part of another test. +//@ ignore-auxiliary (used by `../issue-69838-mods-relative-to-included-path.rs`) pub fn i_am_in_bar() {} diff --git a/tests/ui/macros/issue-69838-dir/included.rs b/tests/ui/macros/issue-69838-dir/included.rs index 11fcd3eff725..328334d5e66a 100644 --- a/tests/ui/macros/issue-69838-dir/included.rs +++ b/tests/ui/macros/issue-69838-dir/included.rs @@ -1,3 +1,3 @@ -//@ ignore-test -- this is an auxiliary file as part of another test. +//@ ignore-auxiliary (used by `../issue-69838-mods-relative-to-included-path.rs`) pub mod bar; diff --git a/tests/ui/macros/macro-expanded-include/foo/mod.rs b/tests/ui/macros/macro-expanded-include/foo/mod.rs index 926d84c93e58..4e6d9e4aea40 100644 --- a/tests/ui/macros/macro-expanded-include/foo/mod.rs +++ b/tests/ui/macros/macro-expanded-include/foo/mod.rs @@ -1,4 +1,4 @@ -//@ ignore-test (auxiliary, used by other tests) +//@ ignore-auxiliary (used by `../test.rs`) macro_rules! m { () => { include!("file.txt"); } diff --git a/tests/ui/missing_non_modrs_mod/foo.rs b/tests/ui/missing_non_modrs_mod/foo.rs index dd3e970b8c6e..afdc5e39b84d 100644 --- a/tests/ui/missing_non_modrs_mod/foo.rs +++ b/tests/ui/missing_non_modrs_mod/foo.rs @@ -1,4 +1,3 @@ -// -//@ ignore-test this is just a helper for the real test in this dir +//@ ignore-auxiliary (used by `./missing_non_modrs_mod.rs`) mod missing; diff --git a/tests/ui/missing_non_modrs_mod/foo_inline.rs b/tests/ui/missing_non_modrs_mod/foo_inline.rs index 9d46e9bdd0c3..ed6d3a49101d 100644 --- a/tests/ui/missing_non_modrs_mod/foo_inline.rs +++ b/tests/ui/missing_non_modrs_mod/foo_inline.rs @@ -1,4 +1,4 @@ -//@ ignore-test this is just a helper for the real test in this dir +//@ ignore-auxiliary (used by `./missing_non_modrs_mod_inline.rs`) mod inline { mod missing; diff --git a/tests/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr b/tests/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr index 4e48799318b6..c084fbf00c26 100644 --- a/tests/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr +++ b/tests/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr @@ -1,5 +1,5 @@ error[E0583]: file not found for module `missing` - --> $DIR/foo.rs:4:1 + --> $DIR/foo.rs:3:1 | LL | mod missing; | ^^^^^^^^^^^^ diff --git a/tests/ui/modules/mod_file_aux.rs b/tests/ui/modules/mod_file_aux.rs index f37296b3af0b..eec38d189b4a 100644 --- a/tests/ui/modules/mod_file_aux.rs +++ b/tests/ui/modules/mod_file_aux.rs @@ -1,4 +1,3 @@ -//@ run-pass -//@ ignore-test Not a test. Used by other tests +//@ ignore-auxiliary (used by `./mod_file_with_path_attr.rs` and `mod_file.rs`) pub fn foo() -> isize { 10 } diff --git a/tests/ui/modules_and_files_visibility/mod_file_aux.rs b/tests/ui/modules_and_files_visibility/mod_file_aux.rs index 77390da75f8f..6fac8dae3d76 100644 --- a/tests/ui/modules_and_files_visibility/mod_file_aux.rs +++ b/tests/ui/modules_and_files_visibility/mod_file_aux.rs @@ -1,3 +1,3 @@ -//@ ignore-test Not a test. Used by other tests +//@ ignore-auxiliary (used by `./mod_file_correct_spans.rs`) pub fn foo() -> isize { 10 } diff --git a/tests/ui/modules_and_files_visibility/mod_file_disambig_aux.rs b/tests/ui/modules_and_files_visibility/mod_file_disambig_aux.rs index e00b5629c083..9a0b1c4b0d8e 100644 --- a/tests/ui/modules_and_files_visibility/mod_file_disambig_aux.rs +++ b/tests/ui/modules_and_files_visibility/mod_file_disambig_aux.rs @@ -1 +1 @@ -//@ ignore-test not a test. aux file +//@ ignore-auxiliary (used by `./mod_file_disambig.rs`) diff --git a/tests/ui/modules_and_files_visibility/mod_file_disambig_aux/mod.rs b/tests/ui/modules_and_files_visibility/mod_file_disambig_aux/mod.rs index e00b5629c083..232c933c4cbf 100644 --- a/tests/ui/modules_and_files_visibility/mod_file_disambig_aux/mod.rs +++ b/tests/ui/modules_and_files_visibility/mod_file_disambig_aux/mod.rs @@ -1 +1 @@ -//@ ignore-test not a test. aux file +//@ ignore-auxiliary (used by `../mod_file_disambig.rs`) diff --git a/tests/ui/non_modrs_mods/foors_mod.rs b/tests/ui/non_modrs_mods/foors_mod.rs index b215e5f09e93..dfaa11bfe13f 100644 --- a/tests/ui/non_modrs_mods/foors_mod.rs +++ b/tests/ui/non_modrs_mods/foors_mod.rs @@ -1,6 +1,4 @@ -//@ run-pass -// -//@ ignore-test: not a test, used by non_modrs_mods.rs +//@ ignore-auxiliary (used by `./non_modrs_mods.rs`) pub mod inner_modrs_mod; pub mod inner_foors_mod; diff --git a/tests/ui/non_modrs_mods_and_inline_mods/x.rs b/tests/ui/non_modrs_mods_and_inline_mods/x.rs index c4548d39fad8..38ff011d4095 100644 --- a/tests/ui/non_modrs_mods_and_inline_mods/x.rs +++ b/tests/ui/non_modrs_mods_and_inline_mods/x.rs @@ -1,4 +1,4 @@ -//@ ignore-test: not a test +//@ ignore-auxiliary (used by `./non_modrs_mods_and_inline_mods.rs`) pub mod y { pub mod z; diff --git a/tests/ui/non_modrs_mods_and_inline_mods/x/y/z/mod.rs b/tests/ui/non_modrs_mods_and_inline_mods/x/y/z/mod.rs index ec7b7de78d8b..cac5e274fbed 100644 --- a/tests/ui/non_modrs_mods_and_inline_mods/x/y/z/mod.rs +++ b/tests/ui/non_modrs_mods_and_inline_mods/x/y/z/mod.rs @@ -1 +1 @@ -//@ ignore-test: not a test +//@ ignore-auxiliary (used by `../../../non_modrs_mods_and_inline_mods.rs`) diff --git a/tests/ui/numbers-arithmetic/saturating-float-casts-impl.rs b/tests/ui/numbers-arithmetic/saturating-float-casts-impl.rs index 4b176ef5caa6..4e578f6132fc 100644 --- a/tests/ui/numbers-arithmetic/saturating-float-casts-impl.rs +++ b/tests/ui/numbers-arithmetic/saturating-float-casts-impl.rs @@ -1,4 +1,4 @@ -//@ ignore-test (auxiliary, used by other tests) +//@ ignore-auxiliary (used by `./saturating-float-casts.rs` and `./saturating-float-casts-wasm.rs`) // Tests saturating float->int casts. See u128-as-f32.rs for the opposite direction. // diff --git a/tests/ui/parser/circular_modules_hello.rs b/tests/ui/parser/circular_modules_hello.rs index eb0284d8b410..540752ea2311 100644 --- a/tests/ui/parser/circular_modules_hello.rs +++ b/tests/ui/parser/circular_modules_hello.rs @@ -1,4 +1,4 @@ -//@ ignore-test: this is an auxiliary file for circular-modules-main.rs +//@ ignore-auxiliary (used by `./circular-modules-main.rs`) #[path = "circular_modules_main.rs"] mod circular_modules_main; diff --git a/tests/ui/parser/issues/circular-module-with-doc-comment-issue-97589/recursive.rs b/tests/ui/parser/issues/circular-module-with-doc-comment-issue-97589/recursive.rs index 3d758be8c055..2e9a15eb06da 100644 --- a/tests/ui/parser/issues/circular-module-with-doc-comment-issue-97589/recursive.rs +++ b/tests/ui/parser/issues/circular-module-with-doc-comment-issue-97589/recursive.rs @@ -1,4 +1,4 @@ -//@ ignore-test: this is an auxiliary file for circular-module-with-doc-comment-issue-97589.rs +//@ ignore-auxiliary (used by `./circular-module-with-doc-comment-issue-97589.rs`) //! this comment caused the circular dependency checker to break diff --git a/tests/ui/parser/issues/issue-48508-aux.rs b/tests/ui/parser/issues/issue-48508-aux.rs index 0f2b4427383f..0bf6490edf4d 100644 --- a/tests/ui/parser/issues/issue-48508-aux.rs +++ b/tests/ui/parser/issues/issue-48508-aux.rs @@ -1,5 +1,4 @@ -//@ run-pass -//@ ignore-test Not a test. Used by issue-48508.rs +//@ ignore-auxiliary (used by `./issue-48508.rs`) pub fn other() -> f64 { let µ = 1.0; diff --git a/tests/ui/proc-macro/module.rs b/tests/ui/proc-macro/module.rs index 210c05988bf2..5878f1b7ddd8 100644 --- a/tests/ui/proc-macro/module.rs +++ b/tests/ui/proc-macro/module.rs @@ -1 +1 @@ -//@ ignore-test (auxiliary, used by other tests) +//@ ignore-auxiliary (used by `./attributes-on-modules-fail.rs`) diff --git a/tests/ui/proc-macro/module_with_attrs.rs b/tests/ui/proc-macro/module_with_attrs.rs index 8a4ca92e44b6..7e4ec978736f 100644 --- a/tests/ui/proc-macro/module_with_attrs.rs +++ b/tests/ui/proc-macro/module_with_attrs.rs @@ -1,4 +1,4 @@ -//@ ignore-test (auxiliary, used by other tests) +//@ ignore-auxiliary (used by `../inner-attr-non-inline-mod.rs`) #![rustfmt::skip] #![print_attr] diff --git a/tests/ui/proc-macro/outer/inner.rs b/tests/ui/proc-macro/outer/inner.rs index 210c05988bf2..d0f2087321f4 100644 --- a/tests/ui/proc-macro/outer/inner.rs +++ b/tests/ui/proc-macro/outer/inner.rs @@ -1 +1 @@ -//@ ignore-test (auxiliary, used by other tests) +//@ ignore-auxiliary (used by `../attributes-on-modules-fail.rs`) diff --git a/tests/ui/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs b/tests/ui/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs index f89098f3a5ec..a27176a38e22 100644 --- a/tests/ui/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs +++ b/tests/ui/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs @@ -1,4 +1,4 @@ -//@ ignore-test (auxiliary, used by other tests) +//@ ignore-auxiliary (used by `../../../pretty-print-hack-show.rs`) #[derive(Print)] enum ProceduralMasqueradeDummyType { diff --git a/tests/ui/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs b/tests/ui/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs index f89098f3a5ec..a27176a38e22 100644 --- a/tests/ui/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs +++ b/tests/ui/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs @@ -1,4 +1,4 @@ -//@ ignore-test (auxiliary, used by other tests) +//@ ignore-auxiliary (used by `../../../pretty-print-hack-show.rs`) #[derive(Print)] enum ProceduralMasqueradeDummyType { diff --git a/tests/ui/proc-macro/pretty-print-hack/rental-0.5.6/src/lib.rs b/tests/ui/proc-macro/pretty-print-hack/rental-0.5.6/src/lib.rs index f89098f3a5ec..765ee4be656e 100644 --- a/tests/ui/proc-macro/pretty-print-hack/rental-0.5.6/src/lib.rs +++ b/tests/ui/proc-macro/pretty-print-hack/rental-0.5.6/src/lib.rs @@ -1,4 +1,4 @@ -//@ ignore-test (auxiliary, used by other tests) +//@ ignore-auxiliary (used by `../../../pretty-print-hack/hide.rs`) #[derive(Print)] enum ProceduralMasqueradeDummyType { diff --git a/tests/ui/runtime/backtrace-debuginfo-aux.rs b/tests/ui/runtime/backtrace-debuginfo-aux.rs index 24180ed21966..4493fa51f950 100644 --- a/tests/ui/runtime/backtrace-debuginfo-aux.rs +++ b/tests/ui/runtime/backtrace-debuginfo-aux.rs @@ -1,5 +1,4 @@ -//@ run-pass -//@ ignore-test: not a test, used by backtrace-debuginfo.rs to test file!() +//@ ignore-auxiliary (used by `./backtrace-debuginfo.rs` to test `file!()`) #[inline(never)] pub fn callback(f: F) where F: FnOnce((&'static str, u32)) { From 6c5a481f939d85b12f358b0be26dcf62aac568e0 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Thu, 17 Apr 2025 18:17:30 +0800 Subject: [PATCH 574/606] tests: remove unused auxiliaries under `tests/ui/directory_ownership/` --- tests/ui/directory_ownership/mod_file_not_owning_aux1.rs | 6 ------ tests/ui/directory_ownership/mod_file_not_owning_aux2.rs | 1 - tests/ui/directory_ownership/mod_file_not_owning_aux3.rs | 3 --- 3 files changed, 10 deletions(-) delete mode 100644 tests/ui/directory_ownership/mod_file_not_owning_aux1.rs delete mode 100644 tests/ui/directory_ownership/mod_file_not_owning_aux2.rs delete mode 100644 tests/ui/directory_ownership/mod_file_not_owning_aux3.rs diff --git a/tests/ui/directory_ownership/mod_file_not_owning_aux1.rs b/tests/ui/directory_ownership/mod_file_not_owning_aux1.rs deleted file mode 100644 index 6d6884fef040..000000000000 --- a/tests/ui/directory_ownership/mod_file_not_owning_aux1.rs +++ /dev/null @@ -1,6 +0,0 @@ -//@ ignore-test this is not a test - -macro_rules! m { - () => { mod mod_file_not_owning_aux2; } -} -m!(); diff --git a/tests/ui/directory_ownership/mod_file_not_owning_aux2.rs b/tests/ui/directory_ownership/mod_file_not_owning_aux2.rs deleted file mode 100644 index 76f1c1a72763..000000000000 --- a/tests/ui/directory_ownership/mod_file_not_owning_aux2.rs +++ /dev/null @@ -1 +0,0 @@ -//@ ignore-test this is not a test diff --git a/tests/ui/directory_ownership/mod_file_not_owning_aux3.rs b/tests/ui/directory_ownership/mod_file_not_owning_aux3.rs deleted file mode 100644 index 96a5780d971f..000000000000 --- a/tests/ui/directory_ownership/mod_file_not_owning_aux3.rs +++ /dev/null @@ -1,3 +0,0 @@ -//@ ignore-test this is not a test - -mod mod_file_not_owning_aux2; From c1d21003bb6d9f1f1bd3f0e5f6edc453c602dcad Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 17 Apr 2025 08:34:54 -0400 Subject: [PATCH 575/606] Update to nightly-2025-04-17 --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 940b3de9f745..fd898c59707b 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2025-01-12" +channel = "nightly-2025-04-17" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] From cc81c706e460c2d8a97a7006664136b62fd2c59e Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 27 Mar 2025 09:22:28 -0400 Subject: [PATCH 576/606] Fix patches --- ...022-core-Disable-not-compiling-tests.patch | 44 ------------------- ...0028-core-Disable-long-running-tests.patch | 26 +++++------ 2 files changed, 13 insertions(+), 57 deletions(-) delete mode 100644 patches/0022-core-Disable-not-compiling-tests.patch diff --git a/patches/0022-core-Disable-not-compiling-tests.patch b/patches/0022-core-Disable-not-compiling-tests.patch deleted file mode 100644 index 70e3e2ba7fee..000000000000 --- a/patches/0022-core-Disable-not-compiling-tests.patch +++ /dev/null @@ -1,44 +0,0 @@ -From af0e237f056fa838c77463381a19b0dc993c0a35 Mon Sep 17 00:00:00 2001 -From: None -Date: Sun, 1 Sep 2024 11:42:17 -0400 -Subject: [PATCH] Disable not compiling tests - ---- - library/core/tests/Cargo.toml | 14 ++++++++++++++ - library/core/tests/lib.rs | 1 + - 2 files changed, 15 insertions(+) - create mode 100644 library/core/tests/Cargo.toml - -diff --git a/library/core/tests/Cargo.toml b/library/core/tests/Cargo.toml -new file mode 100644 -index 0000000..ca326ac ---- /dev/null -+++ b/library/core/tests/Cargo.toml -@@ -0,0 +1,14 @@ -+[workspace] -+ -+[package] -+name = "coretests" -+version = "0.0.0" -+edition = "2021" -+ -+[lib] -+name = "coretests" -+path = "lib.rs" -+ -+[dependencies] -+rand = { version = "0.8.5", default-features = false } -+rand_xorshift = { version = "0.3.0", default-features = false } -diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs -index a4a7946..ecfe43f 100644 ---- a/library/core/tests/lib.rs -+++ b/library/core/tests/lib.rs -@@ -1,4 +1,5 @@ - // tidy-alphabetical-start -+#![cfg(test)] - #![cfg_attr(target_has_atomic = "128", feature(integer_atomics))] - #![cfg_attr(test, feature(cfg_match))] - #![feature(alloc_layout_extra)] --- -2.47.1 - diff --git a/patches/0028-core-Disable-long-running-tests.patch b/patches/0028-core-Disable-long-running-tests.patch index dc1beae6d2e7..20df4245cfdf 100644 --- a/patches/0028-core-Disable-long-running-tests.patch +++ b/patches/0028-core-Disable-long-running-tests.patch @@ -1,17 +1,17 @@ -From eb703e627e7a84f1cd8d0d87f0f69da1f0acf765 Mon Sep 17 00:00:00 2001 -From: bjorn3 -Date: Fri, 3 Dec 2021 12:16:30 +0100 +From ec2d0dc77fb484d926b45bb626b0db6a4bb0ab5c Mon Sep 17 00:00:00 2001 +From: None +Date: Thu, 27 Mar 2025 09:20:41 -0400 Subject: [PATCH] Disable long running tests --- - library/core/tests/slice.rs | 2 ++ + library/coretests/tests/slice.rs | 2 ++ 1 file changed, 2 insertions(+) -diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs -index 8402833..84592e0 100644 ---- a/library/core/tests/slice.rs -+++ b/library/core/tests/slice.rs -@@ -2462,6 +2462,7 @@ take_tests! { +diff --git a/library/coretests/tests/slice.rs b/library/coretests/tests/slice.rs +index d17e681..fba5cd6 100644 +--- a/library/coretests/tests/slice.rs ++++ b/library/coretests/tests/slice.rs +@@ -2486,6 +2486,7 @@ split_off_tests! { #[cfg(not(miri))] // unused in Miri const EMPTY_MAX: &'static [()] = &[(); usize::MAX]; @@ -19,14 +19,14 @@ index 8402833..84592e0 100644 // can't be a constant due to const mutability rules #[cfg(not(miri))] // unused in Miri macro_rules! empty_max_mut { -@@ -2485,6 +2486,7 @@ take_tests! { - (take_mut_oob_max_range_to_inclusive, (..=usize::MAX), None, empty_max_mut!()), - (take_mut_in_bounds_max_range_from, (usize::MAX..), Some(&mut [] as _), empty_max_mut!()), +@@ -2509,6 +2510,7 @@ split_off_tests! { + (split_off_mut_oob_max_range_to_inclusive, (..=usize::MAX), None, empty_max_mut!()), + (split_off_mut_in_bounds_max_range_from, (usize::MAX..), Some(&mut [] as _), empty_max_mut!()), } +*/ #[test] fn test_slice_from_ptr_range() { -- -2.26.2.7.g19db9cfb68 +2.49.0 From be75a58538154cbe901efea7807d7830d3d064c4 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 13 Apr 2025 07:48:56 -0400 Subject: [PATCH 577/606] Fix compilation --- src/abi.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/abi.rs b/src/abi.rs index 1f522f64c9cf..3b0ab9f00426 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -9,7 +9,7 @@ use rustc_middle::ty::Ty; use rustc_middle::ty::layout::LayoutOf; #[cfg(feature = "master")] use rustc_session::config; -use rustc_target::abi::call::{ArgAttributes, CastTarget, FnAbi, PassMode}; +use rustc_target::callconv::{ArgAttributes, CastTarget, FnAbi, PassMode}; #[cfg(feature = "master")] use rustc_target::callconv::Conv; @@ -239,7 +239,7 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { } #[cfg(feature = "master")] -pub fn conv_to_fn_attribute<'gcc>(conv: Conv, _arch: &str) -> Option> { +pub fn conv_to_fn_attribute<'gcc>(conv: Conv, arch: &str) -> Option> { // TODO: handle the calling conventions returning None. let attribute = match conv { Conv::C @@ -250,20 +250,19 @@ pub fn conv_to_fn_attribute<'gcc>(conv: Conv, _arch: &str) -> Option return None, Conv::PreserveMost => return None, Conv::PreserveAll => return None, - /*Conv::GpuKernel => { + Conv::GpuKernel => { if arch == "amdgpu" { return None } else if arch == "nvptx64" { return None } else { - panic!("Architecture {arch} does not support GpuKernel calling convention"); + panic!("Architecture {} does not support GpuKernel calling convention", arch); } - }*/ + } Conv::AvrInterrupt => return None, Conv::AvrNonBlockingInterrupt => return None, Conv::ArmAapcs => return None, Conv::Msp430Intr => return None, - Conv::PtxKernel => return None, Conv::X86Fastcall => return None, Conv::X86Intr => return None, Conv::X86Stdcall => return None, From 5c832e5ece3c55295bbc8c9f58962a2a57e75147 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 27 Mar 2025 14:28:56 -0400 Subject: [PATCH 578/606] Remove most of builtins hack since it's not necessary anymore --- src/context.rs | 28 +--------------------------- 1 file changed, 1 insertion(+), 27 deletions(-) diff --git a/src/context.rs b/src/context.rs index 964f1f265591..73718994e641 100644 --- a/src/context.rs +++ b/src/context.rs @@ -215,33 +215,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { let bool_type = context.new_type::(); let mut functions = FxHashMap::default(); - let builtins = [ - "__builtin_unreachable", - "abort", - "__builtin_expect", /*"__builtin_expect_with_probability",*/ - "__builtin_constant_p", - "__builtin_add_overflow", - "__builtin_mul_overflow", - "__builtin_saddll_overflow", - /*"__builtin_sadd_overflow",*/ - "__builtin_smulll_overflow", /*"__builtin_smul_overflow",*/ - "__builtin_ssubll_overflow", - /*"__builtin_ssub_overflow",*/ "__builtin_sub_overflow", - "__builtin_uaddll_overflow", - "__builtin_uadd_overflow", - "__builtin_umulll_overflow", - "__builtin_umul_overflow", - "__builtin_usubll_overflow", - "__builtin_usub_overflow", - "__builtin_powif", - "__builtin_powi", - "fabsf", - "fabs", - "copysignf", - "copysign", - "nearbyintf", - "nearbyint", - ]; + let builtins = ["abort"]; for builtin in builtins.iter() { functions.insert(builtin.to_string(), context.get_builtin_function(builtin)); From e1fa74b4a9ed699d0abf3c98113b3cc11baa81d6 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 27 Mar 2025 12:14:14 -0400 Subject: [PATCH 579/606] Implement copysignf128 --- src/intrinsic/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index f38622074f18..d22f4229e237 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -78,6 +78,7 @@ fn get_simple_intrinsic<'gcc, 'tcx>( sym::maxnumf64 => "fmax", sym::copysignf32 => "copysignf", sym::copysignf64 => "copysign", + sym::copysignf128 => "copysignl", sym::floorf32 => "floorf", sym::floorf64 => "floor", sym::ceilf32 => "ceilf", From 9a453d46f42c40b91d004064a4cc12f7c28c7fc7 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 27 Mar 2025 14:33:03 -0400 Subject: [PATCH 580/606] Update other patches --- ...001-Disable-libstd-and-libtest-dylib.patch | 18 ++++++----- ...0001-core-Disable-portable-simd-test.patch | 32 ++++++++----------- 2 files changed, 23 insertions(+), 27 deletions(-) diff --git a/patches/cross_patches/0001-Disable-libstd-and-libtest-dylib.patch b/patches/cross_patches/0001-Disable-libstd-and-libtest-dylib.patch index c220f53040f0..fa360fe9e74e 100644 --- a/patches/cross_patches/0001-Disable-libstd-and-libtest-dylib.patch +++ b/patches/cross_patches/0001-Disable-libstd-and-libtest-dylib.patch @@ -1,19 +1,18 @@ -From 966beefe08be6045bfcca26079b76a7a80413080 Mon Sep 17 00:00:00 2001 +From b2911e732d1bf0e28872495c4c47af1dad3c7911 Mon Sep 17 00:00:00 2001 From: None -Date: Thu, 28 Sep 2023 17:37:38 -0400 +Date: Thu, 27 Mar 2025 14:30:10 -0400 Subject: [PATCH] Disable libstd and libtest dylib --- - library/std/Cargo.toml | 2 +- - library/test/Cargo.toml | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) + library/std/Cargo.toml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml -index 5b21355..cb0c49b 100644 +index 176da60..c183cdb 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml -@@ -9,7 +9,7 @@ description = "The Rust Standard Library" - edition = "2021" +@@ -10,7 +10,7 @@ edition = "2024" + autobenches = false [lib] -crate-type = ["dylib", "rlib"] @@ -21,3 +20,6 @@ index 5b21355..cb0c49b 100644 [dependencies] alloc = { path = "../alloc", public = true } +-- +2.49.0 + diff --git a/patches/libgccjit12/0001-core-Disable-portable-simd-test.patch b/patches/libgccjit12/0001-core-Disable-portable-simd-test.patch index 9ef5e0e4f467..9d5b2dc537d2 100644 --- a/patches/libgccjit12/0001-core-Disable-portable-simd-test.patch +++ b/patches/libgccjit12/0001-core-Disable-portable-simd-test.patch @@ -1,25 +1,17 @@ -From 124a11ce086952a5794d5cfbaa45175809497b81 Mon Sep 17 00:00:00 2001 +From 1a8f6b8e39f343959d4d2e6b6957a6d780ac3fc0 Mon Sep 17 00:00:00 2001 From: None -Date: Sat, 18 Nov 2023 10:50:36 -0500 -Subject: [PATCH] [core] Disable portable-simd test +Date: Thu, 27 Mar 2025 14:32:14 -0400 +Subject: [PATCH] Disable portable-simd test --- - library/core/tests/lib.rs | 2 -- - 1 file changed, 2 deletions(-) + library/coretests/tests/lib.rs | 1 - + 1 file changed, 1 deletion(-) -diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs -index b71786c..cf484d5 100644 ---- a/library/core/tests/lib.rs -+++ b/library/core/tests/lib.rs -@@ -87,7 +87,6 @@ - #![feature(numfmt)] - #![feature(pattern)] - #![feature(pointer_is_aligned_to)] --#![feature(portable_simd)] - #![feature(ptr_metadata)] - #![feature(slice_from_ptr_range)] - #![feature(slice_internals)] -@@ -155,7 +154,6 @@ mod pin; +diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs +index 79022fe..9223b2f 100644 +--- a/library/coretests/tests/lib.rs ++++ b/library/coretests/tests/lib.rs +@@ -165,7 +165,6 @@ mod pin; mod pin_macro; mod ptr; mod result; @@ -27,4 +19,6 @@ index b71786c..cf484d5 100644 mod slice; mod str; mod str_lossy; --- 2.45.2 +-- +2.49.0 + From f9822772e8781ed30a89aa4494e47c42b4397133 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 27 Mar 2025 14:33:38 -0400 Subject: [PATCH 581/606] Fix libcore tests --- build_system/src/test.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 297cd7d71316..df4ac85233b0 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -678,7 +678,7 @@ fn test_projects(env: &Env, args: &TestArg) -> Result<(), String> { fn test_libcore(env: &Env, args: &TestArg) -> Result<(), String> { // FIXME: create a function "display_if_not_quiet" or something along the line. println!("[TEST] libcore"); - let path = get_sysroot_dir().join("sysroot_src/library/core/tests"); + let path = get_sysroot_dir().join("sysroot_src/library/coretests"); let _ = remove_dir_all(path.join("target")); run_cargo_command(&[&"test"], Some(&path), env, args)?; Ok(()) From 5cf2bbc4e2c82961f2e82fbacc39fcf5f332e371 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 27 Mar 2025 14:34:44 -0400 Subject: [PATCH 582/606] Fix clippy warnings --- src/abi.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/abi.rs b/src/abi.rs index 3b0ab9f00426..6fdb03fb85b5 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -251,6 +251,8 @@ pub fn conv_to_fn_attribute<'gcc>(conv: Conv, arch: &str) -> Option return None, Conv::PreserveAll => return None, Conv::GpuKernel => { + // TODO(antoyo): remove clippy allow attribute when this is implemented. + #[allow(clippy::if_same_then_else)] if arch == "amdgpu" { return None } else if arch == "nvptx64" { From ecf0a1eea3714a9c9f79bf1f3a53e6feb6c631f5 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 13 Apr 2025 08:28:02 -0400 Subject: [PATCH 583/606] Update GCC version --- libgccjit.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgccjit.version b/libgccjit.version index dfdc222c00fc..125b04004b07 100644 --- a/libgccjit.version +++ b/libgccjit.version @@ -1 +1 @@ -d6f5a708104a98199ac0f01a3b6b279a0f7c66d3 +0ea98a1365b81f7488073512c850e8ee951a4afd From ec44cfdfb4a74d19f522984e2e2e226a3b76df9a Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 27 Mar 2025 15:28:31 -0400 Subject: [PATCH 584/606] Fix tests --- example/mini_core.rs | 16 ++++++++++++++++ tests/run/abort1.rs | 2 +- tests/run/abort2.rs | 2 +- tests/run/assign.rs | 2 +- tests/run/closure.rs | 2 +- tests/run/mut_ref.rs | 2 +- tests/run/static.rs | 2 +- 7 files changed, 22 insertions(+), 6 deletions(-) diff --git a/example/mini_core.rs b/example/mini_core.rs index 32501530cfac..c554a87b8256 100644 --- a/example/mini_core.rs +++ b/example/mini_core.rs @@ -138,6 +138,14 @@ impl Mul for u8 { } } +impl Mul for i32 { + type Output = Self; + + fn mul(self, rhs: Self) -> Self::Output { + self * rhs + } +} + impl Mul for usize { type Output = Self; @@ -248,6 +256,14 @@ impl Sub for i16 { } } +impl Sub for i32 { + type Output = Self; + + fn sub(self, rhs: Self) -> Self { + self - rhs + } +} + #[lang = "rem"] pub trait Rem { type Output; diff --git a/tests/run/abort1.rs b/tests/run/abort1.rs index ae7e457d1cd3..ff2bb75ece22 100644 --- a/tests/run/abort1.rs +++ b/tests/run/abort1.rs @@ -3,7 +3,7 @@ // Run-time: // status: signal -#![feature(no_core, start)] +#![feature(no_core)] #![no_std] #![no_core] #![no_main] diff --git a/tests/run/abort2.rs b/tests/run/abort2.rs index 28fad0107f75..781f518e0b22 100644 --- a/tests/run/abort2.rs +++ b/tests/run/abort2.rs @@ -3,7 +3,7 @@ // Run-time: // status: signal -#![feature(no_core, start)] +#![feature(no_core)] #![no_std] #![no_core] #![no_main] diff --git a/tests/run/assign.rs b/tests/run/assign.rs index a54d0b20def3..4535ab5778e9 100644 --- a/tests/run/assign.rs +++ b/tests/run/assign.rs @@ -23,7 +23,7 @@ fn inc(num: isize) -> isize { } #[no_mangle] -extern "C" fn main(mut argc: i32, _argv: *const *const u8) -> i32 { +extern "C" fn main(mut argc: isize, _argv: *const *const u8) -> i32 { argc = inc(argc); unsafe { libc::printf(b"%ld\n\0" as *const u8 as *const i8, argc); diff --git a/tests/run/closure.rs b/tests/run/closure.rs index b827a2614002..a8a3fadfed47 100644 --- a/tests/run/closure.rs +++ b/tests/run/closure.rs @@ -17,7 +17,7 @@ extern crate mini_core; use mini_core::*; #[no_mangle] -extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { +extern "C" fn main(argc: isize, _argv: *const *const u8) -> i32 { let string = "Arg: %d\n\0"; let mut closure = || unsafe { libc::printf(string as *const str as *const i8, argc); diff --git a/tests/run/mut_ref.rs b/tests/run/mut_ref.rs index 5fa5df751a32..fa50d5bc5d3d 100644 --- a/tests/run/mut_ref.rs +++ b/tests/run/mut_ref.rs @@ -27,7 +27,7 @@ fn update_num(num: &mut isize) { } #[no_mangle] -extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { +extern "C" fn main(mut argc: isize, _argv: *const *const u8) -> i32 { let mut test = test(argc); unsafe { libc::printf(b"%ld\n\0" as *const u8 as *const i8, test.field); diff --git a/tests/run/static.rs b/tests/run/static.rs index c58151f8417b..1e36cf4f3d31 100644 --- a/tests/run/static.rs +++ b/tests/run/static.rs @@ -34,7 +34,7 @@ static mut TEST2: Test = Test { field: 14 }; static mut WITH_REF: WithRef = WithRef { refe: unsafe { &TEST } }; #[no_mangle] -extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { +extern "C" fn main(argc: isize, _argv: *const *const u8) -> i32 { unsafe { libc::printf(b"%ld\n\0" as *const u8 as *const i8, CONSTANT); libc::printf(b"%ld\n\0" as *const u8 as *const i8, TEST2.field); From bc0bc8d5e1a1a38ee5a342e614e490e490bc5604 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 27 Mar 2025 15:36:15 -0400 Subject: [PATCH 585/606] Fix int_to_float_cast for f128 --- src/int.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/int.rs b/src/int.rs index f3552d9b12fc..b5fcb534747d 100644 --- a/src/int.rs +++ b/src/int.rs @@ -905,6 +905,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { let name_suffix = match self.type_kind(dest_typ) { TypeKind::Float => "tisf", TypeKind::Double => "tidf", + TypeKind::FP128 => "tixf", kind => panic!("cannot cast a non-native integer to type {:?}", kind), }; let sign = if signed { "" } else { "un" }; From 6504f4c09ce9e3c72084e647fab8e6565d79573e Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 13 Apr 2025 08:40:42 -0400 Subject: [PATCH 586/606] Format --- src/abi.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/abi.rs b/src/abi.rs index 6fdb03fb85b5..a96b18e01c08 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -9,9 +9,9 @@ use rustc_middle::ty::Ty; use rustc_middle::ty::layout::LayoutOf; #[cfg(feature = "master")] use rustc_session::config; -use rustc_target::callconv::{ArgAttributes, CastTarget, FnAbi, PassMode}; #[cfg(feature = "master")] use rustc_target::callconv::Conv; +use rustc_target::callconv::{ArgAttributes, CastTarget, FnAbi, PassMode}; use crate::builder::Builder; use crate::context::CodegenCx; @@ -254,9 +254,9 @@ pub fn conv_to_fn_attribute<'gcc>(conv: Conv, arch: &str) -> Option Date: Sun, 13 Apr 2025 08:58:32 -0400 Subject: [PATCH 587/606] Fix tests --- tests/failing-ui-tests.txt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/failing-ui-tests.txt b/tests/failing-ui-tests.txt index 0babc748f98b..12dc7f726aab 100644 --- a/tests/failing-ui-tests.txt +++ b/tests/failing-ui-tests.txt @@ -31,7 +31,6 @@ tests/ui/unwind-no-uwtable.rs tests/ui/parser/unclosed-delimiter-in-dep.rs tests/ui/consts/missing_span_in_backtrace.rs tests/ui/drop/dynamic-drop.rs -tests/ui/issues/issue-40883.rs tests/ui/issues/issue-43853.rs tests/ui/issues/issue-47364.rs tests/ui/macros/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.rs @@ -100,14 +99,12 @@ tests/ui/codegen/equal-pointers-unequal/as-cast/basic.rs tests/ui/codegen/equal-pointers-unequal/as-cast/inline1.rs tests/ui/codegen/equal-pointers-unequal/as-cast/print.rs tests/ui/codegen/equal-pointers-unequal/as-cast/inline2.rs -tests/ui/codegen/equal-pointers-unequal/as-cast/print3.rs tests/ui/codegen/equal-pointers-unequal/as-cast/segfault.rs tests/ui/codegen/equal-pointers-unequal/exposed-provenance/function.rs tests/ui/codegen/equal-pointers-unequal/exposed-provenance/basic.rs tests/ui/codegen/equal-pointers-unequal/as-cast/zero.rs tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline1.rs tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print.rs -tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print3.rs tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline2.rs tests/ui/codegen/equal-pointers-unequal/exposed-provenance/segfault.rs tests/ui/codegen/equal-pointers-unequal/exposed-provenance/zero.rs @@ -115,8 +112,8 @@ tests/ui/codegen/equal-pointers-unequal/strict-provenance/basic.rs tests/ui/codegen/equal-pointers-unequal/strict-provenance/function.rs tests/ui/codegen/equal-pointers-unequal/strict-provenance/print.rs tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline1.rs -tests/ui/codegen/equal-pointers-unequal/strict-provenance/print3.rs tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline2.rs tests/ui/codegen/equal-pointers-unequal/strict-provenance/segfault.rs tests/ui/codegen/equal-pointers-unequal/strict-provenance/zero.rs tests/ui/simd/simd-bitmask-notpow2.rs +tests/ui/codegen/StackColoring-not-blowup-stack-issue-40883.rs From 0d773175cc41901f1a558a9b45239c67c3fa0df6 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 13 Apr 2025 10:25:10 -0400 Subject: [PATCH 588/606] Add support for simd_insert_dyn and simd_extract_dyn --- src/intrinsic/simd.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/intrinsic/simd.rs b/src/intrinsic/simd.rs index 8b454ab2a424..6d40d5297f1a 100644 --- a/src/intrinsic/simd.rs +++ b/src/intrinsic/simd.rs @@ -399,7 +399,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( } #[cfg(feature = "master")] - if name == sym::simd_insert { + if name == sym::simd_insert || name == sym::simd_insert_dyn { require!( in_elem == arg_tys[2], InvalidMonomorphization::InsertedType { @@ -410,6 +410,8 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( out_ty: arg_tys[2] } ); + + // TODO(antoyo): For simd_insert, check if the index is a constant of the correct size. let vector = args[0].immediate(); let index = args[1].immediate(); let value = args[2].immediate(); @@ -422,13 +424,15 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( } #[cfg(feature = "master")] - if name == sym::simd_extract { + if name == sym::simd_extract || name == sym::simd_extract_dyn { require!( ret_ty == in_elem, InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty } ); + // TODO(antoyo): For simd_extract, check if the index is a constant of the correct size. let vector = args[0].immediate(); - return Ok(bx.context.new_vector_access(None, vector, args[1].immediate()).to_rvalue()); + let index = args[1].immediate(); + return Ok(bx.context.new_vector_access(None, vector, index).to_rvalue()); } if name == sym::simd_select { From 4b5940ad77cf9a95cf78bef1ecc6fa84ef1fc0ce Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Tue, 15 Apr 2025 12:51:28 -0400 Subject: [PATCH 589/606] Fix overflow operations --- src/int.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/int.rs b/src/int.rs index b5fcb534747d..9b5b0fde6e2f 100644 --- a/src/int.rs +++ b/src/int.rs @@ -404,7 +404,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let ret_indirect = matches!(fn_abi.ret.mode, PassMode::Indirect { .. }); - let result = if ret_indirect { + let call = if ret_indirect { let res_value = self.current_func().new_local(self.location, res_type, "result_value"); let res_addr = res_value.get_address(self.location); let res_param_type = res_type.make_pointer(); @@ -432,8 +432,17 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { ); self.context.new_call(self.location, func, &[lhs, rhs, overflow_addr]) }; + // NOTE: we must assign the result of the operation to a variable at this point to make + // sure it will be evaluated by libgccjit now. + // Otherwise, it will only be evaluated when the rvalue for the call is used somewhere else + // and overflow_value will not be initialized at the correct point in the program. + let result = self.current_func().new_local(self.location, res_type, "result"); + self.block.add_assignment(self.location, result, call); - (result, self.context.new_cast(self.location, overflow_value, self.bool_type).to_rvalue()) + ( + result.to_rvalue(), + self.context.new_cast(self.location, overflow_value, self.bool_type).to_rvalue(), + ) } pub fn gcc_icmp( @@ -865,6 +874,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { let value_type = value.get_type(); if self.is_native_int_type_or_bool(dest_typ) && self.is_native_int_type_or_bool(value_type) { + // TODO: use self.location. self.context.new_cast(None, value, dest_typ) } else if self.is_native_int_type_or_bool(dest_typ) { self.context.new_cast(None, self.low(value), dest_typ) From 06af88e06cd464809bbe3c2ab073d2d575d185e6 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Tue, 15 Apr 2025 13:28:27 -0400 Subject: [PATCH 590/606] Add new failing test --- tests/failing-ui-tests.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/failing-ui-tests.txt b/tests/failing-ui-tests.txt index 12dc7f726aab..499c1a962311 100644 --- a/tests/failing-ui-tests.txt +++ b/tests/failing-ui-tests.txt @@ -117,3 +117,4 @@ tests/ui/codegen/equal-pointers-unequal/strict-provenance/segfault.rs tests/ui/codegen/equal-pointers-unequal/strict-provenance/zero.rs tests/ui/simd/simd-bitmask-notpow2.rs tests/ui/codegen/StackColoring-not-blowup-stack-issue-40883.rs +tests/ui/uninhabited/uninhabited-transparent-return-abi.rs From 8562110e0d8ef293563200d15d466c012e936ff7 Mon Sep 17 00:00:00 2001 From: xizheyin Date: Tue, 15 Apr 2025 15:03:11 +0800 Subject: [PATCH 591/606] Hide unstable print kinds within emit_unknown_print_request_help in stable channel Signed-off-by: xizheyin --- compiler/rustc_session/src/config.rs | 37 +++++++++++++------ .../help-diff.diff | 7 ++++ .../rmake.rs | 33 +++++++++++++++++ .../stable-invalid-print-request-help.err | 5 +++ .../unstable-invalid-print-request-help.err | 5 +++ 5 files changed, 75 insertions(+), 12 deletions(-) create mode 100644 tests/run-make/print-request-help-stable-unstable/help-diff.diff create mode 100644 tests/run-make/print-request-help-stable-unstable/rmake.rs create mode 100644 tests/run-make/print-request-help-stable-unstable/stable-invalid-print-request-help.err create mode 100644 tests/run-make/print-request-help-stable-unstable/unstable-invalid-print-request-help.err diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index bdd54a15147b..d00c08739619 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -2069,7 +2069,8 @@ fn collect_print_requests( check_print_request_stability(early_dcx, unstable_opts, (print_name, *print_kind)); *print_kind } else { - emit_unknown_print_request_help(early_dcx, req) + let is_nightly = nightly_options::match_is_nightly_build(matches); + emit_unknown_print_request_help(early_dcx, req, is_nightly) }; let out = out.unwrap_or(OutFileName::Stdout); @@ -2093,25 +2094,37 @@ fn check_print_request_stability( unstable_opts: &UnstableOptions, (print_name, print_kind): (&str, PrintKind), ) { + if !is_print_request_stable(print_kind) && !unstable_opts.unstable_options { + early_dcx.early_fatal(format!( + "the `-Z unstable-options` flag must also be passed to enable the `{print_name}` \ + print option" + )); + } +} + +fn is_print_request_stable(print_kind: PrintKind) -> bool { match print_kind { PrintKind::AllTargetSpecsJson | PrintKind::CheckCfg | PrintKind::CrateRootLintLevels | PrintKind::SupportedCrateTypes - | PrintKind::TargetSpecJson - if !unstable_opts.unstable_options => - { - early_dcx.early_fatal(format!( - "the `-Z unstable-options` flag must also be passed to enable the `{print_name}` \ - print option" - )); - } - _ => {} + | PrintKind::TargetSpecJson => false, + _ => true, } } -fn emit_unknown_print_request_help(early_dcx: &EarlyDiagCtxt, req: &str) -> ! { - let prints = PRINT_KINDS.iter().map(|(name, _)| format!("`{name}`")).collect::>(); +fn emit_unknown_print_request_help(early_dcx: &EarlyDiagCtxt, req: &str, is_nightly: bool) -> ! { + let prints = PRINT_KINDS + .iter() + .filter_map(|(name, kind)| { + // If we're not on nightly, we don't want to print unstable options + if !is_nightly && !is_print_request_stable(*kind) { + None + } else { + Some(format!("`{name}`")) + } + }) + .collect::>(); let prints = prints.join(", "); let mut diag = early_dcx.early_struct_fatal(format!("unknown print request: `{req}`")); diff --git a/tests/run-make/print-request-help-stable-unstable/help-diff.diff b/tests/run-make/print-request-help-stable-unstable/help-diff.diff new file mode 100644 index 000000000000..07eafca32710 --- /dev/null +++ b/tests/run-make/print-request-help-stable-unstable/help-diff.diff @@ -0,0 +1,7 @@ +@@ -1,5 +1,5 @@ + error: unknown print request: `xxx` + | +- = help: valid print requests are: `calling-conventions`, `cfg`, `code-models`, `crate-name`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `tls-models` ++ = help: valid print requests are: `all-target-specs-json`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `tls-models` + = help: for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information + diff --git a/tests/run-make/print-request-help-stable-unstable/rmake.rs b/tests/run-make/print-request-help-stable-unstable/rmake.rs new file mode 100644 index 000000000000..a59963da5c49 --- /dev/null +++ b/tests/run-make/print-request-help-stable-unstable/rmake.rs @@ -0,0 +1,33 @@ +//! Check that unstable print requests are omitted from help if compiler is in stable channel. +//! +//! Issue: +use run_make_support::{diff, rustc, similar}; + +fn main() { + let stable_invalid_print_request_help = rustc() + .env("RUSTC_BOOTSTRAP", "-1") + .cfg("force_stable") + .print("xxx") + .run_fail() + .stderr_utf8(); + assert!(!stable_invalid_print_request_help.contains("all-target-specs-json")); + diff() + .expected_file("stable-invalid-print-request-help.err") + .actual_text("stable_invalid_print_request_help", &stable_invalid_print_request_help) + .run(); + + let unstable_invalid_print_request_help = rustc().print("xxx").run_fail().stderr_utf8(); + assert!(unstable_invalid_print_request_help.contains("all-target-specs-json")); + diff() + .expected_file("unstable-invalid-print-request-help.err") + .actual_text("unstable_invalid_print_request_help", &unstable_invalid_print_request_help) + .run(); + + let help_diff = similar::TextDiff::from_lines( + &stable_invalid_print_request_help, + &unstable_invalid_print_request_help, + ) + .unified_diff() + .to_string(); + diff().expected_file("help-diff.diff").actual_text("help_diff", help_diff).run(); +} diff --git a/tests/run-make/print-request-help-stable-unstable/stable-invalid-print-request-help.err b/tests/run-make/print-request-help-stable-unstable/stable-invalid-print-request-help.err new file mode 100644 index 000000000000..019a578dad3e --- /dev/null +++ b/tests/run-make/print-request-help-stable-unstable/stable-invalid-print-request-help.err @@ -0,0 +1,5 @@ +error: unknown print request: `xxx` + | + = help: valid print requests are: `calling-conventions`, `cfg`, `code-models`, `crate-name`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `tls-models` + = help: for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information + diff --git a/tests/run-make/print-request-help-stable-unstable/unstable-invalid-print-request-help.err b/tests/run-make/print-request-help-stable-unstable/unstable-invalid-print-request-help.err new file mode 100644 index 000000000000..50ef340e3dd0 --- /dev/null +++ b/tests/run-make/print-request-help-stable-unstable/unstable-invalid-print-request-help.err @@ -0,0 +1,5 @@ +error: unknown print request: `xxx` + | + = help: valid print requests are: `all-target-specs-json`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `crate-root-lint-levels`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `supported-crate-types`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `tls-models` + = help: for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information + From 7a5a884275b0bdbd28397c814b45f71d10b45439 Mon Sep 17 00:00:00 2001 From: Lukas Woodtli Date: Thu, 17 Apr 2025 16:07:12 +0200 Subject: [PATCH 592/606] Make C string merging test work on MIPS Assembly for MIPS uses, by convention, a different prefix for local anonymous variables. --- tests/assembly/cstring-merging.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/assembly/cstring-merging.rs b/tests/assembly/cstring-merging.rs index b5c530ac35d7..f7d0775f7aff 100644 --- a/tests/assembly/cstring-merging.rs +++ b/tests/assembly/cstring-merging.rs @@ -1,3 +1,5 @@ +// MIPS assembler uses the label prefix `$anon.` for local anonymous variables +// other architectures (including ARM and x86-64) use the prefix `.Lanon.` //@ only-linux //@ assembly-output: emit-asm //@ compile-flags: --crate-type=lib -Copt-level=3 @@ -6,13 +8,13 @@ use std::ffi::CStr; // CHECK: .section .rodata.str1.{{[12]}},"aMS" -// CHECK: .Lanon.{{.+}}: +// CHECK: {{(\.L|\$)}}anon.{{.+}}: // CHECK-NEXT: .asciz "foo" #[unsafe(no_mangle)] static CSTR: &[u8; 4] = b"foo\0"; // CHECK-NOT: .section -// CHECK: .Lanon.{{.+}}: +// CHECK: {{(\.L|\$)}}anon.{{.+}}: // CHECK-NEXT: .asciz "bar" #[unsafe(no_mangle)] pub fn cstr() -> &'static CStr { @@ -20,7 +22,7 @@ pub fn cstr() -> &'static CStr { } // CHECK-NOT: .section -// CHECK: .Lanon.{{.+}}: +// CHECK: {{(\.L|\$)}}anon.{{.+}}: // CHECK-NEXT: .asciz "baz" #[unsafe(no_mangle)] pub fn manual_cstr() -> &'static str { From 50cf10231125d7b306ed92867f11771032d28eff Mon Sep 17 00:00:00 2001 From: Patrick-6 Date: Thu, 17 Apr 2025 16:23:36 +0200 Subject: [PATCH 593/606] Change function visibility to pub --- compiler/rustc_const_eval/src/interpret/eval_context.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index c1948e9f31f1..b69bc0918be8 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -268,7 +268,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// Call this on things you got out of the MIR (so it is as generic as the current /// stack frame), to bring it into the proper environment for this interpreter. - pub(super) fn instantiate_from_current_frame_and_normalize_erasing_regions< + pub fn instantiate_from_current_frame_and_normalize_erasing_regions< T: TypeFoldable>, >( &self, @@ -279,9 +279,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// Call this on things you got out of the MIR (so it is as generic as the provided /// stack frame), to bring it into the proper environment for this interpreter. - pub(super) fn instantiate_from_frame_and_normalize_erasing_regions< - T: TypeFoldable>, - >( + pub fn instantiate_from_frame_and_normalize_erasing_regions>>( &self, frame: &Frame<'tcx, M::Provenance, M::FrameExtra>, value: T, From f9091e24a0af713378ee705c86689c1435d0b157 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 7 Apr 2025 12:35:02 -0700 Subject: [PATCH 594/606] Ignore zero-sized types in wasm future-compat warning This commit fixes a false positive of the warning triggered for #138762 and the fix is to codify that zero-sized types are "safe" in both the old and new ABIs. --- compiler/rustc_monomorphize/src/mono_checks/abi_check.rs | 5 +++++ tests/ui/lint/wasm_c_abi_transition.rs | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs index 0f5bdc8d7683..94ee34c8b7bf 100644 --- a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs +++ b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs @@ -111,6 +111,11 @@ fn wasm_abi_safe<'tcx>(tcx: TyCtxt<'tcx>, arg: &ArgAbi<'tcx, Ty<'tcx>>) -> bool } } + // Zero-sized types are dropped in both ABIs, so they're safe + if arg.layout.is_zst() { + return true; + } + false } diff --git a/tests/ui/lint/wasm_c_abi_transition.rs b/tests/ui/lint/wasm_c_abi_transition.rs index 1fe81679e65d..6a933a0de036 100644 --- a/tests/ui/lint/wasm_c_abi_transition.rs +++ b/tests/ui/lint/wasm_c_abi_transition.rs @@ -39,3 +39,9 @@ pub fn call_other_fun(x: MyType) { unsafe { other_fun(x) } //~ERROR: wasm ABI transition //~^WARN: previously accepted } + +// Zero-sized types are safe in both ABIs +#[repr(C)] +pub struct MyZstType; +#[allow(improper_ctypes_definitions)] +pub extern "C" fn zst_safe(_x: (), _y: MyZstType) {} From 83af9f57c12c25807777f0c42ecc5a9ba070b09f Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Thu, 17 Apr 2025 23:20:30 +0800 Subject: [PATCH 595/606] run-make: drop `os_pipe` workaround now that `anonymous_pipe` is stable on beta --- Cargo.lock | 11 ----------- src/tools/run-make-support/Cargo.toml | 4 ---- src/tools/run-make-support/src/lib.rs | 2 -- tests/run-make/broken-pipe-no-ice/rmake.rs | 6 ++---- 4 files changed, 2 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3d0e29421791..58d3673fcbaa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2572,16 +2572,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" -[[package]] -name = "os_pipe" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ffd2b0a5634335b135d5728d84c5e0fd726954b87111f7506a61c502280d982" -dependencies = [ - "libc", - "windows-sys 0.59.0", -] - [[package]] name = "overload" version = "0.1.1" @@ -3142,7 +3132,6 @@ dependencies = [ "gimli 0.31.1", "libc", "object 0.36.7", - "os_pipe", "regex", "serde_json", "similar", diff --git a/src/tools/run-make-support/Cargo.toml b/src/tools/run-make-support/Cargo.toml index f9beffec7508..15ed03ad5c23 100644 --- a/src/tools/run-make-support/Cargo.toml +++ b/src/tools/run-make-support/Cargo.toml @@ -14,9 +14,5 @@ build_helper = { path = "../../build_helper" } serde_json = "1.0" libc = "0.2" -# FIXME(#137532): replace `os_pipe` with `anonymous_pipe` once it stabilizes and -# reaches beta. -os_pipe = "1.2.1" - [lib] crate-type = ["lib", "dylib"] diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index c75d500d2f06..f37b38ac0b15 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -41,8 +41,6 @@ pub use bstr; pub use gimli; pub use libc; pub use object; -// FIXME(#137532): replace with std `anonymous_pipe` once it stabilizes and reaches beta. -pub use os_pipe; pub use regex; pub use serde_json; pub use similar; diff --git a/tests/run-make/broken-pipe-no-ice/rmake.rs b/tests/run-make/broken-pipe-no-ice/rmake.rs index 3e54b576fd42..0521b3950207 100644 --- a/tests/run-make/broken-pipe-no-ice/rmake.rs +++ b/tests/run-make/broken-pipe-no-ice/rmake.rs @@ -14,9 +14,7 @@ use std::io::Read; use std::process::{Command, Stdio}; -// FIXME(#137532): replace `os_pipe` dependency with std `anonymous_pipe` once that stabilizes and -// reaches beta. -use run_make_support::{env_var, os_pipe}; +use run_make_support::env_var; #[derive(Debug, PartialEq)] enum Binary { @@ -25,7 +23,7 @@ enum Binary { } fn check_broken_pipe_handled_gracefully(bin: Binary, mut cmd: Command) { - let (reader, writer) = os_pipe::pipe().unwrap(); + let (reader, writer) = std::io::pipe().unwrap(); drop(reader); // close read-end cmd.stdout(writer).stderr(Stdio::piped()); From e5e5fb9d805dacdd5ceaf73254d61726d75f455a Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Thu, 17 Apr 2025 17:29:32 +0200 Subject: [PATCH 596/606] Fix drop handling in `hint::select_unpredictable` This intrinsic doesn't drop the value that is not selected so this is manually done in the public function that wraps the intrinsic. --- library/core/src/hint.rs | 30 +++++++++++++++++++++--------- library/core/src/intrinsics/mod.rs | 2 ++ library/coretests/tests/hint.rs | 23 +++++++++++++++++++++++ library/coretests/tests/lib.rs | 2 ++ 4 files changed, 48 insertions(+), 9 deletions(-) create mode 100644 library/coretests/tests/hint.rs diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index f6708cc4bc91..1ca23ab6eea6 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -4,6 +4,7 @@ //! //! Hints may be compile time or runtime. +use crate::mem::MaybeUninit; use crate::{intrinsics, ub_checks}; /// Informs the compiler that the site which is calling this function is not @@ -735,9 +736,9 @@ pub const fn cold_path() { crate::intrinsics::cold_path() } -/// Returns either `true_val` or `false_val` depending on the value of `b`, -/// with a hint to the compiler that `b` is unlikely to be correctly -/// predicted by a CPU’s branch predictor. +/// Returns either `true_val` or `false_val` depending on the value of +/// `condition`, with a hint to the compiler that `condition` is unlikely to be +/// correctly predicted by a CPU’s branch predictor. /// /// This method is functionally equivalent to /// ```ignore (this is just for illustrative purposes) @@ -753,10 +754,10 @@ pub const fn cold_path() { /// search. /// /// Note however that this lowering is not guaranteed (on any platform) and -/// should not be relied upon when trying to write constant-time code. Also -/// be aware that this lowering might *decrease* performance if `condition` -/// is well-predictable. It is advisable to perform benchmarks to tell if -/// this function is useful. +/// should not be relied upon when trying to write cryptographic constant-time +/// code. Also be aware that this lowering might *decrease* performance if +/// `condition` is well-predictable. It is advisable to perform benchmarks to +/// tell if this function is useful. /// /// # Examples /// @@ -780,6 +781,17 @@ pub const fn cold_path() { /// ``` #[inline(always)] #[unstable(feature = "select_unpredictable", issue = "133962")] -pub fn select_unpredictable(b: bool, true_val: T, false_val: T) -> T { - crate::intrinsics::select_unpredictable(b, true_val, false_val) +pub fn select_unpredictable(condition: bool, true_val: T, false_val: T) -> T { + // FIXME(https://github.com/rust-lang/unsafe-code-guidelines/issues/245): + // Change this to use ManuallyDrop instead. + let mut true_val = MaybeUninit::new(true_val); + let mut false_val = MaybeUninit::new(false_val); + // SAFETY: The value that is not selected is dropped, and the selected one + // is returned. This is necessary because the intrinsic doesn't drop the + // value that is not selected. + unsafe { + crate::intrinsics::select_unpredictable(!condition, &mut true_val, &mut false_val) + .assume_init_drop(); + crate::intrinsics::select_unpredictable(condition, true_val, false_val).assume_init() + } } diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index e5604d277f57..a01efb2adebe 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -1327,6 +1327,8 @@ pub const fn unlikely(b: bool) -> bool { /// any safety invariants. /// /// The public form of this instrinsic is [`core::hint::select_unpredictable`]. +/// However unlike the public form, the intrinsic will not drop the value that +/// is not selected. #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic] #[rustc_nounwind] diff --git a/library/coretests/tests/hint.rs b/library/coretests/tests/hint.rs new file mode 100644 index 000000000000..032bbc1dcc80 --- /dev/null +++ b/library/coretests/tests/hint.rs @@ -0,0 +1,23 @@ +#[test] +fn select_unpredictable_drop() { + use core::cell::Cell; + struct X<'a>(&'a Cell); + impl Drop for X<'_> { + fn drop(&mut self) { + self.0.set(true); + } + } + + let a_dropped = Cell::new(false); + let b_dropped = Cell::new(false); + let a = X(&a_dropped); + let b = X(&b_dropped); + assert!(!a_dropped.get()); + assert!(!b_dropped.get()); + let selected = core::hint::select_unpredictable(core::hint::black_box(true), a, b); + assert!(!a_dropped.get()); + assert!(b_dropped.get()); + drop(selected); + assert!(a_dropped.get()); + assert!(b_dropped.get()); +} diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index 7ad154796f64..1c43bfe0ed4a 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -68,6 +68,7 @@ #![feature(pointer_is_aligned_to)] #![feature(portable_simd)] #![feature(ptr_metadata)] +#![feature(select_unpredictable)] #![feature(slice_from_ptr_range)] #![feature(slice_internals)] #![feature(slice_partition_dedup)] @@ -147,6 +148,7 @@ mod ffi; mod fmt; mod future; mod hash; +mod hint; mod intrinsics; mod io; mod iter; From 7d6f41b08e730572b196d6c588364973bb3cb12b Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Wed, 16 Apr 2025 18:27:58 +0000 Subject: [PATCH 597/606] Update `compiler-builtins` to 0.1.155 Includes the following changes: * Replace `#[naked]` with `#[unsafe(naked)]` [1] [2] * Replace `bl!` with `asm_sym` [3] [1]: https://github.com/rust-lang/compiler-builtins/pull/817 [2]: https://github.com/rust-lang/compiler-builtins/pull/821 [3]: https://github.com/rust-lang/compiler-builtins/pull/820 --- library/Cargo.lock | 4 ++-- library/alloc/Cargo.toml | 2 +- library/std/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/library/Cargo.lock b/library/Cargo.lock index 29e0e134da7f..e4f1c4ec96a3 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -67,9 +67,9 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.153" +version = "0.1.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "926ef6a360c15a911023352fd6969c51605d70495406f735beb1ca0257448e59" +checksum = "341e0830ca6170a4fcf02e92e57daf4b6f10142d48da32a547023867a6c8b35e" dependencies = [ "cc", "rustc-std-workspace-core", diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml index ee8cb9d25a39..cedbd330cbde 100644 --- a/library/alloc/Cargo.toml +++ b/library/alloc/Cargo.toml @@ -16,7 +16,7 @@ bench = false [dependencies] core = { path = "../core", public = true } -compiler_builtins = { version = "=0.1.153", features = ['rustc-dep-of-std'] } +compiler_builtins = { version = "=0.1.155", features = ['rustc-dep-of-std'] } [features] compiler-builtins-mem = ['compiler_builtins/mem'] diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 6b70ff764d7a..917a470842ca 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -18,7 +18,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] } panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core", public = true } -compiler_builtins = { version = "=0.1.153" } +compiler_builtins = { version = "=0.1.155" } unwind = { path = "../unwind" } hashbrown = { version = "0.15", default-features = false, features = [ 'rustc-dep-of-std', From d3b167493efcfa154640ece0da1b3a9b869d743e Mon Sep 17 00:00:00 2001 From: Augie Fackler Date: Thu, 17 Apr 2025 15:11:21 -0400 Subject: [PATCH 598/606] tests: adjust 101082 test for LLVM 21 fix Fixes #139987. --- tests/codegen/issues/issue-101082.rs | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/tests/codegen/issues/issue-101082.rs b/tests/codegen/issues/issue-101082.rs index 96cdff64dda6..8d15921ddb4e 100644 --- a/tests/codegen/issues/issue-101082.rs +++ b/tests/codegen/issues/issue-101082.rs @@ -12,6 +12,7 @@ // at the time still sometimes fails, so only verify it for the power-of-two size // - https://github.com/llvm/llvm-project/issues/134735 //@[x86-64-v3] only-x86_64 +//@[x86-64-v3] min-llvm-version: 21 //@[x86-64-v3] compile-flags: -Ctarget-cpu=x86-64-v3 #![crate_type = "lib"] @@ -19,16 +20,7 @@ #[no_mangle] pub fn test() -> usize { // CHECK-LABEL: @test( - // host: ret {{i64|i32}} 165 - // x86-64: ret {{i64|i32}} 165 - - // FIXME: Now that this autovectorizes via a masked load, it doesn't actually - // const-fold for certain widths. The `test_eight` case below shows that, yes, - // what we're emitting *can* be const-folded, except that the way LLVM does it - // for certain widths doesn't today. We should be able to put this back to - // the same check after - // x86-64-v3: masked.load - + // CHECK: ret {{i64|i32}} 165 let values = [23, 16, 54, 3, 60, 9]; let mut acc = 0; for item in values { From 5523c87c41b357fe3c3047dabf603f18830eeaf8 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Thu, 17 Apr 2025 21:16:58 +0200 Subject: [PATCH 599/606] Update libcore.natvis for Pin. --- src/etc/natvis/libcore.natvis | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/etc/natvis/libcore.natvis b/src/etc/natvis/libcore.natvis index 8a441cf20935..8fe87a999895 100644 --- a/src/etc/natvis/libcore.natvis +++ b/src/etc/natvis/libcore.natvis @@ -69,9 +69,9 @@ - Pin({(void*)__pointer}: {__pointer}) + Pin({(void*)pointer}: {pointer}) - __pointer + pointer From b8c043f07e71dbc1c8ba6b3b565f9ff211992bf9 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 17 Apr 2025 21:37:03 +0200 Subject: [PATCH 600/606] remove stray file --- diff | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 diff diff --git a/diff b/diff deleted file mode 100644 index e69de29bb2d1..000000000000 From 65b87aae21096c0f22d141ceaf7030ebdf6edbe4 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 17 Apr 2025 15:05:06 -0400 Subject: [PATCH 601/606] Support new target builtins --- src/intrinsic/llvm.rs | 245 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 244 insertions(+), 1 deletion(-) diff --git a/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index 2b172cdfed3a..e030e3b4ff28 100644 --- a/src/intrinsic/llvm.rs +++ b/src/intrinsic/llvm.rs @@ -1,11 +1,86 @@ use std::borrow::Cow; -use gccjit::{CType, Context, Function, FunctionPtrType, RValue, ToRValue}; +use gccjit::{CType, Context, Field, Function, FunctionPtrType, RValue, ToRValue, Type}; use rustc_codegen_ssa::traits::BuilderMethods; use crate::builder::Builder; use crate::context::CodegenCx; +fn encode_key_128_type<'a, 'gcc, 'tcx>( + builder: &Builder<'a, 'gcc, 'tcx>, +) -> (Type<'gcc>, Field<'gcc>, Field<'gcc>) { + let m128i = builder.context.new_vector_type(builder.i64_type, 2); + let field1 = builder.context.new_field(None, builder.u32_type, "field1"); + let field2 = builder.context.new_field(None, m128i, "field2"); + let field3 = builder.context.new_field(None, m128i, "field3"); + let field4 = builder.context.new_field(None, m128i, "field4"); + let field5 = builder.context.new_field(None, m128i, "field5"); + let field6 = builder.context.new_field(None, m128i, "field6"); + let field7 = builder.context.new_field(None, m128i, "field7"); + let encode_type = builder.context.new_struct_type( + None, + "EncodeKey128Output", + &[field1, field2, field3, field4, field5, field6, field7], + ); + encode_type.as_type().set_packed(); + (encode_type.as_type(), field1, field2) +} + +fn encode_key_256_type<'a, 'gcc, 'tcx>( + builder: &Builder<'a, 'gcc, 'tcx>, +) -> (Type<'gcc>, Field<'gcc>, Field<'gcc>) { + let m128i = builder.context.new_vector_type(builder.i64_type, 2); + let field1 = builder.context.new_field(None, builder.u32_type, "field1"); + let field2 = builder.context.new_field(None, m128i, "field2"); + let field3 = builder.context.new_field(None, m128i, "field3"); + let field4 = builder.context.new_field(None, m128i, "field4"); + let field5 = builder.context.new_field(None, m128i, "field5"); + let field6 = builder.context.new_field(None, m128i, "field6"); + let field7 = builder.context.new_field(None, m128i, "field7"); + let field8 = builder.context.new_field(None, m128i, "field8"); + let encode_type = builder.context.new_struct_type( + None, + "EncodeKey256Output", + &[field1, field2, field3, field4, field5, field6, field7, field8], + ); + encode_type.as_type().set_packed(); + (encode_type.as_type(), field1, field2) +} + +fn aes_output_type<'a, 'gcc, 'tcx>( + builder: &Builder<'a, 'gcc, 'tcx>, +) -> (Type<'gcc>, Field<'gcc>, Field<'gcc>) { + let m128i = builder.context.new_vector_type(builder.i64_type, 2); + let field1 = builder.context.new_field(None, builder.u8_type, "field1"); + let field2 = builder.context.new_field(None, m128i, "field2"); + let aes_output_type = builder.context.new_struct_type(None, "AesOutput", &[field1, field2]); + let typ = aes_output_type.as_type(); + typ.set_packed(); + (typ, field1, field2) +} + +fn wide_aes_output_type<'a, 'gcc, 'tcx>( + builder: &Builder<'a, 'gcc, 'tcx>, +) -> (Type<'gcc>, Field<'gcc>, Field<'gcc>) { + let m128i = builder.context.new_vector_type(builder.i64_type, 2); + let field1 = builder.context.new_field(None, builder.u8_type, "field1"); + let field2 = builder.context.new_field(None, m128i, "field2"); + let field3 = builder.context.new_field(None, m128i, "field3"); + let field4 = builder.context.new_field(None, m128i, "field4"); + let field5 = builder.context.new_field(None, m128i, "field5"); + let field6 = builder.context.new_field(None, m128i, "field6"); + let field7 = builder.context.new_field(None, m128i, "field7"); + let field8 = builder.context.new_field(None, m128i, "field8"); + let field9 = builder.context.new_field(None, m128i, "field9"); + let aes_output_type = builder.context.new_struct_type( + None, + "WideAesOutput", + &[field1, field2, field3, field4, field5, field6, field7, field8, field9], + ); + aes_output_type.as_type().set_packed(); + (aes_output_type.as_type(), field1, field2) +} + #[cfg_attr(not(feature = "master"), allow(unused_variables))] pub fn adjust_function<'gcc>( context: &'gcc Context<'gcc>, @@ -503,6 +578,74 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>( let arg4 = builder.context.new_rvalue_from_int(arg4_type, -1); args = vec![a, b, c, arg4, new_args[3]].into(); } + "__builtin_ia32_encodekey128_u32" => { + let mut new_args = args.to_vec(); + let m128i = builder.context.new_vector_type(builder.i64_type, 2); + let array_type = builder.context.new_array_type(None, m128i, 6); + let result = builder.current_func().new_local(None, array_type, "result"); + new_args.push(result.get_address(None)); + args = new_args.into(); + } + "__builtin_ia32_encodekey256_u32" => { + let mut new_args = args.to_vec(); + let m128i = builder.context.new_vector_type(builder.i64_type, 2); + let array_type = builder.context.new_array_type(None, m128i, 7); + let result = builder.current_func().new_local(None, array_type, "result"); + new_args.push(result.get_address(None)); + args = new_args.into(); + } + "__builtin_ia32_aesenc128kl_u8" + | "__builtin_ia32_aesdec128kl_u8" + | "__builtin_ia32_aesenc256kl_u8" + | "__builtin_ia32_aesdec256kl_u8" => { + let mut new_args = vec![]; + // TODO: directly create a variable of type m128i instead of the whole struct? + let (aes_output_type, _, field2) = aes_output_type(builder); + let result = builder.current_func().new_local(None, aes_output_type, "result"); + let field2 = result.access_field(None, field2); + new_args.push(field2.get_address(None)); + new_args.extend(args.to_vec()); + args = new_args.into(); + } + "__builtin_ia32_aesencwide128kl_u8" + | "__builtin_ia32_aesdecwide128kl_u8" + | "__builtin_ia32_aesencwide256kl_u8" + | "__builtin_ia32_aesdecwide256kl_u8" => { + let mut new_args = vec![]; + + let mut old_args = args.to_vec(); + let handle = old_args.swap_remove(0); // Called __P in GCC. + let first_value = old_args.swap_remove(0); + + let element_type = first_value.get_type(); + let array_type = builder.context.new_array_type(None, element_type, 8); + let result = builder.current_func().new_local(None, array_type, "result"); + new_args.push(result.get_address(None)); + + let array = builder.current_func().new_local(None, array_type, "array"); + let input = builder.context.new_array_constructor( + None, + array_type, + &[ + first_value, + old_args.swap_remove(0), + old_args.swap_remove(0), + old_args.swap_remove(0), + old_args.swap_remove(0), + old_args.swap_remove(0), + old_args.swap_remove(0), + old_args.swap_remove(0), + ], + ); + builder.llbb().add_assignment(None, array, input); + let input_ptr = array.get_address(None); + let arg2_type = gcc_func.get_param_type(1); + let input_ptr = builder.context.new_cast(None, input_ptr, arg2_type); + new_args.push(input_ptr); + + new_args.push(handle); + args = new_args.into(); + } _ => (), } } else { @@ -700,6 +843,96 @@ pub fn adjust_intrinsic_return_value<'a, 'gcc, 'tcx>( let f16_type = builder.context.new_c_type(CType::Float16); return_value = builder.context.new_cast(None, return_value, f16_type); } + "__builtin_ia32_encodekey128_u32" => { + // The builtin __builtin_ia32_encodekey128_u32 writes the result in its pointer argument while + // llvm.x86.encodekey128 returns a value. + // We added a result pointer argument and now need to assign its value to the return_value expected by + // the LLVM intrinsic. + let (encode_type, field1, field2) = encode_key_128_type(builder); + let result = builder.current_func().new_local(None, encode_type, "result"); + let field1 = result.access_field(None, field1); + builder.llbb().add_assignment(None, field1, return_value); + let field2 = result.access_field(None, field2); + let field2_type = field2.to_rvalue().get_type(); + let array_type = builder.context.new_array_type(None, field2_type, 6); + let ptr = builder.context.new_cast(None, args[2], array_type.make_pointer()); + let field2_ptr = + builder.context.new_cast(None, field2.get_address(None), array_type.make_pointer()); + builder.llbb().add_assignment( + None, + field2_ptr.dereference(None), + ptr.dereference(None), + ); + return_value = result.to_rvalue(); + } + "__builtin_ia32_encodekey256_u32" => { + // The builtin __builtin_ia32_encodekey256_u32 writes the result in its pointer argument while + // llvm.x86.encodekey256 returns a value. + // We added a result pointer argument and now need to assign its value to the return_value expected by + // the LLVM intrinsic. + let (encode_type, field1, field2) = encode_key_256_type(builder); + let result = builder.current_func().new_local(None, encode_type, "result"); + let field1 = result.access_field(None, field1); + builder.llbb().add_assignment(None, field1, return_value); + let field2 = result.access_field(None, field2); + let field2_type = field2.to_rvalue().get_type(); + let array_type = builder.context.new_array_type(None, field2_type, 7); + let ptr = builder.context.new_cast(None, args[3], array_type.make_pointer()); + let field2_ptr = + builder.context.new_cast(None, field2.get_address(None), array_type.make_pointer()); + builder.llbb().add_assignment( + None, + field2_ptr.dereference(None), + ptr.dereference(None), + ); + return_value = result.to_rvalue(); + } + "__builtin_ia32_aesdec128kl_u8" + | "__builtin_ia32_aesenc128kl_u8" + | "__builtin_ia32_aesdec256kl_u8" + | "__builtin_ia32_aesenc256kl_u8" => { + // The builtin for aesdec/aesenc writes the result in its pointer argument while + // llvm.x86.aesdec128kl returns a value. + // We added a result pointer argument and now need to assign its value to the return_value expected by + // the LLVM intrinsic. + let (aes_output_type, field1, field2) = aes_output_type(builder); + let result = builder.current_func().new_local(None, aes_output_type, "result"); + let field1 = result.access_field(None, field1); + builder.llbb().add_assignment(None, field1, return_value); + let field2 = result.access_field(None, field2); + let ptr = builder.context.new_cast( + None, + args[0], + field2.to_rvalue().get_type().make_pointer(), + ); + builder.llbb().add_assignment(None, field2, ptr.dereference(None)); + return_value = result.to_rvalue(); + } + "__builtin_ia32_aesencwide128kl_u8" + | "__builtin_ia32_aesdecwide128kl_u8" + | "__builtin_ia32_aesencwide256kl_u8" + | "__builtin_ia32_aesdecwide256kl_u8" => { + // The builtin for aesdecwide/aesencwide writes the result in its pointer argument while + // llvm.x86.aesencwide128kl returns a value. + // We added a result pointer argument and now need to assign its value to the return_value expected by + // the LLVM intrinsic. + let (aes_output_type, field1, field2) = wide_aes_output_type(builder); + let result = builder.current_func().new_local(None, aes_output_type, "result"); + let field1 = result.access_field(None, field1); + builder.llbb().add_assignment(None, field1, return_value); + let field2 = result.access_field(None, field2); + let field2_type = field2.to_rvalue().get_type(); + let array_type = builder.context.new_array_type(None, field2_type, 8); + let ptr = builder.context.new_cast(None, args[0], array_type.make_pointer()); + let field2_ptr = + builder.context.new_cast(None, field2.get_address(None), array_type.make_pointer()); + builder.llbb().add_assignment( + None, + field2_ptr.dereference(None), + ptr.dereference(None), + ); + return_value = result.to_rvalue(); + } _ => (), } @@ -1284,6 +1517,16 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function "llvm.x86.avx512fp16.mask.vfmadd.cph.256" => "__builtin_ia32_vfmaddcph256_mask3", "llvm.x86.avx512fp16.mask.vfcmadd.cph.128" => "__builtin_ia32_vfcmaddcph128_mask3", "llvm.x86.avx512fp16.mask.vfmadd.cph.128" => "__builtin_ia32_vfmaddcph128_mask3", + "llvm.x86.encodekey128" => "__builtin_ia32_encodekey128_u32", + "llvm.x86.encodekey256" => "__builtin_ia32_encodekey256_u32", + "llvm.x86.aesenc128kl" => "__builtin_ia32_aesenc128kl_u8", + "llvm.x86.aesdec128kl" => "__builtin_ia32_aesdec128kl_u8", + "llvm.x86.aesenc256kl" => "__builtin_ia32_aesenc256kl_u8", + "llvm.x86.aesdec256kl" => "__builtin_ia32_aesdec256kl_u8", + "llvm.x86.aesencwide128kl" => "__builtin_ia32_aesencwide128kl_u8", + "llvm.x86.aesdecwide128kl" => "__builtin_ia32_aesdecwide128kl_u8", + "llvm.x86.aesencwide256kl" => "__builtin_ia32_aesencwide256kl_u8", + "llvm.x86.aesdecwide256kl" => "__builtin_ia32_aesdecwide256kl_u8", // TODO: support the tile builtins: "llvm.x86.ldtilecfg" => "__builtin_trap", From 98dd5a30b32c1311d5a44ebb2c0667a8ff0ef76a Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 18 Apr 2025 11:45:30 -0400 Subject: [PATCH 602/606] Fix for libgccjit 12 --- src/intrinsic/llvm.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index e030e3b4ff28..befb2e17960c 100644 --- a/src/intrinsic/llvm.rs +++ b/src/intrinsic/llvm.rs @@ -22,6 +22,7 @@ fn encode_key_128_type<'a, 'gcc, 'tcx>( "EncodeKey128Output", &[field1, field2, field3, field4, field5, field6, field7], ); + #[cfg(feature = "master")] encode_type.as_type().set_packed(); (encode_type.as_type(), field1, field2) } @@ -43,6 +44,7 @@ fn encode_key_256_type<'a, 'gcc, 'tcx>( "EncodeKey256Output", &[field1, field2, field3, field4, field5, field6, field7, field8], ); + #[cfg(feature = "master")] encode_type.as_type().set_packed(); (encode_type.as_type(), field1, field2) } @@ -55,6 +57,7 @@ fn aes_output_type<'a, 'gcc, 'tcx>( let field2 = builder.context.new_field(None, m128i, "field2"); let aes_output_type = builder.context.new_struct_type(None, "AesOutput", &[field1, field2]); let typ = aes_output_type.as_type(); + #[cfg(feature = "master")] typ.set_packed(); (typ, field1, field2) } @@ -77,6 +80,7 @@ fn wide_aes_output_type<'a, 'gcc, 'tcx>( "WideAesOutput", &[field1, field2, field3, field4, field5, field6, field7, field8, field9], ); + #[cfg(feature = "master")] aes_output_type.as_type().set_packed(); (aes_output_type.as_type(), field1, field2) } From 52b06872fe92811e5ae5d87bbb3508924525723b Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 18 Apr 2025 12:07:10 -0400 Subject: [PATCH 603/606] Simplify handling of some SIMD intrinsics --- src/intrinsic/llvm.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index befb2e17960c..0eebd21001a9 100644 --- a/src/intrinsic/llvm.rs +++ b/src/intrinsic/llvm.rs @@ -603,11 +603,9 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>( | "__builtin_ia32_aesenc256kl_u8" | "__builtin_ia32_aesdec256kl_u8" => { let mut new_args = vec![]; - // TODO: directly create a variable of type m128i instead of the whole struct? - let (aes_output_type, _, field2) = aes_output_type(builder); - let result = builder.current_func().new_local(None, aes_output_type, "result"); - let field2 = result.access_field(None, field2); - new_args.push(field2.get_address(None)); + let m128i = builder.context.new_vector_type(builder.i64_type, 2); + let result = builder.current_func().new_local(None, m128i, "result"); + new_args.push(result.get_address(None)); new_args.extend(args.to_vec()); args = new_args.into(); } From c123dc63ea5f765488e4d56aa55bf4467fce7d27 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 18 Apr 2025 21:21:15 +0200 Subject: [PATCH 604/606] Fix `rustc_codegen_gcc/tests/run/return-tuple.rs` test --- compiler/rustc_codegen_gcc/tests/run/return-tuple.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/compiler/rustc_codegen_gcc/tests/run/return-tuple.rs b/compiler/rustc_codegen_gcc/tests/run/return-tuple.rs index c6e1ba7ce394..c1254c51ce91 100644 --- a/compiler/rustc_codegen_gcc/tests/run/return-tuple.rs +++ b/compiler/rustc_codegen_gcc/tests/run/return-tuple.rs @@ -6,13 +6,7 @@ // 10 // 42 -<<<<<<< HEAD -#![feature(auto_traits, lang_items, no_core, intrinsics)] -#![allow(internal_features)] - -======= #![feature(no_core)] ->>>>>>> db1a31c243a649e1fe20f5466ba181da5be35c14 #![no_std] #![no_core] #![no_main] From 84f582665ef64467e2ca8f65448f75f14b12edf5 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 18 Apr 2025 22:46:43 +0200 Subject: [PATCH 605/606] Fix compilation error in GCC backend --- compiler/rustc_codegen_gcc/src/int.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_gcc/src/int.rs b/compiler/rustc_codegen_gcc/src/int.rs index 906d7eaceb6b..9b5b0fde6e2f 100644 --- a/compiler/rustc_codegen_gcc/src/int.rs +++ b/compiler/rustc_codegen_gcc/src/int.rs @@ -404,7 +404,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let ret_indirect = matches!(fn_abi.ret.mode, PassMode::Indirect { .. }); - let result = if ret_indirect { + let call = if ret_indirect { let res_value = self.current_func().new_local(self.location, res_type, "result_value"); let res_addr = res_value.get_address(self.location); let res_param_type = res_type.make_pointer(); From cc359b8bb6c693086f69adf013430163992b1807 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 18 Apr 2025 23:02:07 +0200 Subject: [PATCH 606/606] Fix import --- compiler/rustc_codegen_gcc/src/abi.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_gcc/src/abi.rs b/compiler/rustc_codegen_gcc/src/abi.rs index 890a25e6a7ca..a96b18e01c08 100644 --- a/compiler/rustc_codegen_gcc/src/abi.rs +++ b/compiler/rustc_codegen_gcc/src/abi.rs @@ -10,7 +10,8 @@ use rustc_middle::ty::layout::LayoutOf; #[cfg(feature = "master")] use rustc_session::config; #[cfg(feature = "master")] -use rustc_target::callconv::{ArgAttributes, CastTarget, Conv, FnAbi, PassMode}; +use rustc_target::callconv::Conv; +use rustc_target::callconv::{ArgAttributes, CastTarget, FnAbi, PassMode}; use crate::builder::Builder; use crate::context::CodegenCx;