@@ -127,136 +127,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
127127
128128 let expected_arg_count = formal_input_tys. len ( ) ;
129129
130- let param_count_error = |expected_count : usize ,
131- arg_count : usize ,
132- error_code : & str ,
133- c_variadic : bool ,
134- sugg_unit : bool | {
135- let ( span, start_span, args, ctor_of) = match & call_expr. kind {
136- hir:: ExprKind :: Call (
137- hir:: Expr {
138- span,
139- kind :
140- hir:: ExprKind :: Path ( hir:: QPath :: Resolved (
141- _,
142- hir:: Path { res : Res :: Def ( DefKind :: Ctor ( of, _) , _) , .. } ,
143- ) ) ,
144- ..
145- } ,
146- args,
147- ) => ( * span, * span, & args[ ..] , Some ( of) ) ,
148- hir:: ExprKind :: Call ( hir:: Expr { span, .. } , args) => {
149- ( * span, * span, & args[ ..] , None )
150- }
151- hir:: ExprKind :: MethodCall ( path_segment, args, _) => (
152- path_segment. ident . span ,
153- // `sp` doesn't point at the whole `foo.bar()`, only at `bar`.
154- path_segment
155- . args
156- . and_then ( |args| args. args . iter ( ) . last ( ) )
157- // Account for `foo.bar::<T>()`.
158- . map ( |arg| {
159- // Skip the closing `>`.
160- tcx. sess
161- . source_map ( )
162- . next_point ( tcx. sess . source_map ( ) . next_point ( arg. span ( ) ) )
163- } )
164- . unwrap_or ( path_segment. ident . span ) ,
165- & args[ 1 ..] , // Skip the receiver.
166- None , // methods are never ctors
167- ) ,
168- k => span_bug ! ( call_span, "checking argument types on a non-call: `{:?}`" , k) ,
169- } ;
170- let arg_spans = if provided_args. is_empty ( ) {
171- // foo()
172- // ^^^-- supplied 0 arguments
173- // |
174- // expected 2 arguments
175- vec ! [ tcx. sess. source_map( ) . next_point( start_span) . with_hi( call_span. hi( ) ) ]
176- } else {
177- // foo(1, 2, 3)
178- // ^^^ - - - supplied 3 arguments
179- // |
180- // expected 2 arguments
181- args. iter ( ) . map ( |arg| arg. span ) . collect :: < Vec < Span > > ( )
182- } ;
183-
184- let mut err = tcx. sess . struct_span_err_with_code (
185- span,
186- & format ! (
187- "this {} takes {}{} but {} {} supplied" ,
188- match ctor_of {
189- Some ( CtorOf :: Struct ) => "struct" ,
190- Some ( CtorOf :: Variant ) => "enum variant" ,
191- None => "function" ,
192- } ,
193- if c_variadic { "at least " } else { "" } ,
194- potentially_plural_count( expected_count, "argument" ) ,
195- potentially_plural_count( arg_count, "argument" ) ,
196- if arg_count == 1 { "was" } else { "were" }
197- ) ,
198- DiagnosticId :: Error ( error_code. to_owned ( ) ) ,
199- ) ;
200- let label = format ! ( "supplied {}" , potentially_plural_count( arg_count, "argument" ) ) ;
201- for ( i, span) in arg_spans. into_iter ( ) . enumerate ( ) {
202- err. span_label (
203- span,
204- if arg_count == 0 || i + 1 == arg_count { & label } else { "" } ,
205- ) ;
206- }
207-
208- if let Some ( def_id) = fn_def_id {
209- if let Some ( def_span) = tcx. def_ident_span ( def_id) {
210- let mut spans: MultiSpan = def_span. into ( ) ;
211-
212- let params = tcx
213- . hir ( )
214- . get_if_local ( def_id)
215- . and_then ( |node| node. body_id ( ) )
216- . into_iter ( )
217- . map ( |id| tcx. hir ( ) . body ( id) . params )
218- . flatten ( ) ;
219-
220- for param in params {
221- spans. push_span_label ( param. span , String :: new ( ) ) ;
222- }
223-
224- let def_kind = tcx. def_kind ( def_id) ;
225- err. span_note ( spans, & format ! ( "{} defined here" , def_kind. descr( def_id) ) ) ;
226- }
227- }
228-
229- if sugg_unit {
230- let sugg_span = tcx. sess . source_map ( ) . end_point ( call_expr. span ) ;
231- // remove closing `)` from the span
232- let sugg_span = sugg_span. shrink_to_lo ( ) ;
233- err. span_suggestion (
234- sugg_span,
235- "expected the unit value `()`; create it with empty parentheses" ,
236- String :: from ( "()" ) ,
237- Applicability :: MachineApplicable ,
238- ) ;
239- } else {
240- err. span_label (
241- span,
242- format ! (
243- "expected {}{}" ,
244- if c_variadic { "at least " } else { "" } ,
245- potentially_plural_count( expected_count, "argument" )
246- ) ,
247- ) ;
248- }
249- err. emit ( ) ;
250- } ;
130+ // expected_count, arg_count, error_code, sugg_unit
131+ let mut error: Option < ( usize , usize , & str , bool ) > = None ;
251132
133+ // If the arguments should be wrapped in a tuple (ex: closures), unwrap them here
252134 let ( formal_input_tys, expected_input_tys) = if tuple_arguments == TupleArguments {
253135 let tuple_type = self . structurally_resolved_type ( call_span, formal_input_tys[ 0 ] ) ;
254136 match tuple_type. kind ( ) {
255- ty:: Tuple ( arg_types) if arg_types. len ( ) != provided_args. len ( ) => {
256- param_count_error ( arg_types. len ( ) , provided_args. len ( ) , "E0057" , false , false ) ;
257- ( self . err_args ( provided_args. len ( ) ) , vec ! [ ] )
258- }
137+ // We expected a tuple and got a tuple
259138 ty:: Tuple ( arg_types) => {
139+ // Argument length differs
140+ if arg_types. len ( ) != provided_args. len ( ) {
141+ error = Some ( ( arg_types. len ( ) , provided_args. len ( ) , "E0057" , false ) ) ;
142+ }
260143 let expected_input_tys = match expected_input_tys. get ( 0 ) {
261144 Some ( & ty) => match ty. kind ( ) {
262145 ty:: Tuple ( ref tys) => tys. iter ( ) . map ( |k| k. expect_ty ( ) ) . collect ( ) ,
@@ -267,6 +150,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
267150 ( arg_types. iter ( ) . map ( |k| k. expect_ty ( ) ) . collect ( ) , expected_input_tys)
268151 }
269152 _ => {
153+ // Otherwise, there's a mismatch, so clear out what we're expecting, and set
154+ // our input typs to err_args so we don't blow up the error messages
270155 struct_span_err ! (
271156 tcx. sess,
272157 call_span,
@@ -284,7 +169,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
284169 if supplied_arg_count >= expected_arg_count {
285170 ( formal_input_tys. to_vec ( ) , expected_input_tys)
286171 } else {
287- param_count_error ( expected_arg_count, supplied_arg_count, "E0060" , true , false ) ;
172+ error = Some ( ( expected_arg_count, supplied_arg_count, "E0060" , false ) ) ;
288173 ( self . err_args ( supplied_arg_count) , vec ! [ ] )
289174 }
290175 } else {
@@ -296,8 +181,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
296181 } else {
297182 false
298183 } ;
299- param_count_error ( expected_arg_count, supplied_arg_count, "E0061" , false , sugg_unit) ;
300-
184+ error = Some ( ( expected_arg_count, supplied_arg_count, "E0061" , sugg_unit) ) ;
301185 ( self . err_args ( supplied_arg_count) , vec ! [ ] )
302186 } ;
303187
@@ -348,7 +232,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
348232 // argument and not the call. This is otherwise redundant with the `demand_coerce`
349233 // call immediately after, but it lets us customize the span pointed to in the
350234 // fulfillment error to be more accurate.
351- let _ =
235+ let coerced_ty =
352236 self . resolve_vars_with_obligations_and_mutate_fulfillment ( coerced_ty, |errors| {
353237 self . point_at_type_arg_instead_of_call_if_possible ( errors, call_expr) ;
354238 self . point_at_arg_instead_of_call_if_possible (
@@ -360,6 +244,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
360244 ) ;
361245 } ) ;
362246
247+ final_arg_types[ idx] = Some ( ( checked_ty, coerced_ty) ) ;
248+
363249 // We're processing function arguments so we definitely want to use
364250 // two-phase borrows.
365251 self . demand_coerce ( & provided_arg, checked_ty, coerced_ty, None , AllowTwoPhase :: Yes ) ;
@@ -418,6 +304,123 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
418304 }
419305 }
420306
307+ // If there was an error in parameter count, emit that here
308+ if let Some ( ( expected_count, arg_count, err_code, sugg_unit) ) = error {
309+ let ( span, start_span, args, ctor_of) = match & call_expr. kind {
310+ hir:: ExprKind :: Call (
311+ hir:: Expr {
312+ span,
313+ kind :
314+ hir:: ExprKind :: Path ( hir:: QPath :: Resolved (
315+ _,
316+ hir:: Path { res : Res :: Def ( DefKind :: Ctor ( of, _) , _) , .. } ,
317+ ) ) ,
318+ ..
319+ } ,
320+ args,
321+ ) => ( * span, * span, & args[ ..] , Some ( of) ) ,
322+ hir:: ExprKind :: Call ( hir:: Expr { span, .. } , args) => {
323+ ( * span, * span, & args[ ..] , None )
324+ }
325+ hir:: ExprKind :: MethodCall ( path_segment, args, _) => (
326+ path_segment. ident . span ,
327+ // `sp` doesn't point at the whole `foo.bar()`, only at `bar`.
328+ path_segment
329+ . args
330+ . and_then ( |args| args. args . iter ( ) . last ( ) )
331+ // Account for `foo.bar::<T>()`.
332+ . map ( |arg| {
333+ // Skip the closing `>`.
334+ tcx. sess
335+ . source_map ( )
336+ . next_point ( tcx. sess . source_map ( ) . next_point ( arg. span ( ) ) )
337+ } )
338+ . unwrap_or ( path_segment. ident . span ) ,
339+ & args[ 1 ..] , // Skip the receiver.
340+ None , // methods are never ctors
341+ ) ,
342+ k => span_bug ! ( call_span, "checking argument types on a non-call: `{:?}`" , k) ,
343+ } ;
344+ let arg_spans = if provided_args. is_empty ( ) {
345+ // foo()
346+ // ^^^-- supplied 0 arguments
347+ // |
348+ // expected 2 arguments
349+ vec ! [ tcx. sess. source_map( ) . next_point( start_span) . with_hi( call_span. hi( ) ) ]
350+ } else {
351+ // foo(1, 2, 3)
352+ // ^^^ - - - supplied 3 arguments
353+ // |
354+ // expected 2 arguments
355+ args. iter ( ) . map ( |arg| arg. span ) . collect :: < Vec < Span > > ( )
356+ } ;
357+ let call_name = match ctor_of {
358+ Some ( CtorOf :: Struct ) => "struct" ,
359+ Some ( CtorOf :: Variant ) => "enum variant" ,
360+ None => "function" ,
361+ } ;
362+ let mut err = tcx. sess . struct_span_err_with_code (
363+ span,
364+ & format ! (
365+ "this {} takes {}{} but {} {} supplied" ,
366+ call_name,
367+ if c_variadic { "at least " } else { "" } ,
368+ potentially_plural_count( expected_count, "argument" ) ,
369+ potentially_plural_count( arg_count, "argument" ) ,
370+ if arg_count == 1 { "was" } else { "were" }
371+ ) ,
372+ DiagnosticId :: Error ( err_code. to_owned ( ) ) ,
373+ ) ;
374+ let label = format ! ( "supplied {}" , potentially_plural_count( arg_count, "argument" ) ) ;
375+ for ( i, span) in arg_spans. into_iter ( ) . enumerate ( ) {
376+ err. span_label (
377+ span,
378+ if arg_count == 0 || i + 1 == arg_count { & label } else { "" } ,
379+ ) ;
380+ }
381+ if let Some ( def_id) = fn_def_id {
382+ if let Some ( def_span) = tcx. def_ident_span ( def_id) {
383+ let mut spans: MultiSpan = def_span. into ( ) ;
384+
385+ let params = tcx
386+ . hir ( )
387+ . get_if_local ( def_id)
388+ . and_then ( |node| node. body_id ( ) )
389+ . into_iter ( )
390+ . map ( |id| tcx. hir ( ) . body ( id) . params )
391+ . flatten ( ) ;
392+
393+ for param in params {
394+ spans. push_span_label ( param. span , String :: new ( ) ) ;
395+ }
396+
397+ let def_kind = tcx. def_kind ( def_id) ;
398+ err. span_note ( spans, & format ! ( "{} defined here" , def_kind. descr( def_id) ) ) ;
399+ }
400+ }
401+ if sugg_unit {
402+ let sugg_span = tcx. sess . source_map ( ) . end_point ( call_expr. span ) ;
403+ // remove closing `)` from the span
404+ let sugg_span = sugg_span. shrink_to_lo ( ) ;
405+ err. span_suggestion (
406+ sugg_span,
407+ "expected the unit value `()`; create it with empty parentheses" ,
408+ String :: from ( "()" ) ,
409+ Applicability :: MachineApplicable ,
410+ ) ;
411+ } else {
412+ err. span_label (
413+ span,
414+ format ! (
415+ "expected {}{}" ,
416+ if c_variadic { "at least " } else { "" } ,
417+ potentially_plural_count( expected_count, "argument" )
418+ ) ,
419+ ) ;
420+ }
421+ err. emit ( ) ;
422+ }
423+
421424 // We also need to make sure we at least write the ty of the other
422425 // arguments which we skipped above.
423426 if c_variadic {
0 commit comments