Add polarity to TraitPredicate

This commit is contained in:
Santiago Pastorino 2021-10-11 18:10:35 -03:00
parent 72d66064e7
commit 6975afd141
No known key found for this signature in database
GPG key ID: 8131A24E0C79EFAF
15 changed files with 105 additions and 12 deletions

View file

@ -94,6 +94,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
Some(ty::Binder::dummy(ty::PredicateKind::Trait(ty::TraitPredicate {
trait_ref,
constness: ty::BoundConstness::NotConst,
polarity: ty::ImplPolarity::Positive,
}))),
locations,
category,

View file

@ -825,6 +825,7 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> {
Binder::dummy(TraitPredicate {
trait_ref,
constness: ty::BoundConstness::ConstIfConst,
polarity: ty::ImplPolarity::Positive,
}),
);

View file

@ -137,6 +137,7 @@ impl Qualif for NeedsNonConstDrop {
ty::Binder::dummy(ty::TraitPredicate {
trait_ref,
constness: ty::BoundConstness::ConstIfConst,
polarity: ty::ImplPolarity::Positive,
}),
);

View file

@ -34,6 +34,7 @@ impl<T> ExpectedFound<T> {
pub enum TypeError<'tcx> {
Mismatch,
ConstnessMismatch(ExpectedFound<ty::BoundConstness>),
PolarityMismatch(ExpectedFound<ty::ImplPolarity>),
UnsafetyMismatch(ExpectedFound<hir::Unsafety>),
AbiMismatch(ExpectedFound<abi::Abi>),
Mutability,
@ -104,6 +105,9 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
ConstnessMismatch(values) => {
write!(f, "expected {} bound, found {} bound", values.expected, values.found)
}
PolarityMismatch(values) => {
write!(f, "expected {} polarity, found {} polarity", values.expected, values.found)
}
UnsafetyMismatch(values) => {
write!(f, "expected {} fn, found {} fn", values.expected, values.found)
}
@ -212,10 +216,9 @@ impl<'tcx> TypeError<'tcx> {
use self::TypeError::*;
match self {
CyclicTy(_) | CyclicConst(_) | UnsafetyMismatch(_) | ConstnessMismatch(_)
| Mismatch | AbiMismatch(_) | FixedArraySize(_) | ArgumentSorts(..) | Sorts(_)
| IntMismatch(_) | FloatMismatch(_) | VariadicMismatch(_) | TargetFeatureCast(_) => {
false
}
| PolarityMismatch(_) | Mismatch | AbiMismatch(_) | FixedArraySize(_)
| ArgumentSorts(..) | Sorts(_) | IntMismatch(_) | FloatMismatch(_)
| VariadicMismatch(_) | TargetFeatureCast(_) => false,
Mutability
| ArgumentMutability(_)

View file

@ -165,7 +165,18 @@ pub struct ImplHeader<'tcx> {
pub predicates: Vec<Predicate<'tcx>>,
}
#[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)]
#[derive(
Copy,
Clone,
PartialEq,
Eq,
Hash,
TyEncodable,
TyDecodable,
HashStable,
Debug,
TypeFoldable
)]
pub enum ImplPolarity {
/// `impl Trait for Type`
Positive,
@ -178,6 +189,26 @@ pub enum ImplPolarity {
Reservation,
}
impl ImplPolarity {
pub fn flip(&self) -> Option<ImplPolarity> {
match self {
ImplPolarity::Positive => Some(ImplPolarity::Negative),
ImplPolarity::Negative => Some(ImplPolarity::Positive),
ImplPolarity::Reservation => None,
}
}
}
impl fmt::Display for ImplPolarity {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Positive => f.write_str("positive"),
Self::Negative => f.write_str("negative"),
Self::Reservation => f.write_str("reservation"),
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, TyEncodable, TyDecodable, HashStable)]
pub enum Visibility {
/// Visible everywhere (including in other crates).
@ -460,6 +491,26 @@ impl<'tcx> Predicate<'tcx> {
pub fn kind(self) -> Binder<'tcx, PredicateKind<'tcx>> {
self.inner.kind
}
pub fn flip_polarity(&self, tcx: TyCtxt<'tcx>) -> Option<Predicate<'tcx>> {
let kind = self
.inner
.kind
.map_bound(|kind| match kind {
PredicateKind::Trait(TraitPredicate { trait_ref, constness, polarity }) => {
Some(PredicateKind::Trait(TraitPredicate {
trait_ref,
constness,
polarity: polarity.flip()?,
}))
}
_ => None,
})
.transpose()?;
Some(tcx.mk_predicate(kind))
}
}
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for Predicate<'tcx> {
@ -655,6 +706,8 @@ pub struct TraitPredicate<'tcx> {
pub trait_ref: TraitRef<'tcx>,
pub constness: BoundConstness,
pub polarity: ImplPolarity,
}
pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>;
@ -789,7 +842,11 @@ impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<PolyTraitRef<'tcx>> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
self.value
.map_bound(|trait_ref| {
PredicateKind::Trait(ty::TraitPredicate { trait_ref, constness: self.constness })
PredicateKind::Trait(ty::TraitPredicate {
trait_ref,
constness: self.constness,
polarity: ty::ImplPolarity::Positive,
})
})
.to_predicate(tcx)
}

View file

