Rename args to check_argument_types and add some comments for what they are
This commit is contained in:
parent
e100ec5bc7
commit
9a38ed12ca
1 changed files with 46 additions and 37 deletions
|
@ -96,34 +96,43 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
/// method calls and overloaded operators.
|
/// method calls and overloaded operators.
|
||||||
pub(in super::super) fn check_argument_types(
|
pub(in super::super) fn check_argument_types(
|
||||||
&self,
|
&self,
|
||||||
sp: Span,
|
// Span enclosing the call site
|
||||||
expr: &'tcx hir::Expr<'tcx>,
|
call_span: Span,
|
||||||
fn_inputs: &[Ty<'tcx>],
|
// Expression of the call site
|
||||||
expected_arg_tys: &[Ty<'tcx>],
|
call_expr: &'tcx hir::Expr<'tcx>,
|
||||||
args: &'tcx [hir::Expr<'tcx>],
|
// Types (as defined in the *signature* of the target function)
|
||||||
|
formal_input_tys: &[Ty<'tcx>],
|
||||||
|
// More specific expected types, after unifying with caller output types
|
||||||
|
expected_input_tys: &[Ty<'tcx>],
|
||||||
|
// The expressions for each provided argument
|
||||||
|
provided_args: &'tcx [hir::Expr<'tcx>],
|
||||||
|
// Whether the function is variadic, for example when imported from C
|
||||||
c_variadic: bool,
|
c_variadic: bool,
|
||||||
|
// Whether the arguments have been bundled in a tuple (ex: closures)
|
||||||
tuple_arguments: TupleArgumentsFlag,
|
tuple_arguments: TupleArgumentsFlag,
|
||||||
def_id: Option<DefId>,
|
// The DefId for the function being called, for better error messages
|
||||||
|
fn_def_id: Option<DefId>,
|
||||||
) {
|
) {
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
// Grab the argument types, supplying fresh type variables
|
// Grab the argument types, supplying fresh type variables
|
||||||
// if the wrong number of arguments were supplied
|
// if the wrong number of arguments were supplied
|
||||||
let supplied_arg_count = if tuple_arguments == DontTupleArguments { args.len() } else { 1 };
|
let supplied_arg_count =
|
||||||
|
if tuple_arguments == DontTupleArguments { provided_args.len() } else { 1 };
|
||||||
|
|
||||||
// All the input types from the fn signature must outlive the call
|
// All the input types from the fn signature must outlive the call
|
||||||
// so as to validate implied bounds.
|
// so as to validate implied bounds.
|
||||||
for (&fn_input_ty, arg_expr) in iter::zip(fn_inputs, args) {
|
for (&fn_input_ty, arg_expr) in iter::zip(formal_input_tys, provided_args) {
|
||||||
self.register_wf_obligation(fn_input_ty.into(), arg_expr.span, traits::MiscObligation);
|
self.register_wf_obligation(fn_input_ty.into(), arg_expr.span, traits::MiscObligation);
|
||||||
}
|
}
|
||||||
|
|
||||||
let expected_arg_count = fn_inputs.len();
|
let expected_arg_count = formal_input_tys.len();
|
||||||
|
|
||||||
let param_count_error = |expected_count: usize,
|
let param_count_error = |expected_count: usize,
|
||||||
arg_count: usize,
|
arg_count: usize,
|
||||||
error_code: &str,
|
error_code: &str,
|
||||||
c_variadic: bool,
|
c_variadic: bool,
|
||||||
sugg_unit: bool| {
|
sugg_unit: bool| {
|
||||||
let (span, start_span, args, ctor_of) = match &expr.kind {
|
let (span, start_span, args, ctor_of) = match &call_expr.kind {
|
||||||
hir::ExprKind::Call(
|
hir::ExprKind::Call(
|
||||||
hir::Expr {
|
hir::Expr {
|
||||||
span,
|
span,
|
||||||
|
@ -156,14 +165,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
&args[1..], // Skip the receiver.
|
&args[1..], // Skip the receiver.
|
||||||
None, // methods are never ctors
|
None, // methods are never ctors
|
||||||
),
|
),
|
||||||
k => span_bug!(sp, "checking argument types on a non-call: `{:?}`", k),
|
k => span_bug!(call_span, "checking argument types on a non-call: `{:?}`", k),
|
||||||
};
|
};
|
||||||
let arg_spans = if args.is_empty() {
|
let arg_spans = if provided_args.is_empty() {
|
||||||
// foo()
|
// foo()
|
||||||
// ^^^-- supplied 0 arguments
|
// ^^^-- supplied 0 arguments
|
||||||
// |
|
// |
|
||||||
// expected 2 arguments
|
// expected 2 arguments
|
||||||
vec![tcx.sess.source_map().next_point(start_span).with_hi(sp.hi())]
|
vec![tcx.sess.source_map().next_point(start_span).with_hi(call_span.hi())]
|
||||||
} else {
|
} else {
|
||||||
// foo(1, 2, 3)
|
// foo(1, 2, 3)
|
||||||
// ^^^ - - - supplied 3 arguments
|
// ^^^ - - - supplied 3 arguments
|
||||||
|
@ -196,7 +205,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(def_id) = def_id {
|
if let Some(def_id) = fn_def_id {
|
||||||
if let Some(def_span) = tcx.def_ident_span(def_id) {
|
if let Some(def_span) = tcx.def_ident_span(def_id) {
|
||||||
let mut spans: MultiSpan = def_span.into();
|
let mut spans: MultiSpan = def_span.into();
|
||||||
|
|
||||||
|
@ -218,7 +227,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if sugg_unit {
|
if sugg_unit {
|
||||||
let sugg_span = tcx.sess.source_map().end_point(expr.span);
|
let sugg_span = tcx.sess.source_map().end_point(call_expr.span);
|
||||||
// remove closing `)` from the span
|
// remove closing `)` from the span
|
||||||
let sugg_span = sugg_span.shrink_to_lo();
|
let sugg_span = sugg_span.shrink_to_lo();
|
||||||
err.span_suggestion(
|
err.span_suggestion(
|
||||||
|
@ -240,15 +249,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
err.emit();
|
err.emit();
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut expected_arg_tys = expected_arg_tys.to_vec();
|
let mut expected_arg_tys = expected_input_tys.to_vec();
|
||||||
|
|
||||||
let formal_tys = if tuple_arguments == TupleArguments {
|
let formal_tys = if tuple_arguments == TupleArguments {
|
||||||
let tuple_type = self.structurally_resolved_type(sp, fn_inputs[0]);
|
let tuple_type = self.structurally_resolved_type(call_span, formal_input_tys[0]);
|
||||||
match tuple_type.kind() {
|
match tuple_type.kind() {
|
||||||
ty::Tuple(arg_types) if arg_types.len() != args.len() => {
|
ty::Tuple(arg_types) if arg_types.len() != provided_args.len() => {
|
||||||
param_count_error(arg_types.len(), args.len(), "E0057", false, false);
|
param_count_error(arg_types.len(), provided_args.len(), "E0057", false, false);
|
||||||
expected_arg_tys = vec![];
|
expected_arg_tys = vec![];
|
||||||
self.err_args(args.len())
|
self.err_args(provided_args.len())
|
||||||
}
|
}
|
||||||
ty::Tuple(arg_types) => {
|
ty::Tuple(arg_types) => {
|
||||||
expected_arg_tys = match expected_arg_tys.get(0) {
|
expected_arg_tys = match expected_arg_tys.get(0) {
|
||||||
|
@ -263,21 +272,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
_ => {
|
_ => {
|
||||||
struct_span_err!(
|
struct_span_err!(
|
||||||
tcx.sess,
|
tcx.sess,
|
||||||
sp,
|
call_span,
|
||||||
E0059,
|
E0059,
|
||||||
"cannot use call notation; the first type parameter \
|
"cannot use call notation; the first type parameter \
|
||||||
for the function trait is neither a tuple nor unit"
|
for the function trait is neither a tuple nor unit"
|
||||||
)
|
)
|
||||||
.emit();
|
.emit();
|
||||||
expected_arg_tys = vec![];
|
expected_arg_tys = vec![];
|
||||||
self.err_args(args.len())
|
self.err_args(provided_args.len())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if expected_arg_count == supplied_arg_count {
|
} else if expected_arg_count == supplied_arg_count {
|
||||||
fn_inputs.to_vec()
|
formal_input_tys.to_vec()
|
||||||
} else if c_variadic {
|
} else if c_variadic {
|
||||||
if supplied_arg_count >= expected_arg_count {
|
if supplied_arg_count >= expected_arg_count {
|
||||||
fn_inputs.to_vec()
|
formal_input_tys.to_vec()
|
||||||
} else {
|
} else {
|
||||||
param_count_error(expected_arg_count, supplied_arg_count, "E0060", true, false);
|
param_count_error(expected_arg_count, supplied_arg_count, "E0060", true, false);
|
||||||
expected_arg_tys = vec![];
|
expected_arg_tys = vec![];
|
||||||
|
@ -287,8 +296,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
// is the missing argument of type `()`?
|
// is the missing argument of type `()`?
|
||||||
let sugg_unit = if expected_arg_tys.len() == 1 && supplied_arg_count == 0 {
|
let sugg_unit = if expected_arg_tys.len() == 1 && supplied_arg_count == 0 {
|
||||||
self.resolve_vars_if_possible(expected_arg_tys[0]).is_unit()
|
self.resolve_vars_if_possible(expected_arg_tys[0]).is_unit()
|
||||||
} else if fn_inputs.len() == 1 && supplied_arg_count == 0 {
|
} else if formal_input_tys.len() == 1 && supplied_arg_count == 0 {
|
||||||
self.resolve_vars_if_possible(fn_inputs[0]).is_unit()
|
self.resolve_vars_if_possible(formal_input_tys[0]).is_unit()
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
|
@ -322,13 +331,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
// the call. This helps coercions.
|
// the call. This helps coercions.
|
||||||
if check_closures {
|
if check_closures {
|
||||||
self.select_obligations_where_possible(false, |errors| {
|
self.select_obligations_where_possible(false, |errors| {
|
||||||
self.point_at_type_arg_instead_of_call_if_possible(errors, expr);
|
self.point_at_type_arg_instead_of_call_if_possible(errors, call_expr);
|
||||||
self.point_at_arg_instead_of_call_if_possible(
|
self.point_at_arg_instead_of_call_if_possible(
|
||||||
errors,
|
errors,
|
||||||
&final_arg_types,
|
&final_arg_types,
|
||||||
expr,
|
call_expr,
|
||||||
sp,
|
call_span,
|
||||||
&args,
|
&provided_args,
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -339,11 +348,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
let t = if c_variadic {
|
let t = if c_variadic {
|
||||||
expected_arg_count
|
expected_arg_count
|
||||||
} else if tuple_arguments == TupleArguments {
|
} else if tuple_arguments == TupleArguments {
|
||||||
args.len()
|
provided_args.len()
|
||||||
} else {
|
} else {
|
||||||
supplied_arg_count
|
supplied_arg_count
|
||||||
};
|
};
|
||||||
for (i, arg) in args.iter().take(t).enumerate() {
|
for (i, arg) in provided_args.iter().take(t).enumerate() {
|
||||||
// Warn only for the first loop (the "no closures" one).
|
// Warn only for the first loop (the "no closures" one).
|
||||||
// Closure arguments themselves can't be diverging, but
|
// Closure arguments themselves can't be diverging, but
|
||||||
// a previous argument can, e.g., `foo(panic!(), || {})`.
|
// a previous argument can, e.g., `foo(panic!(), || {})`.
|
||||||
|
@ -380,13 +389,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
let _ = self.resolve_vars_with_obligations_and_mutate_fulfillment(
|
let _ = self.resolve_vars_with_obligations_and_mutate_fulfillment(
|
||||||
coerce_ty,
|
coerce_ty,
|
||||||
|errors| {
|
|errors| {
|
||||||
self.point_at_type_arg_instead_of_call_if_possible(errors, expr);
|
self.point_at_type_arg_instead_of_call_if_possible(errors, call_expr);
|
||||||
self.point_at_arg_instead_of_call_if_possible(
|
self.point_at_arg_instead_of_call_if_possible(
|
||||||
errors,
|
errors,
|
||||||
&final_arg_types,
|
&final_arg_types,
|
||||||
expr,
|
call_expr,
|
||||||
sp,
|
call_span,
|
||||||
args,
|
provided_args,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -410,7 +419,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
MissingCastForVariadicArg { sess, span, ty, cast_ty }.diagnostic().emit()
|
MissingCastForVariadicArg { sess, span, ty, cast_ty }.diagnostic().emit()
|
||||||
}
|
}
|
||||||
|
|
||||||
for arg in args.iter().skip(expected_arg_count) {
|
for arg in provided_args.iter().skip(expected_arg_count) {
|
||||||
let arg_ty = self.check_expr(&arg);
|
let arg_ty = self.check_expr(&arg);
|
||||||
|
|
||||||
// There are a few types which get autopromoted when passed via varargs
|
// There are a few types which get autopromoted when passed via varargs
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue