@@ -13,6 +13,7 @@ use middle::freevars::freevar_entry;
13
13
use middle:: freevars;
14
14
use middle:: subst;
15
15
use middle:: ty;
16
+ use middle:: typeck:: { MethodCall , NoAdjustment } ;
16
17
use middle:: typeck;
17
18
use util:: ppaux:: { Repr , ty_to_str} ;
18
19
use util:: ppaux:: UserString ;
@@ -261,7 +262,15 @@ pub fn check_expr(cx: &mut Context, e: &Expr) {
261
262
ExprCast ( ref source, _) => {
262
263
let source_ty = ty:: expr_ty ( cx. tcx , & * * source) ;
263
264
let target_ty = ty:: expr_ty ( cx. tcx , e) ;
264
- check_trait_cast ( cx, source_ty, target_ty, source. span ) ;
265
+ let method_call = MethodCall {
266
+ expr_id : e. id ,
267
+ adjustment : NoAdjustment ,
268
+ } ;
269
+ check_trait_cast ( cx,
270
+ source_ty,
271
+ target_ty,
272
+ source. span ,
273
+ method_call) ;
265
274
}
266
275
ExprRepeat ( ref element, ref count_expr) => {
267
276
let count = ty:: eval_repeat_count ( cx. tcx , & * * count_expr) ;
@@ -281,7 +290,15 @@ pub fn check_expr(cx: &mut Context, e: &Expr) {
281
290
ty:: AutoObject ( ..) => {
282
291
let source_ty = ty:: expr_ty ( cx. tcx , e) ;
283
292
let target_ty = ty:: expr_ty_adjusted ( cx. tcx , e) ;
284
- check_trait_cast ( cx, source_ty, target_ty, e. span ) ;
293
+ let method_call = MethodCall {
294
+ expr_id : e. id ,
295
+ adjustment : typeck:: AutoObject ,
296
+ } ;
297
+ check_trait_cast ( cx,
298
+ source_ty,
299
+ target_ty,
300
+ e. span ,
301
+ method_call) ;
285
302
}
286
303
ty:: AutoAddEnv ( ..) |
287
304
ty:: AutoDerefRef ( ..) => { }
@@ -364,15 +381,62 @@ fn check_bounds_on_type_parameters(cx: &mut Context, e: &Expr) {
364
381
}
365
382
}
366
383
367
- fn check_trait_cast ( cx : & mut Context , source_ty : ty:: t , target_ty : ty:: t , span : Span ) {
384
+ fn check_type_parameter_bounds_in_vtable_result (
385
+ cx : & mut Context ,
386
+ span : Span ,
387
+ vtable_res : & typeck:: vtable_res ) {
388
+ for origins in vtable_res. iter ( ) {
389
+ for origin in origins. iter ( ) {
390
+ let ( type_param_defs, substs) = match * origin {
391
+ typeck:: vtable_static( def_id, ref tys, _) => {
392
+ let type_param_defs =
393
+ ty:: lookup_item_type ( cx. tcx , def_id) . generics
394
+ . types
395
+ . clone ( ) ;
396
+ ( type_param_defs, ( * tys) . clone ( ) )
397
+ }
398
+ _ => {
399
+ // Nothing to do here.
400
+ continue
401
+ }
402
+ } ;
403
+ for type_param_def in type_param_defs. iter ( ) {
404
+ let typ = substs. types . get ( type_param_def. space ,
405
+ type_param_def. index ) ;
406
+ check_typaram_bounds ( cx, span, * typ, type_param_def)
407
+ }
408
+ }
409
+ }
410
+ }
411
+
412
+ fn check_trait_cast ( cx : & mut Context ,
413
+ source_ty : ty:: t ,
414
+ target_ty : ty:: t ,
415
+ span : Span ,
416
+ method_call : MethodCall ) {
368
417
check_cast_for_escaping_regions ( cx, source_ty, target_ty, span) ;
369
418
match ty:: get ( target_ty) . sty {
370
- ty:: ty_uniq( ty) | ty:: ty_rptr( _, ty:: mt { ty, .. } ) => match ty:: get ( ty) . sty {
371
- ty:: ty_trait( box ty:: TyTrait { bounds, .. } ) => {
372
- check_trait_cast_bounds ( cx, span, source_ty, bounds) ;
419
+ ty:: ty_uniq( ty) | ty:: ty_rptr( _, ty:: mt { ty, .. } ) => {
420
+ match ty:: get ( ty) . sty {
421
+ ty:: ty_trait( box ty:: TyTrait { bounds, .. } ) => {
422
+ match cx. tcx . vtable_map . borrow ( ) . find ( & method_call) {
423
+ None => {
424
+ cx. tcx . sess . span_bug ( span,
425
+ "trait cast not in vtable \
426
+ map?!")
427
+ }
428
+ Some ( vtable_res) => {
429
+ check_type_parameter_bounds_in_vtable_result (
430
+ cx,
431
+ span,
432
+ vtable_res)
433
+ }
434
+ } ;
435
+ check_trait_cast_bounds ( cx, span, source_ty, bounds) ;
436
+ }
437
+ _ => { }
373
438
}
374
- _ => { }
375
- } ,
439
+ }
376
440
_ => { }
377
441
}
378
442
}
0 commit comments