@@ -1367,11 +1367,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
13671367 // correct trait, but also the correct type parameters.
13681368 // For example, we may be trying to upcast `Foo` to `Bar<i32>`,
13691369 // 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 ( ) ;
13751379
13761380 if upcast_trait_refs > 1 {
13771381 // can be upcast in many ways; need more type information
@@ -1643,9 +1647,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
16431647 let principal =
16441648 data. principal_trait_ref_with_self_ty ( self . tcx ( ) ,
16451649 self . tcx ( ) . types . err ) ;
1646- let desired_def_id = obligation. predicate . def_id ( ) ;
1650+ let copy_def_id = obligation. predicate . def_id ( ) ;
16471651 for tr in util:: supertraits ( self . tcx ( ) , principal) {
1648- if tr. def_id ( ) == desired_def_id {
1652+ if tr. def_id ( ) == copy_def_id {
16491653 return ok_if ( Vec :: new ( ) )
16501654 }
16511655 }
@@ -2310,31 +2314,41 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
23102314 }
23112315 } ;
23122316
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- } ) ;
23232317 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 ( ) ;
23252346
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) ;
23322347 }
2333- assert ! ( upcast_trait_refs. all( |( _, matches) | !matches) ) ;
23342348
23352349 VtableObjectData {
23362350 upcast_trait_ref : upcast_trait_ref. unwrap ( ) ,
2337- vtable_base : vtable_base
2351+ vtable_base : vtable_base,
23382352 }
23392353 }
23402354
0 commit comments