@@ -1367,11 +1367,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1367
1367
// correct trait, but also the correct type parameters.
1368
1368
// For example, we may be trying to upcast `Foo` to `Bar<i32>`,
1369
1369
// but `Foo` is declared as `trait Foo : Bar<u32>`.
1370
- let upcast_trait_refs = util:: supertraits ( self . tcx ( ) , poly_trait_ref)
1371
- . filter ( |upcast_trait_ref| self . infcx . probe ( |_| {
1372
- let upcast_trait_ref = upcast_trait_ref. clone ( ) ;
1373
- self . match_poly_trait_ref ( obligation, upcast_trait_ref) . is_ok ( )
1374
- } ) ) . count ( ) ;
1370
+ let upcast_trait_refs =
1371
+ util:: supertraits ( self . tcx ( ) , poly_trait_ref)
1372
+ . filter ( |upcast_trait_ref| {
1373
+ self . infcx . probe ( |_| {
1374
+ let upcast_trait_ref = upcast_trait_ref. clone ( ) ;
1375
+ self . match_poly_trait_ref ( obligation, upcast_trait_ref) . is_ok ( )
1376
+ } )
1377
+ } )
1378
+ . count ( ) ;
1375
1379
1376
1380
if upcast_trait_refs > 1 {
1377
1381
// can be upcast in many ways; need more type information
@@ -1643,9 +1647,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1643
1647
let principal =
1644
1648
data. principal_trait_ref_with_self_ty ( self . tcx ( ) ,
1645
1649
self . tcx ( ) . types . err ) ;
1646
- let desired_def_id = obligation. predicate . def_id ( ) ;
1650
+ let copy_def_id = obligation. predicate . def_id ( ) ;
1647
1651
for tr in util:: supertraits ( self . tcx ( ) , principal) {
1648
- if tr. def_id ( ) == desired_def_id {
1652
+ if tr. def_id ( ) == copy_def_id {
1649
1653
return ok_if ( Vec :: new ( ) )
1650
1654
}
1651
1655
}
@@ -2310,31 +2314,41 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
2310
2314
}
2311
2315
} ;
2312
2316
2313
- // Upcast the object type to the obligation type. There must
2314
- // be exactly one applicable trait-reference; if this were not
2315
- // the case, we would have reported an ambiguity error rather
2316
- // than successfully selecting one of the candidates.
2317
- let mut upcast_trait_refs = util:: supertraits ( self . tcx ( ) , poly_trait_ref)
2318
- . map ( |upcast_trait_ref| {
2319
- ( upcast_trait_ref. clone ( ) , self . infcx . probe ( |_| {
2320
- self . match_poly_trait_ref ( obligation, upcast_trait_ref)
2321
- } ) . is_ok ( ) )
2322
- } ) ;
2323
2317
let mut upcast_trait_ref = None ;
2324
- let mut vtable_base = 0 ;
2318
+ let vtable_base;
2319
+
2320
+ {
2321
+ // We want to find the first supertrait in the list of
2322
+ // supertraits that we can unify with, and do that
2323
+ // unification. We know that there is exactly one in the list
2324
+ // where we can unify because otherwise select would have
2325
+ // reported an ambiguity. (When we do find a match, also
2326
+ // record it for later.)
2327
+ let nonmatching =
2328
+ util:: supertraits ( self . tcx ( ) , poly_trait_ref)
2329
+ . take_while ( |& t| {
2330
+ match
2331
+ self . infcx . commit_if_ok (
2332
+ |_| self . match_poly_trait_ref ( obligation, t) )
2333
+ {
2334
+ Ok ( _) => { upcast_trait_ref = Some ( t) ; false }
2335
+ Err ( _) => { true }
2336
+ }
2337
+ } ) ;
2338
+
2339
+ // Additionally, for each of the nonmatching predicates that
2340
+ // we pass over, we sum up the set of number of vtable
2341
+ // entries, so that we can compute the offset for the selected
2342
+ // trait.
2343
+ vtable_base =
2344
+ nonmatching. map ( |t| util:: count_own_vtable_entries ( self . tcx ( ) , t) )
2345
+ . sum ( ) ;
2325
2346
2326
- while let Some ( ( supertrait, matches) ) = upcast_trait_refs. next ( ) {
2327
- if matches {
2328
- upcast_trait_ref = Some ( supertrait) ;
2329
- break ;
2330
- }
2331
- vtable_base += util:: count_own_vtable_entries ( self . tcx ( ) , supertrait) ;
2332
2347
}
2333
- assert ! ( upcast_trait_refs. all( |( _, matches) | !matches) ) ;
2334
2348
2335
2349
VtableObjectData {
2336
2350
upcast_trait_ref : upcast_trait_ref. unwrap ( ) ,
2337
- vtable_base : vtable_base
2351
+ vtable_base : vtable_base,
2338
2352
}
2339
2353
}
2340
2354
0 commit comments