@@ -24,8 +24,10 @@ use super::{ObligationCauseCode, BuiltinDerivedObligation};
2424use super :: { SelectionError , Unimplemented , Overflow , OutputTypeParameterMismatch } ;
2525use super :: { Selection } ;
2626use super :: { SelectionResult } ;
27- use super :: { VtableBuiltin , VtableImpl , VtableParam , VtableUnboxedClosure , VtableFnPointer } ;
28- use super :: { VtableImplData , VtableBuiltinData } ;
27+ use super :: { VtableBuiltin , VtableImpl , VtableParam , VtableUnboxedClosure ,
28+ VtableFnPointer , VtableObject } ;
29+ use super :: { VtableImplData , VtableObjectData , VtableBuiltinData } ;
30+ use super :: object_safety;
2931use super :: { util} ;
3032
3133use middle:: fast_reject;
@@ -147,6 +149,8 @@ enum SelectionCandidate<'tcx> {
147149 /// types generated for a fn pointer type (e.g., `fn(int)->int`)
148150 FnPointerCandidate ,
149151
152+ ObjectCandidate ,
153+
150154 ErrorCandidate ,
151155}
152156
@@ -717,6 +721,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
717721 try!( self . assemble_unboxed_closure_candidates ( obligation, & mut candidates) ) ;
718722 try!( self . assemble_fn_pointer_candidates ( obligation, & mut candidates) ) ;
719723 try!( self . assemble_candidates_from_impls ( obligation, & mut candidates. vec ) ) ;
724+ self . assemble_candidates_from_object_ty ( obligation, & mut candidates) ;
720725 }
721726 }
722727
@@ -878,7 +883,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
878883 let matching_bounds =
879884 all_bounds. filter (
880885 |bound| self . infcx . probe (
881- |_| self . match_where_clause ( obligation, bound. clone ( ) ) ) . is_ok ( ) ) ;
886+ |_| self . match_poly_trait_ref ( obligation, bound. clone ( ) ) ) . is_ok ( ) ) ;
882887
883888 let param_candidates =
884889 matching_bounds. map ( |bound| ParamCandidate ( bound) ) ;
@@ -945,7 +950,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
945950
946951 let self_ty = self . infcx . shallow_resolve ( obligation. self_ty ( ) ) ;
947952 match self_ty. sty {
948- ty:: ty_infer( .. ) => {
953+ ty:: ty_infer( ty :: TyVar ( _ ) ) => {
949954 candidates. ambiguous = true ; // could wind up being a fn() type
950955 }
951956
@@ -991,6 +996,67 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
991996 Ok ( ( ) )
992997 }
993998
999+ /// Search for impls that might apply to `obligation`.
1000+ fn assemble_candidates_from_object_ty ( & mut self ,
1001+ obligation : & TraitObligation < ' tcx > ,
1002+ candidates : & mut SelectionCandidateSet < ' tcx > )
1003+ {
1004+ let self_ty = self . infcx . shallow_resolve ( obligation. self_ty ( ) ) ;
1005+
1006+ debug ! ( "assemble_candidates_from_object_ty(self_ty={})" ,
1007+ self_ty. repr( self . tcx( ) ) ) ;
1008+
1009+ // Object-safety candidates are only applicable to object-safe
1010+ // traits. Including this check is useful because it helps
1011+ // inference in cases of traits like `BorrowFrom`, which are
1012+ // not object-safe, and which rely on being able to infer the
1013+ // self-type from one of the other inputs. Without this check,
1014+ // these cases wind up being considered ambiguous due to a
1015+ // (spurious) ambiguity introduced here.
1016+ if !object_safety:: is_object_safe ( self . tcx ( ) , obligation. predicate . to_poly_trait_ref ( ) ) {
1017+ return ;
1018+ }
1019+
1020+ let poly_trait_ref = match self_ty. sty {
1021+ ty:: ty_trait( ref data) => {
1022+ data. principal_trait_ref_with_self_ty ( self . tcx ( ) , self_ty)
1023+ }
1024+ ty:: ty_infer( ty:: TyVar ( _) ) => {
1025+ debug ! ( "assemble_candidates_from_object_ty: ambiguous" ) ;
1026+ candidates. ambiguous = true ; // could wind up being an object type
1027+ return ;
1028+ }
1029+ _ => {
1030+ return ;
1031+ }
1032+ } ;
1033+
1034+ debug ! ( "assemble_candidates_from_object_ty: poly_trait_ref={}" ,
1035+ poly_trait_ref. repr( self . tcx( ) ) ) ;
1036+
1037+ // see whether the object trait can be upcast to the trait we are looking for
1038+ let obligation_def_id = obligation. predicate . def_id ( ) ;
1039+ let upcast_trait_ref = match util:: upcast ( self . tcx ( ) , poly_trait_ref, obligation_def_id) {
1040+ Some ( r) => r,
1041+ None => { return ; }
1042+ } ;
1043+
1044+ debug ! ( "assemble_candidates_from_object_ty: upcast_trait_ref={}" ,
1045+ upcast_trait_ref. repr( self . tcx( ) ) ) ;
1046+
1047+ // check whether the upcast version of the trait-ref matches what we are looking for
1048+ match
1049+ self . infcx . probe (
1050+ |_| self . match_poly_trait_ref ( obligation, upcast_trait_ref. clone ( ) ) )
1051+ {
1052+ Ok ( ( ) ) => {
1053+ debug ! ( "assemble_candidates_from_object_ty: matched, pushing candidate" ) ;
1054+ candidates. vec . push ( ObjectCandidate ) ;
1055+ }
1056+ Err ( ( ) ) => { }
1057+ }
1058+ }
1059+
9941060 ///////////////////////////////////////////////////////////////////////////
9951061 // WINNOW
9961062 //
@@ -1544,6 +1610,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
15441610 Ok ( VtableUnboxedClosure ( closure_def_id, substs) )
15451611 }
15461612
1613+ ObjectCandidate => {
1614+ let data = self . confirm_object_candidate ( obligation) ;
1615+ Ok ( VtableObject ( data) )
1616+ }
1617+
15471618 FnPointerCandidate => {
15481619 let fn_type =
15491620 try!( self . confirm_fn_pointer_candidate ( obligation) ) ;
@@ -1727,6 +1798,48 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
17271798 nested : impl_predicates }
17281799 }
17291800
1801+ fn confirm_object_candidate ( & mut self ,
1802+ obligation : & TraitObligation < ' tcx > )
1803+ -> VtableObjectData < ' tcx >
1804+ {
1805+ debug ! ( "confirm_object_candidate({})" ,
1806+ obligation. repr( self . tcx( ) ) ) ;
1807+
1808+ let self_ty = self . infcx . shallow_resolve ( obligation. self_ty ( ) ) ;
1809+ let poly_trait_ref = match self_ty. sty {
1810+ ty:: ty_trait( ref data) => {
1811+ data. principal_trait_ref_with_self_ty ( self . tcx ( ) , self_ty)
1812+ }
1813+ _ => {
1814+ self . tcx ( ) . sess . span_bug ( obligation. cause . span ,
1815+ "object candidate with non-object" ) ;
1816+ }
1817+ } ;
1818+
1819+ let obligation_def_id = obligation. predicate . def_id ( ) ;
1820+ let upcast_trait_ref = match util:: upcast ( self . tcx ( ) ,
1821+ poly_trait_ref. clone ( ) ,
1822+ obligation_def_id) {
1823+ Some ( r) => r,
1824+ None => {
1825+ self . tcx ( ) . sess . span_bug ( obligation. cause . span ,
1826+ format ! ( "unable to upcast from {} to {}" ,
1827+ poly_trait_ref. repr( self . tcx( ) ) ,
1828+ obligation_def_id. repr( self . tcx( ) ) ) . as_slice ( ) ) ;
1829+ }
1830+ } ;
1831+
1832+ match self . match_poly_trait_ref ( obligation, upcast_trait_ref) {
1833+ Ok ( ( ) ) => { }
1834+ Err ( ( ) ) => {
1835+ self . tcx ( ) . sess . span_bug ( obligation. cause . span ,
1836+ "failed to match trait refs" ) ;
1837+ }
1838+ }
1839+
1840+ VtableObjectData { object_ty : self_ty }
1841+ }
1842+
17301843 fn confirm_fn_pointer_candidate ( & mut self ,
17311844 obligation : & TraitObligation < ' tcx > )
17321845 -> Result < ty:: Ty < ' tcx > , SelectionError < ' tcx > >
@@ -1962,12 +2075,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
19622075 } )
19632076 }
19642077
1965- fn match_where_clause ( & mut self ,
1966- obligation : & TraitObligation < ' tcx > ,
1967- where_clause_trait_ref : ty:: PolyTraitRef < ' tcx > )
1968- -> Result < ( ) , ( ) >
2078+ fn match_poly_trait_ref ( & mut self ,
2079+ obligation : & TraitObligation < ' tcx > ,
2080+ where_clause_trait_ref : ty:: PolyTraitRef < ' tcx > )
2081+ -> Result < ( ) , ( ) >
19692082 {
1970- debug ! ( "match_where_clause : obligation={} where_clause_trait_ref={}" ,
2083+ debug ! ( "match_poly_trait_ref : obligation={} where_clause_trait_ref={}" ,
19712084 obligation. repr( self . tcx( ) ) ,
19722085 where_clause_trait_ref. repr( self . tcx( ) ) ) ;
19732086
@@ -2161,6 +2274,9 @@ impl<'tcx> Repr<'tcx> for SelectionCandidate<'tcx> {
21612274 ImplCandidate ( a) => format ! ( "ImplCandidate({})" , a. repr( tcx) ) ,
21622275 ProjectionCandidate => format ! ( "ProjectionCandidate" ) ,
21632276 FnPointerCandidate => format ! ( "FnPointerCandidate" ) ,
2277+ ObjectCandidate => {
2278+ format ! ( "ObjectCandidate" )
2279+ }
21642280 UnboxedClosureCandidate ( c, ref s) => {
21652281 format ! ( "UnboxedClosureCandidate({},{})" , c, s. repr( tcx) )
21662282 }
0 commit comments