Skip to content

Commit f361413

Browse files
committed
Auto merge of #106399 - estebank:type-err-span-label, r=nagisa
Modify primary span label for E0308 Looking at the reactions to https://hachyderm.io/`@ekuber/109622160673605438,` a lot of people seem to have trouble understanding the current output, where the primary span label on type errors talks about the specific types that diverged, but these can be deeply nested type parameters. Because of that we could see "expected i32, found u32" in the label while the note said "expected Vec<i32>, found Vec<u32>". This understandably confuses people. I believe that once people learn to read these errors it starts to make more sense, but this PR changes the output to be more in line with what people might expect, without sacrificing terseness. Fix #68220.
2 parents a64ef7d + 449dfc6 commit f361413

File tree

428 files changed

+1110
-1053
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

428 files changed

+1110
-1053
lines changed

compiler/rustc_hir_analysis/src/check/check.rs

+1
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,7 @@ fn check_opaque_meets_bounds<'tcx>(
442442
match ocx.eq(&misc_cause, param_env, opaque_ty, hidden_ty) {
443443
Ok(()) => {}
444444
Err(ty_err) => {
445+
let ty_err = ty_err.to_string(tcx);
445446
tcx.sess.delay_span_bug(
446447
span,
447448
&format!("could not unify `{hidden_ty}` with revealed type:\n{ty_err}"),

compiler/rustc_hir_typeck/src/method/suggest.rs

+29-7
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
259259
let mode = no_match_data.mode;
260260
let tcx = self.tcx;
261261
let rcvr_ty = self.resolve_vars_if_possible(rcvr_ty);
262-
let ty_str = with_forced_trimmed_paths!(self.ty_to_string(rcvr_ty));
262+
let (ty_str, ty_file) = tcx.short_ty_string(rcvr_ty);
263+
let short_ty_str = with_forced_trimmed_paths!(rcvr_ty.to_string());
263264
let is_method = mode == Mode::MethodCall;
264265
let unsatisfied_predicates = &no_match_data.unsatisfied_predicates;
265266
let similar_candidate = no_match_data.similar_candidate;
@@ -276,11 +277,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
276277
}
277278
};
278279

279-
if self.suggest_wrapping_range_with_parens(tcx, rcvr_ty, source, span, item_name, &ty_str)
280-
|| self.suggest_constraining_numerical_ty(
281-
tcx, rcvr_ty, source, span, item_kind, item_name, &ty_str,
282-
)
283-
{
280+
// We could pass the file for long types into these two, but it isn't strictly necessary
281+
// given how targetted they are.
282+
if self.suggest_wrapping_range_with_parens(
283+
tcx,
284+
rcvr_ty,
285+
source,
286+
span,
287+
item_name,
288+
&short_ty_str,
289+
) || self.suggest_constraining_numerical_ty(
290+
tcx,
291+
rcvr_ty,
292+
source,
293+
span,
294+
item_kind,
295+
item_name,
296+
&short_ty_str,
297+
) {
284298
return None;
285299
}
286300
span = item_name.span;
@@ -319,6 +333,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
319333
rcvr_ty.prefix_string(self.tcx),
320334
ty_str_reported,
321335
);
336+
let ty_str = if short_ty_str.len() < ty_str.len() && ty_str.len() > 10 {
337+
short_ty_str
338+
} else {
339+
ty_str
340+
};
341+
if let Some(file) = ty_file {
342+
err.note(&format!("the full type name has been written to '{}'", file.display(),));
343+
}
322344
if rcvr_ty.references_error() {
323345
err.downgrade_to_delayed_bug();
324346
}
@@ -826,7 +848,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
826848
let primary_message = primary_message.unwrap_or_else(|| {
827849
format!(
828850
"the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, \
829-
but its trait bounds were not satisfied"
851+
but its trait bounds were not satisfied"
830852
)
831853
});
832854
err.set_primary_message(&primary_message);

compiler/rustc_infer/src/infer/error_reporting/mod.rs

+31-3
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
6767
use rustc_hir::lang_items::LangItem;
6868
use rustc_hir::Node;
6969
use rustc_middle::dep_graph::DepContext;
70+
use rustc_middle::ty::print::with_forced_trimmed_paths;
7071
use rustc_middle::ty::relate::{self, RelateResult, TypeRelation};
7172
use rustc_middle::ty::{
7273
self, error::TypeError, List, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
@@ -1612,16 +1613,31 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
16121613
{
16131614
format!("expected this to be `{}`", expected)
16141615
} else {
1615-
terr.to_string()
1616+
terr.to_string(self.tcx).to_string()
16161617
};
16171618
label_or_note(sp, &terr);
16181619
label_or_note(span, &msg);
16191620
} else {
1620-
label_or_note(span, &terr.to_string());
1621+
label_or_note(span, &terr.to_string(self.tcx));
16211622
label_or_note(sp, &msg);
16221623
}
16231624
} else {
1624-
label_or_note(span, &terr.to_string());
1625+
if let Some(values) = values
1626+
&& let Some((e, f)) = values.ty()
1627+
&& let TypeError::ArgumentSorts(..) | TypeError::Sorts(_) = terr
1628+
{
1629+
let e = self.tcx.erase_regions(e);
1630+
let f = self.tcx.erase_regions(f);
1631+
let expected = with_forced_trimmed_paths!(e.sort_string(self.tcx));
1632+
let found = with_forced_trimmed_paths!(f.sort_string(self.tcx));
1633+
if expected == found {
1634+
label_or_note(span, &terr.to_string(self.tcx));
1635+
} else {
1636+
label_or_note(span, &format!("expected {expected}, found {found}"));
1637+
}
1638+
} else {
1639+
label_or_note(span, &terr.to_string(self.tcx));
1640+
}
16251641
}
16261642

