@@ -1260,19 +1260,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1260
1260
poly_trait_ref. repr( self . tcx( ) ) ) ;
1261
1261
1262
1262
// see whether the object trait can be upcast to the trait we are looking for
1263
- let obligation_def_id = obligation. predicate . def_id ( ) ;
1264
- let upcast_trait_ref = match util:: upcast ( self . tcx ( ) , poly_trait_ref, obligation_def_id) {
1265
- Some ( r) => r,
1266
- None => { return ; }
1267
- } ;
1268
-
1269
- debug ! ( "assemble_candidates_from_object_ty: upcast_trait_ref={}" ,
1270
- upcast_trait_ref. repr( self . tcx( ) ) ) ;
1271
-
1272
- // check whether the upcast version of the trait-ref matches what we are looking for
1273
- if let Ok ( ( ) ) = self . infcx . probe ( |_| self . match_poly_trait_ref ( obligation,
1274
- upcast_trait_ref. clone ( ) ) ) {
1275
- debug ! ( "assemble_candidates_from_object_ty: matched, pushing candidate" ) ;
1263
+ let upcast_trait_refs = self . upcast ( poly_trait_ref, obligation) ;
1264
+ if upcast_trait_refs. len ( ) > 1 {
1265
+ // can be upcast in many ways; need more type information
1266
+ candidates. ambiguous = true ;
1267
+ } else if upcast_trait_refs. len ( ) == 1 {
1276
1268
candidates. vec . push ( ObjectCandidate ) ;
1277
1269
}
1278
1270
}
@@ -2063,28 +2055,24 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
2063
2055
}
2064
2056
} ;
2065
2057
2066
- let obligation_def_id = obligation. predicate . def_id ( ) ;
2067
- let upcast_trait_ref = match util:: upcast ( self . tcx ( ) ,
2068
- poly_trait_ref. clone ( ) ,
2069
- obligation_def_id) {
2070
- Some ( r) => r,
2071
- None => {
2072
- self . tcx ( ) . sess . span_bug ( obligation. cause . span ,
2073
- & format ! ( "unable to upcast from {} to {}" ,
2074
- poly_trait_ref. repr( self . tcx( ) ) ,
2075
- obligation_def_id. repr( self . tcx( ) ) ) ) ;
2076
- }
2077
- } ;
2058
+ // Upcast the object type to the obligation type. There must
2059
+ // be exactly one applicable trait-reference; if this were not
2060
+ // the case, we would have reported an ambiguity error rather
2061
+ // than successfully selecting one of the candidates.
2062
+ let upcast_trait_refs = self . upcast ( poly_trait_ref. clone ( ) , obligation) ;
2063
+ assert_eq ! ( upcast_trait_refs. len( ) , 1 ) ;
2064
+ let upcast_trait_ref = upcast_trait_refs. into_iter ( ) . next ( ) . unwrap ( ) ;
2078
2065
2079
- match self . match_poly_trait_ref ( obligation, upcast_trait_ref) {
2066
+ match self . match_poly_trait_ref ( obligation, upcast_trait_ref. clone ( ) ) {
2080
2067
Ok ( ( ) ) => { }
2081
2068
Err ( ( ) ) => {
2082
2069
self . tcx ( ) . sess . span_bug ( obligation. cause . span ,
2083
2070
"failed to match trait refs" ) ;
2084
2071
}
2085
2072
}
2086
2073
2087
- VtableObjectData { object_ty : self_ty }
2074
+ VtableObjectData { object_ty : self_ty,
2075
+ upcast_trait_ref : upcast_trait_ref }
2088
2076
}
2089
2077
2090
2078
fn confirm_fn_pointer_candidate ( & mut self ,
@@ -2501,6 +2489,27 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
2501
2489
obligation. cause . clone ( )
2502
2490
}
2503
2491
}
2492
+
2493
+ /// Upcasts an object trait-reference into those that match the obligation.
2494
+ fn upcast ( & mut self , obj_trait_ref : ty:: PolyTraitRef < ' tcx > , obligation : & TraitObligation < ' tcx > )
2495
+ -> Vec < ty:: PolyTraitRef < ' tcx > >
2496
+ {
2497
+ debug ! ( "upcast(obj_trait_ref={}, obligation={})" ,
2498
+ obj_trait_ref. repr( self . tcx( ) ) ,
2499
+ obligation. repr( self . tcx( ) ) ) ;
2500
+
2501
+ let obligation_def_id = obligation. predicate . def_id ( ) ;
2502
+ let mut upcast_trait_refs = util:: upcast ( self . tcx ( ) , obj_trait_ref, obligation_def_id) ;
2503
+
2504
+ // retain only those upcast versions that match the trait-ref we are looking for
2505
+ upcast_trait_refs. retain ( |upcast_trait_ref| {
2506
+ let upcast_trait_ref = upcast_trait_ref. clone ( ) ;
2507
+ self . infcx . probe ( |_| self . match_poly_trait_ref ( obligation, upcast_trait_ref) ) . is_ok ( )
2508
+ } ) ;
2509
+
2510
+ debug ! ( "upcast: upcast_trait_refs={}" , upcast_trait_refs. repr( self . tcx( ) ) ) ;
2511
+ upcast_trait_refs
2512
+ }
2504
2513
}
2505
2514
2506
2515
impl < ' tcx > Repr < ' tcx > for SelectionCandidate < ' tcx > {
0 commit comments