@@ -1351,11 +1351,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1351
1351
// correct trait, but also the correct type parameters.
1352
1352
// For example, we may be trying to upcast `Foo` to `Bar<i32>`,
1353
1353
// but `Foo` is declared as `trait Foo : Bar<u32>`.
1354
- let upcast_trait_refs = util:: supertraits ( self . tcx ( ) , poly_trait_ref)
1355
- . filter ( |upcast_trait_ref| self . infcx . probe ( |_| {
1356
- let upcast_trait_ref = upcast_trait_ref. clone ( ) ;
1357
- self . match_poly_trait_ref ( obligation, upcast_trait_ref) . is_ok ( )
1358
- } ) ) . count ( ) ;
1354
+ let upcast_trait_refs =
1355
+ util:: supertraits ( self . tcx ( ) , poly_trait_ref)
1356
+ . filter ( |upcast_trait_ref| {
1357
+ self . infcx . probe ( |_| {
1358
+ let upcast_trait_ref = upcast_trait_ref. clone ( ) ;
1359
+ self . match_poly_trait_ref ( obligation, upcast_trait_ref) . is_ok ( )
1360
+ } )
1361
+ } )
1362
+ . count ( ) ;
1359
1363
1360
1364
if upcast_trait_refs > 1 {
1361
1365
// can be upcast in many ways; need more type information
@@ -1627,9 +1631,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1627
1631
let principal =
1628
1632
data. principal_trait_ref_with_self_ty ( self . tcx ( ) ,
1629
1633
self . tcx ( ) . types . err ) ;
1630
- let desired_def_id = obligation. predicate . def_id ( ) ;
1634
+ let copy_def_id = obligation. predicate . def_id ( ) ;
1631
1635
for tr in util:: supertraits ( self . tcx ( ) , principal) {
1632
- if tr. def_id ( ) == desired_def_id {
1636
+ if tr. def_id ( ) == copy_def_id {
1633
1637
return ok_if ( Vec :: new ( ) )
1634
1638
}
1635
1639
}
@@ -2282,31 +2286,41 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
2282
2286
}
2283
2287
} ;
2284
2288
2285
- // Upcast the object type to the obligation type. There must
2286
- // be exactly one applicable trait-reference; if this were not
2287
- // the case, we would have reported an ambiguity error rather
2288
- // than successfully selecting one of the candidates.
2289
- let mut upcast_trait_refs = util:: supertraits ( self . tcx ( ) , poly_trait_ref)
2290
- . map ( |upcast_trait_ref| {
2291
- ( upcast_trait_ref. clone ( ) , self . infcx . probe ( |_| {
2292
- self . match_poly_trait_ref ( obligation, upcast_trait_ref)
2293
- } ) . is_ok ( ) )
2294
- } ) ;
2295
2289
let mut upcast_trait_ref = None ;
2296
- let mut vtable_base = 0 ;
2290
+ let vtable_base;
2291
+
2292
+ {
2293
+ // We want to find the first supertrait in the list of
2294
+ // supertraits that we can unify with, and do that
2295
+ // unification. We know that there is exactly one in the list
2296
+ // where we can unify because otherwise select would have
2297
+ // reported an ambiguity. (When we do find a match, also
2298
+ // record it for later.)
2299
+ let nonmatching =
2300
+ util:: supertraits ( self . tcx ( ) , poly_trait_ref)
2301
+ . take_while ( |& t| {
2302
+ match
2303
+ self . infcx . commit_if_ok (
2304
+ |_| self . match_poly_trait_ref ( obligation, t) )
2305
+ {
2306
+ Ok ( _) => { upcast_trait_ref = Some ( t) ; false }
2307
+ Err ( _) => { true }
2308
+ }
2309
+ } ) ;
2310
+
2311
+ // Additionally, for each of the nonmatching predicates that
2312
+ // we pass over, we sum up the set of number of vtable
2313
+ // entries, so that we can compute the offset for the selected
2314
+ // trait.
2315
+ vtable_base =
2316
+ nonmatching. map ( |t| util:: count_own_vtable_entries ( self . tcx ( ) , t) )
2317
+ . sum ( ) ;
2297
2318
2298
- while let Some ( ( supertrait, matches) ) = upcast_trait_refs. next ( ) {
2299
- if matches {
2300
- upcast_trait_ref = Some ( supertrait) ;
2301
- break ;
2302
- }
2303
- vtable_base += util:: count_own_vtable_entries ( self . tcx ( ) , supertrait) ;
2304
2319
}
2305
- assert ! ( upcast_trait_refs. all( |( _, matches) | !matches) ) ;
2306
2320
2307
2321
VtableObjectData {
2308
2322
upcast_trait_ref : upcast_trait_ref. unwrap ( ) ,
2309
- vtable_base : vtable_base
2323
+ vtable_base : vtable_base,
2310
2324
}
2311
2325
}
2312
2326
0 commit comments