1
Fork 0

Normalize the arg spans to be within the call span

This commit is contained in:
Michael Goulet 2022-07-20 03:05:14 +00:00
parent 14dbfebfa2
commit cd3204d1a2
3 changed files with 30 additions and 23 deletions

View file

@ -481,6 +481,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.set_tainted_by_errors(); self.set_tainted_by_errors();
let tcx = self.tcx; let tcx = self.tcx;
// Get the argument span in the context of the call span so that
// suggestions and labels are (more) correct when an arg is a
// macro invocation.
let normalize_span = |span: Span| -> Span {
let normalized_span = span.find_ancestor_inside(error_span).unwrap_or(span);
// Sometimes macros mess up the spans, so do not normalize the
// arg span to equal the error span, because that's less useful
// than pointing out the arg expr in the wrong context.
if normalized_span.source_equal(error_span) { span } else { normalized_span }
};
// Precompute the provided types and spans, since that's all we typically need for below // Precompute the provided types and spans, since that's all we typically need for below
let provided_arg_tys: IndexVec<ProvidedIdx, (Ty<'tcx>, Span)> = provided_args let provided_arg_tys: IndexVec<ProvidedIdx, (Ty<'tcx>, Span)> = provided_args
.iter() .iter()
@ -490,7 +501,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.borrow() .borrow()
.expr_ty_adjusted_opt(*expr) .expr_ty_adjusted_opt(*expr)
.unwrap_or_else(|| tcx.ty_error()); .unwrap_or_else(|| tcx.ty_error());
(self.resolve_vars_if_possible(ty), expr.span) (self.resolve_vars_if_possible(ty), normalize_span(expr.span))
}) })
.collect(); .collect();
let callee_expr = match &call_expr.peel_blocks().kind { let callee_expr = match &call_expr.peel_blocks().kind {
@ -600,11 +611,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Take some care with spans, so we don't suggest wrapping a macro's // Take some care with spans, so we don't suggest wrapping a macro's
// innards in parenthesis, for example. // innards in parenthesis, for example.
if satisfied if satisfied
&& let Some(lo) = && let Some((_, lo)) =
provided_args[mismatch_idx.into()].span.find_ancestor_inside(error_span) provided_arg_tys.get(ProvidedIdx::from_usize(mismatch_idx))
&& let Some(hi) = provided_args[(mismatch_idx + tys.len() - 1).into()] && let Some((_, hi)) =
.span provided_arg_tys.get(ProvidedIdx::from_usize(mismatch_idx + tys.len() - 1))
.find_ancestor_inside(error_span)
{ {
let mut err; let mut err;
if tys.len() == 1 { if tys.len() == 1 {
@ -612,7 +622,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// so don't do anything special here. // so don't do anything special here.
err = self.report_and_explain_type_error( err = self.report_and_explain_type_error(
TypeTrace::types( TypeTrace::types(
&self.misc(lo), &self.misc(*lo),
true, true,
formal_and_expected_inputs[mismatch_idx.into()].1, formal_and_expected_inputs[mismatch_idx.into()].1,
provided_arg_tys[mismatch_idx.into()].0, provided_arg_tys[mismatch_idx.into()].0,
@ -1052,7 +1062,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let suggestion_text = if let Some(provided_idx) = provided_idx let suggestion_text = if let Some(provided_idx) = provided_idx
&& let (_, provided_span) = provided_arg_tys[*provided_idx] && let (_, provided_span) = provided_arg_tys[*provided_idx]
&& let Ok(arg_text) = && let Ok(arg_text) =
source_map.span_to_snippet(provided_span.source_callsite()) source_map.span_to_snippet(provided_span)
{ {
arg_text arg_text
} else { } else {

View file

@ -1,5 +1,5 @@
macro_rules! borrow { macro_rules! borrow {
($x:expr) => { &$x } //~ ERROR mismatched types ($x:expr) => { &$x }
} }
fn foo(_: String) {} fn foo(_: String) {}
@ -32,6 +32,7 @@ fn main() {
foo(&mut "aaa".to_owned()); foo(&mut "aaa".to_owned());
//~^ ERROR mismatched types //~^ ERROR mismatched types
foo3(borrow!(0)); foo3(borrow!(0));
//~^ ERROR mismatched types
foo4(&0); foo4(&0);
assert_eq!(3i32, &3i32); assert_eq!(3i32, &3i32);
//~^ ERROR mismatched types //~^ ERROR mismatched types

View file

@ -70,13 +70,10 @@ LL + foo("aaa".to_owned());
| |
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/deref-suggestion.rs:2:20 --> $DIR/deref-suggestion.rs:34:10
| |
LL | ($x:expr) => { &$x }
| ^^^ expected `u32`, found `&{integer}`
...
LL | foo3(borrow!(0)); LL | foo3(borrow!(0));
| ---- ---------- in this macro invocation | ---- ^^^^^^^^^^ expected `u32`, found `&{integer}`
| | | |
| arguments to this function are incorrect | arguments to this function are incorrect
| |
@ -85,10 +82,9 @@ note: function defined here
| |
LL | fn foo3(_: u32) {} LL | fn foo3(_: u32) {}
| ^^^^ ------ | ^^^^ ------
= note: this error originates in the macro `borrow` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/deref-suggestion.rs:36:5 --> $DIR/deref-suggestion.rs:37:5
| |
LL | assert_eq!(3i32, &3i32); LL | assert_eq!(3i32, &3i32);
| ^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `&i32` | ^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `&i32`
@ -96,7 +92,7 @@ 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) = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/deref-suggestion.rs:39:17 --> $DIR/deref-suggestion.rs:40:17
| |
LL | let s = S { u }; LL | let s = S { u };
| ^ | ^
@ -105,7 +101,7 @@ LL | let s = S { u };
| help: consider borrowing here: `u: &u` | help: consider borrowing here: `u: &u`
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/deref-suggestion.rs:41:20 --> $DIR/deref-suggestion.rs:42:20
| |
LL | let s = S { u: u }; LL | let s = S { u: u };
| ^ | ^
@ -114,7 +110,7 @@ LL | let s = S { u: u };
| help: consider borrowing here: `&u` | help: consider borrowing here: `&u`
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/deref-suggestion.rs:44:17 --> $DIR/deref-suggestion.rs:45:17
| |
LL | let r = R { i }; LL | let r = R { i };
| ^ expected `u32`, found `&{integer}` | ^ expected `u32`, found `&{integer}`
@ -125,7 +121,7 @@ LL | let r = R { i: *i };
| ++++ | ++++
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/deref-suggestion.rs:46:20 --> $DIR/deref-suggestion.rs:47:20
| |
LL | let r = R { i: i }; LL | let r = R { i: i };
| ^ expected `u32`, found `&{integer}` | ^ expected `u32`, found `&{integer}`
@ -136,7 +132,7 @@ LL | let r = R { i: *i };
| + | +
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/deref-suggestion.rs:55:9 --> $DIR/deref-suggestion.rs:56:9
| |
LL | b LL | b
| ^ expected `i32`, found `&{integer}` | ^ expected `i32`, found `&{integer}`
@ -147,7 +143,7 @@ LL | *b
| + | +
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/deref-suggestion.rs:63:9 --> $DIR/deref-suggestion.rs:64:9
| |
LL | b LL | b
| ^ expected `i32`, found `&{integer}` | ^ expected `i32`, found `&{integer}`
@ -158,7 +154,7 @@ LL | *b
| + | +
error[E0308]: `if` and `else` have incompatible types error[E0308]: `if` and `else` have incompatible types
--> $DIR/deref-suggestion.rs:68:12 --> $DIR/deref-suggestion.rs:69:12
| |
LL | let val = if true { LL | let val = if true {
| _______________- | _______________-