Skip to content

Commit 229d0a9

Browse files
committed
Auto merge of #91769 - estebank:type-trait-bound-span-2, r=oli-obk
Tweak assoc type obligation spans * Point at RHS of associated type in obligation span * Point at `impl` assoc type on projection error * Reduce verbosity of recursive obligations * Point at source of binding lifetime obligation * Tweak "required bound" note * Tweak "expected... found opaque (return) type" labels * Point at set type in impl assoc type WF errors r? `@oli-obk` This is a(n uncontroversial) subset of #85799.
2 parents 928783d + 5e1972e commit 229d0a9

File tree

92 files changed

+503
-257
lines changed

Some content is hidden

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

92 files changed

+503
-257
lines changed

Diff for: compiler/rustc_infer/src/infer/error_reporting/mod.rs

+36-3
Original file line numberDiff line numberDiff line change
@@ -1430,13 +1430,23 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
14301430
}
14311431
}
14321432

1433+
/// Extend a type error with extra labels pointing at "non-trivial" types, like closures and
1434+
/// the return type of `async fn`s.
1435+
///
1436+
/// `secondary_span` gives the caller the opportunity to expand `diag` with a `span_label`.
1437+
///
1438+
/// `swap_secondary_and_primary` is used to make projection errors in particular nicer by using
1439+
/// the message in `secondary_span` as the primary label, and apply the message that would
1440+
/// otherwise be used for the primary label on the `secondary_span` `Span`. This applies on
1441+
/// E0271, like `src/test/ui/issues/issue-39970.stderr`.
14331442
pub fn note_type_err(
14341443
&self,
14351444
diag: &mut DiagnosticBuilder<'tcx>,
14361445
cause: &ObligationCause<'tcx>,
14371446
secondary_span: Option<(Span, String)>,
14381447
mut values: Option<ValuePairs<'tcx>>,
14391448
terr: &TypeError<'tcx>,
1449+
swap_secondary_and_primary: bool,
14401450
) {
14411451
let span = cause.span(self.tcx);
14421452
debug!("note_type_err cause={:?} values={:?}, terr={:?}", cause, values, terr);
@@ -1613,9 +1623,32 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
16131623
match terr {
16141624
TypeError::ObjectUnsafeCoercion(_) => {}
16151625
_ => {
1616-
diag.span_label(span, terr.to_string());
1626+
let mut label_or_note = |span: Span, msg: &str| {
1627+
if &[span] == diag.span.primary_spans() {
1628+
diag.span_label(span, msg);
1629+
} else {
1630+
diag.span_note(span, msg);
1631+
}
1632+
};
16171633
if let Some((sp, msg)) = secondary_span {
1618-
diag.span_label(sp, msg);
1634+
if swap_secondary_and_primary {
1635+
let terr = if let Some(infer::ValuePairs::Types(infer::ExpectedFound {
1636+
expected,
1637+
..
1638+
})) = values
1639+
{
1640+
format!("expected this to be `{}`", expected)
1641+
} else {
1642+
terr.to_string()
1643+
};
1644+
label_or_note(sp, &terr);
1645+
label_or_note(span, &msg);
1646+
} else {
1647+
label_or_note(span, &terr.to_string());
1648+
label_or_note(sp, &msg);
1649+
}
1650+
} else {
1651+
label_or_note(span, &terr.to_string());
16191652
}
16201653
}
16211654
};
@@ -2049,7 +2082,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
20492082
struct_span_err!(self.tcx.sess, span, E0644, "{}", failure_str)
20502083
}
20512084
};
2052-
self.note_type_err(&mut diag, &trace.cause, None, Some(trace.values), terr);
2085+
self.note_type_err(&mut diag, &trace.cause, None, Some(trace.values), terr, false);
20532086
diag
20542087
}
20552088