16271643
if let Some((expected, found, exp_p, found_p)) = expected_found {
@@ -1849,6 +1865,18 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
18491865
self.check_and_note_conflicting_crates(diag, terr);
18501866

18511867
self.note_and_explain_type_err(diag, terr, cause, span, cause.body_id.to_def_id());
1868+
if let Some(exp_found) = exp_found
1869+
&& let exp_found = TypeError::Sorts(exp_found)
1870+
&& exp_found != terr
1871+
{
1872+
self.note_and_explain_type_err(
1873+
diag,
1874+
exp_found,
1875+
cause,
1876+
span,
1877+
cause.body_id.to_def_id(),
1878+
);
1879+
}
18521880

18531881
if let Some(ValuePairs::PolyTraitRefs(exp_found)) = values
18541882
&& let ty::Closure(def_id, _) = exp_found.expected.skip_binder().self_ty().kind()

compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs

+13-6
Original file line numberDiff line numberDiff line change
@@ -137,25 +137,25 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
137137
diag.help(
138138
"given a type parameter `T` and a method `foo`:
139139
```
140-
trait Trait<T> { fn foo(&tcx) -> T; }
140+
trait Trait<T> { fn foo(&self) -> T; }
141141
```
142142
the only ways to implement method `foo` are:
143143
- constrain `T` with an explicit type:
144144
```
145145
impl Trait<String> for X {
146-
fn foo(&tcx) -> String { String::new() }
146+
fn foo(&self) -> String { String::new() }
147147
}
148148
```
149149
- add a trait bound to `T` and call a method on that trait that returns `Self`:
150150
```
151151
impl<T: std::default::Default> Trait<T> for X {
152-
fn foo(&tcx) -> T { <T as std::default::Default>::default() }
152+
fn foo(&self) -> T { <T as std::default::Default>::default() }
153153
}
154154
```
155155
- change `foo` to return an argument of type `T`:
156156
```
157157
impl<T> Trait<T> for X {
158-
fn foo(&tcx, x: T) -> T { x }
158+
fn foo(&self, x: T) -> T { x }
159159
}
160160
```",
161161
);
@@ -218,6 +218,13 @@ impl<T> Trait<T> for X {
218218
);
219219
}
220220
}
221+
(ty::FnPtr(_), ty::FnDef(def, _))
222+
if let hir::def::DefKind::Fn = tcx.def_kind(def) => {
223+
diag.note(
224+
"when the arguments and return types match, functions can be coerced \
225+
to function pointers",
226+
);
227+
}
221228
_ => {}
222229
}
223230
debug!(
@@ -389,14 +396,14 @@ impl<T> Trait<T> for X {
389396
```
390397
trait Trait {
391398
type T;
392-
fn foo(&tcx) -> Self::T;
399+
fn foo(&self) -> Self::T;
393400
}
394401
```
395402
the only way of implementing method `foo` is to constrain `T` with an explicit associated type:
396403
```
397404
impl Trait for X {
398405
type T = String;
399-
fn foo(&tcx) -> Self::T { String::new() }
406+
fn foo(&self) -> Self::T { String::new() }
400407
}
401408
```",
402409
);

compiler/rustc_infer/src/infer/error_reporting/suggest.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
404404
(msg, sug)
405405
}
406406
};
407-
diag.span_suggestion(span, msg, sug, Applicability::MaybeIncorrect);
407+
diag.span_suggestion_verbose(span, msg, sug, Applicability::MaybeIncorrect);
408408
}
409409
(ty::FnDef(did1, substs1), ty::FnDef(did2, substs2)) => {
410410
let expected_sig =

0 commit comments

Comments
 (0)