Skip to content

Commit 8dd715e

Browse files
committed
Auto merge of #51895 - nikomatsakis:move-self-trait-predicate-to-items, r=scalexm
Move self trait predicate to items This is a "reimagination" of @tmandry's PR #50183. The main effect is described in this comment from one of the commits: --- Before we had the following results for `predicates_of`: ```rust trait Foo { // predicates_of: Self: Foo fn bar(); // predicates_of: Self: Foo (inherited from trait) } ``` Now we have removed the `Self: Foo` from the trait. However, we still add it to the trait ITEM. This is because when people do things like `<T as Foo>::bar()`, they still need to prove that `T: Foo`, and having it in the `predicates_of` seems to be the cleanest way to ensure that happens right now (otherwise, we'd need special case code in various places): ```rust trait Foo { // predicates_of: [] fn bar(); // predicates_of: Self: Foo } ``` However, we sometimes want to get the list of *just* the predicates truly defined on a trait item (e.g., for chalk, but also for a few other bits of code). For that, we define `predicates_defined_on`, which does not contain the `Self: Foo` predicate yet, and we plumb that through metadata and so forth. --- I'm assigning @eddyb as the main reviewer, but I thought I might delegate to scalexm for this one in any case. I also want to post an alternative that I'll leave in the comments; it occurred to me as I was writing. =) r? @eddyb cc @scalexm @tmandry @leodasvacas
2 parents a739c51 + 90ea49b commit 8dd715e

File tree

17 files changed

+205
-67
lines changed

17 files changed

+205
-67
lines changed

src/librustc/dep_graph/dep_node.rs

+1
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,7 @@ define_dep_nodes!( <'tcx>
504504
[] GenericsOfItem(DefId),
505505
[] PredicatesOfItem(DefId),
506506
[] ExplicitPredicatesOfItem(DefId),
507+
[] PredicatesDefinedOnItem(DefId),
507508
[] InferredOutlivesOf(DefId),
508509
[] InferredOutlivesCrate(CrateNum),
509510
[] SuperPredicatesOfItem(DefId),

src/librustc/traits/object_safety.rs

+4-9
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ use hir::def_id::DefId;
2323
use lint;
2424
use traits;
2525
use ty::{self, Ty, TyCtxt, TypeFoldable};
26-
use ty::subst::Substs;
2726
use ty::util::ExplicitSelf;
2827
use std::borrow::Cow;
2928
use syntax::ast;
@@ -173,10 +172,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
173172
trait_def_id: DefId,
174173
supertraits_only: bool) -> bool
175174
{
176-
let trait_ref = ty::Binder::dummy(ty::TraitRef {
177-
def_id: trait_def_id,
178-
substs: Substs::identity_for_item(self, trait_def_id)
179-
});
175+
let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(self, trait_def_id));
180176
let predicates = if supertraits_only {
181177
self.super_predicates_of(trait_def_id)
182178
} else {
@@ -391,10 +387,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
391387

392388
// Compute supertraits of current trait lazily.
393389
if supertraits.is_none() {
394-
let trait_ref = ty::Binder::bind(ty::TraitRef {
395-
def_id: trait_def_id,
396-
substs: Substs::identity_for_item(self, trait_def_id)
397-
});
390+
let trait_ref = ty::Binder::bind(
391+
ty::TraitRef::identity(self, trait_def_id),
392+
);
398393
supertraits = Some(traits::supertraits(self, trait_ref).collect());
399394
}
400395

src/librustc/traits/select.rs

+5
Original file line numberDiff line numberDiff line change
@@ -1237,6 +1237,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
12371237
let mut candidates: Vec<EvaluatedCandidate> =
12381238
candidates?.into_iter().filter_map(|c| c).collect();
12391239

1240+
debug!("winnowed to {} candidates for {:?}: {:?}",
1241+
candidates.len(),
1242+
stack,
1243+
candidates);
1244+
12401245
// If there are STILL multiple candidate, we can further
12411246
// reduce the list by dropping duplicates -- including
12421247
// resolving specializations.

src/librustc/ty/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2862,8 +2862,8 @@ fn param_env<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
28622862
}
28632863
// Compute the bounds on Self and the type parameters.
28642864

2865-
let bounds = tcx.predicates_of(def_id).instantiate_identity(tcx);
2866-
let predicates = bounds.predicates;
2865+
let InstantiatedPredicates { predicates } =
2866+
tcx.predicates_of(def_id).instantiate_identity(tcx);
28672867

28682868
// Finally, we have to normalize the bounds in the environment, in
28692869
// case they contain any associated type projections. This process

src/librustc/ty/query/mod.rs