Diff for: compiler/rustc_middle/src/ty/error.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -118,17 +118,15 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
118118
ArgumentMutability(_) | Mutability => write!(f, "types differ in mutability"),
119119
TupleSize(values) => write!(
120120
f,
121-
"expected a tuple with {} element{}, \
122-
found one with {} element{}",
121+
"expected a tuple with {} element{}, found one with {} element{}",
123122
values.expected,
124123
pluralize!(values.expected),
125124
values.found,
126125
pluralize!(values.found)
127126
),
128127
FixedArraySize(values) => write!(
129128
f,
130-
"expected an array with a fixed size of {} element{}, \
131-
found one with {} element{}",
129+
"expected an array with a fixed size of {} element{}, found one with {} element{}",
132130
values.expected,
133131
pluralize!(values.expected),
134132
values.found,

Diff for: compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs

+53-3
Original file line numberDiff line numberDiff line change
@@ -1338,7 +1338,46 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
13381338
"type mismatch resolving `{}`",
13391339
predicate
13401340
);
1341-
self.note_type_err(&mut diag, &obligation.cause, None, values, err);
1341+
let secondary_span = match predicate.kind().skip_binder() {
1342+
ty::PredicateKind::Projection(proj) => self
1343+
.tcx
1344+
.opt_associated_item(proj.projection_ty.item_def_id)
1345+
.and_then(|trait_assoc_item| {
1346+
self.tcx
1347+
.trait_of_item(proj.projection_ty.item_def_id)
1348+
.map(|id| (trait_assoc_item, id))
1349+
})
1350+
.and_then(|(trait_assoc_item, id)| {
1351+
self.tcx.find_map_relevant_impl(
1352+
id,
1353+
proj.projection_ty.self_ty(),
1354+
|did| {
1355+
self.tcx
1356+
.associated_items(did)
1357+
.in_definition_order()
1358+
.filter(|assoc| assoc.ident == trait_assoc_item.ident)
1359+
.next()
1360+
},
1361+
)
1362+
})
1363+
.and_then(|item| match self.tcx.hir().get_if_local(item.def_id) {
1364+
Some(
1365+
hir::Node::TraitItem(hir::TraitItem {
1366+
kind: hir::TraitItemKind::Type(_, Some(ty)),
1367+
..
1368+
})
1369+
| hir::Node::ImplItem(hir::ImplItem {
1370+
kind: hir::ImplItemKind::TyAlias(ty),
1371+
..
1372+
}),
1373+
) => {
1374+
Some((ty.span, format!("type mismatch resolving `{}`", predicate)))
1375+
}
1376+
_ => None,
1377+
}),
1378+
_ => None,
1379+
};
1380+
self.note_type_err(&mut diag, &obligation.cause, secondary_span, values, err, true);
13421381
self.note_obligation_cause(&mut diag, obligation);
13431382
diag.emit();
13441383
}
@@ -2095,10 +2134,21 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
20952134
) -> bool {
20962135
if let ObligationCauseCode::BuiltinDerivedObligation(ref data) = cause_code {
20972136
let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_ref);
2098-
2099-
if obligated_types.iter().any(|ot| ot == &parent_trait_ref.skip_binder().self_ty()) {
2137+
let self_ty = parent_trait_ref.skip_binder().self_ty();
2138+
if obligated_types.iter().any(|ot| ot == &self_ty) {
21002139
return true;
21012140
}
2141+
if let ty::Adt(def, substs) = self_ty.kind() {
2142+
if let [arg] = &substs[..] {
2143+
if let ty::subst::GenericArgKind::Type(ty) = arg.unpack() {
2144+
if let ty::Adt(inner_def, _) = ty.kind() {
2145+
if inner_def == def {
2146+
return true;
2147+
}
2148+
}
2149+
}
2150+
}
2151+
}
21022152
}
21032153
false
21042154
}

Diff for: compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

