@@ -169,46 +169,115 @@ fn lookup_vtable(fcx: @fn_ctxt,
169
169
// Nothing found. Continue.
170
170
}
171
171
Some ( implementations) => {
172
+ /*
173
+ implementations is the list of all impls in scope for
174
+ trait_ty. (Usually, there's just one.)
175
+ */
172
176
for uint:: range( 0 , implementations. len( ) ) |i| {
173
177
let im = implementations[ i] ;
174
178
175
- // im = one specific impl
179
+ // im is one specific impl of trait_ty.
176
180
177
181
// First, ensure that we haven't processed this impl yet.
178
182
if impls_seen. contains_key ( im. did ) {
179
183
again;
180
184
}
181
185
impls_seen. insert ( im. did , ( ) ) ;
182
186
183
- // find the trait that im implements (if any)
187
+
188
+ /*
189
+ ty::impl_traits gives us the list of all traits that im
190
+ implements. Again, usually there's just one.
191
+
192
+ For example, if im represented the struct in:
193
+
194
+ struct foo : baz<int>, bar, quux { ... }
195
+
196
+ then ty::impl_traits would return
197
+ ~[baz<int>, bar, quux]
198
+
199
+ For each of the traits foo implements, if it's the
200
+ same trait as trait_ty, we need to unify it with
201
+ trait_ty in order to get all the ty vars sorted out.
202
+ */
184
203
for vec:: each( ty:: impl_traits( tcx, im. did) ) |of_ty| {
185
- // it must have the same id as the expected one
186
204
match ty:: get ( of_ty) . struct {
205
+ // This is a trait that is different from the one
206
+ // we're looking for, so we skip to the next one.
187
207
ty:: ty_trait( id, _, _) if id != trait_id => again,
188
208
_ => { /* ok */ }
189
209
}
190
210
191
- // check whether the type unifies with the type
192
- // that the impl is for, and continue if not
211
+ /* At this point, we know that of_ty is the same trait
212
+ as trait_ty, but possibly applied to different substs.
213
+
214
+ Next, we check whether the "for" ty in the impl is
215
+ compatible with the type that we're casting to a trait. That
216
+ is, if im is:
217
+
218
+ impl<T> self_ty<T>: some_trait<T> { ... }
219
+
220
+ we check whether self_ty<T> is the type of the thing that
221
+ we're trying to cast to some_trait.
222
+ */
193
223
let { substs: substs , ty: for_ty } =
194
224
impl_self_ty ( fcx, expr, im. did , false ) ;
195
225
let im_bs = ty:: lookup_item_type ( tcx, im. did ) . bounds ;
196
226
match fcx. mk_subty ( false , expr. span , ty, for_ty) {
227
+ // for_ty is not compatible with ty, so this impl is
228
+ // irrelevant and we skip to the next impl
197
229
result:: Err ( _) => again,
230
+ // The impl is an impl for ty of the desired trait.
198
231
result:: Ok ( ( ) ) => ( )
199
232
}
200
233
201
- // check that desired trait type unifies
234
+ /*
235
+ Now, in the previous example, for_ty is bound to the
236
+ type self_ty, and substs is bound to [T].
237
+ */
238
+ debug ! ( "The self ty is %s and its substs are %s" ,
239
+ fcx. infcx. ty_to_str( for_ty) ,
240
+ tys_to_str( fcx. ccx. tcx, substs. tps) ) ;
241
+
242
+ /*
243
+ Next, we unify trait_ty -- the type that we want to cast
244
+ to -- with of_ty -- the trait that im implements. At this
245
+ point, we require that they be unifiable with each other --
246
+ that's what relate_trait_tys does.
247
+
248
+ For example, in the above example, of_ty would be
249
+ some_trait<T>, so we would be unifying trait_ty<U> (for
250
+ some value of U) with some_trait<T>. This would fail if
251
+ T and U weren't compatible.
252
+ */
253
+
202
254
debug ! ( "(checking vtable) @2 relating trait ty %s to \
203
255
of_ty %s",
204
256
fcx. infcx. ty_to_str( trait_ty) ,
205
257
fcx. infcx. ty_to_str( of_ty) ) ;
206
258
let of_ty = ty:: subst ( tcx, & substs, of_ty) ;
207
259
relate_trait_tys ( fcx, expr, trait_ty, of_ty) ;
208
260
209
- // recursively process the bounds.
261
+ /*
262
+ Recall that trait_ty -- the trait type we're casting to --
263
+ is the trait with id trait_id applied to the substs
264
+ trait_substs. Now we extract out the types themselves
265
+ from trait_substs.
266
+ */
267
+
210
268
let trait_tps = trait_substs. tps ;
211
- // see comments around the earlier call to fixup_ty
269
+
270
+ debug ! ( "Casting to a trait ty whose substs \
271
+ (trait_tps) are %s",
272
+ tys_to_str( fcx. ccx. tcx, trait_tps) ) ;
273
+
274
+ /*
275
+ Recall that substs is the impl self type's list of
276
+ substitutions. That is, if this is an impl of some trait
277
+ for foo<T, U>, then substs is [T, U]. substs might contain
278
+ type variables, so we call fixup_substs to resolve them.
279
+ */
280
+
212
281
let substs_f = match fixup_substs ( fcx, expr, trait_id,
213
282
substs, is_early) {
214
283
Some ( substs) => substs,
@@ -219,11 +288,30 @@ fn lookup_vtable(fcx: @fn_ctxt,
219
288
}
220
289
} ;
221
290
291
+ debug ! ( "The fixed-up substs for the self ty are %s - \
292
+ they will be unified with the bounds for \
293
+ the target ty, %s",
294
+ tys_to_str( fcx. ccx. tcx, substs_f. tps) ,
295
+ tys_to_str( fcx. ccx. tcx, trait_tps) ) ;
296
+
297
+ /*
298
+ Next, we unify the fixed-up substitutions for the impl self
299
+ ty with the substitutions from the trait type that we're
300
+ trying to cast to. connect_trait_tps requires these
301
+ lists of types to unify pairwise.
302
+ */
303
+
222
304
connect_trait_tps ( fcx, expr, substs_f. tps ,
223
305
trait_tps, im. did ) ;
224
306
let subres = lookup_vtables (
225
307
fcx, expr, im_bs, & substs_f,
226
308
false , is_early) ;
309
+
310
+ /*
311
+ Finally, we register that we found a matching impl,
312
+ and record the def ID of the impl as well as the resolved
313
+ list of type substitutions for the target trait.
314
+ */
227
315
vec:: push ( found,
228
316
vtable_static ( im. did , substs_f. tps ,
229
317
subres) ) ;
@@ -233,8 +321,8 @@ fn lookup_vtable(fcx: @fn_ctxt,
233
321
}
234
322
235
323
match found. len ( ) {
236
- 0 u => { /* fallthrough */ }
237
- 1 u => { return found[ 0 ] ; }
324
+ 0 => { /* fallthrough */ }
325
+ 1 => { return found[ 0 ] ; }
238
326
_ => {
239
327
if !is_early {
240
328
fcx. ccx . tcx . sess . span_err (
0 commit comments