2
2
3
3
use std:: iter;
4
4
5
+ use crate :: traits:: TupleArgumentsFlag ;
6
+
5
7
use super :: assembly:: { self , AssemblyCtxt } ;
6
8
use super :: { CanonicalGoal , Certainty , EvalCtxt , Goal , QueryResult } ;
7
9
use rustc_hir:: def_id:: DefId ;
10
+ use rustc_hir:: Unsafety ;
8
11
use rustc_infer:: infer:: { InferCtxt , InferOk , LateBoundRegionConversionTime } ;
9
12
use rustc_infer:: traits:: query:: NoSolution ;
10
13
use rustc_infer:: traits:: util:: supertraits;
@@ -13,6 +16,7 @@ use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
13
16
use rustc_middle:: ty:: TraitPredicate ;
14
17
use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
15
18
use rustc_span:: DUMMY_SP ;
19
+ use rustc_target:: spec:: abi:: Abi ;
16
20
17
21
#[ allow( dead_code) ] // FIXME: implement and use all variants.
18
22
#[ derive( Debug , Clone , Copy ) ]
@@ -53,6 +57,9 @@ pub(super) enum CandidateSource {
53
57
/// at the constituent types of the `self_ty` to check whether the auto trait
54
58
/// is implemented for those.
55
59
AutoImpl ,
60
+ /// An automatic impl for `Fn`/`FnMut`/`FnOnce` for fn pointers, fn items,
61
+ /// and closures.
62
+ Fn ,
56
63
}
57
64
58
65
type Candidate < ' tcx > = assembly:: Candidate < ' tcx , TraitPredicate < ' tcx > > ;
@@ -214,6 +221,39 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
214
221
acx. try_insert_candidate ( CandidateSource :: AutoImpl , certainty) ;
215
222
} )
216
223
}
224
+
225
+ fn consider_fn_candidate (
226
+ acx : & mut AssemblyCtxt < ' _ , ' tcx , Self > ,
227
+ goal : Goal < ' tcx , Self > ,
228
+ bound_sig : ty:: PolyFnSig < ' tcx > ,
229
+ tuple_args_flag : TupleArgumentsFlag ,
230
+ ) {
231
+ if bound_sig. unsafety ( ) != Unsafety :: Normal || bound_sig. c_variadic ( ) {
232
+ return ;
233
+ }
234
+
235
+ // Binder skipped here (*)
236
+ let ( arguments_tuple, expected_abi) = match tuple_args_flag {
237
+ TupleArgumentsFlag :: No => ( bound_sig. skip_binder ( ) . inputs ( ) [ 0 ] , Abi :: RustCall ) ,
238
+ TupleArgumentsFlag :: Yes => {
239
+ ( acx. cx . tcx . intern_tup ( bound_sig. skip_binder ( ) . inputs ( ) ) , Abi :: Rust )
240
+ }
241
+ } ;
242
+ if expected_abi != bound_sig. abi ( ) {
243
+ return ;
244
+ }
245
+ // (*) Rebound here
246
+ let found_trait_ref = bound_sig. rebind (
247
+ acx. cx
248
+ . tcx
249
+ . mk_trait_ref ( goal. predicate . def_id ( ) , [ goal. predicate . self_ty ( ) , arguments_tuple] ) ,
250
+ ) ;
251
+
252
+ acx. infcx . probe ( |_| {
253
+ // FIXME: This needs to validate that `fn() -> TY` has `TY: Sized`.
254
+ match_poly_trait_ref_against_goal ( acx, goal, found_trait_ref, CandidateSource :: Fn ) ;
255
+ } )
256
+ }
217
257
}
218
258
219
259
fn match_poly_trait_ref_against_goal < ' tcx > (
@@ -379,7 +419,8 @@ impl<'tcx> EvalCtxt<'tcx> {
379
419
| ( CandidateSource :: ObjectBound ( _) , _)
380
420
| ( CandidateSource :: ObjectAutoBound , _)
381
421
| ( CandidateSource :: Builtin , _)
382
- | ( CandidateSource :: AutoImpl , _) => unimplemented ! ( ) ,
422
+ | ( CandidateSource :: AutoImpl , _)
423
+ | ( CandidateSource :: Fn , _) => unimplemented ! ( ) ,
383
424
}
384
425
}
385
426
0 commit comments