mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 00:03:43 +00:00
Auto merge of #133135 - jieyouxu:rollup-4q1wbyq, r=jieyouxu
Rollup of 6 pull requests Successful merges: - #133029 (ABI checks: add support for some tier3 arches, warn on others.) - #133051 (Increase accuracy of `if` condition misparse suggestion) - #133060 (Trim whitespace in RemoveLet primary span) - #133093 (Let chains tests) - #133116 (stabilize const_ptr_is_null) - #133126 (alloc: fix `String`'s doc) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
a8e75c53d0
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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)]
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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,14 +515,11 @@ impl<'a> Parser<'a> {
|
||||
} else {
|
||||
stmt.span
|
||||
};
|
||||
e.multipart_suggestion(
|
||||
"try placing this code inside 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,
|
||||
self.suggest_fixes_misparsed_for_loop_head(
|
||||
&mut e,
|
||||
prev.between(sp),
|
||||
stmt_span,
|
||||
&stmt.kind,
|
||||
);
|
||||
}
|
||||
Err(e) => {
|
||||
@ -534,6 +532,103 @@ impl<'a> Parser<'a> {
|
||||
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(
|
||||
"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,
|
||||
);
|
||||
}
|
||||
(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,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn error_block_no_opening_brace<T>(&mut self) -> PResult<'a, T> {
|
||||
let tok = super::token_descr(&self.token);
|
||||
let msg = format!("expected `{{`, found {tok}");
|
||||
|
@ -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.
|
||||
_ => &[],
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -3292,8 +3292,8 @@ pub const unsafe fn ptr_offset_from_unsigned<T>(_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<T>(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<T>(src: *const T, dst: *mut T, count: usize) {
|
||||
align: usize = align_of::<T>(),
|
||||
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<T>(dst: *mut T, val: u8, count: usize) {
|
||||
addr: *const () = dst as *const (),
|
||||
align: usize = align_of::<T>(),
|
||||
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)
|
||||
}
|
||||
|
@ -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)]
|
||||
|
@ -29,16 +29,18 @@ impl<T: ?Sized> *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<T: ?Sized> *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
|
||||
|
@ -1103,9 +1103,9 @@ pub const unsafe fn swap_nonoverlapping<T>(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<T>(dst: *mut T, src: T) -> T {
|
||||
addr: *const () = dst as *const (),
|
||||
align: usize = align_of::<T>(),
|
||||
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<T>(src: *const T) -> T {
|
||||
addr: *const () = src as *const (),
|
||||
align: usize = align_of::<T>(),
|
||||
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<T>(dst: *mut T, src: T) {
|
||||
addr: *mut () = dst as *mut (),
|
||||
align: usize = align_of::<T>(),
|
||||
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<T>(src: *const T) -> T {
|
||||
addr: *const () = src as *const (),
|
||||
align: usize = align_of::<T>(),
|
||||
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<T>(dst: *mut T, src: T) {
|
||||
addr: *mut () = dst as *mut (),
|
||||
align: usize = align_of::<T>(),
|
||||
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);
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ impl<T: ?Sized> *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<T: ?Sized> *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<T: ?Sized> *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
|
||||
|
@ -132,7 +132,7 @@ pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T]
|
||||
align: usize = align_of::<T>(),
|
||||
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::<T>(),
|
||||
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)
|
||||
|
@ -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,
|
||||
|
@ -1,4 +1,3 @@
|
||||
#![feature(const_ptr_is_null)]
|
||||
use std::ptr;
|
||||
|
||||
const IS_NULL: () = {
|
||||
|
@ -8,7 +8,7 @@ note: inside `std::ptr::const_ptr::<impl *const T>::is_null::compiletime`
|
||||
note: inside `std::ptr::const_ptr::<impl *const i32>::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());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 |
|
||||
|
@ -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 } }
|
||||
| + +
|
||||
|
@ -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; }
|
||||
| + +
|
||||
|
@ -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 {}
|
||||
| + +
|
||||
|
@ -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; }
|
||||
| + +
|
||||
|
@ -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 };
|
||||
| + +
|
||||
|
@ -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! {} };
|
||||
| + +
|
||||
|
@ -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 {} }
|
||||
| + +
|
||||
|
@ -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<i32>,
|
||||
}
|
@ -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<i32>,
|
||||
}
|
@ -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
|
||||
|
@ -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<i32>,
|
||||
}
|
@ -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
|
||||
|
13
tests/ui/parser/unnecessary-let.fixed
Normal file
13
tests/ui/parser/unnecessary-let.fixed
Normal file
@ -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`
|
||||
_ => {}
|
||||
}
|
||||
}
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
|
||||
|
@ -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 {}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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() {}
|
||||
|
@ -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<i32>`, 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`.
|
||||
|
25
tests/ui/rfcs/rfc-2497-if-let-chains/temporary-early-drop.rs
Normal file
25
tests/ui/rfcs/rfc-2497-if-let-chains/temporary-early-drop.rs
Normal file
@ -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<dyn Tr<'a>>);
|
||||
|
||||
trait Tr<'a> {}
|
||||
|
||||
fn f(m: Option<Pd>) {
|
||||
if let Some(n) = m && let it = n.it() {};
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -6,7 +6,7 @@ LL | unsafe //{
|
||||
LL | std::mem::transmute::<f32, u32>(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::<f32, u32>(1.0); }
|
||||
| + +
|
||||
|
Loading…
Reference in New Issue
Block a user