about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume1.gomez@gmail.com>2017-06-13 21:37:13 +0200
committerGuillaume Gomez <guillaume1.gomez@gmail.com>2017-06-13 23:10:43 +0200
commita5dc96397498cf2c0a05407320ff33d939b652e3 (patch)
treecf7e1a494b4ecb2e8ad15dbebe0f51aea5adc4c6
parent03abb1bd70ac56e4aba0684bab819892a0157843 (diff)
downloadrust-a5dc96397498cf2c0a05407320ff33d939b652e3.tar.gz
rust-a5dc96397498cf2c0a05407320ff33d939b652e3.zip
Add E0617
-rw-r--r--src/librustc_typeck/check/mod.rs32
-rw-r--r--src/librustc_typeck/diagnostics.rs21
-rw-r--r--src/test/compile-fail/E0617.rs32
-rw-r--r--src/test/compile-fail/variadic-ffi-3.rs12
4 files changed, 70 insertions, 27 deletions
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 880137f7c71..c12df083c30 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 6ccfab0a324..76c664d7997 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 00000000000..7b769ff4ae2
--- /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 <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]
+    }
+}
diff --git a/src/test/compile-fail/variadic-ffi-3.rs b/src/test/compile-fail/variadic-ffi-3.rs
index 565d8549b37..fb102027180 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`
     }
 }