@@ -65,27 +65,32 @@ impl<'a,'tcx> PredicateSet<'a,'tcx> {
65
65
66
66
///////////////////////////////////////////////////////////////////////////
67
67
// `Elaboration` iterator
68
- ///////////////////////////////////////////////////////////////////////////
68
+ //
69
+ // "Elaboration" is the process of identifying all the predicates that
70
+ // are implied by a source predicate. This is done by expanding out
71
+ // where clauses declared on a trait. Example:
72
+ //
73
+ // ```
74
+ // trait Foo<T> : Bar<T> where T : Baz { .. }
75
+ // trait Bar<T> { .. }
76
+ // trait Baz { .. }
77
+ // ```
78
+ //
79
+ // Elaborating `X:Foo<Y>` would yield `[X:Foo<Y>, X:Bar<Y>, Y:Baz,
80
+ // Y:Sized]`. If you only want the supertraits (`X:Bar<Y>`, here),
81
+ // see the supertrait iterator below.
69
82
70
- /// "Elaboration" is the process of identifying all the predicates that
71
- /// are implied by a source predicate. Currently this basically means
72
- /// walking the "supertraits" and other similar assumptions. For
73
- /// example, if we know that `T : Ord`, the elaborator would deduce
74
- /// that `T : PartialOrd` holds as well. Similarly, if we have `trait
75
- /// Foo : 'static`, and we know that `T : Foo`, then we know that `T :
76
- /// 'static`.
83
+ /// Elaborates a set of predicates into other predicates that are
84
+ /// implied by the initial set.
77
85
pub struct Elaborator < ' cx , ' tcx : ' cx > {
78
86
tcx : & ' cx ty:: ctxt < ' tcx > ,
79
87
stack : Vec < ty:: Predicate < ' tcx > > ,
80
88
visited : PredicateSet < ' cx , ' tcx > ,
81
- }
82
89
83
- pub fn elaborate_trait_ref < ' cx , ' tcx > (
84
- tcx : & ' cx ty:: ctxt < ' tcx > ,
85
- trait_ref : ty:: PolyTraitRef < ' tcx > )
86
- -> Elaborator < ' cx , ' tcx >
87
- {
88
- elaborate_predicates ( tcx, vec ! [ trait_ref. as_predicate( ) ] )
90
+ /// If true, we only elaborate `A:Foo` to `A:Bar` where `Bar` is a
91
+ /// supertrait of `Foo`. Otherwise, we consider all where-clauses
92
+ /// declared on `Foo`.
93
+ supertraits_only : bool ,
89
94
}
90
95
91
96
pub fn elaborate_trait_refs < ' cx , ' tcx > (
@@ -101,15 +106,24 @@ pub fn elaborate_trait_refs<'cx, 'tcx>(
101
106
102
107
pub fn elaborate_predicates < ' cx , ' tcx > (
103
108
tcx : & ' cx ty:: ctxt < ' tcx > ,
104
- mut predicates : Vec < ty:: Predicate < ' tcx > > )
109
+ predicates : Vec < ty:: Predicate < ' tcx > > )
105
110
-> Elaborator < ' cx , ' tcx >
106
111
{
107
- let mut visited = PredicateSet :: new ( tcx) ;
108
- predicates. retain ( |pred| visited. insert ( pred) ) ;
109
- Elaborator { tcx : tcx, stack : predicates, visited : visited }
112
+ Elaborator :: new ( tcx, predicates, false )
110
113
}
111
114
112
115
impl < ' cx , ' tcx > Elaborator < ' cx , ' tcx > {
116
+ fn new ( tcx : & ' cx ty:: ctxt < ' tcx > ,
117
+ mut predicates : Vec < ty:: Predicate < ' tcx > > ,
118
+ supertraits_only : bool )
119
+ -> Elaborator < ' cx , ' tcx >
120
+ {
121
+ let mut visited = PredicateSet :: new ( tcx) ;
122
+ predicates. retain ( |pred| visited. insert ( pred) ) ;
123
+ Elaborator { tcx : tcx, stack : predicates,
124
+ visited : visited, supertraits_only : supertraits_only }
125
+ }
126
+
113
127
pub fn filter_to_traits ( self ) -> FilterToTraits < Elaborator < ' cx , ' tcx > > {
114
128
FilterToTraits :: new ( self )
115
129
}
@@ -118,7 +132,11 @@ impl<'cx, 'tcx> Elaborator<'cx, 'tcx> {
118
132
match * predicate {
119
133
ty:: Predicate :: Trait ( ref data) => {
120
134
// Predicates declared on the trait.
121
- let predicates = ty:: lookup_super_predicates ( self . tcx , data. def_id ( ) ) ;
135
+ let predicates = if self . supertraits_only {
136
+ ty:: lookup_super_predicates ( self . tcx , data. def_id ( ) )
137
+ } else {
138
+ ty:: lookup_predicates ( self . tcx , data. def_id ( ) )
139
+ } ;
122
140
123
141
let mut predicates: Vec < _ > =
124
142
predicates. predicates
@@ -191,27 +209,55 @@ impl<'cx, 'tcx> Iterator for Elaborator<'cx, 'tcx> {
191
209
192
210
///////////////////////////////////////////////////////////////////////////
193
211
// Supertrait iterator
194
- ///////////////////////////////////////////////////////////////////////////
212
+ //
213
+ // Expanding out the set of supertraits is a subset of the full elaboration
214
+ // described above. The difference can be illustrated easily with this
215
+ // example:
216
+ //
217
+ // ```
218
+ // trait Foo<T> : Bar<T> where T : Baz { .. }
219
+ // trait Bar<T> { .. }
220
+ // trait Baz { .. }
221
+ // ```
222
+ //
223
+ // Given the predicate `X:Foo<Y>`, supertrait expansion would yield
224
+ // `[X:Foo<Y>, X:Bar<Y>]`, but the full elaboration would yield
225
+ // `[X:Foo<Y>, X:Bar<Y>, Y:Baz, Y:Sized]`.
226
+ //
227
+ // Supertraits are the correct choice for vtables and objects (which
228
+ // only contain supertraits). Another time when you want supertraits
229
+ // is when elaborating the set of associated items contained by a
230
+ // trait, which includes only those items defined in supertraits, not
231
+ // arbitrary random traits.
195
232
196
233
pub type Supertraits < ' cx , ' tcx > = FilterToTraits < Elaborator < ' cx , ' tcx > > ;
197
234
198
235
pub fn supertraits < ' cx , ' tcx > ( tcx : & ' cx ty:: ctxt < ' tcx > ,
199
236
trait_ref : ty:: PolyTraitRef < ' tcx > )
200
237
-> Supertraits < ' cx , ' tcx >
201
238
{
202
- elaborate_trait_ref ( tcx, trait_ref) . filter_to_traits ( )
239
+ Elaborator :: new ( tcx, vec ! [ trait_ref. as_predicate ( ) ] , true ) . filter_to_traits ( )
203
240
}
204
241
205
- pub fn transitive_bounds < ' cx , ' tcx > ( tcx : & ' cx ty:: ctxt < ' tcx > ,
206
- bounds : & [ ty:: PolyTraitRef < ' tcx > ] )
207
- -> Supertraits < ' cx , ' tcx >
242
+ pub fn superpredicates < ' cx , ' tcx > ( tcx : & ' cx ty:: ctxt < ' tcx > ,
243
+ trait_refs : Vec < ty:: Predicate < ' tcx > > )
244
+ -> Elaborator < ' cx , ' tcx >
208
245
{
209
- elaborate_trait_refs ( tcx, bounds) . filter_to_traits ( )
246
+ Elaborator :: new ( tcx, trait_refs, true )
247
+ }
248
+
249
+ pub fn supertraits_many < ' cx , ' tcx > ( tcx : & ' cx ty:: ctxt < ' tcx > ,
250
+ trait_refs : & [ ty:: PolyTraitRef < ' tcx > ] )
251
+ -> Supertraits < ' cx , ' tcx >
252
+ {
253
+ let predicates = trait_refs. iter ( )
254
+ . map ( |trait_ref| trait_ref. as_predicate ( ) )
255
+ . collect ( ) ;
256
+ Elaborator :: new ( tcx, predicates, true ) . filter_to_traits ( )
210
257
}
211
258
212
259
///////////////////////////////////////////////////////////////////////////
213
260
// Other
214
- ///////////////////////////////////////////////////////////////////////////
215
261
216
262
/// A filter around an iterator of predicates that makes it yield up
217
263
/// just trait references.
@@ -377,15 +423,17 @@ pub fn upcast<'tcx>(tcx: &ty::ctxt<'tcx>,
377
423
pub fn get_vtable_index_of_object_method < ' tcx > ( tcx : & ty:: ctxt < ' tcx > ,
378
424
object_trait_ref : ty:: PolyTraitRef < ' tcx > ,
379
425
trait_def_id : ast:: DefId ,
380
- method_offset_in_trait : uint ) -> uint {
426
+ method_offset_in_trait : uint )
427
+ -> uint
428
+ {
381
429
// We need to figure the "real index" of the method in a
382
430
// listing of all the methods of an object. We do this by
383
431
// iterating down the supertraits of the object's trait until
384
432
// we find the trait the method came from, counting up the
385
433
// methods from them.
386
434
let mut method_count = 0 ;
387
435
388
- for bound_ref in transitive_bounds ( tcx, & [ object_trait_ref] ) {
436
+ for bound_ref in supertraits ( tcx, object_trait_ref) {
389
437
if bound_ref. def_id ( ) == trait_def_id {
390
438
break ;
391
439
}
0 commit comments