Skip to content

Commit 06675ca

Browse files
committed
Comment the default case in typeck::check::vtable::lookup_vtable copiously
Try to save the next person who looks at this code the heartbreak that I went through.
1 parent a70e37b commit 06675ca

File tree

1 file changed

+98
-10
lines changed

1 file changed

+98
-10
lines changed

src/rustc/middle/typeck/check/vtable.rs

+98-10
Original file line numberDiff line numberDiff line change
@@ -169,46 +169,115 @@ fn lookup_vtable(fcx: @fn_ctxt,
169169
// Nothing found. Continue.
170170
}
171171
Some(implementations) => {
172+
/*
173+
implementations is the list of all impls in scope for
174+
trait_ty. (Usually, there's just one.)
175+
*/
172176
for uint::range(0, implementations.len()) |i| {
173177
let im = implementations[i];
174178

175-
// im = one specific impl
179+
// im is one specific impl of trait_ty.
176180

177181
// First, ensure that we haven't processed this impl yet.
178182
if impls_seen.contains_key(im.did) {
179183
again;
180184
}
181185
impls_seen.insert(im.did, ());
182186

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+
*/
184203
for vec::each(ty::impl_traits(tcx, im.did)) |of_ty| {
185-
// it must have the same id as the expected one
186204
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.
187207
ty::ty_trait(id, _, _) if id != trait_id => again,
188208
_ => { /* ok */ }
189209
}
190210

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+
*/
193223
let {substs: substs, ty: for_ty} =
194224
impl_self_ty(fcx, expr, im.did, false);
195225
let im_bs = ty::lookup_item_type(tcx, im.did).bounds;
196226
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
197229
result::Err(_) => again,
230+
// The impl is an impl for ty of the desired trait.
198231
result::Ok(()) => ()
199232
}
200233

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+
202254
debug!("(checking vtable) @2 relating trait ty %s to \
203255
of_ty %s",
204256
fcx.infcx.ty_to_str(trait_ty),
205257
fcx.infcx.ty_to_str(of_ty));
206258
let of_ty = ty::subst(tcx, &substs, of_ty);
207259
relate_trait_tys(fcx, expr, trait_ty, of_ty);
208260

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+
210268
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+
212281
let substs_f = match fixup_substs(fcx, expr, trait_id,
213282
substs, is_early) {
214283
Some(substs) => substs,
@@ -219,11 +288,30 @@ fn lookup_vtable(fcx: @fn_ctxt,
219288
}
220289
};
221290

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+
222304
connect_trait_tps(fcx, expr, substs_f.tps,
223305
trait_tps, im.did);
224306
let subres = lookup_vtables(
225307
fcx, expr, im_bs, &substs_f,
226308
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+
*/
227315
vec::push(found,
228316
vtable_static(im.did, substs_f.tps,
229317
subres));
@@ -233,8 +321,8 @@ fn lookup_vtable(fcx: @fn_ctxt,
233321
}
234322

235323
match found.len() {
236-
0u => { /* fallthrough */ }
237-
1u => { return found[0]; }
324+
0 => { /* fallthrough */ }
325+
1 => { return found[0]; }
238326
_ => {
239327
if !is_early {
240328
fcx.ccx.tcx.sess.span_err(

0 commit comments

Comments
 (0)