Refactor confirm_builtin_call, remove partial if
Pass callee expr to `confirm_builtin_call`. This removes a partial pattern match in `confirm_builtin_call` and the `panic` in the `else` branch. The diff is large because of indentation changes caused by removing the if-let.
This commit is contained in:
parent
6f7673d077
commit
c8a0e8d61b
1 changed files with 103 additions and 102 deletions
|
@ -77,11 +77,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
let output = match result {
|
let output = match result {
|
||||||
None => {
|
None => {
|
||||||
// this will report an error since original_callee_ty is not a fn
|
// this will report an error since original_callee_ty is not a fn
|
||||||
self.confirm_builtin_call(call_expr, original_callee_ty, arg_exprs, expected)
|
self.confirm_builtin_call(
|
||||||
|
call_expr,
|
||||||
|
callee_expr,
|
||||||
|
original_callee_ty,
|
||||||
|
arg_exprs,
|
||||||
|
expected,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(CallStep::Builtin(callee_ty)) => {
|
Some(CallStep::Builtin(callee_ty)) => {
|
||||||
self.confirm_builtin_call(call_expr, callee_ty, arg_exprs, expected)
|
self.confirm_builtin_call(call_expr, callee_expr, callee_ty, arg_exprs, expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(CallStep::DeferredClosure(fn_sig)) => {
|
Some(CallStep::DeferredClosure(fn_sig)) => {
|
||||||
|
@ -281,6 +287,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
fn confirm_builtin_call(
|
fn confirm_builtin_call(
|
||||||
&self,
|
&self,
|
||||||
call_expr: &'tcx hir::Expr<'tcx>,
|
call_expr: &'tcx hir::Expr<'tcx>,
|
||||||
|
callee_expr: &'tcx hir::Expr<'tcx>,
|
||||||
callee_ty: Ty<'tcx>,
|
callee_ty: Ty<'tcx>,
|
||||||
arg_exprs: &'tcx [hir::Expr<'tcx>],
|
arg_exprs: &'tcx [hir::Expr<'tcx>],
|
||||||
expected: Expectation<'tcx>,
|
expected: Expectation<'tcx>,
|
||||||
|
@ -299,111 +306,105 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let hir::ExprKind::Call(callee, _) = call_expr.kind {
|
let mut err = type_error_struct!(
|
||||||
let mut err = type_error_struct!(
|
self.tcx.sess,
|
||||||
self.tcx.sess,
|
callee_expr.span,
|
||||||
callee.span,
|
callee_ty,
|
||||||
callee_ty,
|
E0618,
|
||||||
E0618,
|
"expected function, found {}",
|
||||||
"expected function, found {}",
|
match unit_variant {
|
||||||
match unit_variant {
|
Some(ref path) => format!("enum variant `{}`", path),
|
||||||
Some(ref path) => format!("enum variant `{}`", path),
|
None => format!("`{}`", callee_ty),
|
||||||
None => format!("`{}`", callee_ty),
|
}
|
||||||
}
|
);
|
||||||
);
|
|
||||||
|
|
||||||
self.identify_bad_closure_def_and_call(
|
self.identify_bad_closure_def_and_call(
|
||||||
&mut err,
|
&mut err,
|
||||||
call_expr.hir_id,
|
call_expr.hir_id,
|
||||||
&callee.kind,
|
&callee_expr.kind,
|
||||||
callee.span,
|
callee_expr.span,
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(ref path) = unit_variant {
|
if let Some(ref path) = unit_variant {
|
||||||
err.span_suggestion(
|
err.span_suggestion(
|
||||||
call_expr.span,
|
call_expr.span,
|
||||||
&format!(
|
&format!(
|
||||||
"`{}` is a unit variant, you need to write it \
|
"`{}` is a unit variant, you need to write it \
|
||||||
without the parenthesis",
|
without the parenthesis",
|
||||||
path
|
path
|
||||||
),
|
),
|
||||||
path.to_string(),
|
path.to_string(),
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
let mut inner_callee_path = None;
|
|
||||||
let def = match callee.kind {
|
|
||||||
hir::ExprKind::Path(ref qpath) => {
|
|
||||||
self.typeck_results.borrow().qpath_res(qpath, callee.hir_id)
|
|
||||||
}
|
|
||||||
hir::ExprKind::Call(ref inner_callee, _) => {
|
|
||||||
// If the call spans more than one line and the callee kind is
|
|
||||||
// itself another `ExprCall`, that's a clue that we might just be
|
|
||||||
// missing a semicolon (Issue #51055)
|
|
||||||
let call_is_multiline =
|
|
||||||
self.tcx.sess.source_map().is_multiline(call_expr.span);
|
|
||||||
if call_is_multiline {
|
|
||||||
err.span_suggestion(
|
|
||||||
callee.span.shrink_to_hi(),
|
|
||||||
"consider using a semicolon here",
|
|
||||||
";".to_owned(),
|
|
||||||
Applicability::MaybeIncorrect,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if let hir::ExprKind::Path(ref inner_qpath) = inner_callee.kind {
|
|
||||||
inner_callee_path = Some(inner_qpath);
|
|
||||||
self.typeck_results
|
|
||||||
.borrow()
|
|
||||||
.qpath_res(inner_qpath, inner_callee.hir_id)
|
|
||||||
} else {
|
|
||||||
Res::Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => Res::Err,
|
|
||||||
};
|
|
||||||
|
|
||||||
err.span_label(call_expr.span, "call expression requires function");
|
|
||||||
|
|
||||||
if let Some(span) = self.tcx.hir().res_span(def) {
|
|
||||||
let callee_ty = callee_ty.to_string();
|
|
||||||
let label = match (unit_variant, inner_callee_path) {
|
|
||||||
(Some(path), _) => Some(format!("`{}` defined here", path)),
|
|
||||||
(_, Some(hir::QPath::Resolved(_, path))) => {
|
|
||||||
self.tcx.sess.source_map().span_to_snippet(path.span).ok().map(
|
|
||||||
|p| format!("`{}` defined here returns `{}`", p, callee_ty),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
match def {
|
|
||||||
// Emit a different diagnostic for local variables, as they are not
|
|
||||||
// type definitions themselves, but rather variables *of* that type.
|
|
||||||
Res::Local(hir_id) => Some(format!(
|
|
||||||
"`{}` has type `{}`",
|
|
||||||
self.tcx.hir().name(hir_id),
|
|
||||||
callee_ty
|
|
||||||
)),
|
|
||||||
Res::Def(kind, def_id)
|
|
||||||
if kind.ns() == Some(Namespace::ValueNS) =>
|
|
||||||
{
|
|
||||||
Some(format!(
|
|
||||||
"`{}` defined here",
|
|
||||||
self.tcx.def_path_str(def_id),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
_ => Some(format!("`{}` defined here", callee_ty)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if let Some(label) = label {
|
|
||||||
err.span_label(span, label);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
err.emit();
|
|
||||||
} else {
|
|
||||||
bug!("call_expr.kind should be an ExprKind::Call, got {:?}", call_expr.kind);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut inner_callee_path = None;
|
||||||
|
let def = match callee_expr.kind {
|
||||||
|
hir::ExprKind::Path(ref qpath) => {
|
||||||
|
self.typeck_results.borrow().qpath_res(qpath, callee_expr.hir_id)
|
||||||
|
}
|
||||||
|
hir::ExprKind::Call(ref inner_callee, _) => {
|
||||||
|
// If the call spans more than one line and the callee kind is
|
||||||
|
// itself another `ExprCall`, that's a clue that we might just be
|
||||||
|
// missing a semicolon (Issue #51055)
|
||||||
|
let call_is_multiline =
|
||||||
|
self.tcx.sess.source_map().is_multiline(call_expr.span);
|
||||||
|
if call_is_multiline {
|
||||||
|
err.span_suggestion(
|
||||||
|
callee_expr.span.shrink_to_hi(),
|
||||||
|
"consider using a semicolon here",
|
||||||
|
";".to_owned(),
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if let hir::ExprKind::Path(ref inner_qpath) = inner_callee.kind {
|
||||||
|
inner_callee_path = Some(inner_qpath);
|
||||||
|
self.typeck_results.borrow().qpath_res(inner_qpath, inner_callee.hir_id)
|
||||||
|
} else {
|
||||||
|
Res::Err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => Res::Err,
|
||||||
|
};
|
||||||
|
|
||||||
|
err.span_label(call_expr.span, "call expression requires function");
|
||||||
|
|
||||||
|
if let Some(span) = self.tcx.hir().res_span(def) {
|
||||||
|
let callee_ty = callee_ty.to_string();
|
||||||
|
let label = match (unit_variant, inner_callee_path) {
|
||||||
|
(Some(path), _) => Some(format!("`{}` defined here", path)),
|
||||||
|
(_, Some(hir::QPath::Resolved(_, path))) => self
|
||||||
|
.tcx
|
||||||
|
.sess
|
||||||
|
.source_map()
|
||||||
|
.span_to_snippet(path.span)
|
||||||
|
.ok()
|
||||||
|
.map(|p| format!("`{}` defined here returns `{}`", p, callee_ty)),
|
||||||
|
_ => {
|
||||||
|
match def {
|
||||||
|
// Emit a different diagnostic for local variables, as they are not
|
||||||
|
// type definitions themselves, but rather variables *of* that type.
|
||||||
|
Res::Local(hir_id) => Some(format!(
|
||||||
|
"`{}` has type `{}`",
|
||||||
|
self.tcx.hir().name(hir_id),
|
||||||
|
callee_ty
|
||||||
|
)),
|
||||||
|
Res::Def(kind, def_id) if kind.ns() == Some(Namespace::ValueNS) => {
|
||||||
|
Some(format!(
|
||||||
|
"`{}` defined here",
|
||||||
|
self.tcx.def_path_str(def_id),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
_ => Some(format!("`{}` defined here", callee_ty)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if let Some(label) = label {
|
||||||
|
err.span_label(span, label);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err.emit();
|
||||||
|
|
||||||
// This is the "default" function signature, used in case of error.
|
// This is the "default" function signature, used in case of error.
|
||||||
// In that case, we check each argument against "error" in order to
|
// In that case, we check each argument against "error" in order to
|
||||||
// set up all the node type bindings.
|
// set up all the node type bindings.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue