Skip to content

Commit 9807570

Browse files
authored
Rollup merge of #102476 - oli-obk:split_error_path, r=cjgillot
Split out the error reporting logic into a separate function I was trying to read the function and got distracted by the huge block of code in the middle of it. Turns out it only reports diagnostics and all paths within it end in an error. The main function is now more readable imo.
2 parents af33587 + aa3fbf8 commit 9807570

File tree

1 file changed

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

1 file changed

+140
-134
lines changed

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)