Rollup merge of #124936 - lcnr:cool-beans, r=compiler-errors
analyse visitor: build proof tree in probe see inline comments fixes #124791 fixes #124702 r? ```@compiler-errors```
This commit is contained in:
commit
43ddd1d963
8 changed files with 113 additions and 34 deletions
|
@ -409,6 +409,7 @@ pub(in crate::solve) fn make_canonical_state<'tcx, T: TypeFoldable<TyCtxt<'tcx>>
|
||||||
/// This currently assumes that unifying the var values trivially succeeds.
|
/// This currently assumes that unifying the var values trivially succeeds.
|
||||||
/// Adding any inference constraints which weren't present when originally
|
/// Adding any inference constraints which weren't present when originally
|
||||||
/// computing the canonical query can result in bugs.
|
/// computing the canonical query can result in bugs.
|
||||||
|
#[instrument(level = "debug", skip(infcx, span, param_env))]
|
||||||
pub(in crate::solve) fn instantiate_canonical_state<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
|
pub(in crate::solve) fn instantiate_canonical_state<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
|
||||||
infcx: &InferCtxt<'tcx>,
|
infcx: &InferCtxt<'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
|
|
|
@ -146,6 +146,11 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
|
||||||
/// inference constraints, and optionally the args of an impl if this candidate
|
/// inference constraints, and optionally the args of an impl if this candidate
|
||||||
/// came from a `CandidateSource::Impl`. This function modifies the state of the
|
/// came from a `CandidateSource::Impl`. This function modifies the state of the
|
||||||
/// `infcx`.
|
/// `infcx`.
|
||||||
|
#[instrument(
|
||||||
|
level = "debug",
|
||||||
|
skip_all,
|
||||||
|
fields(goal = ?self.goal.goal, nested_goals = ?self.nested_goals)
|
||||||
|
)]
|
||||||
pub fn instantiate_nested_goals_and_opt_impl_args(
|
pub fn instantiate_nested_goals_and_opt_impl_args(
|
||||||
&self,
|
&self,
|
||||||
span: Span,
|
span: Span,
|
||||||
|
@ -213,10 +218,23 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
|
||||||
};
|
};
|
||||||
let goal =
|
let goal =
|
||||||
goal.with(infcx.tcx, ty::NormalizesTo { alias, term: unconstrained_term });
|
goal.with(infcx.tcx, ty::NormalizesTo { alias, term: unconstrained_term });
|
||||||
let proof_tree = EvalCtxt::enter_root(infcx, GenerateProofTree::Yes, |ecx| {
|
// We have to use a `probe` here as evaluating a `NormalizesTo` can constrain the
|
||||||
ecx.evaluate_goal_raw(GoalEvaluationKind::Root, GoalSource::Misc, goal)
|
// expected term. This means that candidates which only fail due to nested goals
|
||||||
})
|
// and which normalize to a different term then the final result could ICE: when
|
||||||
.1;
|
// building their proof tree, the expected term was unconstrained, but when
|
||||||
|
// instantiating the candidate it is already constrained to the result of another
|
||||||
|
// candidate.
|
||||||
|
let proof_tree = infcx
|
||||||
|
.probe(|_| {
|
||||||
|
EvalCtxt::enter_root(infcx, GenerateProofTree::Yes, |ecx| {
|
||||||
|
ecx.evaluate_goal_raw(
|
||||||
|
GoalEvaluationKind::Root,
|
||||||
|
GoalSource::Misc,
|
||||||
|
goal,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.1;
|
||||||
InspectGoal::new(
|
InspectGoal::new(
|
||||||
infcx,
|
infcx,
|
||||||
self.goal.depth + 1,
|
self.goal.depth + 1,
|
||||||
|
@ -225,13 +243,17 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
|
||||||
source,
|
source,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
_ => InspectGoal::new(
|
_ => {
|
||||||
infcx,
|
// We're using a probe here as evaluating a goal could constrain
|
||||||
self.goal.depth + 1,
|
// inference variables by choosing one candidate. If we then recurse
|
||||||
infcx.evaluate_root_goal(goal, GenerateProofTree::Yes).1.unwrap(),
|
// into another candidate who ends up with different inference
|
||||||
None,
|
// constraints, we get an ICE if we already applied the constraints
|
||||||
source,
|
// from the chosen candidate.
|
||||||
),
|
let proof_tree = infcx
|
||||||
|
.probe(|_| infcx.evaluate_root_goal(goal, GenerateProofTree::Yes).1)
|
||||||
|
.unwrap();
|
||||||
|
InspectGoal::new(infcx, self.goal.depth + 1, proof_tree, None, source)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
//@ known-bug: rust-lang/rust#124702
|
|
||||||
//@ compile-flags: -Znext-solver=coherence
|
|
||||||
trait X {}
|
|
||||||
|
|
||||||
trait Z {
|
|
||||||
type Assoc: Y;
|
|
||||||
}
|
|
||||||
struct A<T>(T);
|
|
||||||
|
|
||||||
impl<T: X> Z for A<T> {
|
|
||||||
type Assoc = T;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> From<<A<A<T>> as Z>::Assoc> for T {}
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
//@ compile-flags: -Znext-solver=coherence
|
||||||
|
//@ check-pass
|
||||||
|
|
||||||
|
// A regression test for #124791. Computing ambiguity causes
|
||||||
|
// for the overlap of the `ToString` impls caused an ICE.
|
||||||
|
#![crate_type = "lib"]
|
||||||
|
#![feature(min_specialization)]
|
||||||
|
trait Display {}
|
||||||
|
|
||||||
|
trait ToOwned {
|
||||||
|
type Owned;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> ToOwned for T {
|
||||||
|
type Owned = T;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Cow<B: ?Sized>(B);
|
||||||
|
|
||||||
|
impl<B: ?Sized> Display for Cow<B>
|
||||||
|
where
|
||||||
|
B: ToOwned,
|
||||||
|
B::Owned: Display,
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for () {}
|
||||||
|
|
||||||
|
trait ToString {
|
||||||
|
fn to_string();
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Display + ?Sized> ToString for T {
|
||||||
|
default fn to_string() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToString for Cow<str> {
|
||||||
|
fn to_string() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToOwned for str {
|
||||||
|
type Owned = ();
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
//@ compile-flags: -Znext-solver=coherence
|
||||||
|
|
||||||
|
// A regression test for #124791. Computing ambiguity causes
|
||||||
|
// for the overlap of the `ToString` impls caused an ICE.
|
||||||
|
#![crate_type = "lib"]
|
||||||
|
trait ToOwned {
|
||||||
|
type Owned;
|
||||||
|
}
|
||||||
|
impl<T> ToOwned for T {
|
||||||
|
type Owned = u8;
|
||||||
|
}
|
||||||
|
impl ToOwned for str {
|
||||||
|
type Owned = i8;
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Overlap {}
|
||||||
|
impl<T: ToOwned<Owned = i8> + ?Sized> Overlap for T {}
|
||||||
|
impl Overlap for str {}
|
||||||
|
//~^ ERROR conflicting implementations of trait `Overlap`
|
|
@ -0,0 +1,11 @@
|
||||||
|
error[E0119]: conflicting implementations of trait `Overlap` for type `str`
|
||||||
|
--> $DIR/ambiguity-causes-canonical-state-ice-2.rs:18:1
|
||||||
|
|
|
||||||
|
LL | impl<T: ToOwned<Owned = i8> + ?Sized> Overlap for T {}
|
||||||
|
| --------------------------------------------------- first implementation here
|
||||||
|
LL | impl Overlap for str {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `str`
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0119`.
|
|
@ -61,7 +61,7 @@ where
|
||||||
// entering the cycle from `A` fails, but would work if we were to use the cache
|
// entering the cycle from `A` fails, but would work if we were to use the cache
|
||||||
// result of `B<X>`.
|
// result of `B<X>`.
|
||||||
impls_trait::<A<X>, _, _, _>();
|
impls_trait::<A<X>, _, _, _>();
|
||||||
//~^ ERROR the trait bound `A<X>: Trait<i32, u8, u8>` is not satisfied
|
//~^ ERROR the trait bound `A<X>: Trait<_, _, _>` is not satisfied
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
error[E0277]: the trait bound `A<X>: Trait<i32, u8, u8>` is not satisfied
|
error[E0277]: the trait bound `A<X>: Trait<_, _, _>` is not satisfied
|
||||||
--> $DIR/incompleteness-unstable-result.rs:63:19
|
--> $DIR/incompleteness-unstable-result.rs:63:19
|
||||||
|
|
|
|
||||||
LL | impls_trait::<A<X>, _, _, _>();
|
LL | impls_trait::<A<X>, _, _, _>();
|
||||||
| ^^^^ the trait `Trait<i32, u8, u8>` is not implemented for `A<X>`, which is required by `A<X>: Trait<_, _, _>`
|
| ^^^^ the trait `Trait<_, _, _>` is not implemented for `A<X>`, which is required by `A<X>: Trait<_, _, _>`
|
||||||
|
|
|
|
||||||
note: required for `A<X>` to implement `Trait<i32, u8, u8>`
|
= help: the trait `Trait<U, V, D>` is implemented for `A<T>`
|
||||||
|
note: required for `A<X>` to implement `Trait<_, _, _>`
|
||||||
--> $DIR/incompleteness-unstable-result.rs:32:50
|
--> $DIR/incompleteness-unstable-result.rs:32:50
|
||||||
|
|
|
|
||||||
LL | impl<T: ?Sized, U: ?Sized, V: ?Sized, D: ?Sized> Trait<U, V, D> for A<T>
|
LL | impl<T: ?Sized, U: ?Sized, V: ?Sized, D: ?Sized> Trait<U, V, D> for A<T>
|
||||||
|
@ -13,16 +14,12 @@ LL | impl<T: ?Sized, U: ?Sized, V: ?Sized, D: ?Sized> Trait<U, V, D> for A<T>
|
||||||
LL | A<T>: Trait<U, D, V>,
|
LL | A<T>: Trait<U, D, V>,
|
||||||
| -------------- unsatisfied trait bound introduced here
|
| -------------- unsatisfied trait bound introduced here
|
||||||
= note: 8 redundant requirements hidden
|
= note: 8 redundant requirements hidden
|
||||||
= note: required for `A<X>` to implement `Trait<i32, u8, u8>`
|
= note: required for `A<X>` to implement `Trait<_, _, _>`
|
||||||
note: required by a bound in `impls_trait`
|
note: required by a bound in `impls_trait`
|
||||||
--> $DIR/incompleteness-unstable-result.rs:51:28
|
--> $DIR/incompleteness-unstable-result.rs:51:28
|
||||||
|
|
|
|
||||||
LL | fn impls_trait<T: ?Sized + Trait<U, V, D>, U: ?Sized, V: ?Sized, D: ?Sized>() {}
|
LL | fn impls_trait<T: ?Sized + Trait<U, V, D>, U: ?Sized, V: ?Sized, D: ?Sized>() {}
|
||||||
| ^^^^^^^^^^^^^^ required by this bound in `impls_trait`
|
| ^^^^^^^^^^^^^^ required by this bound in `impls_trait`
|
||||||
help: consider extending the `where` clause, but there might be an alternative better way to express this requirement
|
|
||||||
|
|
|
||||||
LL | X: IncompleteGuidance<u32, i16>, A<X>: Trait<i32, u8, u8>
|
|
||||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue