Rollup merge of #112772 - compiler-errors:clauses-1, r=lcnr
Add a fully fledged `Clause` type, rename old `Clause` to `ClauseKind` Does two basic things before I put up a more delicate set of PRs (along the lines of #112714, but hopefully much cleaner) that migrate existing usages of `ty::Predicate` to `ty::Clause` (`predicates_of`/`item_bounds`/`ParamEnv::caller_bounds`). 1. Rename `Clause` to `ClauseKind`, so it's parallel with `PredicateKind`. 2. Add a new `Clause` type which is parallel to `Predicate`. * This type exposes `Clause::kind(self) -> Binder<'tcx, ClauseKind<'tcx>>` which is parallel to `Predicate::kind` 😸 The new `Clause` type essentially acts as a newtype wrapper around `Predicate` that asserts that it is specifically a `PredicateKind::Clause`. Turns out from experimentation[^1] that this is not negative performance-wise, which is wonderful, since this a much simpler design than something that requires encoding the discriminant into the alignment bits of a predicate kind, or something else like that... r? ``@lcnr`` or ``@oli-obk`` [^1]: https://github.com/rust-lang/rust/pull/112714#issuecomment-1595653910
This commit is contained in:
commit
a98c14f3a9
101 changed files with 725 additions and 608 deletions
|
@ -584,12 +584,12 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
let ty::OutlivesPredicate(k1, r2) = predicate;
|
||||
|
||||
let atom = match k1.unpack() {
|
||||
GenericArgKind::Lifetime(r1) => {
|
||||
ty::PredicateKind::Clause(ty::Clause::RegionOutlives(ty::OutlivesPredicate(r1, r2)))
|
||||
}
|
||||
GenericArgKind::Type(t1) => {
|
||||
ty::PredicateKind::Clause(ty::Clause::TypeOutlives(ty::OutlivesPredicate(t1, r2)))
|
||||
}
|
||||
GenericArgKind::Lifetime(r1) => ty::PredicateKind::Clause(
|
||||
ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(r1, r2)),
|
||||
),
|
||||
GenericArgKind::Type(t1) => ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(
|
||||
ty::OutlivesPredicate(t1, r2),
|
||||
)),
|
||||
GenericArgKind::Const(..) => {
|
||||
// Consts cannot outlive one another, so we don't expect to
|
||||
// encounter this branch.
|
||||
|
@ -739,9 +739,9 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> {
|
|||
self.obligations.push(Obligation {
|
||||
cause: self.cause.clone(),
|
||||
param_env: self.param_env,
|
||||
predicate: ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::RegionOutlives(
|
||||
ty::OutlivesPredicate(sup, sub),
|
||||
)))
|
||||
predicate: ty::Binder::dummy(ty::PredicateKind::Clause(
|
||||
ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(sup, sub)),
|
||||
))
|
||||
.to_predicate(self.infcx.tcx),
|
||||
recursion_depth: 0,
|
||||
});
|
||||
|
|
|
@ -414,7 +414,9 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
|
|||
self.tcx(),
|
||||
self.trace.cause.clone(),
|
||||
self.param_env,
|
||||
ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::WellFormed(b_ty.into()))),
|
||||
ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(
|
||||
b_ty.into(),
|
||||
))),
|
||||
));
|
||||
}
|
||||
|
||||
|
|
|
@ -408,9 +408,9 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
predicate
|
||||
.kind()
|
||||
.map_bound(|kind| match kind {
|
||||
ty::PredicateKind::Clause(ty::Clause::Projection(projection_predicate))
|
||||
if projection_predicate.projection_ty.def_id == item_def_id =>
|
||||
{
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::Projection(
|
||||
projection_predicate,
|
||||
)) if projection_predicate.projection_ty.def_id == item_def_id => {
|
||||
projection_predicate.term.ty()
|
||||
}
|
||||
_ => None,
|
||||
|
|
|
@ -649,7 +649,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
ct_op: |ct| ct,
|
||||
});
|
||||
|
||||
if let ty::PredicateKind::Clause(ty::Clause::Projection(projection)) =
|
||||
if let ty::PredicateKind::Clause(ty::ClauseKind::Projection(projection)) =
|
||||
predicate.kind().skip_binder()
|
||||
{
|
||||
if projection.term.references_error() {
|
||||
|
|
|
@ -23,21 +23,21 @@ pub fn explicit_outlives_bounds<'tcx>(
|
|||
.map(ty::Predicate::kind)
|
||||
.filter_map(ty::Binder::no_bound_vars)
|
||||
.filter_map(move |kind| match kind {
|
||||
ty::PredicateKind::Clause(ty::Clause::Projection(..))
|
||||
| ty::PredicateKind::Clause(ty::Clause::Trait(..))
|
||||
| ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::Projection(..))
|
||||
| ty::PredicateKind::Clause(ty::ClauseKind::Trait(..))
|
||||
| ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))
|
||||
| ty::PredicateKind::AliasRelate(..)
|
||||
| ty::PredicateKind::Coerce(..)
|
||||
| ty::PredicateKind::Subtype(..)
|
||||
| ty::PredicateKind::Clause(ty::Clause::WellFormed(..))
|
||||
| ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..))
|
||||
| ty::PredicateKind::ObjectSafe(..)
|
||||
| ty::PredicateKind::ClosureKind(..)
|
||||
| ty::PredicateKind::Clause(ty::Clause::TypeOutlives(..))
|
||||
| ty::PredicateKind::Clause(ty::Clause::ConstEvaluatable(..))
|
||||
| ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(..))
|
||||
| ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
|
||||
| ty::PredicateKind::ConstEquate(..)
|
||||
| ty::PredicateKind::Ambiguous
|
||||
| ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
|
||||
ty::PredicateKind::Clause(ty::Clause::RegionOutlives(ty::OutlivesPredicate(
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(
|
||||
r_a,
|
||||
r_b,
|
||||
))) => Some(OutlivesBound::RegionSubRegion(r_b, r_a)),
|
||||
|
|
|
@ -27,7 +27,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
//
|
||||
// The new solver correctly handles projection equality so this hack
|
||||
// is not necessary. if re-enabled it should emit `PredicateKind::AliasRelate`
|
||||
// not `PredicateKind::Clause(Clause::Projection(..))` as in the new solver
|
||||
// not `PredicateKind::Clause(ClauseKind::Projection(..))` as in the new solver
|
||||
// `Projection` is used as `normalizes-to` which will fail for `<T as Trait>::Assoc eq ?0`.
|
||||
return projection_ty.to_ty(self.tcx);
|
||||
} else {
|
||||
|
@ -36,9 +36,10 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
kind: TypeVariableOriginKind::NormalizeProjectionType,
|
||||
span: self.tcx.def_span(def_id),
|
||||
});
|
||||
let projection = ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::Projection(
|
||||
ty::ProjectionPredicate { projection_ty, term: ty_var.into() },
|
||||
)));
|
||||
let projection =
|
||||
ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::Projection(
|
||||
ty::ProjectionPredicate { projection_ty, term: ty_var.into() },
|
||||
)));
|
||||
let obligation =
|
||||
Obligation::with_depth(self.tcx, cause, recursion_depth, param_env, projection);
|
||||
obligations.push(obligation);
|
||||
|
|
|
@ -79,8 +79,8 @@ impl<'tcx> PredicateObligation<'tcx> {
|
|||
|
||||
pub fn without_const(mut self, tcx: TyCtxt<'tcx>) -> PredicateObligation<'tcx> {
|
||||
self.param_env = self.param_env.without_const();
|
||||
if let ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) = self.predicate.kind().skip_binder() && trait_pred.is_const_if_const() {
|
||||
self.predicate = tcx.mk_predicate(self.predicate.kind().map_bound(|_| ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred.without_const()))));
|
||||
if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) = self.predicate.kind().skip_binder() && trait_pred.is_const_if_const() {
|
||||
self.predicate = tcx.mk_predicate(self.predicate.kind().map_bound(|_| ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred.without_const()))));
|
||||
}
|
||||
self
|
||||
}
|
||||
|
|
|
@ -167,6 +167,26 @@ impl<'tcx> Elaboratable<'tcx> for (ty::Predicate<'tcx>, Span) {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Elaboratable<'tcx> for ty::Clause<'tcx> {
|
||||
fn predicate(&self) -> ty::Predicate<'tcx> {
|
||||
self.as_predicate()
|
||||
}
|
||||
|
||||
fn child(&self, predicate: ty::Predicate<'tcx>) -> Self {
|
||||
predicate.as_clause().unwrap()
|
||||
}
|
||||
|
||||
fn child_with_derived_cause(
|
||||
&self,
|
||||
predicate: ty::Predicate<'tcx>,
|
||||
_span: Span,
|
||||
_parent_trait_pred: ty::PolyTraitPredicate<'tcx>,
|
||||
_index: usize,
|
||||
) -> Self {
|
||||
predicate.as_clause().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn elaborate<'tcx, O: Elaboratable<'tcx>>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
obligations: impl IntoIterator<Item = O>,
|
||||
|
@ -199,7 +219,7 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
|
|||
|
||||
let bound_predicate = elaboratable.predicate().kind();
|
||||
match bound_predicate.skip_binder() {
|
||||
ty::PredicateKind::Clause(ty::Clause::Trait(data)) => {
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => {
|
||||
// Negative trait bounds do not imply any supertrait bounds
|
||||
if data.polarity == ty::ImplPolarity::Negative {
|
||||
return;
|
||||
|
@ -227,7 +247,7 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
|
|||
debug!(?data, ?obligations, "super_predicates");
|
||||
self.extend_deduped(obligations);
|
||||
}
|
||||
ty::PredicateKind::Clause(ty::Clause::WellFormed(..)) => {
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..)) => {
|
||||
// Currently, we do not elaborate WF predicates,
|
||||
// although we easily could.
|
||||
}
|
||||
|
@ -243,13 +263,13 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
|
|||
// Currently, we do not "elaborate" predicates like `X -> Y`,
|
||||
// though conceivably we might.
|
||||
}
|
||||
ty::PredicateKind::Clause(ty::Clause::Projection(..)) => {
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::Projection(..)) => {
|
||||
// Nothing to elaborate in a projection predicate.
|
||||
}
|
||||
ty::PredicateKind::ClosureKind(..) => {
|
||||
// Nothing to elaborate when waiting for a closure's kind to be inferred.
|
||||
}
|
||||
ty::PredicateKind::Clause(ty::Clause::ConstEvaluatable(..)) => {
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) => {
|
||||
// Currently, we do not elaborate const-evaluatable
|
||||
// predicates.
|
||||
}
|
||||
|
@ -257,10 +277,10 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
|
|||
// Currently, we do not elaborate const-equate
|
||||
// predicates.
|
||||
}
|
||||
ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..)) => {
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(..)) => {
|
||||
// Nothing to elaborate from `'a: 'b`.
|
||||
}
|
||||
ty::PredicateKind::Clause(ty::Clause::TypeOutlives(ty::OutlivesPredicate(
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(
|
||||
ty_max,
|
||||
r_min,
|
||||
))) => {
|
||||
|
@ -292,7 +312,7 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
|
|||
if r.is_late_bound() {
|
||||
None
|
||||
} else {
|
||||
Some(ty::PredicateKind::Clause(ty::Clause::RegionOutlives(
|
||||
Some(ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(
|
||||
ty::OutlivesPredicate(r, r_min),
|
||||
)))
|
||||
}
|
||||
|
@ -300,7 +320,7 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
|
|||
|
||||
Component::Param(p) => {
|
||||
let ty = tcx.mk_ty_param(p.index, p.name);
|
||||
Some(ty::PredicateKind::Clause(ty::Clause::TypeOutlives(
|
||||
Some(ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(
|
||||
ty::OutlivesPredicate(ty, r_min),
|
||||
)))
|
||||
}
|
||||
|
@ -310,7 +330,7 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
|
|||
Component::Alias(alias_ty) => {
|
||||
// We might end up here if we have `Foo<<Bar as Baz>::Assoc>: 'a`.
|
||||
// With this, we can deduce that `<Bar as Baz>::Assoc: 'a`.
|
||||
Some(ty::PredicateKind::Clause(ty::Clause::TypeOutlives(
|
||||
Some(ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(
|
||||
ty::OutlivesPredicate(alias_ty.to_ty(tcx), r_min),
|
||||
)))
|
||||
}
|
||||
|
@ -334,7 +354,7 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
|
|||
ty::PredicateKind::AliasRelate(..) => {
|
||||
// No
|
||||
}
|
||||
ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) => {
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) => {
|
||||
// Nothing to elaborate
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue