Skip to content

Commit

Permalink
Rollup merge of #72055 - lcnr:predicate-kind, r=nikomatsakis
Browse files Browse the repository at this point in the history
Intern predicates

Implements the first step of rust-lang/compiler-team#285

Renames `ty::Predicate` to `ty::PredicateKind`, which is now interned.
To ease the transition, `ty::Predicate` is now a struct containing a reference
to `ty::PredicateKind`.

r? @ghost
  • Loading branch information
RalfJung authored May 21, 2020
2 parents 148c125 + 3dd830b commit 22438fc
Show file tree
Hide file tree
Showing 61 changed files with 796 additions and 634 deletions.
19 changes: 11 additions & 8 deletions src/librustc_infer/infer/canonical/query_response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use rustc_middle::arena::ArenaAllocatable;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::relate::TypeRelation;
use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
use rustc_middle::ty::{self, BoundVar, Const, Ty, TyCtxt};
use rustc_middle::ty::{self, BoundVar, Const, ToPredicate, Ty, TyCtxt};
use std::fmt::Debug;

impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
Expand Down Expand Up @@ -532,12 +532,14 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
cause.clone(),
param_env,
match k1.unpack() {
GenericArgKind::Lifetime(r1) => ty::Predicate::RegionOutlives(
GenericArgKind::Lifetime(r1) => ty::PredicateKind::RegionOutlives(
ty::Binder::bind(ty::OutlivesPredicate(r1, r2)),
),
GenericArgKind::Type(t1) => {
ty::Predicate::TypeOutlives(ty::Binder::bind(ty::OutlivesPredicate(t1, r2)))
}
)
.to_predicate(self.tcx),
GenericArgKind::Type(t1) => ty::PredicateKind::TypeOutlives(ty::Binder::bind(
ty::OutlivesPredicate(t1, r2),
))
.to_predicate(self.tcx),
GenericArgKind::Const(..) => {
// Consts cannot outlive one another, so we don't expect to
// ecounter this branch.
Expand Down Expand Up @@ -664,9 +666,10 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> {
self.obligations.push(Obligation {
cause: self.cause.clone(),
param_env: self.param_env,
predicate: ty::Predicate::RegionOutlives(ty::Binder::dummy(ty::OutlivesPredicate(
predicate: ty::PredicateKind::RegionOutlives(ty::Binder::dummy(ty::OutlivesPredicate(
sup, sub,
))),
)))
.to_predicate(self.infcx.tcx),
recursion_depth: 0,
});
}
Expand Down
14 changes: 9 additions & 5 deletions src/librustc_infer/infer/combine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ use rustc_hir::def_id::DefId;
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::{self, InferConst, Ty, TyCtxt, TypeFoldable};
use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeFoldable};
use rustc_middle::ty::{IntType, UintType};
use rustc_span::{Span, DUMMY_SP};

Expand Down Expand Up @@ -307,7 +307,7 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
self.obligations.push(Obligation::new(
self.trace.cause.clone(),
self.param_env,
ty::Predicate::WellFormed(b_ty),
ty::PredicateKind::WellFormed(b_ty).to_predicate(self.infcx.tcx),
));
}

Expand Down Expand Up @@ -398,11 +398,15 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
b: &'tcx ty::Const<'tcx>,
) {
let predicate = if a_is_expected {
ty::Predicate::ConstEquate(a, b)
ty::PredicateKind::ConstEquate(a, b)
} else {
ty::Predicate::ConstEquate(b, a)
ty::PredicateKind::ConstEquate(b, a)
};
self.obligations.push(Obligation::new(self.trace.cause.clone(), self.param_env, predicate));
self.obligations.push(Obligation::new(
self.trace.cause.clone(),
self.param_env,
predicate.to_predicate(self.tcx()),
));
}
}

