1
Fork 0

Fully fledged Clause type

This commit is contained in:
Michael Goulet 2023-06-16 06:27:41 +00:00
parent fca56a8d2c
commit 21226eefb2
11 changed files with 155 additions and 96 deletions

View file

@ -561,6 +561,42 @@ impl rustc_errors::IntoDiagnosticArg for Predicate<'_> {
}
}
/// TODO: doc
#[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)]
#[rustc_pass_by_value]
pub struct Clause<'tcx>(Interned<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>);
impl<'tcx> Clause<'tcx> {
pub fn as_predicate(self) -> Predicate<'tcx> {
Predicate(self.0)
}
pub fn kind(self) -> Binder<'tcx, ClauseKind<'tcx>> {
self.0.internee.map_bound(|kind| match kind {
PredicateKind::Clause(clause) => clause,
_ => unreachable!(),
})
}
pub fn as_trait_clause(self) -> Option<Binder<'tcx, TraitPredicate<'tcx>>> {
let clause = self.kind();
if let ty::ClauseKind::Trait(trait_clause) = clause.skip_binder() {
Some(clause.rebind(trait_clause))
} else {
None
}
}
pub fn as_projection_clause(self) -> Option<Binder<'tcx, ProjectionPredicate<'tcx>>> {
let clause = self.kind();
if let ty::ClauseKind::Projection(projection_clause) = clause.skip_binder() {
Some(clause.rebind(projection_clause))
} else {
None
}
}
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
/// A clause is something that can appear in where bounds or be inferred
@ -592,24 +628,6 @@ pub enum ClauseKind<'tcx> {
ConstEvaluatable(ty::Const<'tcx>),
}
impl<'tcx> Binder<'tcx, ClauseKind<'tcx>> {
pub fn as_trait_clause(self) -> Option<Binder<'tcx, TraitPredicate<'tcx>>> {
if let ty::ClauseKind::Trait(trait_clause) = self.skip_binder() {
Some(self.rebind(trait_clause))
} else {
None
}
}
pub fn as_projection_clause(self) -> Option<Binder<'tcx, ProjectionPredicate<'tcx>>> {
if let ty::ClauseKind::Projection(projection_clause) = self.skip_binder() {
Some(self.rebind(projection_clause))
} else {
None
}
}
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
pub enum PredicateKind<'tcx> {
@ -1222,6 +1240,13 @@ impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, ClauseKind<'tcx>> {
}
}
impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for Binder<'tcx, ClauseKind<'tcx>> {
#[inline(always)]
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
tcx.mk_predicate(self.map_bound(|clause| ty::PredicateKind::Clause(clause))).expect_clause()
}
}
impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> {
#[inline(always)]
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
@ -1229,14 +1254,11 @@ impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> {
}
}
impl<'tcx> ToPredicate<'tcx, Binder<'tcx, ClauseKind<'tcx>>> for TraitRef<'tcx> {
impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for TraitRef<'tcx> {
#[inline(always)]
fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> Binder<'tcx, ClauseKind<'tcx>> {
Binder::dummy(ClauseKind::Trait(TraitPredicate {
trait_ref: self,
constness: ty::BoundConstness::NotConst,
polarity: ty::ImplPolarity::Positive,
}))
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
let p: Predicate<'tcx> = self.to_predicate(tcx);
p.expect_clause()
}
}
@ -1248,9 +1270,9 @@ impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, TraitRef<'tcx>> {
}
}
impl<'tcx> ToPredicate<'tcx, Binder<'tcx, ClauseKind<'tcx>>> for Binder<'tcx, TraitRef<'tcx>> {
impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for Binder<'tcx, TraitRef<'tcx>> {
#[inline(always)]
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Binder<'tcx, ClauseKind<'tcx>> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
let pred: PolyTraitPredicate<'tcx> = self.to_predicate(tcx);
pred.to_predicate(tcx)
}
@ -1285,9 +1307,10 @@ impl<'tcx> ToPredicate<'tcx> for PolyTraitPredicate<'tcx> {
}
}
impl<'tcx> ToPredicate<'tcx, Binder<'tcx, ClauseKind<'tcx>>> for PolyTraitPredicate<'tcx> {
fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> Binder<'tcx, ClauseKind<'tcx>> {
self.map_bound(|p| ClauseKind::Trait(p))
impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for PolyTraitPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
let p: Predicate<'tcx> = self.to_predicate(tcx);
p.expect_clause()
}
}
@ -1309,9 +1332,10 @@ impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> {
}
}
impl<'tcx> ToPredicate<'tcx, Binder<'tcx, ClauseKind<'tcx>>> for PolyProjectionPredicate<'tcx> {
fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> Binder<'tcx, ClauseKind<'tcx>> {
self.map_bound(|p| ClauseKind::Projection(p))
impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for PolyProjectionPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
let p: Predicate<'tcx> = self.to_predicate(tcx);
p.expect_clause()
}
}
@ -1385,18 +1409,17 @@ impl<'tcx> Predicate<'tcx> {
}
}
pub fn as_clause(self) -> Option<Binder<'tcx, ClauseKind<'tcx>>> {
let predicate = self.kind();
match predicate.skip_binder() {
PredicateKind::Clause(clause) => Some(predicate.rebind(clause)),
PredicateKind::AliasRelate(..)
| PredicateKind::Subtype(..)
| PredicateKind::Coerce(..)
| PredicateKind::ObjectSafe(..)
| PredicateKind::ClosureKind(..)
| PredicateKind::ConstEquate(..)
| PredicateKind::Ambiguous
| PredicateKind::TypeWellFormedFromEnv(..) => None,
pub fn as_clause(self) -> Option<Clause<'tcx>> {
match self.kind().skip_binder() {
PredicateKind::Clause(..) => Some(self.expect_clause()),
_ => None,
}
}
pub fn expect_clause(self) -> Clause<'tcx> {
match self.kind().skip_binder() {
PredicateKind::Clause(..) => Clause(self.0),
_ => bug!(),
}
}
}

View file

@ -171,6 +171,12 @@ impl<'tcx> fmt::Debug for ty::Predicate<'tcx> {
}
}
impl<'tcx> fmt::Debug for ty::Clause<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", self.kind())
}
}
impl<'tcx> fmt::Debug for ty::ClauseKind<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
@ -654,12 +660,31 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ty::Predicate<'tcx> {
}
}
// FIXME(clause): This is wonky
impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ty::Clause<'tcx> {
fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
self,
folder: &mut F,
) -> Result<Self, F::Error> {
Ok(folder
.try_fold_predicate(self.as_predicate())?
.as_clause()
.expect("no sensible folder would do this"))
}
}
impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::Predicate<'tcx> {
fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
visitor.visit_predicate(*self)
}
}
impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::Clause<'tcx> {
fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
visitor.visit_predicate(self.as_predicate())
}
}
impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for ty::Predicate<'tcx> {
fn try_super_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
self,