@ -797,6 +797,20 @@ impl<'tcx> Relate<'tcx> for GenericArg<'tcx> {
}
}
impl<'tcx> Relate<'tcx> for ty::ImplPolarity {
fn relate<R: TypeRelation<'tcx>>(
relation: &mut R,
a: ty::ImplPolarity,
b: ty::ImplPolarity,
) -> RelateResult<'tcx, ty::ImplPolarity> {
if a != b {
Err(TypeError::PolarityMismatch(expected_found(relation, a, b)))
} else {
Ok(a)
}
}
}
impl<'tcx> Relate<'tcx> for ty::TraitPredicate<'tcx> {
fn relate<R: TypeRelation<'tcx>>(
relation: &mut R,
@ -806,6 +820,7 @@ impl<'tcx> Relate<'tcx> for ty::TraitPredicate<'tcx> {
Ok(ty::TraitPredicate {
trait_ref: relation.relate(a.trait_ref, b.trait_ref)?,
constness: relation.relate(a.constness, b.constness)?,
polarity: relation.relate(a.polarity, b.polarity)?,
})
}
}

View file

@ -157,7 +157,7 @@ impl fmt::Debug for ty::TraitPredicate<'tcx> {
if let ty::BoundConstness::ConstIfConst = self.constness {
write!(f, "~const ")?;
}
write!(f, "TraitPredicate({:?})", self.trait_ref)
write!(f, "TraitPredicate({:?}, polarity:{:?})", self.trait_ref, self.polarity)
}
}
@ -365,8 +365,11 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ExistentialPredicate<'a> {
impl<'a, 'tcx> Lift<'tcx> for ty::TraitPredicate<'a> {
type Lifted = ty::TraitPredicate<'tcx>;
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<ty::TraitPredicate<'tcx>> {
tcx.lift(self.trait_ref)
.map(|trait_ref| ty::TraitPredicate { trait_ref, constness: self.constness })
tcx.lift(self.trait_ref).map(|trait_ref| ty::TraitPredicate {
trait_ref,
constness: self.constness,
polarity: self.polarity,
})
}
}
@ -591,6 +594,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> {
Some(match self {
Mismatch => Mismatch,
ConstnessMismatch(x) => ConstnessMismatch(x),
PolarityMismatch(x) => PolarityMismatch(x),
UnsafetyMismatch(x) => UnsafetyMismatch(x),
AbiMismatch(x) => AbiMismatch(x),
Mutability => Mutability,

View file

@ -882,6 +882,7 @@ impl<'tcx> PolyTraitRef<'tcx> {
self.map_bound(|trait_ref| ty::TraitPredicate {
trait_ref,
constness: ty::BoundConstness::NotConst,
polarity: ty::ImplPolarity::Positive,
})
}
}

View file

@ -124,9 +124,11 @@ where
fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<V::BreakTy> {
match predicate.kind().skip_binder() {
ty::PredicateKind::Trait(ty::TraitPredicate { trait_ref, constness: _ }) => {
self.visit_trait(trait_ref)
}
ty::PredicateKind::Trait(ty::TraitPredicate {
trait_ref,
constness: _,
polarity: _,
}) => self.visit_trait(trait_ref),
ty::PredicateKind::Projection(ty::ProjectionPredicate { projection_ty, ty }) => {
ty.visit_with(self)?;
self.visit_projection_ty(projection_ty)

View file

@ -286,6 +286,8 @@ impl AutoTraitFinder<'tcx> {
substs: infcx.tcx.mk_substs_trait(ty, &[]),
},
constness: ty::BoundConstness::NotConst,
// Auto traits are positive
polarity: ty::ImplPolarity::Positive,
}));
let computed_preds = param_env.caller_bounds().iter();

View file

@ -804,6 +804,7 @@ pub fn vtable_trait_upcasting_coercion_new_vptr_slot(
ty::Binder::dummy(ty::TraitPredicate {
trait_ref,
constness: ty::BoundConstness::NotConst,
polarity: ty::ImplPolarity::Positive,
}),
);

View file

@ -44,6 +44,7 @@ pub(crate) fn update<'tcx, T>(
ty::PredicateKind::Trait(ty::TraitPredicate {
trait_ref,
constness: predicate.constness,
polarity: predicate.polarity,
})
})
.to_predicate(infcx.tcx),

View file

@ -915,6 +915,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
substs: self.tcx().mk_substs_trait(ty, &[]),
},
constness: ty::BoundConstness::NotConst,
polarity: ty::ImplPolarity::Positive,
}));
copy_obligation.recursion_depth = depth + 1;
self.assemble_candidates_from_impls(&copy_obligation, &mut copy_candidates);

View file

@ -531,6 +531,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
substs: self.infcx.tcx.mk_substs_trait(outer_ty, &[]),
},
constness: t.constness,
polarity: t.polarity,
}));
let obl = Obligation::new(
o.cause.clone(),

View file

@ -382,6 +382,7 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
ty::PredicateKind::Trait(ty::TraitPredicate {
trait_ref,
constness: ty::BoundConstness::NotConst,
polarity: _,
}) => {
if !matches!(
trait_predicate_kind(tcx, predicate),
@ -413,6 +414,7 @@ fn trait_predicate_kind<'tcx>(
ty::PredicateKind::Trait(ty::TraitPredicate {
trait_ref,
constness: ty::BoundConstness::NotConst,
polarity: _,
}) => Some(tcx.trait_def(trait_ref.def_id).specialization_kind),
ty::PredicateKind::Trait(_)
| ty::PredicateKind::RegionOutlives(_)