@@ -51,8 +51,8 @@ fn lookup_vtables(fcx: @fn_ctxt,
51
51
match * bound {
52
52
ty:: bound_trait( i_ty) => {
53
53
let i_ty = ty:: subst ( tcx, substs, i_ty) ;
54
- match lookup_vtable ( fcx, expr, * ty, i_ty, allow_unsafe ,
55
- is_early) {
54
+ match lookup_vtable_covariant ( fcx, expr, * ty, i_ty,
55
+ allow_unsafe , is_early) {
56
56
Some ( vtable) => result. push ( vtable) ,
57
57
None => {
58
58
fcx. tcx ( ) . sess . span_fatal (
@@ -91,28 +91,75 @@ fn relate_trait_tys(fcx: @fn_ctxt, expr: @ast::expr,
91
91
demand:: suptype ( fcx, expr. span , exp_trait_ty, act_trait_ty)
92
92
}
93
93
94
- /*
95
- Look up the vtable to use when treating an item of type <t>
96
- as if it has type <trait_ty>
97
- */
98
- fn lookup_vtable ( fcx : @fn_ctxt ,
99
- expr : @ast:: expr ,
100
- ty : ty:: t ,
101
- trait_ty : ty:: t ,
102
- allow_unsafe : bool ,
103
- is_early : bool )
104
- -> Option < vtable_origin >
105
- {
94
+ // Look up the vtable to use when treating an item of type `t` as if it has
95
+ // type `trait_ty`. This does allow subtraits.
96
+ fn lookup_vtable_covariant ( fcx : @fn_ctxt ,
97
+ expr : @ast:: expr ,
98
+ ty : ty:: t ,
99
+ trait_ty : ty:: t ,
100
+ allow_unsafe : bool ,
101
+ is_early : bool )
102
+ -> Option < vtable_origin > {
103
+ let worklist = dvec:: DVec ( ) ;
104
+ worklist. push ( trait_ty) ;
105
+ while worklist. len ( ) > 0 {
106
+ let trait_ty = worklist. pop ( ) ;
107
+ let result = lookup_vtable_invariant ( fcx, expr, ty, trait_ty,
108
+ allow_unsafe, is_early) ;
109
+ if result. is_some ( ) {
110
+ return result;
111
+ }
112
+
113
+ // Add subtraits to the worklist, if applicable.
114
+ match ty:: get ( trait_ty) . sty {
115
+ ty:: ty_trait( trait_id, _, _) => {
116
+ let table = fcx. ccx . coherence_info . supertrait_to_subtraits ;
117
+ match table. find ( trait_id) {
118
+ None => { }
119
+ Some ( subtraits) => {
120
+ for subtraits. each |subtrait_id| {
121
+ // XXX: This is wrong; subtraits should themselves
122
+ // have substs.
123
+ let substs =
124
+ { self_r: None , self_ty: None , tps: ~[ ] } ;
125
+ let trait_ty = ty:: mk_trait ( fcx. ccx . tcx ,
126
+ * subtrait_id,
127
+ substs,
128
+ ty:: vstore_box) ;
129
+ worklist. push ( trait_ty) ;
130
+ }
131
+ }
132
+ }
133
+ }
134
+ _ => {
135
+ fcx. ccx . tcx . sess . impossible_case ( expr. span ,
136
+ "lookup_vtable_covariant: \
137
+ non-trait in worklist") ;
138
+ }
139
+ }
140
+ }
106
141
107
- debug ! ( "lookup_vtable(ty=%s, trait_ty=%s)" ,
142
+ return None ;
143
+ }
144
+
145
+ // Look up the vtable to use when treating an item of type `t` as if it has
146
+ // type `trait_ty`. This does not allow subtraits.
147
+ fn lookup_vtable_invariant ( fcx : @fn_ctxt ,
148
+ expr : @ast:: expr ,
149
+ ty : ty:: t ,
150
+ trait_ty : ty:: t ,
151
+ allow_unsafe : bool ,
152
+ is_early : bool )
153
+ -> Option < vtable_origin > {
154
+ debug ! ( "lookup_vtable_invariant(ty=%s, trait_ty=%s)" ,
108
155
fcx. infcx( ) . ty_to_str( ty) , fcx. inh. infcx. ty_to_str( trait_ty) ) ;
109
156
let _i = indenter ( ) ;
110
157
111
158
let tcx = fcx. ccx . tcx ;
112
159
let ( trait_id, trait_substs) = match ty:: get ( trait_ty) . sty {
113
160
ty:: ty_trait( did, substs, _) => ( did, substs) ,
114
161
_ => tcx. sess . impossible_case ( expr. span ,
115
- "lookup_vtable : \
162
+ "lookup_vtable_invariant : \
116
163
don't know how to handle a non-trait")
117
164
} ;
118
165
let ty = match fixup_ty ( fcx, expr, ty, is_early) {
@@ -150,7 +197,7 @@ fn lookup_vtable(fcx: @fn_ctxt,
150
197
}
151
198
_ => tcx. sess . impossible_case (
152
199
expr. span ,
153
- "lookup_vtable : in loop, \
200
+ "lookup_vtable_invariant : in loop, \
154
201
don't know how to handle a non-trait ity")
155
202
}
156
203
n_bound += 1 u;
@@ -462,24 +509,25 @@ fn early_resolve_expr(ex: @ast::expr, &&fcx: @fn_ctxt, is_early: bool) {
462
509
let target_ty = fcx. expr_ty ( ex) ;
463
510
match ty:: get ( target_ty) . sty {
464
511
ty:: ty_trait( * ) => {
465
- /*
466
- Look up vtables for the type we're casting to,
467
- passing in the source and target type
468
- */
512
+ // Look up vtables for the type we're casting to, passing in the
513
+ // source and target type.
514
+ //
515
+ // XXX: This is invariant and shouldn't be. --pcw
516
+
469
517
let ty = fcx. expr_ty ( src) ;
470
- let vtable_opt = lookup_vtable ( fcx, ex, ty, target_ty, true ,
471
- is_early) ;
518
+ let vtable_opt = lookup_vtable_invariant ( fcx, ex, ty, target_ty,
519
+ true , is_early) ;
472
520
match vtable_opt {
473
521
None => {
474
522
// Try the new-style boxed trait; "@int as @Trait".
475
523
let mut err = false ;
476
524
let ty = structurally_resolved_type ( fcx, ex. span , ty) ;
477
525
match ty:: get ( ty) . sty {
478
526
ty:: ty_box( boxed_ty) => {
479
- let vtable_opt = lookup_vtable ( fcx , ex ,
480
- boxed_ty. ty ,
481
- target_ty, true ,
482
- is_early) ;
527
+ let vtable_opt =
528
+ lookup_vtable_invariant ( fcx , ex , boxed_ty. ty ,
529
+ target_ty, true ,
530
+ is_early) ;
483
531
match vtable_opt {
484
532
Some ( vtable) => {
485
533
/*
0 commit comments