diff options
| author | lcnr <rust@lcnr.de> | 2024-07-10 14:13:16 +0200 |
|---|---|---|
| committer | lcnr <rust@lcnr.de> | 2024-07-10 14:13:16 +0200 |
| commit | f77394fdf3f45188d3f110f72f31c4233d4d38eb (patch) | |
| tree | 84acf68a3a3272fccf6934aa2f37293d16afca10 /compiler/rustc_trait_selection/src | |
| parent | 0fdfb61795b40037955154638fe35f20b16c8e55 (diff) | |
| download | rust-f77394fdf3f45188d3f110f72f31c4233d4d38eb.tar.gz rust-f77394fdf3f45188d3f110f72f31c4233d4d38eb.zip | |
instantiate higher ranked goals in candidate selection
reverts #119820
Diffstat (limited to 'compiler/rustc_trait_selection/src')
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/select/mod.rs | 66 |
1 files changed, 12 insertions, 54 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 2c4ffdabf14..7a93f59f163 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -64,20 +64,6 @@ mod _match; mod candidate_assembly; mod confirmation; -/// Whether to consider the binder of higher ranked goals for the `leak_check` when -/// evaluating higher-ranked goals. See #119820 for more info. -/// -/// While this is a bit hacky, it is necessary to match the behavior of the new solver: -/// We eagerly instantiate binders in the new solver, outside of candidate selection, so -/// the leak check inside of candidates does not consider any bound vars from the higher -/// ranked goal. However, we do exit the binder once we're completely finished with a goal, -/// so the leak-check can be used in evaluate by causing nested higher-ranked goals to fail. -#[derive(Debug, Copy, Clone)] -enum LeakCheckHigherRankedGoal { - No, - Yes, -} - #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub enum IntercrateAmbiguityCause<'tcx> { DownstreamCrate { trait_ref: ty::TraitRef<'tcx>, self_ty: Option<Ty<'tcx>> }, @@ -402,10 +388,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let mut no_candidates_apply = true; for c in candidate_set.vec.iter() { - if self - .evaluate_candidate(stack, c, LeakCheckHigherRankedGoal::No)? - .may_apply() - { + if self.evaluate_candidate(stack, c)?.may_apply() { no_candidates_apply = false; break; } @@ -476,7 +459,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // is needed for specialization. Propagate overflow if it occurs. let mut candidates = candidates .into_iter() - .map(|c| match self.evaluate_candidate(stack, &c, LeakCheckHigherRankedGoal::No) { + .map(|c| match self.evaluate_candidate(stack, &c) { Ok(eval) if eval.may_apply() => { Ok(Some(EvaluatedCandidate { candidate: c, evaluation: eval })) } @@ -566,7 +549,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &PredicateObligation<'tcx>, ) -> Result<EvaluationResult, OverflowError> { debug_assert!(!self.infcx.next_trait_solver()); - self.evaluation_probe(|this, _outer_universe| { + self.evaluation_probe(|this| { let goal = this.infcx.resolve_vars_if_possible((obligation.predicate, obligation.param_env)); let mut result = this.evaluate_predicate_recursively( @@ -589,11 +572,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// `op`, but this can be overwritten if necessary. fn evaluation_probe( &mut self, - op: impl FnOnce(&mut Self, &mut ty::UniverseIndex) -> Result<EvaluationResult, OverflowError>, + op: impl FnOnce(&mut Self) -> Result<EvaluationResult, OverflowError>, ) -> Result<EvaluationResult, OverflowError> { self.infcx.probe(|snapshot| -> Result<EvaluationResult, OverflowError> { - let mut outer_universe = self.infcx.universe(); - let result = op(self, &mut outer_universe)?; + let outer_universe = self.infcx.universe(); + let result = op(self)?; match self.infcx.leak_check(outer_universe, Some(snapshot)) { Ok(()) => {} @@ -1254,7 +1237,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } match self.candidate_from_obligation(stack) { - Ok(Some(c)) => self.evaluate_candidate(stack, &c, LeakCheckHigherRankedGoal::Yes), + Ok(Some(c)) => self.evaluate_candidate(stack, &c), Ok(None) => Ok(EvaluatedToAmbig), Err(Overflow(OverflowError::Canonical)) => Err(OverflowError::Canonical), Err(..) => Ok(EvaluatedToErr), @@ -1279,10 +1262,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// Further evaluates `candidate` to decide whether all type parameters match and whether nested /// obligations are met. Returns whether `candidate` remains viable after this further /// scrutiny. - /// - /// Depending on the value of [LeakCheckHigherRankedGoal], we may ignore the binder of the goal - /// when eagerly detecting higher ranked region errors via the `leak_check`. See that enum for - /// more info. #[instrument( level = "debug", skip(self, stack), @@ -1293,25 +1272,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, stack: &TraitObligationStack<'o, 'tcx>, candidate: &SelectionCandidate<'tcx>, - leak_check_higher_ranked_goal: LeakCheckHigherRankedGoal, ) -> Result<EvaluationResult, OverflowError> { - let mut result = self.evaluation_probe(|this, outer_universe| { - // We eagerly instantiate higher ranked goals to prevent universe errors - // from impacting candidate selection. This matches the behavior of the new - // solver. This slightly weakens type inference. - // - // In case there are no unresolved type or const variables this - // should still not be necessary to select a unique impl as any overlap - // relying on a universe error from higher ranked goals should have resulted - // in an overlap error in coherence. - let p = self.infcx.enter_forall_and_leak_universe(stack.obligation.predicate); - let obligation = stack.obligation.with(this.tcx(), ty::Binder::dummy(p)); - match leak_check_higher_ranked_goal { - LeakCheckHigherRankedGoal::No => *outer_universe = self.infcx.universe(), - LeakCheckHigherRankedGoal::Yes => {} - } - - match this.confirm_candidate(&obligation, candidate.clone()) { + let mut result = self.evaluation_probe(|this| { + match this.confirm_candidate(stack.obligation, candidate.clone()) { Ok(selection) => { debug!(?selection); this.evaluate_predicates_recursively( @@ -1731,19 +1694,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }) .map_err(|_| ()) } + fn where_clause_may_apply<'o>( &mut self, stack: &TraitObligationStack<'o, 'tcx>, where_clause_trait_ref: ty::PolyTraitRef<'tcx>, ) -> Result<EvaluationResult, OverflowError> { - self.evaluation_probe(|this, outer_universe| { - // Eagerly instantiate higher ranked goals. - // - // See the comment in `evaluate_candidate` to see why. - let p = self.infcx.enter_forall_and_leak_universe(stack.obligation.predicate); - let obligation = stack.obligation.with(this.tcx(), ty::Binder::dummy(p)); - *outer_universe = self.infcx.universe(); - match this.match_where_clause_trait_ref(&obligation, where_clause_trait_ref) { + self.evaluation_probe(|this| { + match this.match_where_clause_trait_ref(stack.obligation, where_clause_trait_ref) { Ok(obligations) => this.evaluate_predicates_recursively(stack.list(), obligations), Err(()) => Ok(EvaluatedToErr), } |
