@@ -17,14 +17,24 @@ use rustc::hir::def_id::DefId;
1717use rustc:: infer:: { InferOk , InferResult } ;
1818use rustc:: infer:: LateBoundRegionConversionTime ;
1919use rustc:: infer:: type_variable:: TypeVariableOrigin ;
20+ use rustc:: traits:: error_reporting:: ArgKind ;
2021use rustc:: ty:: { self , ToPolyTraitRef , Ty } ;
2122use rustc:: ty:: subst:: Substs ;
2223use rustc:: ty:: TypeFoldable ;
2324use std:: cmp;
2425use std:: iter;
2526use syntax:: abi:: Abi ;
27+ use syntax:: codemap:: Span ;
2628use rustc:: hir;
2729
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+
2838struct ClosureSignatures < ' tcx > {
2939 bound_sig : ty:: PolyFnSig < ' tcx > ,
3040 liberated_sig : ty:: FnSig < ' tcx > ,
@@ -63,7 +73,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
6373 decl : & ' gcx hir:: FnDecl ,
6474 body : & ' gcx hir:: Body ,
6575 gen : Option < hir:: GeneratorMovability > ,
66- expected_sig : Option < ty :: FnSig < ' tcx > > ,
76+ expected_sig : Option < ExpectedSig < ' tcx > > ,
6777 ) -> Ty < ' tcx > {
6878 debug ! (
6979 "check_closure(opt_kind={:?}, expected_sig={:?})" ,
@@ -160,10 +170,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
160170 closure_type
161171 }
162172
173+ /// Given the expected type, figures out what it can about this closure we
174+ /// are about to type check:
163175 fn deduce_expectations_from_expected_type (
164176 & self ,
165177 expected_ty : Ty < ' tcx > ,
166- ) -> ( Option < ty :: FnSig < ' tcx > > , Option < ty:: ClosureKind > ) {
178+ ) -> ( Option < ExpectedSig < ' tcx > > , Option < ty:: ClosureKind > ) {
167179 debug ! (
168180 "deduce_expectations_from_expected_type(expected_ty={:?})" ,
169181 expected_ty
@@ -175,7 +187,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
175187 . projection_bounds ( )
176188 . filter_map ( |pb| {
177189 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)
179191 } )
180192 . next ( ) ;
181193 let kind = object_type
@@ -184,15 +196,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
184196 ( sig, kind)
185197 }
186198 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+ }
188206 _ => ( None , None ) ,
189207 }
190208 }
191209
192210 fn deduce_expectations_from_obligations (
193211 & self ,
194212 expected_vid : ty:: TyVid ,
195- ) -> ( Option < ty :: FnSig < ' tcx > > , Option < ty:: ClosureKind > ) {
213+ ) -> ( Option < ExpectedSig < ' tcx > > , Option < ty:: ClosureKind > ) {
196214 let fulfillment_cx = self . fulfillment_cx . borrow ( ) ;
197215 // Here `expected_ty` is known to be a type inference variable.
198216
@@ -212,7 +230,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
212230 ty:: Predicate :: Projection ( ref proj_predicate) => {
213231 let trait_ref = proj_predicate. to_poly_trait_ref ( self . tcx ) ;
214232 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+ } )
216239 }
217240 _ => None ,
218241 }
@@ -262,10 +285,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
262285
263286 /// Given a projection like "<F as Fn(X)>::Result == Y", we can deduce
264287 /// 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.
265292 fn deduce_sig_from_projection (
266293 & self ,
294+ cause_span : Option < Span > ,
267295 projection : & ty:: PolyProjectionPredicate < ' tcx > ,
268- ) -> Option < ty :: FnSig < ' tcx > > {
296+ ) -> Option < ExpectedSig < ' tcx > > {
269297 let tcx = self . tcx ;
270298
271299 debug ! ( "deduce_sig_from_projection({:?})" , projection) ;
@@ -297,16 +325,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
297325 ret_param_ty
298326 ) ;
299327
300- let fn_sig = self . tcx . mk_fn_sig (
328+ let sig = self . tcx . mk_fn_sig (
301329 input_tys. cloned ( ) ,
302330 ret_param_ty,
303331 false ,
304332 hir:: Unsafety :: Normal ,
305333 Abi :: Rust ,
306334 ) ;
307- debug ! ( "deduce_sig_from_projection: fn_sig {:?}" , fn_sig ) ;
335+ debug ! ( "deduce_sig_from_projection: sig {:?}" , sig ) ;
308336
309- Some ( fn_sig )
337+ Some ( ExpectedSig { cause_span , sig } )
310338 }
311339
312340 fn self_type_matches_expected_vid (
@@ -330,7 +358,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
330358 expr_def_id : DefId ,
331359 decl : & hir:: FnDecl ,
332360 body : & hir:: Body ,
333- expected_sig : Option < ty :: FnSig < ' tcx > > ,
361+ expected_sig : Option < ExpectedSig < ' tcx > > ,
334362 ) -> ClosureSignatures < ' tcx > {
335363 if let Some ( e) = expected_sig {
336364 self . sig_of_closure_with_expectation ( expr_def_id, decl, body, e)
@@ -406,7 +434,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
406434 expr_def_id : DefId ,
407435 decl : & hir:: FnDecl ,
408436 body : & hir:: Body ,
409- expected_sig : ty :: FnSig < ' tcx > ,
437+ expected_sig : ExpectedSig < ' tcx > ,
410438 ) -> ClosureSignatures < ' tcx > {
411439 debug ! (
412440 "sig_of_closure_with_expectation(expected_sig={:?})" ,
@@ -416,20 +444,24 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
416444 // Watch out for some surprises and just ignore the
417445 // expectation if things don't see to match up with what we
418446 // 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 {
423448 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+ ) ;
424456 }
425457
426458 // Create a `PolyFnSig`. Note the oddity that late bound
427459 // regions appearing free in `expected_sig` are now bound up
428460 // 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 ) ) ;
430462 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 ( ) ,
433465 decl. variadic ,
434466 hir:: Unsafety :: Normal ,
435467 Abi :: RustCall ,
@@ -455,6 +487,35 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
455487 closure_sigs
456488 }
457489
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+
458519 /// Enforce the user's types against the expectation. See
459520 /// `sig_of_closure_with_expectation` for details on the overall
460521 /// strategy.
@@ -560,6 +621,38 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
560621 result
561622 }
562623
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+
563656 fn closure_sigs (
564657 & self ,
565658 expr_def_id : DefId ,
0 commit comments