+29-4
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,39 @@ define_queries! { <'tcx>
101101
[] fn type_of: TypeOfItem(DefId) -> Ty<'tcx>,
102102

103103
/// Maps from the def-id of an item (trait/struct/enum/fn) to its
104-
/// associated generics and predicates.
104+
/// associated generics.
105105
[] fn generics_of: GenericsOfItem(DefId) -> &'tcx ty::Generics,
106+
107+
/// Maps from the def-id of an item (trait/struct/enum/fn) to the
108+
/// predicates (where clauses) that must be proven true in order
109+
/// to reference it. This is almost always the "predicates query"
110+
/// that you want.
111+
///
112+
/// `predicates_of` builds on `predicates_defined_on` -- in fact,
113+
/// it is almost always the same as that query, except for the
114+
/// case of traits. For traits, `predicates_of` contains
115+
/// an additional `Self: Trait<...>` predicate that users don't
116+
/// actually write. This reflects the fact that to invoke the
117+
/// trait (e.g., via `Default::default`) you must supply types
118+
/// that actually implement the trait. (However, this extra
119+
/// predicate gets in the way of some checks, which are intended
120+
/// to operate over only the actual where-clauses written by the
121+
/// user.)
106122
[] fn predicates_of: PredicatesOfItem(DefId) -> ty::GenericPredicates<'tcx>,
123+
124+
/// Maps from the def-id of an item (trait/struct/enum/fn) to the
125+
/// predicates (where clauses) directly defined on it. This is
126+
/// equal to the `explicit_predicates_of` predicates plus the
127+
/// `inferred_outlives_of` predicates.
128+
[] fn predicates_defined_on: PredicatesDefinedOnItem(DefId) -> ty::GenericPredicates<'tcx>,
129+
130+
/// Returns the predicates written explicit by the user.
107131
[] fn explicit_predicates_of: ExplicitPredicatesOfItem(DefId) -> ty::GenericPredicates<'tcx>,
108132

133+
/// Returns the inferred outlives predicates (e.g., for `struct
134+
/// Foo<'a, T> { x: &'a T }`, this would return `T: 'a`).
135+
[] fn inferred_outlives_of: InferredOutlivesOf(DefId) -> Lrc<Vec<ty::Predicate<'tcx>>>,
136+
109137
/// Maps from the def-id of a trait to the list of
110138
/// super-predicates. This is a subset of the full list of
111139
/// predicates. We store these in a separate map because we must
@@ -141,9 +169,6 @@ define_queries! { <'tcx>
141169
/// (inferred) variance.
142170
[] fn variances_of: ItemVariances(DefId) -> Lrc<Vec<ty::Variance>>,
143171

144-
/// Maps from def-id of a type to its (inferred) outlives.
145-
[] fn inferred_outlives_of: InferredOutlivesOf(DefId) -> Lrc<Vec<ty::Predicate<'tcx>>>,
146-
147172
/// Maps from def-id of a type to its (inferred) outlives.
148173
[] fn inferred_outlives_crate: InferredOutlivesCrate(CrateNum)
149174
-> Lrc<ty::CratePredicatesMap<'tcx>>,

src/librustc/ty/query/plumbing.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1074,6 +1074,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
10741074
DepKind::TypeOfItem => { force!(type_of, def_id!()); }
10751075
DepKind::GenericsOfItem => { force!(generics_of, def_id!()); }
10761076
DepKind::PredicatesOfItem => { force!(predicates_of, def_id!()); }
1077+
DepKind::PredicatesDefinedOnItem => { force!(predicates_defined_on, def_id!()); }
10771078
DepKind::ExplicitPredicatesOfItem => { force!(explicit_predicates_of, def_id!()); }
10781079
DepKind::InferredOutlivesOf => { force!(inferred_outlives_of, def_id!()); }
10791080
DepKind::InferredOutlivesCrate => { force!(inferred_outlives_crate, LOCAL_CRATE); }

src/librustc/ty/sty.rs

+9
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,15 @@ impl<'tcx> TraitRef<'tcx> {
614614
TraitRef { def_id: def_id, substs: substs }
615615
}
616616

617+
/// Returns a TraitRef of the form `P0: Foo<P1..Pn>` where `Pi`
618+
/// are the parameters defined on trait.
619+
pub fn identity<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, def_id: DefId) -> TraitRef<'tcx> {
620+
TraitRef {
621+
def_id,
622+
substs: Substs::identity_for_item(tcx, def_id),
623+
}
624+
}
625+
617626
pub fn self_ty(&self) -> Ty<'tcx> {
618627
self.substs.type_at(0)
619628
}

src/librustc/ty/util.rs

+15
Original file line numberDiff line numberDiff line change
@@ -518,10 +518,25 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
518518
result
519519
}
520520

