diff options
Diffstat (limited to 'compiler/rustc_trait_selection/src/solve/mod.rs')
| -rw-r--r-- | compiler/rustc_trait_selection/src/solve/mod.rs | 117 |
1 files changed, 50 insertions, 67 deletions
diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index 5cda9da3c5a..4c87d36ca0d 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -17,7 +17,6 @@ use rustc_hir::def_id::DefId; use rustc_infer::infer::canonical::{Canonical, CanonicalVarValues}; -use rustc_infer::infer::{DefineOpaqueTypes, InferOk}; use rustc_infer::traits::query::NoSolution; use rustc_middle::traits::solve::{ CanonicalGoal, CanonicalResponse, Certainty, ExternalConstraints, ExternalConstraintsData, @@ -101,11 +100,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { // That won't actually reflect in the query response, so it seems moot. self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) } else { - let InferOk { value: (), obligations } = self - .infcx - .at(&ObligationCause::dummy(), goal.param_env) - .sub(DefineOpaqueTypes::No, goal.predicate.a, goal.predicate.b)?; - self.add_goals(obligations.into_iter().map(|pred| pred.into())); + self.sub(goal.param_env, goal.predicate.a, goal.predicate.b)?; self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } } @@ -161,44 +156,41 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { goal: Goal<'tcx, (ty::Term<'tcx>, ty::Term<'tcx>, ty::AliasRelationDirection)>, ) -> QueryResult<'tcx> { let tcx = self.tcx(); - - let evaluate_normalizes_to = |ecx: &mut EvalCtxt<'_, 'tcx>, alias, other, direction| { - debug!("evaluate_normalizes_to(alias={:?}, other={:?})", alias, other); - let result = ecx.probe(|ecx| { - let other = match direction { - // This is purely an optimization. - ty::AliasRelationDirection::Equate => other, - - ty::AliasRelationDirection::Subtype | ty::AliasRelationDirection::Supertype => { - let fresh = ecx.next_term_infer_of_kind(other); - let (sub, sup) = if direction == ty::AliasRelationDirection::Subtype { - (fresh, other) - } else { - (other, fresh) - }; - ecx.add_goals( - ecx.infcx - .at(&ObligationCause::dummy(), goal.param_env) - .sub(DefineOpaqueTypes::No, sub, sup)? - .into_obligations() - .into_iter() - .map(|o| o.into()), - ); - fresh - } - }; - ecx.add_goal(goal.with( - tcx, - ty::Binder::dummy(ty::ProjectionPredicate { - projection_ty: alias, - term: other, - }), - )); - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - }); - debug!("evaluate_normalizes_to({alias}, {other}, {direction:?}) -> {result:?}"); - result - }; + // We may need to invert the alias relation direction if dealing an alias on the RHS. + enum Invert { + No, + Yes, + } + let evaluate_normalizes_to = + |ecx: &mut EvalCtxt<'_, 'tcx>, alias, other, direction, invert| { + debug!("evaluate_normalizes_to(alias={:?}, other={:?})", alias, other); + let result = ecx.probe(|ecx| { + let other = match direction { + // This is purely an optimization. + ty::AliasRelationDirection::Equate => other, + + ty::AliasRelationDirection::Subtype => { + let fresh = ecx.next_term_infer_of_kind(other); + let (sub, sup) = match invert { + Invert::No => (fresh, other), + Invert::Yes => (other, fresh), + }; + ecx.sub(goal.param_env, sub, sup)?; + fresh + } + }; + ecx.add_goal(goal.with( + tcx, + ty::Binder::dummy(ty::ProjectionPredicate { + projection_ty: alias, + term: other, + }), + )); + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + }); + debug!("evaluate_normalizes_to({alias}, {other}, {direction:?}) -> {result:?}"); + result + }; let (lhs, rhs, direction) = goal.predicate; @@ -212,11 +204,13 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { (None, None) => bug!("`AliasRelate` goal without an alias on either lhs or rhs"), // RHS is not a projection, only way this is true is if LHS normalizes-to RHS - (Some(alias_lhs), None) => evaluate_normalizes_to(self, alias_lhs, rhs, direction), + (Some(alias_lhs), None) => { + evaluate_normalizes_to(self, alias_lhs, rhs, direction, Invert::No) + } // LHS is not a projection, only way this is true is if RHS normalizes-to LHS (None, Some(alias_rhs)) => { - evaluate_normalizes_to(self, alias_rhs, lhs, direction.invert()) + evaluate_normalizes_to(self, alias_rhs, lhs, direction, Invert::Yes) } (Some(alias_lhs), Some(alias_rhs)) => { @@ -224,34 +218,23 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { let candidates = vec