Skip to content

Commit

Permalink
Slight cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
jackh726 committed Dec 28, 2021
1 parent 555119f commit bbb8bde
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 35 deletions.
4 changes: 2 additions & 2 deletions compiler/rustc_typeck/src/check/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
call_expr.span,
call_expr,
fn_sig.inputs(),
&expected_arg_tys,
expected_arg_tys,
arg_exprs,
fn_sig.c_variadic,
TupleArgumentsFlag::DontTupleArguments,
Expand Down Expand Up @@ -529,7 +529,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
call_expr.span,
call_expr,
fn_sig.inputs(),
&expected_arg_tys,
expected_arg_tys,
arg_exprs,
fn_sig.c_variadic,
TupleArgumentsFlag::TupleArguments,
Expand Down
60 changes: 27 additions & 33 deletions compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
sp,
expr,
&err_inputs,
&[],
vec![],
args_no_rcvr,
false,
tuple_arguments,
Expand All @@ -83,7 +83,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
sp,
expr,
&method.sig.inputs()[1..],
&expected_input_tys[..],
expected_input_tys,
args_no_rcvr,
method.sig.c_variadic,
tuple_arguments,
Expand All @@ -103,7 +103,7 @@ impl<'a, 'tcx> FnCtxt<'a, '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>],
expected_input_tys: Vec<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
Expand Down Expand Up @@ -249,25 +249,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err.emit();
};

let mut expected_input_tys = expected_input_tys.to_vec();

let formal_input_tys = if tuple_arguments == TupleArguments {
let (formal_input_tys, expected_input_tys) = if tuple_arguments == TupleArguments {
let tuple_type = self.structurally_resolved_type(call_span, formal_input_tys[0]);
match tuple_type.kind() {
ty::Tuple(arg_types) if arg_types.len() != provided_args.len() => {
param_count_error(arg_types.len(), provided_args.len(), "E0057", false, false);
expected_input_tys = vec![];
self.err_args(provided_args.len())
(self.err_args(provided_args.len()), vec![])
}
ty::Tuple(arg_types) => {
expected_input_tys = match expected_input_tys.get(0) {
let expected_input_tys = match expected_input_tys.get(0) {
Some(&ty) => match ty.kind() {
ty::Tuple(ref tys) => tys.iter().map(|k| k.expect_ty()).collect(),
_ => vec![],
},
None => vec![],
};
arg_types.iter().map(|k| k.expect_ty()).collect()
(arg_types.iter().map(|k| k.expect_ty()).collect(), expected_input_tys)
}
_ => {
struct_span_err!(
Expand All @@ -278,19 +275,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
for the function trait is neither a tuple nor unit"
)
.emit();
expected_input_tys = vec![];
self.err_args(provided_args.len())
(self.err_args(provided_args.len()), vec![])
}
}
} else if expected_arg_count == supplied_arg_count {
formal_input_tys.to_vec()
(formal_input_tys.to_vec(), expected_input_tys)
} else if c_variadic {
if supplied_arg_count >= expected_arg_count {
formal_input_tys.to_vec()
(formal_input_tys.to_vec(), expected_input_tys)
} else {
param_count_error(expected_arg_count, supplied_arg_count, "E0060", true, false);
expected_input_tys = vec![];
self.err_args(supplied_arg_count)
(self.err_args(supplied_arg_count), vec![])
}
} else {
// is the missing argument of type `()`?
Expand All @@ -303,8 +298,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};
param_count_error(expected_arg_count, supplied_arg_count, "E0061", false, sugg_unit);

expected_input_tys = vec![];
self.err_args(supplied_arg_count)
(self.err_args(supplied_arg_count), vec![])
};

debug!(
Expand All @@ -319,6 +313,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
formal_input_tys.clone()
};

assert_eq!(expected_input_tys.len(), formal_input_tys.len());

// Keep track of the fully coerced argument types
let mut final_arg_types: Vec<(usize, Ty<'_>, Ty<'_>)> = vec![];

// We introduce a helper function to demand that a given argument satisfy a given input
Expand Down Expand Up @@ -376,8 +373,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// that we have more information about the types of arguments when we
// type-check the functions. This isn't really the right way to do this.
for check_closures in [false, true] {
debug!("check_closures={}", check_closures);

// More awful hacks: before we check argument types, try to do
// an "opportunistic" trait resolution of any trait bounds on
// the call. This helps coercions.
Expand All @@ -394,31 +389,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
})
}

// For C-variadic functions, we don't have a declared type for all of
// the arguments hence we only do our usual type checking with
// the arguments who's types we do know.
let t = if c_variadic {
expected_arg_count
} else if tuple_arguments == TupleArguments {
provided_args.len()
} else {
supplied_arg_count
};
for (i, arg) in provided_args.iter().take(t).enumerate() {
let minimum_input_count = formal_input_tys.len();
for (idx, arg) in provided_args.iter().enumerate() {
// Warn only for the first loop (the "no closures" one).
// Closure arguments themselves can't be diverging, but
// a previous argument can, e.g., `foo(panic!(), || {})`.
if !check_closures {
self.warn_if_unreachable(arg.hir_id, arg.span, "expression");
}

let is_closure = matches!(arg.kind, ExprKind::Closure(..));
// For C-variadic functions, we don't have a declared type for all of
// the arguments hence we only do our usual type checking with
// the arguments who's types we do know. However, we *can* check
// for unreachable expressions (see above).
// FIXME: unreachable warning current isn't emitted
if idx >= minimum_input_count {
continue;
}

let is_closure = matches!(arg.kind, ExprKind::Closure(..));
if is_closure != check_closures {
continue;
}

demand_compatible(i, &mut final_arg_types);
demand_compatible(idx, &mut final_arg_types);
}
}

Expand Down
14 changes: 14 additions & 0 deletions src/test/ui/c-variadic/variadic-unreachable-arg-error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// check-pass

#![feature(c_variadic)]

extern "C" {
fn foo(f: isize, x: u8, ...);
}

fn main() {
unsafe {
// FIXME: Ideally we could give an unreachable warning
foo(1, loop {}, 1usize);
}
}

0 comments on commit bbb8bde

Please sign in to comment.