521+
/// True if `def_id` refers to a closure (e.g., `|x| x * 2`). Note
522+
/// that closures have a def-id, but the closure *expression* also
523+
/// has a `HirId` that is located within the context where the
524+
/// closure appears (and, sadly, a corresponding `NodeId`, since
525+
/// those are not yet phased out). The parent of the closure's
526+
/// def-id will also be the context where it appears.
521527
pub fn is_closure(self, def_id: DefId) -> bool {
522528
self.def_key(def_id).disambiguated_data.data == DefPathData::ClosureExpr
523529
}
524530

531+
/// True if `def_id` refers to a trait (e.g., `trait Foo { ... }`).
532+
pub fn is_trait(self, def_id: DefId) -> bool {
533+
if let DefPathData::Trait(_) = self.def_key(def_id).disambiguated_data.data {
534+
true
535+
} else {
536+
false
537+
}
538+
}
539+
525540
/// True if this def-id refers to the implicit constructor for
526541
/// a tuple struct like `struct Foo(u32)`.
527542
pub fn is_struct_constructor(self, def_id: DefId) -> bool {

src/librustc_metadata/cstore_impl.rs

+1
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
107107
tcx.alloc_generics(cdata.get_generics(def_id.index, tcx.sess))
108108
}
109109
predicates_of => { cdata.get_predicates(def_id.index, tcx) }
110+
predicates_defined_on => { cdata.get_predicates_defined_on(def_id.index, tcx) }
110111
super_predicates_of => { cdata.get_super_predicates(def_id.index, tcx) }
111112
trait_def => {
112113
tcx.alloc_trait_def(cdata.get_trait_def(def_id.index, tcx.sess))

src/librustc_metadata/decoder.rs

+7
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,13 @@ impl<'a, 'tcx> CrateMetadata {
563563
self.entry(item_id).predicates.unwrap().decode((self, tcx))
564564
}
565565

566+
pub fn get_predicates_defined_on(&self,
567+
item_id: DefIndex,
568+
tcx: TyCtxt<'a, 'tcx, 'tcx>)
569+
-> ty::GenericPredicates<'tcx> {
570+
self.entry(item_id).predicates_defined_on.unwrap().decode((self, tcx))
571+
}
572+
566573
pub fn get_super_predicates(&self,
567574
item_id: DefIndex,
568575
tcx: TyCtxt<'a, 'tcx, 'tcx>)

src/librustc_metadata/encoder.rs

+27
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
629629
},
630630
generics: Some(self.encode_generics(def_id)),
631631
predicates: Some(self.encode_predicates(def_id)),
632+
predicates_defined_on: None,
632633

633634
mir: self.encode_optimized_mir(def_id),
634635
}
@@ -666,6 +667,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
666667
variances: LazySeq::empty(),
667668
generics: None,
668669
predicates: None,
670+
predicates_defined_on: None,
669671

670672
mir: None
671673
}
@@ -706,6 +708,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
706708
variances: LazySeq::empty(),
707709
generics: Some(self.encode_generics(def_id)),
708710
predicates: Some(self.encode_predicates(def_id)),
711+
predicates_defined_on: None,
709712

710713
mir: None,
711714
}
@@ -763,6 +766,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
763766
},
764767
generics: Some(self.encode_generics(def_id)),
765768
predicates: Some(self.encode_predicates(def_id)),
769+
predicates_defined_on: None,
766770

767771
mir: self.encode_optimized_mir(def_id),
768772
}
@@ -780,6 +784,12 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
780784
self.lazy(&tcx.predicates_of(def_id))
781785
}
782786

787+
fn encode_predicates_defined_on(&mut self, def_id: DefId) -> Lazy<ty::GenericPredicates<'tcx>> {
788+
debug!("IsolatedEncoder::encode_predicates_defined_on({:?})", def_id);
789+
let tcx = self.tcx;
790+
self.lazy(&tcx.predicates_defined_on(def_id))
791+
}
792+
783793
fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'tcx> {
784794
debug!("IsolatedEncoder::encode_info_for_trait_item({:?})", def_id);
785795
let tcx = self.tcx;
@@ -869,6 +879,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
869879
},
870880
generics: Some(self.encode_generics(def_id)),
871881
predicates: Some(self.encode_predicates(def_id)),
882+
predicates_defined_on: None,
872883

873884
mir: self.encode_optimized_mir(def_id),
874885
}
@@ -965,6 +976,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
965976
},
966977
generics: Some(self.encode_generics(def_id)),
967978
predicates: Some(self.encode_predicates(def_id)),
979+
predicates_defined_on: None,
968980

