diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index ded03c88a16e9..64c808f2597b3 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -1,10 +1,11 @@ +use rustc_errors::codes::*; use rustc_errors::{Applicability, Diag}; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::LocalDefId; use rustc_hir::{self as hir, ExprKind, HirId, PatKind}; use rustc_hir_pretty::ty_to_string; use rustc_middle::ty::{self, Ty}; -use rustc_span::Span; +use rustc_span::{Span, sym}; use rustc_trait_selection::traits::{ MatchExpressionArmCause, ObligationCause, ObligationCauseCode, }; @@ -291,6 +292,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { error } + /// Check if the span comes from an assert-like macro expansion. + fn is_from_assert_macro(&self, span: Span) -> bool { + span.ctxt().outer_expn_data().macro_def_id.is_some_and(|def_id| { + matches!( + self.tcx.get_diagnostic_name(def_id), + Some( + sym::assert_macro + | sym::debug_assert_macro + | sym::assert_eq_macro + | sym::assert_ne_macro + | sym::debug_assert_eq_macro + | sym::debug_assert_ne_macro + ) + ) + }) + } + /// Explain why `if` expressions without `else` evaluate to `()` and detect likely irrefutable /// `if let PAT = EXPR {}` expressions that could be turned into `let PAT = EXPR;`. fn explain_if_expr( @@ -302,6 +320,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { then_expr: &'tcx hir::Expr<'tcx>, error: &mut bool, ) { + let is_assert_macro = self.is_from_assert_macro(if_span); + if let Some((if_span, msg)) = ret_reason { err.span_label(if_span, msg); } else if let ExprKind::Block(block, _) = then_expr.kind @@ -309,8 +329,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { err.span_label(expr.span, "found here"); } - err.note("`if` expressions without `else` evaluate to `()`"); - err.help("consider adding an `else` block that evaluates to the expected type"); + + if is_assert_macro { + err.code(E0308); + err.primary_message("mismatched types"); + } else { + err.note("`if` expressions without `else` evaluate to `()`"); + err.help("consider adding an `else` block that evaluates to the expected type"); + } *error = true; if let ExprKind::Let(hir::LetExpr { span, pat, init, .. }) = cond_expr.kind && let ExprKind::Block(block, _) = then_expr.kind diff --git a/tests/ui/consts/control-flow/issue-50577.rs b/tests/ui/consts/control-flow/issue-50577.rs index beb9a44fca52d..1cecbadbbe635 100644 --- a/tests/ui/consts/control-flow/issue-50577.rs +++ b/tests/ui/consts/control-flow/issue-50577.rs @@ -1,6 +1,6 @@ fn main() { enum Foo { Drop = assert_eq!(1, 1), - //~^ ERROR `if` may be missing an `else` clause + //~^ ERROR mismatched types [E0308] } } diff --git a/tests/ui/consts/control-flow/issue-50577.stderr b/tests/ui/consts/control-flow/issue-50577.stderr index 1556c6f9c5588..96b11f71bb3e3 100644 --- a/tests/ui/consts/control-flow/issue-50577.stderr +++ b/tests/ui/consts/control-flow/issue-50577.stderr @@ -1,13 +1,11 @@ -error[E0317]: `if` may be missing an `else` clause +error[E0308]: mismatched types --> $DIR/issue-50577.rs:3:16 | LL | Drop = assert_eq!(1, 1), | ^^^^^^^^^^^^^^^^ expected `isize`, found `()` | - = note: `if` expressions without `else` evaluate to `()` - = help: consider adding an `else` block that evaluates to the expected type = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0317`. +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/expr/if/assert-macro-without-else.rs b/tests/ui/expr/if/assert-macro-without-else.rs new file mode 100644 index 0000000000000..a808528ab9e4f --- /dev/null +++ b/tests/ui/expr/if/assert-macro-without-else.rs @@ -0,0 +1,34 @@ +//@ dont-require-annotations: NOTE + +fn f() -> bool { + assert!(1 < 2) + //~^ ERROR mismatched types [E0308] +} + +fn g() -> i32 { + assert_eq!(1, 1) + //~^ ERROR mismatched types [E0308] +} + +fn h() -> bool { + assert_ne!(1, 2) + //~^ ERROR mismatched types [E0308] +} + +// Test nested macros +macro_rules! g { + () => { + f!() + }; +} +macro_rules! f { + () => { + assert!(1 < 2) + //~^ ERROR mismatched types [E0308] + }; +} +fn nested() -> bool { + g!() +} + +fn main() {} diff --git a/tests/ui/expr/if/assert-macro-without-else.stderr b/tests/ui/expr/if/assert-macro-without-else.stderr new file mode 100644 index 0000000000000..74179ba899f5f --- /dev/null +++ b/tests/ui/expr/if/assert-macro-without-else.stderr @@ -0,0 +1,40 @@ +error[E0308]: mismatched types + --> $DIR/assert-macro-without-else.rs:4:5 + | +LL | fn f() -> bool { + | ---- expected `bool` because of this return type +LL | assert!(1 < 2) + | ^^^^^^^^^^^^^^ expected `bool`, found `()` + +error[E0308]: mismatched types + --> $DIR/assert-macro-without-else.rs:9:5 + | +LL | assert_eq!(1, 1) + | ^^^^^^^^^^^^^^^^ expected `i32`, found `()` + | + = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> $DIR/assert-macro-without-else.rs:14:5 + | +LL | assert_ne!(1, 2) + | ^^^^^^^^^^^^^^^^ expected `bool`, found `()` + | + = note: this error originates in the macro `assert_ne` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> $DIR/assert-macro-without-else.rs:26:9 + | +LL | assert!(1 < 2) + | ^^^^^^^^^^^^^^ expected `bool`, found `()` +... +LL | fn nested() -> bool { + | ---- expected `bool` because of this return type +LL | g!() + | ---- in this macro invocation + | + = note: this error originates in the macro `assert` which comes from the expansion of the macro `g` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`.