@@ -1362,12 +1362,21 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1362
1362
debug ! ( "assemble_candidates_from_object_ty: poly_trait_ref={:?}" ,
1363
1363
poly_trait_ref) ;
1364
1364
1365
- // see whether the object trait can be upcast to the trait we are looking for
1366
- let upcast_trait_refs = self . upcast ( poly_trait_ref, obligation) ;
1367
- if upcast_trait_refs. len ( ) > 1 {
1365
+ // Count only those upcast versions that match the trait-ref
1366
+ // we are looking for. Specifically, do not only check for the
1367
+ // correct trait, but also the correct type parameters.
1368
+ // For example, we may be trying to upcast `Foo` to `Bar<i32>`,
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 ( ) ;
1375
+
1376
+ if upcast_trait_refs > 1 {
1368
1377
// can be upcast in many ways; need more type information
1369
1378
candidates. ambiguous = true ;
1370
- } else if upcast_trait_refs. len ( ) == 1 {
1379
+ } else if upcast_trait_refs == 1 {
1371
1380
candidates. vec . push ( ObjectCandidate ) ;
1372
1381
}
1373
1382
@@ -2305,20 +2314,28 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
2305
2314
// be exactly one applicable trait-reference; if this were not
2306
2315
// the case, we would have reported an ambiguity error rather
2307
2316
// than successfully selecting one of the candidates.
2308
- let upcast_trait_refs = self . upcast ( poly_trait_ref. clone ( ) , obligation) ;
2309
- assert_eq ! ( upcast_trait_refs. len( ) , 1 ) ;
2310
- let upcast_trait_ref = upcast_trait_refs. into_iter ( ) . next ( ) . unwrap ( ) ;
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
+ let mut upcast_trait_ref = None ;
2324
+ let mut vtable_base = 0 ;
2311
2325
2312
- match self . match_poly_trait_ref ( obligation, upcast_trait_ref. clone ( ) ) {
2313
- Ok ( ( ) ) => { }
2314
- Err ( ( ) ) => {
2315
- self . tcx ( ) . sess . span_bug ( obligation. cause . span ,
2316
- "failed to match trait refs" ) ;
2326
+ while let Some ( ( supertrait, matches) ) = upcast_trait_refs. next ( ) {
2327
+ if matches {
2328
+ upcast_trait_ref = Some ( supertrait) ;
2329
+ break ;
2317
2330
}
2331
+ vtable_base += util:: count_own_vtable_entries ( self . tcx ( ) , supertrait) ;
2318
2332
}
2333
+ assert ! ( upcast_trait_refs. all( |( _, matches) | !matches) ) ;
2319
2334
2320
- VtableObjectData { object_ty : self_ty,
2321
- upcast_trait_ref : upcast_trait_ref }
2335
+ VtableObjectData {
2336
+ upcast_trait_ref : upcast_trait_ref. unwrap ( ) ,
2337
+ vtable_base : vtable_base
2338
+ }
2322
2339
}
2323
2340
2324
2341
fn confirm_fn_pointer_candidate ( & mut self ,
@@ -2719,7 +2736,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
2719
2736
2720
2737
/// Returns `Ok` if `poly_trait_ref` being true implies that the
2721
2738
/// obligation is satisfied.
2722
- fn match_poly_trait_ref ( & mut self ,
2739
+ fn match_poly_trait_ref ( & self ,
2723
2740
obligation : & TraitObligation < ' tcx > ,
2724
2741
poly_trait_ref : ty:: PolyTraitRef < ' tcx > )
2725
2742
-> Result < ( ) , ( ) >
@@ -2930,32 +2947,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
2930
2947
obligation. cause . clone ( )
2931
2948
}
2932
2949
}
2933
-
2934
- /// Upcasts an object trait-reference into those that match the obligation.
2935
- fn upcast ( & mut self , obj_trait_ref : ty:: PolyTraitRef < ' tcx > , obligation : & TraitObligation < ' tcx > )
2936
- -> Vec < ty:: PolyTraitRef < ' tcx > >
2937
- {
2938
- debug ! ( "upcast(obj_trait_ref={:?}, obligation={:?})" ,
2939
- obj_trait_ref,
2940
- obligation) ;
2941
-
2942
- let obligation_def_id = obligation. predicate . def_id ( ) ;
2943
- let mut upcast_trait_refs = util:: upcast ( self . tcx ( ) , obj_trait_ref, obligation_def_id) ;
2944
-
2945
- // Retain only those upcast versions that match the trait-ref
2946
- // we are looking for. In particular, we know that all of
2947
- // `upcast_trait_refs` apply to the correct trait, but
2948
- // possibly with incorrect type parameters. For example, we
2949
- // may be trying to upcast `Foo` to `Bar<i32>`, but `Foo` is
2950
- // declared as `trait Foo : Bar<u32>`.
2951
- upcast_trait_refs. retain ( |upcast_trait_ref| {
2952
- let upcast_trait_ref = upcast_trait_ref. clone ( ) ;
2953
- self . infcx . probe ( |_| self . match_poly_trait_ref ( obligation, upcast_trait_ref) ) . is_ok ( )
2954
- } ) ;
2955
-
2956
- debug ! ( "upcast: upcast_trait_refs={:?}" , upcast_trait_refs) ;
2957
- upcast_trait_refs
2958
- }
2959
2950
}
2960
2951
2961
2952
impl < ' tcx > SelectionCache < ' tcx > {
0 commit comments