diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 62115aef4a70d..f12320cb85171 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -263,6 +263,12 @@ impl<'tcx> CompileTimeInterpCx<'tcx> { } /// See documentation on the `ptr_guaranteed_cmp` intrinsic. + /// Returns `2` if the result is unknown. + /// Returns `1` if the pointers are guaranteed equal. + /// Returns `0` if the pointers are guaranteed inequal. + /// + /// Note that this intrinsic is exposed on stable for comparison with null. In other words, any + /// change to this function that affects comparison with null is insta-stable! fn guaranteed_cmp(&mut self, a: Scalar, b: Scalar) -> InterpResult<'tcx, u8> { interp_ok(match (a, b) { // Comparisons between integers are always known. diff --git a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs index d53595929e733..02b361456e484 100644 --- a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs +++ b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs @@ -36,9 +36,7 @@ fn do_check_abi<'tcx>( target_feature_def: DefId, mut emit_err: impl FnMut(Option<&'static str>), ) { - let Some(feature_def) = tcx.sess.target.features_for_correct_vector_abi() else { - return; - }; + let feature_def = tcx.sess.target.features_for_correct_vector_abi(); let codegen_attrs = tcx.codegen_fn_attrs(target_feature_def); for arg_abi in abi.args.iter().chain(std::iter::once(&abi.ret)) { let size = arg_abi.layout.size; diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index 88536926b1122..112eb8626635a 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -598,7 +598,12 @@ const S390X_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[ const RISCV_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[/*(64, "zvl64b"), */ (128, "v")]; // Always warn on SPARC, as the necessary target features cannot be enabled in Rust at the moment. -const SPARC_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[/*(128, "vis")*/]; +const SPARC_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[/*(64, "vis")*/]; + +const HEXAGON_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = + &[/*(512, "hvx-length64b"),*/ (1024, "hvx-length128b")]; +const MIPS_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[(128, "msa")]; +const CSKY_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[(128, "vdspv1")]; impl super::spec::Target { pub fn rust_target_features(&self) -> &'static [(&'static str, Stability, ImpliedFeatures)] { @@ -620,20 +625,24 @@ impl super::spec::Target { } } - // Returns None if we do not support ABI checks on the given target yet. - pub fn features_for_correct_vector_abi(&self) -> Option<&'static [(u64, &'static str)]> { + pub fn features_for_correct_vector_abi(&self) -> &'static [(u64, &'static str)] { match &*self.arch { - "x86" | "x86_64" => Some(X86_FEATURES_FOR_CORRECT_VECTOR_ABI), - "aarch64" | "arm64ec" => Some(AARCH64_FEATURES_FOR_CORRECT_VECTOR_ABI), - "arm" => Some(ARM_FEATURES_FOR_CORRECT_VECTOR_ABI), - "powerpc" | "powerpc64" => Some(POWERPC_FEATURES_FOR_CORRECT_VECTOR_ABI), - "loongarch64" => Some(&[]), // on-stack ABI, so we complain about all by-val vectors - "riscv32" | "riscv64" => Some(RISCV_FEATURES_FOR_CORRECT_VECTOR_ABI), - "wasm32" | "wasm64" => Some(WASM_FEATURES_FOR_CORRECT_VECTOR_ABI), - "s390x" => Some(S390X_FEATURES_FOR_CORRECT_VECTOR_ABI), - "sparc" | "sparc64" => Some(SPARC_FEATURES_FOR_CORRECT_VECTOR_ABI), - // FIXME: add support for non-tier2 architectures - _ => None, + "x86" | "x86_64" => X86_FEATURES_FOR_CORRECT_VECTOR_ABI, + "aarch64" | "arm64ec" => AARCH64_FEATURES_FOR_CORRECT_VECTOR_ABI, + "arm" => ARM_FEATURES_FOR_CORRECT_VECTOR_ABI, + "powerpc" | "powerpc64" => POWERPC_FEATURES_FOR_CORRECT_VECTOR_ABI, + "loongarch64" => &[], // on-stack ABI, so we complain about all by-val vectors + "riscv32" | "riscv64" => RISCV_FEATURES_FOR_CORRECT_VECTOR_ABI, + "wasm32" | "wasm64" => WASM_FEATURES_FOR_CORRECT_VECTOR_ABI, + "s390x" => S390X_FEATURES_FOR_CORRECT_VECTOR_ABI, + "sparc" | "sparc64" => SPARC_FEATURES_FOR_CORRECT_VECTOR_ABI, + "hexagon" => HEXAGON_FEATURES_FOR_CORRECT_VECTOR_ABI, + "mips" | "mips32r6" | "mips64" | "mips64r6" => MIPS_FEATURES_FOR_CORRECT_VECTOR_ABI, + "bpf" => &[], // no vector ABI + "csky" => CSKY_FEATURES_FOR_CORRECT_VECTOR_ABI, + // FIXME: for some tier3 targets, we are overly cautious and always give warnings + // when passing args in vector registers. + _ => &[], } } diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index b042720933b6d..e0576c2551545 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -116,7 +116,7 @@ use crate::vec::Vec; /// `String`s are always valid UTF-8. If you need a non-UTF-8 string, consider /// [`OsString`]. It is similar, but without the UTF-8 constraint. Because UTF-8 /// is a variable width encoding, `String`s are typically smaller than an array of -/// the same `chars`: +/// the same `char`s: /// /// ``` /// use std::mem; diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 72e34e5faf5a7..6a37c60d9c937 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -3292,8 +3292,8 @@ pub const unsafe fn ptr_offset_from_unsigned(_ptr: *const T, _base: *const T) /// See documentation of `<*const T>::guaranteed_eq` for details. /// Returns `2` if the result is unknown. -/// Returns `1` if the pointers are guaranteed equal -/// Returns `0` if the pointers are guaranteed inequal +/// Returns `1` if the pointers are guaranteed equal. +/// Returns `0` if the pointers are guaranteed inequal. #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020"))] #[rustc_intrinsic] #[rustc_nounwind] @@ -3535,7 +3535,6 @@ pub(crate) macro const_eval_select { /// In other words, the following code has *Undefined Behavior*: /// /// ```no_run -/// #![feature(is_val_statically_known)] /// #![feature(core_intrinsics)] /// # #![allow(internal_features)] /// use std::hint::unreachable_unchecked; @@ -3548,7 +3547,6 @@ pub(crate) macro const_eval_select { /// may panic, or it may not: /// /// ```no_run -/// #![feature(is_val_statically_known)] /// #![feature(core_intrinsics)] /// # #![allow(internal_features)] /// use std::intrinsics::is_val_statically_known; @@ -3581,7 +3579,6 @@ pub(crate) macro const_eval_select { /// behave identically: /// /// ``` -/// #![feature(is_val_statically_known)] /// #![feature(core_intrinsics)] /// # #![allow(internal_features)] /// use std::intrinsics::is_val_statically_known; @@ -3598,7 +3595,11 @@ pub(crate) macro const_eval_select { /// # _ = foo(&5_i32); /// # _ = bar(&5_i32); /// ``` -#[rustc_const_unstable(feature = "is_val_statically_known", issue = "none")] +#[cfg_attr( + bootstrap, + rustc_const_stable(feature = "const_is_val_statically_known", since = "CURRENT_RUSTC_VERSION") +)] +#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic] @@ -4013,9 +4014,9 @@ pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: us count: usize = count, ) => { let zero_size = count == 0 || size == 0; - ub_checks::is_aligned_and_not_null(src, align, zero_size) - && ub_checks::is_aligned_and_not_null(dst, align, zero_size) - && ub_checks::is_nonoverlapping(src, dst, size, count) + ub_checks::maybe_is_aligned_and_not_null(src, align, zero_size) + && ub_checks::maybe_is_aligned_and_not_null(dst, align, zero_size) + && ub_checks::maybe_is_nonoverlapping(src, dst, size, count) } ); @@ -4119,8 +4120,8 @@ pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { align: usize = align_of::(), zero_size: bool = T::IS_ZST || count == 0, ) => - ub_checks::is_aligned_and_not_null(src, align, zero_size) - && ub_checks::is_aligned_and_not_null(dst, align, zero_size) + ub_checks::maybe_is_aligned_and_not_null(src, align, zero_size) + && ub_checks::maybe_is_aligned_and_not_null(dst, align, zero_size) ); copy(src, dst, count) } @@ -4201,7 +4202,7 @@ pub const unsafe fn write_bytes(dst: *mut T, val: u8, count: usize) { addr: *const () = dst as *const (), align: usize = align_of::(), zero_size: bool = T::IS_ZST || count == 0, - ) => ub_checks::is_aligned_and_not_null(addr, align, zero_size) + ) => ub_checks::maybe_is_aligned_and_not_null(addr, align, zero_size) ); write_bytes(dst, val, count) } diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 6f7ea7694207a..3b8ac20e52734 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -109,6 +109,7 @@ // tidy-alphabetical-start #![cfg_attr(bootstrap, feature(const_exact_div))] #![cfg_attr(bootstrap, feature(const_fmt_arguments_new))] +#![cfg_attr(bootstrap, feature(const_ub_checks))] #![feature(array_ptr_get)] #![feature(asm_experimental_arch)] #![feature(const_align_of_val)] @@ -121,7 +122,6 @@ #![feature(const_heap)] #![feature(const_nonnull_new)] #![feature(const_pin_2)] -#![feature(const_ptr_is_null)] #![feature(const_ptr_sub_ptr)] #![feature(const_raw_ptr_comparison)] #![feature(const_size_of_val)] @@ -132,14 +132,12 @@ #![feature(const_type_id)] #![feature(const_type_name)] #![feature(const_typed_swap)] -#![feature(const_ub_checks)] #![feature(core_intrinsics)] #![feature(coverage_attribute)] #![feature(do_not_recommend)] #![feature(internal_impls_macro)] #![feature(ip)] #![feature(is_ascii_octdigit)] -#![feature(is_val_statically_known)] #![feature(lazy_get)] #![feature(link_cfg)] #![feature(non_null_from_ref)] diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 4d24b10209600..318bb8ee4cda2 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -2242,7 +2242,6 @@ macro_rules! int_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - #[rustc_allow_const_fn_unstable(is_val_statically_known)] pub const fn wrapping_pow(self, mut exp: u32) -> Self { if exp == 0 { return 1; @@ -2808,7 +2807,6 @@ macro_rules! int_impl { without modifying the original"] #[inline] #[rustc_inherit_overflow_checks] - #[rustc_allow_const_fn_unstable(is_val_statically_known)] pub const fn pow(self, mut exp: u32) -> Self { if exp == 0 { return 1; diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 0a5101884f7d9..0383c13fa082d 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -2251,7 +2251,6 @@ macro_rules! uint_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - #[rustc_allow_const_fn_unstable(is_val_statically_known)] pub const fn wrapping_pow(self, mut exp: u32) -> Self { if exp == 0 { return 1; @@ -2791,7 +2790,6 @@ macro_rules! uint_impl { without modifying the original"] #[inline] #[rustc_inherit_overflow_checks] - #[rustc_allow_const_fn_unstable(is_val_statically_known)] pub const fn pow(self, mut exp: u32) -> Self { if exp == 0 { return 1; diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 2d7507e2d53ee..0dbe819acb1b9 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -29,16 +29,18 @@ impl *const T { /// assert!(!ptr.is_null()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")] + #[rustc_const_stable(feature = "const_ptr_is_null", since = "CURRENT_RUSTC_VERSION")] #[rustc_diagnostic_item = "ptr_const_is_null"] #[inline] + #[rustc_allow_const_fn_unstable(const_eval_select)] pub const fn is_null(self) -> bool { // Compare via a cast to a thin pointer, so fat pointers are only // considering their "data" part for null-ness. let ptr = self as *const u8; const_eval_select!( @capture { ptr: *const u8 } -> bool: - if const #[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")] { + // This use of `const_raw_ptr_comparison` has been explicitly blessed by t-lang. + if const #[rustc_allow_const_fn_unstable(const_raw_ptr_comparison)] { match (ptr).guaranteed_eq(null_mut()) { Some(res) => res, // To remain maximally convervative, we stop execution when we don't @@ -280,7 +282,7 @@ impl *const T { /// } /// ``` #[stable(feature = "ptr_as_ref", since = "1.9.0")] - #[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")] + #[rustc_const_stable(feature = "const_ptr_is_null", since = "CURRENT_RUSTC_VERSION")] #[inline] pub const unsafe fn as_ref<'a>(self) -> Option<&'a T> { // SAFETY: the caller must guarantee that `self` is valid diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 603e904421782..805edddfe6312 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -1103,9 +1103,9 @@ pub const unsafe fn swap_nonoverlapping(x: *mut T, y: *mut T, count: usize) { count: usize = count, ) => { let zero_size = size == 0 || count == 0; - ub_checks::is_aligned_and_not_null(x, align, zero_size) - && ub_checks::is_aligned_and_not_null(y, align, zero_size) - && ub_checks::is_nonoverlapping(x, y, size, count) + ub_checks::maybe_is_aligned_and_not_null(x, align, zero_size) + && ub_checks::maybe_is_aligned_and_not_null(y, align, zero_size) + && ub_checks::maybe_is_nonoverlapping(x, y, size, count) } ); @@ -1216,7 +1216,7 @@ pub const unsafe fn replace(dst: *mut T, src: T) -> T { addr: *const () = dst as *const (), align: usize = align_of::(), is_zst: bool = T::IS_ZST, - ) => ub_checks::is_aligned_and_not_null(addr, align, is_zst) + ) => ub_checks::maybe_is_aligned_and_not_null(addr, align, is_zst) ); mem::replace(&mut *dst, src) } @@ -1369,7 +1369,7 @@ pub const unsafe fn read(src: *const T) -> T { addr: *const () = src as *const (), align: usize = align_of::(), is_zst: bool = T::IS_ZST, - ) => ub_checks::is_aligned_and_not_null(addr, align, is_zst) + ) => ub_checks::maybe_is_aligned_and_not_null(addr, align, is_zst) ); crate::intrinsics::read_via_copy(src) } @@ -1573,7 +1573,7 @@ pub const unsafe fn write(dst: *mut T, src: T) { addr: *mut () = dst as *mut (), align: usize = align_of::(), is_zst: bool = T::IS_ZST, - ) => ub_checks::is_aligned_and_not_null(addr, align, is_zst) + ) => ub_checks::maybe_is_aligned_and_not_null(addr, align, is_zst) ); intrinsics::write_via_move(dst, src) } @@ -1745,7 +1745,7 @@ pub unsafe fn read_volatile(src: *const T) -> T { addr: *const () = src as *const (), align: usize = align_of::(), is_zst: bool = T::IS_ZST, - ) => ub_checks::is_aligned_and_not_null(addr, align, is_zst) + ) => ub_checks::maybe_is_aligned_and_not_null(addr, align, is_zst) ); intrinsics::volatile_load(src) } @@ -1825,7 +1825,7 @@ pub unsafe fn write_volatile(dst: *mut T, src: T) { addr: *mut () = dst as *mut (), align: usize = align_of::(), is_zst: bool = T::IS_ZST, - ) => ub_checks::is_aligned_and_not_null(addr, align, is_zst) + ) => ub_checks::maybe_is_aligned_and_not_null(addr, align, is_zst) ); intrinsics::volatile_store(dst, src); } diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 344ba46a50e20..f0204bd0f773d 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -29,7 +29,7 @@ impl *mut T { /// assert!(!ptr.is_null()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")] + #[rustc_const_stable(feature = "const_ptr_is_null", since = "CURRENT_RUSTC_VERSION")] #[rustc_diagnostic_item = "ptr_is_null"] #[inline] pub const fn is_null(self) -> bool { @@ -271,7 +271,7 @@ impl *mut T { /// } /// ``` #[stable(feature = "ptr_as_ref", since = "1.9.0")] - #[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")] + #[rustc_const_stable(feature = "const_ptr_is_null", since = "CURRENT_RUSTC_VERSION")] #[inline] pub const unsafe fn as_ref<'a>(self) -> Option<&'a T> { // SAFETY: the caller must guarantee that `self` is valid for a @@ -619,7 +619,7 @@ impl *mut T { /// println!("{s:?}"); // It'll print: "[4, 2, 3]". /// ``` #[stable(feature = "ptr_as_ref", since = "1.9.0")] - #[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")] + #[rustc_const_stable(feature = "const_ptr_is_null", since = "CURRENT_RUSTC_VERSION")] #[inline] pub const unsafe fn as_mut<'a>(self) -> Option<&'a mut T> { // SAFETY: the caller must guarantee that `self` is be valid for diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs index 89840881c4d90..319b76899bf8e 100644 --- a/library/core/src/slice/raw.rs +++ b/library/core/src/slice/raw.rs @@ -132,7 +132,7 @@ pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] align: usize = align_of::(), len: usize = len, ) => - ub_checks::is_aligned_and_not_null(data, align, false) + ub_checks::maybe_is_aligned_and_not_null(data, align, false) && ub_checks::is_valid_allocation_size(size, len) ); &*ptr::slice_from_raw_parts(data, len) @@ -186,7 +186,7 @@ pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a m align: usize = align_of::(), len: usize = len, ) => - ub_checks::is_aligned_and_not_null(data, align, false) + ub_checks::maybe_is_aligned_and_not_null(data, align, false) && ub_checks::is_valid_allocation_size(size, len) ); &mut *ptr::slice_from_raw_parts_mut(data, len) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 93b4ad5c1c941..7f2a5424787f7 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -469,7 +469,7 @@ impl AtomicBool { /// [valid]: crate::ptr#safety /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses #[stable(feature = "atomic_from_ptr", since = "1.75.0")] - #[rustc_const_unstable(feature = "const_atomic_from_ptr", issue = "108652")] + #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "CURRENT_RUSTC_VERSION")] pub const unsafe fn from_ptr<'a>(ptr: *mut bool) -> &'a AtomicBool { // SAFETY: guaranteed by the caller unsafe { &*ptr.cast() } @@ -1264,7 +1264,7 @@ impl AtomicPtr { /// [valid]: crate::ptr#safety /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses #[stable(feature = "atomic_from_ptr", since = "1.75.0")] - #[rustc_const_unstable(feature = "const_atomic_from_ptr", issue = "108652")] + #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "CURRENT_RUSTC_VERSION")] pub const unsafe fn from_ptr<'a>(ptr: *mut *mut T) -> &'a AtomicPtr { // SAFETY: guaranteed by the caller unsafe { &*ptr.cast() } @@ -2263,7 +2263,7 @@ macro_rules! atomic_int { /// [valid]: crate::ptr#safety /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses #[stable(feature = "atomic_from_ptr", since = "1.75.0")] - #[rustc_const_unstable(feature = "const_atomic_from_ptr", issue = "108652")] + #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "CURRENT_RUSTC_VERSION")] pub const unsafe fn from_ptr<'a>(ptr: *mut $int_type) -> &'a $atomic_type { // SAFETY: guaranteed by the caller unsafe { &*ptr.cast() } diff --git a/library/core/src/ub_checks.rs b/library/core/src/ub_checks.rs index 8fcbda141dab7..3e6110c9c88a7 100644 --- a/library/core/src/ub_checks.rs +++ b/library/core/src/ub_checks.rs @@ -64,8 +64,6 @@ macro_rules! assert_unsafe_precondition { #[rustc_no_mir_inline] #[inline] #[rustc_nounwind] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_ub_checks", issue = "none"))] - #[rustc_allow_const_fn_unstable(const_ptr_is_null, const_ub_checks)] // only for UB checks const fn precondition_check($($name:$ty),*) { if !$e { ::core::panicking::panic_nounwind( @@ -116,12 +114,16 @@ pub(crate) const fn check_language_ub() -> bool { /// for `assert_unsafe_precondition!` with `check_language_ub`, in which case the /// check is anyway not executed in `const`. #[inline] -#[rustc_const_unstable(feature = "const_ub_checks", issue = "none")] -pub(crate) const fn is_aligned_and_not_null(ptr: *const (), align: usize, is_zst: bool) -> bool { +#[rustc_allow_const_fn_unstable(const_eval_select)] +pub(crate) const fn maybe_is_aligned_and_not_null( + ptr: *const (), + align: usize, + is_zst: bool, +) -> bool { // This is just for safety checks so we can const_eval_select. const_eval_select!( @capture { ptr: *const (), align: usize, is_zst: bool } -> bool: - if const #[rustc_const_unstable(feature = "const_ub_checks", issue = "none")] { + if const { is_zst || !ptr.is_null() } else { ptr.is_aligned_to(align) && (is_zst || !ptr.is_null()) @@ -141,8 +143,8 @@ pub(crate) const fn is_valid_allocation_size(size: usize, len: usize) -> bool { /// Note that in const-eval this function just returns `true` and therefore must /// only be used with `assert_unsafe_precondition!`, similar to `is_aligned_and_not_null`. #[inline] -#[rustc_const_unstable(feature = "const_ub_checks", issue = "none")] -pub(crate) const fn is_nonoverlapping( +#[rustc_allow_const_fn_unstable(const_eval_select)] +pub(crate) const fn maybe_is_nonoverlapping( src: *const (), dst: *const (), size: usize, diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 6d118ae57843a..c1a021e9f8d9b 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -692,8 +692,6 @@ function createQueryElement(query, parserState, name, generics, isInGenerics) { const quadcolon = /::\s*::/.exec(path); if (path.startsWith("::")) { throw ["Paths cannot start with ", "::"]; - } else if (path.endsWith("::")) { - throw ["Paths cannot end with ", "::"]; } else if (quadcolon !== null) { throw ["Unexpected ", quadcolon[0]]; } @@ -3974,18 +3972,19 @@ class DocSearch { if (parsedQuery.foundElems === 1 && !parsedQuery.hasReturnArrow) { const elem = parsedQuery.elems[0]; - for (const id of this.nameTrie.search(elem.normalizedPathLast, this.tailTable)) { + // use arrow functions to preserve `this`. + const handleNameSearch = id => { const row = this.searchIndex[id]; if (!typePassesFilter(elem.typeFilter, row.ty) || (filterCrates !== null && row.crate !== filterCrates)) { - continue; + return; } let pathDist = 0; if (elem.fullPath.length > 1) { pathDist = checkPath(elem.pathWithoutLast, row); if (pathDist === null) { - continue; + return; } } @@ -4008,9 +4007,20 @@ class DocSearch { maxEditDistance, ); } + }; + if (elem.normalizedPathLast !== "") { + const last = elem.normalizedPathLast; + for (const id of this.nameTrie.search(last, this.tailTable)) { + handleNameSearch(id); + } } const length = this.searchIndex.length; + for (let i = 0, nSearchIndex = length; i < nSearchIndex; ++i) { + // queries that end in :: bypass the trie + if (elem.normalizedPathLast === "") { + handleNameSearch(i); + } const row = this.searchIndex[i]; if (filterCrates !== null && row.crate !== filterCrates) { continue; diff --git a/tests/rustdoc-js-std/parser-errors.js b/tests/rustdoc-js-std/parser-errors.js index 068298e72360a..8bffef61c8f4f 100644 --- a/tests/rustdoc-js-std/parser-errors.js +++ b/tests/rustdoc-js-std/parser-errors.js @@ -143,14 +143,6 @@ const PARSED = [ returned: [], error: "Unexpected `:: ::`", }, - { - query: "a::b::", - elems: [], - foundElems: 0, - userQuery: "a::b::", - returned: [], - error: "Paths cannot end with `::`", - }, { query: ":a", elems: [], diff --git a/tests/rustdoc-js-std/path-end-empty.js b/tests/rustdoc-js-std/path-end-empty.js new file mode 100644 index 0000000000000..6e853c61b4d95 --- /dev/null +++ b/tests/rustdoc-js-std/path-end-empty.js @@ -0,0 +1,6 @@ +const EXPECTED = { + 'query': 'Option::', + 'others': [ + { 'path': 'std::option::Option', 'name': 'get_or_insert_default' }, + ], +} diff --git a/tests/ui/consts/const-ptr-is-null.rs b/tests/ui/consts/const-ptr-is-null.rs index 82c293c0ad6e3..92cf87a9782f2 100644 --- a/tests/ui/consts/const-ptr-is-null.rs +++ b/tests/ui/consts/const-ptr-is-null.rs @@ -1,4 +1,3 @@ -#![feature(const_ptr_is_null)] use std::ptr; const IS_NULL: () = { diff --git a/tests/ui/consts/const-ptr-is-null.stderr b/tests/ui/consts/const-ptr-is-null.stderr index 5fd3514281832..f71b37527726f 100644 --- a/tests/ui/consts/const-ptr-is-null.stderr +++ b/tests/ui/consts/const-ptr-is-null.stderr @@ -8,7 +8,7 @@ note: inside `std::ptr::const_ptr::::is_null::compiletime` note: inside `std::ptr::const_ptr::::is_null` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL note: inside `MAYBE_NULL` - --> $DIR/const-ptr-is-null.rs:17:14 + --> $DIR/const-ptr-is-null.rs:16:14 | LL | assert!(!ptr.wrapping_sub(512).is_null()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/consts/is_val_statically_known.rs b/tests/ui/consts/is_val_statically_known.rs index a9059817bcc50..d55910d32d332 100644 --- a/tests/ui/consts/is_val_statically_known.rs +++ b/tests/ui/consts/is_val_statically_known.rs @@ -1,6 +1,6 @@ //@ run-pass -#![feature(core_intrinsics, is_val_statically_known)] +#![feature(core_intrinsics)] use std::intrinsics::is_val_statically_known; diff --git a/tests/ui/consts/ptr_is_null.rs b/tests/ui/consts/ptr_is_null.rs index bbf1380231295..8b41f5718e8db 100644 --- a/tests/ui/consts/ptr_is_null.rs +++ b/tests/ui/consts/ptr_is_null.rs @@ -1,7 +1,6 @@ //@ compile-flags: --crate-type=lib //@ check-pass -#![feature(const_ptr_is_null)] #![allow(useless_ptr_null_checks)] const FOO: &usize = &42; diff --git a/tests/ui/pattern/usefulness/conflicting_bindings.rs b/tests/ui/pattern/usefulness/conflicting_bindings.rs index 0b3e7ce9e9a0f..16737e0a8946b 100644 --- a/tests/ui/pattern/usefulness/conflicting_bindings.rs +++ b/tests/ui/pattern/usefulness/conflicting_bindings.rs @@ -10,6 +10,8 @@ fn main() { //~^ ERROR: mutable more than once if let Some(ref mut y @ ref mut z) = x && true {} //~^ ERROR: mutable more than once + if let Some(_) = Some(()) && let Some(ref mut y @ ref mut z) = x && true {} + //~^ ERROR: mutable more than once while let Some(ref mut y @ ref mut z) = x {} //~^ ERROR: mutable more than once while let Some(ref mut y @ ref mut z) = x && true {} diff --git a/tests/ui/pattern/usefulness/conflicting_bindings.stderr b/tests/ui/pattern/usefulness/conflicting_bindings.stderr index 679fc83e7f563..6f6504e6f6442 100644 --- a/tests/ui/pattern/usefulness/conflicting_bindings.stderr +++ b/tests/ui/pattern/usefulness/conflicting_bindings.stderr @@ -31,7 +31,15 @@ LL | if let Some(ref mut y @ ref mut z) = x && true {} | value is mutably borrowed by `y` here error: cannot borrow value as mutable more than once at a time - --> $DIR/conflicting_bindings.rs:13:20 + --> $DIR/conflicting_bindings.rs:13:43 + | +LL | if let Some(_) = Some(()) && let Some(ref mut y @ ref mut z) = x && true {} + | ^^^^^^^^^ --------- value is mutably borrowed by `z` here + | | + | value is mutably borrowed by `y` here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/conflicting_bindings.rs:15:20 | LL | while let Some(ref mut y @ ref mut z) = x {} | ^^^^^^^^^ --------- value is mutably borrowed by `z` here @@ -39,7 +47,7 @@ LL | while let Some(ref mut y @ ref mut z) = x {} | value is mutably borrowed by `y` here error: cannot borrow value as mutable more than once at a time - --> $DIR/conflicting_bindings.rs:15:20 + --> $DIR/conflicting_bindings.rs:17:20 | LL | while let Some(ref mut y @ ref mut z) = x && true {} | ^^^^^^^^^ --------- value is mutably borrowed by `z` here @@ -47,7 +55,7 @@ LL | while let Some(ref mut y @ ref mut z) = x && true {} | value is mutably borrowed by `y` here error: cannot borrow value as mutable more than once at a time - --> $DIR/conflicting_bindings.rs:18:9 + --> $DIR/conflicting_bindings.rs:20:9 | LL | ref mut y @ ref mut z => {} | ^^^^^^^^^ --------- value is mutably borrowed by `z` here @@ -55,12 +63,12 @@ LL | ref mut y @ ref mut z => {} | value is mutably borrowed by `y` here error: cannot borrow value as mutable more than once at a time - --> $DIR/conflicting_bindings.rs:21:24 + --> $DIR/conflicting_bindings.rs:23:24 | LL | () if let Some(ref mut y @ ref mut z) = x => {} | ^^^^^^^^^ --------- value is mutably borrowed by `z` here | | | value is mutably borrowed by `y` here -error: aborting due to 8 previous errors +error: aborting due to 9 previous errors diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let-chain.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let-chain.rs index 5c333cd7795c7..47653efffb7b8 100644 --- a/tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let-chain.rs +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let-chain.rs @@ -94,4 +94,15 @@ fn use_in_arm_ok(c: bool) { }; } +fn use_in_same_chain(c: bool) { + let x: Box<_> = Box::new(1); + + let v = (1, 2); + + match v { + (1, 2) if let y = x && c && let z = x => false, //~ ERROR use of moved value: `x` + _ => true, + }; +} + fn main() {} diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let-chain.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let-chain.stderr index 087e54244b319..123c5f1943024 100644 --- a/tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let-chain.stderr +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let-chain.stderr @@ -60,6 +60,22 @@ help: borrow this binding in the pattern to avoid moving the value LL | (1, 2) if let ref y = x && c => false, | +++ -error: aborting due to 4 previous errors +error[E0382]: use of moved value: `x` + --> $DIR/move-guard-if-let-chain.rs:103:41 + | +LL | let x: Box<_> = Box::new(1); + | - move occurs because `x` has type `Box`, which does not implement the `Copy` trait +... +LL | (1, 2) if let y = x && c && let z = x => false, + | - ^ value used here after move + | | + | value moved here + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | (1, 2) if let ref y = x && c && let z = x => false, + | +++ + +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/temporary-early-drop.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/temporary-early-drop.rs new file mode 100644 index 0000000000000..389c76337f097 --- /dev/null +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/temporary-early-drop.rs @@ -0,0 +1,25 @@ +// issue-103476 +//@ compile-flags: -Zlint-mir -Zunstable-options +//@ edition: 2024 +//@ check-pass + +#![feature(let_chains)] +#![allow(irrefutable_let_patterns)] + +struct Pd; + +impl Pd { + fn it(&self) -> It { + todo!() + } +} + +pub struct It<'a>(Box>); + +trait Tr<'a> {} + +fn f(m: Option) { + if let Some(n) = m && let it = n.it() {}; +} + +fn main() {} diff --git a/triagebot.toml b/triagebot.toml index d5bc549ca9ff5..c5942fe27cdd1 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -997,7 +997,6 @@ compiler = [ "@oli-obk", "@petrochenkov", "@pnkfelix", - "@TaKO8Ki", "@wesleywiser", ] libs = [ @@ -1048,7 +1047,6 @@ diagnostics = [ "@davidtwco", "@estebank", "@oli-obk", - "@TaKO8Ki", "@chenyukang", ] parser = [