+10
Original file line numberDiff line numberDiff line change
@@ -2186,6 +2186,16 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
21862186
seen_requirements,
21872187
)
21882188
});
2189+
} else {
2190+
ensure_sufficient_stack(|| {
2191+
self.note_obligation_cause_code(
2192+
err,
2193+
&parent_predicate,
2194+
&cause_code.peel_derives(),
2195+
obligated_types,
2196+
seen_requirements,
2197+
)
2198+
});
21892199
}
21902200
}
21912201
ObligationCauseCode::ImplDerivedObligation(ref data) => {

Diff for: compiler/rustc_typeck/src/check/cast.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -638,7 +638,11 @@ impl<'a, 'tcx> CastCheck<'tcx> {
638638
self.expr_ty = fcx.structurally_resolved_type(self.expr.span, self.expr_ty);
639639
self.cast_ty = fcx.structurally_resolved_type(self.cast_span, self.cast_ty);
640640

641-
if !fcx.type_is_known_to_be_sized_modulo_regions(self.cast_ty, self.span) {
641+
debug!("check_cast({}, {:?} as {:?})", self.expr.hir_id, self.expr_ty, self.cast_ty);
642+
643+
if !fcx.type_is_known_to_be_sized_modulo_regions(self.cast_ty, self.span)
644+
&& !self.cast_ty.has_infer_types()
645+
{
642646
self.report_cast_to_unsized_type(fcx);
643647
} else if self.expr_ty.references_error() || self.cast_ty.references_error() {
644648
// No sense in giving duplicate error messages

Diff for: compiler/rustc_typeck/src/check/check.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -730,15 +730,15 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) {
730730
let abi = sig.header.abi;
731731
fn_maybe_err(tcx, item.ident.span, abi);
732732
}
733-
hir::TraitItemKind::Type(.., Some(_default)) => {
733+
hir::TraitItemKind::Type(.., Some(default)) => {
734734
let assoc_item = tcx.associated_item(item.def_id);
735735
let trait_substs =
736736
InternalSubsts::identity_for_item(tcx, it.def_id.to_def_id());
737737
let _: Result<_, rustc_errors::ErrorReported> = check_type_bounds(
738738
tcx,
739739
assoc_item,
740740
assoc_item,
741-
item.span,
741+
default.span,
742742
ty::TraitRef { def_id: it.def_id.to_def_id(), substs: trait_substs },
743743
);
744744
}
@@ -987,12 +987,12 @@ pub(super) fn check_impl_items_against_trait<'tcx>(
987987
opt_trait_span,
988988
);
989989
}
990-
hir::ImplItemKind::TyAlias(_) => {
990+
hir::ImplItemKind::TyAlias(impl_ty) => {
991991
let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id);
992992
compare_ty_impl(
993993
tcx,
994994
&ty_impl_item,
995-
impl_item.span,
995+
impl_ty.span,
996996
&ty_trait_item,
997997
impl_trait_ref,
998998
opt_trait_span,

Diff for: compiler/rustc_typeck/src/check/compare_method.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,7 @@ fn compare_predicate_entailment<'tcx>(
379379
found: impl_fty,
380380
})),
381381
&terr,
382+
false,
382383
);
383384
diag.emit();
384385
return Err(ErrorReported);
@@ -734,8 +735,7 @@ fn compare_number_of_method_arguments<'tcx>(
734735
tcx.sess,
735736
impl_span,
736737
E0050,
737-
"method `{}` has {} but the declaration in \
738-
trait `{}` has {}",
738+
"method `{}` has {} but the declaration in trait `{}` has {}",
739739
trait_m.ident,
740740
potentially_plural_count(impl_number_args, "parameter"),
741741
tcx.def_path_str(trait_m.def_id),
@@ -1069,6 +1069,7 @@ crate fn compare_const_impl<'tcx>(
10691069
found: impl_ty,
10701070
})),
10711071
&terr,
1072+
false,
10721073
);
10731074
diag.emit();
10741075
}
@@ -1099,7 +1100,8 @@ crate fn compare_ty_impl<'tcx>(
10991100
let _: Result<(), ErrorReported> = (|| {
11001101
compare_number_of_generics(tcx, impl_ty, impl_ty_span, trait_ty, trait_item_span)?;
11011102

1102-
compare_type_predicate_entailment(tcx, impl_ty, impl_ty_span, trait_ty, impl_trait_ref)?;
1103+
let sp = tcx.def_span(impl_ty.def_id);
1104+
compare_type_predicate_entailment(tcx, impl_ty, sp, trait_ty, impl_trait_ref)?;
11031105

11041106
check_type_bounds(tcx, trait_ty, impl_ty, impl_ty_span, impl_trait_ref)
11051107
})();

Diff for: compiler/rustc_typeck/src/check/wfcheck.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -683,7 +683,8 @@ pub fn check_impl_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
683683

684684
let (method_sig, span) = match impl_item.kind {
685685
hir::ImplItemKind::Fn(ref sig, _) => (Some(sig), impl_item.span),
686-
hir::ImplItemKind::TyAlias(ty) => (None, ty.span),
686+
// Constrain binding and overflow error spans to `<Ty>` in `type foo = <Ty>`.
687+
hir::ImplItemKind::TyAlias(ty) if ty.span != DUMMY_SP => (None, ty.span),
687688
_ => (None, impl_item.span),
688689
};
689690

Diff for: src/test/ui/associated-consts/associated-const-generic-obligations.stderr

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
error[E0326]: implemented const `FROM` has an incompatible type for trait
22
--> $DIR/associated-const-generic-obligations.rs:14:17
33
|
4-
LL | const FROM: Self::Out;
5-
| --------- type in trait
6-
...
74
LL | const FROM: &'static str = "foo";
85
| ^^^^^^^^^^^^ expected associated type, found `&str`
96
|
7+
note: type in trait
8+
--> $DIR/associated-const-generic-obligations.rs:10:17
9+
|
10+
LL | const FROM: Self::Out;
11+
| ^^^^^^^^^
1012
= note: expected associated type `<T as Foo>::Out`
1113
found reference `&'static str`
1214

