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 { Some(ty::Binder::dummy(ty::PredicateKind::Trait(ty::TraitPredicate {
trait_ref, trait_ref,
constness: ty::BoundConstness::NotConst, constness: ty::BoundConstness::NotConst,
polarity: ty::ImplPolarity::Positive,
}))), }))),
locations, locations,
category, category,

View File

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

View File

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

View File

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

View File

@ -165,7 +165,18 @@ pub struct ImplHeader<'tcx> {
pub predicates: Vec<Predicate<'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 { pub enum ImplPolarity {
/// `impl Trait for Type` /// `impl Trait for Type`
Positive, Positive,
@ -178,6 +189,26 @@ pub enum ImplPolarity {
Reservation, 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)] #[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, TyEncodable, TyDecodable, HashStable)]
pub enum Visibility { pub enum Visibility {
/// Visible everywhere (including in other crates). /// Visible everywhere (including in other crates).
@ -460,6 +491,26 @@ impl<'tcx> Predicate<'tcx> {
pub fn kind(self) -> Binder<'tcx, PredicateKind<'tcx>> { pub fn kind(self) -> Binder<'tcx, PredicateKind<'tcx>> {
self.inner.kind 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> { impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for Predicate<'tcx> {
@ -655,6 +706,8 @@ pub struct TraitPredicate<'tcx> {
pub trait_ref: TraitRef<'tcx>, pub trait_ref: TraitRef<'tcx>,
pub constness: BoundConstness, pub constness: BoundConstness,
pub polarity: ImplPolarity,
} }
pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>; 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> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
self.value self.value
.map_bound(|trait_ref| { .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) .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> { impl<'tcx> Relate<'tcx> for ty::TraitPredicate<'tcx> {
fn relate<R: TypeRelation<'tcx>>( fn relate<R: TypeRelation<'tcx>>(
relation: &mut R, relation: &mut R,
@ -806,6 +820,7 @@ impl<'tcx> Relate<'tcx> for ty::TraitPredicate<'tcx> {
Ok(ty::TraitPredicate { Ok(ty::TraitPredicate {
trait_ref: relation.relate(a.trait_ref, b.trait_ref)?, trait_ref: relation.relate(a.trait_ref, b.trait_ref)?,
constness: relation.relate(a.constness, b.constness)?, 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 { if let ty::BoundConstness::ConstIfConst = self.constness {
write!(f, "~const ")?; 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> { impl<'a, 'tcx> Lift<'tcx> for ty::TraitPredicate<'a> {
type Lifted = ty::TraitPredicate<'tcx>; type Lifted = ty::TraitPredicate<'tcx>;
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<ty::TraitPredicate<'tcx>> { fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<ty::TraitPredicate<'tcx>> {
tcx.lift(self.trait_ref) tcx.lift(self.trait_ref).map(|trait_ref| ty::TraitPredicate {
.map(|trait_ref| ty::TraitPredicate { trait_ref, constness: self.constness }) 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 { Some(match self {
Mismatch => Mismatch, Mismatch => Mismatch,
ConstnessMismatch(x) => ConstnessMismatch(x), ConstnessMismatch(x) => ConstnessMismatch(x),
PolarityMismatch(x) => PolarityMismatch(x),
UnsafetyMismatch(x) => UnsafetyMismatch(x), UnsafetyMismatch(x) => UnsafetyMismatch(x),
AbiMismatch(x) => AbiMismatch(x), AbiMismatch(x) => AbiMismatch(x),
Mutability => Mutability, Mutability => Mutability,

View File

@ -882,6 +882,7 @@ impl<'tcx> PolyTraitRef<'tcx> {
self.map_bound(|trait_ref| ty::TraitPredicate { self.map_bound(|trait_ref| ty::TraitPredicate {
trait_ref, trait_ref,
constness: ty::BoundConstness::NotConst, 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> { fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<V::BreakTy> {
match predicate.kind().skip_binder() { match predicate.kind().skip_binder() {
ty::PredicateKind::Trait(ty::TraitPredicate { trait_ref, constness: _ }) => { ty::PredicateKind::Trait(ty::TraitPredicate {
self.visit_trait(trait_ref) trait_ref,
} constness: _,
polarity: _,
}) => self.visit_trait(trait_ref),
ty::PredicateKind::Projection(ty::ProjectionPredicate { projection_ty, ty }) => { ty::PredicateKind::Projection(ty::ProjectionPredicate { projection_ty, ty }) => {
ty.visit_with(self)?; ty.visit_with(self)?;
self.visit_projection_ty(projection_ty) self.visit_projection_ty(projection_ty)

View File

@ -286,6 +286,8 @@ impl AutoTraitFinder<'tcx> {
substs: infcx.tcx.mk_substs_trait(ty, &[]), substs: infcx.tcx.mk_substs_trait(ty, &[]),
}, },
constness: ty::BoundConstness::NotConst, constness: ty::BoundConstness::NotConst,
// Auto traits are positive
polarity: ty::ImplPolarity::Positive,
})); }));
let computed_preds = param_env.caller_bounds().iter(); 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 { ty::Binder::dummy(ty::TraitPredicate {
trait_ref, trait_ref,
constness: ty::BoundConstness::NotConst, 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 { ty::PredicateKind::Trait(ty::TraitPredicate {
trait_ref, trait_ref,
constness: predicate.constness, constness: predicate.constness,
polarity: predicate.polarity,
}) })
}) })
.to_predicate(infcx.tcx), .to_predicate(infcx.tcx),

View File

@ -915,6 +915,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
substs: self.tcx().mk_substs_trait(ty, &[]), substs: self.tcx().mk_substs_trait(ty, &[]),
}, },
constness: ty::BoundConstness::NotConst, constness: ty::BoundConstness::NotConst,
polarity: ty::ImplPolarity::Positive,
})); }));
copy_obligation.recursion_depth = depth + 1; copy_obligation.recursion_depth = depth + 1;
self.assemble_candidates_from_impls(&copy_obligation, &mut copy_candidates); 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, &[]), substs: self.infcx.tcx.mk_substs_trait(outer_ty, &[]),
}, },
constness: t.constness, constness: t.constness,
polarity: t.polarity,
})); }));
let obl = Obligation::new( let obl = Obligation::new(
o.cause.clone(), 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 { ty::PredicateKind::Trait(ty::TraitPredicate {
trait_ref, trait_ref,
constness: ty::BoundConstness::NotConst, constness: ty::BoundConstness::NotConst,
polarity: _,
}) => { }) => {
if !matches!( if !matches!(
trait_predicate_kind(tcx, predicate), trait_predicate_kind(tcx, predicate),
@ -413,6 +414,7 @@ fn trait_predicate_kind<'tcx>(
ty::PredicateKind::Trait(ty::TraitPredicate { ty::PredicateKind::Trait(ty::TraitPredicate {
trait_ref, trait_ref,
constness: ty::BoundConstness::NotConst, constness: ty::BoundConstness::NotConst,
polarity: _,
}) => Some(tcx.trait_def(trait_ref.def_id).specialization_kind), }) => Some(tcx.trait_def(trait_ref.def_id).specialization_kind),
ty::PredicateKind::Trait(_) ty::PredicateKind::Trait(_)
| ty::PredicateKind::RegionOutlives(_) | ty::PredicateKind::RegionOutlives(_)