Skip to content

Commit

Permalink
Add E0617
Browse files Browse the repository at this point in the history
  • Loading branch information
GuillaumeGomez committed Jun 13, 2017
1 parent 03abb1b commit a5dc963
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 27 deletions.
32 changes: 11 additions & 21 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2553,42 +2553,32 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// We also need to make sure we at least write the ty of the other
// arguments which we skipped above.
if variadic {
fn variadic_error<'tcx>(s: &Session, span: Span, t: Ty<'tcx>, cast_ty: &str) {
type_error_struct!(s, span, t, E0617,
"can't pass `{}` to variadic function, cast to `{}`",
t, cast_ty).emit();
}

for arg in args.iter().skip(expected_arg_count) {
let arg_ty = self.check_expr(&arg);

// There are a few types which get autopromoted when passed via varargs
// in C but we just error out instead and require explicit casts.
let arg_ty = self.structurally_resolved_type(arg.span,
arg_ty);
let arg_ty = self.structurally_resolved_type(arg.span, arg_ty);
match arg_ty.sty {
ty::TyFloat(ast::FloatTy::F32) => {
self.type_error_message(arg.span, |t| {
format!("can't pass an `{}` to variadic \
function, cast to `c_double`", t)
}, arg_ty);
variadic_error(tcx.sess, arg.span, arg_ty, "c_double");
}
ty::TyInt(ast::IntTy::I8) | ty::TyInt(ast::IntTy::I16) | ty::TyBool => {
self.type_error_message(arg.span, |t| {
format!("can't pass `{}` to variadic \
function, cast to `c_int`",
t)
}, arg_ty);
variadic_error(tcx.sess, arg.span, arg_ty, "c_int");
}
ty::TyUint(ast::UintTy::U8) | ty::TyUint(ast::UintTy::U16) => {
self.type_error_message(arg.span, |t| {
format!("can't pass `{}` to variadic \
function, cast to `c_uint`",
t)
}, arg_ty);
variadic_error(tcx.sess, arg.span, arg_ty, "c_uint");
}
ty::TyFnDef(.., f) => {
let ptr_ty = self.tcx.mk_fn_ptr(f);
let ptr_ty = self.resolve_type_vars_if_possible(&ptr_ty);
self.type_error_message(arg.span,
|t| {
format!("can't pass `{}` to variadic \
function, cast to `{}`", t, ptr_ty)
}, arg_ty);
variadic_error(tcx.sess, arg.span, arg_ty, &format!("{}", ptr_ty));
}
_ => {}
}
Expand Down
21 changes: 21 additions & 0 deletions src/librustc_typeck/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4152,6 +4152,27 @@ println!("x: {}, y: {}", variable.x, variable.y);
For more information see The Rust Book: https://doc.rust-lang.org/book/
"##,

E0617: r##"
Attempted to pass an invalid type of variable into a variadic function.
Erroneous code example:
```compile_fail,E0617
extern {
fn printf(c: *const i8, ...);
}
unsafe {
printf(::std::ptr::null(), 0f32);
// error: can't pass an `f32` to variadic function, cast to `c_double`
}
```
To fix this error, you need to pass variables corresponding to C types as much
as possible. For better explanations, see The Rust Book:
https://doc.rust-lang.org/book/
"##,

}

register_diagnostics! {
Expand Down
32 changes: 32 additions & 0 deletions src/test/compile-fail/E0617.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// ignore-tidy-linelength

extern {
fn printf(c: *const i8, ...);
}

fn main() {
unsafe {
printf(::std::ptr::null(), 0f32);
//~^ ERROR can't pass `f32` to variadic function, cast to `c_double` [E0617]
printf(::std::ptr::null(), 0i8);
//~^ ERROR can't pass `i8` to variadic function, cast to `c_int` [E0617]
printf(::std::ptr::null(), 0i16);
//~^ ERROR can't pass `i16` to variadic function, cast to `c_int` [E0617]
printf(::std::ptr::null(), 0u8);
//~^ ERROR can't pass `u8` to variadic function, cast to `c_uint` [E0617]
printf(::std::ptr::null(), 0u16);
//~^ ERROR can't pass `u16` to variadic function, cast to `c_uint` [E0617]
printf(::std::ptr::null(), printf);
//~^ ERROR can't pass `unsafe extern "C" fn(*const i8, ...) {printf}` to variadic function, cast to `unsafe extern "C" fn(*const i8, ...)` [E0617]
}
}
12 changes: 6 additions & 6 deletions src/test/compile-fail/variadic-ffi-3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ fn main() {
//~| found type `extern "C" fn(isize, u8) {bar}`
//~| NOTE: expected variadic fn, found non-variadic function

foo(1, 2, 3f32); //~ ERROR: can't pass an `f32` to variadic function, cast to `c_double`
foo(1, 2, true); //~ ERROR: can't pass `bool` to variadic function, cast to `c_int`
foo(1, 2, 1i8); //~ ERROR: can't pass `i8` to variadic function, cast to `c_int`
foo(1, 2, 1u8); //~ ERROR: can't pass `u8` to variadic function, cast to `c_uint`
foo(1, 2, 1i16); //~ ERROR: can't pass `i16` to variadic function, cast to `c_int`
foo(1, 2, 1u16); //~ ERROR: can't pass `u16` to variadic function, cast to `c_uint`
foo(1, 2, 3f32); //~ ERROR can't pass `f32` to variadic function, cast to `c_double`
foo(1, 2, true); //~ ERROR can't pass `bool` to variadic function, cast to `c_int`
foo(1, 2, 1i8); //~ ERROR can't pass `i8` to variadic function, cast to `c_int`
foo(1, 2, 1u8); //~ ERROR can't pass `u8` to variadic function, cast to `c_uint`
foo(1, 2, 1i16); //~ ERROR can't pass `i16` to variadic function, cast to `c_int`
foo(1, 2, 1u16); //~ ERROR can't pass `u16` to variadic function, cast to `c_uint`
}
}

0 comments on commit a5dc963

Please sign in to comment.