Skip to content

Commit a5dc963

Browse files
Add E0617
1 parent 03abb1b commit a5dc963

File tree

4 files changed

+70
-27
lines changed

4 files changed

+70
-27
lines changed

src/librustc_typeck/check/mod.rs

+11-21
Original file line numberDiff line numberDiff line change
@@ -2553,42 +2553,32 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
25532553
// We also need to make sure we at least write the ty of the other
25542554
// arguments which we skipped above.
25552555
if variadic {
2556+
fn variadic_error<'tcx>(s: &Session, span: Span, t: Ty<'tcx>, cast_ty: &str) {
2557+
type_error_struct!(s, span, t, E0617,
2558+
"can't pass `{}` to variadic function, cast to `{}`",
2559+
t, cast_ty).emit();
2560+
}
2561+
25562562
for arg in args.iter().skip(expected_arg_count) {
25572563
let arg_ty = self.check_expr(&arg);
25582564

25592565
// There are a few types which get autopromoted when passed via varargs
25602566
// in C but we just error out instead and require explicit casts.
2561-
let arg_ty = self.structurally_resolved_type(arg.span,
2562-
arg_ty);
2567+
let arg_ty = self.structurally_resolved_type(arg.span, arg_ty);
25632568
match arg_ty.sty {
25642569
ty::TyFloat(ast::FloatTy::F32) => {
2565-
self.type_error_message(arg.span, |t| {
2566-
format!("can't pass an `{}` to variadic \
2567-
function, cast to `c_double`", t)
2568-
}, arg_ty);
2570+
variadic_error(tcx.sess, arg.span, arg_ty, "c_double");
25692571
}
25702572
ty::TyInt(ast::IntTy::I8) | ty::TyInt(ast::IntTy::I16) | ty::TyBool => {
2571-
self.type_error_message(arg.span, |t| {
2572-
format!("can't pass `{}` to variadic \
2573-
function, cast to `c_int`",
2574-
t)
2575-
}, arg_ty);
2573+
variadic_error(tcx.sess, arg.span, arg_ty, "c_int");
25762574
}
25772575
ty::TyUint(ast::UintTy::U8) | ty::TyUint(ast::UintTy::U16) => {
2578-
self.type_error_message(arg.span, |t| {
2579-
format!("can't pass `{}` to variadic \
2580-
function, cast to `c_uint`",
2581-
t)
2582-
}, arg_ty);
2576+
variadic_error(tcx.sess, arg.span, arg_ty, "c_uint");
25832577
}
25842578
ty::TyFnDef(.., f) => {
25852579
let ptr_ty = self.tcx.mk_fn_ptr(f);
25862580
let ptr_ty = self.resolve_type_vars_if_possible(&ptr_ty);
2587-
self.type_error_message(arg.span,
2588-
|t| {
2589-
format!("can't pass `{}` to variadic \
2590-
function, cast to `{}`", t, ptr_ty)
2591-
}, arg_ty);
2581+
variadic_error(tcx.sess, arg.span, arg_ty, &format!("{}", ptr_ty));
25922582
}
25932583
_ => {}
25942584
}

src/librustc_typeck/diagnostics.rs

+21
Original file line numberDiff line numberDiff line change
@@ -4152,6 +4152,27 @@ println!("x: {}, y: {}", variable.x, variable.y);
41524152
For more information see The Rust Book: https://doc.rust-lang.org/book/
41534153
"##,
41544154

4155+
E0617: r##"
4156+
Attempted to pass an invalid type of variable into a variadic function.
4157+
4158+
Erroneous code example:
4159+
4160+
```compile_fail,E0617
4161+
extern {
4162+
fn printf(c: *const i8, ...);
4163+
}
4164+
4165+
unsafe {
4166+
printf(::std::ptr::null(), 0f32);
4167+
// error: can't pass an `f32` to variadic function, cast to `c_double`
4168+
}
4169+
```
4170+
4171+
To fix this error, you need to pass variables corresponding to C types as much
4172+
as possible. For better explanations, see The Rust Book:
4173+
https://doc.rust-lang.org/book/
4174+
"##,
4175+
41554176
}
41564177

41574178
register_diagnostics! {

src/test/compile-fail/E0617.rs

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// ignore-tidy-linelength
12+
13+
extern {
14+
fn printf(c: *const i8, ...);
15+
}
16+
17+
fn main() {
18+
unsafe {
19+
printf(::std::ptr::null(), 0f32);
20+
//~^ ERROR can't pass `f32` to variadic function, cast to `c_double` [E0617]
21+
printf(::std::ptr::null(), 0i8);
22+
//~^ ERROR can't pass `i8` to variadic function, cast to `c_int` [E0617]
23+
printf(::std::ptr::null(), 0i16);
24+
//~^ ERROR can't pass `i16` to variadic function, cast to `c_int` [E0617]
25+
printf(::std::ptr::null(), 0u8);
26+
//~^ ERROR can't pass `u8` to variadic function, cast to `c_uint` [E0617]
27+
printf(::std::ptr::null(), 0u16);
28+
//~^ ERROR can't pass `u16` to variadic function, cast to `c_uint` [E0617]
29+
printf(::std::ptr::null(), printf);
30+
//~^ ERROR can't pass `unsafe extern "C" fn(*const i8, ...) {printf}` to variadic function, cast to `unsafe extern "C" fn(*const i8, ...)` [E0617]
31+
}
32+
}

src/test/compile-fail/variadic-ffi-3.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,11 @@ fn main() {
3535
//~| found type `extern "C" fn(isize, u8) {bar}`
3636
//~| NOTE: expected variadic fn, found non-variadic function
3737

38-
foo(1, 2, 3f32); //~ ERROR: can't pass an `f32` to variadic function, cast to `c_double`
39-
foo(1, 2, true); //~ ERROR: can't pass `bool` to variadic function, cast to `c_int`
40-
foo(1, 2, 1i8); //~ ERROR: can't pass `i8` to variadic function, cast to `c_int`
41-
foo(1, 2, 1u8); //~ ERROR: can't pass `u8` to variadic function, cast to `c_uint`
42-
foo(1, 2, 1i16); //~ ERROR: can't pass `i16` to variadic function, cast to `c_int`
43-
foo(1, 2, 1u16); //~ ERROR: can't pass `u16` to variadic function, cast to `c_uint`
38+
foo(1, 2, 3f32); //~ ERROR can't pass `f32` to variadic function, cast to `c_double`
39+
foo(1, 2, true); //~ ERROR can't pass `bool` to variadic function, cast to `c_int`
40+
foo(1, 2, 1i8); //~ ERROR can't pass `i8` to variadic function, cast to `c_int`
41+
foo(1, 2, 1u8); //~ ERROR can't pass `u8` to variadic function, cast to `c_uint`
42+
foo(1, 2, 1i16); //~ ERROR can't pass `i16` to variadic function, cast to `c_int`
43+
foo(1, 2, 1u16); //~ ERROR can't pass `u16` to variadic function, cast to `c_uint`
4444
}
4545
}

0 commit comments

Comments
 (0)