@@ -394,140 +394,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
394394 }
395395 ty:: FnPtr ( sig) => ( sig, None ) ,
396396 _ => {
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) ;
531398
532399 // This is the "default" function signature, used in case of error.
533400 // In that case, we check each argument against "error" in order to
@@ -574,6 +441,145 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
574441 fn_sig. output ( )
575442 }
576443
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+
577583 fn confirm_deferred_closure_call (
578584 & self ,
579585 call_expr : & ' tcx hir:: Expr < ' tcx > ,
0 commit comments