Skip to content

Commit d4d7cc3

Browse files
Rollup merge of rust-lang#126142 - compiler-errors:trait-ref-split, r=jackh726
Harmonize using root or leaf obligation in trait error reporting When rust-lang#121826 changed the error reporting to use root obligation and not the leafmost obligation, it didn't actually make sure that all the other diagnostics helper functions used the right obligation. Specifically, when reporting similar impl candidates we are looking for impls of the root obligation, but trying to match them against the trait ref of the leaf obligation. This does a few other miscellaneous changes. There's a lot more clean-up that could be done here, but working with this code is really grief-inducing due to how messy it has become over the years. Someone really needs to show it love. 😓 r? `@estebank` Fixes rust-lang#126129
2 parents 0e30c7d + c90b1fc commit d4d7cc3

23 files changed

+153
-110
lines changed

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,7 @@ impl<T> Trait<T> for X {
546546
for pred in hir_generics.bounds_for_param(def_id) {
547547
if self.constrain_generic_bound_associated_type_structured_suggestion(
548548
diag,
549-
&trait_ref,
549+
trait_ref,
550550
pred.bounds,
551551
assoc,
552552
assoc_args,
@@ -715,7 +715,7 @@ fn foo(&self) -> Self::T { String::new() }
715715

716716
self.constrain_generic_bound_associated_type_structured_suggestion(
717717
diag,
718-
&trait_ref,
718+
trait_ref,
719719
opaque_hir_ty.bounds,
720720
assoc,
721721
assoc_args,
@@ -869,7 +869,7 @@ fn foo(&self) -> Self::T { String::new() }
869869
fn constrain_generic_bound_associated_type_structured_suggestion(
870870
&self,
871871
diag: &mut Diag<'_>,
872-
trait_ref: &ty::TraitRef<'tcx>,
872+
trait_ref: ty::TraitRef<'tcx>,
873873
bounds: hir::GenericBounds<'_>,
874874
assoc: ty::AssocItem,
875875
assoc_args: &[ty::GenericArg<'tcx>],

compiler/rustc_infer/src/traits/util.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -285,8 +285,7 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
285285
let obligations =
286286
predicates.predicates.iter().enumerate().map(|(index, &(clause, span))| {
287287
elaboratable.child_with_derived_cause(
288-
clause
289-
.instantiate_supertrait(tcx, &bound_clause.rebind(data.trait_ref)),
288+
clause.instantiate_supertrait(tcx, bound_clause.rebind(data.trait_ref)),
290289
span,
291290
bound_clause.rebind(data),
292291
index,

compiler/rustc_middle/src/traits/util.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ impl<'tcx> Elaborator<'tcx> {
3737
let super_predicates =
3838
self.tcx.super_predicates_of(trait_ref.def_id()).predicates.iter().filter_map(
3939
|&(pred, _)| {
40-
let clause = pred.instantiate_supertrait(self.tcx, &trait_ref);
40+
let clause = pred.instantiate_supertrait(self.tcx, trait_ref);
4141
self.visited.insert(clause).then_some(clause)
4242
},
4343
);

compiler/rustc_middle/src/ty/predicate.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ impl<'tcx> Clause<'tcx> {
313313
pub fn instantiate_supertrait(
314314
self,
315315
tcx: TyCtxt<'tcx>,
316-
trait_ref: &ty::PolyTraitRef<'tcx>,
316+
trait_ref: ty::PolyTraitRef<'tcx>,
317317
) -> Clause<'tcx> {
318318
// The interaction between HRTB and supertraits is not entirely
319319
// obvious. Let me walk you (and myself) through an example.

compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -3597,7 +3597,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
35973597
&self,
35983598
obligation: &PredicateObligation<'tcx>,
35993599
err: &mut Diag<'_>,
3600-
trait_ref: &ty::PolyTraitRef<'tcx>,
3600+
trait_ref: ty::PolyTraitRef<'tcx>,
36013601
) {
36023602
let rhs_span = match obligation.cause.code() {
36033603
ObligationCauseCode::BinOp { rhs_span: Some(span), rhs_is_lit, .. } if *rhs_is_lit => {
@@ -4863,14 +4863,13 @@ impl<'a, 'hir> hir::intravisit::Visitor<'hir> for ReplaceImplTraitVisitor<'a> {
48634863
pub(super) fn get_explanation_based_on_obligation<'tcx>(
48644864
tcx: TyCtxt<'tcx>,
48654865
obligation: &PredicateObligation<'tcx>,
4866-
trait_ref: ty::PolyTraitRef<'tcx>,
4867-
trait_predicate: &ty::PolyTraitPredicate<'tcx>,
4866+
trait_predicate: ty::PolyTraitPredicate<'tcx>,
48684867
pre_message: String,
48694868
) -> String {
48704869
if let ObligationCauseCode::MainFunctionType = obligation.cause.code() {
48714870
"consider using `()`, or a `Result`".to_owned()
48724871
} else {
4873-
let ty_desc = match trait_ref.skip_binder().self_ty().kind() {
4872+
let ty_desc = match trait_predicate.self_ty().skip_binder().kind() {
48744873
ty::FnDef(_, _) => Some("fn item"),
48754874
ty::Closure(_, _) => Some("closure"),
48764875
_ => None,
@@ -4895,7 +4894,7 @@ pub(super) fn get_explanation_based_on_obligation<'tcx>(
48954894
format!(
48964895
"{pre_message}the trait `{}` is not implemented for{desc} `{}`{post}",
48974896
trait_predicate.print_modifiers_and_trait_path(),
4898-
tcx.short_ty_string(trait_ref.skip_binder().self_ty(), &mut None),
4897+
tcx.short_ty_string(trait_predicate.self_ty().skip_binder(), &mut None),
48994898
)
49004899
} else {
49014900
// "the trait bound `T: !Send` is not satisfied" reads better than "`!Send` is

compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs

+76-77
Large diffs are not rendered by default.

compiler/rustc_trait_selection/src/traits/object_safety.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ fn predicates_reference_self(
194194
predicates
195195
.predicates
196196
.iter()
197-
.map(|&(predicate, sp)| (predicate.instantiate_supertrait(tcx, &trait_ref), sp))
197+
.map(|&(predicate, sp)| (predicate.instantiate_supertrait(tcx, trait_ref), sp))
198198
.filter_map(|predicate| predicate_references_self(tcx, predicate))
199199
.collect()
200200
}

compiler/rustc_trait_selection/src/traits/select/mod.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -1866,7 +1866,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
18661866
// the param_env so that it can be given the lowest priority. See
18671867
// #50825 for the motivation for this.
18681868
let is_global =
1869-
|cand: &ty::PolyTraitPredicate<'tcx>| cand.is_global() && !cand.has_bound_vars();
1869+
|cand: ty::PolyTraitPredicate<'tcx>| cand.is_global() && !cand.has_bound_vars();
18701870

18711871
// (*) Prefer `BuiltinCandidate { has_nested: false }`, `PointeeCandidate`,
18721872
// `DiscriminantKindCandidate`, `ConstDestructCandidate`
@@ -1909,7 +1909,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
19091909
}
19101910

19111911
(
1912-
ParamCandidate(ref other_cand),
1912+
ParamCandidate(other_cand),
19131913
ImplCandidate(..)
19141914
| AutoImplCandidate
19151915
| ClosureCandidate { .. }
@@ -1934,12 +1934,12 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
19341934
//
19351935
// Global bounds from the where clause should be ignored
19361936
// here (see issue #50825).
1937-
DropVictim::drop_if(!is_global(other_cand))
1937+
DropVictim::drop_if(!is_global(*other_cand))
19381938
}
1939-
(ObjectCandidate(_) | ProjectionCandidate(_), ParamCandidate(ref victim_cand)) => {
1939+
(ObjectCandidate(_) | ProjectionCandidate(_), ParamCandidate(victim_cand)) => {
19401940
// Prefer these to a global where-clause bound
19411941
// (see issue #50825).
1942-
if is_global(victim_cand) { DropVictim::Yes } else { DropVictim::No }
1942+
if is_global(*victim_cand) { DropVictim::Yes } else { DropVictim::No }
19431943
}
19441944
(
19451945
ImplCandidate(_)
@@ -1957,12 +1957,12 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
19571957
| TraitUpcastingUnsizeCandidate(_)
19581958
| BuiltinCandidate { has_nested: true }
19591959
| TraitAliasCandidate,
1960-
ParamCandidate(ref victim_cand),
1960+
ParamCandidate(victim_cand),
19611961
) => {
19621962
// Prefer these to a global where-clause bound
19631963
// (see issue #50825).
19641964
DropVictim::drop_if(
1965-
is_global(victim_cand) && other.evaluation.must_apply_modulo_regions(),
1965+
is_global(*victim_cand) && other.evaluation.must_apply_modulo_regions(),
19661966
)
19671967
}
19681968

compiler/rustc_trait_selection/src/traits/util.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ impl<'tcx> TraitAliasExpander<'tcx> {
132132
debug!(?predicates);
133133

134134
let items = predicates.predicates.iter().rev().filter_map(|(pred, span)| {
135-
pred.instantiate_supertrait(tcx, &trait_ref)
135+
pred.instantiate_supertrait(tcx, trait_ref)
136136
.as_trait_clause()
137137
.map(|trait_ref| item.clone_and_push(trait_ref.map_bound(|t| t.trait_ref), *span))
138138
});

compiler/rustc_trait_selection/src/traits/vtable.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ fn prepare_vtable_segments_inner<'tcx, T>(
125125
.predicates
126126
.into_iter()
127127
.filter_map(move |(pred, _)| {
128-
pred.instantiate_supertrait(tcx, &inner_most_trait_ref).as_trait_clause()
128+
pred.instantiate_supertrait(tcx, inner_most_trait_ref).as_trait_clause()
129129
});
130130

131131
// Find an unvisited supertrait

tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `&'static u32: Defaulted` is not satisfied
22
--> $DIR/typeck-default-trait-impl-precedence.rs:19:20
33
|
44
LL | is_defaulted::<&'static u32>();
5-
| ^^^^^^^^^^^^ the trait `Signed` is not implemented for `&'static u32`, which is required by `&'static u32: Defaulted`
5+
| ^^^^^^^^^^^^ the trait `Signed` is not implemented for `u32`, which is required by `&'static u32: Defaulted`
66
|
77
note: required for `&'static u32` to implement `Defaulted`
88
--> $DIR/typeck-default-trait-impl-precedence.rs:10:19

tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.next.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `i32: Baz<Self>` is not satisfied
22
--> $DIR/assume-gat-normalization-for-nested-goals.rs:9:30
33
|
44
LL | type Bar<T>: Baz<Self> = i32;
5-
| ^^^ the trait `Eq<i32>` is not implemented for `i32`, which is required by `i32: Baz<Self>`
5+
| ^^^ the trait `Eq<i32>` is not implemented for `<Self as Foo>::Bar<()>`, which is required by `i32: Baz<Self>`
66
|
77
note: required for `i32` to implement `Baz<Self>`
88
--> $DIR/assume-gat-normalization-for-nested-goals.rs:16:23

tests/ui/kindck/kindck-send-object.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error[E0277]: `&'static (dyn Dummy + 'static)` cannot be sent between threads sa
44
LL | assert_send::<&'static (dyn Dummy + 'static)>();
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&'static (dyn Dummy + 'static)` cannot be sent between threads safely
66
|
7-
= help: the trait `Sync` is not implemented for `&'static (dyn Dummy + 'static)`, which is required by `&'static (dyn Dummy + 'static): Send`
7+
= help: the trait `Sync` is not implemented for `(dyn Dummy + 'static)`, which is required by `&'static (dyn Dummy + 'static): Send`
88
= note: required for `&'static (dyn Dummy + 'static)` to implement `Send`
99
note: required by a bound in `assert_send`
1010
--> $DIR/kindck-send-object.rs:5:18

tests/ui/kindck/kindck-send-object1.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error[E0277]: `&'a (dyn Dummy + 'a)` cannot be sent between threads safely
44
LL | assert_send::<&'a dyn Dummy>();
55
| ^^^^^^^^^^^^^ `&'a (dyn Dummy + 'a)` cannot be sent between threads safely
66
|
7-
= help: the trait `Sync` is not implemented for `&'a (dyn Dummy + 'a)`, which is required by `&'a (dyn Dummy + 'a): Send`
7+
= help: the trait `Sync` is not implemented for `(dyn Dummy + 'a)`, which is required by `&'a (dyn Dummy + 'a): Send`
88
= note: required for `&'a (dyn Dummy + 'a)` to implement `Send`
99
note: required by a bound in `assert_send`
1010
--> $DIR/kindck-send-object1.rs:5:18

tests/ui/kindck/kindck-send-object2.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error[E0277]: `&'static (dyn Dummy + 'static)` cannot be sent between threads sa
44
LL | assert_send::<&'static dyn Dummy>();
55
| ^^^^^^^^^^^^^^^^^^ `&'static (dyn Dummy + 'static)` cannot be sent between threads safely
66
|
7-
= help: the trait `Sync` is not implemented for `&'static (dyn Dummy + 'static)`, which is required by `&'static (dyn Dummy + 'static): Send`
7+
= help: the trait `Sync` is not implemented for `(dyn Dummy + 'static)`, which is required by `&'static (dyn Dummy + 'static): Send`
88
= note: required for `&'static (dyn Dummy + 'static)` to implement `Send`
99
note: required by a bound in `assert_send`
1010
--> $DIR/kindck-send-object2.rs:3:18

tests/ui/suggestions/suggest-remove-refs-5.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error[E0277]: `&mut &mut &mut &mut Vec<i32>` is not an iterator
44
LL | for _ in &mut &mut v {}
55
| ^^^^^^^^^^^ `&mut &mut &mut &mut Vec<i32>` is not an iterator
66
|
7-
= help: the trait `Iterator` is not implemented for `&mut &mut &mut &mut Vec<i32>`, which is required by `&mut &mut &mut &mut Vec<i32>: IntoIterator`
7+
= help: the trait `Iterator` is not implemented for `Vec<i32>`, which is required by `&mut &mut &mut &mut Vec<i32>: IntoIterator`
88
= note: required for `&mut Vec<i32>` to implement `Iterator`
99
= note: 3 redundant requirements hidden
1010
= note: required for `&mut &mut &mut &mut Vec<i32>` to implement `Iterator`
@@ -21,7 +21,7 @@ error[E0277]: `&mut &mut &mut [u8; 1]` is not an iterator
2121
LL | for _ in &mut v {}
2222
| ^^^^^^ `&mut &mut &mut [u8; 1]` is not an iterator
2323
|
24-
= help: the trait `Iterator` is not implemented for `&mut &mut &mut [u8; 1]`, which is required by `&mut &mut &mut [u8; 1]: IntoIterator`
24+
= help: the trait `Iterator` is not implemented for `[u8; 1]`, which is required by `&mut &mut &mut [u8; 1]: IntoIterator`
2525
= note: required for `&mut [u8; 1]` to implement `Iterator`
2626
= note: 2 redundant requirements hidden
2727
= note: required for `&mut &mut &mut [u8; 1]` to implement `Iterator`

tests/ui/traits/next-solver/auto-with-drop_tracking_mir.fail.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error: future cannot be sent between threads safely
44
LL | is_send(foo());
55
| ^^^^^ future returned by `foo` is not `Send`
66
|
7-
= help: the trait `Sync` is not implemented for `impl Future<Output = ()>`, which is required by `impl Future<Output = ()>: Send`
7+
= help: the trait `Sync` is not implemented for `NotSync`, which is required by `impl Future<Output = ()>: Send`
88
note: future is not `Send` as this value is used across an await
99
--> $DIR/auto-with-drop_tracking_mir.rs:16:11
1010
|

tests/ui/traits/next-solver/diagnostics/point-at-failing-nested.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ error[E0277]: the trait bound `(): Foo` is not satisfied
44
LL | needs_foo::<()>();
55
| ^^ the trait `Bar` is not implemented for `()`, which is required by `(): Foo`
66
|
7+
help: this trait has no implementations, consider adding one
8+
--> $DIR/point-at-failing-nested.rs:4:1
9+
|
10+
LL | trait Bar {}
11+
| ^^^^^^^^^
712
note: required for `()` to implement `Foo`
813
--> $DIR/point-at-failing-nested.rs:9:12
914
|

tests/ui/traits/next-solver/diagnostics/where-clause-doesnt-apply.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ LL | needs_foo(());
66
| |
77
| required by a bound introduced by this call
88
|
9+
help: this trait has no implementations, consider adding one
10+
--> $DIR/where-clause-doesnt-apply.rs:2:1
11+
|
12+
LL | trait Bar {}
13+
| ^^^^^^^^^
914
note: required for `()` to implement `Foo`
1015
--> $DIR/where-clause-doesnt-apply.rs:4:9
1116
|

tests/ui/traits/suggest-dereferences/root-obligation.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `&char: Pattern<'_>` is not satisfied
22
--> $DIR/root-obligation.rs:6:38
33
|
44
LL | .filter(|c| "aeiou".contains(c))
5-
| -------- ^ the trait `Fn(char)` is not implemented for `&char`, which is required by `&char: Pattern<'_>`
5+
| -------- ^ the trait `Fn(char)` is not implemented for `char`, which is required by `&char: Pattern<'_>`
66
| |
77
| required by a bound introduced by this call
88
|

tests/ui/transmutability/references/unsafecell.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0277]: `&u8` cannot be safely transmuted into `&UnsafeCell<u8>`
22
--> $DIR/unsafecell.rs:27:50
33
|
44
LL | assert::is_maybe_transmutable::<&'static u8, &'static UnsafeCell<u8>>();
5-
| ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Freeze` is not implemented for `&'static UnsafeCell<u8>`
5+
| ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Freeze` is not implemented for `UnsafeCell<u8>`
66
|
77
note: required by a bound in `is_maybe_transmutable`
88
--> $DIR/unsafecell.rs:12:14
@@ -17,7 +17,7 @@ error[E0277]: `&UnsafeCell<u8>` cannot be safely transmuted into `&UnsafeCell<u8
1717
--> $DIR/unsafecell.rs:29:62
1818
|
1919
LL | assert::is_maybe_transmutable::<&'static UnsafeCell<u8>, &'static UnsafeCell<u8>>();
20-
| ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Freeze` is not implemented for `&'static UnsafeCell<u8>`
20+
| ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Freeze` is not implemented for `UnsafeCell<u8>`
2121
|
2222
note: required by a bound in `is_maybe_transmutable`
2323
--> $DIR/unsafecell.rs:12:14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
trait Foo<'s> {}
2+
3+
impl<'s> Foo<'s> for () {}
4+
5+
struct Bar;
6+
7+
impl<'s, T: Foo<'s>> From<T> for Bar {
8+
fn from(_: T) -> Self {
9+
Bar
10+
}
11+
}
12+
13+
fn main() {
14+
let _: Bar = ((),).into();
15+
//~^ ERROR he trait bound `((),): Into<Bar>` is not satisfied
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error[E0277]: the trait bound `((),): Into<Bar>` is not satisfied
2+
--> $DIR/suggest-similar-impls-for-root-obligation.rs:14:24
3+
|
4+
LL | let _: Bar = ((),).into();
5+
| ^^^^ the trait `Foo<'_>` is not implemented for `((),)`, which is required by `((),): Into<_>`
6+
|
7+
= help: the trait `Foo<'_>` is implemented for `()`
8+
= help: for that trait implementation, expected `()`, found `((),)`
9+
note: required for `Bar` to implement `From<((),)>`
10+
--> $DIR/suggest-similar-impls-for-root-obligation.rs:7:22
11+
|
12+
LL | impl<'s, T: Foo<'s>> From<T> for Bar {
13+
| ------- ^^^^^^^ ^^^
14+
| |
15+
| unsatisfied trait bound introduced here
16+
= note: required for `((),)` to implement `Into<Bar>`
17+
18+
error: aborting due to 1 previous error
19+
20+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)