Skip to content

Commit 90ea49b

Browse files
nikomatsakistmandry
andcommitted
introduce predicates_defined_on for traits
This new query returns only the predicates *directly defined* on an item (in contrast to the more common `predicates_of`, which returns the predicates that must be proven to reference an item). These two sets are almost always identical except for traits, where `predicates_of` includes an artificial `Self: Trait<...>` predicate (basically saying that you cannot use a trait item without proving that the trait is implemented for the type parameters). This new query is only used in chalk lowering, where this artificial `Self: Trait` predicate is problematic. We encode it in metadata but only where needed since it is kind of repetitive with existing information. Co-authored-by: Tyler Mandry <tmandry@gmail.com>
1 parent 3270930 commit 90ea49b

File tree

10 files changed

+109
-21
lines changed

10 files changed

+109
-21
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/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_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
@@ -627,6 +627,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
627627
},
628628
generics: Some(self.encode_generics(def_id)),
629629
predicates: Some(self.encode_predicates(def_id)),
630+
predicates_defined_on: None,
630631

631632
mir: self.encode_optimized_mir(def_id),
632633
}
@@ -664,6 +665,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
664665
variances: LazySeq::empty(),
665666
generics: None,
666667
predicates: None,
668+
predicates_defined_on: None,
667669

668670
mir: None
669671
}
@@ -704,6 +706,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
704706
variances: LazySeq::empty(),
705707
generics: Some(self.encode_generics(def_id)),
706708
predicates: Some(self.encode_predicates(def_id)),
709+
predicates_defined_on: None,
707710

708711
mir: None,
709712
}
@@ -761,6 +764,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
761764
},
762765
generics: Some(self.encode_generics(def_id)),
763766
predicates: Some(self.encode_predicates(def_id)),
767+
predicates_defined_on: None,
764768

765769
mir: self.encode_optimized_mir(def_id),
766770
}
@@ -778,6 +782,12 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
778782
self.lazy(&tcx.predicates_of(def_id))
779783
}
780784

785+
fn encode_predicates_defined_on(&mut self, def_id: DefId) -> Lazy<ty::GenericPredicates<'tcx>> {
786+
debug!("IsolatedEncoder::encode_predicates_defined_on({:?})", def_id);
787+
let tcx = self.tcx;
788+
self.lazy(&tcx.predicates_defined_on(def_id))
789+
}
790+
781791
fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'tcx> {
782792
debug!("IsolatedEncoder::encode_info_for_trait_item({:?})", def_id);
783793
let tcx = self.tcx;
@@ -867,6 +877,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
867877
},
868878
generics: Some(self.encode_generics(def_id)),
869879
predicates: Some(self.encode_predicates(def_id)),
880+
predicates_defined_on: None,
870881

871882
mir: self.encode_optimized_mir(def_id),
872883
}
@@ -963,6 +974,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
963974
},
964975
generics: Some(self.encode_generics(def_id)),
965976
predicates: Some(self.encode_predicates(def_id)),
977+
predicates_defined_on: None,
966978

967979
mir: if mir { self.encode_optimized_mir(def_id) } else { None },
968980
}
@@ -1226,6 +1238,16 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
12261238
_ => None,
12271239
},
12281240

1241+
// The only time that `predicates_defined_on` is used (on
1242+
// an external item) is for traits, during chalk lowering,
1243+
// so only encode it in that case as an efficiency
1244+
// hack. (No reason not to expand it in the future if
1245+
// necessary.)
1246+
predicates_defined_on: match item.node {
1247+
hir::ItemTrait(..) => Some(self.encode_predicates_defined_on(def_id)),
1248+
_ => None, // not *wrong* for other kinds of items, but not needed
1249+
},
1250+
12291251
mir: match item.node {
12301252
hir::ItemStatic(..) => {
12311253
self.encode_optimized_mir(def_id)
@@ -1276,6 +1298,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
12761298
variances: LazySeq::empty(),
12771299
generics: None,
12781300
predicates: None,
1301+
predicates_defined_on: None,
12791302
mir: None,
12801303
}
12811304
}
@@ -1303,6 +1326,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
13031326
variances: LazySeq::empty(),
13041327
generics: None,
13051328
predicates: None,
1329+
predicates_defined_on: None,
13061330

13071331
mir: None,
13081332
}
@@ -1347,6 +1371,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
13471371
variances: LazySeq::empty(),
13481372
generics: Some(self.encode_generics(def_id)),
13491373
predicates: None,
1374+
predicates_defined_on: None,
13501375

13511376
mir: self.encode_optimized_mir(def_id),
13521377
}
@@ -1374,6 +1399,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
13741399
variances: LazySeq::empty(),
13751400
generics: Some(self.encode_generics(def_id)),
13761401
predicates: Some(self.encode_predicates(def_id)),
1402+
predicates_defined_on: None,
13771403

13781404
mir: self.encode_optimized_mir(def_id),
13791405
}
@@ -1575,6 +1601,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
15751601
},
15761602
generics: Some(self.encode_generics(def_id)),
15771603
predicates: Some(self.encode_predicates(def_id)),
1604+
predicates_defined_on: None,
15781605

15791606
mir: None,
15801607
}

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

