@@ -17,14 +17,24 @@ use rustc::hir::def_id::DefId;
17
17
use rustc:: infer:: { InferOk , InferResult } ;
18
18
use rustc:: infer:: LateBoundRegionConversionTime ;
19
19
use rustc:: infer:: type_variable:: TypeVariableOrigin ;
20
+ use rustc:: traits:: error_reporting:: ArgKind ;
20
21
use rustc:: ty:: { self , ToPolyTraitRef , Ty } ;
21
22
use rustc:: ty:: subst:: Substs ;
22
23
use rustc:: ty:: TypeFoldable ;
23
24
use std:: cmp;
24
25
use std:: iter;
25
26
use syntax:: abi:: Abi ;
27
+ use syntax:: codemap:: Span ;
26
28
use rustc:: hir;
27
29
30
+ /// What signature do we *expect* the closure to have from context?
31
+ #[ derive( Debug ) ]
32
+ struct ExpectedSig < ' tcx > {
33
+ /// Span that gave us this expectation, if we know that.
34
+ cause_span : Option < Span > ,
35
+ sig : ty:: FnSig < ' tcx > ,
36
+ }
37
+
28
38
struct ClosureSignatures < ' tcx > {
29
39
bound_sig : ty:: PolyFnSig < ' tcx > ,
30
40
liberated_sig : ty:: FnSig < ' tcx > ,
@@ -63,7 +73,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
63
73
decl : & ' gcx hir:: FnDecl ,
64
74
body : & ' gcx hir:: Body ,
65
75
gen : Option < hir:: GeneratorMovability > ,
66
- expected_sig : Option < ty :: FnSig < ' tcx > > ,
76
+ expected_sig : Option < ExpectedSig < ' tcx > > ,
67
77
) -> Ty < ' tcx > {
68
78
debug ! (
69
79
"check_closure(opt_kind={:?}, expected_sig={:?})" ,
@@ -160,10 +170,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
160
170
closure_type
161
171
}
162
172
173
+ /// Given the expected type, figures out what it can about this closure we
174
+ /// are about to type check:
163
175
fn deduce_expectations_from_expected_type (
164
176
& self ,
165
177
expected_ty : Ty < ' tcx > ,
166
- ) -> ( Option < ty :: FnSig < ' tcx > > , Option < ty:: ClosureKind > ) {
178
+ ) -> ( Option < ExpectedSig < ' tcx > > , Option < ty:: ClosureKind > ) {
167
179
debug ! (
168
180
"deduce_expectations_from_expected_type(expected_ty={:?})" ,
169
181
expected_ty
@@ -175,7 +187,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
175
187
. projection_bounds ( )
176
188
. filter_map ( |pb| {
177
189
let pb = pb. with_self_ty ( self . tcx , self . tcx . types . err ) ;
178
- self . deduce_sig_from_projection ( & pb)
190
+ self . deduce_sig_from_projection ( None , & pb)
179
191
} )
180
192
. next ( ) ;
181
193
let kind = object_type
@@ -184,15 +196,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
184
196
( sig, kind)
185
197
}
186
198
ty:: TyInfer ( ty:: TyVar ( vid) ) => self . deduce_expectations_from_obligations ( vid) ,
187
- ty:: TyFnPtr ( sig) => ( Some ( sig. skip_binder ( ) . clone ( ) ) , Some ( ty:: ClosureKind :: Fn ) ) ,
199
+ ty:: TyFnPtr ( sig) => {
200
+ let expected_sig = ExpectedSig {
201
+ cause_span : None ,
202
+ sig : sig. skip_binder ( ) . clone ( ) ,
203
+ } ;
204
+ ( Some ( expected_sig) , Some ( ty:: ClosureKind :: Fn ) )
205
+ }
188
206
_ => ( None , None ) ,
189
207
}
190
208
}
191
209
192
210
fn deduce_expectations_from_obligations (
193
211
& self ,
194
212
expected_vid : ty:: TyVid ,
195
- ) -> ( Option < ty :: FnSig < ' tcx > > , Option < ty:: ClosureKind > ) {
213
+ ) -> ( Option < ExpectedSig < ' tcx > > , Option < ty:: ClosureKind > ) {
196
214
let fulfillment_cx = self . fulfillment_cx . borrow ( ) ;
197
215
// Here `expected_ty` is known to be a type inference variable.
198
216
@@ -212,7 +230,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
212
230
ty:: Predicate :: Projection ( ref proj_predicate) => {
213
231
let trait_ref = proj_predicate. to_poly_trait_ref ( self . tcx ) ;
214
232
self . self_type_matches_expected_vid ( trait_ref, expected_vid)
215
- . and_then ( |_| self . deduce_sig_from_projection ( proj_predicate) )
233
+ . and_then ( |_| {
234
+ self . deduce_sig_from_projection (
235
+ Some ( obligation. cause . span ) ,
236
+ proj_predicate,
237
+ )
238
+ } )
216
239
}
217
240
_ => None ,
218
241
}
@@ -262,10 +285,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
262
285
263
286
/// Given a projection like "<F as Fn(X)>::Result == Y", we can deduce
264
287
/// everything we need to know about a closure.
288
+ ///
289
+ /// The `cause_span` should be the span that caused us to
290
+ /// have this expected signature, or `None` if we can't readily
291
+ /// know that.
265
292
fn deduce_sig_from_projection (
266
293
& self ,
294
+ cause_span : Option < Span > ,
267
295
projection : & ty:: PolyProjectionPredicate < ' tcx > ,
268
- ) -> Option < ty :: FnSig < ' tcx > > {
296
+ ) -> Option < ExpectedSig < ' tcx > > {
269
297
let tcx = self . tcx ;
270
298
271
299
debug ! ( "deduce_sig_from_projection({:?})" , projection) ;
@@ -297,16 +325,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
297
325
ret_param_ty
298
326
) ;
299
327
300
- let fn_sig = self . tcx . mk_fn_sig (
328
+ let sig = self . tcx . mk_fn_sig (
301
329
input_tys. cloned ( ) ,
302
330
ret_param_ty,
303
331
false ,
304
332
hir:: Unsafety :: Normal ,
305
333
Abi :: Rust ,
306
334
) ;
307
- debug ! ( "deduce_sig_from_projection: fn_sig {:?}" , fn_sig ) ;
335
+ debug ! ( "deduce_sig_from_projection: sig {:?}" , sig ) ;
308
336
309
- Some ( fn_sig )
337
+ Some ( ExpectedSig { cause_span , sig } )
310
338
}
311
339
312
340
fn self_type_matches_expected_vid (
@@ -330,7 +358,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
330
358
expr_def_id : DefId ,
331
359
decl : & hir:: FnDecl ,
332
360
body : & hir:: Body ,
333
- expected_sig : Option < ty :: FnSig < ' tcx > > ,
361
+ expected_sig : Option < ExpectedSig < ' tcx > > ,
334
362
) -> ClosureSignatures < ' tcx > {
335
363
if let Some ( e) = expected_sig {
336
364
self . sig_of_closure_with_expectation ( expr_def_id, decl, body, e)
@@ -406,7 +434,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
406
434
expr_def_id : DefId ,
407
435
decl : & hir:: FnDecl ,
408
436
body : & hir:: Body ,
409
- expected_sig : ty :: FnSig < ' tcx > ,
437
+ expected_sig : ExpectedSig < ' tcx > ,
410
438
) -> ClosureSignatures < ' tcx > {
411
439
debug ! (
412
440
"sig_of_closure_with_expectation(expected_sig={:?})" ,
@@ -416,20 +444,24 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
416
444
// Watch out for some surprises and just ignore the
417
445
// expectation if things don't see to match up with what we
418
446
// expect.
419
- if expected_sig. variadic != decl. variadic {
420
- return self . sig_of_closure_no_expectation ( expr_def_id, decl, body) ;
421
- } else if expected_sig. inputs_and_output . len ( ) != decl. inputs . len ( ) + 1 {
422
- // we could probably handle this case more gracefully
447
+ if expected_sig. sig . variadic != decl. variadic {
423
448
return self . sig_of_closure_no_expectation ( expr_def_id, decl, body) ;
449
+ } else if expected_sig. sig . inputs_and_output . len ( ) != decl. inputs . len ( ) + 1 {
450
+ return self . sig_of_closure_with_mismatched_number_of_arguments (
451
+ expr_def_id,
452
+ decl,
453
+ body,
454
+ expected_sig,
455
+ ) ;
424
456
}
425
457
426
458
// Create a `PolyFnSig`. Note the oddity that late bound
427
459
// regions appearing free in `expected_sig` are now bound up
428
460
// in this binder we are creating.
429
- assert ! ( !expected_sig. has_regions_escaping_depth( 1 ) ) ;
461
+ assert ! ( !expected_sig. sig . has_regions_escaping_depth( 1 ) ) ;
430
462
let bound_sig = ty:: Binder ( self . tcx . mk_fn_sig (
431
- expected_sig. inputs ( ) . iter ( ) . cloned ( ) ,
432
- expected_sig. output ( ) ,
463
+ expected_sig. sig . inputs ( ) . iter ( ) . cloned ( ) ,
464
+ expected_sig. sig . output ( ) ,
433
465
decl. variadic ,
434
466
hir:: Unsafety :: Normal ,
435
467
Abi :: RustCall ,
@@ -455,6 +487,35 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
455
487
closure_sigs
456
488
}
457
489
490
+ fn sig_of_closure_with_mismatched_number_of_arguments (
491
+ & self ,
492
+ expr_def_id : DefId ,
493
+ decl : & hir:: FnDecl ,
494
+ body : & hir:: Body ,
495
+ expected_sig : ExpectedSig < ' tcx > ,
496
+ ) -> ClosureSignatures < ' tcx > {
497
+ let expr_map_node = self . tcx . hir . get_if_local ( expr_def_id) . unwrap ( ) ;
498
+ let expected_args: Vec < _ > = expected_sig
499
+ . sig
500
+ . inputs ( )
501
+ . iter ( )
502
+ . map ( |ty| ArgKind :: from_expected_ty ( ty) )
503
+ . collect ( ) ;
504
+ let ( closure_span, found_args) = self . get_fn_like_arguments ( expr_map_node) ;
505
+ let expected_span = expected_sig. cause_span . unwrap_or ( closure_span) ;
506
+ self . report_arg_count_mismatch (
507
+ expected_span,
508
+ Some ( closure_span) ,
509
+ expected_args,
510
+ found_args,
511
+ true ,
512
+ ) . emit ( ) ;
513
+
514
+ let error_sig = self . error_sig_of_closure ( decl) ;
515
+
516
+ self . closure_sigs ( expr_def_id, body, error_sig)
517
+ }
518
+
458
519
/// Enforce the user's types against the expectation. See
459
520
/// `sig_of_closure_with_expectation` for details on the overall
460
521
/// strategy.
@@ -560,6 +621,38 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
560
621
result
561
622
}
562
623
624
+ /// Converts the types that the user supplied, in case that doing
625
+ /// so should yield an error, but returns back a signature where
626
+ /// all parameters are of type `TyErr`.
627
+ fn error_sig_of_closure ( & self , decl : & hir:: FnDecl ) -> ty:: PolyFnSig < ' tcx > {
628
+ let astconv: & AstConv = self ;
629
+
630
+ let supplied_arguments = decl. inputs . iter ( ) . map ( |a| {
631
+ // Convert the types that the user supplied (if any), but ignore them.
632
+ astconv. ast_ty_to_ty ( a) ;
633
+ self . tcx . types . err
634
+ } ) ;
635
+
636
+ match decl. output {
637
+ hir:: Return ( ref output) => {
638
+ astconv. ast_ty_to_ty ( & output) ;
639
+ }
640
+ hir:: DefaultReturn ( _) => { }
641
+ }
642
+
643
+ let result = ty:: Binder ( self . tcx . mk_fn_sig (
644
+ supplied_arguments,
645
+ self . tcx . types . err ,
646
+ decl. variadic ,
647
+ hir:: Unsafety :: Normal ,
648
+ Abi :: RustCall ,
649
+ ) ) ;
650
+
651
+ debug ! ( "supplied_sig_of_closure: result={:?}" , result) ;
652
+
653
+ result
654
+ }
655
+
563
656
fn closure_sigs (
564
657
& self ,
565
658
expr_def_id : DefId ,
0 commit comments