1
Fork 0

Rename args to check_argument_types and add some comments for what they are

This commit is contained in:
Jack Huey 2021-12-24 14:31:17 -05:00
parent e100ec5bc7
commit 9a38ed12ca

View file

@ -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