From f7548dd67188ff4f71059fa266b4319ddbade1e1 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Wed, 12 Aug 2026 21:25:35 -0400 Subject: [PATCH 01/20] Stabilize `funnel_shifts` (including `const`) `funnel_shl` and `funnel_shr` have been around for close to a year, the unchecked versions for a number of months. These are reasonably small and uncontroversial, and it can be tricky to get similar performance with a fallback; stabilize them here. Newly stable API: impl {u8, u16, u32, u64, u128, usize} { pub const fn funnel_shl(self, right: Self, shift: u32) -> Self; pub const fn funnel_shr(self, right: Self, shift: u32) -> Self; pub const unsafe fn unchecked_funnel_shl(self, right: Self, shift: u32) -> Self; pub const unsafe fn unchecked_funnel_shr(self, right: Self, shift: u32) -> Self; } The tracking issue also mentions a `wrapping_` version but it has not been implemented. Tracking issue: RUST-145686 --- library/core/src/intrinsics/mod.rs | 12 ++++----- library/core/src/lib.rs | 1 - library/core/src/num/uint_macros.rs | 26 +++++++------------ library/coretests/tests/lib.rs | 1 - library/std/src/lib.rs | 1 - library/stdarch/crates/core_arch/src/lib.rs | 1 - .../miri/tests/fail/intrinsics/funnel_shl.rs | 2 +- .../miri/tests/fail/intrinsics/funnel_shr.rs | 2 +- .../miri/tests/pass/intrinsics/integer.rs | 2 +- .../codegen-llvm/force-intrinsic-fallback.rs | 2 +- tests/ui/std/overflow-check-ops.rs | 1 - 11 files changed, 20 insertions(+), 31 deletions(-) diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 673454abaf04f..305bab8ec27e0 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -2211,7 +2211,7 @@ pub const unsafe fn unchecked_mul(x: T, y: T) -> T; #[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] -#[rustc_allow_const_fn_unstable(const_trait_impl, funnel_shifts)] +#[rustc_allow_const_fn_unstable(const_trait_impl)] #[miri::intrinsic_fallback_is_spec] pub const fn rotate_left(x: T, shift: u32) -> T { // Make sure to call the intrinsic for `funnel_shl`, not the fallback impl. @@ -2233,7 +2233,7 @@ pub const fn rotate_left(x: T, shift: u32) -> #[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] -#[rustc_allow_const_fn_unstable(const_trait_impl, funnel_shifts)] +#[rustc_allow_const_fn_unstable(const_trait_impl)] #[miri::intrinsic_fallback_is_spec] pub const fn rotate_right(x: T, shift: u32) -> T { // Make sure to call the intrinsic for `funnel_shr`, not the fallback impl. @@ -2329,11 +2329,11 @@ pub const fn saturating_sub(a: T, b: T) -> T; /// /// Safe versions of this intrinsic are available on the integer primitives /// via the `funnel_shl` method. For example, [`u32::funnel_shl`]. +#[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_nounwind] -#[rustc_const_unstable(feature = "funnel_shifts", issue = "145686")] -#[unstable(feature = "funnel_shifts", issue = "145686")] #[track_caller] +#[rustc_allow_const_fn_unstable(const_trait_impl, core_intrinsics_fallbacks)] #[miri::intrinsic_fallback_is_spec] pub const unsafe fn unchecked_funnel_shl( a: T, @@ -2357,11 +2357,11 @@ pub const unsafe fn unchecked_funnel_shl( /// /// Safer versions of this intrinsic are available on the integer primitives /// via the `funnel_shr` method. For example, [`u32::funnel_shr`] +#[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_nounwind] -#[rustc_const_unstable(feature = "funnel_shifts", issue = "145686")] -#[unstable(feature = "funnel_shifts", issue = "145686")] #[track_caller] +#[rustc_allow_const_fn_unstable(const_trait_impl, core_intrinsics_fallbacks)] #[miri::intrinsic_fallback_is_spec] pub const unsafe fn unchecked_funnel_shr( a: T, diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 4fbd3c6dc2142..b047657cf10de 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -131,7 +131,6 @@ #![feature(final_associated_functions)] #![feature(freeze_impls)] #![feature(fundamental)] -#![feature(funnel_shifts)] #![feature(impl_restriction)] #![feature(intra_doc_pointers)] #![feature(intrinsics)] diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index a98ef99b9d7bb..2f9de03adced8 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -526,8 +526,6 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(funnel_shifts)] - /// #[doc = concat!("let a = ", $rot_op, "_", stringify!($SelfT), ";")] #[doc = concat!("let b = ", $fsh_op, "_", stringify!($SelfT), ";")] /// @@ -547,10 +545,8 @@ macro_rules! uint_impl { /// rotating by an unbounded amount like [`rotate_left`](Self::rotate_left) does: /// /// ```should_panic - /// #![feature(funnel_shifts)] /// # #![feature(cfg_overflow_checks)] /// # #[cfg(overflow_checks)] { - /// #[doc = concat!("let a = ", stringify!($SelfT), "::MAX;")] /// // Okay #[doc = concat!("let _ = a.rotate_left(", stringify!($SelfT), "::BITS);")] @@ -559,8 +555,8 @@ macro_rules! uint_impl { /// # } /// # #[cfg(not(overflow_checks))] panic!("fulfill should_panic"); /// ``` - #[rustc_const_unstable(feature = "funnel_shifts", issue = "145686")] - #[unstable(feature = "funnel_shifts", issue = "145686")] + #[rustc_const_stable(feature = "funnel_shifts", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "funnel_shifts", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, without modifying the original"] #[inline(always)] #[rustc_inherit_overflow_checks] @@ -597,8 +593,6 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(funnel_shifts)] - /// #[doc = concat!("let a = ", $rot_op, "_", stringify!($SelfT), ";")] #[doc = concat!("let b = ", $fsh_op, "_", stringify!($SelfT), ";")] /// @@ -618,10 +612,8 @@ macro_rules! uint_impl { /// rotating by an unbounded amount like [`rotate_right`](Self::rotate_right) does: /// /// ```should_panic - /// #![feature(funnel_shifts)] /// # #![feature(cfg_overflow_checks)] /// # #[cfg(overflow_checks)] { - /// #[doc = concat!("let a = ", stringify!($SelfT), "::MAX;")] /// // Okay #[doc = concat!("let _ = a.rotate_right(", stringify!($SelfT), "::BITS);")] @@ -630,8 +622,8 @@ macro_rules! uint_impl { /// # } /// # #[cfg(not(overflow_checks))] panic!("fulfill should_panic"); /// ``` - #[rustc_const_unstable(feature = "funnel_shifts", issue = "145686")] - #[unstable(feature = "funnel_shifts", issue = "145686")] + #[rustc_const_stable(feature = "funnel_shifts", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "funnel_shifts", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, without modifying the original"] #[inline(always)] #[rustc_inherit_overflow_checks] @@ -654,8 +646,9 @@ macro_rules! uint_impl { #[doc = concat!("`", stringify!($SelfT) , "::BITS`,")] /// i.e. when [`funnel_shl`](Self::funnel_shl) would panic. /// - #[rustc_const_unstable(feature = "funnel_shifts", issue = "145686")] - #[unstable(feature = "funnel_shifts", issue = "145686")] + #[rustc_const_stable(feature = "funnel_shifts", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "funnel_shifts", since = "CURRENT_RUSTC_VERSION")] + #[rustc_allow_const_fn_unstable(const_trait_impl)] #[must_use = "this returns the result of the operation, without modifying the original"] #[inline(always)] #[track_caller] @@ -680,8 +673,9 @@ macro_rules! uint_impl { #[doc = concat!("`", stringify!($SelfT) , "::BITS`,")] /// i.e. when [`funnel_shr`](Self::funnel_shr) would panic. /// - #[rustc_const_unstable(feature = "funnel_shifts", issue = "145686")] - #[unstable(feature = "funnel_shifts", issue = "145686")] + #[rustc_const_stable(feature = "funnel_shifts", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "funnel_shifts", since = "CURRENT_RUSTC_VERSION")] + #[rustc_allow_const_fn_unstable(const_trait_impl)] #[must_use = "this returns the result of the operation, without modifying the original"] #[inline(always)] #[track_caller] diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index c993c947929cd..116e1eb48d260 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -63,7 +63,6 @@ #![feature(fmt_internals)] #![feature(formatting_options)] #![feature(freeze)] -#![feature(funnel_shifts)] #![feature(future_join)] #![feature(generic_assert_internals)] #![feature(hasher_prefixfree_extras)] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 92eccc27ee05d..921a1ff49511c 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -349,7 +349,6 @@ #![feature(fmt_internals)] #![feature(fn_static)] #![feature(formatting_options)] -#![feature(funnel_shifts)] #![feature(generic_atomic)] #![feature(hash_map_internals)] #![feature(hash_map_macro)] diff --git a/library/stdarch/crates/core_arch/src/lib.rs b/library/stdarch/crates/core_arch/src/lib.rs index 57eca221e1aba..2cb4c43d760e4 100644 --- a/library/stdarch/crates/core_arch/src/lib.rs +++ b/library/stdarch/crates/core_arch/src/lib.rs @@ -33,7 +33,6 @@ x86_amx_intrinsics, f16, aarch64_unstable_target_feature, - funnel_shifts, avx10_target_feature, const_trait_impl, const_cmp, diff --git a/src/tools/miri/tests/fail/intrinsics/funnel_shl.rs b/src/tools/miri/tests/fail/intrinsics/funnel_shl.rs index 40b61f65ebe88..b64f4551fd605 100644 --- a/src/tools/miri/tests/fail/intrinsics/funnel_shl.rs +++ b/src/tools/miri/tests/fail/intrinsics/funnel_shl.rs @@ -1,4 +1,4 @@ -#![feature(core_intrinsics, funnel_shifts)] +#![feature(core_intrinsics)] fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/funnel_shr.rs b/src/tools/miri/tests/fail/intrinsics/funnel_shr.rs index 9582265639716..922144d6d6042 100644 --- a/src/tools/miri/tests/fail/intrinsics/funnel_shr.rs +++ b/src/tools/miri/tests/fail/intrinsics/funnel_shr.rs @@ -1,4 +1,4 @@ -#![feature(core_intrinsics, funnel_shifts)] +#![feature(core_intrinsics)] fn main() { unsafe { diff --git a/src/tools/miri/tests/pass/intrinsics/integer.rs b/src/tools/miri/tests/pass/intrinsics/integer.rs index 555a85147ee5f..2260068704adf 100644 --- a/src/tools/miri/tests/pass/intrinsics/integer.rs +++ b/src/tools/miri/tests/pass/intrinsics/integer.rs @@ -1,5 +1,5 @@ //@run-native -#![feature(core_intrinsics, funnel_shifts)] +#![feature(core_intrinsics)] use std::intrinsics::*; fn main() { diff --git a/tests/codegen-llvm/force-intrinsic-fallback.rs b/tests/codegen-llvm/force-intrinsic-fallback.rs index 1fb80b4e83f12..3a934b27f828e 100644 --- a/tests/codegen-llvm/force-intrinsic-fallback.rs +++ b/tests/codegen-llvm/force-intrinsic-fallback.rs @@ -2,7 +2,7 @@ // //@ revisions: NORMAL FALLBACK //@ [FALLBACK] compile-flags: -Zforce-intrinsic-fallback -#![feature(core_intrinsics, funnel_shifts)] +#![feature(core_intrinsics)] // Check the effect of `-Zforce-intrinsic-fallback`. // diff --git a/tests/ui/std/overflow-check-ops.rs b/tests/ui/std/overflow-check-ops.rs index 458c1b121664e..57db92610b20a 100644 --- a/tests/ui/std/overflow-check-ops.rs +++ b/tests/ui/std/overflow-check-ops.rs @@ -7,7 +7,6 @@ //@[WRAP] compile-flags: -C overflow-checks=false #![feature(cfg_overflow_checks)] -#![feature(funnel_shifts)] use std::hint::black_box as bb; use std::{assert_matches, fmt, panic}; From 1bd00d4f7277abbcdaa62382aff4e314869d8b28 Mon Sep 17 00:00:00 2001 From: Jakob Koschel Date: Tue, 1 Sep 2026 14:36:21 +0000 Subject: [PATCH 02/20] Add support for -Zsanitizer-cfi-minimal-runtime For production use, we should only link in the ubsan_minimal runtime, instead of the complete ubsan runtime. This adds support for both cfi-recover and cfi-diag to use the minimal runtime when `-Zsanitizer-cfi-minimal-runtime` is specified. This also includes tests, to ensure the flag can only be used if either cfi-recover or cfi-diag is enabled, it doesn't disrupt the original behavior, and links in the correct runtime when specified. Co-Authored-By: Bastian Kersting --- compiler/rustc_codegen_llvm/src/builder.rs | 33 +++- compiler/rustc_codegen_ssa/src/back/link.rs | 6 +- compiler/rustc_session/src/diagnostics.rs | 6 + compiler/rustc_session/src/options.rs | 2 + compiler/rustc_session/src/session.rs | 11 ++ src/bootstrap/src/core/build_steps/llvm.rs | 14 +- .../cfi/emit-type-checks-diag-mode.rs | 5 +- .../cfi/emit-type-checks-recover-mode.rs | 5 +- .../run-make/sanitizer-cfi-runtime/program.rs | 17 ++ tests/run-make/sanitizer-cfi-runtime/rmake.rs | 171 ++++++++++++++++++ .../cfi/fn-ptr-type-mismatch-recover.rs | 38 ++++ .../ui/sanitizer/cfi/fn-ptr-type-mismatch.rs | 9 +- ...al-runtime-requires-cfi-recover-or-diag.rs | 11 ++ ...untime-requires-cfi-recover-or-diag.stderr | 4 + 14 files changed, 319 insertions(+), 13 deletions(-) create mode 100644 tests/run-make/sanitizer-cfi-runtime/program.rs create mode 100644 tests/run-make/sanitizer-cfi-runtime/rmake.rs create mode 100644 tests/ui/sanitizer/cfi/fn-ptr-type-mismatch-recover.rs create mode 100644 tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi-recover-or-diag.rs create mode 100644 tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi-recover-or-diag.stderr diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index abc71f450a515..438accb85f377 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -2065,17 +2065,31 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { let is_diag = self.tcx.sess.opts.unstable_opts.sanitizer_cfi_diag.unwrap_or(false); let is_recover = self.tcx.sess.opts.unstable_opts.sanitizer_cfi_recover.unwrap_or(false); + let is_minimal = + self.tcx.sess.opts.unstable_opts.sanitizer_cfi_minimal_runtime.unwrap_or(false); if is_diag || is_recover { - let fty = self.cx.type_func( - &[self.cx.type_ptr(), self.cx.type_isize(), self.cx.type_isize()], - self.cx.type_void(), - ); + let fty = if is_minimal { + self.cx.type_func(&[], self.cx.type_void()) + } else { + self.cx.type_func( + &[self.cx.type_ptr(), self.cx.type_isize(), self.cx.type_isize()], + self.cx.type_void(), + ) + }; let ubsan_handler = self.declare_cfn( if is_recover { - "__ubsan_handle_cfi_check_fail" + if is_minimal { + "__ubsan_handle_cfi_check_fail_minimal" + } else { + "__ubsan_handle_cfi_check_fail" + } } else { - "__ubsan_handle_cfi_check_fail_abort" + if is_minimal { + "__ubsan_handle_cfi_check_fail_minimal_abort" + } else { + "__ubsan_handle_cfi_check_fail_abort" + } }, llvm::UnnamedAddr::Global, fty, @@ -2101,13 +2115,18 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { self.generate_ubsan_cfi_diag_data(self.span, expected_ty, check_kind); let function_address = self.ptrtoint(llfn, self.cx.type_isize()); + let arguments: &[_] = if is_minimal { + &[] + } else { + &[diag_data, function_address, self.const_usize(0)] + }; self.call( fty, None, None, ubsan_handler, ReturnSlot::Direct, - &[diag_data, function_address, self.const_usize(0)], + arguments, None, None, ); diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index c283e464821e5..7c8bb4f59dfba 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1764,7 +1764,11 @@ fn add_sanitizer_libraries( && (sess.opts.unstable_opts.sanitizer_cfi_diag.unwrap_or(false) || sess.opts.unstable_opts.sanitizer_cfi_recover.unwrap_or(false)) { - link_sanitizer_runtime(sess, flavor, linker, "ubsan"); + if sess.opts.unstable_opts.sanitizer_cfi_minimal_runtime.unwrap_or(false) { + link_sanitizer_runtime(sess, flavor, linker, "ubsan_minimal"); + } else { + link_sanitizer_runtime(sess, flavor, linker, "ubsan"); + } } } diff --git a/compiler/rustc_session/src/diagnostics.rs b/compiler/rustc_session/src/diagnostics.rs index a2bf9a0d2dfc3..d27b616d7e359 100644 --- a/compiler/rustc_session/src/diagnostics.rs +++ b/compiler/rustc_session/src/diagnostics.rs @@ -340,6 +340,12 @@ pub(crate) struct SanitizerCfiRecoverRequiresCfi; #[diag("`-Zsanitizer-cfi-diag` requires `-Zsanitizer=cfi`")] pub(crate) struct SanitizerCfiDiagRequiresCfi; +#[derive(Diagnostic)] +#[diag( + "`-Zsanitizer-cfi-minimal-runtime` requires `-Zsanitizer-cfi-recover` or `-Zsanitizer-cfi-diag`" +)] +pub(crate) struct SanitizerCfiMinimalRuntimeRequiresCfiRecoverOrDiag; + #[derive(Diagnostic)] #[diag("`-Zsanitizer-kcfi-arity` requires `-Zsanitizer=kcfi`")] pub(crate) struct SanitizerKcfiArityRequiresKcfi; diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 13fc598d86bfa..f11bdadf5b67d 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2825,6 +2825,8 @@ written to standard error output)"), "enable CFI diagnostics (default: no)"), sanitizer_cfi_recover: Option = (None, parse_opt_bool, [TRACKED], "enable CFI recovery (default: no)"), + sanitizer_cfi_minimal_runtime: Option = (None, parse_opt_bool, [TRACKED], + "enable minimal UBSan runtime for CFI (default: no)"), sanitizer_dataflow_abilist: Vec = (Vec::new(), parse_comma_list, [TRACKED], "additional ABI list files that control how shadow parameters are passed (comma separated)"), sanitizer_kcfi_arity: Option = (None, parse_opt_bool, [TRACKED], diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 274cfe8d7eb8a..bf310270d0a19 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -746,6 +746,10 @@ impl Session { self.opts.unstable_opts.sanitizer_cfi_diag == Some(true) } + pub fn is_sanitizer_cfi_minimal_runtime_enabled(&self) -> bool { + self.opts.unstable_opts.sanitizer_cfi_minimal_runtime == Some(true) + } + pub fn is_sanitizer_kcfi_arity_enabled(&self) -> bool { self.opts.unstable_opts.sanitizer_kcfi_arity == Some(true) } @@ -1684,6 +1688,13 @@ fn validate_commandline_args_with_session_available(sess: &Session) { } } + // LLVM CFI minimal runtime requires CFI Recover or CFI Diag. + if sess.is_sanitizer_cfi_minimal_runtime_enabled() { + if !(sess.is_sanitizer_cfi_recover_enabled() || sess.is_sanitizer_cfi_diag_enabled()) { + sess.dcx().emit_err(diagnostics::SanitizerCfiMinimalRuntimeRequiresCfiRecoverOrDiag); + } + } + // LLVM CFI integer normalization requires CFI or KCFI. if sess.is_sanitizer_cfi_normalize_integers_enabled() { if !(sess.is_sanitizer_cfi_enabled() || sess.is_sanitizer_kcfi_enabled()) { diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index 096184ee9e5b4..2062461de4c2a 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -1903,7 +1903,7 @@ fn supported_sanitizers( "aarch64-unknown-linux-gnu" => common_libs( "linux", "aarch64", - &["asan", "lsan", "msan", "tsan", "hwasan", "rtsan", "ubsan"], + &["asan", "lsan", "msan", "tsan", "hwasan", "rtsan", "ubsan", "ubsan_minimal"], ), "aarch64-unknown-linux-ohos" => { common_libs("linux", "aarch64", &["asan", "lsan", "msan", "tsan", "hwasan"]) @@ -1924,7 +1924,17 @@ fn supported_sanitizers( "x86_64-unknown-linux-gnu" => common_libs( "linux", "x86_64", - &["asan", "dfsan", "lsan", "msan", "safestack", "tsan", "rtsan", "ubsan"], + &[ + "asan", + "dfsan", + "lsan", + "msan", + "safestack", + "tsan", + "rtsan", + "ubsan", + "ubsan_minimal", + ], ), "x86_64-unknown-linux-gnuasan" => common_libs("linux", "x86_64", &["asan"]), "x86_64-unknown-linux-gnumsan" => common_libs("linux", "x86_64", &["msan"]), diff --git a/tests/codegen-llvm/sanitizer/cfi/emit-type-checks-diag-mode.rs b/tests/codegen-llvm/sanitizer/cfi/emit-type-checks-diag-mode.rs index 07688a8e5cb0b..96cfb94289724 100644 --- a/tests/codegen-llvm/sanitizer/cfi/emit-type-checks-diag-mode.rs +++ b/tests/codegen-llvm/sanitizer/cfi/emit-type-checks-diag-mode.rs @@ -1,7 +1,9 @@ // Verifies that pointer type membership tests for indirect calls are emitted. // +//@ revisions: cfi-diag cfi-diag-minimal-runtime //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-diag=true -Copt-level=0 -C unsafe-allow-abi-mismatch=sanitizer +//@ [cfi-diag-minimal-runtime] compile-flags: -Zsanitizer-cfi-minimal-runtime=true #![crate_type = "lib"] @@ -14,7 +16,8 @@ pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 { // CHECK-NEXT: {{%.+}} = call i32 %f(i32{{.*}} %arg) // CHECK: type_test.fail: // CHECK-NEXT: {{%.+}} = ptrtoint ptr {{%f|%0}} to i64 - // CHECK-NEXT: call void @__ubsan_handle_cfi_check_fail_abort( + // cfi-diag-NEXT: call void @__ubsan_handle_cfi_check_fail_abort( + // cfi-diag-minimal-runtime-NEXT: call void @__ubsan_handle_cfi_check_fail_minimal_abort() // CHECK-NEXT: unreachable f(arg) } diff --git a/tests/codegen-llvm/sanitizer/cfi/emit-type-checks-recover-mode.rs b/tests/codegen-llvm/sanitizer/cfi/emit-type-checks-recover-mode.rs index 0dbcb7a833fb7..b3a1e2cb0b02e 100644 --- a/tests/codegen-llvm/sanitizer/cfi/emit-type-checks-recover-mode.rs +++ b/tests/codegen-llvm/sanitizer/cfi/emit-type-checks-recover-mode.rs @@ -1,7 +1,9 @@ // Verifies that pointer type membership tests for indirect calls are emitted. // +//@ revisions: cfi-recover cfi-recover-minimal-runtime //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-recover=true -Copt-level=0 -C unsafe-allow-abi-mismatch=sanitizer +//@ [cfi-recover-minimal-runtime] compile-flags: -Zsanitizer-cfi-minimal-runtime=true #![crate_type = "lib"] @@ -14,7 +16,8 @@ pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 { // CHECK-NEXT: {{%.+}} = call i32 %f(i32{{.*}} %arg) // CHECK: type_test.fail: // CHECK-NEXT: {{%.+}} = ptrtoint ptr {{%f|%0}} to i64 - // CHECK-NEXT: call void @__ubsan_handle_cfi_check_fail( + // cfi-recover-NEXT: call void @__ubsan_handle_cfi_check_fail( + // cfi-recover-minimal-runtime-NEXT: call void @__ubsan_handle_cfi_check_fail_minimal() // CHECK-NEXT: br label %type_test.pass f(arg) } diff --git a/tests/run-make/sanitizer-cfi-runtime/program.rs b/tests/run-make/sanitizer-cfi-runtime/program.rs new file mode 100644 index 0000000000000..0a46dcedef9de --- /dev/null +++ b/tests/run-make/sanitizer-cfi-runtime/program.rs @@ -0,0 +1,17 @@ +use std::hint::black_box; +use std::mem; + +fn add_one(x: i32) -> i32 { + x + 1 +} + +#[inline(never)] +fn call_with_mismatch(f: fn(i32) -> i32) { + let g: fn(i32, i32) -> i32 = unsafe { mem::transmute(f) }; + let res = g(1, 2); + assert_eq!(res, 2); +} + +fn main() { + call_with_mismatch(black_box(add_one)); +} diff --git a/tests/run-make/sanitizer-cfi-runtime/rmake.rs b/tests/run-make/sanitizer-cfi-runtime/rmake.rs new file mode 100644 index 0000000000000..adb739e43c341 --- /dev/null +++ b/tests/run-make/sanitizer-cfi-runtime/rmake.rs @@ -0,0 +1,171 @@ +//@ needs-sanitizer-support +//@ needs-sanitizer-cfi + +use run_make_support::{run, run_fail, rustc}; + +fn main() { + // 1. Check link args for default CFI (no diag/recover, no UBSan runtime) + let link_args_default = rustc() + .arg("-Clto") + .arg("-Ccodegen-units=1") + .arg("-Ctarget-feature=-crt-static") + .arg("-Cunsafe-allow-abi-mismatch=sanitizer") + .arg("-Zsanitizer=cfi") + .print("link-args") + .input("program.rs") + .run() + .stdout_utf8(); + assert!( + !link_args_default.contains("ubsan"), + "did not expect any ubsan runtime in link args, got: {link_args_default}" + ); + + // 2. Check link args for full UBSan runtime with CFI diag mode + let link_args_full_diag = rustc() + .arg("-Clto") + .arg("-Ccodegen-units=1") + .arg("-Ctarget-feature=-crt-static") + .arg("-Cunsafe-allow-abi-mismatch=sanitizer") + .arg("-Zsanitizer=cfi") + .arg("-Zsanitizer-cfi-diag=true") + .print("link-args") + .input("program.rs") + .run() + .stdout_utf8(); + assert!( + link_args_full_diag.contains("rt.ubsan.") || link_args_full_diag.contains("rt.ubsan\""), + "expected ubsan runtime in link args, got: {link_args_full_diag}" + ); + assert!( + !link_args_full_diag.contains("ubsan_minimal"), + "did not expect ubsan_minimal in link args, got: {link_args_full_diag}" + ); + + // 3. Check link args for full UBSan runtime with CFI recover mode + let link_args_full_recover = rustc() + .arg("-Clto") + .arg("-Ccodegen-units=1") + .arg("-Ctarget-feature=-crt-static") + .arg("-Cunsafe-allow-abi-mismatch=sanitizer") + .arg("-Zsanitizer=cfi") + .arg("-Zsanitizer-cfi-recover=true") + .print("link-args") + .input("program.rs") + .run() + .stdout_utf8(); + assert!( + link_args_full_recover.contains("rt.ubsan.") + || link_args_full_recover.contains("rt.ubsan\""), + "expected ubsan runtime in link args, got: {link_args_full_recover}" + ); + assert!( + !link_args_full_recover.contains("ubsan_minimal"), + "did not expect ubsan_minimal in link args, got: {link_args_full_recover}" + ); + + // 4. Check link args for minimal UBSan runtime with CFI diag mode + let link_args_min_diag = rustc() + .arg("-Clto") + .arg("-Ccodegen-units=1") + .arg("-Ctarget-feature=-crt-static") + .arg("-Cunsafe-allow-abi-mismatch=sanitizer") + .arg("-Zsanitizer=cfi") + .arg("-Zsanitizer-cfi-diag=true") + .arg("-Zsanitizer-cfi-minimal-runtime=true") + .print("link-args") + .input("program.rs") + .run() + .stdout_utf8(); + assert!( + link_args_min_diag.contains("rt.ubsan_minimal.") + || link_args_min_diag.contains("rt.ubsan_minimal\""), + "expected ubsan_minimal runtime in link args, got: {link_args_min_diag}" + ); + + // 5. Check link args for minimal UBSan runtime with CFI recover mode + let link_args_min_recover = rustc() + .arg("-Clto") + .arg("-Ccodegen-units=1") + .arg("-Ctarget-feature=-crt-static") + .arg("-Cunsafe-allow-abi-mismatch=sanitizer") + .arg("-Zsanitizer=cfi") + .arg("-Zsanitizer-cfi-recover=true") + .arg("-Zsanitizer-cfi-minimal-runtime=true") + .print("link-args") + .input("program.rs") + .run() + .stdout_utf8(); + assert!( + link_args_min_recover.contains("rt.ubsan_minimal.") + || link_args_min_recover.contains("rt.ubsan_minimal\""), + "expected ubsan_minimal runtime in link args, got: {link_args_min_recover}" + ); + + // 6. Build and run binary with default CFI (trap mode, no runtime) + rustc() + .arg("-Clto") + .arg("-Ccodegen-units=1") + .arg("-Ctarget-feature=-crt-static") + .arg("-Cunsafe-allow-abi-mismatch=sanitizer") + .arg("-Zsanitizer=cfi") + .output("program_default") + .input("program.rs") + .run(); + run_fail("program_default"); + + // 7. Build and run binary with full runtime in diag (abort) mode + rustc() + .arg("-Clto") + .arg("-Ccodegen-units=1") + .arg("-Ctarget-feature=-crt-static") + .arg("-Cunsafe-allow-abi-mismatch=sanitizer") + .arg("-Zsanitizer=cfi") + .arg("-Zsanitizer-cfi-diag=true") + .output("program_full_diag") + .input("program.rs") + .run(); + run_fail("program_full_diag") + .assert_stderr_contains("runtime error: control flow integrity check for type"); + + // 8. Build and run binary with full runtime in recover mode + rustc() + .arg("-Clto") + .arg("-Ccodegen-units=1") + .arg("-Ctarget-feature=-crt-static") + .arg("-Cunsafe-allow-abi-mismatch=sanitizer") + .arg("-Zsanitizer=cfi") + .arg("-Zsanitizer-cfi-recover=true") + .output("program_full_recover") + .input("program.rs") + .run(); + run("program_full_recover") + .assert_stderr_contains("runtime error: control flow integrity check for type"); + + // 9. Build and run binary with minimal runtime in diag (abort) mode + rustc() + .arg("-Clto") + .arg("-Ccodegen-units=1") + .arg("-Ctarget-feature=-crt-static") + .arg("-Cunsafe-allow-abi-mismatch=sanitizer") + .arg("-Zsanitizer=cfi") + .arg("-Zsanitizer-cfi-diag=true") + .arg("-Zsanitizer-cfi-minimal-runtime=true") + .output("program_min_diag") + .input("program.rs") + .run(); + run_fail("program_min_diag").assert_stderr_contains("ubsan: cfi-check-fail"); + + // 10. Build and run binary with minimal runtime in recover mode + rustc() + .arg("-Clto") + .arg("-Ccodegen-units=1") + .arg("-Ctarget-feature=-crt-static") + .arg("-Cunsafe-allow-abi-mismatch=sanitizer") + .arg("-Zsanitizer=cfi") + .arg("-Zsanitizer-cfi-recover=true") + .arg("-Zsanitizer-cfi-minimal-runtime=true") + .output("program_min_recover") + .input("program.rs") + .run(); + run("program_min_recover").assert_stderr_contains("ubsan: cfi-check-fail"); +} diff --git a/tests/ui/sanitizer/cfi/fn-ptr-type-mismatch-recover.rs b/tests/ui/sanitizer/cfi/fn-ptr-type-mismatch-recover.rs new file mode 100644 index 0000000000000..21953675684ee --- /dev/null +++ b/tests/ui/sanitizer/cfi/fn-ptr-type-mismatch-recover.rs @@ -0,0 +1,38 @@ +// Verifies that calling a function pointer with a mismatched type with CFI +// recovery enabled reports the failure and continues execution. + +//@ revisions: cfi cfi-minimal-runtime +// FIXME(#122848) Remove only-linux once OSX CFI binaries work +//@ only-linux +//@ ignore-backends: gcc +//@ [cfi] needs-sanitizer-cfi +//@ [cfi] needs-sanitizer-support +//@ [cfi-minimal-runtime] needs-sanitizer-cfi +//@ [cfi-minimal-runtime] needs-sanitizer-support +//@ compile-flags: -C target-feature=-crt-static +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer +//@ compile-flags: -C opt-level=0 -C codegen-units=1 -C lto +//@ compile-flags: -C prefer-dynamic=off +//@ compile-flags: -Z sanitizer=cfi +//@ [cfi] compile-flags: -Z sanitizer-cfi-recover=true +//@ [cfi-minimal-runtime] compile-flags: -Z sanitizer-cfi-recover=true +//@ [cfi-minimal-runtime] compile-flags: -Z sanitizer-cfi-minimal-runtime=true +//@ run-pass + +use std::hint::black_box; +use std::mem; + +fn add_one(x: i32) -> i32 { + x + 1 +} + +#[inline(never)] +fn call_with_mismatch(f: fn(i32) -> i32) { + let g: fn(i32, i32) -> i32 = unsafe { mem::transmute(f) }; + let res = g(1, 2); + assert_eq!(res, 2); +} + +fn main() { + call_with_mismatch(black_box(add_one)); +} diff --git a/tests/ui/sanitizer/cfi/fn-ptr-type-mismatch.rs b/tests/ui/sanitizer/cfi/fn-ptr-type-mismatch.rs index 6fe7eec7c6920..d64f6c1f43965 100644 --- a/tests/ui/sanitizer/cfi/fn-ptr-type-mismatch.rs +++ b/tests/ui/sanitizer/cfi/fn-ptr-type-mismatch.rs @@ -1,12 +1,14 @@ // Verifies that calling a function pointer with a mismatched type triggers a // CFI violation and causes the process to trap. -//@ revisions: cfi kcfi +//@ revisions: cfi cfi-minimal-runtime kcfi // FIXME(#122848) Remove only-linux once OSX CFI binaries work //@ only-linux //@ ignore-backends: gcc //@ [cfi] needs-sanitizer-cfi //@ [cfi] needs-sanitizer-support +//@ [cfi-minimal-runtime] needs-sanitizer-cfi +//@ [cfi-minimal-runtime] needs-sanitizer-support //@ [kcfi] needs-sanitizer-kcfi //@ compile-flags: -C target-feature=-crt-static //@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer @@ -14,6 +16,11 @@ //@ [cfi] compile-flags: -C prefer-dynamic=off //@ [cfi] compile-flags: -Z sanitizer=cfi //@ [cfi] compile-flags: -Z sanitizer-cfi-diag=true +//@ [cfi-minimal-runtime] compile-flags: -C opt-level=0 -C codegen-units=1 -C lto +//@ [cfi-minimal-runtime] compile-flags: -C prefer-dynamic=off +//@ [cfi-minimal-runtime] compile-flags: -Z sanitizer=cfi +//@ [cfi-minimal-runtime] compile-flags: -Z sanitizer-cfi-diag=true +//@ [cfi-minimal-runtime] compile-flags: -Z sanitizer-cfi-minimal-runtime=true //@ [kcfi] compile-flags: -Z sanitizer=kcfi //@ [kcfi] compile-flags: -C panic=abort -C prefer-dynamic=off //@ run-fail-or-crash diff --git a/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi-recover-or-diag.rs b/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi-recover-or-diag.rs new file mode 100644 index 0000000000000..f241598131d65 --- /dev/null +++ b/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi-recover-or-diag.rs @@ -0,0 +1,11 @@ +// Verifies that `-Zsanitizer-cfi-minimal-runtime` requires +// `-Zsanitizer-cfi-recover` or `-Zsanitizer-cfi-diag`. +// +//@ needs-sanitizer-cfi +//@ compile-flags: -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer-cfi-minimal-runtime + +#![feature(no_core)] +#![no_core] +#![no_main] + +//~? ERROR `-Zsanitizer-cfi-minimal-runtime` requires `-Zsanitizer-cfi-recover` or `-Zsanitizer-cfi-diag` diff --git a/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi-recover-or-diag.stderr b/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi-recover-or-diag.stderr new file mode 100644 index 0000000000000..f3d483bef7eb7 --- /dev/null +++ b/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi-recover-or-diag.stderr @@ -0,0 +1,4 @@ +error: `-Zsanitizer-cfi-minimal-runtime` requires `-Zsanitizer-cfi-recover` or `-Zsanitizer-cfi-diag` + +error: aborting due to 1 previous error + From 4d68be3d806fd0894977dea0a5758800cab25ac6 Mon Sep 17 00:00:00 2001 From: Jakob Koschel Date: Thu, 10 Sep 2026 14:11:10 +0000 Subject: [PATCH 03/20] minor cleanup for minimal runtime test --- .../cfi/minimal-runtime-requires-cfi-recover-or-diag.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi-recover-or-diag.rs b/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi-recover-or-diag.rs index f241598131d65..cbc0bac40c2b3 100644 --- a/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi-recover-or-diag.rs +++ b/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi-recover-or-diag.rs @@ -2,7 +2,7 @@ // `-Zsanitizer-cfi-recover` or `-Zsanitizer-cfi-diag`. // //@ needs-sanitizer-cfi -//@ compile-flags: -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer-cfi-minimal-runtime +//@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer-cfi-minimal-runtime #![feature(no_core)] #![no_core] From 855d8a275b860bf5bb6d0a2499278a90a8d1b547 Mon Sep 17 00:00:00 2001 From: Jakob Koschel Date: Thu, 10 Sep 2026 14:42:35 +0000 Subject: [PATCH 04/20] Add target modifier for -Zsanitizer-cfi-minimal-runtime Co-Authored-By: Bastian Kersting --- compiler/rustc_session/src/options.rs | 22 ++++++++++++++++++- .../auxiliary/cfi-minimal-runtime.rs | 7 ++++++ .../sanitizer-cfi-minimal-runtime.rs | 18 +++++++++++++++ ...izer-cfi-minimal-runtime.wrong_flag.stderr | 9 ++++++++ ...cfi-minimal-runtime.wrong_sanitizer.stderr | 9 ++++++++ 5 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 tests/ui/target_modifiers/auxiliary/cfi-minimal-runtime.rs create mode 100644 tests/ui/target_modifiers/sanitizer-cfi-minimal-runtime.rs create mode 100644 tests/ui/target_modifiers/sanitizer-cfi-minimal-runtime.wrong_flag.stderr create mode 100644 tests/ui/target_modifiers/sanitizer-cfi-minimal-runtime.wrong_sanitizer.stderr diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index f11bdadf5b67d..63bc2da30f063 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -136,6 +136,21 @@ mod target_modifier_consistency_check { } true } + pub(super) fn sanitizer_cfi_minimal_runtime( + sess: &Session, + l: &TargetModifier, + r: Option<&TargetModifier>, + ) -> bool { + // For CFI, the helper flag -Zsanitizer-cfi-minimal-runtime should also be a target modifier + if sess.sanitizers().contains(SanitizerSet::CFI) { + if let Some(r) = r { + return l.extend().tech_value == r.extend().tech_value; + } else { + return false; + } + } + true + } pub(super) fn target_cpu( sess: &Session, l: &TargetModifier, @@ -178,6 +193,11 @@ impl TargetModifier { sess, self, other, ); } + UnstableOptionsTargetModifiers::SanitizerCfiMinimalRuntime => { + return target_modifier_consistency_check::sanitizer_cfi_minimal_runtime( + sess, self, other, + ); + } _ => {} }, OptionsTargetModifiers::CodegenOptions(codegen) => match codegen { @@ -2825,7 +2845,7 @@ written to standard error output)"), "enable CFI diagnostics (default: no)"), sanitizer_cfi_recover: Option = (None, parse_opt_bool, [TRACKED], "enable CFI recovery (default: no)"), - sanitizer_cfi_minimal_runtime: Option = (None, parse_opt_bool, [TRACKED], + sanitizer_cfi_minimal_runtime: Option = (None, parse_opt_bool, [TRACKED] { TARGET_MODIFIER: SanitizerCfiMinimalRuntime }, "enable minimal UBSan runtime for CFI (default: no)"), sanitizer_dataflow_abilist: Vec = (Vec::new(), parse_comma_list, [TRACKED], "additional ABI list files that control how shadow parameters are passed (comma separated)"), diff --git a/tests/ui/target_modifiers/auxiliary/cfi-minimal-runtime.rs b/tests/ui/target_modifiers/auxiliary/cfi-minimal-runtime.rs new file mode 100644 index 0000000000000..aacea1ee65dd2 --- /dev/null +++ b/tests/ui/target_modifiers/auxiliary/cfi-minimal-runtime.rs @@ -0,0 +1,7 @@ +//@ no-prefer-dynamic +//@ needs-sanitizer-cfi +//@ compile-flags: -Clto -Zsanitizer=cfi -Zsanitizer-cfi-recover -Zsanitizer-cfi-minimal-runtime + +#![feature(no_core)] +#![crate_type = "rlib"] +#![no_core] diff --git a/tests/ui/target_modifiers/sanitizer-cfi-minimal-runtime.rs b/tests/ui/target_modifiers/sanitizer-cfi-minimal-runtime.rs new file mode 100644 index 0000000000000..45c6ad7b521a3 --- /dev/null +++ b/tests/ui/target_modifiers/sanitizer-cfi-minimal-runtime.rs @@ -0,0 +1,18 @@ +// For CFI, the helper flag -Zsanitizer-cfi-minimal-runtime should also be a target modifier. + +//@ needs-sanitizer-cfi +//@ aux-build:cfi-minimal-runtime.rs + +//@ revisions: ok wrong_flag wrong_sanitizer +//@[ok] compile-flags: -Clto -Zsanitizer=cfi -Zsanitizer-cfi-recover -Zsanitizer-cfi-minimal-runtime +//@[wrong_flag] compile-flags: -Clto -Zsanitizer=cfi -Zsanitizer-cfi-recover +//@[ok] check-pass + +#![feature(no_core)] +#![crate_type = "rlib"] +#![no_core] + +extern crate cfi_minimal_runtime; + +//[wrong_flag]~? ERROR mixing `-Zsanitizer-cfi-minimal-runtime` will cause an ABI mismatch in crate `sanitizer_cfi_minimal_runtime` +//[wrong_sanitizer]~? ERROR mixing `-Zsanitizer` will cause an ABI mismatch in crate `sanitizer_cfi_minimal_runtime` diff --git a/tests/ui/target_modifiers/sanitizer-cfi-minimal-runtime.wrong_flag.stderr b/tests/ui/target_modifiers/sanitizer-cfi-minimal-runtime.wrong_flag.stderr new file mode 100644 index 0000000000000..6dfc1a3bb7d16 --- /dev/null +++ b/tests/ui/target_modifiers/sanitizer-cfi-minimal-runtime.wrong_flag.stderr @@ -0,0 +1,9 @@ +error: mixing `-Zsanitizer-cfi-minimal-runtime` will cause an ABI mismatch in crate `sanitizer_cfi_minimal_runtime` + | + = help: the `-Zsanitizer-cfi-minimal-runtime` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely + = note: `-Zsanitizer-cfi-minimal-runtime` is unset in this crate which is incompatible with `-Zsanitizer-cfi-minimal-runtime` being set in dependency `cfi_minimal_runtime` + = help: set `-Zsanitizer-cfi-minimal-runtime` in this crate or unset `-Zsanitizer-cfi-minimal-runtime` in `cfi_minimal_runtime` + = help: if you are sure this will not cause problems, you may use `-Cunsafe-allow-abi-mismatch=sanitizer-cfi-minimal-runtime` to silence this error + +error: aborting due to 1 previous error + diff --git a/tests/ui/target_modifiers/sanitizer-cfi-minimal-runtime.wrong_sanitizer.stderr b/tests/ui/target_modifiers/sanitizer-cfi-minimal-runtime.wrong_sanitizer.stderr new file mode 100644 index 0000000000000..32ba848b3b2ad --- /dev/null +++ b/tests/ui/target_modifiers/sanitizer-cfi-minimal-runtime.wrong_sanitizer.stderr @@ -0,0 +1,9 @@ +error: mixing `-Zsanitizer` will cause an ABI mismatch in crate `sanitizer_cfi_minimal_runtime` + | + = help: the `-Zsanitizer` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely + = note: `-Zsanitizer` is unset in this crate which is incompatible with `-Zsanitizer=cfi` in dependency `cfi_minimal_runtime` + = help: set `-Zsanitizer=cfi` in this crate or unset `-Zsanitizer` in `cfi_minimal_runtime` + = help: if you are sure this will not cause problems, you may use `-Cunsafe-allow-abi-mismatch=sanitizer` to silence this error + +error: aborting due to 1 previous error + From a42ab2f36cf031d3f95181edc8a613d38c7e00b5 Mon Sep 17 00:00:00 2001 From: Jakob Koschel Date: Fri, 11 Sep 2026 08:47:12 +0000 Subject: [PATCH 05/20] Make -Zsanitizer-cfi-minimal-runtime also dependent on -Zsanitizer=cfi --- compiler/rustc_session/src/diagnostics.rs | 6 ++++++ compiler/rustc_session/src/session.rs | 3 +++ .../minimal-runtime-requires-cfi-recover-or-diag.rs | 2 +- .../ui/sanitizer/cfi/minimal-runtime-requires-cfi.rs | 11 +++++++++++ .../sanitizer/cfi/minimal-runtime-requires-cfi.stderr | 6 ++++++ 5 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi.rs create mode 100644 tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi.stderr diff --git a/compiler/rustc_session/src/diagnostics.rs b/compiler/rustc_session/src/diagnostics.rs index d27b616d7e359..b0bbccd7fe91f 100644 --- a/compiler/rustc_session/src/diagnostics.rs +++ b/compiler/rustc_session/src/diagnostics.rs @@ -340,6 +340,12 @@ pub(crate) struct SanitizerCfiRecoverRequiresCfi; #[diag("`-Zsanitizer-cfi-diag` requires `-Zsanitizer=cfi`")] pub(crate) struct SanitizerCfiDiagRequiresCfi; +#[derive(Diagnostic)] +#[diag( + "`-Zsanitizer-cfi-minimal-runtime` requires `-Zsanitizer=cfi`" +)] +pub(crate) struct SanitizerCfiMinimalRuntimeRequiresCfi; + #[derive(Diagnostic)] #[diag( "`-Zsanitizer-cfi-minimal-runtime` requires `-Zsanitizer-cfi-recover` or `-Zsanitizer-cfi-diag`" diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index bf310270d0a19..a209219758026 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1690,6 +1690,9 @@ fn validate_commandline_args_with_session_available(sess: &Session) { // LLVM CFI minimal runtime requires CFI Recover or CFI Diag. if sess.is_sanitizer_cfi_minimal_runtime_enabled() { + if !sess.is_sanitizer_cfi_enabled() { + sess.dcx().emit_err(diagnostics::SanitizerCfiMinimalRuntimeRequiresCfi); + } if !(sess.is_sanitizer_cfi_recover_enabled() || sess.is_sanitizer_cfi_diag_enabled()) { sess.dcx().emit_err(diagnostics::SanitizerCfiMinimalRuntimeRequiresCfiRecoverOrDiag); } diff --git a/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi-recover-or-diag.rs b/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi-recover-or-diag.rs index cbc0bac40c2b3..16f39f09ec7a0 100644 --- a/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi-recover-or-diag.rs +++ b/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi-recover-or-diag.rs @@ -2,7 +2,7 @@ // `-Zsanitizer-cfi-recover` or `-Zsanitizer-cfi-diag`. // //@ needs-sanitizer-cfi -//@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer-cfi-minimal-runtime +//@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-minimal-runtime #![feature(no_core)] #![no_core] diff --git a/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi.rs b/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi.rs new file mode 100644 index 0000000000000..13b296b4329ee --- /dev/null +++ b/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi.rs @@ -0,0 +1,11 @@ +// Verifies that `-Zsanitizer-cfi-minimal-runtime` requires `-Zsanitizer=cfi`. +// +//@ needs-sanitizer-cfi +//@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer-cfi-minimal-runtime + +#![feature(no_core)] +#![no_core] +#![no_main] + +//~? ERROR `-Zsanitizer-cfi-minimal-runtime` requires `-Zsanitizer=cfi` +//~? ERROR `-Zsanitizer-cfi-minimal-runtime` requires `-Zsanitizer-cfi-recover` or `-Zsanitizer-cfi-diag` diff --git a/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi.stderr b/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi.stderr new file mode 100644 index 0000000000000..251d0d0817631 --- /dev/null +++ b/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi.stderr @@ -0,0 +1,6 @@ +error: `-Zsanitizer-cfi-minimal-runtime` requires `-Zsanitizer=cfi` + +error: `-Zsanitizer-cfi-minimal-runtime` requires `-Zsanitizer-cfi-recover` or `-Zsanitizer-cfi-diag` + +error: aborting due to 2 previous errors + From bba4a3f986f4e2d4b0bea8711c436bf3ffe4a92a Mon Sep 17 00:00:00 2001 From: Jakob Koschel Date: Fri, 11 Sep 2026 09:00:38 +0000 Subject: [PATCH 06/20] Fix tests with new cfi-minimal-runtime target modifier --- tests/ui/sanitizer/cfi/fn-ptr-type-mismatch-recover.rs | 2 +- tests/ui/sanitizer/cfi/fn-ptr-type-mismatch.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ui/sanitizer/cfi/fn-ptr-type-mismatch-recover.rs b/tests/ui/sanitizer/cfi/fn-ptr-type-mismatch-recover.rs index 21953675684ee..069ac811f481d 100644 --- a/tests/ui/sanitizer/cfi/fn-ptr-type-mismatch-recover.rs +++ b/tests/ui/sanitizer/cfi/fn-ptr-type-mismatch-recover.rs @@ -10,7 +10,7 @@ //@ [cfi-minimal-runtime] needs-sanitizer-cfi //@ [cfi-minimal-runtime] needs-sanitizer-support //@ compile-flags: -C target-feature=-crt-static -//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer,sanitizer-cfi-minimal-runtime //@ compile-flags: -C opt-level=0 -C codegen-units=1 -C lto //@ compile-flags: -C prefer-dynamic=off //@ compile-flags: -Z sanitizer=cfi diff --git a/tests/ui/sanitizer/cfi/fn-ptr-type-mismatch.rs b/tests/ui/sanitizer/cfi/fn-ptr-type-mismatch.rs index d64f6c1f43965..1e32a1042c848 100644 --- a/tests/ui/sanitizer/cfi/fn-ptr-type-mismatch.rs +++ b/tests/ui/sanitizer/cfi/fn-ptr-type-mismatch.rs @@ -11,7 +11,7 @@ //@ [cfi-minimal-runtime] needs-sanitizer-support //@ [kcfi] needs-sanitizer-kcfi //@ compile-flags: -C target-feature=-crt-static -//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer,sanitizer-cfi-minimal-runtime //@ [cfi] compile-flags: -C opt-level=0 -C codegen-units=1 -C lto //@ [cfi] compile-flags: -C prefer-dynamic=off //@ [cfi] compile-flags: -Z sanitizer=cfi From 775c187f3add8c381e818575687df32c01abf92a Mon Sep 17 00:00:00 2001 From: Jakob Koschel Date: Fri, 11 Sep 2026 09:37:04 +0000 Subject: [PATCH 07/20] Fix linter issue in diagnostics.rs --- compiler/rustc_session/src/diagnostics.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/compiler/rustc_session/src/diagnostics.rs b/compiler/rustc_session/src/diagnostics.rs index b0bbccd7fe91f..0ec847767336e 100644 --- a/compiler/rustc_session/src/diagnostics.rs +++ b/compiler/rustc_session/src/diagnostics.rs @@ -341,9 +341,7 @@ pub(crate) struct SanitizerCfiRecoverRequiresCfi; pub(crate) struct SanitizerCfiDiagRequiresCfi; #[derive(Diagnostic)] -#[diag( - "`-Zsanitizer-cfi-minimal-runtime` requires `-Zsanitizer=cfi`" -)] +#[diag("`-Zsanitizer-cfi-minimal-runtime` requires `-Zsanitizer=cfi`")] pub(crate) struct SanitizerCfiMinimalRuntimeRequiresCfi; #[derive(Diagnostic)] From 3058339f0e35413263d71e595a8bb1421646edd3 Mon Sep 17 00:00:00 2001 From: Jakob Koschel Date: Fri, 11 Sep 2026 10:53:13 +0000 Subject: [PATCH 08/20] Fix broken test introduced by cfi-minimal-runtime target modifier --- .../sanitizer/cfi/emit-type-checks-diag-mode.rs | 2 +- .../sanitizer/cfi/emit-type-checks-recover-mode.rs | 2 +- tests/run-make/sanitizer-cfi-runtime/rmake.rs | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/codegen-llvm/sanitizer/cfi/emit-type-checks-diag-mode.rs b/tests/codegen-llvm/sanitizer/cfi/emit-type-checks-diag-mode.rs index 96cfb94289724..4d58872db7c45 100644 --- a/tests/codegen-llvm/sanitizer/cfi/emit-type-checks-diag-mode.rs +++ b/tests/codegen-llvm/sanitizer/cfi/emit-type-checks-diag-mode.rs @@ -2,7 +2,7 @@ // //@ revisions: cfi-diag cfi-diag-minimal-runtime //@ needs-sanitizer-cfi -//@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-diag=true -Copt-level=0 -C unsafe-allow-abi-mismatch=sanitizer +//@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-diag=true -Copt-level=0 -C unsafe-allow-abi-mismatch=sanitizer,sanitizer-cfi-minimal-runtime //@ [cfi-diag-minimal-runtime] compile-flags: -Zsanitizer-cfi-minimal-runtime=true #![crate_type = "lib"] diff --git a/tests/codegen-llvm/sanitizer/cfi/emit-type-checks-recover-mode.rs b/tests/codegen-llvm/sanitizer/cfi/emit-type-checks-recover-mode.rs index b3a1e2cb0b02e..3ea97e44c21e7 100644 --- a/tests/codegen-llvm/sanitizer/cfi/emit-type-checks-recover-mode.rs +++ b/tests/codegen-llvm/sanitizer/cfi/emit-type-checks-recover-mode.rs @@ -2,7 +2,7 @@ // //@ revisions: cfi-recover cfi-recover-minimal-runtime //@ needs-sanitizer-cfi -//@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-recover=true -Copt-level=0 -C unsafe-allow-abi-mismatch=sanitizer +//@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-recover=true -Copt-level=0 -C unsafe-allow-abi-mismatch=sanitizer,sanitizer-cfi-minimal-runtime //@ [cfi-recover-minimal-runtime] compile-flags: -Zsanitizer-cfi-minimal-runtime=true #![crate_type = "lib"] diff --git a/tests/run-make/sanitizer-cfi-runtime/rmake.rs b/tests/run-make/sanitizer-cfi-runtime/rmake.rs index adb739e43c341..8e92f5927d952 100644 --- a/tests/run-make/sanitizer-cfi-runtime/rmake.rs +++ b/tests/run-make/sanitizer-cfi-runtime/rmake.rs @@ -68,7 +68,7 @@ fn main() { .arg("-Clto") .arg("-Ccodegen-units=1") .arg("-Ctarget-feature=-crt-static") - .arg("-Cunsafe-allow-abi-mismatch=sanitizer") + .arg("-Cunsafe-allow-abi-mismatch=sanitizer,sanitizer-cfi-minimal-runtime") .arg("-Zsanitizer=cfi") .arg("-Zsanitizer-cfi-diag=true") .arg("-Zsanitizer-cfi-minimal-runtime=true") @@ -87,7 +87,7 @@ fn main() { .arg("-Clto") .arg("-Ccodegen-units=1") .arg("-Ctarget-feature=-crt-static") - .arg("-Cunsafe-allow-abi-mismatch=sanitizer") + .arg("-Cunsafe-allow-abi-mismatch=sanitizer,sanitizer-cfi-minimal-runtime") .arg("-Zsanitizer=cfi") .arg("-Zsanitizer-cfi-recover=true") .arg("-Zsanitizer-cfi-minimal-runtime=true") @@ -146,7 +146,7 @@ fn main() { .arg("-Clto") .arg("-Ccodegen-units=1") .arg("-Ctarget-feature=-crt-static") - .arg("-Cunsafe-allow-abi-mismatch=sanitizer") + .arg("-Cunsafe-allow-abi-mismatch=sanitizer,sanitizer-cfi-minimal-runtime") .arg("-Zsanitizer=cfi") .arg("-Zsanitizer-cfi-diag=true") .arg("-Zsanitizer-cfi-minimal-runtime=true") @@ -160,7 +160,7 @@ fn main() { .arg("-Clto") .arg("-Ccodegen-units=1") .arg("-Ctarget-feature=-crt-static") - .arg("-Cunsafe-allow-abi-mismatch=sanitizer") + .arg("-Cunsafe-allow-abi-mismatch=sanitizer,sanitizer-cfi-minimal-runtime") .arg("-Zsanitizer=cfi") .arg("-Zsanitizer-cfi-recover=true") .arg("-Zsanitizer-cfi-minimal-runtime=true") From 7aacc8a2dab9300860afc1d912193e490ceeb5a1 Mon Sep 17 00:00:00 2001 From: Jakob Koschel Date: Fri, 11 Sep 2026 12:05:31 +0000 Subject: [PATCH 09/20] Skip gcc for CFI runtime tests --- tests/run-make/sanitizer-cfi-runtime/rmake.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/run-make/sanitizer-cfi-runtime/rmake.rs b/tests/run-make/sanitizer-cfi-runtime/rmake.rs index 8e92f5927d952..3cad996a14054 100644 --- a/tests/run-make/sanitizer-cfi-runtime/rmake.rs +++ b/tests/run-make/sanitizer-cfi-runtime/rmake.rs @@ -1,5 +1,6 @@ //@ needs-sanitizer-support //@ needs-sanitizer-cfi +//@ ignore-backends: gcc use run_make_support::{run, run_fail, rustc}; From 8e5ad6c1e4d2590797636dd5c8e7049e002b3b39 Mon Sep 17 00:00:00 2001 From: Jakob Koschel Date: Mon, 21 Sep 2026 11:14:06 +0000 Subject: [PATCH 10/20] use match to determine correct ubsan cfi handler --- compiler/rustc_codegen_llvm/src/builder.rs | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 438accb85f377..7fa079a01a6b1 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -2078,18 +2078,11 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { ) }; let ubsan_handler = self.declare_cfn( - if is_recover { - if is_minimal { - "__ubsan_handle_cfi_check_fail_minimal" - } else { - "__ubsan_handle_cfi_check_fail" - } - } else { - if is_minimal { - "__ubsan_handle_cfi_check_fail_minimal_abort" - } else { - "__ubsan_handle_cfi_check_fail_abort" - } + match (is_minimal, is_recover) { + (true, true) => "__ubsan_handle_cfi_check_fail_minimal", + (true, false) => "__ubsan_handle_cfi_check_fail_minimal_abort", + (false, true) => "__ubsan_handle_cfi_check_fail", + (false, false) => "__ubsan_handle_cfi_check_fail_abort", }, llvm::UnnamedAddr::Global, fty, From 20b6fd622136db582c32a964e3cec9a56030af0d Mon Sep 17 00:00:00 2001 From: Jakob Koschel Date: Wed, 23 Sep 2026 20:06:33 +0000 Subject: [PATCH 11/20] Address review feedback Only check `SanitizerCfiMinimalRuntimeRequiresCfiRecoverOrDiag` if CFI is actually enabled. Use `is_sanitizer_cfi_minimal_runtime_enabled()` helper within `link.rs`. --- compiler/rustc_codegen_ssa/src/back/link.rs | 2 +- compiler/rustc_session/src/session.rs | 6 +++--- tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi.rs | 1 - tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi.stderr | 4 +--- 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 7c8bb4f59dfba..3a405f275cf4b 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1764,7 +1764,7 @@ fn add_sanitizer_libraries( && (sess.opts.unstable_opts.sanitizer_cfi_diag.unwrap_or(false) || sess.opts.unstable_opts.sanitizer_cfi_recover.unwrap_or(false)) { - if sess.opts.unstable_opts.sanitizer_cfi_minimal_runtime.unwrap_or(false) { + if sess.is_sanitizer_cfi_minimal_runtime_enabled() { link_sanitizer_runtime(sess, flavor, linker, "ubsan_minimal"); } else { link_sanitizer_runtime(sess, flavor, linker, "ubsan"); diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index a209219758026..cea3a32729b98 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1688,12 +1688,12 @@ fn validate_commandline_args_with_session_available(sess: &Session) { } } - // LLVM CFI minimal runtime requires CFI Recover or CFI Diag. + // LLVM CFI minimal runtime requires CFI recovery or CFI diagnostics. if sess.is_sanitizer_cfi_minimal_runtime_enabled() { if !sess.is_sanitizer_cfi_enabled() { sess.dcx().emit_err(diagnostics::SanitizerCfiMinimalRuntimeRequiresCfi); - } - if !(sess.is_sanitizer_cfi_recover_enabled() || sess.is_sanitizer_cfi_diag_enabled()) { + } else if !(sess.is_sanitizer_cfi_recover_enabled() || sess.is_sanitizer_cfi_diag_enabled()) + { sess.dcx().emit_err(diagnostics::SanitizerCfiMinimalRuntimeRequiresCfiRecoverOrDiag); } } diff --git a/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi.rs b/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi.rs index 13b296b4329ee..cb68734608ac7 100644 --- a/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi.rs +++ b/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi.rs @@ -8,4 +8,3 @@ #![no_main] //~? ERROR `-Zsanitizer-cfi-minimal-runtime` requires `-Zsanitizer=cfi` -//~? ERROR `-Zsanitizer-cfi-minimal-runtime` requires `-Zsanitizer-cfi-recover` or `-Zsanitizer-cfi-diag` diff --git a/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi.stderr b/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi.stderr index 251d0d0817631..5cb83e40dc0c4 100644 --- a/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi.stderr +++ b/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi.stderr @@ -1,6 +1,4 @@ error: `-Zsanitizer-cfi-minimal-runtime` requires `-Zsanitizer=cfi` -error: `-Zsanitizer-cfi-minimal-runtime` requires `-Zsanitizer-cfi-recover` or `-Zsanitizer-cfi-diag` - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error From f3b4f0f80c74e8ed19e38b14608effb51e7d339a Mon Sep 17 00:00:00 2001 From: "Tim (Theemathas Chirananthavat)" Date: Tue, 25 Aug 2026 07:25:17 +0700 Subject: [PATCH 12/20] Stabilize `Result::into_{ok,err}` Tracking issue: https://github.com/rust-lang/rust/issues/61695 --- compiler/rustc_arena/src/lib.rs | 2 +- compiler/rustc_data_structures/src/lib.rs | 2 +- compiler/rustc_hir_analysis/src/lib.rs | 2 +- compiler/rustc_trait_selection/src/lib.rs | 2 +- library/alloc/src/lib.rs | 1 - library/alloctests/lib.rs | 1 - library/core/src/result.rs | 8 ++------ library/coretests/tests/lib.rs | 1 - library/std/src/lib.rs | 1 - src/tools/clippy/clippy_lints/src/lib.rs | 2 +- src/tools/clippy/clippy_utils/src/lib.rs | 2 +- 11 files changed, 8 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index 0fc1f96dfe469..f2c6ffe44cdfd 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -11,13 +11,13 @@ #![allow(clippy::mut_from_ref)] // Arena allocators are one place where this pattern is fine. #![allow(internal_features)] #![cfg_attr(bootstrap, feature(never_type))] +#![cfg_attr(bootstrap, feature(unwrap_infallible))] #![cfg_attr(test, feature(test))] #![deny(unsafe_op_in_unsafe_fn)] #![doc(test(no_crate_inject, attr(deny(warnings))))] #![feature(decl_macro)] #![feature(dropck_eyepatch)] #![feature(rustc_attrs)] -#![feature(unwrap_infallible)] // tidy-alphabetical-end use std::alloc::Layout; diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 041763f57fc9e..4ebd6ef9f92b3 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -12,6 +12,7 @@ #![allow(rustc::potential_query_instability)] #![cfg_attr(bootstrap, feature(allocator_api))] #![cfg_attr(bootstrap, feature(never_type))] +#![cfg_attr(bootstrap, feature(unwrap_infallible))] #![cfg_attr(not(bootstrap), feature(allocator_ext))] #![cfg_attr(test, feature(test))] #![deny(unsafe_op_in_unsafe_fn)] @@ -35,7 +36,6 @@ #![feature(thread_id_value)] #![feature(trusted_len)] #![feature(type_alias_impl_trait)] -#![feature(unwrap_infallible)] // tidy-alphabetical-end // This allows derive macros to reference this crate diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index dbbf068185c23..c0abcc3a6119a 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -57,12 +57,12 @@ This API is completely unstable and subject to change. // tidy-alphabetical-start #![cfg_attr(bootstrap, feature(never_type))] +#![cfg_attr(bootstrap, feature(unwrap_infallible))] #![feature(default_field_values)] #![feature(gen_blocks)] #![feature(iter_intersperse)] #![feature(slice_partition_dedup)] #![feature(try_blocks)] -#![feature(unwrap_infallible)] // tidy-alphabetical-end // These are used by Clippy. diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index bbaf683f4288a..a5cb7d0c7bb1a 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -12,6 +12,7 @@ // tidy-alphabetical-start #![cfg_attr(bootstrap, feature(never_type))] +#![cfg_attr(bootstrap, feature(unwrap_infallible))] #![feature(associated_type_defaults)] #![feature(default_field_values)] #![feature(deref_patterns)] @@ -20,7 +21,6 @@ #![feature(iterator_try_reduce)] #![feature(option_into_flat_iter)] #![feature(try_blocks)] -#![feature(unwrap_infallible)] #![feature(yeet_expr)] #![recursion_limit = "512"] // For rustdoc // tidy-alphabetical-end diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index de6830a514656..5e4b3b3d536f6 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -186,7 +186,6 @@ #![feature(ub_checks)] #![feature(unicode_internals)] #![feature(unsize)] -#![feature(unwrap_infallible)] #![feature(write_all_vectored)] #![feature(wtf8_internals)] // tidy-alphabetical-end diff --git a/library/alloctests/lib.rs b/library/alloctests/lib.rs index 76550081a703c..a5f46099173c0 100644 --- a/library/alloctests/lib.rs +++ b/library/alloctests/lib.rs @@ -50,7 +50,6 @@ #![feature(trusted_random_access)] #![feature(try_reserve_kind)] #![feature(try_trait_v2)] -#![feature(unwrap_infallible)] #![feature(wtf8_internals)] // tidy-alphabetical-end // diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 472d568c5cf66..da6be4d6d48a0 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -1343,8 +1343,6 @@ impl Result { /// # Examples /// /// ``` - /// # #![feature(unwrap_infallible)] - /// /// fn only_good_news() -> Result { /// Ok("this is fine".into()) /// } @@ -1352,7 +1350,7 @@ impl Result { /// let s: String = only_good_news().into_ok(); /// println!("{s}"); /// ``` - #[unstable(feature = "unwrap_infallible", issue = "61695")] + #[stable(feature = "unwrap_infallible", since = "CURRENT_RUSTC_VERSION")] #[inline] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] @@ -1379,8 +1377,6 @@ impl Result { /// # Examples /// /// ``` - /// # #![feature(unwrap_infallible)] - /// /// fn only_bad_news() -> Result { /// Err("Oops, it failed".into()) /// } @@ -1388,7 +1384,7 @@ impl Result { /// let error: String = only_bad_news().into_err(); /// println!("{error}"); /// ``` - #[unstable(feature = "unwrap_infallible", issue = "61695")] + #[stable(feature = "unwrap_infallible", since = "CURRENT_RUSTC_VERSION")] #[inline] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index 69bc6edd1b833..c52357da0279d 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -130,7 +130,6 @@ #![feature(uint_gather_scatter_bits)] #![feature(unicode_internals)] #![feature(unsize)] -#![feature(unwrap_infallible)] // tidy-alphabetical-end #![allow(internal_features)] #![deny(implicit_provenance_casts)] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index d59d204d6e144..bfdfb6ba9a4fd 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -313,7 +313,6 @@ #![feature(try_blocks)] #![feature(try_trait_v2)] #![feature(type_alias_impl_trait)] -#![feature(unwrap_infallible)] // tidy-alphabetical-end // // Library features (core): diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index 435f787f7012f..87bb44875aee9 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -8,9 +8,9 @@ #![feature(macro_metavar_expr)] #![feature(macro_metavar_expr_concat)] #![cfg_attr(bootstrap, feature(never_type))] +#![cfg_attr(bootstrap, feature(unwrap_infallible))] #![feature(rustc_private)] #![feature(stmt_expr_attributes)] -#![feature(unwrap_infallible)] #![recursion_limit = "512"] #![expect(clippy::literal_string_with_formatting_args, clippy::must_use_candidate)] #![warn( diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 0030f1cdc8208..5579dd1fc62d8 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -1,7 +1,7 @@ +#![cfg_attr(bootstrap, feature(unwrap_infallible))] #![feature(deref_patterns)] #![feature(macro_metavar_expr)] #![feature(rustc_private)] -#![feature(unwrap_infallible)] #![recursion_limit = "512"] #![expect(clippy::missing_errors_doc, clippy::missing_panics_doc, clippy::must_use_candidate)] #![warn( From a579f7e4b5bd444a569b18ac26e9b4ab52fcc338 Mon Sep 17 00:00:00 2001 From: Jakob Koschel Date: Fri, 25 Sep 2026 08:14:05 +0000 Subject: [PATCH 13/20] Add -Ctarget-feature=-crt-static to CFI minimal runtime tests --- tests/ui/target_modifiers/auxiliary/cfi-minimal-runtime.rs | 2 +- tests/ui/target_modifiers/sanitizer-cfi-minimal-runtime.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/ui/target_modifiers/auxiliary/cfi-minimal-runtime.rs b/tests/ui/target_modifiers/auxiliary/cfi-minimal-runtime.rs index aacea1ee65dd2..689c141811f60 100644 --- a/tests/ui/target_modifiers/auxiliary/cfi-minimal-runtime.rs +++ b/tests/ui/target_modifiers/auxiliary/cfi-minimal-runtime.rs @@ -1,6 +1,6 @@ //@ no-prefer-dynamic //@ needs-sanitizer-cfi -//@ compile-flags: -Clto -Zsanitizer=cfi -Zsanitizer-cfi-recover -Zsanitizer-cfi-minimal-runtime +//@ compile-flags: -Clto -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-recover -Zsanitizer-cfi-minimal-runtime #![feature(no_core)] #![crate_type = "rlib"] diff --git a/tests/ui/target_modifiers/sanitizer-cfi-minimal-runtime.rs b/tests/ui/target_modifiers/sanitizer-cfi-minimal-runtime.rs index 45c6ad7b521a3..fe2be11e6a3d5 100644 --- a/tests/ui/target_modifiers/sanitizer-cfi-minimal-runtime.rs +++ b/tests/ui/target_modifiers/sanitizer-cfi-minimal-runtime.rs @@ -2,6 +2,7 @@ //@ needs-sanitizer-cfi //@ aux-build:cfi-minimal-runtime.rs +//@ compile-flags: -Ctarget-feature=-crt-static //@ revisions: ok wrong_flag wrong_sanitizer //@[ok] compile-flags: -Clto -Zsanitizer=cfi -Zsanitizer-cfi-recover -Zsanitizer-cfi-minimal-runtime From 08793166b03bc268c09eff6ce50d669a2ad03ff4 Mon Sep 17 00:00:00 2001 From: Jakob Koschel Date: Sat, 26 Sep 2026 09:16:32 +0000 Subject: [PATCH 14/20] Limit CFI run-make test to Linux --- tests/run-make/sanitizer-cfi-runtime/rmake.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/run-make/sanitizer-cfi-runtime/rmake.rs b/tests/run-make/sanitizer-cfi-runtime/rmake.rs index 3cad996a14054..a86e9084dff12 100644 --- a/tests/run-make/sanitizer-cfi-runtime/rmake.rs +++ b/tests/run-make/sanitizer-cfi-runtime/rmake.rs @@ -1,3 +1,5 @@ +// FIXME(#122848) Remove only-linux once OSX CFI binaries work +//@ only-linux //@ needs-sanitizer-support //@ needs-sanitizer-cfi //@ ignore-backends: gcc From 01d2c4087d4288f09e7e32fb91b0a9df75f7cafe Mon Sep 17 00:00:00 2001 From: conferatur <309554028+conferatur@users.noreply.github.com> Date: Sat, 26 Sep 2026 14:39:26 -0700 Subject: [PATCH 15/20] add automatically_derived documentation --- library/core/src/attribute_docs.rs | 74 ++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/library/core/src/attribute_docs.rs b/library/core/src/attribute_docs.rs index 584e1583c9bdb..97629be8ec6ef 100644 --- a/library/core/src/attribute_docs.rs +++ b/library/core/src/attribute_docs.rs @@ -633,3 +633,77 @@ const _: () = (); /// /// [the `non_exhaustive` attribute]: ../reference/attributes/type_system.html#the-non_exhaustive-attribute const _: () = (); + +#[doc(attribute = "automatically_derived")] +// +/// The `automatically_derived` attribute is used to indicate that an `impl` block is automatically +/// generated by a [derive macro]. It has no direct effect, but it may be used by tools and +/// diagnostic lints, such as [Clippy], to detect these automatically generated implementations. +/// +/// Example: +/// +/// ```rust +/// // Given #[derive(Clone)] on struct Example, the derive macro may produce: +/// #[automatically_derived] +/// impl ::core::clone::Clone for Example { +/// fn clone(&self) -> Self { Example } +/// } +/// # struct Example; +/// ``` +/// +/// The attribute may only be applied to an `impl` block. +/// +/// Because code generated by a macro becomes part of the source code representation of the crate +/// that calls the macro, diagnostic lints for the expanded macro will be emitted in the caller's +/// workspace (whereas warnings generated while building dependencies not in the local workspace +/// are suppressed by Cargo). This may be undesirable, so the author of the macro can use the +/// `automatically_derived` attribute to hint to tools that the generated code is not written by the +/// caller (and that tools should not render warnings for it). +/// +/// For example, this `impl` block lacks `#[automatically_derived]`: +/// +/// ```rust +/// // Suppose this impl block is the output of a derive macro +/// impl ::core::cmp::PartialEq for Example { +/// fn eq(&self, other: &Self) -> bool { true } +/// fn ne(&self, other: &Self) -> bool { !(self == other) } +/// } +/// # struct Example; +/// ``` +/// +/// In the example above, Clippy will emit the following warning: +/// +/// ```text +/// warning: re-implementing `PartialEq::ne` is unnecessary +/// --> src/lib.rs:7:9 +/// | +/// 4 | fn ne(&self, other: &Self) -> bool { !(self == other) } +/// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +/// | +/// = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#partialeq_ne_impl +/// = note: `#[warn(clippy::partialeq_ne_impl)]` on by default +/// ``` +/// +/// However, if the derive macro were written so that it outputs `#[automatically_derived]` on the +/// `impl` block, as below, then Clippy will not emit the above `partialeq_ne_impl` lint: +/// +/// ```rust +/// // Suppose this impl block is the output of a derive macro +/// #[automatically_derived] +/// impl ::core::cmp::PartialEq for Example { +/// fn eq(&self, other: &Self) -> bool { true } +/// fn ne(&self, other: &Self) -> bool { !(self == other) } +/// } +/// # struct Example; +/// ``` +/// +/// The `automatically_derived` attribute should be preferred over the [`allow`] attribute for +/// suppressing unintended user-facing diagnostics in automatically generated code. +/// +/// For more information, see the Reference on [the `automatically_derived` attribute]. +/// +/// [`allow`]: ./attribute.allow.html +/// [derive macro]: ./attr.derive.html +/// [Clippy]: https://github.com/rust-lang/rust-clippy +/// [the `automatically_derived` attribute]: ../reference/attributes/derive.html#the-automatically_derived-attribute +const _: () = (); From 9e8ca583f8115555cc39997e4468328c655879f3 Mon Sep 17 00:00:00 2001 From: khyperia <953151+khyperia@users.noreply.github.com> Date: Mon, 28 Sep 2026 15:50:47 +0200 Subject: [PATCH 16/20] implement #![feature(gca_adts)] --- Cargo.lock | 1 + compiler/rustc_ast_lowering/Cargo.toml | 1 + compiler/rustc_ast_lowering/src/lib.rs | 149 ++++++++++++------ compiler/rustc_ast_passes/src/feature_gate.rs | 59 ++++--- compiler/rustc_feature/src/lib.rs | 4 +- compiler/rustc_feature/src/unstable.rs | 34 +++- compiler/rustc_hir_analysis/src/collect.rs | 2 +- .../src/collect/generics_of.rs | 2 +- .../src/hir_ty_lowering/errors.rs | 2 +- .../src/hir_ty_lowering/mod.rs | 2 +- .../rustc_resolve/src/diagnostics/impls.rs | 25 +-- compiler/rustc_resolve/src/diagnostics/mod.rs | 4 +- compiler/rustc_resolve/src/ident.rs | 4 +- compiler/rustc_resolve/src/late.rs | 2 +- .../rustc_resolve/src/late/diagnostics.rs | 5 +- compiler/rustc_resolve/src/lib.rs | 2 +- compiler/rustc_span/src/symbol.rs | 1 + .../traits/fulfillment_errors.rs | 3 +- .../src/traits/const_evaluatable.rs | 2 +- .../rustc_trait_selection/src/traits/wf.rs | 2 +- compiler/rustc_type_ir/src/const_kind.rs | 3 - library/core/src/marker.rs | 9 +- library/std/src/lib.rs | 2 +- .../src/language-features/gca-adts.md | 21 +++ .../language-features/gca-min-const-items.md | 2 +- ...onst-pattern-field-type-mismatch-162394.rs | 13 +- ...-pattern-field-type-mismatch-162394.stderr | 2 +- .../const-generics/gca/gca-macro-fn-call.rs | 12 +- .../gca/gca-macro-fn-call.stderr | 10 +- .../gca_adts/missing-dependent-features.rs | 3 + .../missing-dependent-features.stderr | 10 ++ .../gca_adts/none-incomplete.rs | 21 +++ .../gca_adts/none-incomplete.stderr | 8 + tests/ui/const-generics/gca_adts/none.rs | 21 +++ .../inherent-type-const.rs | 5 +- .../mgca/adt_expr_arg_simple.rs | 3 +- .../mgca/adt_expr_arg_simple.stderr | 4 +- .../mgca/adt_expr_arg_tuple_expr_fail.rs | 6 +- .../mgca/adt_expr_erroneuous_inits.rs | 15 +- .../mgca/adt_expr_erroneuous_inits.stderr | 38 ++--- .../mgca/adt_expr_fields_type_check.rs | 3 +- .../mgca/adt_expr_fields_type_check.stderr | 14 +- .../mgca/adt_expr_infers_from_value.rs | 12 +- .../mgca/adt_expr_unit_enum_extra_field.rs | 8 +- .../adt_expr_unit_enum_extra_field.stderr | 6 +- .../mgca/adt_expr_unit_struct_extra_field.rs | 2 +- .../mgca/array-const-arg-len-mismatch.rs | 11 +- .../mgca/array-const-arg-len-mismatch.stderr | 20 +-- .../mgca/array-const-arg-type-mismatch.rs | 3 +- .../mgca/array-const-arg-type-mismatch.stderr | 2 +- .../mgca/array-expr-complex.r1.stderr | 2 +- .../mgca/array-expr-complex.r2.stderr | 2 +- .../mgca/array-expr-complex.r3.stderr | 2 +- .../const-generics/mgca/array-expr-complex.rs | 3 +- .../const-generics/mgca/array-expr-simple.rs | 3 +- ...array-expr-type-mismatch-in-where-bound.rs | 4 +- ...y-expr-type-mismatch-in-where-bound.stderr | 4 +- .../mgca/array-expr-with-assoc-const.rs | 3 +- .../mgca/array-expr-with-macro.rs | 3 +- .../mgca/array-expr-with-struct.rs | 3 +- .../mgca/array-expr-with-tuple.rs | 6 +- .../mgca/array-with-wrong-tuple-type.rs | 4 +- .../mgca/array_elem_type_mismatch.rs | 6 +- .../mgca/array_expr_arg_complex.rs | 3 +- .../mgca/array_expr_arg_complex.stderr | 4 +- ...eric-args-on-enum-variant-segments-fail.rs | 7 +- ...-args-on-enum-variant-segments-fail.stderr | 6 +- .../generic-args-on-enum-variant-segments.rs | 3 +- ...eneric_const_items-mismatched-array-len.rs | 10 +- ...ic_const_items-mismatched-array-len.stderr | 4 +- ...onst_parameter_types-inferred-array-len.rs | 2 +- .../mgca/generic_const_type_mismatch.rs | 8 +- .../mgca/invalid-array-in-tuple.rs | 4 +- ...ixed-direct-anon-expression-diagnostics.rs | 3 +- ...-direct-anon-expression-diagnostics.stderr | 4 +- .../mgca/nonsensical-negated-literal.rs | 4 +- .../printing_valtrees_supports_non_values.rs | 3 +- ...inting_valtrees_supports_non_values.stderr | 18 +-- .../mgca/size-of-generic-ptr-in-array-len.rs | 3 +- .../size-of-generic-ptr-in-array-len.stderr | 6 +- .../mgca/syntactic-type-mismatch.rs | 3 +- .../mgca/syntactic-type-mismatch.stderr | 4 +- .../mgca/tuple_ctor_arg_simple.rs | 3 +- .../mgca/tuple_ctor_complex_args.rs | 3 +- .../mgca/tuple_ctor_complex_args.stderr | 4 +- .../mgca/tuple_ctor_erroneous.rs | 3 +- .../mgca/tuple_ctor_erroneous.stderr | 22 +-- .../const-generics/mgca/tuple_ctor_nested.rs | 3 +- .../mgca/tuple_ctor_type_relative.rs | 3 +- .../mgca/tuple_expr_arg_bad-issue-151048.rs | 3 +- .../tuple_expr_arg_bad-issue-151048.stderr | 2 +- .../mgca/tuple_expr_arg_complex.rs | 3 +- .../mgca/tuple_expr_arg_complex.stderr | 8 +- .../mgca/tuple_expr_arg_macroless.rs | 6 +- .../mgca/tuple_expr_arg_mismatch_type.rs | 3 +- .../mgca/tuple_expr_arg_mismatch_type.stderr | 2 +- .../mgca/tuple_expr_arg_simple.rs | 3 +- .../tuple_expr_arg_unbounded_assoc_const.rs | 2 +- .../mgca/tuple_expr_type_mismatch.rs | 4 +- .../mgca/type_const-adt-expr-missing-field.rs | 12 +- .../type_const-adt-expr-missing-field.stderr | 6 +- ..._const-generic-param-in-type.nogate.stderr | 18 +-- .../mgca/type_const-generic-param-in-type.rs | 9 +- .../mgca/wrapped_array_elem_type_mismatch.rs | 2 +- .../mgca/wrong_type_const_arr_diag.rs | 3 +- .../mgca/wrong_type_const_arr_diag.stderr | 2 +- .../mgca/wrong_type_const_arr_diag_trait.rs | 3 +- .../wrong_type_const_arr_diag_trait.stderr | 2 +- .../tuple_with_infer_arg.rs | 2 +- .../ui/feature-gates/feature-gate-gca-adts.rs | 24 +++ .../feature-gate-gca-adts.without.stderr | 58 +++++++ ...ate-gca-adts.without_with_min_items.stderr | 14 ++ .../non_scalar_alignment_value.rs | 8 +- .../non_scalar_alignment_value.stderr | 8 +- ...struct-exprs-tuple-call-pretty-printing.rs | 3 +- ...ct-exprs-tuple-call-pretty-printing.stdout | 5 +- 116 files changed, 640 insertions(+), 355 deletions(-) create mode 100644 src/doc/unstable-book/src/language-features/gca-adts.md create mode 100644 tests/ui/const-generics/gca_adts/missing-dependent-features.rs create mode 100644 tests/ui/const-generics/gca_adts/missing-dependent-features.stderr create mode 100644 tests/ui/const-generics/gca_adts/none-incomplete.rs create mode 100644 tests/ui/const-generics/gca_adts/none-incomplete.stderr create mode 100644 tests/ui/const-generics/gca_adts/none.rs create mode 100644 tests/ui/feature-gates/feature-gate-gca-adts.rs create mode 100644 tests/ui/feature-gates/feature-gate-gca-adts.without.stderr create mode 100644 tests/ui/feature-gates/feature-gate-gca-adts.without_with_min_items.stderr diff --git a/Cargo.lock b/Cargo.lock index b5fb5057716ac..002ee75873ee5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3626,6 +3626,7 @@ dependencies = [ name = "rustc_ast_lowering" version = "0.0.0" dependencies = [ + "bitflags", "rustc_abi", "rustc_ast", "rustc_attr_ir", diff --git a/compiler/rustc_ast_lowering/Cargo.toml b/compiler/rustc_ast_lowering/Cargo.toml index 9dc5f81581e87..350687ba299c7 100644 --- a/compiler/rustc_ast_lowering/Cargo.toml +++ b/compiler/rustc_ast_lowering/Cargo.toml @@ -8,6 +8,7 @@ doctest = false [dependencies] # tidy-alphabetical-start +bitflags = "2.4.1" rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } rustc_attr_ir = { path = "../rustc_attr_ir" } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 4bc61a22b3b3d..eee6d7af5593d 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -56,7 +56,7 @@ use rustc_data_structures::steal::Steal; use rustc_data_structures::tagged_ptr::TaggedRef; use rustc_errors::codes::*; use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle, ErrorGuaranteed}; -use rustc_hir::def::{DefKind, Namespace, PerNS, Res}; +use rustc_hir::def::{CtorKind, DefKind, Namespace, PerNS, Res}; use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId, LocalDefIdMap}; use rustc_hir::definitions::PerParentDisambiguatorState; use rustc_hir::lints::DelayedLint; @@ -1420,10 +1420,10 @@ impl<'hir> LoweringContext<'_, 'hir> { let ct = self.arena.alloc(ct); return GenericArg::Const(ct.try_as_ambig_ct().unwrap()); } - TyKind::GcaMacro(expr) if self.tcx.features().gca_min_const_items() => { + TyKind::GcaMacro(expr) if self.tcx.features().gca() => { let ct = match self.can_lower_expr_to_const_arg_direct( expr, - DirectConstArgContext::MacrolessMinGenericConstArgs, + self.direct_const_arg_context_enabled_by_gca_macro(), ) { Ok(()) => self.lower_expr_to_const_arg_direct(expr, None), Err(e) => e.emit(self), @@ -2632,18 +2632,12 @@ impl<'hir> LoweringContext<'_, 'hir> { span: Span, ) -> hir::ConstItemRhs<'hir> { let is_direct = |body| { - if self.tcx.features().gca_macroless_items() { - self.can_lower_expr_to_const_arg_direct( - body, - DirectConstArgContext::MacrolessMinGenericConstArgs, - ) - .is_ok() + let context = if self.tcx.features().gca_macroless_items() { + self.direct_const_arg_context_enabled_by_gca_macro() } else { - // do not check can_lower_expr_to_const_arg_direct, but rather just - // ExprKind::GcaMacro, because we don't want e.g. - // `impl { const C: u8 = N; }` to be a direct-rhs const - matches!(body, Expr { kind: ExprKind::GcaMacro(_), .. }) - } + DirectConstArgContext::GCA_MACRO + }; + self.can_lower_expr_to_const_arg_direct(body, context).is_ok() }; if self.tcx.features().gca_min_const_items() && let Some(body) = body @@ -2657,13 +2651,25 @@ impl<'hir> LoweringContext<'_, 'hir> { } } + fn direct_const_arg_context_enabled_by_gca_macro(&self) -> DirectConstArgContext { + let mut result = DirectConstArgContext::GCA_BASE_FEATURES; + if self.tcx.features().gca_min_const_items() { + result |= DirectConstArgContext::GCA_MIN_CONST_ITEMS; + } + if self.tcx.features().gca_adts() { + result |= DirectConstArgContext::GCA_ADTS; + } + result + } + + /// Only valid for const *arg* contexts, not const *item* contexts. fn ambient_direct_const_arg_context(&self) -> DirectConstArgContext { if self.tcx.features().gca_macroless_args() { - DirectConstArgContext::MacrolessMinGenericConstArgs - } else if self.tcx.features().gca_min_const_items() { - DirectConstArgContext::MinGenericConstArgs + self.direct_const_arg_context_enabled_by_gca_macro() + } else if self.tcx.features().gca() { + DirectConstArgContext::GCA } else { - DirectConstArgContext::Stable + DirectConstArgContext::STABLE } } @@ -2675,9 +2681,16 @@ impl<'hir> LoweringContext<'_, 'hir> { res: Option>, context: DirectConstArgContext, ) -> Result<(), UnrepresentableConstArgError> { - if let DirectConstArgContext::MacrolessMinGenericConstArgs = context { + if context.contains(DirectConstArgContext::PATH_ANY) { + Ok(()) + } else if context.contains(DirectConstArgContext::PATH_CONST_CTOR) + && matches!(res, Some(Res::Def(DefKind::Ctor(_, CtorKind::Const), _))) + { + // FIXME(gca_adts): This check is incomplete. Type-relative paths and other complicating + // factors make things very difficult - e.g. `>::None` Ok(()) - } else if qself.is_none() + } else if context.contains(DirectConstArgContext::PATH_PLAIN_PARAM) + && qself.is_none() && path.is_single_argless_ident() && matches!(res, Some(Res::Def(DefKind::ConstParam, _))) { @@ -2693,59 +2706,61 @@ impl<'hir> LoweringContext<'_, 'hir> { expr: &Expr, context: DirectConstArgContext, ) -> Result<(), UnrepresentableConstArgError> { - use DirectConstArgContext::*; // Note the only stable case is currently ExprKind::Path - match (&expr.kind, context) { - ( - ExprKind::Call(Expr { kind: ExprKind::Path(_, _), .. }, args), - MacrolessMinGenericConstArgs, - ) => { + match &expr.kind { + ExprKind::Call(Expr { kind: ExprKind::Path(_, _), .. }, args) + if context.contains(DirectConstArgContext::TUPLE_CALL) => + { for arg in args { self.can_lower_expr_to_const_arg_direct(arg, context)?; } Ok(()) } - (ExprKind::Tup(exprs), MacrolessMinGenericConstArgs) => { + ExprKind::Tup(exprs) if context.contains(DirectConstArgContext::TUPLE) => { for expr in exprs { self.can_lower_expr_to_const_arg_direct(expr, context)?; } Ok(()) } - (ExprKind::Path(qself, path), _) => { + ExprKind::Path(qself, path) => { let res = self.get_partial_res(expr.id).and_then(|partial_res| partial_res.full_res()); self.can_lower_path_to_const_arg_direct(qself, path, expr.span, res, context) } - (ExprKind::Struct(se), MacrolessMinGenericConstArgs) => { + ExprKind::Struct(se) if context.contains(DirectConstArgContext::STRUCT) => { for f in &se.fields { self.can_lower_expr_to_const_arg_direct(&f.expr, context)?; } Ok(()) } - (ExprKind::Array(elements), MacrolessMinGenericConstArgs) => { + ExprKind::Array(elements) if context.contains(DirectConstArgContext::ARRAY) => { for element in elements { self.can_lower_expr_to_const_arg_direct(element, context)?; } Ok(()) } - (ExprKind::Underscore, MacrolessMinGenericConstArgs) => Ok(()), - (ExprKind::Paren(expr), MacrolessMinGenericConstArgs) => { + ExprKind::Underscore if context.contains(DirectConstArgContext::UNDERSCORE) => Ok(()), + ExprKind::Paren(expr) if context.contains(DirectConstArgContext::PAREN) => { self.can_lower_expr_to_const_arg_direct(expr, context) } - (ExprKind::Block(block, _), MacrolessMinGenericConstArgs) - if let [stmt] = block.stmts.as_slice() + ExprKind::Block(block, _) + if context.contains(DirectConstArgContext::BLOCK) + && let [stmt] = block.stmts.as_slice() && let StmtKind::Expr(expr) = &stmt.kind => { self.can_lower_expr_to_const_arg_direct(expr, context) } - (ExprKind::Lit(_), MacrolessMinGenericConstArgs) => Ok(()), - (ExprKind::Unary(UnOp::Neg, inner_expr), MacrolessMinGenericConstArgs) - if let ExprKind::Lit(_) = &inner_expr.kind => + ExprKind::Lit(_) if context.contains(DirectConstArgContext::LIT) => Ok(()), + ExprKind::Unary(UnOp::Neg, inner_expr) + if context.contains(DirectConstArgContext::LIT) + && let ExprKind::Lit(_) = &inner_expr.kind => { Ok(()) } - (ExprKind::ConstBlock(_), MacrolessMinGenericConstArgs) => Ok(()), - (ExprKind::GcaMacro(_), MacrolessMinGenericConstArgs | MinGenericConstArgs) => { + ExprKind::ConstBlock(_) if context.contains(DirectConstArgContext::CONST_BLOCK) => { + Ok(()) + } + ExprKind::GcaMacro(_) if context.contains(DirectConstArgContext::GCA_MACRO) => { // Always report this as able to be represented directly. If it turns out not to be, // `lower_expr_to_const_arg_direct` will report an error. Ok(()) @@ -2931,11 +2946,9 @@ impl<'hir> LoweringContext<'_, 'hir> { // `can_lower_expr_to_const_arg_direct` always returns success upon encountering a // ExprKind::GcaMacro, which effectively forces the expression to be lowered as a // direct arg. If it actually turns out to not be possible, emit an error instead. - // Always use MacrolessMinGenericConstArgs, even if we're under regular GCA, because - // that's what the macro means: to enter a context that is like macroless GCA. match self.can_lower_expr_to_const_arg_direct( expr, - DirectConstArgContext::MacrolessMinGenericConstArgs, + self.direct_const_arg_context_enabled_by_gca_macro(), ) { Ok(()) => self.lower_expr_to_const_arg_direct(expr, id_override), Err(err) => err.emit(self), @@ -3277,19 +3290,53 @@ impl<'hir> GenericArgsCtor<'hir> { } } -#[derive(Copy, Clone, Debug)] -enum DirectConstArgContext { +bitflags::bitflags! { + #[derive(Copy, Clone, Debug)] + struct DirectConstArgContext: u16 { + const TUPLE_CALL = 1 << 0; + const TUPLE = 1 << 1; + const PATH_PLAIN_PARAM = 1 << 2; + const PATH_CONST_CTOR = 1 << 3; + const PATH_ANY = 1 << 4; + const STRUCT = 1 << 5; + const ARRAY = 1 << 6; + const UNDERSCORE = 1 << 7; + const PAREN = 1 << 8; + const BLOCK = 1 << 9; + const LIT = 1 << 10; + const CONST_BLOCK = 1 << 11; + const GCA_MACRO = 1 << 12; + } +} + +impl DirectConstArgContext { /// The only allowed direct const arg representation is simple paths that nameres to generic /// const parameters. - Stable, + const STABLE: DirectConstArgContext = Self::PATH_PLAIN_PARAM; + /// The allowed representations are what is allowed on stable, plus the `gca!` macro. - MinGenericConstArgs, - /// Expressions attempt to be lowered directly, and if that fails, the expression falls back to - /// being represented as an anon const. + const GCA: DirectConstArgContext = Self::STABLE.union(Self::GCA_MACRO); + + /// These expressions are allowed inside the `gca!` macro, regardless of what feature is + /// enabling the base `gca!` functionality. /// - /// This context is also used under MinGenericConstArgs inside a `gca!` macro, for - /// simplicity, as they allow the same code. - MacrolessMinGenericConstArgs, + /// These are also allowed under macroless features without a `gca!` macro. + const GCA_BASE_FEATURES: DirectConstArgContext = Self::GCA + .union(DirectConstArgContext::UNDERSCORE) + .union(DirectConstArgContext::PAREN) + .union(DirectConstArgContext::BLOCK) + .union(DirectConstArgContext::LIT) + .union(DirectConstArgContext::CONST_BLOCK); + + /// These are allowed under `#![feature(gca_min_const_items)]` + const GCA_MIN_CONST_ITEMS: DirectConstArgContext = DirectConstArgContext::PATH_ANY; + + /// These are allowed under `#![feature(gca_adts)]` + const GCA_ADTS: DirectConstArgContext = DirectConstArgContext::PATH_CONST_CTOR + .union(DirectConstArgContext::TUPLE_CALL) + .union(DirectConstArgContext::TUPLE) + .union(DirectConstArgContext::STRUCT) + .union(DirectConstArgContext::ARRAY); } #[derive(Debug)] diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 9d0ca67ce93d5..bbc80f6a5728d 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -3,7 +3,7 @@ use rustc_ast::{self as ast, AttrVec, GenericBound, NodeId, PatKind, attr, token use rustc_attr_ir::{Attribute, AttributeKind}; use rustc_attr_parsing::AttributeParser; use rustc_errors::msg; -use rustc_feature::Features; +use rustc_feature::{DependentFeature, Features}; use rustc_session::Session; use rustc_session::diagnostics::{feature_err, feature_warn}; use rustc_span::{Span, Spanned, sym}; @@ -651,26 +651,47 @@ fn check_incompatible_features(sess: &Session, features: &Features) { } fn check_dependent_features(sess: &Session, features: &Features) { - for &(parent, children) in - rustc_feature::DEPENDENT_FEATURES.iter().filter(|(parent, _)| features.enabled(*parent)) + for &(parent, ref children) in + rustc_feature::DEPENDENT_FEATURES.iter().filter(|(parent, children)| { + features.enabled(*parent) && !check_enabled(features, children) + }) { - if children.iter().any(|f| !features.enabled(*f)) { - let parent_span = features - .enabled_features_iter_stable_order() - .find_map(|(name, span)| (name == parent).then_some(span)) - .unwrap(); - // FIXME: should probably format this in fluent instead of here - let missing = children + let parent_span = features + .enabled_features_iter_stable_order() + .find_map(|(name, span)| (name == parent).then_some(span)) + .unwrap(); + // FIXME: should probably format this in fluent instead of here + let missing = format(features, &children); + sess.dcx().emit_err(diagnostics::MissingDependentFeatures { parent_span, parent, missing }); + } + + fn check_enabled(features: &Features, feature: &DependentFeature) -> bool { + match feature { + DependentFeature::And(children) => { + children.iter().all(|child| check_enabled(features, child)) + } + DependentFeature::Or(children) => { + children.iter().any(|child| check_enabled(features, child)) + } + DependentFeature::Leaf(symbol) => features.enabled(*symbol), + } + } + + fn format(features: &Features, feature: &DependentFeature) -> String { + // FIXME: parentheses/precedence + match feature { + DependentFeature::And(children) => children .iter() - .filter(|f| !features.enabled(**f)) - .map(|s| format!("`{}`", s.as_str())) - .intersperse(String::from(", ")) - .collect(); - sess.dcx().emit_err(diagnostics::MissingDependentFeatures { - parent_span, - parent, - missing, - }); + .filter(|child| !check_enabled(features, child)) + .map(|child| format(features, child)) + .intersperse(String::from(" and ")) + .collect(), + DependentFeature::Or(children) => children + .iter() + .map(|child| format(features, child)) + .intersperse(String::from(" or ")) + .collect(), + DependentFeature::Leaf(symbol) => format!("`{}`", symbol.as_str()), } } } diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs index 5b9b899fc463f..83bf4f47a8ac9 100644 --- a/compiler/rustc_feature/src/lib.rs +++ b/compiler/rustc_feature/src/lib.rs @@ -133,6 +133,6 @@ pub use builtin_attrs::{ }; pub use removed::REMOVED_LANG_FEATURES; pub use unstable::{ - DEPENDENT_FEATURES, EnabledLangFeature, EnabledLibFeature, Features, INCOMPATIBLE_FEATURES, - TRACK_FEATURE, UNSTABLE_LANG_FEATURES, + DEPENDENT_FEATURES, DependentFeature, EnabledLangFeature, EnabledLibFeature, Features, + INCOMPATIBLE_FEATURES, TRACK_FEATURE, UNSTABLE_LANG_FEATURES, }; diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 49489c0ed903d..71ab8250254f4 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -119,6 +119,13 @@ impl Features { false } } + + /// The generic_const_args family of features has a set of common behavior that can be enabled + /// by either `gca_min_const_items` or `gca_adts`. There is no actual `gca` base feature, but + /// this method acts as one. + pub fn gca(&self) -> bool { + self.gca_min_const_items() || self.gca_adts() + } } macro_rules! declare_features { @@ -546,6 +553,8 @@ declare_features! ( (internal, freeze_impls, "1.78.0", Some(121675)), /// Frontmatter `---` blocks for use by external tools. (unstable, frontmatter, "1.88.0", Some(136889)), + /// Allows using ADTs in directly represented generic const args. + (incomplete, gca_adts, "CURRENT_RUSTC_VERSION", Some(163420)), /// Allows using generics in more complex const expressions, based on definitional equality. (incomplete, gca_const_items, "1.95.0", Some(151972)), /// Allows directly represented gca_const_items without the `gca!` macro. @@ -857,10 +866,25 @@ pub const INCOMPATIBLE_FEATURES: &[(Symbol, Symbol)] = &[ (sym::ref_pat_eat_one_layer_2024, sym::ref_pat_eat_one_layer_2024_structural), ]; +pub enum DependentFeature { + And(&'static [DependentFeature]), + Or(&'static [DependentFeature]), + Leaf(Symbol), +} + /// Some features require one or more other features to be enabled. -pub const DEPENDENT_FEATURES: &[(Symbol, &[Symbol])] = &[ - (sym::gca_const_items, &[sym::gca_min_const_items]), - (sym::gca_macroless_args, &[sym::gca_min_const_items]), - (sym::gca_macroless_items, &[sym::gca_min_const_items]), - (sym::unsized_const_params, &[sym::adt_const_params]), +pub const DEPENDENT_FEATURES: &[(Symbol, DependentFeature)] = &[ + // tidy-alphabetical-start + ( + sym::gca_adts, + DependentFeature::Or(&[ + DependentFeature::Leaf(sym::min_adt_const_params), + DependentFeature::Leaf(sym::adt_const_params), + ]), + ), + (sym::gca_const_items, DependentFeature::Leaf(sym::gca_min_const_items)), + (sym::gca_macroless_args, DependentFeature::Leaf(sym::gca_min_const_items)), + (sym::gca_macroless_items, DependentFeature::Leaf(sym::gca_min_const_items)), + (sym::unsized_const_params, DependentFeature::Leaf(sym::adt_const_params)), + // tidy-alphabetical-end ]; diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index c3cc3bcd6cd0c..9504fce939733 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1803,7 +1803,7 @@ fn anon_const_kind<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ty::AnonConstKin debug_assert_matches!(const_arg.kind, hir::ConstArgKind::Anon(hir::AnonConst { def_id, .. }) if *def_id == def); if tcx.features().generic_const_exprs() { ty::AnonConstKind::GCE - } else if tcx.features().gca_min_const_items() { + } else if tcx.features().gca() { ty::AnonConstKind::MCG } else if let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Repeat(_, repeat_count), diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 9605c777e55a9..4d43a9ca5700e 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -224,7 +224,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { // Node::AnonConst, or whether it will be represented directly, so it must generate a // DefId. If it ends up being direct, this DefId is then attached to the top-level // ConstArg, which is what we are seeing here. - debug_assert!(tcx.features().gca_min_const_items()); + debug_assert!(tcx.features().gca()); // Forward to the real parent. Some(tcx.local_parent(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 bee062b27e0f5..1538b3afaf236 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -370,7 +370,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { && let Some(hir_ty) = constraint.ty() && let ty = self.lower_ty(hir_ty) && (ty.is_enum() || ty.references_error()) - && tcx.features().gca_min_const_items() + && tcx.features().gca() { Some(diagnostics::AssocKindMismatchWrapInBracesSugg { lo: hir_ty.span.shrink_to_lo(), 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 e9dc2a61d698d..037996fc926b2 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -3120,7 +3120,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }) } - /// `def_id` is a const item used in the type system. Checks if that's OK. + /// `alias_const` is a const item used in the type system. Checks if that's OK. fn check_const_item_in_type_system( &self, alias_const: ty::AliasConstKind<'tcx>, diff --git a/compiler/rustc_resolve/src/diagnostics/impls.rs b/compiler/rustc_resolve/src/diagnostics/impls.rs index 2ea2f52c696ba..bf1feb2ae5172 100644 --- a/compiler/rustc_resolve/src/diagnostics/impls.rs +++ b/compiler/rustc_resolve/src/diagnostics/impls.rs @@ -1327,18 +1327,19 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { enable_feature: self.tcx().sess.is_nightly_build(), }) } - ResolutionError::ParamInNonTrivialAnonConst { is_gca, name, param_kind: is_type } => { - self.dcx().create_err(diagnostics::ParamInNonTrivialAnonConst { - span, - name, - param_kind: is_type, - help: self.tcx.sess.is_nightly_build() - && !self.tcx.features().gca_min_const_items(), - is_gca, - help_gca: is_gca, - help_suggest_gca: self.tcx.sess.is_nightly_build() && !is_gca, - }) - } + ResolutionError::ParamInNonTrivialAnonConst { + is_gca_const_items, + name, + param_kind, + } => self.dcx().create_err(diagnostics::ParamInNonTrivialAnonConst { + span, + name, + param_kind, + help: self.tcx.sess.is_nightly_build() && !self.tcx.features().gca(), + is_gca_const_items, + help_gca: is_gca_const_items, + help_suggest_gca: self.tcx.sess.is_nightly_build() && !is_gca_const_items, + }), ResolutionError::ParamInEnumDiscriminant { name, param_kind: is_type } => { self.dcx().create_err(diagnostics::ParamInEnumDiscriminant { span, diff --git a/compiler/rustc_resolve/src/diagnostics/mod.rs b/compiler/rustc_resolve/src/diagnostics/mod.rs index ae4f7cabbe87f..c0e687fc94a38 100644 --- a/compiler/rustc_resolve/src/diagnostics/mod.rs +++ b/compiler/rustc_resolve/src/diagnostics/mod.rs @@ -409,7 +409,7 @@ pub(crate) struct SelfInConstGenericTy { #[derive(Diagnostic)] #[diag( - "{$is_gca -> + "{$is_gca_const_items -> [true] generic parameters in const blocks are not allowed; use a named `const` item instead *[false] generic parameters may not be used in const operations }" @@ -423,7 +423,7 @@ pub(crate) struct ParamInNonTrivialAnonConst { pub(crate) param_kind: ParamKindInNonTrivialAnonConst, #[help("add `#![feature(generic_const_exprs)]` to allow generic const expressions")] pub(crate) help: bool, - pub(crate) is_gca: bool, + pub(crate) is_gca_const_items: bool, #[help( "consider factoring the expression into a `type const` item and use it as the const argument instead" )] diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index d743093aae92f..138bb4bd72ab0 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -1658,7 +1658,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } NoConstantGenericsReason::NonTrivialConstArg => { ResolutionError::ParamInNonTrivialAnonConst { - is_gca: self.features.gca_const_items(), + is_gca_const_items: self.features.gca_const_items(), name: rib_ident.name, param_kind: ParamKindInNonTrivialAnonConst::Type, } @@ -1750,7 +1750,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } NoConstantGenericsReason::NonTrivialConstArg => { ResolutionError::ParamInNonTrivialAnonConst { - is_gca: self.features.gca_const_items(), + is_gca_const_items: self.features.gca_const_items(), name: rib_ident.name, param_kind: ParamKindInNonTrivialAnonConst::Const { name: rib_ident.name, diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index e1787eadf5fb9..ebb041bf3878d 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -5232,7 +5232,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { AnonConstKind::InlineConst => ConstantHasGenerics::Yes, AnonConstKind::ConstArg(_) | AnonConstKind::ArrayLength => { if self.r.features.generic_const_exprs() - || self.r.features.gca_min_const_items() + || self.r.features.gca() || is_trivial_const_arg { ConstantHasGenerics::Yes diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 84c07d0fb0f44..6a4bc7470038d 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -4163,9 +4163,8 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { span: lifetime_ref.ident.span, name: lifetime_ref.ident.name, param_kind: diagnostics::ParamKindInNonTrivialAnonConst::Lifetime, - help: self.r.tcx.sess.is_nightly_build() - && !self.r.features.gca_min_const_items(), - is_gca: self.r.features.gca_const_items(), + help: self.r.tcx.sess.is_nightly_build() && !self.r.features.gca(), + is_gca_const_items: self.r.features.gca_const_items(), help_gca: self.r.features.gca_const_items(), help_suggest_gca: self.r.tcx.sess.is_nightly_build() && !self.r.features.gca_const_items(), diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 0a96becf993e9..b62ad9a708c29 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -304,7 +304,7 @@ enum ResolutionError<'ra> { /// /// This error is only emitted when using `min_const_generics`. ParamInNonTrivialAnonConst { - is_gca: bool, + is_gca_const_items: bool, name: Symbol, param_kind: ParamKindInNonTrivialAnonConst, }, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index e62ad42875248..68e7ee914f483 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1067,6 +1067,7 @@ symbols! { future_trait, fxsr, gca, + gca_adts, gca_const_items, gca_macroless_args, gca_macroless_items, 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 63b0733b0a095..e751c87d37007 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 @@ -3984,8 +3984,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { obligation: &PredicateObligation<'tcx>, span: Span, ) -> Result, ErrorGuaranteed> { - if !self.tcx.features().generic_const_exprs() && !self.tcx.features().gca_min_const_items() - { + if !self.tcx.features().generic_const_exprs() && !self.tcx.features().gca() { let guar = self .dcx() .struct_span_err(span, "constant expression depends on a generic parameter") diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 9acc0682e6641..242aa260b8372 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -84,7 +84,7 @@ pub fn is_const_evaluatable<'tcx>( } _ => bug!("unexpected constkind in `is_const_evalautable: {unexpanded_ct:?}`"), } - } else if tcx.features().gca_min_const_items() { + } else if tcx.features().gca() { // This is a sanity check to make sure that non-generics consts are checked to // be evaluatable in case they aren't cchecked elsewhere. This will NOT error // if the const uses generics, as desired. diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 955ab1799a794..ba463184a41f8 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -1169,7 +1169,7 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { } ty::ConstKind::Value(val) => { // FIXME(mgca): no need to feature-gate once valtree lifetimes are not erased - if tcx.features().gca_min_const_items() { + if tcx.features().gca() { match val.ty.kind() { ty::Adt(adt_def, args) => { let adt_val = val.destructure_adt_const(); diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs index d969cca3dcda2..1ef498f072f22 100644 --- a/compiler/rustc_type_ir/src/const_kind.rs +++ b/compiler/rustc_type_ir/src/const_kind.rs @@ -280,9 +280,6 @@ pub enum AnonConstKind { /// `feature(generic_const_exprs)` anon consts are allowed to use arbitrary generic parameters in scope GCE, /// stable `min_const_generics` anon consts are not allowed to use any generic parameters - /// - /// under `feature(gca_min_const_items)`, these may be inline consts as well, and should be - /// treated the same as anon consts. MCG, /// anon consts used as the length of a repeat expr are syntactically allowed to use generic parameters /// but must not depend on the actual instantiation. See #76200 for more information diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 514c2aa1c9bd1..d1a68412247ef 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -1074,13 +1074,20 @@ pub const trait Destruct: PointeeSized {} #[rustc_dyn_incompatible_trait] pub trait Tuple {} +// HACK(khyperia): if this is missing, the gca macro's `implied_by = "gca_adts"` emits an error +#[unstable(feature = "gca_adts", issue = "163420")] +#[expect(dead_code)] +struct HackGcaAdtsFeature; + /// Creates a new style directly represented const argument. /// ```ignore (cannot test this from within core yet) /// const BAR: usize = gca!(N); /// const FOO: usize = gca!(BAR::); /// ``` #[rustc_builtin_macro(gca)] -#[unstable(feature = "gca_min_const_items", issue = "132980")] +// HACK: abuse implied_by, this should be enabled if gca_min_const_items or gca_adts is enabled, +// neither one is more particularly special than the other +#[unstable(feature = "gca_min_const_items", issue = "132980", implied_by = "gca_adts")] #[macro_export] macro_rules! gca { ($($arg:tt)*) => { diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index f716f49ffd60a..6d579f0cb9601 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -758,7 +758,7 @@ pub use core::concat_bytes; )] #[unstable(feature = "derive_macro_global_path", issue = "154645")] pub use core::derive; -#[unstable(feature = "gca_min_const_items", issue = "132980")] +#[unstable(feature = "gca_min_const_items", issue = "132980", implied_by = "gca_adts")] pub use core::gca; #[stable(feature = "matches_macro", since = "1.42.0")] pub use core::matches; diff --git a/src/doc/unstable-book/src/language-features/gca-adts.md b/src/doc/unstable-book/src/language-features/gca-adts.md new file mode 100644 index 0000000000000..49905d57a9a4c --- /dev/null +++ b/src/doc/unstable-book/src/language-features/gca-adts.md @@ -0,0 +1,21 @@ +# gca_adts + +Enables ADTs under the generic const args family of features (e.g. `gca!` macro). + +The tracking issue for this feature is: [#163420] + +[#163420]: https://github.com/rust-lang/rust/issues/163420 + +## Examples + +```rust +#![feature(gca_min_const_items, min_adt_const_params, gca_adts)] + +use std::gca; + +struct S; + +fn main() { + let _: S = S::; +} +``` diff --git a/src/doc/unstable-book/src/language-features/gca-min-const-items.md b/src/doc/unstable-book/src/language-features/gca-min-const-items.md index 4027e782714ed..486db1f50885b 100644 --- a/src/doc/unstable-book/src/language-features/gca-min-const-items.md +++ b/src/doc/unstable-book/src/language-features/gca-min-const-items.md @@ -1,6 +1,6 @@ # gca_min_const_items -Enables the generic const args MVP (paths to direct const items and constructors for ADTs and primitives). +Enables the generic const args MVP (paths to direct const items and primitives). The tracking issue for this feature is: [#132980] diff --git a/tests/ui/const-generics/gca/const-pattern-field-type-mismatch-162394.rs b/tests/ui/const-generics/gca/const-pattern-field-type-mismatch-162394.rs index 7600c4882a91c..b4bfdb494a863 100644 --- a/tests/ui/const-generics/gca/const-pattern-field-type-mismatch-162394.rs +++ b/tests/ui/const-generics/gca/const-pattern-field-type-mismatch-162394.rs @@ -1,10 +1,13 @@ //@ compile-flags: -Znext-solver=globally -#![allow(incomplete_features)] -#![feature(gca_macroless_args)] -#![feature(gca_macroless_items)] -#![feature(gca_const_items, gca_min_const_items)] -#![feature(min_adt_const_params)] +#![feature( + gca_adts, + gca_const_items, + gca_macroless_args, + gca_macroless_items, + gca_min_const_items, + min_adt_const_params +)] use std::marker::ConstParamTy; diff --git a/tests/ui/const-generics/gca/const-pattern-field-type-mismatch-162394.stderr b/tests/ui/const-generics/gca/const-pattern-field-type-mismatch-162394.stderr index 9dd229cc46a34..42d1d8b5fd1d7 100644 --- a/tests/ui/const-generics/gca/const-pattern-field-type-mismatch-162394.stderr +++ b/tests/ui/const-generics/gca/const-pattern-field-type-mismatch-162394.stderr @@ -1,5 +1,5 @@ error: the constant `"foo"` is not of type `()` - --> $DIR/const-pattern-field-type-mismatch-162394.rs:17:5 + --> $DIR/const-pattern-field-type-mismatch-162394.rs:20:5 | LL | const A2: Foo = Self::FooA("foo"); | ^^^^^^^^^^^^^ expected `()`, found `&'static str` diff --git a/tests/ui/const-generics/gca/gca-macro-fn-call.rs b/tests/ui/const-generics/gca/gca-macro-fn-call.rs index 6035c14e5eb75..73945b14af4b9 100644 --- a/tests/ui/const-generics/gca/gca-macro-fn-call.rs +++ b/tests/ui/const-generics/gca/gca-macro-fn-call.rs @@ -13,10 +13,14 @@ //! tuple-variant constructor (unions, primitives, foreign types), not just structs. //@ compile-flags: -Znext-solver -#![feature(gca_min_const_items, gca_macroless_args)] -#![feature(gca_const_items)] -#![feature(extern_types)] -#![expect(incomplete_features)] +#![feature( + extern_types, + gca_adts, + gca_const_items, + gca_macroless_args, + gca_min_const_items, + min_adt_const_params +)] struct FieldName([u8; N]); diff --git a/tests/ui/const-generics/gca/gca-macro-fn-call.stderr b/tests/ui/const-generics/gca/gca-macro-fn-call.stderr index 1399bcb1dee92..4b7bf15ace96d 100644 --- a/tests/ui/const-generics/gca/gca-macro-fn-call.stderr +++ b/tests/ui/const-generics/gca/gca-macro-fn-call.stderr @@ -1,29 +1,29 @@ error: complex const arguments must be placed inside of a `const` block - --> $DIR/gca-macro-fn-call.rs:35:23 + --> $DIR/gca-macro-fn-call.rs:39:23 | LL | fn bad(_: FieldName<{ FieldName::len() }>) {} | ^^^^^^^^^^^^^^^^ error: complex const arguments must be placed inside of a `const` block - --> $DIR/gca-macro-fn-call.rs:44:31 + --> $DIR/gca-macro-fn-call.rs:48:31 | LL | fn bad_tracing(_: FieldName<{ FieldName::len_of("id") }>) {} | ^^^^^^^^^^^^^^^^^^^^^^^ error: complex const arguments must be placed inside of a `const` block - --> $DIR/gca-macro-fn-call.rs:61:23 + --> $DIR/gca-macro-fn-call.rs:65:23 | LL | fn bad_union(_: Tag<{ Tag::width() }>) {} | ^^^^^^^^^^^^ error: complex const arguments must be placed inside of a `const` block - --> $DIR/gca-macro-fn-call.rs:70:28 + --> $DIR/gca-macro-fn-call.rs:74:28 | LL | fn bad_prim(_: FieldName<{ u32::from_str_radix("10", 10) }>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: complex const arguments must be placed inside of a `const` block - --> $DIR/gca-macro-fn-call.rs:81:31 + --> $DIR/gca-macro-fn-call.rs:85:31 | LL | fn bad_foreign(_: FieldName<{ Opaque::foo() }>) {} | ^^^^^^^^^^^^^ diff --git a/tests/ui/const-generics/gca_adts/missing-dependent-features.rs b/tests/ui/const-generics/gca_adts/missing-dependent-features.rs new file mode 100644 index 0000000000000..55a6338dadb64 --- /dev/null +++ b/tests/ui/const-generics/gca_adts/missing-dependent-features.rs @@ -0,0 +1,3 @@ +#![feature(gca_adts)] +//~^ ERROR `gca_adts` requires `min_adt_const_params` or `adt_const_params` to be enabled +fn main() {} diff --git a/tests/ui/const-generics/gca_adts/missing-dependent-features.stderr b/tests/ui/const-generics/gca_adts/missing-dependent-features.stderr new file mode 100644 index 0000000000000..19c96d5d7bd9e --- /dev/null +++ b/tests/ui/const-generics/gca_adts/missing-dependent-features.stderr @@ -0,0 +1,10 @@ +error: `gca_adts` requires `min_adt_const_params` or `adt_const_params` to be enabled + --> $DIR/missing-dependent-features.rs:1:12 + | +LL | #![feature(gca_adts)] + | ^^^^^^^^ + | + = help: enable all of these features + +error: aborting due to 1 previous error + diff --git a/tests/ui/const-generics/gca_adts/none-incomplete.rs b/tests/ui/const-generics/gca_adts/none-incomplete.rs new file mode 100644 index 0000000000000..76078a42fa08a --- /dev/null +++ b/tests/ui/const-generics/gca_adts/none-incomplete.rs @@ -0,0 +1,21 @@ +//! This test file ought to be part of `none.rs`, but, type-relative paths are difficult + +#![feature(gca_adts, adt_const_params)] + +use std::gca; +use std::marker::ConstParamTy; + +#[derive(ConstParamTy, PartialEq, Eq)] +enum MyOption { + MySome, + MyNone, +} + +use MyOption::*; + +struct Struct; + +fn main() { + let _: Struct::MyNone)>; + //~^ ERROR complex const arguments must be placed inside of a `const` block +} diff --git a/tests/ui/const-generics/gca_adts/none-incomplete.stderr b/tests/ui/const-generics/gca_adts/none-incomplete.stderr new file mode 100644 index 0000000000000..bf8c538207579 --- /dev/null +++ b/tests/ui/const-generics/gca_adts/none-incomplete.stderr @@ -0,0 +1,8 @@ +error: complex const arguments must be placed inside of a `const` block + --> $DIR/none-incomplete.rs:19:24 + | +LL | let _: Struct::MyNone)>; + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/const-generics/gca_adts/none.rs b/tests/ui/const-generics/gca_adts/none.rs new file mode 100644 index 0000000000000..223f01d81a5a8 --- /dev/null +++ b/tests/ui/const-generics/gca_adts/none.rs @@ -0,0 +1,21 @@ +//@check-pass + +#![feature(gca_adts, adt_const_params)] + +use std::gca; +use std::marker::ConstParamTy; + +#[derive(ConstParamTy, PartialEq, Eq)] +enum MyOption { + MySome, + MyNone, +} + +use MyOption::*; + +struct Struct; + +fn main() { + let _: Struct; + let _: Struct; +} diff --git a/tests/ui/const-generics/generic_const_parameter_types/inherent-type-const.rs b/tests/ui/const-generics/generic_const_parameter_types/inherent-type-const.rs index b4fe7a9a5da2a..0053db1608ea4 100644 --- a/tests/ui/const-generics/generic_const_parameter_types/inherent-type-const.rs +++ b/tests/ui/const-generics/generic_const_parameter_types/inherent-type-const.rs @@ -3,11 +3,12 @@ //@[next] compile-flags: -Znext-solver //@ ignore-compare-mode-next-solver (explicit revisions) #![feature( + const_param_ty_trait, + gca_adts, gca_min_const_items, generic_const_parameter_types, inherent_associated_types, - min_adt_const_params, - const_param_ty_trait + min_adt_const_params )] use std::gca; diff --git a/tests/ui/const-generics/mgca/adt_expr_arg_simple.rs b/tests/ui/const-generics/mgca/adt_expr_arg_simple.rs index 112cf5563a59e..cd90cc6f66b99 100644 --- a/tests/ui/const-generics/mgca/adt_expr_arg_simple.rs +++ b/tests/ui/const-generics/mgca/adt_expr_arg_simple.rs @@ -1,5 +1,4 @@ -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] use std::gca; diff --git a/tests/ui/const-generics/mgca/adt_expr_arg_simple.stderr b/tests/ui/const-generics/mgca/adt_expr_arg_simple.stderr index 96f8461b9cb82..70ed0cbc41f64 100644 --- a/tests/ui/const-generics/mgca/adt_expr_arg_simple.stderr +++ b/tests/ui/const-generics/mgca/adt_expr_arg_simple.stderr @@ -1,11 +1,11 @@ error: complex const arguments must be placed inside of a `const` block - --> $DIR/adt_expr_arg_simple.rs:31:35 + --> $DIR/adt_expr_arg_simple.rs:30:35 | LL | foo::<{ gca!(Some:: { 0: N + 1 }) }>(); | ^^^^^ error: generic parameters may not be used in const operations - --> $DIR/adt_expr_arg_simple.rs:36:38 + --> $DIR/adt_expr_arg_simple.rs:35:38 | LL | foo::<{ Some:: { 0: const { N + 1 } } }>(); | ^ diff --git a/tests/ui/const-generics/mgca/adt_expr_arg_tuple_expr_fail.rs b/tests/ui/const-generics/mgca/adt_expr_arg_tuple_expr_fail.rs index c488b90aec14b..c9652b1c83385 100644 --- a/tests/ui/const-generics/mgca/adt_expr_arg_tuple_expr_fail.rs +++ b/tests/ui/const-generics/mgca/adt_expr_arg_tuple_expr_fail.rs @@ -1,10 +1,10 @@ #![feature( - gca_min_const_items, - gca_macroless_args, adt_const_params, + gca_adts, + gca_macroless_args, + gca_min_const_items, unsized_const_params )] -#![expect(incomplete_features)] trait Trait { #[rustc_always_gca] diff --git a/tests/ui/const-generics/mgca/adt_expr_erroneuous_inits.rs b/tests/ui/const-generics/mgca/adt_expr_erroneuous_inits.rs index 20bac03fab1c0..5bcfea9246066 100644 --- a/tests/ui/const-generics/mgca/adt_expr_erroneuous_inits.rs +++ b/tests/ui/const-generics/mgca/adt_expr_erroneuous_inits.rs @@ -1,26 +1,27 @@ -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] #![crate_type = "lib"] // Miscellaneous assortment of invalid cases of directly represented // `ConstArgKind::Struct`'s under mgca. #[derive(Eq, PartialEq, std::marker::ConstParamTy)] -struct Foo { field: T } +struct Foo { + field: T, +} fn NonStruct() {} fn accepts>() {} fn bar() { - accepts::<{ Foo:: { }}>(); + accepts::<{ Foo:: {} }>(); //~^ ERROR: struct expression with missing field initialiser for `field` - accepts::<{ Foo:: { field: const { 1 }, field: const { 2} }}>(); + accepts::<{ Foo:: { field: const { 1 }, field: const { 2 } } }>(); //~^ ERROR: struct expression with multiple initialisers for `field` - accepts::<{ Fooo:: { field: const { 1 } }}>(); + accepts::<{ Fooo:: { field: const { 1 } } }>(); //~^ ERROR: cannot find struct, variant or union type `Fooo` in this scope //~| ERROR: struct expression with invalid base path - accepts::<{ NonStruct { }}>(); + accepts::<{ NonStruct {} }>(); //~^ ERROR: cannot find struct, variant or union type `NonStruct` in this scope //~| ERROR: struct expression with invalid base path } diff --git a/tests/ui/const-generics/mgca/adt_expr_erroneuous_inits.stderr b/tests/ui/const-generics/mgca/adt_expr_erroneuous_inits.stderr index 370a73b5a4bc6..707cfa1b73b31 100644 --- a/tests/ui/const-generics/mgca/adt_expr_erroneuous_inits.stderr +++ b/tests/ui/const-generics/mgca/adt_expr_erroneuous_inits.stderr @@ -1,51 +1,51 @@ error[E0422]: cannot find struct, variant or union type `Fooo` in this scope - --> $DIR/adt_expr_erroneuous_inits.rs:20:17 + --> $DIR/adt_expr_erroneuous_inits.rs:21:17 | -LL | accepts::<{ Fooo:: { field: const { 1 } }}>(); +LL | accepts::<{ Fooo:: { field: const { 1 } } }>(); | ^^^^ not found in this scope | note: similarly named struct `Foo` defined here - --> $DIR/adt_expr_erroneuous_inits.rs:9:1 + --> $DIR/adt_expr_erroneuous_inits.rs:8:1 | -LL | struct Foo { field: T } +LL | struct Foo { | ^^^^^^^^^^^^^ help: a struct with a similar name exists | -LL - accepts::<{ Fooo:: { field: const { 1 } }}>(); -LL + accepts::<{ Foo:: { field: const { 1 } }}>(); +LL - accepts::<{ Fooo:: { field: const { 1 } } }>(); +LL + accepts::<{ Foo:: { field: const { 1 } } }>(); | error[E0574]: cannot find struct, variant or union type `NonStruct` in this scope - --> $DIR/adt_expr_erroneuous_inits.rs:23:17 + --> $DIR/adt_expr_erroneuous_inits.rs:24:17 | -LL | accepts::<{ NonStruct { }}>(); +LL | accepts::<{ NonStruct {} }>(); | ^^^^^^^^^ not found in this scope | = note: a function named `NonStruct` exists in another namespace error: struct expression with missing field initialiser for `field` - --> $DIR/adt_expr_erroneuous_inits.rs:16:17 + --> $DIR/adt_expr_erroneuous_inits.rs:17:17 | -LL | accepts::<{ Foo:: { }}>(); - | ^^^^^^^^^^^^^ +LL | accepts::<{ Foo:: {} }>(); + | ^^^^^^^^^^^^ error: struct expression with multiple initialisers for `field` - --> $DIR/adt_expr_erroneuous_inits.rs:18:49 + --> $DIR/adt_expr_erroneuous_inits.rs:19:49 | -LL | accepts::<{ Foo:: { field: const { 1 }, field: const { 2} }}>(); - | ^^^^^^^^^^^^^^^^^ +LL | accepts::<{ Foo:: { field: const { 1 }, field: const { 2 } } }>(); + | ^^^^^^^^^^^^^^^^^^ error: struct expression with invalid base path - --> $DIR/adt_expr_erroneuous_inits.rs:20:17 + --> $DIR/adt_expr_erroneuous_inits.rs:21:17 | -LL | accepts::<{ Fooo:: { field: const { 1 } }}>(); +LL | accepts::<{ Fooo:: { field: const { 1 } } }>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: struct expression with invalid base path - --> $DIR/adt_expr_erroneuous_inits.rs:23:17 + --> $DIR/adt_expr_erroneuous_inits.rs:24:17 | -LL | accepts::<{ NonStruct { }}>(); - | ^^^^^^^^^^^^^ +LL | accepts::<{ NonStruct {} }>(); + | ^^^^^^^^^^^^ error: aborting due to 6 previous errors diff --git a/tests/ui/const-generics/mgca/adt_expr_fields_type_check.rs b/tests/ui/const-generics/mgca/adt_expr_fields_type_check.rs index 38eb04760c598..f4b59aaa1404e 100644 --- a/tests/ui/const-generics/mgca/adt_expr_fields_type_check.rs +++ b/tests/ui/const-generics/mgca/adt_expr_fields_type_check.rs @@ -1,5 +1,4 @@ -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] #[derive(Eq, PartialEq, std::marker::ConstParamTy)] struct S1 { diff --git a/tests/ui/const-generics/mgca/adt_expr_fields_type_check.stderr b/tests/ui/const-generics/mgca/adt_expr_fields_type_check.stderr index 81f7c5366b461..dea156db19c14 100644 --- a/tests/ui/const-generics/mgca/adt_expr_fields_type_check.stderr +++ b/tests/ui/const-generics/mgca/adt_expr_fields_type_check.stderr @@ -1,41 +1,41 @@ error: the constant `N` is not of type `u8` - --> $DIR/adt_expr_fields_type_check.rs:24:19 + --> $DIR/adt_expr_fields_type_check.rs:23:19 | LL | accepts_1::<{ S1:: { f1: N, f2: N } }>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u8`, found `bool` error: the constant `N` is not of type `isize` - --> $DIR/adt_expr_fields_type_check.rs:24:19 + --> $DIR/adt_expr_fields_type_check.rs:23:19 | LL | accepts_1::<{ S1:: { f1: N, f2: N } }>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `isize`, found `bool` error: the constant `N` is not of type `u8` - --> $DIR/adt_expr_fields_type_check.rs:27:19 + --> $DIR/adt_expr_fields_type_check.rs:26:19 | LL | accepts_2::<{ S2::(N, N) }>(); | ^^^^^^^^^^^^^^ expected `u8`, found `bool` error: the constant `N` is not of type `isize` - --> $DIR/adt_expr_fields_type_check.rs:27:19 + --> $DIR/adt_expr_fields_type_check.rs:26:19 | LL | accepts_2::<{ S2::(N, N) }>(); | ^^^^^^^^^^^^^^ expected `isize`, found `bool` error: the constant `N` is not of type `u8` - --> $DIR/adt_expr_fields_type_check.rs:30:19 + --> $DIR/adt_expr_fields_type_check.rs:29:19 | LL | accepts_3::<{ En::Var1::(N, N) }>(); | ^^^^^^^^^^^^^^^^^^^^ expected `u8`, found `bool` error: the constant `N` is not of type `i64` - --> $DIR/adt_expr_fields_type_check.rs:32:19 + --> $DIR/adt_expr_fields_type_check.rs:31:19 | LL | accepts_3::<{ En::Var2:: { field: N } }>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i64`, found `bool` error[E0308]: mismatched types - --> $DIR/adt_expr_fields_type_check.rs:34:51 + --> $DIR/adt_expr_fields_type_check.rs:33:51 | LL | accepts_3::<{ En::Var2:: { field: const { false } } }>(); | ^^^^^ expected `i64`, found `bool` diff --git a/tests/ui/const-generics/mgca/adt_expr_infers_from_value.rs b/tests/ui/const-generics/mgca/adt_expr_infers_from_value.rs index 30b8ca3dd2752..13feedadbcfd7 100644 --- a/tests/ui/const-generics/mgca/adt_expr_infers_from_value.rs +++ b/tests/ui/const-generics/mgca/adt_expr_infers_from_value.rs @@ -1,14 +1,14 @@ //@ check-pass #![feature( - generic_const_items, - gca_min_const_items, - gca_macroless_args, adt_const_params, - generic_const_parameter_types, - const_param_ty_trait + const_param_ty_trait, + gca_adts, + gca_macroless_args, + gca_min_const_items, + generic_const_items, + generic_const_parameter_types )] -#![expect(incomplete_features)] use std::gca; use std::marker::{ConstParamTy, ConstParamTy_, PhantomData}; diff --git a/tests/ui/const-generics/mgca/adt_expr_unit_enum_extra_field.rs b/tests/ui/const-generics/mgca/adt_expr_unit_enum_extra_field.rs index d48b5cb9e7100..7cc24d660d04c 100644 --- a/tests/ui/const-generics/mgca/adt_expr_unit_enum_extra_field.rs +++ b/tests/ui/const-generics/mgca/adt_expr_unit_enum_extra_field.rs @@ -1,13 +1,13 @@ -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] #[derive(Eq, PartialEq, std::marker::ConstParamTy)] enum E { - S {} + S {}, } fn foo() {} fn main() { - foo::<{E::S { x: const { 1 } }}>(); - //~^ ERROR variant `E::S` has no field named `x` [E0559] + foo::<{ E::S { x: const { 1 } } }>(); + //~^ ERROR variant `E::S` has no field named `x` [E0559] } diff --git a/tests/ui/const-generics/mgca/adt_expr_unit_enum_extra_field.stderr b/tests/ui/const-generics/mgca/adt_expr_unit_enum_extra_field.stderr index 7ac3b28cdca5b..8d201a2b8943c 100644 --- a/tests/ui/const-generics/mgca/adt_expr_unit_enum_extra_field.stderr +++ b/tests/ui/const-generics/mgca/adt_expr_unit_enum_extra_field.stderr @@ -1,8 +1,8 @@ error[E0559]: variant `E::S` has no field named `x` - --> $DIR/adt_expr_unit_enum_extra_field.rs:11:19 + --> $DIR/adt_expr_unit_enum_extra_field.rs:11:20 | -LL | foo::<{E::S { x: const { 1 } }}>(); - | ^ `E::S` does not have this field +LL | foo::<{ E::S { x: const { 1 } } }>(); + | ^ `E::S` does not have this field error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/mgca/adt_expr_unit_struct_extra_field.rs b/tests/ui/const-generics/mgca/adt_expr_unit_struct_extra_field.rs index 0eaadd1a9b31d..68a1600e218eb 100644 --- a/tests/ui/const-generics/mgca/adt_expr_unit_struct_extra_field.rs +++ b/tests/ui/const-generics/mgca/adt_expr_unit_struct_extra_field.rs @@ -1,4 +1,4 @@ -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] #[derive(Eq, PartialEq, std::marker::ConstParamTy)] struct Foo; diff --git a/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.rs b/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.rs index 134a82e9d3490..59587c0093295 100644 --- a/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.rs +++ b/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.rs @@ -2,9 +2,14 @@ //! //! Ensure that providing an array const arg with the wrong number of elements //! doesn't ICE or silently cause UB. -#![expect(incomplete_features)] -#![feature(adt_const_params, gca_min_const_items, gca_macroless_args)] -#![feature(unsized_const_params, generic_const_parameter_types)] +#![feature( + adt_const_params, + gca_adts, + gca_macroless_args, + gca_min_const_items, + generic_const_parameter_types, + unsized_const_params +)] use std::gca; use std::marker::ConstParamTy_; diff --git a/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.stderr b/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.stderr index 72c2a367c7246..c0625e737d307 100644 --- a/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.stderr +++ b/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.stderr @@ -1,59 +1,59 @@ error: the constant `*b""` is not of type `[u8; 2]` - --> $DIR/array-const-arg-len-mismatch.rs:31:11 + --> $DIR/array-const-arg-len-mismatch.rs:36:11 | LL | foo::(); | ^^ expected `[u8; 2]`, found `[u8; 0]` | note: required by a const generic parameter in `foo` - --> $DIR/array-const-arg-len-mismatch.rs:12:42 + --> $DIR/array-const-arg-len-mismatch.rs:17:42 | LL | fn foo() -> [T; N] { | ^^^^^^^^^^^^^^^ required by this const generic parameter in `foo` error: the constant `*b"\x00\x00\x00"` is not of type `[u8; 2]` - --> $DIR/array-const-arg-len-mismatch.rs:33:11 + --> $DIR/array-const-arg-len-mismatch.rs:38:11 | LL | foo::(); | ^^ expected `[u8; 2]`, found `[u8; 3]` | note: required by a const generic parameter in `foo` - --> $DIR/array-const-arg-len-mismatch.rs:12:42 + --> $DIR/array-const-arg-len-mismatch.rs:17:42 | LL | fn foo() -> [T; N] { | ^^^^^^^^^^^^^^^ required by this const generic parameter in `foo` error: the constant `*b""` is not of type `[u8; 2]` - --> $DIR/array-const-arg-len-mismatch.rs:35:13 + --> $DIR/array-const-arg-len-mismatch.rs:40:13 | LL | bar::<{ [] }>(); | ^^ expected `[u8; 2]`, found `[u8; 0]` | note: required by a const generic parameter in `bar` - --> $DIR/array-const-arg-len-mismatch.rs:16:8 + --> $DIR/array-const-arg-len-mismatch.rs:21:8 | LL | fn bar() {} | ^^^^^^^^^^^^^^^^ required by this const generic parameter in `bar` error: the constant `*b"\x01\x02\x03"` is not of type `[u8; 2]` - --> $DIR/array-const-arg-len-mismatch.rs:37:13 + --> $DIR/array-const-arg-len-mismatch.rs:42:13 | LL | bar::<{ [1, 2, 3] }>(); | ^^^^^^^^^ expected `[u8; 2]`, found `[u8; 3]` | note: required by a const generic parameter in `bar` - --> $DIR/array-const-arg-len-mismatch.rs:16:8 + --> $DIR/array-const-arg-len-mismatch.rs:21:8 | LL | fn bar() {} | ^^^^^^^^^^^^^^^^ required by this const generic parameter in `bar` error: the constant `*b"*"` is not of type `[u8; 3]` - --> $DIR/array-const-arg-len-mismatch.rs:39:13 + --> $DIR/array-const-arg-len-mismatch.rs:44:13 | LL | baz::<{ [42] }>(); | ^^^^ expected `[u8; 3]`, found `[u8; 1]` | note: required by a const generic parameter in `baz` - --> $DIR/array-const-arg-len-mismatch.rs:28:8 + --> $DIR/array-const-arg-len-mismatch.rs:33:8 | LL | fn baz::LEN]>() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this const generic parameter in `baz` diff --git a/tests/ui/const-generics/mgca/array-const-arg-type-mismatch.rs b/tests/ui/const-generics/mgca/array-const-arg-type-mismatch.rs index def077e4d292d..a6d1acb773a23 100644 --- a/tests/ui/const-generics/mgca/array-const-arg-type-mismatch.rs +++ b/tests/ui/const-generics/mgca/array-const-arg-type-mismatch.rs @@ -1,5 +1,4 @@ -#![expect(incomplete_features)] -#![feature(adt_const_params, gca_min_const_items, gca_macroless_args)] +#![feature(adt_const_params, gca_adts, gca_min_const_items, gca_macroless_args)] use std::marker::ConstParamTy; #[derive(Eq, PartialEq, ConstParamTy)] diff --git a/tests/ui/const-generics/mgca/array-const-arg-type-mismatch.stderr b/tests/ui/const-generics/mgca/array-const-arg-type-mismatch.stderr index 573620366cbce..f8b9a3c9cee37 100644 --- a/tests/ui/const-generics/mgca/array-const-arg-type-mismatch.stderr +++ b/tests/ui/const-generics/mgca/array-const-arg-type-mismatch.stderr @@ -1,5 +1,5 @@ error: the constant `Bar` is not of type `Foo` - --> $DIR/array-const-arg-type-mismatch.rs:13:14 + --> $DIR/array-const-arg-type-mismatch.rs:12:14 | LL | test::<{ [Bar] }>(); | ^^^^^ expected `Foo`, found `Bar` diff --git a/tests/ui/const-generics/mgca/array-expr-complex.r1.stderr b/tests/ui/const-generics/mgca/array-expr-complex.r1.stderr index 2e3b2172b7325..43a8312a21dbd 100644 --- a/tests/ui/const-generics/mgca/array-expr-complex.r1.stderr +++ b/tests/ui/const-generics/mgca/array-expr-complex.r1.stderr @@ -1,5 +1,5 @@ error: complex const arguments must be placed inside of a `const` block - --> $DIR/array-expr-complex.rs:13:33 + --> $DIR/array-expr-complex.rs:12:33 | LL | takes_array::<{ gca!([1, 2, 1 + 2]) }>(); | ^^^^^ diff --git a/tests/ui/const-generics/mgca/array-expr-complex.r2.stderr b/tests/ui/const-generics/mgca/array-expr-complex.r2.stderr index 2b25efb6ab090..ed9e7d184c023 100644 --- a/tests/ui/const-generics/mgca/array-expr-complex.r2.stderr +++ b/tests/ui/const-generics/mgca/array-expr-complex.r2.stderr @@ -1,5 +1,5 @@ error: complex const arguments must be placed inside of a `const` block - --> $DIR/array-expr-complex.rs:16:26 + --> $DIR/array-expr-complex.rs:15:26 | LL | takes_array::<{ gca!([X; 3]) }>(); | ^^^^^^ diff --git a/tests/ui/const-generics/mgca/array-expr-complex.r3.stderr b/tests/ui/const-generics/mgca/array-expr-complex.r3.stderr index 09515bafa7025..e67703aab474f 100644 --- a/tests/ui/const-generics/mgca/array-expr-complex.r3.stderr +++ b/tests/ui/const-generics/mgca/array-expr-complex.r3.stderr @@ -1,5 +1,5 @@ error: complex const arguments must be placed inside of a `const` block - --> $DIR/array-expr-complex.rs:19:26 + --> $DIR/array-expr-complex.rs:18:26 | LL | takes_array::<{ gca!([0; Y]) }>(); | ^^^^^^ diff --git a/tests/ui/const-generics/mgca/array-expr-complex.rs b/tests/ui/const-generics/mgca/array-expr-complex.rs index 1c96c492b3cfd..12104e5c5bd08 100644 --- a/tests/ui/const-generics/mgca/array-expr-complex.rs +++ b/tests/ui/const-generics/mgca/array-expr-complex.rs @@ -1,7 +1,6 @@ //@ revisions: r1 r2 r3 -#![expect(incomplete_features)] -#![feature(gca_min_const_items, adt_const_params)] +#![feature(gca_adts, gca_min_const_items, adt_const_params)] use std::gca; diff --git a/tests/ui/const-generics/mgca/array-expr-simple.rs b/tests/ui/const-generics/mgca/array-expr-simple.rs index eba86898c41a1..d9436afb6015d 100644 --- a/tests/ui/const-generics/mgca/array-expr-simple.rs +++ b/tests/ui/const-generics/mgca/array-expr-simple.rs @@ -1,6 +1,5 @@ //@ run-pass -#![expect(incomplete_features)] -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] #![allow(dead_code)] fn takes_array_u32() {} diff --git a/tests/ui/const-generics/mgca/array-expr-type-mismatch-in-where-bound.rs b/tests/ui/const-generics/mgca/array-expr-type-mismatch-in-where-bound.rs index a7582258de2f5..fe1641ff38b2f 100644 --- a/tests/ui/const-generics/mgca/array-expr-type-mismatch-in-where-bound.rs +++ b/tests/ui/const-generics/mgca/array-expr-type-mismatch-in-where-bound.rs @@ -1,7 +1,5 @@ //! regression test for -#![feature(gca_min_const_items, gca_macroless_args)] -#![feature(adt_const_params)] -#![expect(incomplete_features)] +#![feature(adt_const_params, gca_adts, gca_min_const_items, gca_macroless_args)] trait Trait1 {} trait Trait2 {} diff --git a/tests/ui/const-generics/mgca/array-expr-type-mismatch-in-where-bound.stderr b/tests/ui/const-generics/mgca/array-expr-type-mismatch-in-where-bound.stderr index 169282547fc1d..f930849466eae 100644 --- a/tests/ui/const-generics/mgca/array-expr-type-mismatch-in-where-bound.stderr +++ b/tests/ui/const-generics/mgca/array-expr-type-mismatch-in-where-bound.stderr @@ -1,11 +1,11 @@ error: expected `usize`, found const array - --> $DIR/array-expr-type-mismatch-in-where-bound.rs:11:17 + --> $DIR/array-expr-type-mismatch-in-where-bound.rs:9:17 | LL | T: Trait1<{ [] }>, | ^^ error: type annotations needed for the literal - --> $DIR/array-expr-type-mismatch-in-where-bound.rs:17:15 + --> $DIR/array-expr-type-mismatch-in-where-bound.rs:15:15 | LL | T: Trait2<3>, | ^ diff --git a/tests/ui/const-generics/mgca/array-expr-with-assoc-const.rs b/tests/ui/const-generics/mgca/array-expr-with-assoc-const.rs index 85ef64c498a4c..5b22ff101030b 100644 --- a/tests/ui/const-generics/mgca/array-expr-with-assoc-const.rs +++ b/tests/ui/const-generics/mgca/array-expr-with-assoc-const.rs @@ -1,6 +1,5 @@ //@ run-pass -#![expect(incomplete_features)] -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] #![allow(dead_code)] fn takes_array() {} diff --git a/tests/ui/const-generics/mgca/array-expr-with-macro.rs b/tests/ui/const-generics/mgca/array-expr-with-macro.rs index db768339118f3..bf586b90a8e5a 100644 --- a/tests/ui/const-generics/mgca/array-expr-with-macro.rs +++ b/tests/ui/const-generics/mgca/array-expr-with-macro.rs @@ -1,6 +1,5 @@ //@ run-pass -#![expect(incomplete_features)] -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] #![allow(dead_code)] macro_rules! make_array { diff --git a/tests/ui/const-generics/mgca/array-expr-with-struct.rs b/tests/ui/const-generics/mgca/array-expr-with-struct.rs index 1d4c051e53f0b..bdc7b6009ea04 100644 --- a/tests/ui/const-generics/mgca/array-expr-with-struct.rs +++ b/tests/ui/const-generics/mgca/array-expr-with-struct.rs @@ -1,6 +1,5 @@ //@ run-pass -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] #![allow(dead_code)] use std::marker::ConstParamTy; diff --git a/tests/ui/const-generics/mgca/array-expr-with-tuple.rs b/tests/ui/const-generics/mgca/array-expr-with-tuple.rs index f429ca20ce832..a4749c63f3a8a 100644 --- a/tests/ui/const-generics/mgca/array-expr-with-tuple.rs +++ b/tests/ui/const-generics/mgca/array-expr-with-tuple.rs @@ -1,11 +1,11 @@ //@ run-pass #![feature( - gca_min_const_items, - gca_macroless_args, adt_const_params, + gca_adts, + gca_macroless_args, + gca_min_const_items, unsized_const_params )] -#![expect(incomplete_features)] #![allow(dead_code)] fn takes_tuple() {} diff --git a/tests/ui/const-generics/mgca/array-with-wrong-tuple-type.rs b/tests/ui/const-generics/mgca/array-with-wrong-tuple-type.rs index a4131a22337aa..624484c4d1467 100644 --- a/tests/ui/const-generics/mgca/array-with-wrong-tuple-type.rs +++ b/tests/ui/const-generics/mgca/array-with-wrong-tuple-type.rs @@ -1,10 +1,10 @@ #![feature( adt_const_params, - gca_min_const_items, + gca_adts, gca_macroless_args, + gca_min_const_items, unsized_const_params )] -#![allow(incomplete_features)] use std::marker::ConstParamTy; diff --git a/tests/ui/const-generics/mgca/array_elem_type_mismatch.rs b/tests/ui/const-generics/mgca/array_elem_type_mismatch.rs index aa6385c28ded0..7b5f3747f5a58 100644 --- a/tests/ui/const-generics/mgca/array_elem_type_mismatch.rs +++ b/tests/ui/const-generics/mgca/array_elem_type_mismatch.rs @@ -1,10 +1,10 @@ //! Regression test for -#![expect(incomplete_features)] #![feature( adt_const_params, - generic_const_parameter_types, + gca_adts, + gca_macroless_args, gca_min_const_items, - gca_macroless_args + generic_const_parameter_types )] fn foo() {} diff --git a/tests/ui/const-generics/mgca/array_expr_arg_complex.rs b/tests/ui/const-generics/mgca/array_expr_arg_complex.rs index 7edeb25f30e48..308ba90d72646 100644 --- a/tests/ui/const-generics/mgca/array_expr_arg_complex.rs +++ b/tests/ui/const-generics/mgca/array_expr_arg_complex.rs @@ -1,5 +1,4 @@ -#![feature(gca_min_const_items, adt_const_params, unsized_const_params)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, adt_const_params, unsized_const_params)] use std::gca; diff --git a/tests/ui/const-generics/mgca/array_expr_arg_complex.stderr b/tests/ui/const-generics/mgca/array_expr_arg_complex.stderr index b044775b80c94..fd963a5055d0e 100644 --- a/tests/ui/const-generics/mgca/array_expr_arg_complex.stderr +++ b/tests/ui/const-generics/mgca/array_expr_arg_complex.stderr @@ -1,11 +1,11 @@ error: complex const arguments must be placed inside of a `const` block - --> $DIR/array_expr_arg_complex.rs:15:30 + --> $DIR/array_expr_arg_complex.rs:14:30 | LL | takes_array::<{ gca!([N, N + 1]) }>(); | ^^^^^ error: complex const arguments must be placed inside of a `const` block - --> $DIR/array_expr_arg_complex.rs:16:42 + --> $DIR/array_expr_arg_complex.rs:15:42 | LL | takes_tuple_with_array::<{ gca!(([N, N + 1], N)) }>(); | ^^^^^ diff --git a/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.rs b/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.rs index 9642a066ad32b..258160017f179 100644 --- a/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.rs +++ b/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.rs @@ -1,15 +1,18 @@ -#![feature(gca_min_const_items)] -#![feature(adt_const_params, unsized_const_params)] +#![feature(adt_const_params, gca_adts, gca_min_const_items, unsized_const_params)] + use std::gca; + #[derive(PartialEq, Eq, std::marker::ConstParamTy)] pub enum Enum { Unit, Tuple(), Store(T), } + pub mod module { pub use super::Enum::Store; } + fn main() { const _: Enum<()> = gca!(Enum::<()>::Unit::<()>); //~^ ERROR: type arguments are not allowed on unit variant `Unit` [E0109] diff --git a/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.stderr b/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.stderr index 02903379932ae..c9d8033d15b68 100644 --- a/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.stderr +++ b/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.stderr @@ -1,5 +1,5 @@ error[E0109]: type arguments are not allowed on unit variant `Unit` - --> $DIR/generic-args-on-enum-variant-segments-fail.rs:14:49 + --> $DIR/generic-args-on-enum-variant-segments-fail.rs:17:49 | LL | const _: Enum<()> = gca!(Enum::<()>::Unit::<()>); | ---- ^^ type argument not allowed @@ -14,7 +14,7 @@ LL + const _: Enum<()> = gca!(Enum::<()>::Unit); | error[E0109]: type arguments are not allowed on tuple variant `Tuple` - --> $DIR/generic-args-on-enum-variant-segments-fail.rs:16:50 + --> $DIR/generic-args-on-enum-variant-segments-fail.rs:19:50 | LL | const _: Enum<()> = gca!(Enum::<()>::Tuple::<()>()); | ----- ^^ type argument not allowed @@ -29,7 +29,7 @@ LL + const _: Enum<()> = gca!(Enum::<()>::Tuple()); | error[E0109]: type arguments are not allowed on module `generic_args_on_enum_variant_segments_fail` - --> $DIR/generic-args-on-enum-variant-segments-fail.rs:18:37 + --> $DIR/generic-args-on-enum-variant-segments-fail.rs:21:37 | LL | const _: Enum<()> = gca!(self::::Enum::<()>::Store); | ---- ^^^ type argument not allowed diff --git a/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments.rs b/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments.rs index f89dd4b87f32a..b705e695754da 100644 --- a/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments.rs +++ b/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments.rs @@ -1,7 +1,6 @@ //@ check-pass -#![feature(gca_min_const_items)] -#![feature(adt_const_params, unsized_const_params)] +#![feature(adt_const_params, gca_adts, gca_min_const_items, unsized_const_params)] use std::gca; diff --git a/tests/ui/const-generics/mgca/generic_const_items-mismatched-array-len.rs b/tests/ui/const-generics/mgca/generic_const_items-mismatched-array-len.rs index 009722fbe93a5..2377a3051307c 100644 --- a/tests/ui/const-generics/mgca/generic_const_items-mismatched-array-len.rs +++ b/tests/ui/const-generics/mgca/generic_const_items-mismatched-array-len.rs @@ -1,7 +1,11 @@ //! Regression test for #160553 (used to ICE) -#![allow(incomplete_features)] -#![feature(adt_const_params, gca_min_const_items, gca_macroless_args)] -#![feature(generic_const_parameter_types)] +#![feature( + adt_const_params, + gca_adts, + gca_macroless_args, + gca_min_const_items, + generic_const_parameter_types +)] use std::gca; diff --git a/tests/ui/const-generics/mgca/generic_const_items-mismatched-array-len.stderr b/tests/ui/const-generics/mgca/generic_const_items-mismatched-array-len.stderr index 4906b05939900..08c115d5dedb5 100644 --- a/tests/ui/const-generics/mgca/generic_const_items-mismatched-array-len.stderr +++ b/tests/ui/const-generics/mgca/generic_const_items-mismatched-array-len.stderr @@ -1,11 +1,11 @@ error: the constant `*b"\x01\x02\x03"` is not of type `[u8; ::LEN]` - --> $DIR/generic_const_items-mismatched-array-len.rs:23:11 + --> $DIR/generic_const_items-mismatched-array-len.rs:27:11 | LL | foo::() | ^ expected `[u8; ::LEN]`, found `[u8; 3]` | note: required by a const generic parameter in `foo` - --> $DIR/generic_const_items-mismatched-array-len.rs:18:18 + --> $DIR/generic_const_items-mismatched-array-len.rs:22:18 | LL | fn foo::LEN]>() -> [u8; ::LEN] { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this const generic parameter in `foo` diff --git a/tests/ui/const-generics/mgca/generic_const_parameter_types-inferred-array-len.rs b/tests/ui/const-generics/mgca/generic_const_parameter_types-inferred-array-len.rs index 075237a2094b5..bdf7a50bd3041 100644 --- a/tests/ui/const-generics/mgca/generic_const_parameter_types-inferred-array-len.rs +++ b/tests/ui/const-generics/mgca/generic_const_parameter_types-inferred-array-len.rs @@ -1,6 +1,6 @@ //@ check-pass -#![feature(min_adt_const_params, gca_min_const_items, generic_const_parameter_types)] +#![feature(min_adt_const_params, gca_adts, gca_min_const_items, generic_const_parameter_types)] use std::gca; diff --git a/tests/ui/const-generics/mgca/generic_const_type_mismatch.rs b/tests/ui/const-generics/mgca/generic_const_type_mismatch.rs index aecd2b81b1c02..5563d35bb92af 100644 --- a/tests/ui/const-generics/mgca/generic_const_type_mismatch.rs +++ b/tests/ui/const-generics/mgca/generic_const_type_mismatch.rs @@ -1,11 +1,11 @@ //! Regression test for -#![expect(incomplete_features)] #![feature( adt_const_params, - generic_const_items, - generic_const_parameter_types, + const_param_ty_trait, + gca_adts, gca_min_const_items, - const_param_ty_trait + generic_const_items, + generic_const_parameter_types )] use std::gca; diff --git a/tests/ui/const-generics/mgca/invalid-array-in-tuple.rs b/tests/ui/const-generics/mgca/invalid-array-in-tuple.rs index 69c45462fb011..80bfe0d13b35e 100644 --- a/tests/ui/const-generics/mgca/invalid-array-in-tuple.rs +++ b/tests/ui/const-generics/mgca/invalid-array-in-tuple.rs @@ -1,10 +1,10 @@ #![feature( adt_const_params, - gca_min_const_items, + gca_adts, gca_macroless_args, + gca_min_const_items, unsized_const_params )] -#![allow(incomplete_features)] use std::marker::ConstParamTy; diff --git a/tests/ui/const-generics/mgca/mixed-direct-anon-expression-diagnostics.rs b/tests/ui/const-generics/mgca/mixed-direct-anon-expression-diagnostics.rs index 995f715984d54..3654a2c6ff249 100644 --- a/tests/ui/const-generics/mgca/mixed-direct-anon-expression-diagnostics.rs +++ b/tests/ui/const-generics/mgca/mixed-direct-anon-expression-diagnostics.rs @@ -2,8 +2,7 @@ //! things that must be an anon const, are currently less than ideal. This test merely asserts the //! current (bad) state of diagnostics, so we can track improvements over time. -#![feature(gca_min_const_items, min_adt_const_params)] -#![allow(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, min_adt_const_params)] use std::gca; diff --git a/tests/ui/const-generics/mgca/mixed-direct-anon-expression-diagnostics.stderr b/tests/ui/const-generics/mgca/mixed-direct-anon-expression-diagnostics.stderr index 4d5f071037f97..744014bb18ca5 100644 --- a/tests/ui/const-generics/mgca/mixed-direct-anon-expression-diagnostics.stderr +++ b/tests/ui/const-generics/mgca/mixed-direct-anon-expression-diagnostics.stderr @@ -1,11 +1,11 @@ error: complex const arguments must be placed inside of a `const` block - --> $DIR/mixed-direct-anon-expression-diagnostics.rs:15:20 + --> $DIR/mixed-direct-anon-expression-diagnostics.rs:14:20 | LL | f::<{ gca!((N, 1 + 1)) }>(); | ^^^^^ error: generic parameters may not be used in const operations - --> $DIR/mixed-direct-anon-expression-diagnostics.rs:13:12 + --> $DIR/mixed-direct-anon-expression-diagnostics.rs:12:12 | LL | f::<{ (N, 1 + 1) }>(); | ^ diff --git a/tests/ui/const-generics/mgca/nonsensical-negated-literal.rs b/tests/ui/const-generics/mgca/nonsensical-negated-literal.rs index c5f3a6caeb112..5680e0fffe5f9 100644 --- a/tests/ui/const-generics/mgca/nonsensical-negated-literal.rs +++ b/tests/ui/const-generics/mgca/nonsensical-negated-literal.rs @@ -1,10 +1,10 @@ #![feature( adt_const_params, - gca_min_const_items, + gca_adts, gca_macroless_args, + gca_min_const_items, unsized_const_params )] -#![expect(incomplete_features)] use std::marker::ConstParamTy; diff --git a/tests/ui/const-generics/mgca/printing_valtrees_supports_non_values.rs b/tests/ui/const-generics/mgca/printing_valtrees_supports_non_values.rs index 6888a45c3bd3f..d35971802e7f2 100644 --- a/tests/ui/const-generics/mgca/printing_valtrees_supports_non_values.rs +++ b/tests/ui/const-generics/mgca/printing_valtrees_supports_non_values.rs @@ -1,8 +1,7 @@ //! Regression test for //@ edition: 2024 -#![allow(incomplete_features)] -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] #[derive(Eq, PartialEq, core::marker::ConstParamTy)] struct Foo; diff --git a/tests/ui/const-generics/mgca/printing_valtrees_supports_non_values.stderr b/tests/ui/const-generics/mgca/printing_valtrees_supports_non_values.stderr index 0184aebf157ae..9087f98cbb3f4 100644 --- a/tests/ui/const-generics/mgca/printing_valtrees_supports_non_values.stderr +++ b/tests/ui/const-generics/mgca/printing_valtrees_supports_non_values.stderr @@ -1,29 +1,29 @@ error: the constant `Option::::Some(N)` is not of type `Foo` - --> $DIR/printing_valtrees_supports_non_values.rs:18:13 + --> $DIR/printing_valtrees_supports_non_values.rs:17:13 | LL | foo::<{ Option::Some:: { 0: N } }>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Foo`, found `Option` | note: required by a const generic parameter in `foo` - --> $DIR/printing_valtrees_supports_non_values.rs:15:8 + --> $DIR/printing_valtrees_supports_non_values.rs:14:8 | LL | fn foo() {} | ^^^^^^^^^^^^ required by this const generic parameter in `foo` error: the constant `Option::::Some(::ASSOC)` is not of type `Foo` - --> $DIR/printing_valtrees_supports_non_values.rs:23:13 + --> $DIR/printing_valtrees_supports_non_values.rs:22:13 | LL | foo::<{ Option::Some:: { 0: ::ASSOC } }>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Foo`, found `Option` | note: required by a const generic parameter in `foo` - --> $DIR/printing_valtrees_supports_non_values.rs:15:8 + --> $DIR/printing_valtrees_supports_non_values.rs:14:8 | LL | fn foo() {} | ^^^^^^^^^^^^ required by this const generic parameter in `foo` error[E0277]: the trait bound `T: Trait` is not satisfied - --> $DIR/printing_valtrees_supports_non_values.rs:30:5 + --> $DIR/printing_valtrees_supports_non_values.rs:29:5 | LL | foo::<{ Option::Some:: { 0: ::ASSOC } }>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `T` @@ -34,25 +34,25 @@ LL | fn test_ice_missing_bound() { | +++++++ error: the constant `Option::::Some(_)` is not of type `Foo` - --> $DIR/printing_valtrees_supports_non_values.rs:30:13 + --> $DIR/printing_valtrees_supports_non_values.rs:29:13 | LL | foo::<{ Option::Some:: { 0: ::ASSOC } }>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Foo`, found `Option` | note: required by a const generic parameter in `foo` - --> $DIR/printing_valtrees_supports_non_values.rs:15:8 + --> $DIR/printing_valtrees_supports_non_values.rs:14:8 | LL | fn foo() {} | ^^^^^^^^^^^^ required by this const generic parameter in `foo` error: the constant `Option::::Some(_)` is not of type `Foo` - --> $DIR/printing_valtrees_supports_non_values.rs:36:13 + --> $DIR/printing_valtrees_supports_non_values.rs:35:13 | LL | foo::<{ Option::Some:: { 0: _ } }>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Foo`, found `Option` | note: required by a const generic parameter in `foo` - --> $DIR/printing_valtrees_supports_non_values.rs:15:8 + --> $DIR/printing_valtrees_supports_non_values.rs:14:8 | LL | fn foo() {} | ^^^^^^^^^^^^ required by this const generic parameter in `foo` diff --git a/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.rs b/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.rs index 9a4d4ca05be33..115b32d91ea46 100644 --- a/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.rs +++ b/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.rs @@ -1,6 +1,5 @@ //! regression test for -#![expect(incomplete_features)] -#![feature(gca_min_const_items, gca_macroless_args)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, min_adt_const_params)] fn foo() { [0; size_of::<*mut T>()]; diff --git a/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.stderr b/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.stderr index 1abfff9518f44..2d725d66fcdc4 100644 --- a/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.stderr +++ b/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.stderr @@ -1,17 +1,17 @@ error: function items cannot be used as const args - --> $DIR/size-of-generic-ptr-in-array-len.rs:6:9 + --> $DIR/size-of-generic-ptr-in-array-len.rs:5:9 | LL | [0; size_of::<*mut T>()]; | ^^^^^^^^^^^^^^^^^ error: tuple constructor with invalid base path - --> $DIR/size-of-generic-ptr-in-array-len.rs:6:9 + --> $DIR/size-of-generic-ptr-in-array-len.rs:5:9 | LL | [0; size_of::<*mut T>()]; | ^^^^^^^^^^^^^^^^^^^ error: generic parameters may not be used in const operations - --> $DIR/size-of-generic-ptr-in-array-len.rs:9:32 + --> $DIR/size-of-generic-ptr-in-array-len.rs:8:32 | LL | [0; const { size_of::<*mut T>() }]; | ^ diff --git a/tests/ui/const-generics/mgca/syntactic-type-mismatch.rs b/tests/ui/const-generics/mgca/syntactic-type-mismatch.rs index f14309f7492f4..9cca963a13f00 100644 --- a/tests/ui/const-generics/mgca/syntactic-type-mismatch.rs +++ b/tests/ui/const-generics/mgca/syntactic-type-mismatch.rs @@ -1,8 +1,7 @@ // This test ensures proper diagnostics emission during HIR ty lowering // See https://github.com/rust-lang/rust/issues/153254 -#![feature(gca_min_const_items)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, min_adt_const_params)] use std::gca; diff --git a/tests/ui/const-generics/mgca/syntactic-type-mismatch.stderr b/tests/ui/const-generics/mgca/syntactic-type-mismatch.stderr index 3d09bbdab6072..73f0e76498770 100644 --- a/tests/ui/const-generics/mgca/syntactic-type-mismatch.stderr +++ b/tests/ui/const-generics/mgca/syntactic-type-mismatch.stderr @@ -1,11 +1,11 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants - --> $DIR/syntactic-type-mismatch.rs:9:11 + --> $DIR/syntactic-type-mismatch.rs:8:11 | LL | const T0: _ = gca!(()); | ^ not allowed in type signatures error: missing type for `const` item - --> $DIR/syntactic-type-mismatch.rs:12:9 + --> $DIR/syntactic-type-mismatch.rs:11:9 | LL | const T1 = gca!([0]); | ^ diff --git a/tests/ui/const-generics/mgca/tuple_ctor_arg_simple.rs b/tests/ui/const-generics/mgca/tuple_ctor_arg_simple.rs index da66ce8195d0f..318bf82691316 100644 --- a/tests/ui/const-generics/mgca/tuple_ctor_arg_simple.rs +++ b/tests/ui/const-generics/mgca/tuple_ctor_arg_simple.rs @@ -1,6 +1,5 @@ //@ run-pass -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] #![allow(dead_code)] use std::marker::ConstParamTy; diff --git a/tests/ui/const-generics/mgca/tuple_ctor_complex_args.rs b/tests/ui/const-generics/mgca/tuple_ctor_complex_args.rs index 42ebe44172b05..f16106cd798d0 100644 --- a/tests/ui/const-generics/mgca/tuple_ctor_complex_args.rs +++ b/tests/ui/const-generics/mgca/tuple_ctor_complex_args.rs @@ -1,5 +1,4 @@ -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] use std::gca; use std::marker::ConstParamTy; diff --git a/tests/ui/const-generics/mgca/tuple_ctor_complex_args.stderr b/tests/ui/const-generics/mgca/tuple_ctor_complex_args.stderr index 925572c27cb0b..e3f6b3b8834b2 100644 --- a/tests/ui/const-generics/mgca/tuple_ctor_complex_args.stderr +++ b/tests/ui/const-generics/mgca/tuple_ctor_complex_args.stderr @@ -1,11 +1,11 @@ error: complex const arguments must be placed inside of a `const` block - --> $DIR/tuple_ctor_complex_args.rs:13:31 + --> $DIR/tuple_ctor_complex_args.rs:12:31 | LL | with_point::<{ gca!(Point(N + 1, N)) }>(); | ^^^^^ error: generic parameters may not be used in const operations - --> $DIR/tuple_ctor_complex_args.rs:16:34 + --> $DIR/tuple_ctor_complex_args.rs:15:34 | LL | with_point::<{ Point(const { N + 1 }, N) }>(); | ^ diff --git a/tests/ui/const-generics/mgca/tuple_ctor_erroneous.rs b/tests/ui/const-generics/mgca/tuple_ctor_erroneous.rs index db158f3f38b00..6e720aba1b4ac 100644 --- a/tests/ui/const-generics/mgca/tuple_ctor_erroneous.rs +++ b/tests/ui/const-generics/mgca/tuple_ctor_erroneous.rs @@ -1,5 +1,4 @@ -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] use std::gca; use std::marker::ConstParamTy; diff --git a/tests/ui/const-generics/mgca/tuple_ctor_erroneous.stderr b/tests/ui/const-generics/mgca/tuple_ctor_erroneous.stderr index 56b11b2894aa2..b9bbfcc37469d 100644 --- a/tests/ui/const-generics/mgca/tuple_ctor_erroneous.stderr +++ b/tests/ui/const-generics/mgca/tuple_ctor_erroneous.stderr @@ -1,5 +1,5 @@ error[E0425]: cannot find function, tuple struct or tuple variant `UnresolvedIdent` in this scope - --> $DIR/tuple_ctor_erroneous.rs:30:23 + --> $DIR/tuple_ctor_erroneous.rs:29:23 | LL | accepts_point::<{ UnresolvedIdent(N, N) }>(); | ^^^^^^^^^^^^^^^ not found in this scope @@ -10,61 +10,61 @@ LL | fn test_errors() { | +++++++++++++++++++++++++++++++++++ error: tuple constructor has 2 arguments but 1 were provided - --> $DIR/tuple_ctor_erroneous.rs:24:23 + --> $DIR/tuple_ctor_erroneous.rs:23:23 | LL | accepts_point::<{ Point(N) }>(); | ^^^^^^^^ error: tuple constructor has 2 arguments but 3 were provided - --> $DIR/tuple_ctor_erroneous.rs:27:23 + --> $DIR/tuple_ctor_erroneous.rs:26:23 | LL | accepts_point::<{ Point(N, N, N) }>(); | ^^^^^^^^^^^^^^ error: tuple constructor with invalid base path - --> $DIR/tuple_ctor_erroneous.rs:30:23 + --> $DIR/tuple_ctor_erroneous.rs:29:23 | LL | accepts_point::<{ UnresolvedIdent(N, N) }>(); | ^^^^^^^^^^^^^^^^^^^^^ error: function items cannot be used as const args - --> $DIR/tuple_ctor_erroneous.rs:34:23 + --> $DIR/tuple_ctor_erroneous.rs:33:23 | LL | accepts_point::<{ non_ctor(N, N) }>(); | ^^^^^^^^ error: tuple constructor with invalid base path - --> $DIR/tuple_ctor_erroneous.rs:34:23 + --> $DIR/tuple_ctor_erroneous.rs:33:23 | LL | accepts_point::<{ non_ctor(N, N) }>(); | ^^^^^^^^^^^^^^ error: tuple constructor with invalid base path - --> $DIR/tuple_ctor_erroneous.rs:38:23 + --> $DIR/tuple_ctor_erroneous.rs:37:23 | LL | accepts_point::<{ CONST_ITEM(N, N) }>(); | ^^^^^^^^^^^^^^^^ error: the constant `Point` is not of type `Point` - --> $DIR/tuple_ctor_erroneous.rs:41:23 + --> $DIR/tuple_ctor_erroneous.rs:40:23 | LL | accepts_point::<{ Point }>(); | ^^^^^ expected `Point`, found struct constructor | note: required by a const generic parameter in `accepts_point` - --> $DIR/tuple_ctor_erroneous.rs:18:18 + --> $DIR/tuple_ctor_erroneous.rs:17:18 | LL | fn accepts_point() {} | ^^^^^^^^^^^^^^ required by this const generic parameter in `accepts_point` error: the constant `MyEnum::::Variant` is not of type `MyEnum` - --> $DIR/tuple_ctor_erroneous.rs:44:22 + --> $DIR/tuple_ctor_erroneous.rs:43:22 | LL | accepts_enum::<{ MyEnum::Variant:: }>(); | ^^^^^^^^^^^^^^^^^^^^^^ expected `MyEnum`, found enum constructor | note: required by a const generic parameter in `accepts_enum` - --> $DIR/tuple_ctor_erroneous.rs:19:17 + --> $DIR/tuple_ctor_erroneous.rs:18:17 | LL | fn accepts_enum>() {} | ^^^^^^^^^^^^^^^^^^^^ required by this const generic parameter in `accepts_enum` diff --git a/tests/ui/const-generics/mgca/tuple_ctor_nested.rs b/tests/ui/const-generics/mgca/tuple_ctor_nested.rs index 096f56d9512a8..e03db5d7b0fdc 100644 --- a/tests/ui/const-generics/mgca/tuple_ctor_nested.rs +++ b/tests/ui/const-generics/mgca/tuple_ctor_nested.rs @@ -1,6 +1,5 @@ //@ run-pass -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] use std::marker::ConstParamTy; diff --git a/tests/ui/const-generics/mgca/tuple_ctor_type_relative.rs b/tests/ui/const-generics/mgca/tuple_ctor_type_relative.rs index 6a5c28bca6898..eaa1744bc5bbd 100644 --- a/tests/ui/const-generics/mgca/tuple_ctor_type_relative.rs +++ b/tests/ui/const-generics/mgca/tuple_ctor_type_relative.rs @@ -1,6 +1,5 @@ //@ run-pass -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] use std::marker::ConstParamTy; diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.rs b/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.rs index 50abdd97e908f..53216e3c5c14b 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.rs +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.rs @@ -1,5 +1,4 @@ -#![feature(gca_min_const_items, gca_macroless_args)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, min_adt_const_params)] struct Y { stuff: [u8; { ([1, 2], 3, [4, 5]) }], //~ ERROR expected `usize`, found `([1, 2], 3, [4, 5])` diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.stderr b/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.stderr index aa54a5ae77048..098a676d6d918 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.stderr +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.stderr @@ -1,5 +1,5 @@ error: expected `usize`, found `([1, 2], 3, [4, 5])` - --> $DIR/tuple_expr_arg_bad-issue-151048.rs:5:19 + --> $DIR/tuple_expr_arg_bad-issue-151048.rs:4:19 | LL | stuff: [u8; { ([1, 2], 3, [4, 5]) }], | ^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_complex.rs b/tests/ui/const-generics/mgca/tuple_expr_arg_complex.rs index 2b39a8b585faf..ff73b128fd522 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_complex.rs +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_complex.rs @@ -1,5 +1,4 @@ -#![feature(gca_min_const_items, adt_const_params, unsized_const_params)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, adt_const_params, unsized_const_params)] use std::gca; diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_complex.stderr b/tests/ui/const-generics/mgca/tuple_expr_arg_complex.stderr index e6f004b2f9d68..cdee5ff343ba3 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_complex.stderr +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_complex.stderr @@ -1,23 +1,23 @@ error: complex const arguments must be placed inside of a `const` block - --> $DIR/tuple_expr_arg_complex.rs:15:30 + --> $DIR/tuple_expr_arg_complex.rs:14:30 | LL | takes_tuple::<{ gca!((N, N + 1)) }>(); | ^^^^^ error: complex const arguments must be placed inside of a `const` block - --> $DIR/tuple_expr_arg_complex.rs:16:30 + --> $DIR/tuple_expr_arg_complex.rs:15:30 | LL | takes_tuple::<{ gca!((N, T::ASSOC + 1)) }>(); | ^^^^^^^^^^^^ error: complex const arguments must be placed inside of a `const` block - --> $DIR/tuple_expr_arg_complex.rs:18:41 + --> $DIR/tuple_expr_arg_complex.rs:17:41 | LL | takes_nested_tuple::<{ gca!((N, (N, N + 1))) }>(); | ^^^^^ error: generic parameters may not be used in const operations - --> $DIR/tuple_expr_arg_complex.rs:19:49 + --> $DIR/tuple_expr_arg_complex.rs:18:49 | LL | takes_nested_tuple::<{ gca!((N, (N, const { N + 1 }))) }>(); | ^ diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_macroless.rs b/tests/ui/const-generics/mgca/tuple_expr_arg_macroless.rs index 2b67665d7281b..685d29ed4cec1 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_macroless.rs +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_macroless.rs @@ -1,12 +1,12 @@ //@ check-pass #![feature( - gca_min_const_items, - gca_macroless_args, adt_const_params, + gca_adts, + gca_macroless_args, + gca_min_const_items, unsized_const_params )] -#![expect(incomplete_features)] trait Trait { #[rustc_always_gca] diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_mismatch_type.rs b/tests/ui/const-generics/mgca/tuple_expr_arg_mismatch_type.rs index 780b757c0df1c..5247fcdec0e2f 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_mismatch_type.rs +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_mismatch_type.rs @@ -1,5 +1,4 @@ -#![feature(gca_min_const_items, gca_macroless_args)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, min_adt_const_params)] pub fn takes_nested_tuple() { takes_nested_tuple::<{ () }> //~ ERROR expected `u32`, found `()` diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_mismatch_type.stderr b/tests/ui/const-generics/mgca/tuple_expr_arg_mismatch_type.stderr index d8314a6b6a57e..a45ca91d69e3c 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_mismatch_type.stderr +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_mismatch_type.stderr @@ -1,5 +1,5 @@ error: expected `u32`, found `()` - --> $DIR/tuple_expr_arg_mismatch_type.rs:5:28 + --> $DIR/tuple_expr_arg_mismatch_type.rs:4:28 | LL | takes_nested_tuple::<{ () }> | ^^ diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_simple.rs b/tests/ui/const-generics/mgca/tuple_expr_arg_simple.rs index 8c4f64adf34dc..315636bc2e75d 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_simple.rs +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_simple.rs @@ -1,7 +1,6 @@ //@ check-pass -#![feature(gca_min_const_items, adt_const_params, unsized_const_params)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, adt_const_params, unsized_const_params)] use std::gca; diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_unbounded_assoc_const.rs b/tests/ui/const-generics/mgca/tuple_expr_arg_unbounded_assoc_const.rs index 7d8a1a1264bd9..c1c118d575a69 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_unbounded_assoc_const.rs +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_unbounded_assoc_const.rs @@ -1,4 +1,4 @@ -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] // Regression test for an ICE in privacy checking while walking the `T` qself // of `T::ASSOC` inside a tuple const argument. diff --git a/tests/ui/const-generics/mgca/tuple_expr_type_mismatch.rs b/tests/ui/const-generics/mgca/tuple_expr_type_mismatch.rs index e67a5a0a72e54..04533b8d96455 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_type_mismatch.rs +++ b/tests/ui/const-generics/mgca/tuple_expr_type_mismatch.rs @@ -1,9 +1,9 @@ //! Regression test for -#![expect(incomplete_features)] #![feature( adt_const_params, - gca_min_const_items, + gca_adts, gca_macroless_args, + gca_min_const_items, unsized_const_params )] fn foo() {} diff --git a/tests/ui/const-generics/mgca/type_const-adt-expr-missing-field.rs b/tests/ui/const-generics/mgca/type_const-adt-expr-missing-field.rs index 46c661cfb96ce..e7f396543e66d 100644 --- a/tests/ui/const-generics/mgca/type_const-adt-expr-missing-field.rs +++ b/tests/ui/const-generics/mgca/type_const-adt-expr-missing-field.rs @@ -1,9 +1,13 @@ // Regression test for https://github.com/rust-lang/rust/issues/154632 -#![feature(generic_const_exprs)] -#![feature(gca_min_const_items)] -#![feature(gca_macroless_args)] -#![feature(generic_const_items)] +#![feature( + gca_adts, + gca_macroless_args, + gca_min_const_items, + generic_const_exprs, + generic_const_items, + min_adt_const_params +)] use std::gca; diff --git a/tests/ui/const-generics/mgca/type_const-adt-expr-missing-field.stderr b/tests/ui/const-generics/mgca/type_const-adt-expr-missing-field.stderr index 623ae087687f5..7135773752b55 100644 --- a/tests/ui/const-generics/mgca/type_const-adt-expr-missing-field.stderr +++ b/tests/ui/const-generics/mgca/type_const-adt-expr-missing-field.stderr @@ -1,5 +1,5 @@ error[E0573]: cannot find type `ADD1` in this scope - --> $DIR/type_const-adt-expr-missing-field.rs:12:22 + --> $DIR/type_const-adt-expr-missing-field.rs:16:22 | LL | const AliasFnUnused: ADD1 = gca!(ADD1::<{ Some:: {} }>); | ^^^^ not found in this scope @@ -7,7 +7,7 @@ LL | const AliasFnUnused: ADD1 = gca!(ADD1::<{ Some:: {} }>); = note: a constant named `ADD1` exists in another namespace error: unconstrained generic constant - --> $DIR/type_const-adt-expr-missing-field.rs:10:1 + --> $DIR/type_const-adt-expr-missing-field.rs:14:1 | LL | const ADD1: usize = gca!(const { N + 1 }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -18,7 +18,7 @@ LL | const ADD1: usize where [(); const { N + 1 }]: = gca!(const | ++++++++++++++++++++++++++++ error: struct expression with missing field initialiser for `0` - --> $DIR/type_const-adt-expr-missing-field.rs:12:43 + --> $DIR/type_const-adt-expr-missing-field.rs:16:43 | LL | const AliasFnUnused: ADD1 = gca!(ADD1::<{ Some:: {} }>); | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/const-generics/mgca/type_const-generic-param-in-type.nogate.stderr b/tests/ui/const-generics/mgca/type_const-generic-param-in-type.nogate.stderr index 46be38bb1a53d..aac10bc622b5d 100644 --- a/tests/ui/const-generics/mgca/type_const-generic-param-in-type.nogate.stderr +++ b/tests/ui/const-generics/mgca/type_const-generic-param-in-type.nogate.stderr @@ -1,53 +1,53 @@ error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/type_const-generic-param-in-type.rs:13:1 + --> $DIR/type_const-generic-param-in-type.rs:18:1 | LL | const FOO: [T; 0] = gca!([]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the type `[T; 0]` must not depend on other generic parameter error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/type_const-generic-param-in-type.rs:16:1 + --> $DIR/type_const-generic-param-in-type.rs:21:1 | LL | const BAR: StructWithConstParam = gca!(StructWithConstParam::); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the type `StructWithConstParam` must not depend on other generic parameter error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/type_const-generic-param-in-type.rs:19:1 + --> $DIR/type_const-generic-param-in-type.rs:24:1 | LL | const BAZ<'a>: [&'a (); 0] = gca!([]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the type `[&'a (); 0]` must not depend on other generic parameter error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/type_const-generic-param-in-type.rs:37:5 + --> $DIR/type_const-generic-param-in-type.rs:42:5 | LL | const ASSOC: [T; 0] = gca!([]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the type `[T; 0]` must not depend on other generic parameter error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/type_const-generic-param-in-type.rs:40:5 + --> $DIR/type_const-generic-param-in-type.rs:45:5 | LL | const ASSOC_CONST: StructWithConstParam = gca!(StructWithConstParam::); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the type `StructWithConstParam` must not depend on other generic parameter error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/type_const-generic-param-in-type.rs:43:5 + --> $DIR/type_const-generic-param-in-type.rs:48:5 | LL | const ASSOC_LT<'a>: [&'a (); 0] = gca!([]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the type `[&'a (); 0]` must not depend on other generic parameter error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/type_const-generic-param-in-type.rs:24:5 + --> $DIR/type_const-generic-param-in-type.rs:29:5 | LL | const ASSOC: [T; 0]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the type `[T; 0]` must not depend on other generic parameter error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/type_const-generic-param-in-type.rs:28:5 + --> $DIR/type_const-generic-param-in-type.rs:33:5 | LL | const ASSOC_CONST: StructWithConstParam; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the type `StructWithConstParam` must not depend on other generic parameter error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/type_const-generic-param-in-type.rs:32:5 + --> $DIR/type_const-generic-param-in-type.rs:37:5 | LL | const ASSOC_LT<'a>: [&'a (); 0]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the type `[&'a (); 0]` must not depend on other generic parameter diff --git a/tests/ui/const-generics/mgca/type_const-generic-param-in-type.rs b/tests/ui/const-generics/mgca/type_const-generic-param-in-type.rs index 80293325d8800..b64853f37bb8f 100644 --- a/tests/ui/const-generics/mgca/type_const-generic-param-in-type.rs +++ b/tests/ui/const-generics/mgca/type_const-generic-param-in-type.rs @@ -1,7 +1,12 @@ //@ revisions: nogate gate //@ [gate] check-pass -#![expect(incomplete_features)] -#![feature(adt_const_params, unsized_const_params, gca_min_const_items, generic_const_items)] +#![feature( + adt_const_params, + gca_adts, + gca_min_const_items, + generic_const_items, + unsized_const_params +)] #![cfg_attr(gate, feature(generic_const_parameter_types))] use std::gca; diff --git a/tests/ui/const-generics/mgca/wrapped_array_elem_type_mismatch.rs b/tests/ui/const-generics/mgca/wrapped_array_elem_type_mismatch.rs index a80f602fbf96a..c3ba68ae5213d 100644 --- a/tests/ui/const-generics/mgca/wrapped_array_elem_type_mismatch.rs +++ b/tests/ui/const-generics/mgca/wrapped_array_elem_type_mismatch.rs @@ -1,5 +1,5 @@ #![expect(incomplete_features)] -#![feature(adt_const_params, gca_min_const_items, gca_macroless_args)] +#![feature(adt_const_params, gca_min_const_items, gca_macroless_args, gca_adts)] struct ArrWrap; diff --git a/tests/ui/const-generics/mgca/wrong_type_const_arr_diag.rs b/tests/ui/const-generics/mgca/wrong_type_const_arr_diag.rs index f5d3c06d7bc8e..3ca3c9bcb7536 100644 --- a/tests/ui/const-generics/mgca/wrong_type_const_arr_diag.rs +++ b/tests/ui/const-generics/mgca/wrong_type_const_arr_diag.rs @@ -1,7 +1,6 @@ // This test causes ERROR: mismatched types [E0308] // and makes rustc to print array from const arguments -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] -#![allow(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] struct TakesArr; diff --git a/tests/ui/const-generics/mgca/wrong_type_const_arr_diag.stderr b/tests/ui/const-generics/mgca/wrong_type_const_arr_diag.stderr index a2e212b28ec6f..3e2ee8c5f718a 100644 --- a/tests/ui/const-generics/mgca/wrong_type_const_arr_diag.stderr +++ b/tests/ui/const-generics/mgca/wrong_type_const_arr_diag.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/wrong_type_const_arr_diag.rs:9:32 + --> $DIR/wrong_type_const_arr_diag.rs:8:32 | LL | let _: TakesArr<{ [N] }> = TakesArr::<{ [1] }>; | ----------------- ^^^^^^^^^^^^^^^^^^^ expected `[N]`, found `*b"\x01"` diff --git a/tests/ui/const-generics/mgca/wrong_type_const_arr_diag_trait.rs b/tests/ui/const-generics/mgca/wrong_type_const_arr_diag_trait.rs index 225d3ef226cba..ee91819204859 100644 --- a/tests/ui/const-generics/mgca/wrong_type_const_arr_diag_trait.rs +++ b/tests/ui/const-generics/mgca/wrong_type_const_arr_diag_trait.rs @@ -1,7 +1,6 @@ // This test causes ERROR: mismatched types [E0308] // and makes rustc to print array from const arguments -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params, trivial_bounds)] -#![allow(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params, trivial_bounds)] trait Trait { #[rustc_always_gca] diff --git a/tests/ui/const-generics/mgca/wrong_type_const_arr_diag_trait.stderr b/tests/ui/const-generics/mgca/wrong_type_const_arr_diag_trait.stderr index 66de4a4d6a864..5338a7bfbd973 100644 --- a/tests/ui/const-generics/mgca/wrong_type_const_arr_diag_trait.stderr +++ b/tests/ui/const-generics/mgca/wrong_type_const_arr_diag_trait.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/wrong_type_const_arr_diag_trait.rs:17:51 + --> $DIR/wrong_type_const_arr_diag_trait.rs:16:51 | LL | let _: TakesArr<{ [::ASSOC] }> = TakesArr::<{ [1] }>; | ------------------------------------ ^^^^^^^^^^^^^^^^^^^ expected `[::ASSOC]`, found `*b"\x01"` diff --git a/tests/ui/const-generics/min_adt_const_params/tuple_with_infer_arg.rs b/tests/ui/const-generics/min_adt_const_params/tuple_with_infer_arg.rs index 675cecc68f884..e6d8e362dd191 100644 --- a/tests/ui/const-generics/min_adt_const_params/tuple_with_infer_arg.rs +++ b/tests/ui/const-generics/min_adt_const_params/tuple_with_infer_arg.rs @@ -1,6 +1,6 @@ //@ check-pass -#![feature(min_adt_const_params, gca_min_const_items, gca_macroless_args)] +#![feature(min_adt_const_params, gca_adts, gca_min_const_items, gca_macroless_args)] struct S; diff --git a/tests/ui/feature-gates/feature-gate-gca-adts.rs b/tests/ui/feature-gates/feature-gate-gca-adts.rs new file mode 100644 index 0000000000000..6b77771fc4cdc --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-gca-adts.rs @@ -0,0 +1,24 @@ +//@ revisions: without without_with_min_items with +//@[with] check-pass + +#![feature(min_adt_const_params)] +#![cfg_attr(with, feature(gca_adts))] +// gca_min_const_items enables the gca! macro as well, which is vaguely interesting to test too +#![cfg_attr(without_with_min_items, feature(gca_min_const_items))] + +use std::gca; +//[without]~^ ERROR use of unstable library feature `gca_min_const_items` + +struct S; + +fn main() { + let _: S = S::; + //[without_with_min_items]~^ ERROR complex const arguments must be placed inside of a `const` block + //[without_with_min_items]~| ERROR complex const arguments must be placed inside of a `const` block + //[without]~^^^ ERROR use of unstable library feature `gca_min_const_items` + //[without]~| ERROR use of unstable library feature `gca_min_const_items` + //[without]~| ERROR expected type, found `gca!()` constant + //[without]~| ERROR expected type, found `gca!()` constant + //[without]~| ERROR type provided when a constant was expected + //[without]~| ERROR type provided when a constant was expected +} diff --git a/tests/ui/feature-gates/feature-gate-gca-adts.without.stderr b/tests/ui/feature-gates/feature-gate-gca-adts.without.stderr new file mode 100644 index 0000000000000..9076e2313db09 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-gca-adts.without.stderr @@ -0,0 +1,58 @@ +error[E0658]: use of unstable library feature `gca_min_const_items` + --> $DIR/feature-gate-gca-adts.rs:15:14 + | +LL | let _: S = S::; + | ^^^ + | + = note: see issue #132980 for more information + = help: add `#![feature(gca_min_const_items)]` 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]: use of unstable library feature `gca_min_const_items` + --> $DIR/feature-gate-gca-adts.rs:15:34 + | +LL | let _: S = S::; + | ^^^ + | + = note: see issue #132980 for more information + = help: add `#![feature(gca_min_const_items)]` 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: expected type, found `gca!()` constant + --> $DIR/feature-gate-gca-adts.rs:15:14 + | +LL | let _: S = S::; + | ^^^^^^^^^^^^ + +error: expected type, found `gca!()` constant + --> $DIR/feature-gate-gca-adts.rs:15:34 + | +LL | let _: S = S::; + | ^^^^^^^^^^^^ + +error[E0658]: use of unstable library feature `gca_min_const_items` + --> $DIR/feature-gate-gca-adts.rs:9:5 + | +LL | use std::gca; + | ^^^^^^^^ + | + = note: see issue #132980 for more information + = help: add `#![feature(gca_min_const_items)]` 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[E0747]: type provided when a constant was expected + --> $DIR/feature-gate-gca-adts.rs:15:14 + | +LL | let _: S = S::; + | ^^^^^^^^^^^^ + +error[E0747]: type provided when a constant was expected + --> $DIR/feature-gate-gca-adts.rs:15:34 + | +LL | let _: S = S::; + | ^^^^^^^^^^^^ + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0658, E0747. +For more information about an error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-gca-adts.without_with_min_items.stderr b/tests/ui/feature-gates/feature-gate-gca-adts.without_with_min_items.stderr new file mode 100644 index 0000000000000..84c64b828b3fc --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-gca-adts.without_with_min_items.stderr @@ -0,0 +1,14 @@ +error: complex const arguments must be placed inside of a `const` block + --> $DIR/feature-gate-gca-adts.rs:15:19 + | +LL | let _: S = S::; + | ^^^^^^ + +error: complex const arguments must be placed inside of a `const` block + --> $DIR/feature-gate-gca-adts.rs:15:39 + | +LL | let _: S = S::; + | ^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/transmutability/non_scalar_alignment_value.rs b/tests/ui/transmutability/non_scalar_alignment_value.rs index 24e97a2a55356..937fa39876303 100644 --- a/tests/ui/transmutability/non_scalar_alignment_value.rs +++ b/tests/ui/transmutability/non_scalar_alignment_value.rs @@ -1,4 +1,10 @@ -#![feature(gca_min_const_items, gca_macroless_args, transmutability)] +#![feature( + gca_adts, + gca_macroless_args, + gca_min_const_items, + min_adt_const_params, + transmutability +)] mod assert { use std::mem::{Assume, TransmuteFrom}; diff --git a/tests/ui/transmutability/non_scalar_alignment_value.stderr b/tests/ui/transmutability/non_scalar_alignment_value.stderr index 80a125d540a8f..020a557573bda 100644 --- a/tests/ui/transmutability/non_scalar_alignment_value.stderr +++ b/tests/ui/transmutability/non_scalar_alignment_value.stderr @@ -1,23 +1,23 @@ error: struct expression with missing field initialiser for `alignment` - --> $DIR/non_scalar_alignment_value.rs:12:32 + --> $DIR/non_scalar_alignment_value.rs:18:32 | LL | alignment: Assume {}, | ^^^^^^^^^ error: struct expression with missing field initialiser for `lifetimes` - --> $DIR/non_scalar_alignment_value.rs:12:32 + --> $DIR/non_scalar_alignment_value.rs:18:32 | LL | alignment: Assume {}, | ^^^^^^^^^ error: struct expression with missing field initialiser for `safety` - --> $DIR/non_scalar_alignment_value.rs:12:32 + --> $DIR/non_scalar_alignment_value.rs:18:32 | LL | alignment: Assume {}, | ^^^^^^^^^ error: struct expression with missing field initialiser for `validity` - --> $DIR/non_scalar_alignment_value.rs:12:32 + --> $DIR/non_scalar_alignment_value.rs:18:32 | LL | alignment: Assume {}, | ^^^^^^^^^ diff --git a/tests/ui/unpretty/struct-exprs-tuple-call-pretty-printing.rs b/tests/ui/unpretty/struct-exprs-tuple-call-pretty-printing.rs index a155d9ade5cf3..9895ccbfd0926 100644 --- a/tests/ui/unpretty/struct-exprs-tuple-call-pretty-printing.rs +++ b/tests/ui/unpretty/struct-exprs-tuple-call-pretty-printing.rs @@ -1,8 +1,7 @@ //@ compile-flags: -Zunpretty=hir //@ check-pass -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] -#![expect(incomplete_features)] +#![feature(adt_const_params, gca_adts, gca_min_const_items, gca_macroless_args)] #![allow(dead_code)] use std::marker::ConstParamTy; diff --git a/tests/ui/unpretty/struct-exprs-tuple-call-pretty-printing.stdout b/tests/ui/unpretty/struct-exprs-tuple-call-pretty-printing.stdout index c2c79249a6bd4..f117acc810606 100644 --- a/tests/ui/unpretty/struct-exprs-tuple-call-pretty-printing.stdout +++ b/tests/ui/unpretty/struct-exprs-tuple-call-pretty-printing.stdout @@ -1,10 +1,9 @@ //@ compile-flags: -Zunpretty=hir //@ check-pass -#![expect(incomplete_features)] #![allow(dead_code)] -#![attr = Feature([gca_min_const_items#0, gca_macroless_args#0, -adt_const_params#0])] +#![attr = Feature([adt_const_params#0, gca_adts#0, gca_min_const_items#0, +gca_macroless_args#0])] extern crate std; #[attr = PreludeImport] use ::std::prelude::rust_2015::*; From 773ad198b6b28ba21cd319607d264618420b3060 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Mon, 28 Sep 2026 15:39:32 +0200 Subject: [PATCH 17/20] Add `stable_rustc` helper in `run-make-support` --- .../src/external_deps/rustc.rs | 24 ++++++++++++++++--- src/tools/run-make-support/src/lib.rs | 4 +++- .../const-destruct-stable-toolchain/rmake.rs | 6 ++--- .../const-trait-stable-toolchain/rmake.rs | 9 +++---- .../issue-149402-suggest-unresolve/rmake.rs | 10 ++------ .../missing-unstable-trait-bound/rmake.rs | 6 ++--- .../rmake.rs | 11 +++------ 7 files changed, 36 insertions(+), 34 deletions(-) diff --git a/src/tools/run-make-support/src/external_deps/rustc.rs b/src/tools/run-make-support/src/external_deps/rustc.rs index 8b28105abe5ed..fab7f2098ea1c 100644 --- a/src/tools/run-make-support/src/external_deps/rustc.rs +++ b/src/tools/run-make-support/src/external_deps/rustc.rs @@ -22,6 +22,15 @@ pub fn bare_rustc() -> Rustc { Rustc::bare() } +/// Construct a plain `rustc` invocation with no flags set that behaves like a stable compiler, +/// i.e. rejects unstable flags. +/// Note that [`set_host_compiler_dylib_path`] still presets the environment variable +/// `HOST_RUSTC_DYLIB_PATH` by default. +#[track_caller] +pub fn stable_bare_rustc() -> Rustc { + Rustc::bare_stable() +} + /// Construct a `rustc` invocation for building `minicore`. /// /// This function: @@ -76,9 +85,6 @@ pub fn rustc_path() -> String { fn setup_common() -> Command { let mut cmd = Command::new(rustc_path()); set_host_compiler_dylib_path(&mut cmd); - if let Ok(codegen_backend) = std::env::var("RUSTC_CODEGEN_BACKEND") { - cmd.arg(format!("-Zcodegen-backend={codegen_backend}")); - } cmd } @@ -100,6 +106,10 @@ impl Rustc { cmd.arg("-Ctarget-feature=-crt-static"); } + if let Ok(codegen_backend) = std::env::var("RUSTC_CODEGEN_BACKEND") { + cmd.arg(format!("-Zcodegen-backend={codegen_backend}")); + } + // Automatically default to cross-compilation Self { cmd, target: Some(target()) } } @@ -111,6 +121,14 @@ impl Rustc { Self { cmd, target: None } } + /// Construct a bare `rustc` invocation with no flags set that acts like a stable compiler. + #[track_caller] + pub fn bare_stable() -> Self { + let mut cmd = setup_common(); + cmd.env("RUSTC_BOOTSTRAP", "-1"); + Self { cmd, target: None } + } + // Argument provider methods /// Configure the compilation environment. diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index d3c2115e745e0..b9717bda1e2c7 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -79,7 +79,9 @@ pub use crate::external_deps::llvm::{ llvm_readobj, }; pub use crate::external_deps::python::python_command; -pub use crate::external_deps::rustc::{self, Rustc, bare_rustc, rustc, rustc_minicore, rustc_path}; +pub use crate::external_deps::rustc::{ + self, Rustc, bare_rustc, rustc, rustc_minicore, rustc_path, stable_bare_rustc, +}; pub use crate::external_deps::rustdoc::{Rustdoc, bare_rustdoc, rustdoc}; // Path-related helpers. pub use crate::path_helpers::{ diff --git a/tests/run-make/const-destruct-stable-toolchain/rmake.rs b/tests/run-make/const-destruct-stable-toolchain/rmake.rs index 0f36d71f2c874..c4990582d40ba 100644 --- a/tests/run-make/const-destruct-stable-toolchain/rmake.rs +++ b/tests/run-make/const-destruct-stable-toolchain/rmake.rs @@ -1,17 +1,15 @@ //@ needs-target-std -// FIXME: Once GCC backend is fixed, remove this `ignore-backends`. //@ ignore-backends: gcc // Test that the suggestion to constrain a type parameter that is dropped in a const // function with a `[const] Destruct` bound is only offered on nightly, since the bound // requires an unstable feature. -use run_make_support::{diff, rustc}; +use run_make_support::{diff, rustc, stable_bare_rustc}; fn main() { - let out = rustc() + let out = stable_bare_rustc() .input("const-drop.rs") - .env("RUSTC_BOOTSTRAP", "-1") .run_fail() .assert_stderr_not_contains("consider restricting type parameter `T`") .stderr_utf8(); diff --git a/tests/run-make/const-trait-stable-toolchain/rmake.rs b/tests/run-make/const-trait-stable-toolchain/rmake.rs index e2ec58f03db19..c778873463063 100644 --- a/tests/run-make/const-trait-stable-toolchain/rmake.rs +++ b/tests/run-make/const-trait-stable-toolchain/rmake.rs @@ -1,16 +1,14 @@ //@ needs-target-std -// FIXME: Once GCC backend is fixed, remove this `ignore-backends`. //@ ignore-backends: gcc // Test output of const super trait errors in both stable and nightly. // We don't want to provide suggestions on stable that only make sense in nightly. -use run_make_support::{diff, rustc}; +use run_make_support::{diff, rustc, stable_bare_rustc}; fn main() { - let out = rustc() + let out = stable_bare_rustc() .input("const-super-trait.rs") - .env("RUSTC_BOOTSTRAP", "-1") .cfg("feature_enabled") .run_fail() .assert_stderr_not_contains("as `const` to allow it to have `const` implementations") @@ -35,9 +33,8 @@ fn main() { .expected_file("const-super-trait-nightly-enabled.stderr") .actual_text("(rustc)", &out) .run(); - let out = rustc() + let out = stable_bare_rustc() .input("const-super-trait.rs") - .env("RUSTC_BOOTSTRAP", "-1") .run_fail() .assert_stderr_not_contains("enable `#![feature(const_trait_impl)]` in your crate and mark") .assert_stderr_not_contains("as `const` to allow it to have `const` implementations") diff --git a/tests/run-make/issue-149402-suggest-unresolve/rmake.rs b/tests/run-make/issue-149402-suggest-unresolve/rmake.rs index 78348b914d1e6..a8d92606ee893 100644 --- a/tests/run-make/issue-149402-suggest-unresolve/rmake.rs +++ b/tests/run-make/issue-149402-suggest-unresolve/rmake.rs @@ -4,18 +4,12 @@ //! //@ only-nightly //@ needs-target-std -// FIXME: Once GCC backend is fixed, remove this `ignore-backends`. //@ ignore-backends: gcc -use run_make_support::{diff, rustc, similar}; +use run_make_support::{diff, rustc, similar, stable_bare_rustc}; fn main() { - let stable_like = rustc() - .env("RUSTC_BOOTSTRAP", "-1") - .edition("2024") - .input("foo.rs") - .run_fail() - .stderr_utf8(); + let stable_like = stable_bare_rustc().edition("2024").input("foo.rs").run_fail().stderr_utf8(); assert!(!stable_like.contains("CoroutineState::Complete")); diff().expected_file("stable.err").actual_text("stable_like", &stable_like).run(); diff --git a/tests/run-make/missing-unstable-trait-bound/rmake.rs b/tests/run-make/missing-unstable-trait-bound/rmake.rs index 753f4abcf32fd..52a011285c95c 100644 --- a/tests/run-make/missing-unstable-trait-bound/rmake.rs +++ b/tests/run-make/missing-unstable-trait-bound/rmake.rs @@ -2,17 +2,15 @@ //@ ignore-wasm32 //@ ignore-wasm64 // ignore-tidy-linelength -// FIXME: Once GCC backend is fixed, remove this `ignore-backends`. //@ ignore-backends: gcc // Ensure that on stable we don't suggest restricting with an unsafe trait and we continue // mentioning the rest of the obligation chain. -use run_make_support::{diff, rustc}; +use run_make_support::{diff, stable_bare_rustc}; fn main() { - let out = rustc() - .env("RUSTC_BOOTSTRAP", "-1") + let out = stable_bare_rustc() .input("missing-bound.rs") .run_fail() .assert_stderr_not_contains("help: consider restricting type parameter `T`") diff --git a/tests/run-make/print-request-help-stable-unstable/rmake.rs b/tests/run-make/print-request-help-stable-unstable/rmake.rs index 62cf0483f320d..01572a5aad942 100644 --- a/tests/run-make/print-request-help-stable-unstable/rmake.rs +++ b/tests/run-make/print-request-help-stable-unstable/rmake.rs @@ -2,18 +2,13 @@ //! //! Issue: -// FIXME: Once GCC backend is fixed, remove this `ignore-backends`. //@ ignore-backends: gcc -use run_make_support::{diff, rustc, similar}; +use run_make_support::{diff, rustc, similar, stable_bare_rustc}; fn main() { - let stable_invalid_print_request_help = rustc() - .env("RUSTC_BOOTSTRAP", "-1") - .cfg("force_stable") - .print("xxx") - .run_fail() - .stderr_utf8(); + let stable_invalid_print_request_help = + stable_bare_rustc().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") From 62ce017dc8d51dee67e7bc021c202ab564f507c0 Mon Sep 17 00:00:00 2001 From: aerooneqq Date: Mon, 28 Sep 2026 17:21:14 +0300 Subject: [PATCH 18/20] Allow using different index types when reading and writing to tables --- compiler/rustc_metadata/src/rmeta/decoder.rs | 4 +-- compiler/rustc_metadata/src/rmeta/encoder.rs | 12 ++++--- compiler/rustc_metadata/src/rmeta/mod.rs | 34 ++++++++++++-------- compiler/rustc_metadata/src/rmeta/table.rs | 32 +++++++++++------- 4 files changed, 49 insertions(+), 33 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 27b36c23daf46..7dd920c7e39bd 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -189,7 +189,7 @@ pub(super) trait LazyDecoder: BlobDecoder { self.read_lazy_offset_then(|pos| LazyArray::from_position_and_num_elems(pos, len)) } - fn read_lazy_table(&mut self, width: usize, len: usize) -> LazyTable { + fn read_lazy_table(&mut self, width: usize, len: usize) -> LazyTable { self.read_lazy_offset_then(|pos| LazyTable::from_position_and_encoded_size(pos, width, len)) } @@ -667,7 +667,7 @@ impl Decodable for LazyArray { } } -impl Decodable for LazyTable { +impl Decodable for LazyTable { fn decode(decoder: &mut D) -> Self { let width = decoder.read_usize(); let len = decoder.read_usize(); diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index afa5646bea80e..40b61a52d2310 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -133,7 +133,7 @@ impl<'a, 'tcx, T> Encodable> for LazyArray { } } -impl<'a, 'tcx, I, T> Encodable> for LazyTable { +impl<'a, 'tcx, Ie, Id, T> Encodable> for LazyTable { fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) { e.emit_usize(self.width); e.emit_usize(self.len); @@ -547,7 +547,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.lazy(DefPathHashMapRef::BorrowedFromTcx(self.tcx.def_path_hash_to_def_index_map())) } - fn encode_source_map(&mut self) -> LazyTable>> { + fn encode_source_map( + &mut self, + ) -> LazyTable>> { let source_map = self.tcx.sess.source_map(); let all_source_files = source_map.files(); @@ -2004,9 +2006,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } fn encode_hygiene(&mut self) -> (SyntaxContextTable, ExpnDataTable, ExpnHashTable) { - let mut syntax_contexts: TableBuilder<_, _> = Default::default(); - let mut expn_data_table: TableBuilder<_, _> = Default::default(); - let mut expn_hash_table: TableBuilder<_, _> = Default::default(); + let mut syntax_contexts: TableBuilder<_, _, _> = Default::default(); + let mut expn_data_table: TableBuilder<_, _, _> = Default::default(); + let mut expn_hash_table: TableBuilder<_, _, _> = Default::default(); HygieneEncodeContext::encode( &Rc::clone(&self.hygiene_ctxt), diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index e3f3257acc137..b70151604f679 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -48,6 +48,7 @@ use rustc_target::spec::{PanicStrategy, TargetTuple}; use table::TableBuilder; use crate::eii::EiiMapEncodedKeyValue; +use crate::rmeta::table::TableBuilderSingleIdx; mod decoder; mod def_path_hash_map; @@ -143,22 +144,27 @@ impl LazyArray { /// Random-access table (i.e. offering constant-time `get`/`set`), similar to /// `LazyArray`, but without requiring encoding or decoding all the values /// eagerly and in-order. -struct LazyTable { +/// +/// `IdxEncode` - is a type of index that is used to write to the table, +/// `IdxDecode` - is a type of index that is used to read from the table. +struct LazyTable { position: NonZero, /// The encoded size of the elements of a table is selected at runtime to drop /// trailing zeroes. This is the number of bytes used for each table element. width: usize, /// How many elements are in the table. len: usize, - _marker: PhantomData T>, + _marker: PhantomData T>, } -impl LazyTable { +type LazyTableSingleIdx = LazyTable; + +impl LazyTable { fn from_position_and_encoded_size( position: NonZero, width: usize, len: usize, - ) -> LazyTable { + ) -> LazyTable { LazyTable { position, width, len, _marker: PhantomData } } } @@ -177,8 +183,8 @@ impl Clone for LazyArray { } } -impl Copy for LazyTable {} -impl Clone for LazyTable { +impl Copy for LazyTable {} +impl Clone for LazyTable { fn clone(&self) -> Self { *self } @@ -199,9 +205,9 @@ enum LazyState { Previous(NonZero), } -type SyntaxContextTable = LazyTable>>; -type ExpnDataTable = LazyTable>>; -type ExpnHashTable = LazyTable>>; +type SyntaxContextTable = LazyTableSingleIdx>>; +type ExpnDataTable = LazyTableSingleIdx>>; +type ExpnHashTable = LazyTableSingleIdx>>; #[derive(MetadataEncodable, LazyDecodable)] pub(crate) struct ProcMacroData { @@ -305,7 +311,7 @@ pub(crate) struct CrateRoot { def_path_hash_map: LazyValue>, - source_map: LazyTable>>, + source_map: LazyTableSingleIdx>>, target_modifiers: LazyArray, denied_partial_mitigations: LazyArray, @@ -389,14 +395,14 @@ macro_rules! define_tables { ) => { #[derive(MetadataEncodable, LazyDecodable)] pub(crate) struct LazyTables { - $($name1: LazyTable<$IDX1, $T1>,)+ - $($name2: LazyTable<$IDX2, Option<$T2>>,)+ + $($name1: LazyTableSingleIdx<$IDX1, $T1>,)+ + $($name2: LazyTableSingleIdx<$IDX2, Option<$T2>>,)+ } #[derive(Default)] struct TableBuilders { - $($name1: TableBuilder<$IDX1, $T1>,)+ - $($name2: TableBuilder<$IDX2, Option<$T2>>,)+ + $($name1: TableBuilderSingleIdx<$IDX1, $T1>,)+ + $($name2: TableBuilderSingleIdx<$IDX2, Option<$T2>>,)+ } impl TableBuilders { diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index 7b53ebba8adfc..c023b61d73571 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -427,34 +427,38 @@ impl FixedSizeEncoding for Option> { } /// Helper for constructing a table's serialization (also see `Table`). -pub(super) struct TableBuilder { +pub(super) struct TableBuilder { width: usize, - blocks: IndexVec, - _marker: PhantomData, + blocks: IndexVec, + _marker: PhantomData<(IdxDecode, T)>, } -impl Default for TableBuilder { +pub(super) type TableBuilderSingleIdx = TableBuilder; + +impl Default for TableBuilder { fn default() -> Self { TableBuilder { width: 0, blocks: Default::default(), _marker: PhantomData } } } -impl TableBuilder> +impl TableBuilder> where Option: FixedSizeEncoding, { - pub(crate) fn set_some(&mut self, i: I, value: T) { + pub(crate) fn set_some(&mut self, i: Ie, value: T) { self.set(i, Some(value)) } } -impl> TableBuilder { +impl> + TableBuilder +{ /// Sets the table value if it is not default. /// ATTENTION: For optimization default values are simply ignored by this function, because /// right now metadata tables never need to reset non-default values to default. If such need /// arises in the future then a new method (e.g. `clear` or `reset`) will need to be introduced /// for doing that explicitly. - pub(crate) fn set(&mut self, i: I, value: T) { + pub(crate) fn set(&mut self, i: Ie, value: T) { #[cfg(debug_assertions)] { debug_assert!( @@ -477,7 +481,7 @@ impl> TableBui } } - pub(crate) fn encode(&self, buf: &mut FileEncoder<'_>) -> LazyTable { + pub(crate) fn encode(&self, buf: &mut FileEncoder<'_>) -> LazyTable { let pos = buf.position(); let width = self.width; @@ -500,13 +504,17 @@ fn trailing_zeros(x: &[u8]) -> usize { x.iter().rev().take_while(|b| **b == 0).count() } -impl + ParameterizedOverTcx> - LazyTable +impl< + Ie: Idx, + Id: Idx, + const N: usize, + T: FixedSizeEncoding + ParameterizedOverTcx, +> LazyTable where for<'tcx> T::Value<'tcx>: FixedSizeEncoding, { /// Given the metadata, extract out the value at a particular index (if any). - pub(super) fn get<'a, 'tcx, M: MetaBlob<'a>>(&self, metadata: M, i: I) -> T::Value<'tcx> { + pub(super) fn get<'a, 'tcx, M: MetaBlob<'a>>(&self, metadata: M, i: Id) -> T::Value<'tcx> { // Access past the end of the table returns a Default if i.index() >= self.len { return Default::default(); From 48b2592ad8bdbcba6a5585dd39d560bf4a2e3ca1 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 28 Sep 2026 10:31:49 +0200 Subject: [PATCH 19/20] do not complain about unstable target features on nightly --- .../rustc_codegen_ssa/src/target_features.rs | 6 +- compiler/rustc_session/src/session.rs | 4 ++ src/doc/rustc-dev-guide/src/tests/misc.md | 13 ++-- .../run-make/unstable-target-feature/rmake.rs | 20 ++++++ .../unstable-target-feature.rs | 2 + .../unstable-target-feature.stderr | 8 +++ ...cv-discoverability-guidance.riscv32.stderr | 12 +--- ...cv-discoverability-guidance.riscv64.stderr | 12 +--- .../ui/abi/riscv-discoverability-guidance.rs | 5 -- tests/ui/abi/sparcv8plus.rs | 1 - tests/ui/abi/sparcv8plus.sparc.stderr | 2 +- tests/ui/abi/sparcv8plus.sparc_cpu_v9.stderr | 2 +- ...cv8plus.sparc_cpu_v9_feature_v8plus.stderr | 10 +-- .../sparcv8plus.sparc_feature_v8plus.stderr | 10 +-- tests/ui/abi/sparcv8plus.sparcv8plus.stderr | 2 +- tests/ui/asm/hexagon-register-pairs.rs | 2 - tests/ui/asm/hexagon-register-pairs.stderr | 12 +--- tests/ui/asm/hexagon/bad-reg.rs | 2 - tests/ui/asm/hexagon/bad-reg.stderr | 64 +++++++++---------- tests/ui/asm/mips/reg-conflict.mips32.stderr | 18 +----- .../ui/asm/mips/reg-conflict.mips32r6.stderr | 18 +----- tests/ui/asm/mips/reg-conflict.mips64.stderr | 18 +----- .../ui/asm/mips/reg-conflict.mips64r6.stderr | 18 +----- tests/ui/asm/mips/reg-conflict.rs | 2 - ...-irrelevant-target-feature-flag-disable.rs | 2 - ...elevant-target-feature-flag-disable.stderr | 8 --- ...bi-required-target-feature-flag-disable.rs | 1 - ...red-target-feature-flag-disable.x86.stderr | 8 +-- .../feature-hierarchy.hexagon-hvxv66.stderr | 8 --- .../feature-hierarchy.hexagon-v60.stderr | 8 --- .../feature-hierarchy.hexagon-v68.stderr | 8 --- tests/ui/target-feature/feature-hierarchy.rs | 4 -- .../packedstack-combinations.rs | 2 - ...edstack-combinations.with_softfloat.stderr | 8 --- tests/ui/target-feature/unstable-feature.rs | 8 --- .../ui/target-feature/unstable-feature.stderr | 8 --- 36 files changed, 100 insertions(+), 236 deletions(-) create mode 100644 tests/run-make/unstable-target-feature/rmake.rs create mode 100644 tests/run-make/unstable-target-feature/unstable-target-feature.rs create mode 100644 tests/run-make/unstable-target-feature/unstable-target-feature.stderr delete mode 100644 tests/ui/target-feature/abi-irrelevant-target-feature-flag-disable.stderr delete mode 100644 tests/ui/target-feature/feature-hierarchy.hexagon-hvxv66.stderr delete mode 100644 tests/ui/target-feature/feature-hierarchy.hexagon-v60.stderr delete mode 100644 tests/ui/target-feature/feature-hierarchy.hexagon-v68.stderr delete mode 100644 tests/ui/target-feature/packedstack-combinations.with_softfloat.stderr delete mode 100644 tests/ui/target-feature/unstable-feature.rs delete mode 100644 tests/ui/target-feature/unstable-feature.stderr diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index b630155c144ea..301195efb9a8f 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -383,8 +383,10 @@ pub fn internal_target_features<'a, const N: usize>( } else { sess.dcx().emit_warn(diag); } - } else if stability.requires_nightly(/* in_cfg */ false).is_some() { - // An unstable feature. Warn about using it. It makes little sense + } else if stability.requires_nightly(/* in_cfg */ false).is_some() + && !sess.is_nightly_build() + { + // An unstable feature. Warn about using it on stable. It makes little sense // to hard-error here since we just warn about fully unknown // features above. let note = if stability.is_cfg_stable_toggle_unstable() { diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 060e614e82180..3180d8ca5d10c 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -427,6 +427,10 @@ impl EarlySession { pub fn merge_functions(&self) -> MergeFunctions { self.opts.unstable_opts.merge_functions.unwrap_or(self.target.merge_functions) } + + pub fn is_nightly_build(&self) -> bool { + self.opts.unstable_features.is_nightly_build() + } } /// Some info about the backend, returned by `CodegenBackend::init` and put into the `Session`. diff --git a/src/doc/rustc-dev-guide/src/tests/misc.md b/src/doc/rustc-dev-guide/src/tests/misc.md index 34f9faa9cc722..8fe49c82e9873 100644 --- a/src/doc/rustc-dev-guide/src/tests/misc.md +++ b/src/doc/rustc-dev-guide/src/tests/misc.md @@ -12,15 +12,10 @@ This is a bootstrap/compiler implementation detail, but it can also be useful fo This is useful because some behaviors of the compiler (e.g. diagnostics) can differ depending on whether the compiler is nightly or not. -In `ui` tests and other test suites that support `//@ rustc-env`, you can specify - -```rust,ignore -// Force unstable features to be usable on stable rustc -//@ rustc-env:RUSTC_BOOTSTRAP=1 - -// Or force nightly rustc to pretend it is a stable rustc -//@ rustc-env:RUSTC_BOOTSTRAP=-1 -``` +Note that setting `RUSTC_BOOTSTRAP` in ui tests (e.g. via `//@ rustc-env`) is pointless since ui +tests inherit the bootstrap env var from bootstrap (so it's set to `1` by default), and since +compiletest itself passes `-Z` flags (so `-1` breaks the test). To test stable-only behavior, you +need to write a `run-make` test instead. For `run-make`/`run-make-cargo` tests, `//@ rustc-env` is not supported. You can do something like the following for individual `rustc` invocations. diff --git a/tests/run-make/unstable-target-feature/rmake.rs b/tests/run-make/unstable-target-feature/rmake.rs new file mode 100644 index 0000000000000..3fefe11ff791e --- /dev/null +++ b/tests/run-make/unstable-target-feature/rmake.rs @@ -0,0 +1,20 @@ +//@ only-x86_64 +// FIXME: Once GCC backend is fixed, remove this `ignore-backends`. +//@ ignore-backends: gcc + +// Ensure that on stable we don't suggest restricting with an unsafe trait and we continue +// mentioning the rest of the obligation chain. + +use run_make_support::{diff, rustc}; + +fn main() { + let out = rustc() + .env("RUSTC_BOOTSTRAP", "-1") + .input("unstable-target-feature.rs") + .args(&["-Ctarget-feature=+x87", "--crate-type=rlib"]) + .run() + .assert_stderr_not_contains("help: consider restricting type parameter `T`") + .assert_stderr_contains("unstable feature") + .stderr_utf8(); + diff().expected_file("unstable-target-feature.stderr").actual_text("(stable rustc)", &out).run() +} diff --git a/tests/run-make/unstable-target-feature/unstable-target-feature.rs b/tests/run-make/unstable-target-feature/unstable-target-feature.rs new file mode 100644 index 0000000000000..ec7318829e77e --- /dev/null +++ b/tests/run-make/unstable-target-feature/unstable-target-feature.rs @@ -0,0 +1,2 @@ +/// Tidy is unhappy if we leave the file empty. +pub fn empty() {} diff --git a/tests/run-make/unstable-target-feature/unstable-target-feature.stderr b/tests/run-make/unstable-target-feature/unstable-target-feature.stderr new file mode 100644 index 0000000000000..e4b2717f911f3 --- /dev/null +++ b/tests/run-make/unstable-target-feature/unstable-target-feature.stderr @@ -0,0 +1,8 @@ +warning: unstable feature specified for `-Ctarget-feature`: `x87` + | + = note: this feature is not stably supported; its behavior can change in the future + = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #162235 + +warning: 1 warning emitted + diff --git a/tests/ui/abi/riscv-discoverability-guidance.riscv32.stderr b/tests/ui/abi/riscv-discoverability-guidance.riscv32.stderr index c618e5f63546a..0378b9daafe79 100644 --- a/tests/ui/abi/riscv-discoverability-guidance.riscv32.stderr +++ b/tests/ui/abi/riscv-discoverability-guidance.riscv32.stderr @@ -1,11 +1,5 @@ -warning: unstable feature specified for `-Ctarget-feature`: `unaligned-scalar-mem` - | - = note: this feature is not stably supported; its behavior can change in the future - = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #162235 - error[E0703]: invalid ABI: found `riscv-interrupt` - --> $DIR/riscv-discoverability-guidance.rs:21:8 + --> $DIR/riscv-discoverability-guidance.rs:16:8 | LL | extern "riscv-interrupt" fn isr() {} | ^^^^^^^^^^^^^^^^^ invalid ABI @@ -17,7 +11,7 @@ LL | extern "riscv-interrupt-m" fn isr() {} | ++ error[E0703]: invalid ABI: found `riscv-interrupt-u` - --> $DIR/riscv-discoverability-guidance.rs:26:8 + --> $DIR/riscv-discoverability-guidance.rs:21:8 | LL | extern "riscv-interrupt-u" fn isr_U() {} | ^^^^^^^^^^^^^^^^^^^ invalid ABI @@ -29,6 +23,6 @@ LL - extern "riscv-interrupt-u" fn isr_U() {} LL + extern "riscv-interrupt-m" fn isr_U() {} | -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0703`. diff --git a/tests/ui/abi/riscv-discoverability-guidance.riscv64.stderr b/tests/ui/abi/riscv-discoverability-guidance.riscv64.stderr index c618e5f63546a..0378b9daafe79 100644 --- a/tests/ui/abi/riscv-discoverability-guidance.riscv64.stderr +++ b/tests/ui/abi/riscv-discoverability-guidance.riscv64.stderr @@ -1,11 +1,5 @@ -warning: unstable feature specified for `-Ctarget-feature`: `unaligned-scalar-mem` - | - = note: this feature is not stably supported; its behavior can change in the future - = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #162235 - error[E0703]: invalid ABI: found `riscv-interrupt` - --> $DIR/riscv-discoverability-guidance.rs:21:8 + --> $DIR/riscv-discoverability-guidance.rs:16:8 | LL | extern "riscv-interrupt" fn isr() {} | ^^^^^^^^^^^^^^^^^ invalid ABI @@ -17,7 +11,7 @@ LL | extern "riscv-interrupt-m" fn isr() {} | ++ error[E0703]: invalid ABI: found `riscv-interrupt-u` - --> $DIR/riscv-discoverability-guidance.rs:26:8 + --> $DIR/riscv-discoverability-guidance.rs:21:8 | LL | extern "riscv-interrupt-u" fn isr_U() {} | ^^^^^^^^^^^^^^^^^^^ invalid ABI @@ -29,6 +23,6 @@ LL - extern "riscv-interrupt-u" fn isr_U() {} LL + extern "riscv-interrupt-m" fn isr_U() {} | -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0703`. diff --git a/tests/ui/abi/riscv-discoverability-guidance.rs b/tests/ui/abi/riscv-discoverability-guidance.rs index 9937c28030f89..86e34a44ec59a 100644 --- a/tests/ui/abi/riscv-discoverability-guidance.rs +++ b/tests/ui/abi/riscv-discoverability-guidance.rs @@ -10,11 +10,6 @@ #![no_core] #![feature(no_core, lang_items, abi_riscv_interrupt)] -//~? WARN unstable feature specified for `-Ctarget-feature` -//~? NOTE this feature is not stably supported; its behavior can change in the future -//~? NOTE previously accepted -//~? NOTE for more information, see issue - extern crate minicore; use minicore::*; diff --git a/tests/ui/abi/sparcv8plus.rs b/tests/ui/abi/sparcv8plus.rs index 93e8871c642ee..ec64eb414f2ec 100644 --- a/tests/ui/abi/sparcv8plus.rs +++ b/tests/ui/abi/sparcv8plus.rs @@ -12,7 +12,6 @@ //@[sparc_cpu_v9_feature_v8plus] needs-llvm-components: sparc //@ ignore-backends: gcc -//[sparc_feature_v8plus,sparc_cpu_v9_feature_v8plus]~? WARN unstable feature specified for `-Ctarget-feature` //[sparc_feature_v8plus,sparc_cpu_v9_feature_v8plus]~? WARN `v8plus` must be disabled #![crate_type = "rlib"] diff --git a/tests/ui/abi/sparcv8plus.sparc.stderr b/tests/ui/abi/sparcv8plus.sparc.stderr index 779bf597d6f66..718ff1ab0af52 100644 --- a/tests/ui/abi/sparcv8plus.sparc.stderr +++ b/tests/ui/abi/sparcv8plus.sparc.stderr @@ -1,5 +1,5 @@ error: -v8plus,-v9 - --> $DIR/sparcv8plus.rs:31:1 + --> $DIR/sparcv8plus.rs:30:1 | LL | compile_error!("-v8plus,-v9"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/abi/sparcv8plus.sparc_cpu_v9.stderr b/tests/ui/abi/sparcv8plus.sparc_cpu_v9.stderr index edf75ab70db15..5e5e108d74dfc 100644 --- a/tests/ui/abi/sparcv8plus.sparc_cpu_v9.stderr +++ b/tests/ui/abi/sparcv8plus.sparc_cpu_v9.stderr @@ -1,5 +1,5 @@ error: -v8plus,+v9 - --> $DIR/sparcv8plus.rs:44:1 + --> $DIR/sparcv8plus.rs:43:1 | LL | compile_error!("-v8plus,+v9"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/abi/sparcv8plus.sparc_cpu_v9_feature_v8plus.stderr b/tests/ui/abi/sparcv8plus.sparc_cpu_v9_feature_v8plus.stderr index 7e1d9edff230f..27545025828b5 100644 --- a/tests/ui/abi/sparcv8plus.sparc_cpu_v9_feature_v8plus.stderr +++ b/tests/ui/abi/sparcv8plus.sparc_cpu_v9_feature_v8plus.stderr @@ -1,19 +1,13 @@ -warning: unstable feature specified for `-Ctarget-feature`: `v8plus` - | - = note: this feature is not stably supported; its behavior can change in the future - = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #162235 - warning: target feature `v8plus` must be disabled to ensure that the ABI of the current target can be implemented correctly | = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #162235 error: +v8plus,+v9 - --> $DIR/sparcv8plus.rs:35:1 + --> $DIR/sparcv8plus.rs:34:1 | LL | compile_error!("+v8plus,+v9"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 1 previous error; 2 warnings emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/abi/sparcv8plus.sparc_feature_v8plus.stderr b/tests/ui/abi/sparcv8plus.sparc_feature_v8plus.stderr index 3e9e7ff7c4a5c..5fdbdea580fef 100644 --- a/tests/ui/abi/sparcv8plus.sparc_feature_v8plus.stderr +++ b/tests/ui/abi/sparcv8plus.sparc_feature_v8plus.stderr @@ -1,19 +1,13 @@ -warning: unstable feature specified for `-Ctarget-feature`: `v8plus` - | - = note: this feature is not stably supported; its behavior can change in the future - = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #162235 - warning: target feature `v8plus` must be disabled to ensure that the ABI of the current target can be implemented correctly | = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #162235 error: +v8plus,-v9 (FIXME) - --> $DIR/sparcv8plus.rs:40:1 + --> $DIR/sparcv8plus.rs:39:1 | LL | compile_error!("+v8plus,-v9 (FIXME)"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 1 previous error; 2 warnings emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/abi/sparcv8plus.sparcv8plus.stderr b/tests/ui/abi/sparcv8plus.sparcv8plus.stderr index 37a03abae9b4b..5e1e1fa5c798f 100644 --- a/tests/ui/abi/sparcv8plus.sparcv8plus.stderr +++ b/tests/ui/abi/sparcv8plus.sparcv8plus.stderr @@ -1,5 +1,5 @@ error: +v8plus,+v9 - --> $DIR/sparcv8plus.rs:35:1 + --> $DIR/sparcv8plus.rs:34:1 | LL | compile_error!("+v8plus,+v9"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/asm/hexagon-register-pairs.rs b/tests/ui/asm/hexagon-register-pairs.rs index 75f2960778455..e14a80355cc14 100644 --- a/tests/ui/asm/hexagon-register-pairs.rs +++ b/tests/ui/asm/hexagon-register-pairs.rs @@ -7,8 +7,6 @@ #![crate_type = "lib"] #![no_core] -//~? WARN unstable feature specified for `-Ctarget-feature`: `hvx-length128b` - extern crate minicore; use minicore::*; diff --git a/tests/ui/asm/hexagon-register-pairs.stderr b/tests/ui/asm/hexagon-register-pairs.stderr index d59d46363bdb8..6de55c34a8bc2 100644 --- a/tests/ui/asm/hexagon-register-pairs.stderr +++ b/tests/ui/asm/hexagon-register-pairs.stderr @@ -1,11 +1,5 @@ -warning: unstable feature specified for `-Ctarget-feature`: `hvx-length128b` - | - = note: this feature is not stably supported; its behavior can change in the future - = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #162235 - error: avoid using named labels in inline assembly - --> $DIR/hexagon-register-pairs.rs:32:15 + --> $DIR/hexagon-register-pairs.rs:30:15 | LL | asm!("label1: r7:6 = combine(#2, #3)"); | ^^^^^^ @@ -15,7 +9,7 @@ LL | asm!("label1: r7:6 = combine(#2, #3)"); = note: `#[deny(named_asm_labels)]` on by default error: avoid using named labels in inline assembly - --> $DIR/hexagon-register-pairs.rs:35:15 + --> $DIR/hexagon-register-pairs.rs:33:15 | LL | asm!("hexagon_label: nop"); | ^^^^^^^^^^^^^ @@ -23,5 +17,5 @@ LL | asm!("hexagon_label: nop"); = help: only local labels of the form `:` should be used in inline asm = note: see the asm section of Rust By Example for more information -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 2 previous errors diff --git a/tests/ui/asm/hexagon/bad-reg.rs b/tests/ui/asm/hexagon/bad-reg.rs index 6d3e1521a26cc..cbff6d3c521da 100644 --- a/tests/ui/asm/hexagon/bad-reg.rs +++ b/tests/ui/asm/hexagon/bad-reg.rs @@ -3,8 +3,6 @@ //@ needs-llvm-components: hexagon //@ ignore-backends: gcc -//~? WARN unstable feature specified for `-Ctarget-feature`: `hvx-length128b` - #![crate_type = "lib"] #![feature(no_core, asm_experimental_arch)] #![no_core] diff --git a/tests/ui/asm/hexagon/bad-reg.stderr b/tests/ui/asm/hexagon/bad-reg.stderr index ce8f46e1b8498..5fcdd03c6b93e 100644 --- a/tests/ui/asm/hexagon/bad-reg.stderr +++ b/tests/ui/asm/hexagon/bad-reg.stderr @@ -1,95 +1,89 @@ -warning: unstable feature specified for `-Ctarget-feature`: `hvx-length128b` - | - = note: this feature is not stably supported; its behavior can change in the future - = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #162235 - error: invalid register `r19`: r19 is used internally by LLVM and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:20:18 + --> $DIR/bad-reg.rs:18:18 | LL | asm!("", out("r19") _); | ^^^^^^^^^^^^ error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:22:18 + --> $DIR/bad-reg.rs:20:18 | LL | asm!("", out("sp") _); | ^^^^^^^^^^^ error: invalid register `r29`: the stack pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:24:18 + --> $DIR/bad-reg.rs:22:18 | LL | asm!("", out("r29") _); | ^^^^^^^^^^^^ error: invalid register `r30`: the frame register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:26:18 + --> $DIR/bad-reg.rs:24:18 | LL | asm!("", out("r30") _); | ^^^^^^^^^^^^ error: invalid register `fr`: the frame register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:28:18 + --> $DIR/bad-reg.rs:26:18 | LL | asm!("", out("fr") _); | ^^^^^^^^^^^ error: invalid register `r31`: the link register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:30:18 + --> $DIR/bad-reg.rs:28:18 | LL | asm!("", out("r31") _); | ^^^^^^^^^^^^ error: invalid register `lr`: the link register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:32:18 + --> $DIR/bad-reg.rs:30:18 | LL | asm!("", out("lr") _); | ^^^^^^^^^^^ error: invalid register `r19:18`: r19 is used internally by LLVM and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:36:18 + --> $DIR/bad-reg.rs:34:18 | LL | asm!("", out("r19:18") _); | ^^^^^^^^^^^^^^^ error: invalid register `r29:28`: the stack pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:38:18 + --> $DIR/bad-reg.rs:36:18 | LL | asm!("", out("r29:28") _); | ^^^^^^^^^^^^^^^ error: invalid register `r31:30`: the frame register and link register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:40:18 + --> $DIR/bad-reg.rs:38:18 | LL | asm!("", out("r31:30") _); | ^^^^^^^^^^^^^^^ error: register class `preg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:45:18 + --> $DIR/bad-reg.rs:43:18 | LL | asm!("", in("p0") x); | ^^^^^^^^^^ error: register class `preg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:48:18 + --> $DIR/bad-reg.rs:46:18 | LL | asm!("", out("p0") x); | ^^^^^^^^^^^ error: register class `qreg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:54:18 + --> $DIR/bad-reg.rs:52:18 | LL | asm!("", in("q0") x); | ^^^^^^^^^^ error: register class `qreg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:57:18 + --> $DIR/bad-reg.rs:55:18 | LL | asm!("", out("q0") x); | ^^^^^^^^^^^ error: register `r1:0` conflicts with register `r0` - --> $DIR/bad-reg.rs:99:31 + --> $DIR/bad-reg.rs:97:31 | LL | asm!("", out("r0") _, out("r1:0") _); | ----------- ^^^^^^^^^^^^^ register `r1:0` @@ -97,7 +91,7 @@ LL | asm!("", out("r0") _, out("r1:0") _); | register `r0` error: register `r1:0` conflicts with register `r1` - --> $DIR/bad-reg.rs:101:31 + --> $DIR/bad-reg.rs:99:31 | LL | asm!("", out("r1") _, out("r1:0") _); | ----------- ^^^^^^^^^^^^^ register `r1:0` @@ -105,7 +99,7 @@ LL | asm!("", out("r1") _, out("r1:0") _); | register `r1` error: register `v1:0` conflicts with register `v0` - --> $DIR/bad-reg.rs:105:31 + --> $DIR/bad-reg.rs:103:31 | LL | asm!("", out("v0") _, out("v1:0") _); | ----------- ^^^^^^^^^^^^^ register `v1:0` @@ -113,7 +107,7 @@ LL | asm!("", out("v0") _, out("v1:0") _); | register `v0` error: register `v1:0` conflicts with register `v1` - --> $DIR/bad-reg.rs:107:31 + --> $DIR/bad-reg.rs:105:31 | LL | asm!("", out("v1") _, out("v1:0") _); | ----------- ^^^^^^^^^^^^^ register `v1:0` @@ -121,7 +115,7 @@ LL | asm!("", out("v1") _, out("v1:0") _); | register `v1` error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:45:27 + --> $DIR/bad-reg.rs:43:27 | LL | asm!("", in("p0") x); | ^ @@ -129,7 +123,7 @@ LL | asm!("", in("p0") x); = note: register class `preg` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:48:28 + --> $DIR/bad-reg.rs:46:28 | LL | asm!("", out("p0") x); | ^ @@ -137,7 +131,7 @@ LL | asm!("", out("p0") x); = note: register class `preg` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:54:27 + --> $DIR/bad-reg.rs:52:27 | LL | asm!("", in("q0") x); | ^ @@ -145,7 +139,7 @@ LL | asm!("", in("q0") x); = note: register class `qreg` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:57:28 + --> $DIR/bad-reg.rs:55:28 | LL | asm!("", out("q0") x); | ^ @@ -153,7 +147,7 @@ LL | asm!("", out("q0") x); = note: register class `qreg` supports these types: error: type `i64` cannot be used with this register class - --> $DIR/bad-reg.rs:62:34 + --> $DIR/bad-reg.rs:60:34 | LL | asm!("/* {} */", in(reg) y); | ^ @@ -161,7 +155,7 @@ LL | asm!("/* {} */", in(reg) y); = note: register class `reg` supports these types: i8, i16, i32, f32 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:66:39 + --> $DIR/bad-reg.rs:64:39 | LL | asm!("/* {} */", in(reg_pair) x); | ^ @@ -169,7 +163,7 @@ LL | asm!("/* {} */", in(reg_pair) x); = note: register class `reg_pair` supports these types: i64, f64 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:70:35 + --> $DIR/bad-reg.rs:68:35 | LL | asm!("/* {} */", in(vreg) x); | ^ @@ -177,7 +171,7 @@ LL | asm!("/* {} */", in(vreg) x); = note: register class `vreg` supports these types: i32x16, i32x32 error: type `i64` cannot be used with this register class - --> $DIR/bad-reg.rs:72:35 + --> $DIR/bad-reg.rs:70:35 | LL | asm!("/* {} */", in(vreg) y); | ^ @@ -185,7 +179,7 @@ LL | asm!("/* {} */", in(vreg) y); = note: register class `vreg` supports these types: i32x16, i32x32 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:76:40 + --> $DIR/bad-reg.rs:74:40 | LL | asm!("/* {} */", in(vreg_pair) x); | ^ @@ -193,12 +187,12 @@ LL | asm!("/* {} */", in(vreg_pair) x); = note: register class `vreg_pair` supports these types: i32x32, i32x64 error: type `i64` cannot be used with this register class - --> $DIR/bad-reg.rs:78:40 + --> $DIR/bad-reg.rs:76:40 | LL | asm!("/* {} */", in(vreg_pair) y); | ^ | = note: register class `vreg_pair` supports these types: i32x32, i32x64 -error: aborting due to 28 previous errors; 1 warning emitted +error: aborting due to 28 previous errors diff --git a/tests/ui/asm/mips/reg-conflict.mips32.stderr b/tests/ui/asm/mips/reg-conflict.mips32.stderr index 0bb1148e94bd2..7e7857662cca2 100644 --- a/tests/ui/asm/mips/reg-conflict.mips32.stderr +++ b/tests/ui/asm/mips/reg-conflict.mips32.stderr @@ -5,20 +5,8 @@ warning: unknown and unstable feature specified for `-Ctarget-feature`: `mips32r = note: for more information, see issue #162235 = help: consider filing a feature request -warning: unstable feature specified for `-Ctarget-feature`: `fp64` - | - = note: this feature is not stably supported; its behavior can change in the future - = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #162235 - -warning: unstable feature specified for `-Ctarget-feature`: `msa` - | - = note: this feature is not stably supported; its behavior can change in the future - = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #162235 - error: register `$f4` conflicts with register `$w4` - --> $DIR/reg-conflict.rs:28:33 + --> $DIR/reg-conflict.rs:26:33 | LL | asm!("", in("$w4") 0.0, in("$f4") 0.0); | ------------- ^^^^^^^^^^^^^ register `$f4` @@ -26,12 +14,12 @@ LL | asm!("", in("$w4") 0.0, in("$f4") 0.0); | register `$w4` error: register `$f25` conflicts with register `$w25` - --> $DIR/reg-conflict.rs:30:34 + --> $DIR/reg-conflict.rs:28:34 | LL | asm!("", in("$w25") 0.0, in("$f25") 0.0); | -------------- ^^^^^^^^^^^^^^ register `$f25` | | | register `$w25` -error: aborting due to 2 previous errors; 3 warnings emitted +error: aborting due to 2 previous errors; 1 warning emitted diff --git a/tests/ui/asm/mips/reg-conflict.mips32r6.stderr b/tests/ui/asm/mips/reg-conflict.mips32r6.stderr index ee8f6ee07bf8a..a2adedeef3f77 100644 --- a/tests/ui/asm/mips/reg-conflict.mips32r6.stderr +++ b/tests/ui/asm/mips/reg-conflict.mips32r6.stderr @@ -1,17 +1,5 @@ -warning: unstable feature specified for `-Ctarget-feature`: `fp64` - | - = note: this feature is not stably supported; its behavior can change in the future - = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #162235 - -warning: unstable feature specified for `-Ctarget-feature`: `msa` - | - = note: this feature is not stably supported; its behavior can change in the future - = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #162235 - error: register `$f4` conflicts with register `$w4` - --> $DIR/reg-conflict.rs:28:33 + --> $DIR/reg-conflict.rs:26:33 | LL | asm!("", in("$w4") 0.0, in("$f4") 0.0); | ------------- ^^^^^^^^^^^^^ register `$f4` @@ -19,12 +7,12 @@ LL | asm!("", in("$w4") 0.0, in("$f4") 0.0); | register `$w4` error: register `$f25` conflicts with register `$w25` - --> $DIR/reg-conflict.rs:30:34 + --> $DIR/reg-conflict.rs:28:34 | LL | asm!("", in("$w25") 0.0, in("$f25") 0.0); | -------------- ^^^^^^^^^^^^^^ register `$f25` | | | register `$w25` -error: aborting due to 2 previous errors; 2 warnings emitted +error: aborting due to 2 previous errors diff --git a/tests/ui/asm/mips/reg-conflict.mips64.stderr b/tests/ui/asm/mips/reg-conflict.mips64.stderr index 1deb3ae1a4b0d..b8cadec4d4102 100644 --- a/tests/ui/asm/mips/reg-conflict.mips64.stderr +++ b/tests/ui/asm/mips/reg-conflict.mips64.stderr @@ -5,20 +5,8 @@ warning: unknown and unstable feature specified for `-Ctarget-feature`: `mips64r = note: for more information, see issue #162235 = help: consider filing a feature request -warning: unstable feature specified for `-Ctarget-feature`: `fp64` - | - = note: this feature is not stably supported; its behavior can change in the future - = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #162235 - -warning: unstable feature specified for `-Ctarget-feature`: `msa` - | - = note: this feature is not stably supported; its behavior can change in the future - = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #162235 - error: register `$f4` conflicts with register `$w4` - --> $DIR/reg-conflict.rs:28:33 + --> $DIR/reg-conflict.rs:26:33 | LL | asm!("", in("$w4") 0.0, in("$f4") 0.0); | ------------- ^^^^^^^^^^^^^ register `$f4` @@ -26,12 +14,12 @@ LL | asm!("", in("$w4") 0.0, in("$f4") 0.0); | register `$w4` error: register `$f25` conflicts with register `$w25` - --> $DIR/reg-conflict.rs:30:34 + --> $DIR/reg-conflict.rs:28:34 | LL | asm!("", in("$w25") 0.0, in("$f25") 0.0); | -------------- ^^^^^^^^^^^^^^ register `$f25` | | | register `$w25` -error: aborting due to 2 previous errors; 3 warnings emitted +error: aborting due to 2 previous errors; 1 warning emitted diff --git a/tests/ui/asm/mips/reg-conflict.mips64r6.stderr b/tests/ui/asm/mips/reg-conflict.mips64r6.stderr index ee8f6ee07bf8a..a2adedeef3f77 100644 --- a/tests/ui/asm/mips/reg-conflict.mips64r6.stderr +++ b/tests/ui/asm/mips/reg-conflict.mips64r6.stderr @@ -1,17 +1,5 @@ -warning: unstable feature specified for `-Ctarget-feature`: `fp64` - | - = note: this feature is not stably supported; its behavior can change in the future - = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #162235 - -warning: unstable feature specified for `-Ctarget-feature`: `msa` - | - = note: this feature is not stably supported; its behavior can change in the future - = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #162235 - error: register `$f4` conflicts with register `$w4` - --> $DIR/reg-conflict.rs:28:33 + --> $DIR/reg-conflict.rs:26:33 | LL | asm!("", in("$w4") 0.0, in("$f4") 0.0); | ------------- ^^^^^^^^^^^^^ register `$f4` @@ -19,12 +7,12 @@ LL | asm!("", in("$w4") 0.0, in("$f4") 0.0); | register `$w4` error: register `$f25` conflicts with register `$w25` - --> $DIR/reg-conflict.rs:30:34 + --> $DIR/reg-conflict.rs:28:34 | LL | asm!("", in("$w25") 0.0, in("$f25") 0.0); | -------------- ^^^^^^^^^^^^^^ register `$f25` | | | register `$w25` -error: aborting due to 2 previous errors; 2 warnings emitted +error: aborting due to 2 previous errors diff --git a/tests/ui/asm/mips/reg-conflict.rs b/tests/ui/asm/mips/reg-conflict.rs index f0c9b5e6fd091..7fdf799b9d2d3 100644 --- a/tests/ui/asm/mips/reg-conflict.rs +++ b/tests/ui/asm/mips/reg-conflict.rs @@ -17,8 +17,6 @@ //[mips32]~? WARN unknown and unstable feature specified for `-Ctarget-feature`: `mips32r5` //[mips64]~? WARN unknown and unstable feature specified for `-Ctarget-feature`: `mips64r5` -//~? WARN unstable feature specified for `-Ctarget-feature`: `fp64` -//~? WARN unstable feature specified for `-Ctarget-feature`: `msa` extern crate minicore; use minicore::*; diff --git a/tests/ui/target-feature/abi-irrelevant-target-feature-flag-disable.rs b/tests/ui/target-feature/abi-irrelevant-target-feature-flag-disable.rs index 688f51dad58cb..38b35c67ba6ff 100644 --- a/tests/ui/target-feature/abi-irrelevant-target-feature-flag-disable.rs +++ b/tests/ui/target-feature/abi-irrelevant-target-feature-flag-disable.rs @@ -12,5 +12,3 @@ extern crate minicore; use minicore::*; - -//~? WARN unstable feature specified for `-Ctarget-feature`: `x87` diff --git a/tests/ui/target-feature/abi-irrelevant-target-feature-flag-disable.stderr b/tests/ui/target-feature/abi-irrelevant-target-feature-flag-disable.stderr deleted file mode 100644 index c7623519db2ed..0000000000000 --- a/tests/ui/target-feature/abi-irrelevant-target-feature-flag-disable.stderr +++ /dev/null @@ -1,8 +0,0 @@ -warning: unstable feature specified for `-Ctarget-feature`: `x87` - | - = note: this feature is not stably supported; its behavior can change in the future - = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #162235 - -warning: 1 warning emitted - diff --git a/tests/ui/target-feature/abi-required-target-feature-flag-disable.rs b/tests/ui/target-feature/abi-required-target-feature-flag-disable.rs index 4faef8d02d673..f15aa5313ba43 100644 --- a/tests/ui/target-feature/abi-required-target-feature-flag-disable.rs +++ b/tests/ui/target-feature/abi-required-target-feature-flag-disable.rs @@ -26,4 +26,3 @@ extern crate minicore; use minicore::*; //~? WARN must be enabled to ensure that the ABI of the current target can be implemented correctly -//[x86]~? WARN unstable feature specified for `-Ctarget-feature` diff --git a/tests/ui/target-feature/abi-required-target-feature-flag-disable.x86.stderr b/tests/ui/target-feature/abi-required-target-feature-flag-disable.x86.stderr index 52611d230af55..d7f4b3d670b73 100644 --- a/tests/ui/target-feature/abi-required-target-feature-flag-disable.x86.stderr +++ b/tests/ui/target-feature/abi-required-target-feature-flag-disable.x86.stderr @@ -1,13 +1,7 @@ -warning: unstable feature specified for `-Ctarget-feature`: `x87` - | - = note: this feature is not stably supported; its behavior can change in the future - = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #162235 - warning: target feature `x87` must be enabled to ensure that the ABI of the current target can be implemented correctly | = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #162235 -warning: 2 warnings emitted +warning: 1 warning emitted diff --git a/tests/ui/target-feature/feature-hierarchy.hexagon-hvxv66.stderr b/tests/ui/target-feature/feature-hierarchy.hexagon-hvxv66.stderr deleted file mode 100644 index a48e3f28bc683..0000000000000 --- a/tests/ui/target-feature/feature-hierarchy.hexagon-hvxv66.stderr +++ /dev/null @@ -1,8 +0,0 @@ -warning: unstable feature specified for `-Ctarget-feature`: `hvxv66` - | - = note: this feature is not stably supported; its behavior can change in the future - = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #162235 - -warning: 1 warning emitted - diff --git a/tests/ui/target-feature/feature-hierarchy.hexagon-v60.stderr b/tests/ui/target-feature/feature-hierarchy.hexagon-v60.stderr deleted file mode 100644 index 83ce776cb1c97..0000000000000 --- a/tests/ui/target-feature/feature-hierarchy.hexagon-v60.stderr +++ /dev/null @@ -1,8 +0,0 @@ -warning: unstable feature specified for `-Ctarget-feature`: `v60` - | - = note: this feature is not stably supported; its behavior can change in the future - = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #162235 - -warning: 1 warning emitted - diff --git a/tests/ui/target-feature/feature-hierarchy.hexagon-v68.stderr b/tests/ui/target-feature/feature-hierarchy.hexagon-v68.stderr deleted file mode 100644 index 2e62c87d7c9d8..0000000000000 --- a/tests/ui/target-feature/feature-hierarchy.hexagon-v68.stderr +++ /dev/null @@ -1,8 +0,0 @@ -warning: unstable feature specified for `-Ctarget-feature`: `v68` - | - = note: this feature is not stably supported; its behavior can change in the future - = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #162235 - -warning: 1 warning emitted - diff --git a/tests/ui/target-feature/feature-hierarchy.rs b/tests/ui/target-feature/feature-hierarchy.rs index 65f7a1e6d3db4..2629f5b000f80 100644 --- a/tests/ui/target-feature/feature-hierarchy.rs +++ b/tests/ui/target-feature/feature-hierarchy.rs @@ -63,10 +63,6 @@ fn check_sve2_includes_neon() { assert!(cfg!(target_feature = "sve2")); } -//[hexagon-v60]~? WARN unstable feature specified for `-Ctarget-feature`: `v60` -//[hexagon-v68]~? WARN unstable feature specified for `-Ctarget-feature`: `v68` -//[hexagon-hvxv66]~? WARN unstable feature specified for `-Ctarget-feature`: `hvxv66` - #[cfg(hexagon_v60)] fn check_v60_not_v68() { // Enabling v60 should not jump up the scalar feature hierarchy. diff --git a/tests/ui/target-feature/packedstack-combinations.rs b/tests/ui/target-feature/packedstack-combinations.rs index 5dc0f6adf812e..dc45ac1ff5e83 100644 --- a/tests/ui/target-feature/packedstack-combinations.rs +++ b/tests/ui/target-feature/packedstack-combinations.rs @@ -38,7 +38,5 @@ pub fn test() { } //[wrong_arch]~? ERROR `-Zpacked-stack` is only supported on s390x -//[backchain_cli]~? WARN unstable feature specified for `-Ctarget-feature`: `backchain` //[backchain_cli]~? ERROR `-Zpacked-stack` is incompatible with `backchain` target feature //[backchain_attr]~? ERROR `-Zpacked-stack` is incompatible with `backchain` target feature -//[with_softfloat]~? WARN unstable feature specified for `-Ctarget-feature`: `backchain` diff --git a/tests/ui/target-feature/packedstack-combinations.with_softfloat.stderr b/tests/ui/target-feature/packedstack-combinations.with_softfloat.stderr deleted file mode 100644 index eeec785448bc3..0000000000000 --- a/tests/ui/target-feature/packedstack-combinations.with_softfloat.stderr +++ /dev/null @@ -1,8 +0,0 @@ -warning: unstable feature specified for `-Ctarget-feature`: `backchain` - | - = note: this feature is not stably supported; its behavior can change in the future - = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #162235 - -warning: 1 warning emitted - diff --git a/tests/ui/target-feature/unstable-feature.rs b/tests/ui/target-feature/unstable-feature.rs deleted file mode 100644 index a79ad4696033a..0000000000000 --- a/tests/ui/target-feature/unstable-feature.rs +++ /dev/null @@ -1,8 +0,0 @@ -//@ compile-flags: -Ctarget-feature=+x87 --crate-type=rlib --target=x86_64-unknown-linux-gnu -//@ build-pass -//@ needs-llvm-components: x86 - -#![feature(no_core)] -#![no_core] - -//~? WARN unstable feature specified for `-Ctarget-feature`: `x87` diff --git a/tests/ui/target-feature/unstable-feature.stderr b/tests/ui/target-feature/unstable-feature.stderr deleted file mode 100644 index c7623519db2ed..0000000000000 --- a/tests/ui/target-feature/unstable-feature.stderr +++ /dev/null @@ -1,8 +0,0 @@ -warning: unstable feature specified for `-Ctarget-feature`: `x87` - | - = note: this feature is not stably supported; its behavior can change in the future - = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #162235 - -warning: 1 warning emitted - From b89cf31026972568ba8318d55269d71b9a6527ee Mon Sep 17 00:00:00 2001 From: Petrichor Park Date: Mon, 28 Sep 2026 14:32:36 -0500 Subject: [PATCH 20/20] Stabilize vec_try_remove --- library/alloc/src/vec/mod.rs | 3 +-- library/alloctests/tests/lib.rs | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 4537e50e634f2..f837d963a572e 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -2421,12 +2421,11 @@ impl Vec { /// # Examples /// /// ``` - /// #![feature(vec_try_remove)] /// let mut v = vec![1, 2, 3]; /// assert_eq!(v.try_remove(0), Some(1)); /// assert_eq!(v.try_remove(2), None); /// ``` - #[unstable(feature = "vec_try_remove", issue = "146954")] + #[stable(feature = "vec_try_remove", since = "CURRENT_RUSTC_VERSION")] #[rustc_confusables("delete", "take", "remove")] pub fn try_remove(&mut self, index: usize) -> Option { let len = self.len(); diff --git a/library/alloctests/tests/lib.rs b/library/alloctests/tests/lib.rs index 9bcb545c8e87d..5c8ee92388dd0 100644 --- a/library/alloctests/tests/lib.rs +++ b/library/alloctests/tests/lib.rs @@ -60,7 +60,6 @@ #![feature(unique_rc_arc)] #![feature(vec_deque_retain_range)] #![feature(vec_peek_mut)] -#![feature(vec_try_remove)] #![feature(write_all_vectored)] // tidy-alphabetical-end