60
60
//! sort of a minor point so I've opted to leave it for later---after all
61
61
//! we may want to adjust precisely when coercions occur.
62
62
63
- use middle:: infer:: { cres, Coercion , InferCtxt , TypeOrigin , TypeTrace } ;
64
- use middle:: infer:: combine:: { CombineFields , Combine } ;
65
- use middle:: infer:: sub:: Sub ;
63
+ use check:: FnCtxt ;
66
64
65
+ use middle:: infer:: { self , cres, Coercion , TypeTrace } ;
66
+ use middle:: infer:: combine:: Combine ;
67
+ use middle:: infer:: sub:: Sub ;
67
68
use middle:: subst;
68
69
use middle:: ty:: { AutoPtr , AutoDerefRef , AdjustDerefRef , AutoUnsize , AutoUnsafe } ;
69
70
use middle:: ty:: { mt} ;
@@ -74,21 +75,31 @@ use util::ppaux::Repr;
74
75
75
76
use syntax:: ast;
76
77
77
- // Note: Coerce is not actually a combiner, in that it does not
78
- // conform to the same interface, though it performs a similar
79
- // function.
80
- pub struct Coerce < ' f , ' tcx : ' f > ( pub CombineFields < ' f , ' tcx > ) ;
78
+ struct Coerce < ' a , ' tcx : ' a > {
79
+ fcx : & ' a FnCtxt < ' a , ' tcx > ,
80
+ trace : TypeTrace < ' tcx >
81
+ }
82
+
83
+ type CoerceResult < ' tcx > = cres < ' tcx , Option < ty:: AutoAdjustment < ' tcx > > > ;
81
84
82
85
impl < ' f , ' tcx > Coerce < ' f , ' tcx > {
83
- pub fn get_ref < ' a > ( & ' a self ) -> & ' a CombineFields < ' f , ' tcx > {
84
- let Coerce ( ref v ) = * self ; v
86
+ fn tcx ( & self ) -> & ty :: ctxt < ' tcx > {
87
+ self . fcx . tcx ( )
85
88
}
86
89
87
- fn tcx ( & self ) -> & ty:: ctxt < ' tcx > {
88
- self . get_ref ( ) . infcx . tcx
90
+ fn subtype ( & self , a : Ty < ' tcx > , b : Ty < ' tcx > ) -> CoerceResult < ' tcx > {
91
+ let sub = Sub ( self . fcx . infcx ( ) . combine_fields ( false , self . trace . clone ( ) ) ) ;
92
+ try!( sub. tys ( a, b) ) ;
93
+ Ok ( None ) // No coercion required.
89
94
}
90
95
91
- pub fn tys ( & self , a : Ty < ' tcx > , b : Ty < ' tcx > ) -> CoerceResult < ' tcx > {
96
+ fn unpack_actual_value < T , F > ( & self , a : Ty < ' tcx > , f : F ) -> T where
97
+ F : FnOnce ( Ty < ' tcx > ) -> T ,
98
+ {
99
+ f ( self . fcx . infcx ( ) . shallow_resolve ( a) )
100
+ }
101
+
102
+ fn coerce ( & self , a : Ty < ' tcx > , b : Ty < ' tcx > ) -> CoerceResult < ' tcx > {
92
103
debug ! ( "Coerce.tys({} => {})" ,
93
104
a. repr( self . tcx( ) ) ,
94
105
b. repr( self . tcx( ) ) ) ;
@@ -179,25 +190,12 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
179
190
} )
180
191
}
181
192
182
- pub fn subtype ( & self , a : Ty < ' tcx > , b : Ty < ' tcx > ) -> CoerceResult < ' tcx > {
183
- match Sub ( self . get_ref ( ) . clone ( ) ) . tys ( a, b) {
184
- Ok ( _) => Ok ( None ) , // No coercion required.
185
- Err ( ref e) => Err ( * e)
186
- }
187
- }
188
-
189
- pub fn unpack_actual_value < T , F > ( & self , a : Ty < ' tcx > , f : F ) -> T where
190
- F : FnOnce ( Ty < ' tcx > ) -> T ,
191
- {
192
- f ( self . get_ref ( ) . infcx . shallow_resolve ( a) )
193
- }
194
-
195
193
// ~T -> &T or &mut T -> &T (including where T = [U] or str)
196
- pub fn coerce_borrowed_pointer ( & self ,
197
- a : Ty < ' tcx > ,
198
- b : Ty < ' tcx > ,
199
- mutbl_b : ast:: Mutability )
200
- -> CoerceResult < ' tcx > {
194
+ fn coerce_borrowed_pointer ( & self ,
195
+ a : Ty < ' tcx > ,
196
+ b : Ty < ' tcx > ,
197
+ mutbl_b : ast:: Mutability )
198
+ -> CoerceResult < ' tcx > {
201
199
debug ! ( "coerce_borrowed_pointer(a={}, b={})" ,
202
200
a. repr( self . tcx( ) ) ,
203
201
b. repr( self . tcx( ) ) ) ;
@@ -208,9 +206,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
208
206
// to type check, we will construct the type that `&M*expr` would
209
207
// yield.
210
208
211
- let sub = Sub ( self . get_ref ( ) . clone ( ) ) ;
212
- let coercion = Coercion ( self . get_ref ( ) . trace . clone ( ) ) ;
213
- let r_borrow = self . get_ref ( ) . infcx . next_region_var ( coercion) ;
209
+ let coercion = Coercion ( self . trace . clone ( ) ) ;
210
+ let r_borrow = self . fcx . infcx ( ) . next_region_var ( coercion) ;
214
211
215
212
let inner_ty = match a. sty {
216
213
ty:: ty_uniq( _) => return Err ( ty:: terr_mismatch) ,
@@ -220,15 +217,14 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
220
217
}
221
218
mt_a. ty
222
219
}
223
- _ => {
224
- return self . subtype ( a, b) ;
225
- }
220
+ _ => return self . subtype ( a, b)
226
221
} ;
227
222
228
223
let a_borrowed = ty:: mk_rptr ( self . tcx ( ) ,
229
224
self . tcx ( ) . mk_region ( r_borrow) ,
230
225
mt { ty : inner_ty, mutbl : mutbl_b} ) ;
231
- try!( sub. tys ( a_borrowed, b) ) ;
226
+ try!( self . subtype ( a_borrowed, b) ) ;
227
+ if let Err ( original_err) = self . subtype ( a_borrowed, b) {
232
228
233
229
Ok ( Some ( AdjustDerefRef ( AutoDerefRef {
234
230
autoderefs : 1 ,
@@ -253,8 +249,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
253
249
// we can't unify [T] with U. But to properly support DST, we need to allow
254
250
// that, at which point we will need extra checks on b here.
255
251
256
- let sub = Sub ( self . get_ref ( ) . clone ( ) ) ;
257
-
258
252
match ( & a. sty , & b. sty ) {
259
253
( & ty:: ty_rptr( _, ty:: mt { ty : t_a, mutbl : mutbl_a} ) , & ty:: ty_rptr( _, mt_b) ) => {
260
254
self . unpack_actual_value ( t_a, |a| {
@@ -264,12 +258,12 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
264
258
return Err ( ty:: terr_mutability) ;
265
259
}
266
260
267
- let coercion = Coercion ( self . get_ref ( ) . trace . clone ( ) ) ;
268
- let r_borrow = self . get_ref ( ) . infcx . next_region_var ( coercion) ;
261
+ let coercion = Coercion ( self . trace . clone ( ) ) ;
262
+ let r_borrow = self . fcx . infcx ( ) . next_region_var ( coercion) ;
269
263
let ty = ty:: mk_rptr ( self . tcx ( ) ,
270
264
self . tcx ( ) . mk_region ( r_borrow) ,
271
265
ty:: mt { ty : ty, mutbl : mt_b. mutbl } ) ;
272
- try!( self . get_ref ( ) . infcx . try ( |_| sub . tys ( ty, b) ) ) ;
266
+ try!( self . fcx . infcx ( ) . try ( |_| self . subtype ( ty, b) ) ) ;
273
267
debug ! ( "Success, coerced with AutoDerefRef(1, \
274
268
AutoPtr(AutoUnsize({:?})))", kind) ;
275
269
Ok ( Some ( AdjustDerefRef ( AutoDerefRef {
@@ -292,7 +286,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
292
286
293
287
let ty = ty:: mk_ptr ( self . tcx ( ) ,
294
288
ty:: mt { ty : ty, mutbl : mt_b. mutbl } ) ;
295
- try!( self . get_ref ( ) . infcx . try ( |_| sub . tys ( ty, b) ) ) ;
289
+ try!( self . fcx . infcx ( ) . try ( |_| self . subtype ( ty, b) ) ) ;
296
290
debug ! ( "Success, coerced with AutoDerefRef(1, \
297
291
AutoPtr(AutoUnsize({:?})))", kind) ;
298
292
Ok ( Some ( AdjustDerefRef ( AutoDerefRef {
@@ -310,7 +304,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
310
304
match self . unsize_ty ( t_a, a, t_b) {
311
305
Some ( ( ty, kind) ) => {
312
306
let ty = ty:: mk_uniq ( self . tcx ( ) , ty) ;
313
- try!( self . get_ref ( ) . infcx . try ( |_| sub . tys ( ty, b) ) ) ;
307
+ try!( self . fcx . infcx ( ) . try ( |_| self . subtype ( ty, b) ) ) ;
314
308
debug ! ( "Success, coerced with AutoDerefRef(1, \
315
309
AutoUnsizeUniq({:?}))", kind) ;
316
310
Ok ( Some ( AdjustDerefRef ( AutoDerefRef {
@@ -362,12 +356,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
362
356
let ty_substs_b = substs_b. types . get_slice ( subst:: TypeSpace ) ;
363
357
assert ! ( ty_substs_a. len( ) == ty_substs_b. len( ) ) ;
364
358
365
- let sub = Sub ( self . get_ref ( ) . clone ( ) ) ;
366
-
367
359
let mut result = None ;
368
360
let mut tps = ty_substs_a. iter ( ) . zip ( ty_substs_b. iter ( ) ) . enumerate ( ) ;
369
361
for ( i, ( tp_a, tp_b) ) in tps {
370
- if self . get_ref ( ) . infcx . try ( |_| sub . tys ( * tp_a, * tp_b) ) . is_ok ( ) {
362
+ if self . fcx . infcx ( ) . try ( |_| self . subtype ( * tp_a, * tp_b) ) . is_ok ( ) {
371
363
continue ;
372
364
}
373
365
match
@@ -380,7 +372,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
380
372
let mut new_substs = substs_a. clone ( ) ;
381
373
new_substs. types . get_mut_slice ( subst:: TypeSpace ) [ i] = new_tp;
382
374
let ty = ty:: mk_struct ( tcx, did_a, tcx. mk_substs ( new_substs) ) ;
383
- if self . get_ref ( ) . infcx . try ( |_| sub . tys ( ty, ty_b) ) . is_err ( ) {
375
+ if self . fcx . infcx ( ) . try ( |_| self . subtype ( ty, ty_b) ) . is_err ( ) {
384
376
debug ! ( "Unsized type parameter '{}', but still \
385
377
could not match types {} and {}",
386
378
ppaux:: ty_to_string( tcx, * tp_a) ,
@@ -416,8 +408,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
416
408
a. repr( tcx) ,
417
409
b. repr( tcx) , b_mutbl) ;
418
410
419
- let coercion = Coercion ( self . get_ref ( ) . trace . clone ( ) ) ;
420
- let r_a = self . get_ref ( ) . infcx . next_region_var ( coercion) ;
411
+ let coercion = Coercion ( self . trace . clone ( ) ) ;
412
+ let r_a = self . fcx . infcx ( ) . next_region_var ( coercion) ;
421
413
422
414
self . coerce_object ( a, b, b_mutbl,
423
415
|tr| ty:: mk_rptr ( tcx, tcx. mk_region ( r_a) ,
@@ -501,11 +493,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
501
493
} )
502
494
}
503
495
504
- pub fn coerce_unsafe_ptr ( & self ,
505
- a : Ty < ' tcx > ,
506
- b : Ty < ' tcx > ,
507
- mutbl_b : ast:: Mutability )
508
- -> CoerceResult < ' tcx > {
496
+ fn coerce_unsafe_ptr ( & self ,
497
+ a : Ty < ' tcx > ,
498
+ b : Ty < ' tcx > ,
499
+ mutbl_b : ast:: Mutability )
500
+ -> CoerceResult < ' tcx > {
509
501
debug ! ( "coerce_unsafe_ptr(a={}, b={})" ,
510
502
a. repr( self . tcx( ) ) ,
511
503
b. repr( self . tcx( ) ) ) ;
@@ -534,21 +526,25 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
534
526
}
535
527
}
536
528
537
- pub type CoerceResult < ' tcx > = cres < ' tcx , Option < ty:: AutoAdjustment < ' tcx > > > ;
538
-
539
- pub fn mk_coercety < ' a , ' tcx > ( cx : & InferCtxt < ' a , ' tcx > ,
540
- a_is_expected : bool ,
541
- origin : TypeOrigin ,
529
+ pub fn mk_assignty < ' a , ' tcx > ( fcx : & FnCtxt < ' a , ' tcx > ,
530
+ expr : & ast:: Expr ,
542
531
a : Ty < ' tcx > ,
543
532
b : Ty < ' tcx > )
544
- -> CoerceResult < ' tcx > {
545
- debug ! ( "mk_coercety({} -> {})" , a. repr( cx. tcx) , b. repr( cx. tcx) ) ;
546
- indent ( || {
547
- cx. commit_if_ok ( || {
548
- let trace = TypeTrace :: types ( origin, a_is_expected, a, b) ;
549
- Coerce ( cx. combine_fields ( a_is_expected, trace) ) . tys ( a, b)
533
+ -> cres < ' tcx , ( ) > {
534
+ debug ! ( "mk_assignty({} -> {})" , a. repr( fcx. tcx( ) ) , b. repr( fcx. tcx( ) ) ) ;
535
+ let adjustment = try!( indent ( || {
536
+ fcx. infcx ( ) . commit_if_ok ( || {
537
+ let origin = infer:: ExprAssignable ( expr. span ) ;
538
+ Coerce {
539
+ fcx : fcx,
540
+ trace : infer:: TypeTrace :: types ( origin, false , a, b)
541
+ } . coerce ( a, b)
550
542
} )
551
- } )
543
+ } ) ) ;
544
+ if let Some ( adjustment) = adjustment {
545
+ fcx. write_adjustment ( expr. id , expr. span , adjustment) ;
546
+ }
547
+ Ok ( ( ) )
552
548
}
553
549
554
550
fn can_coerce_mutbls ( from_mutbl : ast:: Mutability ,
0 commit comments