@@ -131,7 +131,37 @@ pub enum DepNode<D: Clone + Debug> {
131
131
// which would yield an overly conservative dep-graph.
132
132
TraitItems ( D ) ,
133
133
ReprHints ( D ) ,
134
- TraitSelect ( Vec < D > ) ,
134
+
135
+ // Trait selection cache is a little funny. Given a trait
136
+ // reference like `Foo: SomeTrait<Bar>`, there could be
137
+ // arbitrarily many def-ids to map on in there (e.g., `Foo`,
138
+ // `SomeTrait`, `Bar`). We could have a vector of them, but it
139
+ // requires heap-allocation, and trait sel in general can be a
140
+ // surprisingly hot path. So instead we pick two def-ids: the
141
+ // trait def-id, and the first def-id in the input types. If there
142
+ // is no def-id in the input types, then we use the trait def-id
143
+ // again. So for example:
144
+ //
145
+ // - `i32: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }`
146
+ // - `u32: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }`
147
+ // - `Clone: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Clone }`
148
+ // - `Vec<i32>: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: Vec }`
149
+ // - `String: Clone` -> `TraitSelect { trait_def_id: Clone, self_def_id: String }`
150
+ // - `Foo: Trait<Bar>` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }`
151
+ // - `Foo: Trait<i32>` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }`
152
+ // - `(Foo, Bar): Trait` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }`
153
+ // - `i32: Trait<Foo>` -> `TraitSelect { trait_def_id: Trait, self_def_id: Foo }`
154
+ //
155
+ // You can see that we map many trait refs to the same
156
+ // trait-select node. This is not a problem, it just means
157
+ // imprecision in our dep-graph tracking. The important thing is
158
+ // that for any given trait-ref, we always map to the **same**
159
+ // trait-select node.
160
+ TraitSelect { trait_def_id : D , input_def_id : D } ,
161
+
162
+ // For proj. cache, we just keep a list of all def-ids, since it is
163
+ // not a hotspot.
164
+ ProjectionCache { def_ids : Vec < D > } ,
135
165
}
136
166
137
167
impl < D : Clone + Debug > DepNode < D > {
@@ -236,9 +266,17 @@ impl<D: Clone + Debug> DepNode<D> {
236
266
TraitImpls ( ref d) => op ( d) . map ( TraitImpls ) ,
237
267
TraitItems ( ref d) => op ( d) . map ( TraitItems ) ,
238
268
ReprHints ( ref d) => op ( d) . map ( ReprHints ) ,
239
- TraitSelect ( ref type_ds) => {
240
- let type_ds = try_opt ! ( type_ds. iter( ) . map( |d| op( d) ) . collect( ) ) ;
241
- Some ( TraitSelect ( type_ds) )
269
+ TraitSelect { ref trait_def_id, ref input_def_id } => {
270
+ op ( trait_def_id) . and_then ( |trait_def_id| {
271
+ op ( input_def_id) . and_then ( |input_def_id| {
272
+ Some ( TraitSelect { trait_def_id : trait_def_id,
273
+ input_def_id : input_def_id } )
274
+ } )
275
+ } )
276
+ }
277
+ ProjectionCache { ref def_ids } => {
278
+ let def_ids: Option < Vec < E > > = def_ids. iter ( ) . map ( op) . collect ( ) ;
279
+ def_ids. map ( |d| ProjectionCache { def_ids : d } )
242
280
}
243
281
}
244
282
}
0 commit comments