@@ -24,8 +24,10 @@ use super::{ObligationCauseCode, BuiltinDerivedObligation};
24
24
use super :: { SelectionError , Unimplemented , Overflow , OutputTypeParameterMismatch } ;
25
25
use super :: { Selection } ;
26
26
use 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;
29
31
use super :: { util} ;
30
32
31
33
use middle:: fast_reject;
@@ -147,6 +149,8 @@ enum SelectionCandidate<'tcx> {
147
149
/// types generated for a fn pointer type (e.g., `fn(int)->int`)
148
150
FnPointerCandidate ,
149
151
152
+ ObjectCandidate ,
153
+
150
154
ErrorCandidate ,
151
155
}
152
156
@@ -717,6 +721,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
717
721
try!( self . assemble_unboxed_closure_candidates ( obligation, & mut candidates) ) ;
718
722
try!( self . assemble_fn_pointer_candidates ( obligation, & mut candidates) ) ;
719
723
try!( self . assemble_candidates_from_impls ( obligation, & mut candidates. vec ) ) ;
724
+ self . assemble_candidates_from_object_ty ( obligation, & mut candidates) ;
720
725
}
721
726
}
722
727
@@ -878,7 +883,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
878
883
let matching_bounds =
879
884
all_bounds. filter (
880
885
|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 ( ) ) ;
882
887
883
888
let param_candidates =
884
889
matching_bounds. map ( |bound| ParamCandidate ( bound) ) ;
@@ -945,7 +950,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
945
950
946
951
let self_ty = self . infcx . shallow_resolve ( obligation. self_ty ( ) ) ;
947
952
match self_ty. sty {
948
- ty:: ty_infer( .. ) => {
953
+ ty:: ty_infer( ty :: TyVar ( _ ) ) => {
949
954
candidates. ambiguous = true ; // could wind up being a fn() type
950
955
}
951
956
@@ -991,6 +996,67 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
991
996
Ok ( ( ) )
992
997
}
993
998
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
+
994
1060
///////////////////////////////////////////////////////////////////////////
995
1061
// WINNOW
996
1062
//
@@ -1544,6 +1610,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1544
1610
Ok ( VtableUnboxedClosure ( closure_def_id, substs) )
1545
1611
}
1546
1612
1613
+ ObjectCandidate => {
1614
+ let data = self . confirm_object_candidate ( obligation) ;
1615
+ Ok ( VtableObject ( data) )
1616
+ }
1617
+
1547
1618
FnPointerCandidate => {
1548
1619
let fn_type =
1549
1620
try!( self . confirm_fn_pointer_candidate ( obligation) ) ;
@@ -1727,6 +1798,48 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1727
1798
nested : impl_predicates }
1728
1799
}
1729
1800
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
+
1730
1843
fn confirm_fn_pointer_candidate ( & mut self ,
1731
1844
obligation : & TraitObligation < ' tcx > )
1732
1845
-> Result < ty:: Ty < ' tcx > , SelectionError < ' tcx > >
@@ -1962,12 +2075,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1962
2075
} )
1963
2076
}
1964
2077
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 < ( ) , ( ) >
1969
2082
{
1970
- debug ! ( "match_where_clause : obligation={} where_clause_trait_ref={}" ,
2083
+ debug ! ( "match_poly_trait_ref : obligation={} where_clause_trait_ref={}" ,
1971
2084
obligation. repr( self . tcx( ) ) ,
1972
2085
where_clause_trait_ref. repr( self . tcx( ) ) ) ;
1973
2086
@@ -2161,6 +2274,9 @@ impl<'tcx> Repr<'tcx> for SelectionCandidate<'tcx> {
2161
2274
ImplCandidate ( a) => format ! ( "ImplCandidate({})" , a. repr( tcx) ) ,
2162
2275
ProjectionCandidate => format ! ( "ProjectionCandidate" ) ,
2163
2276
FnPointerCandidate => format ! ( "FnPointerCandidate" ) ,
2277
+ ObjectCandidate => {
2278
+ format ! ( "ObjectCandidate" )
2279
+ }
2164
2280
UnboxedClosureCandidate ( c, ref s) => {
2165
2281
format ! ( "UnboxedClosureCandidate({},{})" , c, s. repr( tcx) )
2166
2282
}
0 commit comments