@@ -1260,19 +1260,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
12601260 poly_trait_ref. repr( self . tcx( ) ) ) ;
12611261
12621262 // 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 {
12761268 candidates. vec . push ( ObjectCandidate ) ;
12771269 }
12781270 }
@@ -2063,28 +2055,24 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
20632055 }
20642056 } ;
20652057
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 ( ) ;
20782065
2079- match self . match_poly_trait_ref ( obligation, upcast_trait_ref) {
2066+ match self . match_poly_trait_ref ( obligation, upcast_trait_ref. clone ( ) ) {
20802067 Ok ( ( ) ) => { }
20812068 Err ( ( ) ) => {
20822069 self . tcx ( ) . sess . span_bug ( obligation. cause . span ,
20832070 "failed to match trait refs" ) ;
20842071 }
20852072 }
20862073
2087- VtableObjectData { object_ty : self_ty }
2074+ VtableObjectData { object_ty : self_ty,
2075+ upcast_trait_ref : upcast_trait_ref }
20882076 }
20892077
20902078 fn confirm_fn_pointer_candidate ( & mut self ,
@@ -2501,6 +2489,27 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
25012489 obligation. cause . clone ( )
25022490 }
25032491 }
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+ }
25042513}
25052514
25062515impl < ' tcx > Repr < ' tcx > for SelectionCandidate < ' tcx > {
0 commit comments