mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-15 13:36:49 +00:00
Deeply normalize obligations in BestObligation
This commit is contained in:
parent
62d5fb85ac
commit
decd7ecd1e
@ -13,9 +13,9 @@ use rustc_next_trait_solver::solve::{GenerateProofTree, SolverDelegateEvalExt as
|
||||
use rustc_type_ir::solve::NoSolution;
|
||||
use tracing::{instrument, trace};
|
||||
|
||||
use crate::solve::Certainty;
|
||||
use crate::solve::delegate::SolverDelegate;
|
||||
use crate::solve::inspect::{self, ProofTreeInferCtxtExt, ProofTreeVisitor};
|
||||
use crate::solve::{Certainty, deeply_normalize_for_diagnostics};
|
||||
use crate::traits::{FulfillmentError, FulfillmentErrorCode, wf};
|
||||
|
||||
pub(super) fn fulfillment_error_for_no_solution<'tcx>(
|
||||
@ -151,7 +151,7 @@ fn find_best_leaf_obligation<'tcx>(
|
||||
//
|
||||
// We should probably fix the visitor to not do so instead, as this also
|
||||
// means the leaf obligation may be incorrect.
|
||||
infcx
|
||||
let obligation = infcx
|
||||
.fudge_inference_if_ok(|| {
|
||||
infcx
|
||||
.visit_proof_tree(
|
||||
@ -161,7 +161,8 @@ fn find_best_leaf_obligation<'tcx>(
|
||||
.break_value()
|
||||
.ok_or(())
|
||||
})
|
||||
.unwrap_or(obligation)
|
||||
.unwrap_or(obligation);
|
||||
deeply_normalize_for_diagnostics(infcx, obligation.param_env, obligation)
|
||||
}
|
||||
|
||||
struct BestObligation<'tcx> {
|
||||
@ -298,7 +299,7 @@ impl<'tcx> BestObligation<'tcx> {
|
||||
/// `NormalizesTo` goal, so we don't fall back to the rigid projection check
|
||||
/// that should catch when a projection goal fails due to an unsatisfied trait
|
||||
/// goal.
|
||||
fn detect_error_in_higher_ranked_projection(
|
||||
fn detect_trait_error_in_higher_ranked_projection(
|
||||
&mut self,
|
||||
goal: &inspect::InspectGoal<'_, 'tcx>,
|
||||
) -> ControlFlow<PredicateObligation<'tcx>> {
|
||||
@ -307,7 +308,13 @@ impl<'tcx> BestObligation<'tcx> {
|
||||
&& !projection_clause.bound_vars().is_empty()
|
||||
{
|
||||
let pred = projection_clause.map_bound(|proj| proj.projection_term.trait_ref(tcx));
|
||||
self.with_derived_obligation(self.obligation.with(tcx, pred), |this| {
|
||||
let obligation = Obligation::new(
|
||||
tcx,
|
||||
self.obligation.cause.clone(),
|
||||
goal.goal().param_env,
|
||||
deeply_normalize_for_diagnostics(goal.infcx(), goal.goal().param_env, pred),
|
||||
);
|
||||
self.with_derived_obligation(obligation, |this| {
|
||||
goal.infcx().visit_proof_tree_at_depth(
|
||||
goal.goal().with(tcx, pred),
|
||||
goal.depth() + 1,
|
||||
@ -526,7 +533,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
|
||||
)?;
|
||||
}
|
||||
|
||||
self.detect_error_in_higher_ranked_projection(goal)?;
|
||||
self.detect_trait_error_in_higher_ranked_projection(goal)?;
|
||||
|
||||
ControlFlow::Break(self.obligation.clone())
|
||||
}
|
||||
|
@ -253,20 +253,28 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for DeeplyNormalizeForDiagnosticsFolder<'_,
|
||||
}
|
||||
|
||||
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
deeply_normalize_with_skipped_universes(
|
||||
self.at,
|
||||
ty,
|
||||
vec![None; ty.outer_exclusive_binder().as_usize()],
|
||||
)
|
||||
.unwrap_or_else(|_: Vec<ScrubbedTraitError<'tcx>>| ty.super_fold_with(self))
|
||||
let infcx = self.at.infcx;
|
||||
infcx
|
||||
.commit_if_ok(|_| {
|
||||
deeply_normalize_with_skipped_universes(
|
||||
self.at,
|
||||
ty,
|
||||
vec![None; ty.outer_exclusive_binder().as_usize()],
|
||||
)
|
||||
})
|
||||
.unwrap_or_else(|_: Vec<ScrubbedTraitError<'tcx>>| ty.super_fold_with(self))
|
||||
}
|
||||
|
||||
fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
|
||||
deeply_normalize_with_skipped_universes(
|
||||
self.at,
|
||||
ct,
|
||||
vec![None; ct.outer_exclusive_binder().as_usize()],
|
||||
)
|
||||
.unwrap_or_else(|_: Vec<ScrubbedTraitError<'tcx>>| ct.super_fold_with(self))
|
||||
let infcx = self.at.infcx;
|
||||
infcx
|
||||
.commit_if_ok(|_| {
|
||||
deeply_normalize_with_skipped_universes(
|
||||
self.at,
|
||||
ct,
|
||||
vec![None; ct.outer_exclusive_binder().as_usize()],
|
||||
)
|
||||
})
|
||||
.unwrap_or_else(|_: Vec<ScrubbedTraitError<'tcx>>| ct.super_fold_with(self))
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,14 @@
|
||||
error[E0277]: the trait bound `&str: AsExpression<<SelectInt as Expression>::SqlType>` is not satisfied
|
||||
error[E0277]: the trait bound `&str: AsExpression<Integer>` is not satisfied
|
||||
--> $DIR/as_expression.rs:56:21
|
||||
|
|
||||
LL | SelectInt.check("bar");
|
||||
| ----- ^^^^^ the trait `AsExpression<<SelectInt as Expression>::SqlType>` is not implemented for `&str`
|
||||
| ----- ^^^^^ the trait `AsExpression<Integer>` is not implemented for `&str`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= help: the trait `AsExpression<Text>` is implemented for `&str`
|
||||
= help: the trait `AsExpression<Integer>` is not implemented for `&str`
|
||||
but trait `AsExpression<Text>` is implemented for it
|
||||
= help: for that trait implementation, expected `Text`, found `Integer`
|
||||
note: required by a bound in `Foo::check`
|
||||
--> $DIR/as_expression.rs:47:12
|
||||
|
|
||||
@ -16,11 +18,11 @@ LL | where
|
||||
LL | T: AsExpression<Self::SqlType>,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::check`
|
||||
|
||||
error[E0271]: type mismatch resolving `<SelectInt as Expression>::SqlType == Text`
|
||||
error[E0271]: type mismatch resolving `Integer == Text`
|
||||
--> $DIR/as_expression.rs:56:5
|
||||
|
|
||||
LL | SelectInt.check("bar");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ expected `Text`, found `Integer`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ types differ
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -54,7 +54,6 @@ impl<T> Foo for T where T: Expression {}
|
||||
|
||||
fn main() {
|
||||
SelectInt.check("bar");
|
||||
//[current]~^ ERROR the trait bound `&str: AsExpression<Integer>` is not satisfied
|
||||
//[next]~^^ ERROR the trait bound `&str: AsExpression<<SelectInt as Expression>::SqlType>` is not satisfied
|
||||
//~^ ERROR the trait bound `&str: AsExpression<Integer>` is not satisfied
|
||||
//[next]~| ERROR type mismatch
|
||||
}
|
||||
|
@ -6,30 +6,134 @@ LL | #![feature(const_trait_impl, generic_const_exprs)]
|
||||
|
|
||||
= help: remove one of these features
|
||||
|
||||
error[E0277]: the trait bound `T: const Trait` is not satisfied
|
||||
--> $DIR/unsatisfied-const-trait-bound.rs:29:37
|
||||
error[E0391]: cycle detected when evaluating type-level constant
|
||||
--> $DIR/unsatisfied-const-trait-bound.rs:29:35
|
||||
|
|
||||
LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
|
||||
| ^
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
note: ...which requires const-evaluating + checking `accept0::{constant#0}`...
|
||||
--> $DIR/unsatisfied-const-trait-bound.rs:29:35
|
||||
|
|
||||
LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
|
||||
| ^^^^^^^^^^^^^
|
||||
note: ...which requires caching mir of `accept0::{constant#0}` for CTFE...
|
||||
--> $DIR/unsatisfied-const-trait-bound.rs:29:35
|
||||
|
|
||||
LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
|
||||
| ^^^^^^^^^^^^^
|
||||
note: ...which requires elaborating drops for `accept0::{constant#0}`...
|
||||
--> $DIR/unsatisfied-const-trait-bound.rs:29:35
|
||||
|
|
||||
LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
|
||||
| ^^^^^^^^^^^^^
|
||||
note: ...which requires borrow-checking `accept0::{constant#0}`...
|
||||
--> $DIR/unsatisfied-const-trait-bound.rs:29:35
|
||||
|
|
||||
LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
|
||||
| ^^^^^^^^^^^^^
|
||||
note: ...which requires promoting constants in MIR for `accept0::{constant#0}`...
|
||||
--> $DIR/unsatisfied-const-trait-bound.rs:29:35
|
||||
|
|
||||
LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
|
||||
| ^^^^^^^^^^^^^
|
||||
note: ...which requires const checking `accept0::{constant#0}`...
|
||||
--> $DIR/unsatisfied-const-trait-bound.rs:29:35
|
||||
|
|
||||
LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
|
||||
| ^^^^^^^^^^^^^
|
||||
note: ...which requires building MIR for `accept0::{constant#0}`...
|
||||
--> $DIR/unsatisfied-const-trait-bound.rs:29:35
|
||||
|
|
||||
LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
|
||||
| ^^^^^^^^^^^^^
|
||||
note: ...which requires building an abstract representation for `accept0::{constant#0}`...
|
||||
--> $DIR/unsatisfied-const-trait-bound.rs:29:35
|
||||
|
|
||||
LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
|
||||
| ^^^^^^^^^^^^^
|
||||
note: ...which requires building THIR for `accept0::{constant#0}`...
|
||||
--> $DIR/unsatisfied-const-trait-bound.rs:29:35
|
||||
|
|
||||
LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
|
||||
| ^^^^^^^^^^^^^
|
||||
note: ...which requires type-checking `accept0::{constant#0}`...
|
||||
--> $DIR/unsatisfied-const-trait-bound.rs:29:35
|
||||
|
|
||||
LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
|
||||
| ^^^^^^^^^^^^^
|
||||
= note: ...which again requires evaluating type-level constant, completing the cycle
|
||||
note: cycle used when checking that `accept0` is well-formed
|
||||
--> $DIR/unsatisfied-const-trait-bound.rs:29:1
|
||||
|
|
||||
LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
|
||||
|
||||
error[E0277]: the trait bound `T: const Trait` is not satisfied
|
||||
--> $DIR/unsatisfied-const-trait-bound.rs:33:50
|
||||
error[E0391]: cycle detected when caching mir of `accept1::{constant#0}` for CTFE
|
||||
--> $DIR/unsatisfied-const-trait-bound.rs:33:48
|
||||
|
|
||||
LL | const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {}
|
||||
| ^
|
||||
|
||||
error[E0277]: the trait bound `Ty: const Trait` is not satisfied
|
||||
--> $DIR/unsatisfied-const-trait-bound.rs:22:15
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
LL | require::<Ty>();
|
||||
| ^^
|
||||
note: ...which requires elaborating drops for `accept1::{constant#0}`...
|
||||
--> $DIR/unsatisfied-const-trait-bound.rs:33:48
|
||||
|
|
||||
note: required by a bound in `require`
|
||||
--> $DIR/unsatisfied-const-trait-bound.rs:8:15
|
||||
LL | const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {}
|
||||
| ^^^^^^^^^^^^^
|
||||
note: ...which requires borrow-checking `accept1::{constant#0}`...
|
||||
--> $DIR/unsatisfied-const-trait-bound.rs:33:48
|
||||
|
|
||||
LL | fn require<T: const Trait>() {}
|
||||
| ^^^^^^^^^^^ required by this bound in `require`
|
||||
LL | const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {}
|
||||
| ^^^^^^^^^^^^^
|
||||
note: ...which requires promoting constants in MIR for `accept1::{constant#0}`...
|
||||
--> $DIR/unsatisfied-const-trait-bound.rs:33:48
|
||||
|
|
||||
LL | const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {}
|
||||
| ^^^^^^^^^^^^^
|
||||
note: ...which requires const checking `accept1::{constant#0}`...
|
||||
--> $DIR/unsatisfied-const-trait-bound.rs:33:48
|
||||
|
|
||||
LL | const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {}
|
||||
| ^^^^^^^^^^^^^
|
||||
note: ...which requires building MIR for `accept1::{constant#0}`...
|
||||
--> $DIR/unsatisfied-const-trait-bound.rs:33:48
|
||||
|
|
||||
LL | const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {}
|
||||
| ^^^^^^^^^^^^^
|
||||
note: ...which requires building an abstract representation for `accept1::{constant#0}`...
|
||||
--> $DIR/unsatisfied-const-trait-bound.rs:33:48
|
||||
|
|
||||
LL | const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {}
|
||||
| ^^^^^^^^^^^^^
|
||||
note: ...which requires building THIR for `accept1::{constant#0}`...
|
||||
--> $DIR/unsatisfied-const-trait-bound.rs:33:48
|
||||
|
|
||||
LL | const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {}
|
||||
| ^^^^^^^^^^^^^
|
||||
note: ...which requires type-checking `accept1::{constant#0}`...
|
||||
--> $DIR/unsatisfied-const-trait-bound.rs:33:48
|
||||
|
|
||||
LL | const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {}
|
||||
| ^^^^^^^^^^^^^
|
||||
note: ...which requires evaluating type-level constant...
|
||||
--> $DIR/unsatisfied-const-trait-bound.rs:33:48
|
||||
|
|
||||
LL | const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {}
|
||||
| ^^^^^^^^^^^^^
|
||||
note: ...which requires const-evaluating + checking `accept1::{constant#0}`...
|
||||
--> $DIR/unsatisfied-const-trait-bound.rs:33:48
|
||||
|
|
||||
LL | const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {}
|
||||
| ^^^^^^^^^^^^^
|
||||
= note: ...which again requires caching mir of `accept1::{constant#0}` for CTFE, completing the cycle
|
||||
note: cycle used when const-evaluating + checking `accept1::{constant#0}`
|
||||
--> $DIR/unsatisfied-const-trait-bound.rs:33:48
|
||||
|
|
||||
LL | const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {}
|
||||
| ^^^^^^^^^^^^^
|
||||
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
For more information about this error, try `rustc --explain E0391`.
|
||||
|
@ -1,8 +1,8 @@
|
||||
error[E0271]: expected `{async block@$DIR/async.rs:12:17: 12:22}` to be a future that resolves to `i32`, but it resolves to `()`
|
||||
error[E0271]: type mismatch resolving `() == i32`
|
||||
--> $DIR/async.rs:12:17
|
||||
|
|
||||
LL | needs_async(async {});
|
||||
| ----------- ^^^^^^^^ expected `i32`, found `()`
|
||||
| ----------- ^^^^^^^^ types differ
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
|
@ -10,7 +10,7 @@ fn needs_async(_: impl Future<Output = i32>) {}
|
||||
#[cfg(fail)]
|
||||
fn main() {
|
||||
needs_async(async {});
|
||||
//[fail]~^ ERROR expected `{async block@$DIR/async.rs:12:17: 12:22}` to be a future that resolves to `i32`, but it resolves to `()`
|
||||
//[fail]~^ ERROR type mismatch resolving `() == i32`
|
||||
}
|
||||
|
||||
#[cfg(pass)]
|
||||
|
@ -10,7 +10,7 @@ trait Trait: SuperTrait<A = <Self as SuperTrait>::B> {}
|
||||
|
||||
fn transmute<A, B>(x: A) -> B {
|
||||
foo::<A, B, dyn Trait<A = A, B = B>>(x)
|
||||
//~^ ERROR type mismatch resolving `<dyn Trait<A = A, B = B> as SuperTrait>::A == B`
|
||||
//~^ ERROR type mismatch resolving `A == B`
|
||||
}
|
||||
|
||||
fn foo<A, B, T: ?Sized>(x: T::A) -> B
|
||||
|
@ -1,17 +1,9 @@
|
||||
error[E0271]: type mismatch resolving `<dyn Trait<A = A, B = B> as SuperTrait>::A == B`
|
||||
error[E0271]: type mismatch resolving `A == B`
|
||||
--> $DIR/more-object-bound.rs:12:5
|
||||
|
|
||||
LL | fn transmute<A, B>(x: A) -> B {
|
||||
| - - expected type parameter
|
||||
| |
|
||||
| found type parameter
|
||||
LL | foo::<A, B, dyn Trait<A = A, B = B>>(x)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `B`, found type parameter `A`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ
|
||||
|
|
||||
= note: expected type parameter `B`
|
||||
found type parameter `A`
|
||||
= note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
|
||||
= note: required because it appears within the type `dyn Trait<A = A, B = B>`
|
||||
note: required by a bound in `foo`
|
||||
--> $DIR/more-object-bound.rs:18:8
|
||||
|
@ -13,7 +13,7 @@ fn needs_bar<S: Bar>() {}
|
||||
|
||||
fn test<T: Foo1<Assoc1 = <T as Foo2>::Assoc2> + Foo2<Assoc2 = <T as Foo1>::Assoc1>>() {
|
||||
needs_bar::<T::Assoc1>();
|
||||
//~^ ERROR the trait bound `<T as Foo1>::Assoc1: Bar` is not satisfied
|
||||
//~^ ERROR the trait bound `<T as Foo2>::Assoc2: Bar` is not satisfied
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,8 +1,8 @@
|
||||
error[E0277]: the trait bound `<T as Foo1>::Assoc1: Bar` is not satisfied
|
||||
error[E0277]: the trait bound `<T as Foo2>::Assoc2: Bar` is not satisfied
|
||||
--> $DIR/recursive-self-normalization-2.rs:15:17
|
||||
|
|
||||
LL | needs_bar::<T::Assoc1>();
|
||||
| ^^^^^^^^^ the trait `Bar` is not implemented for `<T as Foo1>::Assoc1`
|
||||
| ^^^^^^^^^ the trait `Bar` is not implemented for `<T as Foo2>::Assoc2`
|
||||
|
|
||||
note: required by a bound in `needs_bar`
|
||||
--> $DIR/recursive-self-normalization-2.rs:12:17
|
||||
@ -11,7 +11,7 @@ LL | fn needs_bar<S: Bar>() {}
|
||||
| ^^^ required by this bound in `needs_bar`
|
||||
help: consider further restricting the associated type
|
||||
|
|
||||
LL | fn test<T: Foo1<Assoc1 = <T as Foo2>::Assoc2> + Foo2<Assoc2 = <T as Foo1>::Assoc1>>() where <T as Foo1>::Assoc1: Bar {
|
||||
LL | fn test<T: Foo1<Assoc1 = <T as Foo2>::Assoc2> + Foo2<Assoc2 = <T as Foo1>::Assoc1>>() where <T as Foo2>::Assoc2: Bar {
|
||||
| ++++++++++++++++++++++++++++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
Loading…
Reference in New Issue
Block a user