Point at correct exprs for assert_eq type mismatch

This commit is contained in:
Michael Goulet 2023-05-30 19:48:35 +00:00
parent af54d584b2
commit acf257e62c
3 changed files with 69 additions and 16 deletions

View File

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

View File

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

View File

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