@@ -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,42 @@ 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 (but not e.g. `FnMut`).
1028
+ if Some ( obligation. trait_ref . def_id ) != self . tcx ( ) . lang_items . fn_trait ( ) {
1029
+ return Ok ( ( ) ) ;
1030
+ }
1031
+
1032
+ let self_ty = self . infcx . shallow_resolve ( obligation. self_ty ( ) ) ;
1033
+ match self_ty. sty {
1034
+ ty:: ty_infer( ..) => {
1035
+ candidates. ambiguous = true ; // could wind up being a fn() type
1036
+ }
1037
+
1038
+ // provide an impl, but only for suitable `fn` pointers
1039
+ ty:: ty_bare_fn( ty:: BareFnTy {
1040
+ fn_style : ast:: NormalFn ,
1041
+ abi : abi:: Rust ,
1042
+ sig : ty:: FnSig {
1043
+ inputs : _,
1044
+ output : ty:: FnConverging ( _) ,
1045
+ variadic : false
1046
+ }
1047
+ } ) => {
1048
+ candidates. vec . push ( FnPointerCandidate ) ;
1049
+ }
1050
+
1051
+ _ => { }
1052
+ }
1053
+
1054
+ Ok ( ( ) )
1055
+ }
1056
+
1018
1057
/// Search for impls that might apply to `obligation`.
1019
1058
fn assemble_candidates_from_impls ( & mut self ,
1020
1059
obligation : & Obligation < ' tcx > ,
@@ -1551,6 +1590,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1551
1590
try!( self . confirm_unboxed_closure_candidate ( obligation, closure_def_id, & substs) ) ;
1552
1591
Ok ( VtableUnboxedClosure ( closure_def_id, substs) )
1553
1592
}
1593
+
1594
+ FnPointerCandidate => {
1595
+ let fn_type =
1596
+ try!( self . confirm_fn_pointer_candidate ( obligation) ) ;
1597
+ Ok ( VtableFnPointer ( fn_type) )
1598
+ }
1554
1599
}
1555
1600
}
1556
1601
@@ -1646,6 +1691,51 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1646
1691
nested : impl_obligations }
1647
1692
}
1648
1693
1694
+ fn confirm_fn_pointer_candidate ( & mut self ,
1695
+ obligation : & Obligation < ' tcx > )
1696
+ -> Result < ty:: Ty < ' tcx > , SelectionError < ' tcx > >
1697
+ {
1698
+ debug ! ( "confirm_fn_pointer_candidate({})" ,
1699
+ obligation. repr( self . tcx( ) ) ) ;
1700
+
1701
+ let self_ty = self . infcx . shallow_resolve ( obligation. self_ty ( ) ) ;
1702
+ let sig = match self_ty. sty {
1703
+ ty:: ty_bare_fn( ty:: BareFnTy {
1704
+ fn_style : ast:: NormalFn ,
1705
+ abi : abi:: Rust ,
1706
+ ref sig
1707
+ } ) => {
1708
+ ( * sig) . clone ( )
1709
+ }
1710
+ _ => {
1711
+ self . tcx ( ) . sess . span_bug (
1712
+ obligation. cause . span ,
1713
+ format ! ( "Fn pointer candidate for inappropriate self type: {}" ,
1714
+ self_ty. repr( self . tcx( ) ) ) . as_slice ( ) ) ;
1715
+ }
1716
+ } ;
1717
+
1718
+ let arguments_tuple = ty:: mk_tup ( self . tcx ( ) , sig. inputs . to_vec ( ) ) ;
1719
+ let output_type = sig. output . unwrap ( ) ;
1720
+ let substs =
1721
+ Substs :: new_trait (
1722
+ vec ! [ arguments_tuple, output_type] ,
1723
+ vec ! [ ] ,
1724
+ vec ! [ ] ,
1725
+ self_ty) ;
1726
+ let trait_ref = Rc :: new ( ty:: TraitRef {
1727
+ def_id : obligation. trait_ref . def_id ,
1728
+ substs : substs,
1729
+ } ) ;
1730
+
1731
+ let ( ) =
1732
+ try!( self . confirm ( obligation. cause ,
1733
+ obligation. trait_ref . clone ( ) ,
1734
+ trait_ref) ) ;
1735
+
1736
+ Ok ( self_ty)
1737
+ }
1738
+
1649
1739
fn confirm_unboxed_closure_candidate ( & mut self ,
1650
1740
obligation : & Obligation < ' tcx > ,
1651
1741
closure_def_id : ast:: DefId ,
@@ -1964,6 +2054,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1964
2054
util:: obligations_for_generics ( self . tcx ( ) , cause, recursion_depth,
1965
2055
& bounds, & impl_substs. types )
1966
2056
}
2057
+
2058
+ fn fn_family_trait_kind ( & self ,
2059
+ trait_def_id : ast:: DefId )
2060
+ -> Option < ty:: UnboxedClosureKind >
2061
+ {
2062
+ let tcx = self . tcx ( ) ;
2063
+ if Some ( trait_def_id) == tcx. lang_items . fn_trait ( ) {
2064
+ Some ( ty:: FnUnboxedClosureKind )
2065
+ } else if Some ( trait_def_id) == tcx. lang_items . fn_mut_trait ( ) {
2066
+ Some ( ty:: FnMutUnboxedClosureKind )
2067
+ } else if Some ( trait_def_id) == tcx. lang_items . fn_once_trait ( ) {
2068
+ Some ( ty:: FnOnceUnboxedClosureKind )
2069
+ } else {
2070
+ None
2071
+ }
2072
+ }
1967
2073
}
1968
2074
1969
2075
impl < ' tcx > Repr < ' tcx > for Candidate < ' tcx > {
@@ -1972,7 +2078,10 @@ impl<'tcx> Repr<'tcx> for Candidate<'tcx> {
1972
2078
ErrorCandidate => format ! ( "ErrorCandidate" ) ,
1973
2079
BuiltinCandidate ( b) => format ! ( "BuiltinCandidate({})" , b) ,
1974
2080
UnboxedClosureCandidate ( c, ref s) => {
1975
- format ! ( "MatchedUnboxedClosureCandidate({},{})" , c, s. repr( tcx) )
2081
+ format ! ( "UnboxedClosureCandidate({},{})" , c, s. repr( tcx) )
2082
+ }
2083
+ FnPointerCandidate => {
2084
+ format ! ( "FnPointerCandidate" )
1976
2085
}
1977
2086
ParamCandidate ( ref a) => format ! ( "ParamCandidate({})" , a. repr( tcx) ) ,
1978
2087
ImplCandidate ( a) => format ! ( "ImplCandidate({})" , a. repr( tcx) ) ,
0 commit comments