@@ -252,70 +252,64 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
252
252
253
253
match ( & a. sty , & b. sty ) {
254
254
( & ty:: ty_rptr( _, ty:: mt { ty : t_a, mutbl : mutbl_a} ) , & ty:: ty_rptr( _, mt_b) ) => {
255
- self . unpack_actual_value ( t_a, |a| {
256
- match self . unsize_ty ( t_a, a, mt_b. ty ) {
257
- Some ( ( ty, kind) ) => {
258
- if !can_coerce_mutbls ( mutbl_a, mt_b. mutbl ) {
259
- return Err ( ty:: terr_mutability) ;
260
- }
261
-
262
- let coercion = Coercion ( self . trace . clone ( ) ) ;
263
- let r_borrow = self . fcx . infcx ( ) . next_region_var ( coercion) ;
264
- let ty = ty:: mk_rptr ( self . tcx ( ) ,
265
- self . tcx ( ) . mk_region ( r_borrow) ,
266
- ty:: mt { ty : ty, mutbl : mt_b. mutbl } ) ;
267
- try!( self . fcx . infcx ( ) . try ( |_| self . subtype ( ty, b) ) ) ;
268
- debug ! ( "Success, coerced with AutoDerefRef(1, \
269
- AutoPtr(AutoUnsize({:?})))", kind) ;
270
- Ok ( Some ( AdjustDerefRef ( AutoDerefRef {
271
- autoderefs : 1 ,
272
- autoref : Some ( ty:: AutoPtr ( r_borrow, mt_b. mutbl ,
273
- Some ( box AutoUnsize ( kind) ) ) )
274
- } ) ) )
255
+ match self . unsize_ty ( t_a, mt_b. ty ) {
256
+ Some ( ( ty, kind) ) => {
257
+ if !can_coerce_mutbls ( mutbl_a, mt_b. mutbl ) {
258
+ return Err ( ty:: terr_mutability) ;
275
259
}
276
- _ => Err ( ty:: terr_mismatch)
260
+
261
+ let coercion = Coercion ( self . trace . clone ( ) ) ;
262
+ let r_borrow = self . fcx . infcx ( ) . next_region_var ( coercion) ;
263
+ let ty = ty:: mk_rptr ( self . tcx ( ) ,
264
+ self . tcx ( ) . mk_region ( r_borrow) ,
265
+ ty:: mt { ty : ty, mutbl : mt_b. mutbl } ) ;
266
+ try!( self . fcx . infcx ( ) . try ( |_| self . subtype ( ty, b) ) ) ;
267
+ debug ! ( "Success, coerced with AutoDerefRef(1, \
268
+ AutoPtr(AutoUnsize({:?})))", kind) ;
269
+ Ok ( Some ( AdjustDerefRef ( AutoDerefRef {
270
+ autoderefs : 1 ,
271
+ autoref : Some ( ty:: AutoPtr ( r_borrow, mt_b. mutbl ,
272
+ Some ( box AutoUnsize ( kind) ) ) )
273
+ } ) ) )
277
274
}
278
- } )
275
+ _ => Err ( ty:: terr_mismatch)
276
+ }
279
277
}
280
278
( & ty:: ty_rptr( _, ty:: mt { ty : t_a, mutbl : mutbl_a} ) , & ty:: ty_ptr( mt_b) ) => {
281
- self . unpack_actual_value ( t_a, |a| {
282
- match self . unsize_ty ( t_a, a, mt_b. ty ) {
283
- Some ( ( ty, kind) ) => {
284
- if !can_coerce_mutbls ( mutbl_a, mt_b. mutbl ) {
285
- return Err ( ty:: terr_mutability) ;
286
- }
287
-
288
- let ty = ty:: mk_ptr ( self . tcx ( ) ,
289
- ty:: mt { ty : ty, mutbl : mt_b. mutbl } ) ;
290
- try!( self . fcx . infcx ( ) . try ( |_| self . subtype ( ty, b) ) ) ;
291
- debug ! ( "Success, coerced with AutoDerefRef(1, \
292
- AutoPtr(AutoUnsize({:?})))", kind) ;
293
- Ok ( Some ( AdjustDerefRef ( AutoDerefRef {
294
- autoderefs : 1 ,
295
- autoref : Some ( ty:: AutoUnsafe ( mt_b. mutbl ,
296
- Some ( box AutoUnsize ( kind) ) ) )
297
- } ) ) )
279
+ match self . unsize_ty ( t_a, mt_b. ty ) {
280
+ Some ( ( ty, kind) ) => {
281
+ if !can_coerce_mutbls ( mutbl_a, mt_b. mutbl ) {
282
+ return Err ( ty:: terr_mutability) ;
298
283
}
299
- _ => Err ( ty:: terr_mismatch)
284
+
285
+ let ty = ty:: mk_ptr ( self . tcx ( ) ,
286
+ ty:: mt { ty : ty, mutbl : mt_b. mutbl } ) ;
287
+ try!( self . fcx . infcx ( ) . try ( |_| self . subtype ( ty, b) ) ) ;
288
+ debug ! ( "Success, coerced with AutoDerefRef(1, \
289
+ AutoPtr(AutoUnsize({:?})))", kind) ;
290
+ Ok ( Some ( AdjustDerefRef ( AutoDerefRef {
291
+ autoderefs : 1 ,
292
+ autoref : Some ( ty:: AutoUnsafe ( mt_b. mutbl ,
293
+ Some ( box AutoUnsize ( kind) ) ) )
294
+ } ) ) )
300
295
}
301
- } )
296
+ _ => Err ( ty:: terr_mismatch)
297
+ }
302
298
}
303
299
( & ty:: ty_uniq( t_a) , & ty:: ty_uniq( t_b) ) => {
304
- self . unpack_actual_value ( t_a, |a| {
305
- match self . unsize_ty ( t_a, a, t_b) {
306
- Some ( ( ty, kind) ) => {
307
- let ty = ty:: mk_uniq ( self . tcx ( ) , ty) ;
308
- try!( self . fcx . infcx ( ) . try ( |_| self . subtype ( ty, b) ) ) ;
309
- debug ! ( "Success, coerced with AutoDerefRef(1, \
310
- AutoUnsizeUniq({:?}))", kind) ;
311
- Ok ( Some ( AdjustDerefRef ( AutoDerefRef {
312
- autoderefs : 1 ,
313
- autoref : Some ( ty:: AutoUnsizeUniq ( kind) )
314
- } ) ) )
315
- }
316
- _ => Err ( ty:: terr_mismatch)
300
+ match self . unsize_ty ( t_a, t_b) {
301
+ Some ( ( ty, kind) ) => {
302
+ let ty = ty:: mk_uniq ( self . tcx ( ) , ty) ;
303
+ try!( self . fcx . infcx ( ) . try ( |_| self . subtype ( ty, b) ) ) ;
304
+ debug ! ( "Success, coerced with AutoDerefRef(1, \
305
+ AutoUnsizeUniq({:?}))", kind) ;
306
+ Ok ( Some ( AdjustDerefRef ( AutoDerefRef {
307
+ autoderefs : 1 ,
308
+ autoref : Some ( ty:: AutoUnsizeUniq ( kind) )
309
+ } ) ) )
317
310
}
318
- } )
311
+ _ => Err ( ty:: terr_mismatch)
312
+ }
319
313
}
320
314
_ => Err ( ty:: terr_mismatch)
321
315
}
@@ -326,93 +320,92 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
326
320
// E.g., `[T, ..n]` -> `([T], UnsizeLength(n))`
327
321
fn unsize_ty ( & self ,
328
322
ty_a : Ty < ' tcx > ,
329
- a : Ty < ' tcx > , // TODO unwrap ty_a here, not in the caller
330
323
ty_b : Ty < ' tcx > )
331
324
-> Option < ( Ty < ' tcx > , ty:: UnsizeKind < ' tcx > ) >
332
325
{
333
326
let tcx = self . tcx ( ) ;
334
327
335
- self . unpack_actual_value ( ty_b, |b| {
336
- debug ! ( "unsize_ty(a={}, b={})" , a. repr( self . tcx( ) ) , b. repr( self . tcx( ) ) ) ;
337
- match ( & a. sty , & b. sty ) {
338
- ( & ty:: ty_vec( t_a, Some ( len) ) , & ty:: ty_vec( _, None ) ) => {
339
- let ty = ty:: mk_vec ( tcx, t_a, None ) ;
340
- Some ( ( ty, ty:: UnsizeLength ( len) ) )
341
- }
342
- ( & ty:: ty_trait( ref data_a) , & ty:: ty_trait( ref data_b) ) => {
343
- // For now, we only support upcasts from
344
- // `Foo+Send` to `Foo` (really, any time there are
345
- // fewer builtin bounds then before). These are
346
- // convenient because they don't require any sort
347
- // of change to the vtable at runtime.
348
- if data_a. bounds . builtin_bounds != data_b. bounds . builtin_bounds &&
349
- data_a. bounds . builtin_bounds . is_superset ( & data_b. bounds . builtin_bounds )
350
- {
351
- let bounds_a1 = ty:: ExistentialBounds {
352
- region_bound : data_a. bounds . region_bound ,
353
- builtin_bounds : data_b. bounds . builtin_bounds ,
354
- projection_bounds : data_a. bounds . projection_bounds . clone ( ) ,
355
- } ;
356
- let ty_a1 = ty:: mk_trait ( tcx, data_a. principal . clone ( ) , bounds_a1) ;
357
- match self . fcx . infcx ( ) . try ( |_| self . subtype ( ty_a1, ty_b) ) {
358
- Ok ( _) => Some ( ( ty_b, ty:: UnsizeUpcast ( ty_b) ) ) ,
359
- Err ( _) => None ,
360
- }
361
- } else {
362
- None
328
+ self . unpack_actual_value ( ty_a, |a| {
329
+ self . unpack_actual_value ( ty_b, |b| {
330
+ debug ! ( "unsize_ty(a={}, b={})" , a. repr( self . tcx( ) ) , b. repr( self . tcx( ) ) ) ;
331
+ match ( & a. sty , & b. sty ) {
332
+ ( & ty:: ty_vec( t_a, Some ( len) ) , & ty:: ty_vec( _, None ) ) => {
333
+ let ty = ty:: mk_vec ( tcx, t_a, None ) ;
334
+ Some ( ( ty, ty:: UnsizeLength ( len) ) )
363
335
}
364
- }
365
- ( _, & ty:: ty_trait( ref data) ) => {
366
- Some ( ( ty_b, ty:: UnsizeVtable ( ty:: TyTrait { principal : data. principal . clone ( ) ,
367
- bounds : data. bounds . clone ( ) } ,
368
- ty_a) ) )
369
- }
370
- ( & ty:: ty_struct( did_a, substs_a) , & ty:: ty_struct( did_b, substs_b) )
371
- if did_a == did_b => {
372
- debug ! ( "unsizing a struct" ) ;
373
- // Try unsizing each type param in turn to see if we end up with ty_b.
374
- let ty_substs_a = substs_a. types . get_slice ( subst:: TypeSpace ) ;
375
- let ty_substs_b = substs_b. types . get_slice ( subst:: TypeSpace ) ;
376
- assert ! ( ty_substs_a. len( ) == ty_substs_b. len( ) ) ;
377
-
378
- let mut result = None ;
379
- let tps = ty_substs_a. iter ( ) . zip ( ty_substs_b. iter ( ) ) . enumerate ( ) ;
380
- for ( i, ( tp_a, tp_b) ) in tps {
381
- if self . fcx . infcx ( ) . try ( |_| self . subtype ( * tp_a, * tp_b) ) . is_ok ( ) {
382
- continue ;
383
- }
384
- match
385
- self . unpack_actual_value (
386
- * tp_a,
387
- |tp| self . unsize_ty ( * tp_a, tp, * tp_b) )
336
+ ( & ty:: ty_trait( ref data_a) , & ty:: ty_trait( ref data_b) ) => {
337
+ // For now, we only support upcasts from
338
+ // `Foo+Send` to `Foo` (really, any time there are
339
+ // fewer builtin bounds then before). These are
340
+ // convenient because they don't require any sort
341
+ // of change to the vtable at runtime.
342
+ if data_a. bounds . builtin_bounds != data_b. bounds . builtin_bounds &&
343
+ data_a. bounds . builtin_bounds . is_superset ( & data_b. bounds . builtin_bounds )
388
344
{
389
- Some ( ( new_tp, k) ) => {
390
- // Check that the whole types match.
391
- let mut new_substs = substs_a. clone ( ) ;
392
- new_substs. types . get_mut_slice ( subst:: TypeSpace ) [ i] = new_tp;
393
- let ty = ty:: mk_struct ( tcx, did_a, tcx. mk_substs ( new_substs) ) ;
394
- if self . fcx . infcx ( ) . try ( |_| self . subtype ( ty, ty_b) ) . is_err ( ) {
395
- debug ! ( "Unsized type parameter '{}', but still \
396
- could not match types {} and {}",
397
- ppaux:: ty_to_string( tcx, * tp_a) ,
398
- ppaux:: ty_to_string( tcx, ty) ,
399
- ppaux:: ty_to_string( tcx, ty_b) ) ;
400
- // We can only unsize a single type parameter, so
401
- // if we unsize one and it doesn't give us the
402
- // type we want, then we won't succeed later.
345
+ let bounds_a1 = ty:: ExistentialBounds {
346
+ region_bound : data_a. bounds . region_bound ,
347
+ builtin_bounds : data_b. bounds . builtin_bounds ,
348
+ projection_bounds : data_a. bounds . projection_bounds . clone ( ) ,
349
+ } ;
350
+ let ty_a1 = ty:: mk_trait ( tcx, data_a. principal . clone ( ) , bounds_a1) ;
351
+ match self . fcx . infcx ( ) . try ( |_| self . subtype ( ty_a1, ty_b) ) {
352
+ Ok ( _) => Some ( ( ty_b, ty:: UnsizeUpcast ( ty_b) ) ) ,
353
+ Err ( _) => None ,
354
+ }
355
+ } else {
356
+ None
357
+ }
358
+ }
359
+ ( _, & ty:: ty_trait( ref data) ) => {
360
+ Some ( ( ty_b, ty:: UnsizeVtable ( ty:: TyTrait {
361
+ principal : data. principal . clone ( ) ,
362
+ bounds : data. bounds . clone ( )
363
+ } ,
364
+ ty_a) ) )
365
+ }
366
+ ( & ty:: ty_struct( did_a, substs_a) , & ty:: ty_struct( did_b, substs_b) )
367
+ if did_a == did_b => {
368
+ debug ! ( "unsizing a struct" ) ;
369
+ // Try unsizing each type param in turn to see if we end up with ty_b.
370
+ let ty_substs_a = substs_a. types . get_slice ( subst:: TypeSpace ) ;
371
+ let ty_substs_b = substs_b. types . get_slice ( subst:: TypeSpace ) ;
372
+ assert ! ( ty_substs_a. len( ) == ty_substs_b. len( ) ) ;
373
+
374
+ let mut result = None ;
375
+ let tps = ty_substs_a. iter ( ) . zip ( ty_substs_b. iter ( ) ) . enumerate ( ) ;
376
+ for ( i, ( tp_a, tp_b) ) in tps {
377
+ if self . fcx . infcx ( ) . try ( |_| self . subtype ( * tp_a, * tp_b) ) . is_ok ( ) {
378
+ continue ;
379
+ }
380
+ match self . unsize_ty ( * tp_a, * tp_b) {
381
+ Some ( ( new_tp, k) ) => {
382
+ // Check that the whole types match.
383
+ let mut new_substs = substs_a. clone ( ) ;
384
+ new_substs. types . get_mut_slice ( subst:: TypeSpace ) [ i] = new_tp;
385
+ let ty = ty:: mk_struct ( tcx, did_a, tcx. mk_substs ( new_substs) ) ;
386
+ if self . fcx . infcx ( ) . try ( |_| self . subtype ( ty, ty_b) ) . is_err ( ) {
387
+ debug ! ( "Unsized type parameter '{}', but still \
388
+ could not match types {} and {}",
389
+ ppaux:: ty_to_string( tcx, * tp_a) ,
390
+ ppaux:: ty_to_string( tcx, ty) ,
391
+ ppaux:: ty_to_string( tcx, ty_b) ) ;
392
+ // We can only unsize a single type parameter, so
393
+ // if we unsize one and it doesn't give us the
394
+ // type we want, then we won't succeed later.
395
+ break ;
396
+ }
397
+
398
+ result = Some ( ( ty, ty:: UnsizeStruct ( box k, i) ) ) ;
403
399
break ;
404
400
}
405
-
406
- result = Some ( ( ty, ty:: UnsizeStruct ( box k, i) ) ) ;
407
- break ;
401
+ None => { }
408
402
}
409
- None => { }
410
403
}
404
+ result
411
405
}
412
- result
406
+ _ => None
413
407
}
414
- _ => None
415
- }
408
+ } )
416
409
} )
417
410
}
418
411
0 commit comments