From a5dc96397498cf2c0a05407320ff33d939b652e3 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 13 Jun 2017 21:37:13 +0200 Subject: [PATCH] Add E0617 --- src/librustc_typeck/check/mod.rs | 32 +++++++++---------------- src/librustc_typeck/diagnostics.rs | 21 ++++++++++++++++ src/test/compile-fail/E0617.rs | 32 +++++++++++++++++++++++++ src/test/compile-fail/variadic-ffi-3.rs | 12 +++++----- 4 files changed, 70 insertions(+), 27 deletions(-) create mode 100644 src/test/compile-fail/E0617.rs diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 880137f7c71b1..c12df083c30e6 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -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)); } _ => {} } diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 6ccfab0a324b6..76c664d7997a4 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -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! { diff --git a/src/test/compile-fail/E0617.rs b/src/test/compile-fail/E0617.rs new file mode 100644 index 0000000000000..7b769ff4ae2e0 --- /dev/null +++ b/src/test/compile-fail/E0617.rs @@ -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 or the MIT license +// , 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] + } +} diff --git a/src/test/compile-fail/variadic-ffi-3.rs b/src/test/compile-fail/variadic-ffi-3.rs index 565d8549b3729..fb102027180f0 100644 --- a/src/test/compile-fail/variadic-ffi-3.rs +++ b/src/test/compile-fail/variadic-ffi-3.rs @@ -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` } }