1
1
use check:: { fn_ctxt, impl_self_ty} ;
2
2
use infer:: { resolve_type, resolve_and_force_all_but_regions,
3
3
fixup_err_to_str} ;
4
+ use syntax:: codemap:: span;
4
5
use syntax:: print:: pprust;
5
6
use result:: { Result , Ok , Err } ;
6
7
use util:: common:: indenter;
@@ -21,6 +22,14 @@ use util::common::indenter;
21
22
// would require much more care, and this seems to work decently in
22
23
// practice.)
23
24
25
+ /// Location info records the span and ID of the expression or item that is
26
+ /// responsible for this vtable instantiation. (This may not be an expression
27
+ /// if the vtable instantiation is being performed as part of "deriving".)
28
+ struct LocationInfo {
29
+ span : span ,
30
+ id : ast:: node_id
31
+ }
32
+
24
33
fn has_trait_bounds ( tps : ~[ ty:: param_bounds ] ) -> bool {
25
34
vec:: any ( tps, |bs| {
26
35
bs. any ( |b| {
@@ -30,16 +39,16 @@ fn has_trait_bounds(tps: ~[ty::param_bounds]) -> bool {
30
39
}
31
40
32
41
fn lookup_vtables ( fcx : @fn_ctxt ,
33
- expr : @ast :: expr ,
42
+ location_info : & LocationInfo ,
34
43
bounds : @~[ ty:: param_bounds ] ,
35
44
substs : & ty:: substs ,
36
45
allow_unsafe : bool ,
37
46
is_early : bool ) -> vtable_res
38
47
{
39
- debug ! ( "lookup_vtables(expr =%?/%s, \
48
+ debug ! ( "lookup_vtables(location_info =%?,
40
49
# bounds=%?, \
41
50
substs=%s",
42
- expr . id , fcx . expr_to_str ( expr ) ,
51
+ location_info ,
43
52
bounds. len( ) ,
44
53
ty:: substs_to_str( fcx. tcx( ) , substs) ) ;
45
54
let _i = indenter ( ) ;
@@ -51,12 +60,12 @@ fn lookup_vtables(fcx: @fn_ctxt,
51
60
match * bound {
52
61
ty:: bound_trait( i_ty) => {
53
62
let i_ty = ty:: subst ( tcx, substs, i_ty) ;
54
- match lookup_vtable_covariant ( fcx, expr , * ty, i_ty,
63
+ match lookup_vtable_covariant ( fcx, location_info , * ty, i_ty,
55
64
allow_unsafe, is_early) {
56
65
Some ( vtable) => result. push ( vtable) ,
57
66
None => {
58
67
fcx. tcx ( ) . sess . span_fatal (
59
- expr . span ,
68
+ location_info . span ,
60
69
fmt ! ( "failed to find an implementation of trait \
61
70
%s for %s",
62
71
ty_to_str( fcx. tcx( ) , i_ty) ,
@@ -72,29 +81,29 @@ fn lookup_vtables(fcx: @fn_ctxt,
72
81
@result
73
82
}
74
83
75
- fn fixup_substs ( fcx : @fn_ctxt , expr : @ast :: expr ,
84
+ fn fixup_substs ( fcx : @fn_ctxt , location_info : & LocationInfo ,
76
85
id : ast:: def_id , substs : ty:: substs ,
77
86
is_early : bool ) -> Option < ty:: substs > {
78
87
let tcx = fcx. ccx . tcx ;
79
88
// use a dummy type just to package up the substs that need fixing up
80
89
let t = ty:: mk_trait ( tcx, id, substs, ty:: vstore_slice ( ty:: re_static) ) ;
81
- do fixup_ty( fcx, expr , t, is_early) . map |t_f| {
90
+ do fixup_ty( fcx, location_info , t, is_early) . map |t_f| {
82
91
match ty:: get ( * t_f) . sty {
83
92
ty:: ty_trait( _, substs_f, _) => substs_f,
84
93
_ => fail ~"t_f should be a trait"
85
94
}
86
95
}
87
96
}
88
97
89
- fn relate_trait_tys ( fcx : @fn_ctxt , expr : @ast :: expr ,
98
+ fn relate_trait_tys ( fcx : @fn_ctxt , location_info : & LocationInfo ,
90
99
exp_trait_ty : ty:: t , act_trait_ty : ty:: t ) {
91
- demand:: suptype ( fcx, expr . span , exp_trait_ty, act_trait_ty)
100
+ demand:: suptype ( fcx, location_info . span , exp_trait_ty, act_trait_ty)
92
101
}
93
102
94
103
// Look up the vtable to use when treating an item of type `t` as if it has
95
104
// type `trait_ty`. This does allow subtraits.
96
105
fn lookup_vtable_covariant ( fcx : @fn_ctxt ,
97
- expr : @ast :: expr ,
106
+ location_info : & LocationInfo ,
98
107
ty : ty:: t ,
99
108
trait_ty : ty:: t ,
100
109
allow_unsafe : bool ,
@@ -108,7 +117,7 @@ fn lookup_vtable_covariant(fcx: @fn_ctxt,
108
117
worklist. push ( trait_ty) ;
109
118
while worklist. len ( ) > 0 {
110
119
let trait_ty = worklist. pop ( ) ;
111
- let result = lookup_vtable_invariant ( fcx, expr , ty, trait_ty,
120
+ let result = lookup_vtable_invariant ( fcx, location_info , ty, trait_ty,
112
121
allow_unsafe, is_early) ;
113
122
if result. is_some ( ) {
114
123
return result;
@@ -136,7 +145,7 @@ fn lookup_vtable_covariant(fcx: @fn_ctxt,
136
145
}
137
146
}
138
147
_ => {
139
- fcx. ccx . tcx . sess . impossible_case ( expr . span ,
148
+ fcx. ccx . tcx . sess . impossible_case ( location_info . span ,
140
149
"lookup_vtable_covariant: \
141
150
non-trait in worklist") ;
142
151
}
@@ -149,7 +158,7 @@ fn lookup_vtable_covariant(fcx: @fn_ctxt,
149
158
// Look up the vtable to use when treating an item of type `t` as if it has
150
159
// type `trait_ty`. This does not allow subtraits.
151
160
fn lookup_vtable_invariant ( fcx : @fn_ctxt ,
152
- expr : @ast :: expr ,
161
+ location_info : & LocationInfo ,
153
162
ty : ty:: t ,
154
163
trait_ty : ty:: t ,
155
164
allow_unsafe : bool ,
@@ -162,11 +171,11 @@ fn lookup_vtable_invariant(fcx: @fn_ctxt,
162
171
let tcx = fcx. ccx . tcx ;
163
172
let ( trait_id, trait_substs, trait_vstore) = match ty:: get ( trait_ty) . sty {
164
173
ty:: ty_trait( did, substs, vstore) => ( did, substs, vstore) ,
165
- _ => tcx. sess . impossible_case ( expr . span ,
174
+ _ => tcx. sess . impossible_case ( location_info . span ,
166
175
"lookup_vtable_invariant: \
167
176
don't know how to handle a non-trait")
168
177
} ;
169
- let ty = match fixup_ty ( fcx, expr , ty, is_early) {
178
+ let ty = match fixup_ty ( fcx, location_info , ty, is_early) {
170
179
Some ( ty) => ty,
171
180
None => {
172
181
// fixup_ty can only fail if this is early resolution
@@ -194,13 +203,13 @@ fn lookup_vtable_invariant(fcx: @fn_ctxt,
194
203
debug ! ( "(checking vtable) @0 relating \
195
204
ty to trait ty with did %?",
196
205
idid) ;
197
- relate_trait_tys ( fcx, expr ,
206
+ relate_trait_tys ( fcx, location_info ,
198
207
trait_ty, ity) ;
199
208
return Some ( vtable_param ( n, n_bound) ) ;
200
209
}
201
210
}
202
211
_ => tcx. sess . impossible_case (
203
- expr . span ,
212
+ location_info . span ,
204
213
"lookup_vtable_invariant: in loop, \
205
214
don't know how to handle a non-trait ity")
206
215
}
@@ -214,17 +223,17 @@ fn lookup_vtable_invariant(fcx: @fn_ctxt,
214
223
debug ! ( "(checking vtable) @1 relating ty to trait ty with did %?" ,
215
224
did) ;
216
225
217
- relate_trait_tys ( fcx, expr , trait_ty, ty) ;
226
+ relate_trait_tys ( fcx, location_info , trait_ty, ty) ;
218
227
if !allow_unsafe && !is_early {
219
228
for vec:: each( * ty:: trait_methods( tcx, did) ) |m| {
220
229
if ty:: type_has_self ( ty:: mk_fn ( tcx, m. fty ) ) {
221
230
tcx. sess . span_err (
222
- expr . span ,
231
+ location_info . span ,
223
232
~"a boxed trait with self types may not be \
224
233
passed as a bounded type ") ;
225
234
} else if ( * m. tps ) . len ( ) > 0 u {
226
235
tcx. sess . span_err (
227
- expr . span ,
236
+ location_info . span ,
228
237
~"a boxed trait with generic methods may not \
229
238
be passed as a bounded type ") ;
230
239
@@ -300,10 +309,11 @@ fn lookup_vtable_invariant(fcx: @fn_ctxt,
300
309
// to some_trait. If not, then we try the next
301
310
// impl.
302
311
let { substs: substs , ty: for_ty } =
303
- impl_self_ty ( fcx, expr , im. did ) ;
312
+ impl_self_ty ( fcx, location_info , im. did ) ;
304
313
let im_bs = ty:: lookup_item_type ( tcx,
305
314
im. did ) . bounds ;
306
- match fcx. mk_subty ( false , expr. span , ty, for_ty) {
315
+ match fcx. mk_subty ( false , location_info. span , ty,
316
+ for_ty) {
307
317
result:: Err ( _) => loop ,
308
318
result:: Ok ( ( ) ) => ( )
309
319
}
@@ -334,7 +344,8 @@ fn lookup_vtable_invariant(fcx: @fn_ctxt,
334
344
fcx. infcx( ) . ty_to_str( trait_ty) ,
335
345
fcx. infcx( ) . ty_to_str( * of_ty) ) ;
336
346
let of_ty = ty:: subst ( tcx, & substs, * of_ty) ;
337
- relate_trait_tys ( fcx, expr, trait_ty, of_ty) ;
347
+ relate_trait_tys ( fcx, location_info, trait_ty,
348
+ of_ty) ;
338
349
339
350
// Recall that trait_ty -- the trait type
340
351
// we're casting to -- is the trait with
@@ -357,7 +368,7 @@ fn lookup_vtable_invariant(fcx: @fn_ctxt,
357
368
// resolve them.
358
369
359
370
let substs_f = match fixup_substs ( fcx,
360
- expr ,
371
+ location_info ,
361
372
trait_id,
362
373
substs,
363
374
is_early) {
@@ -382,11 +393,14 @@ fn lookup_vtable_invariant(fcx: @fn_ctxt,
382
393
// to. connect_trait_tps requires these
383
394
// lists of types to unify pairwise.
384
395
385
- connect_trait_tps ( fcx, expr, substs_f. tps ,
386
- trait_tps, im. did ,
396
+ connect_trait_tps ( fcx,
397
+ location_info,
398
+ substs_f. tps ,
399
+ trait_tps,
400
+ im. did ,
387
401
trait_vstore) ;
388
402
let subres = lookup_vtables (
389
- fcx, expr , im_bs, & substs_f,
403
+ fcx, location_info , im_bs, & substs_f,
390
404
false , is_early) ;
391
405
392
406
// Finally, we register that we found a
@@ -408,7 +422,7 @@ fn lookup_vtable_invariant(fcx: @fn_ctxt,
408
422
_ => {
409
423
if !is_early {
410
424
fcx. ccx . tcx . sess . span_err (
411
- expr . span ,
425
+ location_info . span ,
412
426
~"multiple applicable methods in scope") ;
413
427
}
414
428
return Some ( found[ 0 ] ) ;
@@ -421,7 +435,7 @@ fn lookup_vtable_invariant(fcx: @fn_ctxt,
421
435
}
422
436
423
437
fn fixup_ty ( fcx : @fn_ctxt ,
424
- expr : @ast :: expr ,
438
+ location_info : & LocationInfo ,
425
439
ty : ty:: t ,
426
440
is_early : bool ) -> Option < ty:: t >
427
441
{
@@ -430,7 +444,7 @@ fn fixup_ty(fcx: @fn_ctxt,
430
444
Ok ( new_type) => Some ( new_type) ,
431
445
Err ( e) if !is_early => {
432
446
tcx. sess . span_fatal (
433
- expr . span ,
447
+ location_info . span ,
434
448
fmt ! ( "cannot determine a type \
435
449
for this bounded type parameter: %s",
436
450
fixup_err_to_str( e) ) )
@@ -441,8 +455,11 @@ fn fixup_ty(fcx: @fn_ctxt,
441
455
}
442
456
}
443
457
444
- fn connect_trait_tps ( fcx : @fn_ctxt , expr : @ast:: expr , impl_tys : ~[ ty:: t ] ,
445
- trait_tys : ~[ ty:: t ] , impl_did : ast:: def_id ,
458
+ fn connect_trait_tps ( fcx : @fn_ctxt ,
459
+ location_info : & LocationInfo ,
460
+ impl_tys : ~[ ty:: t ] ,
461
+ trait_tys : ~[ ty:: t ] ,
462
+ impl_did : ast:: def_id ,
446
463
vstore : ty:: vstore ) {
447
464
let tcx = fcx. ccx . tcx ;
448
465
@@ -454,10 +471,10 @@ fn connect_trait_tps(fcx: @fn_ctxt, expr: @ast::expr, impl_tys: ~[ty::t],
454
471
match ty:: get ( trait_ty) . sty {
455
472
ty:: ty_trait( _, substs, _) => {
456
473
for vec:: each2( substs. tps, trait_tys) |a, b| {
457
- demand:: suptype( fcx, expr . span, * a, * b)
474
+ demand:: suptype( fcx, location_info . span, * a, * b)
458
475
}
459
476
}
460
- _ => tcx. sess . impossible_case ( expr . span , "connect_trait_tps: \
477
+ _ => tcx. sess . impossible_case ( location_info . span , "connect_trait_tps: \
461
478
don't know how to handle a non-trait ty")
462
479
}
463
480
}
@@ -469,6 +486,13 @@ fn insert_vtables(ccx: @crate_ctxt, callee_id: ast::node_id,
469
486
ccx. vtable_map . insert ( callee_id, vtables) ;
470
487
}
471
488
489
+ fn location_info_for_expr ( expr : @ast:: expr ) -> LocationInfo {
490
+ LocationInfo {
491
+ span : expr. span ,
492
+ id : expr. id
493
+ }
494
+ }
495
+
472
496
fn early_resolve_expr( ex : @ast:: expr , & & fcx: @fn_ctxt , is_early : bool ) {
473
497
debug ! ( "vtable: early_resolve_expr() ex with id %? (early: %b): %s" ,
474
498
ex. id, is_early, expr_to_str( ex, fcx. tcx( ) . sess. intr( ) ) ) ;
@@ -489,8 +513,9 @@ fn early_resolve_expr(ex: @ast::expr, &&fcx: @fn_ctxt, is_early: bool) {
489
513
%s",
490
514
ty:: param_bounds_to_str( fcx. tcx( ) , * bounds) ) ;
491
515
}
492
- let vtbls = lookup_vtables ( fcx, ex, item_ty. bounds ,
493
- substs, false , is_early) ;
516
+ let vtbls = lookup_vtables ( fcx, & location_info_for_expr ( ex) ,
517
+ item_ty. bounds , substs, false ,
518
+ is_early) ;
494
519
if !is_early { cx. vtable_map . insert ( ex. id , vtbls) ; }
495
520
}
496
521
}
@@ -514,8 +539,8 @@ fn early_resolve_expr(ex: @ast::expr, &&fcx: @fn_ctxt, is_early: bool) {
514
539
_ => ex. callee_id
515
540
} ;
516
541
let substs = fcx. node_ty_substs ( callee_id) ;
517
- let vtbls = lookup_vtables ( fcx, ex , bounds ,
518
- & substs, false , is_early) ;
542
+ let vtbls = lookup_vtables ( fcx, & location_info_for_expr ( ex ) ,
543
+ bounds , & substs, false , is_early) ;
519
544
if !is_early {
520
545
insert_vtables ( cx, callee_id, vtbls) ;
521
546
}
@@ -534,8 +559,13 @@ fn early_resolve_expr(ex: @ast::expr, &&fcx: @fn_ctxt, is_early: bool) {
534
559
// XXX: This is invariant and shouldn't be. --pcw
535
560
536
561
let ty = fcx. expr_ty ( src) ;
537
- let vtable_opt = lookup_vtable_invariant ( fcx, ex, ty, target_ty,
538
- true , is_early) ;
562
+ let vtable_opt =
563
+ lookup_vtable_invariant ( fcx,
564
+ & location_info_for_expr ( ex) ,
565
+ ty,
566
+ target_ty,
567
+ true ,
568
+ is_early) ;
539
569
match vtable_opt {
540
570
None => {
541
571
// Try the new-style boxed trait; "@int as @Trait".
@@ -553,9 +583,11 @@ fn early_resolve_expr(ex: @ast::expr, &&fcx: @fn_ctxt, is_early: bool) {
553
583
( ty:: ty_box( _) , ty:: vstore_box) |
554
584
( ty:: ty_uniq( _) , ty:: vstore_uniq) |
555
585
( ty:: ty_rptr( * ) , ty:: vstore_slice( * ) ) => {
586
+ let location_info =
587
+ & location_info_for_expr ( ex) ;
556
588
let vtable_opt =
557
589
lookup_vtable_invariant ( fcx,
558
- ex ,
590
+ location_info ,
559
591
mt. ty ,
560
592
target_ty,
561
593
true ,
0 commit comments