Skip to content

Commit ae46b4e

Browse files
Deeply normalize obligations in BestObligation
1 parent aefb9f6 commit ae46b4e

File tree

10 files changed

+77
-56
lines changed

10 files changed

+77
-56
lines changed

compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs

+39-19
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ use rustc_next_trait_solver::solve::{GenerateProofTree, SolverDelegateEvalExt as
1313
use rustc_type_ir::solve::NoSolution;
1414
use tracing::{instrument, trace};
1515

16-
use crate::solve::Certainty;
1716
use crate::solve::delegate::SolverDelegate;
1817
use crate::solve::inspect::{self, ProofTreeInferCtxtExt, ProofTreeVisitor};
18+
use crate::solve::{Certainty, deeply_normalize_for_diagnostics};
1919
use crate::traits::{FulfillmentError, FulfillmentErrorCode, wf};
2020

2121
pub(super) fn fulfillment_error_for_no_solution<'tcx>(
@@ -153,10 +153,17 @@ fn find_best_leaf_obligation<'tcx>(
153153
// means the leaf obligation may be incorrect.
154154
infcx
155155
.fudge_inference_if_ok(|| {
156+
let goal = obligation.as_goal();
156157
infcx
157158
.visit_proof_tree(
158-
obligation.as_goal(),
159-
&mut BestObligation { obligation: obligation.clone(), consider_ambiguities },
159+
goal,
160+
&mut BestObligation {
161+
obligation: obligation.with(
162+
infcx.tcx,
163+
deeply_normalize_for_diagnostics(infcx, goal.param_env, goal.predicate),
164+
),
165+
consider_ambiguities,
166+
},
160167
)
161168
.break_value()
162169
.ok_or(())
@@ -239,21 +246,18 @@ impl<'tcx> BestObligation<'tcx> {
239246
let param_env = candidate.goal().goal().param_env;
240247
let body_id = self.obligation.cause.body_id;
241248

242-
for obligation in wf::unnormalized_obligations(infcx, param_env, arg, self.span(), body_id)
243-
.into_iter()
244-
.flatten()
249+
for mut obligation in
250+
wf::unnormalized_obligations(infcx, param_env, arg, self.span(), body_id)
251+
.into_iter()
252+
.flatten()
245253
{
246254
let nested_goal = candidate.instantiate_proof_tree_for_nested_goal(
247255
GoalSource::Misc,
248256
obligation.as_goal(),
249257
self.span(),
250258
);
251-
// Skip nested goals that aren't the *reason* for our goal's failure.
252-
match (self.consider_ambiguities, nested_goal.result()) {
253-
(true, Ok(Certainty::Maybe(MaybeCause::Ambiguity))) | (false, Err(_)) => {}
254-
_ => continue,
255-
}
256-
259+
obligation.predicate =
260+
deeply_normalize_for_diagnostics(infcx, param_env, obligation.predicate);
257261
self.with_derived_obligation(obligation, |this| nested_goal.visit_with(this))?;
258262
}
259263

@@ -277,8 +281,12 @@ impl<'tcx> BestObligation<'tcx> {
277281
infer_term.into(),
278282
ty::AliasRelationDirection::Equate,
279283
);
280-
let obligation =
281-
Obligation::new(tcx, self.obligation.cause.clone(), goal.goal().param_env, pred);
284+
let obligation = Obligation::new(
285+
tcx,
286+
self.obligation.cause.clone(),
287+
goal.goal().param_env,
288+
deeply_normalize_for_diagnostics(goal.infcx(), goal.goal().param_env, pred),
289+
);
282290
self.with_derived_obligation(obligation, |this| {
283291
goal.infcx().visit_proof_tree_at_depth(
284292
goal.goal().with(tcx, pred),
@@ -307,7 +315,11 @@ impl<'tcx> BestObligation<'tcx> {
307315
tcx,
308316
self.obligation.cause.clone(),
309317
goal.goal().param_env,
310-
alias.trait_ref(tcx),
318+
deeply_normalize_for_diagnostics(
319+
goal.infcx(),
320+
goal.goal().param_env,
321+
alias.trait_ref(tcx),
322+
),
311323
);
312324
self.with_derived_obligation(obligation, |this| {
313325
goal.infcx().visit_proof_tree_at_depth(
@@ -430,12 +442,14 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
430442
for nested_goal in nested_goals {
431443
trace!(nested_goal = ?(nested_goal.goal(), nested_goal.source(), nested_goal.result()));
432444

433-
let nested_pred = nested_goal.goal().predicate;
434-
435445
let make_obligation = |cause| Obligation {
436446
cause,
437447
param_env: nested_goal.goal().param_env,
438-
predicate: nested_pred,
448+
predicate: deeply_normalize_for_diagnostics(
449+
nested_goal.infcx(),
450+
nested_goal.goal().param_env,
451+
nested_goal.goal().predicate,
452+
),
439453
recursion_depth: self.obligation.recursion_depth + 1,
440454
};
441455

@@ -508,7 +522,13 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
508522
&& !projection_clause.bound_vars().is_empty()
509523
{
510524
let pred = projection_clause.map_bound(|proj| proj.projection_term.trait_ref(tcx));
511-
self.with_derived_obligation(self.obligation.with(tcx, pred), |this| {
525+
let obligation = Obligation::new(
526+
tcx,
527+
self.obligation.cause.clone(),
528+
goal.goal().param_env,
529+
deeply_normalize_for_diagnostics(goal.infcx(), goal.goal().param_env, pred),
530+
);
531+
self.with_derived_obligation(obligation, |this| {
512532
goal.infcx().visit_proof_tree_at_depth(
513533
goal.goal().with(tcx, pred),
514534
goal.depth() + 1,

compiler/rustc_trait_selection/src/solve/normalize.rs

+20-12
Original file line numberDiff line numberDiff line change
@@ -253,20 +253,28 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for DeeplyNormalizeForDiagnosticsFolder<'_,
253253
}
254254

255255
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
256-
deeply_normalize_with_skipped_universes(
257-
self.at,
258-
ty,
259-
vec![None; ty.outer_exclusive_binder().as_usize()],
260-
)
261-
.unwrap_or_else(|_: Vec<ScrubbedTraitError<'tcx>>| ty.super_fold_with(self))
256+
self.at
257+
.infcx
258+
.commit_if_ok(|_| {
259+
deeply_normalize_with_skipped_universes(
260+
self.at,
261+
ty,
262+
vec![None; ty.outer_exclusive_binder().as_usize()],
263+
)
264+
})
265+
.unwrap_or_else(|_: Vec<ScrubbedTraitError<'tcx>>| ty.super_fold_with(self))
262266
}
263267

264268
fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
265-
deeply_normalize_with_skipped_universes(
266-
self.at,
267-
ct,
268-
vec![None; ct.outer_exclusive_binder().as_usize()],
269-
)
270-
.unwrap_or_else(|_: Vec<ScrubbedTraitError<'tcx>>| ct.super_fold_with(self))
269+
self.at
270+
.infcx
271+
.commit_if_ok(|_| {
272+
deeply_normalize_with_skipped_universes(
273+
self.at,
274+
ct,
275+
vec![None; ct.outer_exclusive_binder().as_usize()],
276+
)
277+
})
278+
.unwrap_or_else(|_: Vec<ScrubbedTraitError<'tcx>>| ct.super_fold_with(self))
271279
}
272280
}

tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr

+7-5
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1-
error[E0277]: the trait bound `&str: AsExpression<<SelectInt as Expression>::SqlType>` is not satisfied
1+
error[E0277]: the trait bound `&str: AsExpression<Integer>` is not satisfied
22
--> $DIR/as_expression.rs:56:21
33
|
44
LL | SelectInt.check("bar");
5-
| ----- ^^^^^ the trait `AsExpression<<SelectInt as Expression>::SqlType>` is not implemented for `&str`
5+
| ----- ^^^^^ the trait `AsExpression<Integer>` is not implemented for `&str`
66
| |
77
| required by a bound introduced by this call
88
|
9-
= help: the trait `AsExpression<Text>` is implemented for `&str`
9+
= help: the trait `AsExpression<Integer>` is not implemented for `&str`
10+
but trait `AsExpression<Text>` is implemented for it
11+
= help: for that trait implementation, expected `Text`, found `Integer`
1012
note: required by a bound in `Foo::check`
1113
--> $DIR/as_expression.rs:47:12
1214
|
@@ -16,11 +18,11 @@ LL | where
1618
LL | T: AsExpression<Self::SqlType>,
1719
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::check`
1820

19-
error[E0271]: type mismatch resolving `<SelectInt as Expression>::SqlType == Text`
21+
error[E0271]: type mismatch resolving `Integer == Text`
2022
--> $DIR/as_expression.rs:56:5
2123
|
2224
LL | SelectInt.check("bar");
23-
| ^^^^^^^^^^^^^^^^^^^^^^ expected `Text`, found `Integer`
25+
| ^^^^^^^^^^^^^^^^^^^^^^ types differ
2426

2527
error: aborting due to 2 previous errors
2628

tests/ui/diagnostic_namespace/do_not_recommend/as_expression.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ impl<T> Foo for T where T: Expression {}
5454

5555
fn main() {
5656
SelectInt.check("bar");
57-
//[current]~^ ERROR the trait bound `&str: AsExpression<Integer>` is not satisfied
58-
//[next]~^^ the trait bound `&str: AsExpression<<SelectInt as Expression>::SqlType>` is not satisfied
57+
//~^ ERROR the trait bound `&str: AsExpression<Integer>` is not satisfied
5958
//[next]~| type mismatch
6059
}

tests/ui/traits/next-solver/async.fail.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error[E0271]: expected `{async block@$DIR/async.rs:12:17: 12:22}` to be a future that resolves to `i32`, but it resolves to `()`
1+
error[E0271]: type mismatch resolving `() == i32`
22
--> $DIR/async.rs:12:17
33
|
44
LL | needs_async(async {});
5-
| ----------- ^^^^^^^^ expected `i32`, found `()`
5+
| ----------- ^^^^^^^^ types differ
66
| |
77
| required by a bound introduced by this call
88
|

tests/ui/traits/next-solver/async.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ fn needs_async(_: impl Future<Output = i32>) {}
1010
#[cfg(fail)]
1111
fn main() {
1212
needs_async(async {});
13-
//[fail]~^ ERROR expected `{async block@$DIR/async.rs:12:17: 12:22}` to be a future that resolves to `i32`, but it resolves to `()`
13+
//[fail]~^ ERROR type mismatch resolving `() == i32`
1414
}
1515

1616
#[cfg(pass)]

tests/ui/traits/next-solver/more-object-bound.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ trait Trait: SuperTrait<A = <Self as SuperTrait>::B> {}
1010

1111
fn transmute<A, B>(x: A) -> B {
1212
foo::<A, B, dyn Trait<A = A, B = B>>(x)
13-
//~^ ERROR type mismatch resolving `<dyn Trait<A = A, B = B> as SuperTrait>::A == B`
13+
//~^ ERROR type mismatch resolving `A == B`
1414
}
1515

1616
fn foo<A, B, T: ?Sized>(x: T::A) -> B

tests/ui/traits/next-solver/more-object-bound.stderr

+2-10
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,9 @@
1-
error[E0271]: type mismatch resolving `<dyn Trait<A = A, B = B> as SuperTrait>::A == B`
1+
error[E0271]: type mismatch resolving `A == B`
22
--> $DIR/more-object-bound.rs:12:5
33
|
4-
LL | fn transmute<A, B>(x: A) -> B {
5-
| - - expected type parameter
6-
| |
7-
| found type parameter
84
LL | foo::<A, B, dyn Trait<A = A, B = B>>(x)
9-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `B`, found type parameter `A`
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ
106
|
11-
= note: expected type parameter `B`
12-
found type parameter `A`
13-
= note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
14-
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
157
= note: required because it appears within the type `dyn Trait<A = A, B = B>`
168
note: required by a bound in `foo`
179
--> $DIR/more-object-bound.rs:18:8

tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ fn needs_bar<S: Bar>() {}
1313

1414
fn test<T: Foo1<Assoc1 = <T as Foo2>::Assoc2> + Foo2<Assoc2 = <T as Foo1>::Assoc1>>() {
1515
needs_bar::<T::Assoc1>();
16-
//~^ ERROR the trait bound `<T as Foo1>::Assoc1: Bar` is not satisfied
16+
//~^ ERROR the trait bound `<T as Foo2>::Assoc2: Bar` is not satisfied
1717
}
1818

1919
fn main() {}

tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error[E0277]: the trait bound `<T as Foo1>::Assoc1: Bar` is not satisfied
1+
error[E0277]: the trait bound `<T as Foo2>::Assoc2: Bar` is not satisfied
22
--> $DIR/recursive-self-normalization-2.rs:15:17
33
|
44
LL | needs_bar::<T::Assoc1>();
5-
| ^^^^^^^^^ the trait `Bar` is not implemented for `<T as Foo1>::Assoc1`
5+
| ^^^^^^^^^ the trait `Bar` is not implemented for `<T as Foo2>::Assoc2`
66
|
77
note: required by a bound in `needs_bar`
88
--> $DIR/recursive-self-normalization-2.rs:12:17
@@ -11,7 +11,7 @@ LL | fn needs_bar<S: Bar>() {}
1111
| ^^^ required by this bound in `needs_bar`
1212
help: consider further restricting the associated type
1313
|
14-
LL | fn test<T: Foo1<Assoc1 = <T as Foo2>::Assoc2> + Foo2<Assoc2 = <T as Foo1>::Assoc1>>() where <T as Foo1>::Assoc1: Bar {
14+
LL | fn test<T: Foo1<Assoc1 = <T as Foo2>::Assoc2> + Foo2<Assoc2 = <T as Foo1>::Assoc1>>() where <T as Foo2>::Assoc2: Bar {
1515
| ++++++++++++++++++++++++++++++
1616

1717
error: aborting due to 1 previous error

0 commit comments

Comments
 (0)