99// except according to those terms.
1010
1111use check:: { FnCtxt , structurally_resolved_type} ;
12+ use check:: demand;
1213use middle:: traits:: { self , ObjectSafetyViolation , MethodViolationCode } ;
1314use middle:: traits:: { Obligation , ObligationCause } ;
1415use middle:: traits:: report_fulfillment_errors;
1516use middle:: ty:: { self , Ty , AsPredicate } ;
16- use middle:: infer;
1717use syntax:: ast;
1818use syntax:: codemap:: Span ;
1919use util:: nodemap:: FnvHashSet ;
@@ -24,71 +24,63 @@ pub fn check_object_cast<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2424 source_expr : & ast:: Expr ,
2525 target_object_ty : Ty < ' tcx > )
2626{
27+ let tcx = fcx. tcx ( ) ;
2728 debug ! ( "check_object_cast(cast_expr={}, target_object_ty={})" ,
28- cast_expr. repr( fcx . tcx( ) ) ,
29- target_object_ty. repr( fcx . tcx( ) ) ) ;
29+ cast_expr. repr( tcx) ,
30+ target_object_ty. repr( tcx) ) ;
3031
3132 // Look up vtables for the type we're casting to,
3233 // passing in the source and target type. The source
3334 // must be a pointer type suitable to the object sigil,
3435 // e.g.: `&x as &Trait` or `box x as Box<Trait>`
35- let source_ty = fcx. expr_ty ( source_expr) ;
36- let source_ty = structurally_resolved_type ( fcx, source_expr. span , source_ty) ;
37- debug ! ( "source_ty={}" , source_ty. repr( fcx. tcx( ) ) ) ;
38- match ( & source_ty. sty , & target_object_ty. sty ) {
39- ( & ty:: ty_uniq( referent_ty) , & ty:: ty_uniq( object_trait_ty) ) => {
40- let object_trait = object_trait ( & object_trait_ty) ;
41-
42- // Ensure that if ~T is cast to ~Trait, then T : Trait
43- push_cast_obligation ( fcx, cast_expr, object_trait, referent_ty) ;
44- check_object_safety ( fcx. tcx ( ) , object_trait, source_expr. span ) ;
45- }
46-
47- ( & ty:: ty_rptr( referent_region, ty:: mt { ty : referent_ty,
48- mutbl : referent_mutbl } ) ,
49- & ty:: ty_rptr( target_region, ty:: mt { ty : object_trait_ty,
50- mutbl : target_mutbl } ) ) =>
51- {
52- let object_trait = object_trait ( & object_trait_ty) ;
53- if !mutability_allowed ( referent_mutbl, target_mutbl) {
54- span_err ! ( fcx. tcx( ) . sess, source_expr. span, E0188 ,
55- "types differ in mutability" ) ;
56- } else {
57- // Ensure that if &'a T is cast to &'b Trait, then T : Trait
58- push_cast_obligation ( fcx, cast_expr,
59- object_trait,
60- referent_ty) ;
61-
62- // Ensure that if &'a T is cast to &'b Trait, then 'b <= 'a
63- infer:: mk_subr ( fcx. infcx ( ) ,
64- infer:: RelateObjectBound ( source_expr. span ) ,
65- * target_region,
66- * referent_region) ;
67-
68- check_object_safety ( fcx. tcx ( ) , object_trait, source_expr. span ) ;
69- }
70- }
7136
72- ( _, & ty:: ty_uniq( ..) ) => {
73- span_err ! ( fcx. ccx. tcx. sess, source_expr. span, E0189 ,
74- "can only cast a boxed pointer \
75- to a boxed object, not a {}",
76- ty:: ty_sort_string( fcx. tcx( ) , source_ty) ) ;
37+ // First, construct a fresh type that we can feed into `<expr>`
38+ // within `<expr> as <type>` to inform type inference (e.g. to
39+ // tell it that we are expecting a `Box<_>` or an `&_`).
40+ let fresh_ty = fcx. infcx ( ) . next_ty_var ( ) ;
41+ let ( object_trait_ty, source_expected_ty) = match target_object_ty. sty {
42+ ty:: ty_uniq( object_trait_ty) => {
43+ ( object_trait_ty, ty:: mk_uniq ( fcx. tcx ( ) , fresh_ty) )
7744 }
78-
79- ( _ , & ty :: ty_rptr ( .. ) ) => {
80- span_err ! ( fcx . ccx . tcx . sess , source_expr . span , E0190 ,
81- "can only cast a &-pointer \
82- to an &-object, not a {}" ,
83- ty :: ty_sort_string ( fcx . tcx ( ) , source_ty ) ) ;
45+ ty :: ty_rptr ( target_region , ty :: mt { ty : object_trait_ty ,
46+ mutbl : target_mutbl } ) => {
47+ ( object_trait_ty ,
48+ ty :: mk_rptr ( fcx . tcx ( ) ,
49+ target_region , ty :: mt { ty : fresh_ty ,
50+ mutbl : target_mutbl } ) )
8451 }
85-
8652 _ => {
87- fcx. tcx ( ) . sess . span_bug (
88- source_expr. span ,
89- "expected object type" ) ;
53+ fcx. tcx ( ) . sess . span_bug ( source_expr. span , "expected object type" ) ;
9054 }
91- }
55+ } ;
56+
57+ let source_ty = fcx. expr_ty ( source_expr) ;
58+ debug ! ( "check_object_cast pre unify source_ty={}" , source_ty. repr( tcx) ) ;
59+
60+ // This ensures that the source_ty <: source_expected_ty, which
61+ // will ensure e.g. that &'a T <: &'b T when doing `&'a T as &'b Trait`
62+ //
63+ // FIXME (pnkfelix): do we need to use suptype_with_fn in order to
64+ // override the error message emitted when the types do not work
65+ // out in the manner desired?
66+ demand:: suptype ( fcx, source_expr. span , source_expected_ty, source_ty) ;
67+
68+ debug ! ( "check_object_cast postunify source_ty={}" , source_ty. repr( tcx) ) ;
69+ let source_ty = structurally_resolved_type ( fcx, source_expr. span , source_ty) ;
70+ debug ! ( "check_object_cast resolveto source_ty={}" , source_ty. repr( tcx) ) ;
71+
72+ let object_trait = object_trait ( & object_trait_ty) ;
73+
74+ let referent_ty = match source_ty. sty {
75+ ty:: ty_uniq( ty) => ty,
76+ ty:: ty_rptr( _, ty:: mt { ty, mutbl : _ } ) => ty,
77+ _ => fcx. tcx ( ) . sess . span_bug ( source_expr. span ,
78+ "expected appropriate reference type" ) ,
79+ } ;
80+
81+ // Ensure that if Ptr<T> is cast to Ptr<Trait>, then T : Trait.
82+ push_cast_obligation ( fcx, cast_expr, object_trait, referent_ty) ;
83+ check_object_safety ( tcx, object_trait, source_expr. span ) ;
9284
9385 fn object_trait < ' a , ' tcx > ( t : & ' a Ty < ' tcx > ) -> & ' a ty:: TyTrait < ' tcx > {
9486 match t. sty {
@@ -97,13 +89,6 @@ pub fn check_object_cast<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
9789 }
9890 }
9991
100- fn mutability_allowed ( a_mutbl : ast:: Mutability ,
101- b_mutbl : ast:: Mutability )
102- -> bool {
103- a_mutbl == b_mutbl ||
104- ( a_mutbl == ast:: MutMutable && b_mutbl == ast:: MutImmutable )
105- }
106-
10792 fn push_cast_obligation < ' a , ' tcx > ( fcx : & FnCtxt < ' a , ' tcx > ,
10893 cast_expr : & ast:: Expr ,
10994 object_trait : & ty:: TyTrait < ' tcx > ,
0 commit comments