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_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 7ec4ad6dc359f..37eb463cba63e 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -650,8 +650,9 @@ pub(crate) struct LeftArrowOperator { #[diag(parse_remove_let)] pub(crate) struct RemoveLet { #[primary_span] - #[suggestion(applicability = "machine-applicable", code = "", style = "verbose")] pub span: Span, + #[suggestion(applicability = "machine-applicable", code = "", style = "verbose")] + pub suggestion: Span, } #[derive(Diagnostic)] diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 0ac6133e8289f..0012db471ef4a 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2683,6 +2683,13 @@ impl<'a> Parser<'a> { // ^^ // } // + // We account for macro calls that were meant as conditions as well. + // + // if ... { + // } else if macro! { foo bar } { + // ^^ + // } + // // If $cond is "statement-like" such as ExprKind::While then we // want to suggest wrapping in braces. // @@ -2693,7 +2700,9 @@ impl<'a> Parser<'a> { // } // ^ if self.check(&TokenKind::OpenDelim(Delimiter::Brace)) - && classify::expr_requires_semi_to_be_stmt(&cond) => + && (classify::expr_requires_semi_to_be_stmt(&cond) + || matches!(cond.kind, ExprKind::MacCall(..))) + => { self.dcx().emit_err(errors::ExpectedElseBlock { first_tok_span, diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 3546e5b0f0495..c4326427f67b0 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -685,7 +685,7 @@ impl<'a> Parser<'a> { self.bump(); // Trim extra space after the `let` let span = lo.with_hi(self.token.span.lo()); - self.dcx().emit_err(RemoveLet { span }); + self.dcx().emit_err(RemoveLet { span: lo, suggestion: span }); lo = self.token.span; } diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index b7cdae3e3e123..190cd9ed0610f 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -475,6 +475,7 @@ impl<'a> Parser<'a> { } fn error_block_no_opening_brace_msg(&mut self, msg: Cow<'static, str>) -> Diag<'a> { + let prev = self.prev_token.span; let sp = self.token.span; let mut e = self.dcx().struct_span_err(sp, msg); let do_not_suggest_help = self.token.is_keyword(kw::In) || self.token == token::Colon; @@ -514,8 +515,97 @@ impl<'a> Parser<'a> { } else { stmt.span }; + self.suggest_fixes_misparsed_for_loop_head( + &mut e, + prev.between(sp), + stmt_span, + &stmt.kind, + ); + } + Err(e) => { + self.recover_stmt_(SemiColonMode::Break, BlockMode::Ignore); + e.cancel(); + } + _ => {} + } + e.span_label(sp, "expected `{`"); + e + } + + fn suggest_fixes_misparsed_for_loop_head( + &self, + e: &mut Diag<'_>, + between: Span, + stmt_span: Span, + stmt_kind: &StmtKind, + ) { + match (&self.token.kind, &stmt_kind) { + (token::OpenDelim(Delimiter::Brace), StmtKind::Expr(expr)) + if let ExprKind::Call(..) = expr.kind => + { + // for _ in x y() {} + e.span_suggestion_verbose( + between, + "you might have meant to write a method call", + ".".to_string(), + Applicability::MaybeIncorrect, + ); + } + (token::OpenDelim(Delimiter::Brace), StmtKind::Expr(expr)) + if let ExprKind::Field(..) = expr.kind => + { + // for _ in x y.z {} + e.span_suggestion_verbose( + between, + "you might have meant to write a field access", + ".".to_string(), + Applicability::MaybeIncorrect, + ); + } + (token::CloseDelim(Delimiter::Brace), StmtKind::Expr(expr)) + if let ExprKind::Struct(expr) = &expr.kind + && let None = expr.qself + && expr.path.segments.len() == 1 => + { + // This is specific to "mistyped `if` condition followed by empty body" + // + // for _ in x y {} + e.span_suggestion_verbose( + between, + "you might have meant to write a field access", + ".".to_string(), + Applicability::MaybeIncorrect, + ); + } + (token::OpenDelim(Delimiter::Brace), StmtKind::Expr(expr)) + if let ExprKind::Lit(lit) = expr.kind + && let None = lit.suffix + && let token::LitKind::Integer | token::LitKind::Float = lit.kind => + { + // for _ in x 0 {} + // for _ in x 0.0 {} + e.span_suggestion_verbose( + between, + format!("you might have meant to write a field access"), + ".".to_string(), + Applicability::MaybeIncorrect, + ); + } + (token::OpenDelim(Delimiter::Brace), StmtKind::Expr(expr)) + if let ExprKind::Loop(..) + | ExprKind::If(..) + | ExprKind::While(..) + | ExprKind::Match(..) + | ExprKind::ForLoop { .. } + | ExprKind::TryBlock(..) + | ExprKind::Ret(..) + | ExprKind::Closure(..) + | ExprKind::Struct(..) + | ExprKind::Try(..) = expr.kind => + { + // These are more likely to have been meant as a block body. e.multipart_suggestion( - "try placing this code inside a block", + "you might have meant to write this as part of a block", vec![ (stmt_span.shrink_to_lo(), "{ ".to_string()), (stmt_span.shrink_to_hi(), " }".to_string()), @@ -524,14 +614,19 @@ impl<'a> Parser<'a> { Applicability::MaybeIncorrect, ); } - Err(e) => { - self.recover_stmt_(SemiColonMode::Break, BlockMode::Ignore); - e.cancel(); + (token::OpenDelim(Delimiter::Brace), _) => {} + (_, _) => { + e.multipart_suggestion( + "you might have meant to write this as part of a block", + vec![ + (stmt_span.shrink_to_lo(), "{ ".to_string()), + (stmt_span.shrink_to_hi(), " }".to_string()), + ], + // Speculative; has been misleading in the past (#46836). + Applicability::MaybeIncorrect, + ); } - _ => {} } - e.span_label(sp, "expected `{`"); - e } fn error_block_no_opening_brace(&mut self) -> PResult<'a, T> { 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 c87a6439ec3eb..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] @@ -4014,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) } ); @@ -4120,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) } @@ -4202,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 0ce33958941c8..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,7 +132,6 @@ #![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)] 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/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/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/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/issues/issue-39848.stderr b/tests/ui/issues/issue-39848.stderr index a6c6c61f17095..1ffed2d4a1da1 100644 --- a/tests/ui/issues/issue-39848.stderr +++ b/tests/ui/issues/issue-39848.stderr @@ -16,10 +16,10 @@ LL | if $tgt.has_$field() {} LL | get_opt!(bar, foo); | ------------------ in this macro invocation = note: this error originates in the macro `get_opt` (in Nightly builds, run with -Z macro-backtrace for more info) -help: try placing this code inside a block +help: you might have meant to write a method call | -LL | if $tgt.has_{ $field() } {} - | + + +LL | if $tgt.has_.$field() {} + | + error: aborting due to 1 previous error diff --git a/tests/ui/let-else/let-else-if.stderr b/tests/ui/let-else/let-else-if.stderr index 7e2215c8c05d9..ad36b423150a7 100644 --- a/tests/ui/let-else/let-else-if.stderr +++ b/tests/ui/let-else/let-else-if.stderr @@ -4,7 +4,7 @@ error: conditional `else if` is not supported for `let...else` LL | let Some(_) = Some(()) else if true { | ^^ expected `{` | -help: try placing this code inside a block +help: you might have meant to write this as part of a block | LL ~ let Some(_) = Some(()) else { if true { LL | diff --git a/tests/ui/lint/issue-104392.stderr b/tests/ui/lint/issue-104392.stderr index 8e466439ae643..4d8d8c56d41c1 100644 --- a/tests/ui/lint/issue-104392.stderr +++ b/tests/ui/lint/issue-104392.stderr @@ -6,7 +6,7 @@ LL | { unsafe 92 } | | | while parsing this `unsafe` expression | -help: try placing this code inside a block +help: you might have meant to write this as part of a block | LL | { unsafe { 92 } } | + + diff --git a/tests/ui/missing/missing-block-hint.stderr b/tests/ui/missing/missing-block-hint.stderr index 18719289abdc8..7a08d70d0ce55 100644 --- a/tests/ui/missing/missing-block-hint.stderr +++ b/tests/ui/missing/missing-block-hint.stderr @@ -25,7 +25,7 @@ note: the `if` expression is missing a block after this condition | LL | if (foo) | ^^^^^ -help: try placing this code inside a block +help: you might have meant to write this as part of a block | LL | { bar; } | + + diff --git a/tests/ui/parser/bad-if-statements.stderr b/tests/ui/parser/bad-if-statements.stderr index ee839db645509..320b1176993d8 100644 --- a/tests/ui/parser/bad-if-statements.stderr +++ b/tests/ui/parser/bad-if-statements.stderr @@ -29,7 +29,7 @@ note: the `if` expression is missing a block after this condition | LL | if true x | ^^^^ -help: try placing this code inside a block +help: you might have meant to write this as part of a block | LL | if true { x } | + + @@ -65,7 +65,7 @@ note: the `if` expression is missing a block after this condition | LL | if true x else {} | ^^^^ -help: try placing this code inside a block +help: you might have meant to write this as part of a block | LL | if true { x } else {} | + + diff --git a/tests/ui/parser/block-no-opening-brace.stderr b/tests/ui/parser/block-no-opening-brace.stderr index 83360944ed560..b65de4eac3f80 100644 --- a/tests/ui/parser/block-no-opening-brace.stderr +++ b/tests/ui/parser/block-no-opening-brace.stderr @@ -6,7 +6,7 @@ LL | loop LL | let x = 0; | ^^^ expected `{` | -help: try placing this code inside a block +help: you might have meant to write this as part of a block | LL | { let x = 0; } | + + @@ -21,7 +21,7 @@ LL | while true LL | let x = 0; | ^^^ expected `{` | -help: try placing this code inside a block +help: you might have meant to write this as part of a block | LL | { let x = 0; } | + + @@ -32,7 +32,7 @@ error: expected `{`, found keyword `let` LL | let x = 0; | ^^^ expected `{` | -help: try placing this code inside a block +help: you might have meant to write this as part of a block | LL | { let x = 0; } | + + diff --git a/tests/ui/parser/closure-return-syntax.stderr b/tests/ui/parser/closure-return-syntax.stderr index eb8428854afb9..aacc31ed871d3 100644 --- a/tests/ui/parser/closure-return-syntax.stderr +++ b/tests/ui/parser/closure-return-syntax.stderr @@ -4,7 +4,7 @@ error: expected `{`, found `22` LL | let x = || -> i32 22; | ^^ expected `{` | -help: try placing this code inside a block +help: you might have meant to write this as part of a block | LL | let x = || -> i32 { 22 }; | + + diff --git a/tests/ui/parser/else-no-if.stderr b/tests/ui/parser/else-no-if.stderr index 2e3e8f6b50e95..eec64b0f4bc2f 100644 --- a/tests/ui/parser/else-no-if.stderr +++ b/tests/ui/parser/else-no-if.stderr @@ -30,7 +30,7 @@ error: expected `{`, found `falsy` LL | } else falsy(); | ^^^^^ expected `{` | -help: try placing this code inside a block +help: you might have meant to write this as part of a block | LL | } else { falsy() }; | + + @@ -41,7 +41,7 @@ error: expected `{`, found keyword `loop` LL | } else loop{} | ^^^^ expected `{` | -help: try placing this code inside a block +help: you might have meant to write this as part of a block | LL | } else { loop{} } | + + @@ -65,7 +65,7 @@ error: expected `{`, found `falsy` LL | } else falsy!(); | ^^^^^ expected `{` | -help: try placing this code inside a block +help: you might have meant to write this as part of a block | LL | } else { falsy!() }; | + + @@ -74,12 +74,14 @@ error: expected `{`, found `falsy` --> $DIR/else-no-if.rs:47:12 | LL | } else falsy! {} { - | ^^^^^ expected `{` + | ---- ^^^^^ + | | + | expected an `if` or a block after this `else` | -help: try placing this code inside a block +help: add an `if` if this is the condition of a chained `else if` statement | -LL | } else { falsy! {} } { - | + + +LL | } else if falsy! {} { + | ++ error: expected `{`, found `falsy` --> $DIR/else-no-if.rs:54:12 @@ -87,7 +89,7 @@ error: expected `{`, found `falsy` LL | } else falsy! {}; | ^^^^^ expected `{` | -help: try placing this code inside a block +help: you might have meant to write this as part of a block | LL | } else { falsy! {} }; | + + diff --git a/tests/ui/parser/label-after-block-like.stderr b/tests/ui/parser/label-after-block-like.stderr index be8c679d8ce31..4dea225e3f3e3 100644 --- a/tests/ui/parser/label-after-block-like.stderr +++ b/tests/ui/parser/label-after-block-like.stderr @@ -23,7 +23,7 @@ note: the `if` expression is missing a block after this condition | LL | if let () = () 'a {} | ^^^^^^^^^^^ -help: try placing this code inside a block +help: you might have meant to write this as part of a block | LL | if let () = () { 'a {} } | + + @@ -53,7 +53,7 @@ note: the `if` expression is missing a block after this condition | LL | if true 'a {} | ^^^^ -help: try placing this code inside a block +help: you might have meant to write this as part of a block | LL | if true { 'a {} } | + + @@ -80,7 +80,7 @@ LL | loop 'a {} | | | while parsing this `loop` expression | -help: try placing this code inside a block +help: you might have meant to write this as part of a block | LL | loop { 'a {} } | + + @@ -108,7 +108,7 @@ LL | while true 'a {} | | this `while` condition successfully parsed | while parsing the body of this `while` expression | -help: try placing this code inside a block +help: you might have meant to write this as part of a block | LL | while true { 'a {} } | + + @@ -136,7 +136,7 @@ LL | while let () = () 'a {} | | this `while` condition successfully parsed | while parsing the body of this `while` expression | -help: try placing this code inside a block +help: you might have meant to write this as part of a block | LL | while let () = () { 'a {} } | + + @@ -161,7 +161,7 @@ error: expected `{`, found `'a` LL | for _ in 0..0 'a {} | ^^ expected `{` | -help: try placing this code inside a block +help: you might have meant to write this as part of a block | LL | for _ in 0..0 { 'a {} } | + + @@ -188,7 +188,7 @@ LL | unsafe 'a {} | | | while parsing this `unsafe` expression | -help: try placing this code inside a block +help: you might have meant to write this as part of a block | LL | unsafe { 'a {} } | + + diff --git a/tests/ui/parser/recover/missing-dot-on-if-condition-expression-fixable.fixed b/tests/ui/parser/recover/missing-dot-on-if-condition-expression-fixable.fixed new file mode 100644 index 0000000000000..ea9dc4cf6cc6b --- /dev/null +++ b/tests/ui/parser/recover/missing-dot-on-if-condition-expression-fixable.fixed @@ -0,0 +1,39 @@ +//@ run-rustfix +#![allow(dead_code)] +fn main() { + for _ in [1, 2, 3].iter().map(|x| x) {} + //~^ ERROR expected `{`, found `map` + //~| HELP you might have meant to write a method call +} +fn foo5() { + let x = (vec![1, 2, 3],); + for _ in x.0 {} + //~^ ERROR expected `{`, found `0` + //~| HELP you might have meant to write a field access +} +fn foo6() { + let x = ((vec![1, 2, 3],),); + for _ in x.0.0 {} + //~^ ERROR expected `{`, found `0.0` + //~| HELP you might have meant to write a field access +} +fn foo7() { + let x = Some(vec![1, 2, 3]); + for _ in x.unwrap() {} + //~^ ERROR expected `{`, found `unwrap` + //~| HELP you might have meant to write a method call +} +fn foo8() { + let x = S { a: A { b: vec![1, 2, 3] } }; + for _ in x.a.b {} + //~^ ERROR expected `{`, found `a` + //~| HELP you might have meant to write a field access +} + +struct S { + a: A, +} + +struct A { + b: Vec, +} diff --git a/tests/ui/parser/recover/missing-dot-on-if-condition-expression-fixable.rs b/tests/ui/parser/recover/missing-dot-on-if-condition-expression-fixable.rs new file mode 100644 index 0000000000000..1833f458a8ac0 --- /dev/null +++ b/tests/ui/parser/recover/missing-dot-on-if-condition-expression-fixable.rs @@ -0,0 +1,39 @@ +//@ run-rustfix +#![allow(dead_code)] +fn main() { + for _ in [1, 2, 3].iter()map(|x| x) {} + //~^ ERROR expected `{`, found `map` + //~| HELP you might have meant to write a method call +} +fn foo5() { + let x = (vec![1, 2, 3],); + for _ in x 0 {} + //~^ ERROR expected `{`, found `0` + //~| HELP you might have meant to write a field access +} +fn foo6() { + let x = ((vec![1, 2, 3],),); + for _ in x 0.0 {} + //~^ ERROR expected `{`, found `0.0` + //~| HELP you might have meant to write a field access +} +fn foo7() { + let x = Some(vec![1, 2, 3]); + for _ in x unwrap() {} + //~^ ERROR expected `{`, found `unwrap` + //~| HELP you might have meant to write a method call +} +fn foo8() { + let x = S { a: A { b: vec![1, 2, 3] } }; + for _ in x a.b {} + //~^ ERROR expected `{`, found `a` + //~| HELP you might have meant to write a field access +} + +struct S { + a: A, +} + +struct A { + b: Vec, +} diff --git a/tests/ui/parser/recover/missing-dot-on-if-condition-expression-fixable.stderr b/tests/ui/parser/recover/missing-dot-on-if-condition-expression-fixable.stderr new file mode 100644 index 0000000000000..87f76efffa676 --- /dev/null +++ b/tests/ui/parser/recover/missing-dot-on-if-condition-expression-fixable.stderr @@ -0,0 +1,57 @@ +error: expected `{`, found `map` + --> $DIR/missing-dot-on-if-condition-expression-fixable.rs:4:30 + | +LL | for _ in [1, 2, 3].iter()map(|x| x) {} + | ^^^ expected `{` + | +help: you might have meant to write a method call + | +LL | for _ in [1, 2, 3].iter().map(|x| x) {} + | + + +error: expected `{`, found `0` + --> $DIR/missing-dot-on-if-condition-expression-fixable.rs:10:16 + | +LL | for _ in x 0 {} + | ^ expected `{` + | +help: you might have meant to write a field access + | +LL | for _ in x.0 {} + | + + +error: expected `{`, found `0.0` + --> $DIR/missing-dot-on-if-condition-expression-fixable.rs:16:16 + | +LL | for _ in x 0.0 {} + | ^^^ expected `{` + | +help: you might have meant to write a field access + | +LL | for _ in x.0.0 {} + | + + +error: expected `{`, found `unwrap` + --> $DIR/missing-dot-on-if-condition-expression-fixable.rs:22:16 + | +LL | for _ in x unwrap() {} + | ^^^^^^ expected `{` + | +help: you might have meant to write a method call + | +LL | for _ in x.unwrap() {} + | + + +error: expected `{`, found `a` + --> $DIR/missing-dot-on-if-condition-expression-fixable.rs:28:16 + | +LL | for _ in x a.b {} + | ^ expected `{` + | +help: you might have meant to write a field access + | +LL | for _ in x.a.b {} + | + + +error: aborting due to 5 previous errors + diff --git a/tests/ui/parser/recover/missing-dot-on-if-condition-expression.rs b/tests/ui/parser/recover/missing-dot-on-if-condition-expression.rs new file mode 100644 index 0000000000000..c4a9ed66a8322 --- /dev/null +++ b/tests/ui/parser/recover/missing-dot-on-if-condition-expression.rs @@ -0,0 +1,57 @@ +fn main() { + for _ in [1, 2, 3].iter()map(|x| x) {} + //~^ ERROR expected `{`, found `map` + //~| HELP you might have meant to write a method call +} +fn foo1() { + for _ in 1.3f64 cos() {} + //~^ ERROR expected `{`, found `cos` + //~| HELP you might have meant to write a method call +} +fn foo2() { + for _ in 1.3 cos {} + //~^ ERROR expected `{`, found `cos` + //~| HELP you might have meant to write a field access +} +fn foo3() { + for _ in 1 cos() {} + //~^ ERROR expected `{`, found `cos` + //~| HELP you might have meant to write a method call +} +fn foo4() { + for _ in 1 cos {} + //~^ ERROR expected `{`, found `cos` + //~| HELP you might have meant to write a field access +} +fn foo5() { + let x = (vec![1, 2, 3],); + for _ in x 0 {} + //~^ ERROR expected `{`, found `0` + //~| HELP you might have meant to write a field access +} +fn foo6() { + let x = ((vec![1, 2, 3],),); + for _ in x 0.0 {} + //~^ ERROR expected `{`, found `0.0` + //~| HELP you might have meant to write a field access +} +fn foo7() { + let x = Some(vec![1, 2, 3]); + for _ in x unwrap() {} + //~^ ERROR expected `{`, found `unwrap` + //~| HELP you might have meant to write a method call +} +fn foo8() { + let x = S { a: A { b: vec![1, 2, 3] } }; + for _ in x a.b {} + //~^ ERROR expected `{`, found `a` + //~| HELP you might have meant to write a field access +} + +struct S { + a: A, +} + +struct A { + b: Vec, +} diff --git a/tests/ui/parser/recover/missing-dot-on-if-condition-expression.stderr b/tests/ui/parser/recover/missing-dot-on-if-condition-expression.stderr new file mode 100644 index 0000000000000..bfb72b9568281 --- /dev/null +++ b/tests/ui/parser/recover/missing-dot-on-if-condition-expression.stderr @@ -0,0 +1,101 @@ +error: expected `{`, found `map` + --> $DIR/missing-dot-on-if-condition-expression.rs:2:30 + | +LL | for _ in [1, 2, 3].iter()map(|x| x) {} + | ^^^ expected `{` + | +help: you might have meant to write a method call + | +LL | for _ in [1, 2, 3].iter().map(|x| x) {} + | + + +error: expected `{`, found `cos` + --> $DIR/missing-dot-on-if-condition-expression.rs:7:21 + | +LL | for _ in 1.3f64 cos() {} + | ^^^ expected `{` + | +help: you might have meant to write a method call + | +LL | for _ in 1.3f64.cos() {} + | + + +error: expected `{`, found `cos` + --> $DIR/missing-dot-on-if-condition-expression.rs:12:18 + | +LL | for _ in 1.3 cos {} + | ^^^ expected `{` + | +help: you might have meant to write a field access + | +LL | for _ in 1.3.cos {} + | + + +error: expected `{`, found `cos` + --> $DIR/missing-dot-on-if-condition-expression.rs:17:16 + | +LL | for _ in 1 cos() {} + | ^^^ expected `{` + | +help: you might have meant to write a method call + | +LL | for _ in 1.cos() {} + | + + +error: expected `{`, found `cos` + --> $DIR/missing-dot-on-if-condition-expression.rs:22:16 + | +LL | for _ in 1 cos {} + | ^^^ expected `{` + | +help: you might have meant to write a field access + | +LL | for _ in 1.cos {} + | + + +error: expected `{`, found `0` + --> $DIR/missing-dot-on-if-condition-expression.rs:28:16 + | +LL | for _ in x 0 {} + | ^ expected `{` + | +help: you might have meant to write a field access + | +LL | for _ in x.0 {} + | + + +error: expected `{`, found `0.0` + --> $DIR/missing-dot-on-if-condition-expression.rs:34:16 + | +LL | for _ in x 0.0 {} + | ^^^ expected `{` + | +help: you might have meant to write a field access + | +LL | for _ in x.0.0 {} + | + + +error: expected `{`, found `unwrap` + --> $DIR/missing-dot-on-if-condition-expression.rs:40:16 + | +LL | for _ in x unwrap() {} + | ^^^^^^ expected `{` + | +help: you might have meant to write a method call + | +LL | for _ in x.unwrap() {} + | + + +error: expected `{`, found `a` + --> $DIR/missing-dot-on-if-condition-expression.rs:46:16 + | +LL | for _ in x a.b {} + | ^ expected `{` + | +help: you might have meant to write a field access + | +LL | for _ in x.a.b {} + | + + +error: aborting due to 9 previous errors + diff --git a/tests/ui/parser/unnecessary-let.fixed b/tests/ui/parser/unnecessary-let.fixed new file mode 100644 index 0000000000000..bdee07e76aaec --- /dev/null +++ b/tests/ui/parser/unnecessary-let.fixed @@ -0,0 +1,13 @@ +//@ run-rustfix + +fn main() { + for _x in [1, 2, 3] {} + //~^ ERROR expected pattern, found `let` + //~| ERROR missing `in` in `for` loop + + match 1 { + 1 => {} + //~^ ERROR expected pattern, found `let` + _ => {} + } +} diff --git a/tests/ui/parser/unnecessary-let.rs b/tests/ui/parser/unnecessary-let.rs index 6279109621d70..a889d9f778977 100644 --- a/tests/ui/parser/unnecessary-let.rs +++ b/tests/ui/parser/unnecessary-let.rs @@ -1,5 +1,7 @@ +//@ run-rustfix + fn main() { - for let x of [1, 2, 3] {} + for let _x of [1, 2, 3] {} //~^ ERROR expected pattern, found `let` //~| ERROR missing `in` in `for` loop diff --git a/tests/ui/parser/unnecessary-let.stderr b/tests/ui/parser/unnecessary-let.stderr index 05ac1faafd4d9..0b28123747a02 100644 --- a/tests/ui/parser/unnecessary-let.stderr +++ b/tests/ui/parser/unnecessary-let.stderr @@ -1,31 +1,31 @@ error: expected pattern, found `let` - --> $DIR/unnecessary-let.rs:2:9 + --> $DIR/unnecessary-let.rs:4:9 | -LL | for let x of [1, 2, 3] {} - | ^^^^ +LL | for let _x of [1, 2, 3] {} + | ^^^ | help: remove the unnecessary `let` keyword | -LL - for let x of [1, 2, 3] {} -LL + for x of [1, 2, 3] {} +LL - for let _x of [1, 2, 3] {} +LL + for _x of [1, 2, 3] {} | error: missing `in` in `for` loop - --> $DIR/unnecessary-let.rs:2:15 + --> $DIR/unnecessary-let.rs:4:16 | -LL | for let x of [1, 2, 3] {} - | ^^ +LL | for let _x of [1, 2, 3] {} + | ^^ | help: try using `in` here instead | -LL | for let x in [1, 2, 3] {} - | ~~ +LL | for let _x in [1, 2, 3] {} + | ~~ error: expected pattern, found `let` - --> $DIR/unnecessary-let.rs:7:9 + --> $DIR/unnecessary-let.rs:9:9 | LL | let 1 => {} - | ^^^^ + | ^^^ | help: remove the unnecessary `let` keyword | 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/tests/ui/unsafe/unsafe-block-without-braces.stderr b/tests/ui/unsafe/unsafe-block-without-braces.stderr index d29e49d73a661..3d8234c15e79a 100644 --- a/tests/ui/unsafe/unsafe-block-without-braces.stderr +++ b/tests/ui/unsafe/unsafe-block-without-braces.stderr @@ -6,7 +6,7 @@ LL | unsafe //{ LL | std::mem::transmute::(1.0); | ^^^ expected `{` | -help: try placing this code inside a block +help: you might have meant to write this as part of a block | LL | { std::mem::transmute::(1.0); } | + +