@@ -1351,11 +1351,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
13511351 // correct trait, but also the correct type parameters.
13521352 // For example, we may be trying to upcast `Foo` to `Bar<i32>`,
13531353 // 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 ( ) ;
13591363
13601364 if upcast_trait_refs > 1 {
13611365 // can be upcast in many ways; need more type information
@@ -1627,9 +1631,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
16271631 let principal =
16281632 data. principal_trait_ref_with_self_ty ( self . tcx ( ) ,
16291633 self . tcx ( ) . types . err ) ;
1630- let desired_def_id = obligation. predicate . def_id ( ) ;
1634+ let copy_def_id = obligation. predicate . def_id ( ) ;
16311635 for tr in util:: supertraits ( self . tcx ( ) , principal) {
1632- if tr. def_id ( ) == desired_def_id {
1636+ if tr. def_id ( ) == copy_def_id {
16331637 return ok_if ( Vec :: new ( ) )
16341638 }
16351639 }
@@ -2282,31 +2286,41 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
22822286 }
22832287 } ;
22842288
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- } ) ;
22952289 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 ( ) ;
22972318
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) ;
23042319 }
2305- assert ! ( upcast_trait_refs. all( |( _, matches) | !matches) ) ;
23062320
23072321 VtableObjectData {
23082322 upcast_trait_ref : upcast_trait_ref. unwrap ( ) ,
2309- vtable_base : vtable_base
2323+ vtable_base : vtable_base,
23102324 }
23112325 }
23122326
0 commit comments