+2-4
Original file line numberDiff line numberDiff line change
@@ -252,10 +252,8 @@ fn program_clauses_for_trait<'a, 'tcx>(
252252
// ```
253253

254254
// `FromEnv(WC) :- FromEnv(Self: Trait<P1..Pn>)`, for each where clause WC
255-
// FIXME: Remove the [1..] slice; this is a hack because the query
256-
// predicates_of currently includes the trait itself (`Self: Trait<P1..Pn>`).
257-
let where_clauses = &tcx.predicates_of(def_id).predicates;
258-
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
259257
.into_iter()
260258
.map(|wc| wc.lower())
261259

src/librustc_typeck/collect.rs

+37-11
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ pub fn provide(providers: &mut Providers) {
6767
type_of,
6868
generics_of,
6969
predicates_of,
70+
predicates_defined_on,
7071
explicit_predicates_of,
7172
super_predicates_of,
7273
type_param_predicates,
@@ -1309,10 +1310,10 @@ fn early_bound_lifetimes_from_generics<'a, 'tcx>(
13091310
})
13101311
}
13111312

1312-
fn predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
1313-
def_id: DefId)
1314-
-> ty::GenericPredicates<'tcx> {
1315-
let explicit = explicit_predicates_of(tcx, def_id);
1313+
fn predicates_defined_on<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
1314+
def_id: DefId)
1315+
-> ty::GenericPredicates<'tcx> {
1316+
let explicit = tcx.explicit_predicates_of(def_id);
13161317
let predicates = if tcx.sess.features_untracked().infer_outlives_requirements {
13171318
[&explicit.predicates[..], &tcx.inferred_outlives_of(def_id)[..]].concat()
13181319
} else { explicit.predicates };
@@ -1323,9 +1324,35 @@ fn predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
13231324
}
13241325
}
13251326

1326-
pub fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
1327+
fn predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
13271328
def_id: DefId)
13281329
-> ty::GenericPredicates<'tcx> {
1330+
let ty::GenericPredicates { parent, mut predicates } =
1331+
tcx.predicates_defined_on(def_id);
1332+
1333+
if tcx.is_trait(def_id) {
1334+
// For traits, add `Self: Trait` predicate. This is
1335+
// not part of the predicates that a user writes, but it
1336+
// is something that one must prove in order to invoke a
1337+
// method or project an associated type.
1338+
//
1339+
// In the chalk setup, this predicate is not part of the
1340+
// "predicates" for a trait item. But it is useful in
1341+
// rustc because if you directly (e.g.) invoke a trait
1342+
// method like `Trait::method(...)`, you must naturally
1343+
// prove that the trait applies to the types that were
1344+
// used, and adding the predicate into this list ensures
1345+
// that this is done.
1346+
predicates.push(ty::TraitRef::identity(tcx, def_id).to_predicate());
1347+
}
1348+
1349+
ty::GenericPredicates { parent, predicates }
1350+
}
1351+
1352+
fn explicit_predicates_of<'a, 'tcx>(
1353+
tcx: TyCtxt<'a, 'tcx, 'tcx>,
1354+
def_id: DefId,
1355+
) -> ty::GenericPredicates<'tcx> {
13291356
use rustc::hir::map::*;
13301357
use rustc::hir::*;
13311358

@@ -1340,7 +1367,10 @@ pub fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
13401367
let icx = ItemCtxt::new(tcx, def_id);
13411368
let no_generics = hir::Generics::empty();
13421369
let ast_generics = match node {
1343-
NodeTraitItem(item) => &item.generics,
1370+
NodeTraitItem(item) => {
1371+
&item.generics
1372+
}
1373+
13441374
NodeImplItem(item) => &item.generics,
13451375

13461376
NodeItem(item) => {
@@ -1405,12 +1435,8 @@ pub fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
14051435
// and the explicit where-clauses, but to get the full set of predicates
14061436
// on a trait we need to add in the supertrait bounds and bounds found on
14071437
// associated types.
1408-
if let Some((trait_ref, _)) = is_trait {
1438+
if let Some((_trait_ref, _)) = is_trait {
14091439
predicates = tcx.super_predicates_of(def_id).predicates;
1410-
1411-
// Add in a predicate that `Self:Trait` (where `Trait` is the
1412-
// current trait). This is needed for builtin bounds.
1413-
predicates.push(trait_ref.to_poly_trait_ref().to_predicate());
14141440
}
14151441

14161442
// In default impls, we can assume that the self type implements

src/test/ui/chalkify/lower_env1.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error: program clause dump
44
LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66
|
7-
= note: FromEnv(Self: Bar) :- FromEnv(Self: Bar).
7+
= note: FromEnv(Self: Foo) :- FromEnv(Self: Bar).
88
= note: FromEnv(Self: Foo) :- FromEnv(Self: Bar).
99
= note: Implemented(Self: Bar) :- FromEnv(Self: Bar).
1010

@@ -14,7 +14,7 @@ error: program clause dump
1414
LL | #[rustc_dump_env_program_clauses] //~ ERROR program clause dump
1515
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1616
|
17-
= note: FromEnv(Self: Bar) :- FromEnv(Self: Bar).
17+
= note: FromEnv(Self: Foo) :- FromEnv(Self: Bar).
1818
= note: FromEnv(Self: Foo) :- FromEnv(Self: Bar).
1919
= note: Implemented(Self: Bar) :- FromEnv(Self: Bar).
2020
= note: Implemented(Self: Foo) :- FromEnv(Self: Foo).

0 commit comments

Comments
 (0)