@@ -22,7 +22,7 @@ use super::{SelectionError, Unimplemented, Overflow,
22
22
OutputTypeParameterMismatch } ;
23
23
use super :: { Selection } ;
24
24
use super :: { SelectionResult } ;
25
- use super :: { VtableBuiltin , VtableImpl , VtableParam , VtableUnboxedClosure } ;
25
+ use super :: { VtableBuiltin , VtableImpl , VtableParam , VtableUnboxedClosure , VtableFnPointer } ;
26
26
use super :: { VtableImplData , VtableParamData , VtableBuiltinData } ;
27
27
use super :: { util} ;
28
28
@@ -36,7 +36,7 @@ use middle::ty_fold::TypeFoldable;
36
36
use std:: cell:: RefCell ;
37
37
use std:: collections:: hash_map:: HashMap ;
38
38
use std:: rc:: Rc ;
39
- use syntax:: ast;
39
+ use syntax:: { abi , ast} ;
40
40
use util:: common:: ErrorReported ;
41
41
use util:: ppaux:: Repr ;
42
42
@@ -131,7 +131,15 @@ enum Candidate<'tcx> {
131
131
BuiltinCandidate ( ty:: BuiltinBound ) ,
132
132
ParamCandidate ( VtableParamData < ' tcx > ) ,
133
133
ImplCandidate ( ast:: DefId ) ,
134
+
135
+ /// Implementation of a `Fn`-family trait by one of the
136
+ /// anonymous types generated for a `||` expression.
134
137
UnboxedClosureCandidate ( /* closure */ ast:: DefId , Substs < ' tcx > ) ,
138
+
139
+ /// Implementation of a `Fn`-family trait by one of the anonymous
140
+ /// types generated for a fn pointer type (e.g., `fn(int)->int`)
141
+ FnPointerCandidate ,
142
+
135
143
ErrorCandidate ,
136
144
}
137
145
@@ -917,7 +925,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
917
925
None => {
918
926
// For the time being, we ignore user-defined impls for builtin-bounds.
919
927
// (And unboxed candidates only apply to the Fn/FnMut/etc traits.)
920
- try!( self . assemble_unboxed_candidates ( obligation, & mut candidates) ) ;
928
+ try!( self . assemble_unboxed_closure_candidates ( obligation, & mut candidates) ) ;
929
+ try!( self . assemble_fn_pointer_candidates ( obligation, & mut candidates) ) ;
921
930
try!( self . assemble_candidates_from_impls ( obligation, & mut candidates) ) ;
922
931
}
923
932
}
@@ -968,20 +977,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
968
977
/// Note: the type parameters on an unboxed closure candidate are modeled as *output* type
969
978
/// parameters and hence do not affect whether this trait is a match or not. They will be
970
979
/// unified during the confirmation step.
971
- fn assemble_unboxed_candidates ( & mut self ,
972
- obligation : & Obligation < ' tcx > ,
973
- candidates : & mut CandidateSet < ' tcx > )
974
- -> Result < ( ) , SelectionError < ' tcx > >
980
+ fn assemble_unboxed_closure_candidates ( & mut self ,
981
+ obligation : & Obligation < ' tcx > ,
982
+ candidates : & mut CandidateSet < ' tcx > )
983
+ -> Result < ( ) , SelectionError < ' tcx > >
975
984
{
976
- let tcx = self . tcx ( ) ;
977
- let kind = if Some ( obligation. trait_ref . def_id ) == tcx. lang_items . fn_trait ( ) {
978
- ty:: FnUnboxedClosureKind
979
- } else if Some ( obligation. trait_ref . def_id ) == tcx. lang_items . fn_mut_trait ( ) {
980
- ty:: FnMutUnboxedClosureKind
981
- } else if Some ( obligation. trait_ref . def_id ) == tcx. lang_items . fn_once_trait ( ) {
982
- ty:: FnOnceUnboxedClosureKind
983
- } else {
984
- return Ok ( ( ) ) ; // not a fn trait, ignore
985
+ let kind = match self . fn_family_trait_kind ( obligation. trait_ref . def_id ) {
986
+ Some ( k) => k,
987
+ None => { return Ok ( ( ) ) ; }
985
988
} ;
986
989
987
990
let self_ty = self . infcx . shallow_resolve ( obligation. self_ty ( ) ) ;
@@ -1015,6 +1018,44 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1015
1018
Ok ( ( ) )
1016
1019
}
1017
1020
1021
+ /// Implement one of the `Fn()` family for a fn pointer.
1022
+ fn assemble_fn_pointer_candidates ( & mut self ,
1023
+ obligation : & Obligation < ' tcx > ,
1024
+ candidates : & mut CandidateSet < ' tcx > )
1025
+ -> Result < ( ) , SelectionError < ' tcx > >
1026
+ {
1027
+ // We provide a `Fn` impl for fn pointers. There is no need to provide
1028
+ // the other traits (e.g. `FnMut`) since those are provided by blanket
1029
+ // impls.
1030
+ if Some ( obligation. trait_ref . def_id ) != self . tcx ( ) . lang_items . fn_trait ( ) {
1031
+ return Ok ( ( ) ) ;
1032
+ }
1033
+
1034
+ let self_ty = self . infcx . shallow_resolve ( obligation. self_ty ( ) ) ;
1035
+ match self_ty. sty {
1036
+ ty:: ty_infer( ..) => {
1037
+ candidates. ambiguous = true ; // could wind up being a fn() type
1038
+ }
1039
+
1040
+ // provide an impl, but only for suitable `fn` pointers
1041
+ ty:: ty_bare_fn( ty:: BareFnTy {
1042
+ fn_style : ast:: NormalFn ,
1043
+ abi : abi:: Rust ,
1044
+ sig : ty:: FnSig {
1045
+ inputs : _,
1046
+ output : ty:: FnConverging ( _) ,
1047
+ variadic : false
1048
+ }
1049
+ } ) => {
1050
+ candidates. vec . push ( FnPointerCandidate ) ;
1051
+ }
1052
+
1053
+ _ => { }
1054
+ }
1055
+
1056
+ Ok ( ( ) )
1057
+ }
1058
+
1018
1059
/// Search for impls that might apply to `obligation`.
1019
1060
fn assemble_candidates_from_impls ( & mut self ,
1020
1061
obligation : & Obligation < ' tcx > ,
@@ -1551,6 +1592,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1551
1592
try!( self . confirm_unboxed_closure_candidate ( obligation, closure_def_id, & substs) ) ;
1552
1593
Ok ( VtableUnboxedClosure ( closure_def_id, substs) )
1553
1594
}
1595
+
1596
+ FnPointerCandidate => {
1597
+ let fn_type =
1598
+ try!( self . confirm_fn_pointer_candidate ( obligation) ) ;
1599
+ Ok ( VtableFnPointer ( fn_type) )
1600
+ }
1554
1601
}
1555
1602
}
1556
1603
@@ -1646,6 +1693,51 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1646
1693
nested : impl_obligations }
1647
1694
}
1648
1695
1696
+ fn confirm_fn_pointer_candidate ( & mut self ,
1697
+ obligation : & Obligation < ' tcx > )
1698
+ -> Result < ty:: Ty < ' tcx > , SelectionError < ' tcx > >
1699
+ {
1700
+ debug ! ( "confirm_fn_pointer_candidate({})" ,
1701
+ obligation. repr( self . tcx( ) ) ) ;
1702
+
1703
+ let self_ty = self . infcx . shallow_resolve ( obligation. self_ty ( ) ) ;
1704
+ let sig = match self_ty. sty {
1705
+ ty:: ty_bare_fn( ty:: BareFnTy {
1706
+ fn_style : ast:: NormalFn ,
1707
+ abi : abi:: Rust ,
1708
+ ref sig
1709
+ } ) => {
1710
+ sig
1711
+ }
1712
+ _ => {
1713
+ self . tcx ( ) . sess . span_bug (
1714
+ obligation. cause . span ,
1715
+ format ! ( "Fn pointer candidate for inappropriate self type: {}" ,
1716
+ self_ty. repr( self . tcx( ) ) ) . as_slice ( ) ) ;
1717
+ }
1718
+ } ;
1719
+
1720
+ let arguments_tuple = ty:: mk_tup ( self . tcx ( ) , sig. inputs . to_vec ( ) ) ;
1721
+ let output_type = sig. output . unwrap ( ) ;
1722
+ let substs =
1723
+ Substs :: new_trait (
1724
+ vec ! [ arguments_tuple, output_type] ,
1725
+ vec ! [ ] ,
1726
+ vec ! [ ] ,
1727
+ self_ty) ;
1728
+ let trait_ref = Rc :: new ( ty:: TraitRef {
1729
+ def_id : obligation. trait_ref . def_id ,
1730
+ substs : substs,
1731
+ } ) ;
1732
+
1733
+ let ( ) =
1734
+ try!( self . confirm ( obligation. cause ,
1735
+ obligation. trait_ref . clone ( ) ,
1736
+ trait_ref) ) ;
1737
+
1738
+ Ok ( self_ty)
1739
+ }
1740
+
1649
1741
fn confirm_unboxed_closure_candidate ( & mut self ,
1650
1742
obligation : & Obligation < ' tcx > ,
1651
1743
closure_def_id : ast:: DefId ,
@@ -1964,6 +2056,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1964
2056
util:: obligations_for_generics ( self . tcx ( ) , cause, recursion_depth,
1965
2057
& bounds, & impl_substs. types )
1966
2058
}
2059
+
2060
+ fn fn_family_trait_kind ( & self ,
2061
+ trait_def_id : ast:: DefId )
2062
+ -> Option < ty:: UnboxedClosureKind >
2063
+ {
2064
+ let tcx = self . tcx ( ) ;
2065
+ if Some ( trait_def_id) == tcx. lang_items . fn_trait ( ) {
2066
+ Some ( ty:: FnUnboxedClosureKind )
2067
+ } else if Some ( trait_def_id) == tcx. lang_items . fn_mut_trait ( ) {
2068
+ Some ( ty:: FnMutUnboxedClosureKind )
2069
+ } else if Some ( trait_def_id) == tcx. lang_items . fn_once_trait ( ) {
2070
+ Some ( ty:: FnOnceUnboxedClosureKind )
2071
+ } else {
2072
+ None
2073
+ }
2074
+ }
1967
2075
}
1968
2076
1969
2077
impl < ' tcx > Repr < ' tcx > for Candidate < ' tcx > {
@@ -1972,7 +2080,10 @@ impl<'tcx> Repr<'tcx> for Candidate<'tcx> {
1972
2080
ErrorCandidate => format ! ( "ErrorCandidate" ) ,
1973
2081
BuiltinCandidate ( b) => format ! ( "BuiltinCandidate({})" , b) ,
1974
2082
UnboxedClosureCandidate ( c, ref s) => {
1975
- format ! ( "MatchedUnboxedClosureCandidate({},{})" , c, s. repr( tcx) )
2083
+ format ! ( "UnboxedClosureCandidate({},{})" , c, s. repr( tcx) )
2084
+ }
2085
+ FnPointerCandidate => {
2086
+ format ! ( "FnPointerCandidate" )
1976
2087
}
1977
2088
ParamCandidate ( ref a) => format ! ( "ParamCandidate({})" , a. repr( tcx) ) ,
1978
2089
ImplCandidate ( a) => format ! ( "ImplCandidate({})" , a. repr( tcx) ) ,
0 commit comments