6060//! sort of a minor point so I've opted to leave it for later---after all
6161//! we may want to adjust precisely when coercions occur.
6262
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 ;
6664
65+ use middle:: infer:: { self , cres, Coercion , TypeTrace } ;
66+ use middle:: infer:: combine:: Combine ;
67+ use middle:: infer:: sub:: Sub ;
6768use middle:: subst;
6869use middle:: ty:: { AutoPtr , AutoDerefRef , AdjustDerefRef , AutoUnsize , AutoUnsafe } ;
6970use middle:: ty:: { mt} ;
@@ -74,21 +75,31 @@ use util::ppaux::Repr;
7475
7576use syntax:: ast;
7677
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 > > > ;
8184
8285impl < ' 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 ( )
8588 }
8689
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.
8994 }
9095
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 > {
92103 debug ! ( "Coerce.tys({} => {})" ,
93104 a. repr( self . tcx( ) ) ,
94105 b. repr( self . tcx( ) ) ) ;
@@ -179,25 +190,12 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
179190 } )
180191 }
181192
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-
195193 // ~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 > {
201199 debug ! ( "coerce_borrowed_pointer(a={}, b={})" ,
202200 a. repr( self . tcx( ) ) ,
203201 b. repr( self . tcx( ) ) ) ;
@@ -208,9 +206,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
208206 // to type check, we will construct the type that `&M*expr` would
209207 // yield.
210208
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) ;
214211
215212 let inner_ty = match a. sty {
216213 ty:: ty_uniq( _) => return Err ( ty:: terr_mismatch) ,
@@ -220,15 +217,14 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
220217 }
221218 mt_a. ty
222219 }
223- _ => {
224- return self . subtype ( a, b) ;
225- }
220+ _ => return self . subtype ( a, b)
226221 } ;
227222
228223 let a_borrowed = ty:: mk_rptr ( self . tcx ( ) ,
229224 self . tcx ( ) . mk_region ( r_borrow) ,
230225 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) {
232228
233229 Ok ( Some ( AdjustDerefRef ( AutoDerefRef {
234230 autoderefs : 1 ,
@@ -253,8 +249,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
253249 // we can't unify [T] with U. But to properly support DST, we need to allow
254250 // that, at which point we will need extra checks on b here.
255251
256- let sub = Sub ( self . get_ref ( ) . clone ( ) ) ;
257-
258252 match ( & a. sty , & b. sty ) {
259253 ( & ty:: ty_rptr( _, ty:: mt { ty : t_a, mutbl : mutbl_a} ) , & ty:: ty_rptr( _, mt_b) ) => {
260254 self . unpack_actual_value ( t_a, |a| {
@@ -264,12 +258,12 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
264258 return Err ( ty:: terr_mutability) ;
265259 }
266260
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) ;
269263 let ty = ty:: mk_rptr ( self . tcx ( ) ,
270264 self . tcx ( ) . mk_region ( r_borrow) ,
271265 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) ) ) ;
273267 debug ! ( "Success, coerced with AutoDerefRef(1, \
274268 AutoPtr(AutoUnsize({:?})))", kind) ;
275269 Ok ( Some ( AdjustDerefRef ( AutoDerefRef {
@@ -292,7 +286,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
292286
293287 let ty = ty:: mk_ptr ( self . tcx ( ) ,
294288 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) ) ) ;
296290 debug ! ( "Success, coerced with AutoDerefRef(1, \
297291 AutoPtr(AutoUnsize({:?})))", kind) ;
298292 Ok ( Some ( AdjustDerefRef ( AutoDerefRef {
@@ -310,7 +304,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
310304 match self . unsize_ty ( t_a, a, t_b) {
311305 Some ( ( ty, kind) ) => {
312306 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) ) ) ;
314308 debug ! ( "Success, coerced with AutoDerefRef(1, \
315309 AutoUnsizeUniq({:?}))", kind) ;
316310 Ok ( Some ( AdjustDerefRef ( AutoDerefRef {
@@ -362,12 +356,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
362356 let ty_substs_b = substs_b. types . get_slice ( subst:: TypeSpace ) ;
363357 assert ! ( ty_substs_a. len( ) == ty_substs_b. len( ) ) ;
364358
365- let sub = Sub ( self . get_ref ( ) . clone ( ) ) ;
366-
367359 let mut result = None ;
368360 let mut tps = ty_substs_a. iter ( ) . zip ( ty_substs_b. iter ( ) ) . enumerate ( ) ;
369361 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 ( ) {
371363 continue ;
372364 }
373365 match
@@ -380,7 +372,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
380372 let mut new_substs = substs_a. clone ( ) ;
381373 new_substs. types . get_mut_slice ( subst:: TypeSpace ) [ i] = new_tp;
382374 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 ( ) {
384376 debug ! ( "Unsized type parameter '{}', but still \
385377 could not match types {} and {}",
386378 ppaux:: ty_to_string( tcx, * tp_a) ,
@@ -416,8 +408,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
416408 a. repr( tcx) ,
417409 b. repr( tcx) , b_mutbl) ;
418410
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) ;
421413
422414 self . coerce_object ( a, b, b_mutbl,
423415 |tr| ty:: mk_rptr ( tcx, tcx. mk_region ( r_a) ,
@@ -501,11 +493,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
501493 } )
502494 }
503495
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 > {
509501 debug ! ( "coerce_unsafe_ptr(a={}, b={})" ,
510502 a. repr( self . tcx( ) ) ,
511503 b. repr( self . tcx( ) ) ) ;
@@ -534,21 +526,25 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
534526 }
535527}
536528
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 ,
542531 a : Ty < ' tcx > ,
543532 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)
550542 } )
551- } )
543+ } ) ) ;
544+ if let Some ( adjustment) = adjustment {
545+ fcx. write_adjustment ( expr. id , expr. span , adjustment) ;
546+ }
547+ Ok ( ( ) )
552548}
553549
554550fn can_coerce_mutbls ( from_mutbl : ast:: Mutability ,
0 commit comments