Improve error message for assert!() macro in functions returning bool

This commit is contained in:
enthropy7 2026-01-21 23:30:04 +03:00
parent 625b63f9e1
commit 95b58ac6ac
No known key found for this signature in database
5 changed files with 106 additions and 8 deletions

View file

@ -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

View file

@ -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]
}
}

View file

@ -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`.

View file

@ -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() {}

View file

@ -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`.