Skip to content

Commit

Permalink
Auto merge of #133135 - jieyouxu:rollup-4q1wbyq, r=jieyouxu
Browse files Browse the repository at this point in the history
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
  • Loading branch information
bors committed Nov 17, 2024
2 parents 23e7ecb + defc866 commit a8e75c5
Show file tree
Hide file tree
Showing 41 changed files with 602 additions and 111 deletions.
6 changes: 6 additions & 0 deletions compiler/rustc_const_eval/src/const_eval/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
4 changes: 1 addition & 3 deletions compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_parse/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
11 changes: 10 additions & 1 deletion compiler/rustc_parse/src/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
//
Expand All @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_parse/src/parser/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
109 changes: 102 additions & 7 deletions compiler/rustc_parse/src/parser/stmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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()),
Expand All @@ -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<T>(&mut self) -> PResult<'a, T> {
Expand Down
37 changes: 23 additions & 14 deletions compiler/rustc_target/src/target_features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)] {
Expand All @@ -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.
_ => &[],
}
}

Expand Down
2 changes: 1 addition & 1 deletion library/alloc/src/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
16 changes: 8 additions & 8 deletions library/core/src/intrinsics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down Expand Up @@ -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)
}
);

Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -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)
}
Expand Down
3 changes: 1 addition & 2 deletions library/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand All @@ -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)]
Expand All @@ -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)]
Expand Down
8 changes: 5 additions & 3 deletions library/core/src/ptr/const_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
Loading

0 comments on commit a8e75c5

Please sign in to comment.