summary refs log tree commit diff
path: root/compiler/rustc_trait_selection/src
diff options
context:
space:
mode:
authorlcnr <rust@lcnr.de>2024-07-10 14:13:16 +0200
committerlcnr <rust@lcnr.de>2024-07-10 14:13:16 +0200
commitf77394fdf3f45188d3f110f72f31c4233d4d38eb (patch)
tree84acf68a3a3272fccf6934aa2f37293d16afca10 /compiler/rustc_trait_selection/src
parent0fdfb61795b40037955154638fe35f20b16c8e55 (diff)
downloadrust-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.rs66
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),
             }