add PredicateKint, because who doesn't like bodging

This commit is contained in:
Bastian Kauschke 2020-06-11 21:42:39 +02:00
parent 52d2c7ac94
commit 104cb878e3
3 changed files with 200 additions and 3 deletions

View File

@ -19,7 +19,7 @@ use crate::ty::TyKind::*;
use crate::ty::{
self, query, AdtDef, AdtKind, BindingMode, BoundVar, CanonicalPolyFnSig, Const, ConstVid,
DefIdTree, ExistentialPredicate, FloatVar, FloatVid, GenericParamDefKind, InferConst, InferTy,
IntVar, IntVid, List, ParamConst, ParamTy, PolyFnSig, Predicate, PredicateInner, PredicateKind,
IntVar, IntVid, List, ParamConst, ParamTy, PolyFnSig, Predicate, PredicateInner, PredicateKint,
ProjectionTy, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyS, TyVar,
TyVid, TypeAndMut,
};
@ -79,6 +79,7 @@ pub struct CtxtInterners<'tcx> {
region: InternedSet<'tcx, RegionKind>,
existential_predicates: InternedSet<'tcx, List<ExistentialPredicate<'tcx>>>,
predicate: InternedSet<'tcx, PredicateInner<'tcx>>,
predicate_kint: InternedSet<'tcx, PredicateKint<'tcx>>,
predicates: InternedSet<'tcx, List<Predicate<'tcx>>>,
projs: InternedSet<'tcx, List<ProjectionKind>>,
place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>,
@ -98,11 +99,11 @@ impl<'tcx> CtxtInterners<'tcx> {
existential_predicates: Default::default(),
canonical_var_infos: Default::default(),
predicate: Default::default(),
predicate_kint: Default::default(),
predicates: Default::default(),
projs: Default::default(),
place_elems: Default::default(),
const_: Default::default(),
chalk_environment_clause_list: Default::default(),
}
}
@ -1616,6 +1617,7 @@ nop_lift! {type_; Ty<'a> => Ty<'tcx>}
nop_lift! {region; Region<'a> => Region<'tcx>}
nop_lift! {const_; &'a Const<'a> => &'tcx Const<'tcx>}
nop_lift! {predicate; &'a PredicateInner<'a> => &'tcx PredicateInner<'tcx>}
nop_lift! {predicate_kint; &'a PredicateKint<'a> => &'tcx PredicateKint<'tcx>}
nop_list_lift! {type_list; Ty<'a> => Ty<'tcx>}
nop_list_lift! {existential_predicates; ExistentialPredicate<'a> => ExistentialPredicate<'tcx>}
@ -2034,6 +2036,12 @@ impl<'tcx> Borrow<PredicateKind<'tcx>> for Interned<'tcx, PredicateKind<'tcx>> {
}
}
impl<'tcx> Borrow<PredicateKint<'tcx>> for Interned<'tcx, PredicateKint<'tcx>> {
fn borrow<'a>(&'a self) -> &'a PredicateKint<'tcx> {
&self.0
}
}
macro_rules! direct_interners {
($($name:ident: $method:ident($ty:ty),)+) => {
$(impl<'tcx> PartialEq for Interned<'tcx, $ty> {
@ -2063,6 +2071,7 @@ macro_rules! direct_interners {
direct_interners! {
region: mk_region(RegionKind),
const_: mk_const(Const<'tcx>),
predicate_kint: intern_predicate_kint(PredicateKint<'tcx>),
}
macro_rules! slice_interners {
@ -2128,7 +2137,7 @@ impl<'tcx> TyCtxt<'tcx> {
#[allow(rustc::usage_of_ty_tykind)]
#[inline]
pub fn mk_ty(&self, st: TyKind<'tcx>) -> Ty<'tcx> {
pub fn mk_ty(self, st: TyKind<'tcx>) -> Ty<'tcx> {
self.interners.intern_ty(st)
}

View File

@ -1063,6 +1063,113 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for Predicate<'tcx> {
kind.hash_stable(hcx, hasher);
}
pub fn kint(self, tcx: TyCtxt<'tcx>) -> &'tcx PredicateKint<'tcx> {
// I am efficient
tcx.intern_predicate_kint(match *self.kind() {
PredicateKind::Trait(binder, data) => {
if let Some(simpl) = binder.no_bound_vars() {
PredicateKint::Trait(simpl, data)
} else {
let inner = tcx
.intern_predicate_kint(PredicateKint::Trait(*binder.skip_binder(), data));
PredicateKint::ForAll(Binder::bind(inner))
}
}
PredicateKind::RegionOutlives(binder) => {
if let Some(simpl) = binder.no_bound_vars() {
PredicateKint::RegionOutlives(simpl)
} else {
let inner = tcx.intern_predicate_kint(PredicateKint::RegionOutlives(
*binder.skip_binder(),
));
PredicateKint::ForAll(Binder::bind(inner))
}
}
PredicateKind::TypeOutlives(binder) => {
if let Some(simpl) = binder.no_bound_vars() {
PredicateKint::TypeOutlives(simpl)
} else {
let inner = tcx
.intern_predicate_kint(PredicateKint::TypeOutlives(*binder.skip_binder()));
PredicateKint::ForAll(Binder::bind(inner))
}
}
PredicateKind::Projection(binder) => {
if let Some(simpl) = binder.no_bound_vars() {
PredicateKint::Projection(simpl)
} else {
let inner =
tcx.intern_predicate_kint(PredicateKint::Projection(*binder.skip_binder()));
PredicateKint::ForAll(Binder::bind(inner))
}
}
PredicateKind::WellFormed(arg) => PredicateKint::WellFormed(arg),
PredicateKind::ObjectSafe(def_id) => PredicateKint::ObjectSafe(def_id),
PredicateKind::ClosureKind(def_id, substs, kind) => {
PredicateKint::ClosureKind(def_id, substs, kind)
}
PredicateKind::Subtype(binder) => {
if let Some(simpl) = binder.no_bound_vars() {
PredicateKint::Subtype(simpl)
} else {
let inner =
tcx.intern_predicate_kint(PredicateKint::Subtype(*binder.skip_binder()));
PredicateKint::ForAll(Binder::bind(inner))
}
}
PredicateKind::ConstEvaluatable(def, substs) => {
PredicateKint::ConstEvaluatable(def, substs)
}
PredicateKind::ConstEquate(l, r) => PredicateKint::ConstEquate(l, r),
})
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(TypeFoldable)]
pub enum PredicateKint<'tcx> {
/// Corresponds to `where Foo: Bar<A, B, C>`. `Foo` here would be
/// the `Self` type of the trait reference and `A`, `B`, and `C`
/// would be the type parameters.
///
/// A trait predicate will have `Constness::Const` if it originates
/// from a bound on a `const fn` without the `?const` opt-out (e.g.,
/// `const fn foobar<Foo: Bar>() {}`).
Trait(TraitPredicate<'tcx>, Constness),
/// `where 'a: 'b`
RegionOutlives(RegionOutlivesPredicate<'tcx>),
/// `where T: 'a`
TypeOutlives(TypeOutlivesPredicate<'tcx>),
/// `where <T as TraitRef>::Name == X`, approximately.
/// See the `ProjectionPredicate` struct for details.
Projection(ProjectionPredicate<'tcx>),
/// No syntax: `T` well-formed.
WellFormed(GenericArg<'tcx>),
/// Trait must be object-safe.
ObjectSafe(DefId),
/// No direct syntax. May be thought of as `where T: FnFoo<...>`
/// for some substitutions `...` and `T` being a closure type.
/// Satisfied (or refuted) once we know the closure's kind.
ClosureKind(DefId, SubstsRef<'tcx>, ClosureKind),
/// `T1 <: T2`
Subtype(SubtypePredicate<'tcx>),
/// Constant initializer must evaluate successfully.
ConstEvaluatable(DefId, SubstsRef<'tcx>),
/// Constants must be equal. The first component is the const that is expected.
ConstEquate(&'tcx Const<'tcx>, &'tcx Const<'tcx>),
/// `for<'a>: ...`
ForAll(Binder<&'tcx PredicateKint<'tcx>>),
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
@ -1349,6 +1456,76 @@ impl ToPredicate<'tcx> for PredicateKind<'tcx> {
}
}
impl ToPredicate<'tcx> for PredicateKint<'tcx> {
#[inline(always)]
fn to_predicate(&self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
let (predicate, in_binder) = if let PredicateKint::ForAll(binder) = self {
(*binder.skip_binder(), true)
} else {
(self, false)
};
macro_rules! bind {
($expr:expr) => {
match $expr {
expr => {
if in_binder {
Binder::bind(expr)
} else {
Binder::dummy(expr)
}
}
}
};
}
match *predicate {
PredicateKint::ForAll(_) => bug!("unexpected PredicateKint: {:?}", self),
PredicateKint::Trait(data, ct) => PredicateKind::Trait(bind!(data), ct),
PredicateKint::RegionOutlives(data) => PredicateKind::RegionOutlives(bind!(data)),
PredicateKint::TypeOutlives(data) => PredicateKind::TypeOutlives(bind!(data)),
PredicateKint::Projection(data) => PredicateKind::Projection(bind!(data)),
PredicateKint::WellFormed(arg) => {
if in_binder {
bug!("unexpected ForAll: {:?}", self)
} else {
PredicateKind::WellFormed(arg)
}
}
PredicateKint::ObjectSafe(def_id) => {
if in_binder {
bug!("unexpected ForAll: {:?}", self)
} else {
PredicateKind::ObjectSafe(def_id)
}
}
PredicateKint::ClosureKind(def_id, substs, kind) => {
if in_binder {
bug!("unexpected ForAll: {:?}", self)
} else {
PredicateKind::ClosureKind(def_id, substs, kind)
}
}
PredicateKint::Subtype(data) => PredicateKind::Subtype(bind!(data)),
PredicateKint::ConstEvaluatable(def_id, substs) => {
if in_binder {
bug!("unexpected ForAll: {:?}", self)
} else {
PredicateKind::ConstEvaluatable(def_id, substs)
}
}
PredicateKint::ConstEquate(l, r) => {
if in_binder {
bug!("unexpected ForAll: {:?}", self)
} else {
PredicateKind::ConstEquate(l, r)
}
}
}
.to_predicate(tcx)
}
}
impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<TraitRef<'tcx>> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
ty::PredicateKind::Trait(

View File

@ -1028,6 +1028,17 @@ impl<T: TypeVisitor<'tcx>> PredicateVisitor<'tcx> for T {
}
}
impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::PredicateKint<'tcx> {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
let new = ty::PredicateKint::super_fold_with(self, folder);
folder.tcx().intern_predicate_kint(new)
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
ty::PredicateKint::super_visit_with(self, visitor)
}
}
impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::Predicate<'tcx>> {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
fold_list(*self, folder, |tcx, v| tcx.intern_predicates(v))