diff options
| author | Jieyou Xu <jieyouxu@outlook.com> | 2025-09-11 09:00:01 +0800 | 
|---|---|---|
| committer | Jieyou Xu <jieyouxu@outlook.com> | 2025-09-11 09:10:46 +0800 | 
| commit | b38a86f4d7c28ae9ab153b87c7e45037e56306fb (patch) | |
| tree | 4a732b90729f242a458b49d98ec79d96dc186a58 | |
| parent | fc58d8f5cce592998d0ba43b25e445eb6b96c827 (diff) | |
| download | rust-b38a86f4d7c28ae9ab153b87c7e45037e56306fb.tar.gz rust-b38a86f4d7c28ae9ab153b87c7e45037e56306fb.zip | |
Revert "Rollup merge of #122661 - estebank:assert-macro-span, r=petrochenkov"
This reverts commit 1eeb8e8b151d1da7daa73837a25dc5f7a1a7fa28, reversing
changes made to 324bf2b9fd8bf9661e7045c8a93f5ff0ec1a8ca5.
Unfortunately the assert desugaring change is not backwards compatible,
see RUST-145770.
Code such as
```rust
#[derive(Debug)]
struct F {
    data: bool
}
impl std::ops::Not for F {
  type Output = bool;
  fn not(self) -> Self::Output { !self.data }
}
fn main() {
  let f = F { data: true };
  assert!(f);
}
```
would be broken by the assert desugaring change. We may need to land
the change over an edition boundary, or limit the editions that the
desugaring change impacts.
17 files changed, 53 insertions, 150 deletions
| diff --git a/compiler/rustc_builtin_macros/src/assert.rs b/compiler/rustc_builtin_macros/src/assert.rs index 013258a1b4e..855da5caa31 100644 --- a/compiler/rustc_builtin_macros/src/assert.rs +++ b/compiler/rustc_builtin_macros/src/assert.rs @@ -1,8 +1,8 @@ mod context; -use rustc_ast::token::{self, Delimiter}; +use rustc_ast::token::Delimiter; use rustc_ast::tokenstream::{DelimSpan, TokenStream}; -use rustc_ast::{DelimArgs, Expr, ExprKind, MacCall, Path, PathSegment}; +use rustc_ast::{DelimArgs, Expr, ExprKind, MacCall, Path, PathSegment, UnOp, token}; use rustc_ast_pretty::pprust; use rustc_errors::PResult; use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult}; @@ -29,7 +29,7 @@ pub(crate) fn expand_assert<'cx>( // `core::panic` and `std::panic` are different macros, so we use call-site // context to pick up whichever is currently in scope. - let call_site_span = cx.with_call_site_ctxt(cond_expr.span); + let call_site_span = cx.with_call_site_ctxt(span); let panic_path = || { if use_panic_2021(span) { @@ -63,7 +63,7 @@ pub(crate) fn expand_assert<'cx>( }), })), ); - assert_cond_check(cx, call_site_span, cond_expr, then) + expr_if_not(cx, call_site_span, cond_expr, then, None) } // If `generic_assert` is enabled, generates rich captured outputs // @@ -88,33 +88,26 @@ pub(crate) fn expand_assert<'cx>( )), )], ); - assert_cond_check(cx, call_site_span, cond_expr, then) + expr_if_not(cx, call_site_span, cond_expr, then, None) }; ExpandResult::Ready(MacEager::expr(expr)) } -/// `assert!($cond_expr, $custom_message)` struct Assert { cond_expr: Box<Expr>, custom_message: Option<TokenStream>, } -/// `match <cond> { true => {} _ => <then> }` -fn assert_cond_check(cx: &ExtCtxt<'_>, span: Span, cond: Box<Expr>, then: Box<Expr>) -> Box<Expr> { - // Instead of expanding to `if !<cond> { <then> }`, we expand to - // `match <cond> { true => {} _ => <then> }`. - // This allows us to always complain about mismatched types instead of "cannot apply unary - // operator `!` to type `X`" when passing an invalid `<cond>`, while also allowing `<cond>` to - // be `&true`. - let els = cx.expr_block(cx.block(span, thin_vec![])); - let mut arms = thin_vec![]; - arms.push(cx.arm(span, cx.pat_lit(span, cx.expr_bool(span, true)), els)); - arms.push(cx.arm(span, cx.pat_wild(span), then)); - - // We wrap the `match` in a statement to limit the length of any borrows introduced in the - // condition. - cx.expr_block(cx.block(span, [cx.stmt_expr(cx.expr_match(span, cond, arms))].into())) +// if !{ ... } { ... } else { ... } +fn expr_if_not( + cx: &ExtCtxt<'_>, + span: Span, + cond: Box<Expr>, + then: Box<Expr>, + els: Option<Box<Expr>>, +) -> Box<Expr> { + cx.expr_if(span, cx.expr(span, ExprKind::Unary(UnOp::Not, cond)), then, els) } fn parse_assert<'a>(cx: &ExtCtxt<'a>, sp: Span, stream: TokenStream) -> PResult<'a, Assert> { diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index d71110521ff..e18e294635b 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -1618,18 +1618,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { { let e = self.tcx.erase_and_anonymize_regions(e); let f = self.tcx.erase_and_anonymize_regions(f); - let mut expected = with_forced_trimmed_paths!(e.sort_string(self.tcx)); - let mut found = with_forced_trimmed_paths!(f.sort_string(self.tcx)); - if let ObligationCauseCode::Pattern { span, .. } = cause.code() - && let Some(span) = span - && !span.from_expansion() - && cause.span.from_expansion() - { - // When the type error comes from a macro like `assert!()`, and we are pointing at - // code the user wrote the cause and effect are reversed as the expected value is - // what the macro expanded to. - (found, expected) = (expected, found); - } + let expected = with_forced_trimmed_paths!(e.sort_string(self.tcx)); + let found = with_forced_trimmed_paths!(f.sort_string(self.tcx)); if expected == found { label_or_note(span, terr.to_string(self.tcx)); } else { @@ -2152,9 +2142,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ) -> Option<(DiagStyledString, DiagStyledString)> { match values { ValuePairs::Regions(exp_found) => self.expected_found_str(exp_found), - ValuePairs::Terms(exp_found) => { - self.expected_found_str_term(cause, exp_found, long_ty_path) - } + ValuePairs::Terms(exp_found) => self.expected_found_str_term(exp_found, long_ty_path), ValuePairs::Aliases(exp_found) => self.expected_found_str(exp_found), ValuePairs::ExistentialTraitRef(exp_found) => self.expected_found_str(exp_found), ValuePairs::ExistentialProjection(exp_found) => self.expected_found_str(exp_found), @@ -2193,7 +2181,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { fn expected_found_str_term( &self, - cause: &ObligationCause<'tcx>, exp_found: ty::error::ExpectedFound<ty::Term<'tcx>>, long_ty_path: &mut Option<PathBuf>, ) -> Option<(DiagStyledString, DiagStyledString)> { @@ -2201,27 +2188,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if exp_found.references_error() { return None; } - let (mut expected, mut found) = (exp_found.expected, exp_found.found); - - if let ObligationCauseCode::Pattern { span, .. } = cause.code() - && let Some(span) = span - && !span.from_expansion() - && cause.span.from_expansion() - { - // When the type error comes from a macro like `assert!()`, and we are pointing at - // code the user wrote, the cause and effect are reversed as the expected value is - // what the macro expanded to. So if the user provided a `Type` when the macro is - // written in such a way that a `bool` was expected, we want to print: - // = note: expected `bool` - // found `Type`" - // but as far as the compiler is concerned, after expansion what was expected was `Type` - // = note: expected `Type` - // found `bool`" - // so we reverse them here to match user expectation. - (expected, found) = (found, expected); - } - Some(match (expected.kind(), found.kind()) { + Some(match (exp_found.expected.kind(), exp_found.found.kind()) { (ty::TermKind::Ty(expected), ty::TermKind::Ty(found)) => { let (mut exp, mut fnd) = self.cmp(expected, found); // Use the terminal width as the basis to determine when to compress the printed diff --git a/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs b/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs index 788a04357b1..cf0c85990b1 100644 --- a/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs +++ b/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs @@ -11,7 +11,7 @@ use rustc_ast::{BinOpKind, LitKind, RangeLimits}; use rustc_data_structures::packed::Pu128; use rustc_data_structures::unhash::UnindexMap; use rustc_errors::{Applicability, Diag}; -use rustc_hir::{Body, Expr, ExprKind}; +use rustc_hir::{Block, Body, Expr, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; use rustc_span::source_map::Spanned; @@ -135,12 +135,12 @@ fn assert_len_expr<'hir>( cx: &LateContext<'_>, expr: &'hir Expr<'hir>, ) -> Option<(LengthComparison, usize, &'hir Expr<'hir>)> { - let (cmp, asserted_len, slice_len) = if let Some( - higher::IfLetOrMatch::Match(cond, [_, then], _) - ) = higher::IfLetOrMatch::parse(cx, expr) - && let ExprKind::Binary(bin_op, left, right) = &cond.kind + let (cmp, asserted_len, slice_len) = if let Some(higher::If { cond, then, .. }) = higher::If::hir(expr) + && let ExprKind::Unary(UnOp::Not, condition) = &cond.kind + && let ExprKind::Binary(bin_op, left, right) = &condition.kind // check if `then` block has a never type expression - && cx.typeck_results().expr_ty(then.body).is_never() + && let ExprKind::Block(Block { expr: Some(then_expr), .. }, _) = then.kind + && cx.typeck_results().expr_ty(then_expr).is_never() { len_comparison(bin_op.node, left, right)? } else if let Some((macro_call, bin_op)) = first_node_macro_backtrace(cx, expr).find_map(|macro_call| { diff --git a/src/tools/clippy/tests/ui/const_is_empty.rs b/src/tools/clippy/tests/ui/const_is_empty.rs index 63c6342a323..8bb4f0e5d97 100644 --- a/src/tools/clippy/tests/ui/const_is_empty.rs +++ b/src/tools/clippy/tests/ui/const_is_empty.rs @@ -196,7 +196,6 @@ fn issue_13106() { const { assert!(EMPTY_STR.is_empty()); - //~^ const_is_empty } const { diff --git a/src/tools/clippy/tests/ui/const_is_empty.stderr b/src/tools/clippy/tests/ui/const_is_empty.stderr index 9a42518698e..2ba189058e8 100644 --- a/src/tools/clippy/tests/ui/const_is_empty.stderr +++ b/src/tools/clippy/tests/ui/const_is_empty.stderr @@ -158,16 +158,10 @@ LL | let _ = val.is_empty(); | ^^^^^^^^^^^^^^ error: this expression always evaluates to true - --> tests/ui/const_is_empty.rs:198:17 - | -LL | assert!(EMPTY_STR.is_empty()); - | ^^^^^^^^^^^^^^^^^^^^ - -error: this expression always evaluates to true - --> tests/ui/const_is_empty.rs:203:9 + --> tests/ui/const_is_empty.rs:202:9 | LL | EMPTY_STR.is_empty(); | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 28 previous errors +error: aborting due to 27 previous errors diff --git a/src/tools/clippy/tests/ui/incompatible_msrv.rs b/src/tools/clippy/tests/ui/incompatible_msrv.rs index 882f909e30c..f7f21e1850d 100644 --- a/src/tools/clippy/tests/ui/incompatible_msrv.rs +++ b/src/tools/clippy/tests/ui/incompatible_msrv.rs @@ -1,6 +1,6 @@ #![warn(clippy::incompatible_msrv)] #![feature(custom_inner_attributes)] -#![allow(stable_features, clippy::diverging_sub_expression)] +#![allow(stable_features)] #![feature(strict_provenance)] // For use in test #![clippy::msrv = "1.3.0"] diff --git a/tests/ui/codemap_tests/issue-28308.rs b/tests/ui/codemap_tests/issue-28308.rs index b0e04d0f1f6..81493f8c453 100644 --- a/tests/ui/codemap_tests/issue-28308.rs +++ b/tests/ui/codemap_tests/issue-28308.rs @@ -1,16 +1,4 @@ fn main() { - assert!("foo"); //~ ERROR mismatched types - //~^ NOTE expected `bool`, found `str` - //~| NOTE in this expansion of assert! - let x = Some(&1); - assert!(x); //~ ERROR mismatched types - //~^ NOTE expected `bool`, found `Option<&{integer}>` - //~| NOTE expected enum `bool` - //~| NOTE in this expansion of assert! - //~| NOTE in this expansion of assert! - assert!(x, ""); //~ ERROR mismatched types - //~^ NOTE expected `bool`, found `Option<&{integer}>` - //~| NOTE expected enum `bool` - //~| NOTE in this expansion of assert! - //~| NOTE in this expansion of assert! + assert!("foo"); + //~^ ERROR cannot apply unary operator `!` } diff --git a/tests/ui/codemap_tests/issue-28308.stderr b/tests/ui/codemap_tests/issue-28308.stderr index e84ceb44aac..7bc9e05dfc0 100644 --- a/tests/ui/codemap_tests/issue-28308.stderr +++ b/tests/ui/codemap_tests/issue-28308.stderr @@ -1,27 +1,9 @@ -error[E0308]: mismatched types - --> $DIR/issue-28308.rs:2:13 +error[E0600]: cannot apply unary operator `!` to type `&'static str` + --> $DIR/issue-28308.rs:2:5 | LL | assert!("foo"); - | ^^^^^ expected `bool`, found `str` + | ^^^^^^^^^^^^^^ cannot apply unary operator `!` -error[E0308]: mismatched types - --> $DIR/issue-28308.rs:6:13 - | -LL | assert!(x); - | ^ expected `bool`, found `Option<&{integer}>` - | - = note: expected enum `bool` - found type `Option<&{integer}>` - -error[E0308]: mismatched types - --> $DIR/issue-28308.rs:11:13 - | -LL | assert!(x, ""); - | ^ expected `bool`, found `Option<&{integer}>` - | - = note: expected enum `bool` - found type `Option<&{integer}>` - -error: aborting due to 3 previous errors +error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0600`. diff --git a/tests/ui/consts/control-flow/assert.stderr b/tests/ui/consts/control-flow/assert.stderr index deaad6abbcc..026097a6ba0 100644 --- a/tests/ui/consts/control-flow/assert.stderr +++ b/tests/ui/consts/control-flow/assert.stderr @@ -1,8 +1,8 @@ error[E0080]: evaluation panicked: assertion failed: false - --> $DIR/assert.rs:5:23 + --> $DIR/assert.rs:5:15 | LL | const _: () = assert!(false); - | ^^^^^ evaluation of `_` failed here + | ^^^^^^^^^^^^^^ evaluation of `_` failed here error: aborting due to 1 previous error diff --git a/tests/ui/generics/post_monomorphization_error_backtrace.stderr b/tests/ui/generics/post_monomorphization_error_backtrace.stderr index 92c7df73638..6953414f0c2 100644 --- a/tests/ui/generics/post_monomorphization_error_backtrace.stderr +++ b/tests/ui/generics/post_monomorphization_error_backtrace.stderr @@ -1,8 +1,8 @@ error[E0080]: evaluation panicked: assertion failed: std::mem::size_of::<T>() == 0 - --> $DIR/post_monomorphization_error_backtrace.rs:6:31 + --> $DIR/post_monomorphization_error_backtrace.rs:6:23 | LL | const V: () = assert!(std::mem::size_of::<T>() == 0); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `assert_zst::F::<u32>::V` failed here + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `assert_zst::F::<u32>::V` failed here note: erroneous constant encountered --> $DIR/post_monomorphization_error_backtrace.rs:14:5 @@ -17,10 +17,10 @@ LL | assert_zst::<U>() | ^^^^^^^^^^^^^^^^^ error[E0080]: evaluation panicked: assertion failed: std::mem::size_of::<T>() == 0 - --> $DIR/post_monomorphization_error_backtrace.rs:6:31 + --> $DIR/post_monomorphization_error_backtrace.rs:6:23 | LL | const V: () = assert!(std::mem::size_of::<T>() == 0); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `assert_zst::F::<i32>::V` failed here + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `assert_zst::F::<i32>::V` failed here note: erroneous constant encountered --> $DIR/post_monomorphization_error_backtrace.rs:14:5 diff --git a/tests/ui/inline-const/const-expr-generic-err.stderr b/tests/ui/inline-const/const-expr-generic-err.stderr index e053e88db17..26039ba6d44 100644 --- a/tests/ui/inline-const/const-expr-generic-err.stderr +++ b/tests/ui/inline-const/const-expr-generic-err.stderr @@ -1,8 +1,8 @@ error[E0080]: evaluation panicked: assertion failed: std::mem::size_of::<T>() == 0 - --> $DIR/const-expr-generic-err.rs:4:21 + --> $DIR/const-expr-generic-err.rs:4:13 | LL | const { assert!(std::mem::size_of::<T>() == 0); } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `foo::<i32>::{constant#0}` failed here + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `foo::<i32>::{constant#0}` failed here note: erroneous constant encountered --> $DIR/const-expr-generic-err.rs:4:5 diff --git a/tests/ui/macros/assert-desugaring-145770.rs b/tests/ui/macros/assert-desugaring-145770.rs index 9eb850f0380..d56e771ecfb 100644 --- a/tests/ui/macros/assert-desugaring-145770.rs +++ b/tests/ui/macros/assert-desugaring-145770.rs @@ -4,6 +4,8 @@ //! backwards-incompatible, and may need to be done over an edition boundary or limit editions for //! which the desguaring change impacts. +//@ check-pass + #[derive(Debug)] struct F { data: bool @@ -18,5 +20,4 @@ fn main() { let f = F { data: true }; assert!(f); - //~^ ERROR mismatched types } diff --git a/tests/ui/macros/assert-desugaring-145770.stderr b/tests/ui/macros/assert-desugaring-145770.stderr deleted file mode 100644 index 875ea8f7c32..00000000000 --- a/tests/ui/macros/assert-desugaring-145770.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/assert-desugaring-145770.rs:20:11 - | -LL | assert!(f); - | ^ expected `bool`, found `F` - | -help: you might have meant to use field `data` whose type is `bool` - | -LL | assert!(f.data); - | +++++ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/macros/assert-macro-lifetimes.rs b/tests/ui/macros/assert-macro-lifetimes.rs deleted file mode 100644 index cc259283204..00000000000 --- a/tests/ui/macros/assert-macro-lifetimes.rs +++ /dev/null @@ -1,8 +0,0 @@ -//@ check-pass -#[derive(PartialEq, Eq, Hash)] -struct S; -fn main() { - let foo = std::rc::Rc::new(std::cell::RefCell::new(std::collections::HashMap::<S, S>::new())); - // Ensure that the lifetimes of the borrow do not leak past the end of `main`. - assert!(matches!(foo.borrow().get(&S).unwrap(), S)) -} diff --git a/tests/ui/mir/alignment/packed.rs b/tests/ui/mir/alignment/packed.rs index aa79880a21a..cf908365e1a 100644 --- a/tests/ui/mir/alignment/packed.rs +++ b/tests/ui/mir/alignment/packed.rs @@ -12,7 +12,7 @@ fn main() { // Test that we can use addr_of! to get the address of a packed member which according to its // type is not aligned, but because it is a projection from a packed type is a valid place. let ptr0 = std::ptr::addr_of!(memory[0].tail); - let ptr1 = std::ptr::addr_of!(memory[1].tail); + let ptr1 = std::ptr::addr_of!(memory[0].tail); // Even if ptr0 happens to be aligned by chance, ptr1 is not. assert!(!ptr0.is_aligned() || !ptr1.is_aligned()); diff --git a/tests/ui/simd/const-err-trumps-simd-err.stderr b/tests/ui/simd/const-err-trumps-simd-err.stderr index 6d25a28c92c..93d1fce637f 100644 --- a/tests/ui/simd/const-err-trumps-simd-err.stderr +++ b/tests/ui/simd/const-err-trumps-simd-err.stderr @@ -1,8 +1,8 @@ error[E0080]: evaluation panicked: assertion failed: LANE < 4 - --> $DIR/const-err-trumps-simd-err.rs:17:21 + --> $DIR/const-err-trumps-simd-err.rs:17:13 | LL | const { assert!(LANE < 4); } // the error should be here... - | ^^^^^^^^ evaluation of `get_elem::<4>::{constant#0}` failed here + | ^^^^^^^^^^^^^^^^^ evaluation of `get_elem::<4>::{constant#0}` failed here note: erroneous constant encountered --> $DIR/const-err-trumps-simd-err.rs:17:5 diff --git a/tests/ui/transmutability/uninhabited.stderr b/tests/ui/transmutability/uninhabited.stderr index 9f289852809..4757daec997 100644 --- a/tests/ui/transmutability/uninhabited.stderr +++ b/tests/ui/transmutability/uninhabited.stderr @@ -41,10 +41,10 @@ LL | | }> | |__________^ required by this bound in `is_maybe_transmutable` error[E0080]: evaluation panicked: assertion failed: false - --> $DIR/uninhabited.rs:41:17 + --> $DIR/uninhabited.rs:41:9 | LL | assert!(false); - | ^^^^^ evaluation of `yawning_void_struct::_` failed here + | ^^^^^^^^^^^^^^ evaluation of `yawning_void_struct::_` failed here error[E0277]: `()` cannot be safely transmuted into `yawning_void_enum::Void` --> $DIR/uninhabited.rs:71:41 @@ -68,10 +68,10 @@ LL | | }> | |__________^ required by this bound in `is_maybe_transmutable` error[E0080]: evaluation panicked: assertion failed: false - --> $DIR/uninhabited.rs:63:17 + --> $DIR/uninhabited.rs:63:9 | LL | assert!(false); - | ^^^^^ evaluation of `yawning_void_enum::_` failed here + | ^^^^^^^^^^^^^^ evaluation of `yawning_void_enum::_` failed here error[E0277]: `u128` cannot be safely transmuted into `DistantVoid` --> $DIR/uninhabited.rs:92:43 @@ -95,10 +95,10 @@ LL | | }> | |__________^ required by this bound in `is_maybe_transmutable` error[E0080]: evaluation panicked: assertion failed: false - --> $DIR/uninhabited.rs:87:17 + --> $DIR/uninhabited.rs:87:9 | LL | assert!(false); - | ^^^^^ evaluation of `distant_void::_` failed here + | ^^^^^^^^^^^^^^ evaluation of `distant_void::_` failed here error[E0277]: `Src` cannot be safely transmuted into `issue_126267::Error` --> $DIR/uninhabited.rs:108:42 | 
