Point at correct exprs for assert_eq type mismatch
This commit is contained in:
parent
af54d584b2
commit
acf257e62c
@ -3,7 +3,7 @@
|
||||
use rustc_errors::MultiSpan;
|
||||
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::CtorKind;
|
||||
use rustc_hir::def::{CtorKind, Res};
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::{is_range_literal, Node};
|
||||
@ -91,6 +91,56 @@ pub fn emit_coerce_suggestions(
|
||||
self.note_wrong_return_ty_due_to_generic_arg(err, expr, expr_ty);
|
||||
}
|
||||
|
||||
/// Really hacky heuristic to remap an `assert_eq!` error to the user
|
||||
/// expressions provided to the macro.
|
||||
fn adjust_expr_for_assert_eq_macro(
|
||||
&self,
|
||||
found_expr: &mut &'tcx hir::Expr<'tcx>,
|
||||
expected_expr: &mut Option<&'tcx hir::Expr<'tcx>>,
|
||||
) {
|
||||
let Some(expected_expr) = expected_expr else { return; };
|
||||
|
||||
if !found_expr.span.eq_ctxt(expected_expr.span) {
|
||||
return;
|
||||
}
|
||||
|
||||
if !found_expr
|
||||
.span
|
||||
.ctxt()
|
||||
.outer_expn_data()
|
||||
.macro_def_id
|
||||
.is_some_and(|def_id| self.tcx.is_diagnostic_item(sym::assert_eq_macro, def_id))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
let hir::ExprKind::Unary(
|
||||
hir::UnOp::Deref,
|
||||
hir::Expr { kind: hir::ExprKind::Path(found_path), .. },
|
||||
) = found_expr.kind else { return; };
|
||||
let hir::ExprKind::Unary(
|
||||
hir::UnOp::Deref,
|
||||
hir::Expr { kind: hir::ExprKind::Path(expected_path), .. },
|
||||
) = expected_expr.kind else { return; };
|
||||
|
||||
for (path, name, idx, var) in [
|
||||
(expected_path, "left_val", 0, expected_expr),
|
||||
(found_path, "right_val", 1, found_expr),
|
||||
] {
|
||||
if let hir::QPath::Resolved(_, path) = path
|
||||
&& let [segment] = path.segments
|
||||
&& segment.ident.name.as_str() == name
|
||||
&& let Res::Local(hir_id) = path.res
|
||||
&& let Some((_, hir::Node::Expr(match_expr))) = self.tcx.hir().parent_iter(hir_id).nth(2)
|
||||
&& let hir::ExprKind::Match(scrutinee, _, _) = match_expr.kind
|
||||
&& let hir::ExprKind::Tup(exprs) = scrutinee.kind
|
||||
&& let hir::ExprKind::AddrOf(_, _, macro_arg) = exprs[idx].kind
|
||||
{
|
||||
*var = macro_arg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Requires that the two types unify, and prints an error message if
|
||||
/// they don't.
|
||||
pub fn demand_suptype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) {
|
||||
@ -156,7 +206,7 @@ pub fn demand_eqtype_with_origin(
|
||||
|
||||
pub fn demand_coerce(
|
||||
&self,
|
||||
expr: &hir::Expr<'tcx>,
|
||||
expr: &'tcx hir::Expr<'tcx>,
|
||||
checked_ty: Ty<'tcx>,
|
||||
expected: Ty<'tcx>,
|
||||
expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
|
||||
@ -177,10 +227,10 @@ pub fn demand_coerce(
|
||||
#[instrument(level = "debug", skip(self, expr, expected_ty_expr, allow_two_phase))]
|
||||
pub fn demand_coerce_diag(
|
||||
&self,
|
||||
expr: &hir::Expr<'tcx>,
|
||||
mut expr: &'tcx hir::Expr<'tcx>,
|
||||
checked_ty: Ty<'tcx>,
|
||||
expected: Ty<'tcx>,
|
||||
expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
|
||||
mut expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
|
||||
allow_two_phase: AllowTwoPhase,
|
||||
) -> (Ty<'tcx>, Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>>) {
|
||||
let expected = self.resolve_vars_with_obligations(expected);
|
||||
@ -190,6 +240,8 @@ pub fn demand_coerce_diag(
|
||||
Err(e) => e,
|
||||
};
|
||||
|
||||
self.adjust_expr_for_assert_eq_macro(&mut expr, &mut expected_ty_expr);
|
||||
|
||||
self.set_tainted_by_errors(self.tcx.sess.delay_span_bug(
|
||||
expr.span,
|
||||
"`TypeError` when attempting coercion but no error emitted",
|
||||
|
@ -84,15 +84,16 @@ LL | fn foo3(_: u32) {}
|
||||
| ^^^^ ------
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/deref-suggestion.rs:37:5
|
||||
--> $DIR/deref-suggestion.rs:37:22
|
||||
|
|
||||
LL | assert_eq!(3i32, &3i32);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| expected `i32`, found `&i32`
|
||||
| expected because this is `i32`
|
||||
| ^^^^^ expected `i32`, found `&i32`
|
||||
|
|
||||
help: consider removing the borrow
|
||||
|
|
||||
LL - assert_eq!(3i32, &3i32);
|
||||
LL + assert_eq!(3i32, 3i32);
|
||||
|
|
||||
= 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/deref-suggestion.rs:40:17
|
||||
|
@ -1,13 +1,13 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/dont-suggest-try_into-in-macros.rs:2:5
|
||||
--> $DIR/dont-suggest-try_into-in-macros.rs:2:23
|
||||
|
|
||||
LL | assert_eq!(10u64, 10usize);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| expected `u64`, found `usize`
|
||||
| expected because this is `u64`
|
||||
| ^^^^^^^ expected `u64`, found `usize`
|
||||
|
|
||||
= note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
help: change the type of the numeric literal from `usize` to `u64`
|
||||
|
|
||||
LL | assert_eq!(10u64, 10u64);
|
||||
| ~~~
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user