Skip to content

Commit

Permalink
Rollup merge of rust-lang#124936 - lcnr:cool-beans, r=compiler-errors
Browse files Browse the repository at this point in the history
analyse visitor: build proof tree in probe

see inline comments

fixes rust-lang#124791
fixes rust-lang#124702

r? `@compiler-errors`
  • Loading branch information
matthiaskrgr authored May 9, 2024
2 parents 3847582 + feff752 commit b9c69f2
Show file tree
Hide file tree
Showing 8 changed files with 113 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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.
/// Adding any inference constraints which weren't present when originally
/// 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>>>(
infcx: &InferCtxt<'tcx>,
span: Span,
Expand Down
44 changes: 33 additions & 11 deletions compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,11 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
/// inference constraints, and optionally the args of an impl if this candidate
/// came from a `CandidateSource::Impl`. This function modifies the state of the
/// `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(
&self,
span: Span,
Expand Down Expand Up @@ -213,10 +218,23 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
};
let goal =
goal.with(infcx.tcx, ty::NormalizesTo { alias, term: unconstrained_term });
let proof_tree = EvalCtxt::enter_root(infcx, GenerateProofTree::Yes, |ecx| {
ecx.evaluate_goal_raw(GoalEvaluationKind::Root, GoalSource::Misc, goal)
})
.1;
// We have to use a `probe` here as evaluating a `NormalizesTo` can constrain the
// 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
// 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(
infcx,
self.goal.depth + 1,
Expand All @@ -225,13 +243,17 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
source,
)
}
_ => InspectGoal::new(
infcx,
self.goal.depth + 1,
infcx.evaluate_root_goal(goal, GenerateProofTree::Yes).1.unwrap(),
None,
source,
),
_ => {
// We're using a probe here as evaluating a goal could constrain
// inference variables by choosing one candidate. If we then recurse
// into another candidate who ends up with different inference
// constraints, we get an ICE if we already applied the constraints
// 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();

Expand Down
14 changes: 0 additions & 14 deletions tests/crashes/124702.rs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -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 = ();
}
Original file line number Diff line number Diff line change
@@ -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`
Original file line number Diff line number Diff line change
@@ -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`.
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ where
// entering the cycle from `A` fails, but would work if we were to use the cache
// result of `B<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() {
Expand Down
Original file line number Diff line number Diff line change
@@ -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
|
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
|
LL | impl<T: ?Sized, U: ?Sized, V: ?Sized, D: ?Sized> Trait<U, V, D> for A<T>
Expand All @@ -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>,
| -------------- unsatisfied trait bound introduced here
= 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`
--> $DIR/incompleteness-unstable-result.rs:51:28
|
LL | fn impls_trait<T: ?Sized + Trait<U, V, D>, U: ?Sized, V: ?Sized, D: ?Sized>() {}
| ^^^^^^^^^^^^^^ 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

Expand Down

0 comments on commit b9c69f2

Please sign in to comment.