Skip to content

Commit aa3fbf8

Browse files
committed
Split out the error reporting logic into a separate function
1 parent c5bbf36 commit aa3fbf8

File tree

1 file changed

+140
-134
lines changed
  • compiler/rustc_hir_analysis/src/check

1 file changed

+140
-134
lines changed

Diff for: compiler/rustc_hir_analysis/src/check/callee.rs

+140-134
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)