969981
mir: if mir { self.encode_optimized_mir(def_id) } else { None },
970982
}
@@ -1228,6 +1240,16 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
12281240
_ => None,
12291241
},
12301242

1243+
// The only time that `predicates_defined_on` is used (on
1244+
// an external item) is for traits, during chalk lowering,
1245+
// so only encode it in that case as an efficiency
1246+
// hack. (No reason not to expand it in the future if
1247+
// necessary.)
1248+
predicates_defined_on: match item.node {
1249+
hir::ItemTrait(..) => Some(self.encode_predicates_defined_on(def_id)),
1250+
_ => None, // not *wrong* for other kinds of items, but not needed
1251+
},
1252+
12311253
mir: match item.node {
12321254
hir::ItemStatic(..) => {
12331255
self.encode_optimized_mir(def_id)
@@ -1278,6 +1300,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
12781300
variances: LazySeq::empty(),
12791301
generics: None,
12801302
predicates: None,
1303+
predicates_defined_on: None,
12811304
mir: None,
12821305
}
12831306
}
@@ -1305,6 +1328,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
13051328
variances: LazySeq::empty(),
13061329
generics: None,
13071330
predicates: None,
1331+
predicates_defined_on: None,
13081332

13091333
mir: None,
13101334
}
@@ -1349,6 +1373,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
13491373
variances: LazySeq::empty(),
13501374
generics: Some(self.encode_generics(def_id)),
13511375
predicates: None,
1376+
predicates_defined_on: None,
13521377

13531378
mir: self.encode_optimized_mir(def_id),
13541379
}
@@ -1376,6 +1401,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
13761401
variances: LazySeq::empty(),
13771402
generics: Some(self.encode_generics(def_id)),
13781403
predicates: Some(self.encode_predicates(def_id)),
1404+
predicates_defined_on: None,
13791405

13801406
mir: self.encode_optimized_mir(def_id),
13811407
}
@@ -1577,6 +1603,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
15771603
},
15781604
generics: Some(self.encode_generics(def_id)),
15791605
predicates: Some(self.encode_predicates(def_id)),
1606+
predicates_defined_on: None,
15801607

15811608
mir: None,
15821609
}

src/librustc_metadata/schema.rs

+2
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ pub struct Entry<'tcx> {
273273
pub variances: LazySeq<ty::Variance>,
274274
pub generics: Option<Lazy<ty::Generics>>,
275275
pub predicates: Option<Lazy<ty::GenericPredicates<'tcx>>>,
276+
pub predicates_defined_on: Option<Lazy<ty::GenericPredicates<'tcx>>>,
276277

277278
pub mir: Option<Lazy<mir::Mir<'tcx>>>,
278279
}
@@ -290,6 +291,7 @@ impl_stable_hash_for!(struct Entry<'tcx> {
290291
variances,
291292
generics,
292293
predicates,
294+
predicates_defined_on,
293295
mir
294296
});
295297

src/librustc_traits/lowering.rs

+3-9
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ use rustc::hir::{self, ImplPolarity};
1515
use rustc::traits::{Clause, Clauses, DomainGoal, Goal, PolyDomainGoal, ProgramClause,
1616
WhereClause, FromEnv, WellFormed};
1717
use rustc::ty::query::Providers;
18-
use rustc::ty::subst::Substs;
1918
use rustc::ty::{self, Slice, TyCtxt};
2019
use rustc_data_structures::fx::FxHashSet;
2120
use std::mem;
@@ -225,10 +224,7 @@ fn program_clauses_for_trait<'a, 'tcx>(
225224

226225
// `Self: Trait<P1..Pn>`
227226
let trait_pred = ty::TraitPredicate {
228-
trait_ref: ty::TraitRef {
229-
def_id,
230-
substs: Substs::identity_for_item(tcx, def_id),
231-
},
227+
trait_ref: ty::TraitRef::identity(tcx, def_id),
232228
};
233229

234230
// `Implemented(Self: Trait<P1..Pn>)`
@@ -256,10 +252,8 @@ fn program_clauses_for_trait<'a, 'tcx>(
256252
// ```
257253

258254
// `FromEnv(WC) :- FromEnv(Self: Trait<P1..Pn>)`, for each where clause WC
259-
// FIXME: Remove the [1..] slice; this is a hack because the query
260-
// predicates_of currently includes the trait itself (`Self: Trait<P1..Pn>`).
261-
let where_clauses = &tcx.predicates_of(def_id).predicates;
262-
let implied_bound_clauses = where_clauses[1..]
255+
let where_clauses = &tcx.predicates_defined_on(def_id).predicates;
256+
let implied_bound_clauses = where_clauses
263257
.into_iter()
264258
.map(|wc| wc.lower())
265259

0 commit comments

Comments
 (0)