@@ -394,140 +394,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
394
394
}
395
395
ty:: FnPtr ( sig) => ( sig, None ) ,
396
396
_ => {
397
- let mut unit_variant = None ;
398
- if let hir:: ExprKind :: Path ( qpath) = & callee_expr. kind
399
- && let Res :: Def ( def:: DefKind :: Ctor ( kind, def:: CtorKind :: Const ) , _)
400
- = self . typeck_results . borrow ( ) . qpath_res ( qpath, callee_expr. hir_id )
401
- // Only suggest removing parens if there are no arguments
402
- && arg_exprs. is_empty ( )
403
- {
404
- let descr = match kind {
405
- def:: CtorOf :: Struct => "struct" ,
406
- def:: CtorOf :: Variant => "enum variant" ,
407
- } ;
408
- let removal_span =
409
- callee_expr. span . shrink_to_hi ( ) . to ( call_expr. span . shrink_to_hi ( ) ) ;
410
- unit_variant =
411
- Some ( ( removal_span, descr, rustc_hir_pretty:: qpath_to_string ( qpath) ) ) ;
412
- }
413
-
414
- let callee_ty = self . resolve_vars_if_possible ( callee_ty) ;
415
- let mut err = type_error_struct ! (
416
- self . tcx. sess,
417
- callee_expr. span,
418
- callee_ty,
419
- E0618 ,
420
- "expected function, found {}" ,
421
- match & unit_variant {
422
- Some ( ( _, kind, path) ) => format!( "{kind} `{path}`" ) ,
423
- None => format!( "`{callee_ty}`" ) ,
424
- }
425
- ) ;
426
-
427
- self . identify_bad_closure_def_and_call (
428
- & mut err,
429
- call_expr. hir_id ,
430
- & callee_expr. kind ,
431
- callee_expr. span ,
432
- ) ;
433
-
434
- if let Some ( ( removal_span, kind, path) ) = & unit_variant {
435
- err. span_suggestion_verbose (
436
- * removal_span,
437
- & format ! (
438
- "`{path}` is a unit {kind}, and does not take parentheses to be constructed" ,
439
- ) ,
440
- "" ,
441
- Applicability :: MachineApplicable ,
442
- ) ;
443
- }
444
-
445
- let mut inner_callee_path = None ;
446
- let def = match callee_expr. kind {
447
- hir:: ExprKind :: Path ( ref qpath) => {
448
- self . typeck_results . borrow ( ) . qpath_res ( qpath, callee_expr. hir_id )
449
- }
450
- hir:: ExprKind :: Call ( ref inner_callee, _) => {
451
- // If the call spans more than one line and the callee kind is
452
- // itself another `ExprCall`, that's a clue that we might just be
453
- // missing a semicolon (Issue #51055)
454
- let call_is_multiline =
455
- self . tcx . sess . source_map ( ) . is_multiline ( call_expr. span ) ;
456
- if call_is_multiline {
457
- err. span_suggestion (
458
- callee_expr. span . shrink_to_hi ( ) ,
459
- "consider using a semicolon here" ,
460
- ";" ,
461
- Applicability :: MaybeIncorrect ,
462
- ) ;
463
- }
464
- if let hir:: ExprKind :: Path ( ref inner_qpath) = inner_callee. kind {
465
- inner_callee_path = Some ( inner_qpath) ;
466
- self . typeck_results . borrow ( ) . qpath_res ( inner_qpath, inner_callee. hir_id )
467
- } else {
468
- Res :: Err
469
- }
470
- }
471
- _ => Res :: Err ,
472
- } ;
473
-
474
- if !self . maybe_suggest_bad_array_definition ( & mut err, call_expr, callee_expr) {
475
- if let Some ( ( maybe_def, output_ty, _) ) = self . extract_callable_info ( callee_expr, callee_ty)
476
- && !self . type_is_sized_modulo_regions ( self . param_env , output_ty, callee_expr. span )
477
- {
478
- let descr = match maybe_def {
479
- DefIdOrName :: DefId ( def_id) => self . tcx . def_kind ( def_id) . descr ( def_id) ,
480
- DefIdOrName :: Name ( name) => name,
481
- } ;
482
- err. span_label (
483
- callee_expr. span ,
484
- format ! ( "this {descr} returns an unsized value `{output_ty}`, so it cannot be called" )
485
- ) ;
486
- if let DefIdOrName :: DefId ( def_id) = maybe_def
487
- && let Some ( def_span) = self . tcx . hir ( ) . span_if_local ( def_id)
488
- {
489
- err. span_label ( def_span, "the callable type is defined here" ) ;
490
- }
491
- } else {
492
- err. span_label ( call_expr. span , "call expression requires function" ) ;
493
- }
494
- }
495
-
496
- if let Some ( span) = self . tcx . hir ( ) . res_span ( def) {
497
- let callee_ty = callee_ty. to_string ( ) ;
498
- let label = match ( unit_variant, inner_callee_path) {
499
- ( Some ( ( _, kind, path) ) , _) => Some ( format ! ( "{kind} `{path}` defined here" ) ) ,
500
- ( _, Some ( hir:: QPath :: Resolved ( _, path) ) ) => self
501
- . tcx
502
- . sess
503
- . source_map ( )
504
- . span_to_snippet ( path. span )
505
- . ok ( )
506
- . map ( |p| format ! ( "`{p}` defined here returns `{callee_ty}`" ) ) ,
507
- _ => {
508
- match def {
509
- // Emit a different diagnostic for local variables, as they are not
510
- // type definitions themselves, but rather variables *of* that type.
511
- Res :: Local ( hir_id) => Some ( format ! (
512
- "`{}` has type `{}`" ,
513
- self . tcx. hir( ) . name( hir_id) ,
514
- callee_ty
515
- ) ) ,
516
- Res :: Def ( kind, def_id) if kind. ns ( ) == Some ( Namespace :: ValueNS ) => {
517
- Some ( format ! (
518
- "`{}` defined here" ,
519
- self . tcx. def_path_str( def_id) ,
520
- ) )
521
- }
522
- _ => Some ( format ! ( "`{callee_ty}` defined here" ) ) ,
523
- }
524
- }
525
- } ;
526
- if let Some ( label) = label {
527
- err. span_label ( span, label) ;
528
- }
529
- }
530
- err. emit ( ) ;
397
+ self . report_invalid_callee ( call_expr, callee_expr, callee_ty, arg_exprs) ;
531
398
532
399
// This is the "default" function signature, used in case of error.
533
400
// In that case, we check each argument against "error" in order to
@@ -574,6 +441,145 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
574
441
fn_sig. output ( )
575
442
}
576
443
444
+ fn report_invalid_callee (
445
+ & self ,
446
+ call_expr : & ' tcx hir:: Expr < ' tcx > ,
447
+ callee_expr : & ' tcx hir:: Expr < ' tcx > ,
448
+ callee_ty : Ty < ' tcx > ,
449
+ arg_exprs : & ' tcx [ hir:: Expr < ' tcx > ] ,
450
+ ) {
451
+ let mut unit_variant = None ;
452
+ if let hir:: ExprKind :: Path ( qpath) = & callee_expr. kind
453
+ && let Res :: Def ( def:: DefKind :: Ctor ( kind, def:: CtorKind :: Const ) , _)
454
+ = self . typeck_results . borrow ( ) . qpath_res ( qpath, callee_expr. hir_id )
455
+ // Only suggest removing parens if there are no arguments
456
+ && arg_exprs. is_empty ( )
457
+ {
458
+ let descr = match kind {
459
+ def:: CtorOf :: Struct => "struct" ,
460
+ def:: CtorOf :: Variant => "enum variant" ,
461
+ } ;
462
+ let removal_span =
463
+ callee_expr. span . shrink_to_hi ( ) . to ( call_expr. span . shrink_to_hi ( ) ) ;
464
+ unit_variant =
465
+ Some ( ( removal_span, descr, rustc_hir_pretty:: qpath_to_string ( qpath) ) ) ;
466
+ }
467
+
468
+ let callee_ty = self . resolve_vars_if_possible ( callee_ty) ;
469
+ let mut err = type_error_struct ! (
470
+ self . tcx. sess,
471
+ callee_expr. span,
472
+ callee_ty,
473
+ E0618 ,
474
+ "expected function, found {}" ,
475
+ match & unit_variant {
476
+ Some ( ( _, kind, path) ) => format!( "{kind} `{path}`" ) ,
477
+ None => format!( "`{callee_ty}`" ) ,
478
+ }
479
+ ) ;
480
+
481
+ self . identify_bad_closure_def_and_call (
482
+ & mut err,
483
+ call_expr. hir_id ,
484
+ & callee_expr. kind ,
485
+ callee_expr. span ,
486
+ ) ;
487
+
488
+ if let Some ( ( removal_span, kind, path) ) = & unit_variant {
489
+ err. span_suggestion_verbose (
490
+ * removal_span,
491
+ & format ! (
492
+ "`{path}` is a unit {kind}, and does not take parentheses to be constructed" ,
493
+ ) ,
494
+ "" ,
495
+ Applicability :: MachineApplicable ,
496
+ ) ;
497
+ }
498
+
499
+ let mut inner_callee_path = None ;
500
+ let def = match callee_expr. kind {
501
+ hir:: ExprKind :: Path ( ref qpath) => {
502
+ self . typeck_results . borrow ( ) . qpath_res ( qpath, callee_expr. hir_id )
503
+ }
504
+ hir:: ExprKind :: Call ( ref inner_callee, _) => {
505
+ // If the call spans more than one line and the callee kind is
506
+ // itself another `ExprCall`, that's a clue that we might just be
507
+ // missing a semicolon (Issue #51055)
508
+ let call_is_multiline = self . tcx . sess . source_map ( ) . is_multiline ( call_expr. span ) ;
509
+ if call_is_multiline {
510
+ err. span_suggestion (
511
+ callee_expr. span . shrink_to_hi ( ) ,
512
+ "consider using a semicolon here" ,
513
+ ";" ,
514
+ Applicability :: MaybeIncorrect ,
515
+ ) ;
516
+ }
517
+ if let hir:: ExprKind :: Path ( ref inner_qpath) = inner_callee. kind {
518
+ inner_callee_path = Some ( inner_qpath) ;
519
+ self . typeck_results . borrow ( ) . qpath_res ( inner_qpath, inner_callee. hir_id )
520
+ } else {
521
+ Res :: Err
522
+ }
523
+ }
524
+ _ => Res :: Err ,
525
+ } ;
526
+
527
+ if !self . maybe_suggest_bad_array_definition ( & mut err, call_expr, callee_expr) {
528
+ if let Some ( ( maybe_def, output_ty, _) ) = self . extract_callable_info ( callee_expr, callee_ty)
529
+ && !self . type_is_sized_modulo_regions ( self . param_env , output_ty, callee_expr. span )
530
+ {
531
+ let descr = match maybe_def {
532
+ DefIdOrName :: DefId ( def_id) => self . tcx . def_kind ( def_id) . descr ( def_id) ,
533
+ DefIdOrName :: Name ( name) => name,
534
+ } ;
535
+ err. span_label (
536
+ callee_expr. span ,
537
+ format ! ( "this {descr} returns an unsized value `{output_ty}`, so it cannot be called" )
538
+ ) ;
539
+ if let DefIdOrName :: DefId ( def_id) = maybe_def
540
+ && let Some ( def_span) = self . tcx . hir ( ) . span_if_local ( def_id)
541
+ {
542
+ err. span_label ( def_span, "the callable type is defined here" ) ;
543
+ }
544
+ } else {
545
+ err. span_label ( call_expr. span , "call expression requires function" ) ;
546
+ }
547
+ }
548
+
549
+ if let Some ( span) = self . tcx . hir ( ) . res_span ( def) {
550
+ let callee_ty = callee_ty. to_string ( ) ;
551
+ let label = match ( unit_variant, inner_callee_path) {
552
+ ( Some ( ( _, kind, path) ) , _) => Some ( format ! ( "{kind} `{path}` defined here" ) ) ,
553
+ ( _, Some ( hir:: QPath :: Resolved ( _, path) ) ) => self
554
+ . tcx
555
+ . sess
556
+ . source_map ( )
557
+ . span_to_snippet ( path. span )
558
+ . ok ( )
559
+ . map ( |p| format ! ( "`{p}` defined here returns `{callee_ty}`" ) ) ,
560
+ _ => {
561
+ match def {
562
+ // Emit a different diagnostic for local variables, as they are not
563
+ // type definitions themselves, but rather variables *of* that type.
564
+ Res :: Local ( hir_id) => Some ( format ! (
565
+ "`{}` has type `{}`" ,
566
+ self . tcx. hir( ) . name( hir_id) ,
567
+ callee_ty
568
+ ) ) ,
569
+ Res :: Def ( kind, def_id) if kind. ns ( ) == Some ( Namespace :: ValueNS ) => {
570
+ Some ( format ! ( "`{}` defined here" , self . tcx. def_path_str( def_id) , ) )
571
+ }
572
+ _ => Some ( format ! ( "`{callee_ty}` defined here" ) ) ,
573
+ }
574
+ }
575
+ } ;
576
+ if let Some ( label) = label {
577
+ err. span_label ( span, label) ;
578
+ }
579
+ }
580
+ err. emit ( ) ;
581
+ }
582
+
577
583
fn confirm_deferred_closure_call (
578
584
& self ,
579
585
call_expr : & ' tcx hir:: Expr < ' tcx > ,
0 commit comments