9
9
// except according to those terms.
10
10
11
11
use check:: { FnCtxt , structurally_resolved_type} ;
12
+ use check:: demand;
12
13
use middle:: traits:: { self , ObjectSafetyViolation , MethodViolationCode } ;
13
14
use middle:: traits:: { Obligation , ObligationCause } ;
14
15
use middle:: traits:: report_fulfillment_errors;
15
16
use middle:: ty:: { self , Ty , AsPredicate } ;
16
- use middle:: infer;
17
17
use syntax:: ast;
18
18
use syntax:: codemap:: Span ;
19
19
use util:: nodemap:: FnvHashSet ;
@@ -24,71 +24,63 @@ pub fn check_object_cast<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
24
24
source_expr : & ast:: Expr ,
25
25
target_object_ty : Ty < ' tcx > )
26
26
{
27
+ let tcx = fcx. tcx ( ) ;
27
28
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) ) ;
30
31
31
32
// Look up vtables for the type we're casting to,
32
33
// passing in the source and target type. The source
33
34
// must be a pointer type suitable to the object sigil,
34
35
// 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
- }
71
36
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) )
77
44
}
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 } ) )
84
51
}
85
-
86
52
_ => {
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" ) ;
90
54
}
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 ) ;
92
84
93
85
fn object_trait < ' a , ' tcx > ( t : & ' a Ty < ' tcx > ) -> & ' a ty:: TyTrait < ' tcx > {
94
86
match t. sty {
@@ -97,13 +89,6 @@ pub fn check_object_cast<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
97
89
}
98
90
}
99
91
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
-
107
92
fn push_cast_obligation < ' a , ' tcx > ( fcx : & FnCtxt < ' a , ' tcx > ,
108
93
cast_expr : & ast:: Expr ,
109
94
object_trait : & ty:: TyTrait < ' tcx > ,
0 commit comments