Expand Down
22 changes: 11 additions & 11 deletions src/librustc_infer/infer/outlives/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,17 @@ pub fn explicit_outlives_bounds<'tcx>(
param_env: ty::ParamEnv<'tcx>,
) -> impl Iterator<Item = OutlivesBound<'tcx>> + 'tcx {
debug!("explicit_outlives_bounds()");
param_env.caller_bounds.into_iter().filter_map(move |predicate| match predicate {
ty::Predicate::Projection(..)
| ty::Predicate::Trait(..)
| ty::Predicate::Subtype(..)
| ty::Predicate::WellFormed(..)
| ty::Predicate::ObjectSafe(..)
| ty::Predicate::ClosureKind(..)
| ty::Predicate::TypeOutlives(..)
| ty::Predicate::ConstEvaluatable(..)
| ty::Predicate::ConstEquate(..) => None,
ty::Predicate::RegionOutlives(ref data) => data
param_env.caller_bounds.into_iter().filter_map(move |predicate| match predicate.kind() {
ty::PredicateKind::Projection(..)
| ty::PredicateKind::Trait(..)
| ty::PredicateKind::Subtype(..)
| ty::PredicateKind::WellFormed(..)
| ty::PredicateKind::ObjectSafe(..)
| ty::PredicateKind::ClosureKind(..)
| ty::PredicateKind::TypeOutlives(..)
| ty::PredicateKind::ConstEvaluatable(..)
| ty::PredicateKind::ConstEquate(..) => None,
ty::PredicateKind::RegionOutlives(ref data) => data
.no_bound_vars()
.map(|ty::OutlivesPredicate(r_a, r_b)| OutlivesBound::RegionSubRegion(r_b, r_a)),
})
Expand Down
7 changes: 4 additions & 3 deletions src/librustc_infer/infer/sub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::traits::Obligation;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::relate::{Cause, Relate, RelateResult, TypeRelation};
use rustc_middle::ty::TyVar;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt};
use std::mem;

/// Ensures `a` is made a subtype of `b`. Returns `a` on success.
Expand Down Expand Up @@ -100,11 +100,12 @@ impl TypeRelation<'tcx> for Sub<'combine, 'infcx, 'tcx> {
self.fields.obligations.push(Obligation::new(
self.fields.trace.cause.clone(),
self.fields.param_env,
ty::Predicate::Subtype(ty::Binder::dummy(ty::SubtypePredicate {
ty::PredicateKind::Subtype(ty::Binder::dummy(ty::SubtypePredicate {
a_is_expected: self.a_is_expected,
a,
b,
})),
}))
.to_predicate(self.tcx()),
));

Ok(a)
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_infer/traits/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ pub trait TraitEngine<'tcx>: 'tcx {
cause,
recursion_depth: 0,
param_env,
predicate: trait_ref.without_const().to_predicate(),
predicate: trait_ref.without_const().to_predicate(infcx.tcx),
},
);
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_infer/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ pub type TraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>;

// `PredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(target_arch = "x86_64")]
static_assert_size!(PredicateObligation<'_>, 112);
static_assert_size!(PredicateObligation<'_>, 88);

pub type Obligations<'tcx, O> = Vec<Obligation<'tcx, O>>;
pub type PredicateObligations<'tcx> = Vec<PredicateObligation<'tcx>>;
Expand Down
82 changes: 46 additions & 36 deletions src/librustc_infer/traits/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,40 +10,49 @@ pub fn anonymize_predicate<'tcx>(
tcx: TyCtxt<'tcx>,
pred: &ty::Predicate<'tcx>,
) -> ty::Predicate<'tcx> {
match *pred {
ty::Predicate::Trait(ref data, constness) => {
ty::Predicate::Trait(tcx.anonymize_late_bound_regions(data), constness)
match pred.kind() {
&ty::PredicateKind::Trait(ref data, constness) => {
ty::PredicateKind::Trait(tcx.anonymize_late_bound_regions(data), constness)
.to_predicate(tcx)
}

ty::Predicate::RegionOutlives(ref data) => {
ty::Predicate::RegionOutlives(tcx.anonymize_late_bound_regions(data))
ty::PredicateKind::RegionOutlives(data) => {
ty::PredicateKind::RegionOutlives(tcx.anonymize_late_bound_regions(data))
.to_predicate(tcx)
}

ty::Predicate::TypeOutlives(ref data) => {
ty::Predicate::TypeOutlives(tcx.anonymize_late_bound_regions(data))
ty::PredicateKind::TypeOutlives(data) => {
ty::PredicateKind::TypeOutlives(tcx.anonymize_late_bound_regions(data))
.to_predicate(tcx)
}

ty::Predicate::Projection(ref data) => {
ty::Predicate::Projection(tcx.anonymize_late_bound_regions(data))
ty::PredicateKind::Projection(data) => {
ty::PredicateKind::Projection(tcx.anonymize_late_bound_regions(data)).to_predicate(tcx)
}

ty::Predicate::WellFormed(data) => ty::Predicate::WellFormed(data),
&ty::PredicateKind::WellFormed(data) => {
ty::PredicateKind::WellFormed(data).to_predicate(tcx)
}

ty::Predicate::ObjectSafe(data) => ty::Predicate::ObjectSafe(data),
&ty::PredicateKind::ObjectSafe(data) => {
ty::PredicateKind::ObjectSafe(data).to_predicate(tcx)
}

ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind)
&ty::PredicateKind::ClosureKind(closure_def_id, closure_substs, kind) => {
ty::PredicateKind::ClosureKind(closure_def_id, closure_substs, kind).to_predicate(tcx)
}

ty::Predicate::Subtype(ref data) => {
ty::Predicate::Subtype(tcx.anonymize_late_bound_regions(data))
ty::PredicateKind::Subtype(data) => {
ty::PredicateKind::Subtype(tcx.anonymize_late_bound_regions(data)).to_predicate(tcx)
}

ty::Predicate::ConstEvaluatable(def_id, substs) => {
ty::Predicate::ConstEvaluatable(def_id, substs)
&ty::PredicateKind::ConstEvaluatable(def_id, substs) => {
ty::PredicateKind::ConstEvaluatable(def_id, substs).to_predicate(tcx)
}

ty::Predicate::ConstEquate(c1, c2) => ty::Predicate::ConstEquate(c1, c2),
ty::PredicateKind::ConstEquate(c1, c2) => {
ty::PredicateKind::ConstEquate(c1, c2).to_predicate(tcx)
}
}
}

Expand Down Expand Up @@ -99,14 +108,14 @@ pub fn elaborate_trait_ref<'tcx>(
tcx: TyCtxt<'tcx>,
trait_ref: ty::PolyTraitRef<'tcx>,
) -> Elaborator<'tcx> {
elaborate_predicates(tcx, std::iter::once(trait_ref.without_const().to_predicate()))
elaborate_predicates(tcx, std::iter::once(trait_ref.without_const().to_predicate(tcx)))
}

pub fn elaborate_trait_refs<'tcx>(
tcx: TyCtxt<'tcx>,
trait_refs: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
) -> Elaborator<'tcx> {
let predicates = trait_refs.map(|trait_ref| trait_ref.without_const().to_predicate());
let predicates = trait_refs.map(|trait_ref| trait_ref.without_const().to_predicate(tcx));
elaborate_predicates(tcx, predicates)
}

Expand Down Expand Up @@ -145,8 +154,8 @@ impl Elaborator<'tcx> {

fn elaborate(&mut self, obligation: &PredicateObligation<'tcx>) {
let tcx = self.visited.tcx;
match obligation.predicate {
ty::Predicate::Trait(ref data, _) => {
match obligation.predicate.kind() {
ty::PredicateKind::Trait(ref data, _) => {
// Get predicates declared on the trait.
let predicates = tcx.super_predicates_of(data.def_id());

Expand All @@ -167,36 +176,36 @@ impl Elaborator<'tcx> {

self.stack.extend(obligations);
}
ty::Predicate::WellFormed(..) => {
ty::PredicateKind::WellFormed(..) => {
// Currently, we do not elaborate WF predicates,
// although we easily could.
}
ty::Predicate::ObjectSafe(..) => {
ty::PredicateKind::ObjectSafe(..) => {
// Currently, we do not elaborate object-safe
// predicates.
}
ty::Predicate::Subtype(..) => {
ty::PredicateKind::Subtype(..) => {
// Currently, we do not "elaborate" predicates like `X <: Y`,
// though conceivably we might.
}
ty::Predicate::Projection(..) => {
ty::PredicateKind::Projection(..) => {
// Nothing to elaborate in a projection predicate.
}
ty::Predicate::ClosureKind(..) => {
ty::PredicateKind::ClosureKind(..) => {
// Nothing to elaborate when waiting for a closure's kind to be inferred.
}
ty::Predicate::ConstEvaluatable(..) => {
ty::PredicateKind::ConstEvaluatable(..) => {
// Currently, we do not elaborate const-evaluatable
// predicates.
}
ty::Predicate::ConstEquate(..) => {
ty::PredicateKind::ConstEquate(..) => {
// Currently, we do not elaborate const-equate
// predicates.
}
ty::Predicate::RegionOutlives(..) => {
ty::PredicateKind::RegionOutlives(..) => {
// Nothing to elaborate from `'a: 'b`.
}
ty::Predicate::TypeOutlives(ref data) => {
ty::PredicateKind::TypeOutlives(ref data) => {
// We know that `T: 'a` for some type `T`. We can
// often elaborate this. For example, if we know that
// `[U]: 'a`, that implies that `U: 'a`. Similarly, if
Expand Down Expand Up @@ -228,15 +237,15 @@ impl Elaborator<'tcx> {
if r.is_late_bound() {
None
} else {
Some(ty::Predicate::RegionOutlives(ty::Binder::dummy(
Some(ty::PredicateKind::RegionOutlives(ty::Binder::dummy(
ty::OutlivesPredicate(r, r_min),
)))
}
}

Component::Param(p) => {
let ty = tcx.mk_ty_param(p.index, p.name);
Some(ty::Predicate::TypeOutlives(ty::Binder::dummy(
Some(ty::PredicateKind::TypeOutlives(ty::Binder::dummy(
ty::OutlivesPredicate(ty, r_min),
)))
}
Expand All @@ -250,8 +259,9 @@ impl Elaborator<'tcx> {
None
}
})
.filter(|p| visited.insert(p))
.map(|p| predicate_obligation(p, None)),
.map(|predicate_kind| predicate_kind.to_predicate(tcx))
.filter(|predicate| visited.insert(predicate))
.map(|predicate| predicate_obligation(predicate, None)),
);
}
}
Expand Down Expand Up @@ -317,7 +327,7 @@ impl<'tcx, I: Iterator<Item = PredicateObligation<'tcx>>> Iterator for FilterToT

fn next(&mut self) -> Option<ty::PolyTraitRef<'tcx>> {
while let Some(obligation) = self.base_iterator.next() {
if let ty::Predicate::Trait(data, _) = obligation.predicate {
if let ty::PredicateKind::Trait(data, _) = obligation.predicate.kind() {
return Some(data.to_poly_trait_ref());
}
}
Expand Down
12 changes: 6 additions & 6 deletions src/librustc_lint/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1202,13 +1202,13 @@ declare_lint_pass!(
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TrivialConstraints {
fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::Item<'tcx>) {
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::Predicate::*;
use rustc_middle::ty::PredicateKind::*;

if cx.tcx.features().trivial_bounds {
let def_id = cx.tcx.hir().local_def_id(item.hir_id);
let predicates = cx.tcx.predicates_of(def_id);
for &(predicate, span) in predicates.predicates {
let predicate_kind_name = match predicate {
let predicate_kind_name = match predicate.kind() {
Trait(..) => "Trait",
TypeOutlives(..) |
RegionOutlives(..) => "Lifetime",
Expand Down Expand Up @@ -1497,8 +1497,8 @@ impl ExplicitOutlivesRequirements {
) -> Vec<ty::Region<'tcx>> {
inferred_outlives
.iter()
.filter_map(|(pred, _)| match pred {
ty::Predicate::RegionOutlives(outlives) => {
.filter_map(|(pred, _)| match pred.kind() {
ty::PredicateKind::RegionOutlives(outlives) => {
let outlives = outlives.skip_binder();
match outlives.0 {
ty::ReEarlyBound(ebr) if ebr.index == index => Some(outlives.1),
Expand All @@ -1516,8 +1516,8 @@ impl ExplicitOutlivesRequirements {
) -> Vec<ty::Region<'tcx>> {
inferred_outlives
.iter()
.filter_map(|(pred, _)| match pred {
ty::Predicate::TypeOutlives(outlives) => {
.filter_map(|(pred, _)| match pred.kind() {
ty::PredicateKind::TypeOutlives(outlives) => {
let outlives = outlives.skip_binder();
outlives.0.is_param(index).then_some(outlives.1)
}
Expand Down
4 changes: 3 additions & 1 deletion src/librustc_lint/unused.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
ty::Opaque(def, _) => {
let mut has_emitted = false;
for (predicate, _) in cx.tcx.predicates_of(def).predicates {
if let ty::Predicate::Trait(ref poly_trait_predicate, _) = predicate {
if let ty::PredicateKind::Trait(ref poly_trait_predicate, _) =
predicate.kind()
{
let trait_ref = poly_trait_predicate.skip_binder().trait_ref;
let def_id = trait_ref.def_id;
let descr_pre =
Expand Down
Loading

0 comments on commit 22438fc

Please sign in to comment.