Diff for: src/test/ui/associated-consts/associated-const-impl-wrong-type.stderr

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
error[E0326]: implemented const `BAR` has an incompatible type for trait
22
--> $DIR/associated-const-impl-wrong-type.rs:8:16
33
|
4-
LL | const BAR: u32;
5-
| --- type in trait
6-
...
74
LL | const BAR: i32 = -1;
85
| ^^^ expected `u32`, found `i32`
6+
|
7+
note: type in trait
8+
--> $DIR/associated-const-impl-wrong-type.rs:2:16
9+
|
10+
LL | const BAR: u32;
11+
| ^^^
912

1013
error: aborting due to previous error
1114

Diff for: src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.stderr

+12-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,13 @@ error[E0271]: type mismatch resolving `<ModelT as Vehicle>::Color == Blue`
22
--> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:31:10
33
|
44
LL | fn b() { blue_car(ModelT); }
5-
| ^^^^^^^^ expected struct `Blue`, found struct `Black`
5+
| ^^^^^^^^ type mismatch resolving `<ModelT as Vehicle>::Color == Blue`
66
|
7+
note: expected this to be `Blue`
8+
--> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:16:40
9+
|
10+
LL | impl Vehicle for ModelT { type Color = Black; }
11+
| ^^^^^
712
note: required by a bound in `blue_car`
813
--> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:27:19
914
|
@@ -14,8 +19,13 @@ error[E0271]: type mismatch resolving `<ModelU as Vehicle>::Color == Black`
1419
--> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:32:10
1520
|
1621
LL | fn c() { black_car(ModelU); }
17-
| ^^^^^^^^^ expected struct `Black`, found struct `Blue`
22+
| ^^^^^^^^^ type mismatch resolving `<ModelU as Vehicle>::Color == Black`
23+
|
24+
note: expected this to be `Black`
25+
--> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:21:40
1826
|
27+
LL | impl Vehicle for ModelU { type Color = Blue; }
28+
| ^^^^
1929
note: required by a bound in `black_car`
2030
--> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:24:20
2131
|

Diff for: src/test/ui/associated-types/associated-types-eq-3.rs

-2
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,6 @@ pub fn main() {
3737
let a = 42;
3838
foo1(a);
3939
//~^ ERROR type mismatch resolving
40-
//~| expected struct `Bar`, found `usize`
4140
baz(&a);
4241
//~^ ERROR type mismatch resolving
43-
//~| expected struct `Bar`, found `usize`
4442
}

Diff for: src/test/ui/associated-types/associated-types-eq-3.stderr

+13-3
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,30 @@ error[E0271]: type mismatch resolving `<isize as Foo>::A == Bar`
1717
--> $DIR/associated-types-eq-3.rs:38:5
1818
|
1919
LL | foo1(a);
20-
| ^^^^ expected struct `Bar`, found `usize`
20+
| ^^^^ type mismatch resolving `<isize as Foo>::A == Bar`
2121
|
22+
note: expected this to be `Bar`
23+
--> $DIR/associated-types-eq-3.rs:12:14
24+
|
25+
LL | type A = usize;
26+
| ^^^^^
2227
note: required by a bound in `foo1`
2328
--> $DIR/associated-types-eq-3.rs:18:16
2429
|
2530
LL | fn foo1<I: Foo<A=Bar>>(x: I) {
2631
| ^^^^^ required by this bound in `foo1`
2732

2833
error[E0271]: type mismatch resolving `<isize as Foo>::A == Bar`
29-
--> $DIR/associated-types-eq-3.rs:41:9
34+
--> $DIR/associated-types-eq-3.rs:40:9
3035
|
3136
LL | baz(&a);
32-
| ^^ expected struct `Bar`, found `usize`
37+
| ^^ type mismatch resolving `<isize as Foo>::A == Bar`
38+
|
39+
note: expected this to be `Bar`
40+
--> $DIR/associated-types-eq-3.rs:12:14
3341
|
42+
LL | type A = usize;
43+
| ^^^^^
3444
= note: required for the cast to the object type `dyn Foo<A = Bar>`
3545

3646
error: aborting due to 3 previous errors

0 commit comments

Comments
 (0)