Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Remove AliasRelationDirection::Supertype
  • Loading branch information
compiler-errors committed Mar 23, 2023
commit 244cdaa457d80b3e1ef90795a48833f948ac0db9
12 changes: 6 additions & 6 deletions compiler/rustc_infer/src/infer/combine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

Expand Down Expand Up @@ -848,18 +848,18 @@ 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(),
self.alias_relate_direction(),
))]);
}

/// 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;
}

Expand Down
30 changes: 24 additions & 6 deletions compiler/rustc_infer/src/infer/nll_relate/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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!(),
}
})]);
}
}

Expand Down
12 changes: 0 additions & 12 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -648,25 +648,13 @@ 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 {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
AliasRelationDirection::Equate => write!(f, " == "),
AliasRelationDirection::Subtype => write!(f, " <: "),
AliasRelationDirection::Supertype => write!(f, " :> "),
}
}
}
Expand Down
19 changes: 19 additions & 0 deletions compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
///
Expand Down
117 changes: 50 additions & 67 deletions compiler/rustc_trait_selection/src/solve/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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)
}
}
Expand Down Expand Up @@ -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;

Expand All @@ -212,46 +204,37 @@ 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)) => {
debug!("compute_alias_relate_goal: both sides are aliases");

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)
}),
Expand Down