diff options
| author | lcnr <rust@lcnr.de> | 2024-05-09 17:11:51 +0000 |
|---|---|---|
| committer | lcnr <rust@lcnr.de> | 2024-05-09 17:29:53 +0000 |
| commit | 83e6da0be5e0e7cec8326ad5c4ba463299d32eea (patch) | |
| tree | 964cf7496871933227693d45a005c28c7b014439 /compiler/rustc_trait_selection/src | |
| parent | 8c7c151a7a03d92cc5c75c49aa82a658ec1fe4ff (diff) | |
analyse visitor: build proof tree in probe
Diffstat (limited to 'compiler/rustc_trait_selection/src')
| -rw-r--r-- | compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/solve/inspect/analyse.rs | 44 |
2 files changed, 34 insertions, 11 deletions
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs index 5f73432750d..41b304ec538 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs @@ -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, diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index fa4323a3a94..71ae410a03f 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -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, @@ -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, @@ -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(); |
