about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2023-03-22 16:58:51 +0000
committerMichael Goulet <michael@errs.io>2023-03-23 05:57:09 +0000
commit244cdaa457d80b3e1ef90795a48833f948ac0db9 (patch)
treece30e96a9b7191dbe69e43346c25657fb4088d68
parentf6fd7546804dd25d4996196dbc9653bde2b4a131 (diff)
downloadrust-244cdaa457d80b3e1ef90795a48833f948ac0db9.tar.gz
rust-244cdaa457d80b3e1ef90795a48833f948ac0db9.zip
Remove AliasRelationDirection::Supertype
-rw-r--r--compiler/rustc_infer/src/infer/combine.rs12
-rw-r--r--compiler/rustc_infer/src/infer/nll_relate/mod.rs30
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs12
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt.rs19
-rw-r--r--compiler/rustc_trait_selection/src/solve/mod.rs117
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![
                     // LHS normalizes-to RHS
-                    evaluate_normalizes_to(self, alias_lhs, rhs, direction),
+                    evaluate_normalizes_to(self, alias_lhs, rhs, direction, Invert::No),
                     // RHS normalizes-to RHS
-                    evaluate_normalizes_to(self, alias_rhs, lhs, direction.invert()),
+                    evaluate_normalizes_to(self, alias_rhs, lhs, direction, Invert::Yes),
                     // Relate via substs
                     self.probe(|ecx| {
                         debug!(
                             "compute_alias_relate_goal: alias defids are equal, equating substs"
                         );
 
-                        ecx.add_goals(
-                            match direction {
-                                ty::AliasRelationDirection::Equate => ecx
-                                    .infcx
-                                    .at(&ObligationCause::dummy(), goal.param_env)
-                                    .eq(DefineOpaqueTypes::No, alias_lhs, alias_rhs),
-                                ty::AliasRelationDirection::Subtype => ecx
-                                    .infcx
-                                    .at(&ObligationCause::dummy(), goal.param_env)
-                                    .sub(DefineOpaqueTypes::No, alias_lhs, alias_rhs),
-                                ty::AliasRelationDirection::Supertype => ecx
-                                    .infcx
-                                    .at(&ObligationCause::dummy(), goal.param_env)
-                                    .sup(DefineOpaqueTypes::No, alias_lhs, alias_rhs),
-                            }?
-                            .into_obligations()
-                            .into_iter()
-                            .map(|o| o.into()),
-                        );
+                        match direction {
+                            ty::AliasRelationDirection::Equate => {
+                                ecx.eq(goal.param_env, alias_lhs, alias_rhs)?;
+                            }
+                            ty::AliasRelationDirection::Subtype => {
+                                ecx.sub(goal.param_env, alias_lhs, alias_rhs)?;
+                            }
+                        }
 
                         ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
                     }),