diff options
| author | Michael Goulet <michael@errs.io> | 2023-03-22 16:58:51 +0000 |
|---|---|---|
| committer | Michael Goulet <michael@errs.io> | 2023-03-23 05:57:09 +0000 |
| commit | 244cdaa457d80b3e1ef90795a48833f948ac0db9 (patch) | |
| tree | ce30e96a9b7191dbe69e43346c25657fb4088d68 | |
| parent | f6fd7546804dd25d4996196dbc9653bde2b4a131 (diff) | |
| download | rust-244cdaa457d80b3e1ef90795a48833f948ac0db9.tar.gz rust-244cdaa457d80b3e1ef90795a48833f948ac0db9.zip | |
Remove AliasRelationDirection::Supertype
| -rw-r--r-- | compiler/rustc_infer/src/infer/combine.rs | 12 | ||||
| -rw-r--r-- | compiler/rustc_infer/src/infer/nll_relate/mod.rs | 30 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/mod.rs | 12 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/solve/eval_ctxt.rs | 19 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/solve/mod.rs | 117 |
5 files changed, 99 insertions, 91 deletions
diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs index 3fadc243dcd..88a28e26005 100644 --- a/compiler/rustc_infer/src/infer/combine.rs +++ b/compiler/rustc_infer/src/infer/combine.rs @@ -128,7 +128,7 @@ impl<'tcx> InferCtxt<'tcx> { (_, ty::Alias(AliasKind::Projection, _)) | (ty::Alias(AliasKind::Projection, _), _) if self.tcx.trait_solver_next() => { - relation.register_type_equate_obligation(a, b); + relation.register_type_relate_obligation(a, b); Ok(a) } @@ -848,10 +848,9 @@ pub trait ObligationEmittingRelation<'tcx>: TypeRelation<'tcx> { })]); } - /// Register an obligation that both types must be equal to each other. - /// - /// If they aren't equal then the relation doesn't hold. - fn register_type_equate_obligation(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) { + /// Register an obligation that both types must be related to each other according to + /// the [`ty::AliasRelationDirection`] given by [`ObligationEmittingRelation::alias_relate_direction`] + fn register_type_relate_obligation(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) { self.register_predicates([ty::Binder::dummy(ty::PredicateKind::AliasRelate( a.into(), b.into(), @@ -859,7 +858,8 @@ pub trait ObligationEmittingRelation<'tcx>: TypeRelation<'tcx> { ))]); } - /// Relation direction emitted for `AliasRelate` predicates + /// Relation direction emitted for `AliasRelate` predicates, corresponding to the direction + /// of the relation. fn alias_relate_direction(&self) -> ty::AliasRelationDirection; } diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index 216d2965da7..61d1b69be55 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -779,13 +779,31 @@ where } fn alias_relate_direction(&self) -> ty::AliasRelationDirection { - match self.ambient_variance { - ty::Variance::Covariant => ty::AliasRelationDirection::Subtype, - ty::Variance::Contravariant => ty::AliasRelationDirection::Supertype, - ty::Variance::Invariant => ty::AliasRelationDirection::Equate, - // FIXME(deferred_projection_equality): Implement this when we trigger it + unreachable!("manually overridden to handle ty::Variance::Contravariant ambient variance") + } + + fn register_type_relate_obligation(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) { + self.register_predicates([ty::Binder::dummy(match self.ambient_variance { + ty::Variance::Covariant => ty::PredicateKind::AliasRelate( + a.into(), + b.into(), + ty::AliasRelationDirection::Subtype, + ), + // a :> b is b <: a + ty::Variance::Contravariant => ty::PredicateKind::AliasRelate( + b.into(), + a.into(), + ty::AliasRelationDirection::Subtype, + ), + ty::Variance::Invariant => ty::PredicateKind::AliasRelate( + a.into(), + b.into(), + ty::AliasRelationDirection::Equate, + ), + // FIXME(deferred_projection_equality): Implement this when we trigger it. + // Probably just need to do nothing here. ty::Variance::Bivariant => unreachable!(), - } + })]); } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 23139e6be7a..7ea242f55b0 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -648,17 +648,6 @@ pub enum PredicateKind<'tcx> { pub enum AliasRelationDirection { Equate, Subtype, - Supertype, -} - -impl AliasRelationDirection { - pub fn invert(self) -> Self { - match self { - AliasRelationDirection::Equate => AliasRelationDirection::Equate, - AliasRelationDirection::Subtype => AliasRelationDirection::Supertype, - AliasRelationDirection::Supertype => AliasRelationDirection::Subtype, - } - } } impl std::fmt::Display for AliasRelationDirection { @@ -666,7 +655,6 @@ impl std::fmt::Display for AliasRelationDirection { match self { AliasRelationDirection::Equate => write!(f, " == "), AliasRelationDirection::Subtype => write!(f, " <: "), - AliasRelationDirection::Supertype => write!(f, " :> "), } } } diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs index 4cfea284757..75b304cce4e 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs @@ -459,6 +459,25 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { }) } + #[instrument(level = "debug", skip(self, param_env), ret)] + pub(super) fn sub<T: ToTrace<'tcx>>( + &mut self, + param_env: ty::ParamEnv<'tcx>, + sub: T, + sup: T, + ) -> Result<(), NoSolution> { + self.infcx + .at(&ObligationCause::dummy(), param_env) + .sub(DefineOpaqueTypes::No, sub, sup) + .map(|InferOk { value: (), obligations }| { + self.add_goals(obligations.into_iter().map(|o| o.into())); + }) + .map_err(|e| { + debug!(?e, "failed to subtype"); + NoSolution + }) + } + /// Equates two values returning the nested goals without adding them /// to the nested goals of the `EvalCtxt`. /// 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