From 18612b21d05ce0021f9ef995592b158e181ffd90 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sun, 4 Jun 2017 01:47:21 -0700 Subject: [PATCH 1/8] Delegate str:Index(Mut) to SliceIndex Move any extra logic that the former had into the latter, so they're consistent. --- src/libcore/str/mod.rs | 55 ++++++++++++++---------------------------- 1 file changed, 18 insertions(+), 37 deletions(-) diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 547a4899c7118..76a5d0c0b50b1 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -1617,12 +1617,7 @@ mod traits { #[inline] fn index(&self, index: ops::RangeTo) -> &str { - // is_char_boundary checks that the index is in [0, .len()] - if self.is_char_boundary(index.end) { - unsafe { self.slice_unchecked(0, index.end) } - } else { - super::slice_error_fail(self, 0, index.end) - } + index.index(self) } } @@ -1636,12 +1631,7 @@ mod traits { impl ops::IndexMut> for str { #[inline] fn index_mut(&mut self, index: ops::RangeTo) -> &mut str { - // is_char_boundary checks that the index is in [0, .len()] - if self.is_char_boundary(index.end) { - unsafe { self.slice_mut_unchecked(0, index.end) } - } else { - super::slice_error_fail(self, 0, index.end) - } + index.index_mut(self) } } @@ -1657,12 +1647,7 @@ mod traits { #[inline] fn index(&self, index: ops::RangeFrom) -> &str { - // is_char_boundary checks that the index is in [0, .len()] - if self.is_char_boundary(index.start) { - unsafe { self.slice_unchecked(index.start, self.len()) } - } else { - super::slice_error_fail(self, index.start, self.len()) - } + index.index(self) } } @@ -1676,13 +1661,7 @@ mod traits { impl ops::IndexMut> for str { #[inline] fn index_mut(&mut self, index: ops::RangeFrom) -> &mut str { - // is_char_boundary checks that the index is in [0, .len()] - if self.is_char_boundary(index.start) { - let len = self.len(); - unsafe { self.slice_mut_unchecked(index.start, len) } - } else { - super::slice_error_fail(self, index.start, self.len()) - } + index.index_mut(self) } } @@ -1724,9 +1703,7 @@ mod traits { #[inline] fn index(&self, index: ops::RangeInclusive) -> &str { - assert!(index.end != usize::max_value(), - "attempted to index str up to maximum usize"); - self.index(index.start .. index.end+1) + index.index(self) } } @@ -1738,9 +1715,7 @@ mod traits { #[inline] fn index(&self, index: ops::RangeToInclusive) -> &str { - assert!(index.end != usize::max_value(), - "attempted to index str up to maximum usize"); - self.index(.. index.end+1) + index.index(self) } } @@ -1750,9 +1725,7 @@ mod traits { impl ops::IndexMut> for str { #[inline] fn index_mut(&mut self, index: ops::RangeInclusive) -> &mut str { - assert!(index.end != usize::max_value(), - "attempted to index str up to maximum usize"); - self.index_mut(index.start .. index.end+1) + index.index_mut(self) } } #[unstable(feature = "inclusive_range", @@ -1761,9 +1734,7 @@ mod traits { impl ops::IndexMut> for str { #[inline] fn index_mut(&mut self, index: ops::RangeToInclusive) -> &mut str { - assert!(index.end != usize::max_value(), - "attempted to index str up to maximum usize"); - self.index_mut(.. index.end+1) + index.index_mut(self) } } @@ -1886,6 +1857,7 @@ mod traits { } #[inline] fn index_mut(self, slice: &mut str) -> &mut Self::Output { + // is_char_boundary checks that the index is in [0, .len()] if slice.is_char_boundary(self.end) { unsafe { self.get_unchecked_mut(slice) } } else { @@ -1932,6 +1904,7 @@ mod traits { } #[inline] fn index_mut(self, slice: &mut str) -> &mut Self::Output { + // is_char_boundary checks that the index is in [0, .len()] if slice.is_char_boundary(self.start) { unsafe { self.get_unchecked_mut(slice) } } else { @@ -1961,10 +1934,14 @@ mod traits { } #[inline] fn index(self, slice: &str) -> &Self::Output { + assert!(self.end != usize::max_value(), + "attempted to index str up to maximum usize"); (self.start..self.end+1).index(slice) } #[inline] fn index_mut(self, slice: &mut str) -> &mut Self::Output { + assert!(self.end != usize::max_value(), + "attempted to index str up to maximum usize"); (self.start..self.end+1).index_mut(slice) } } @@ -2002,11 +1979,15 @@ mod traits { } #[inline] fn index(self, slice: &str) -> &Self::Output { + assert!(self.end != usize::max_value(), + "attempted to index str up to maximum usize"); let end = self.end + 1; self.get(slice).unwrap_or_else(|| super::slice_error_fail(slice, 0, end)) } #[inline] fn index_mut(self, slice: &mut str) -> &mut Self::Output { + assert!(self.end != usize::max_value(), + "attempted to index str up to maximum usize"); if slice.is_char_boundary(self.end) { unsafe { self.get_unchecked_mut(slice) } } else { From 808a08a363591abf754fafd93ec3f44c686486ec Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sun, 4 Jun 2017 11:08:25 -0700 Subject: [PATCH 2/8] Add overflow checking for str::get with inclusive ranges Fixes #42401 --- src/libcollections/tests/lib.rs | 1 + src/libcollections/tests/str.rs | 42 +++++++++++++++++++++++++++++++++ src/libcore/str/mod.rs | 16 +++++++++---- 3 files changed, 55 insertions(+), 4 deletions(-) diff --git a/src/libcollections/tests/lib.rs b/src/libcollections/tests/lib.rs index 8af8786994e40..f64a549a05d4d 100644 --- a/src/libcollections/tests/lib.rs +++ b/src/libcollections/tests/lib.rs @@ -22,6 +22,7 @@ #![feature(rand)] #![feature(slice_rotate)] #![feature(splice)] +#![feature(str_checked_slicing)] #![feature(str_escape)] #![feature(test)] #![feature(unboxed_closures)] diff --git a/src/libcollections/tests/str.rs b/src/libcollections/tests/str.rs index c9b7104fec4f0..9d8ca38b20e48 100644 --- a/src/libcollections/tests/str.rs +++ b/src/libcollections/tests/str.rs @@ -358,6 +358,48 @@ fn test_slice_fail() { &"中华Việt Nam"[0..2]; } +#[test] +#[should_panic] +fn test_str_slice_rangetoinclusive_max_panics() { + &"hello"[...usize::max_value()]; +} + +#[test] +#[should_panic] +fn test_str_slice_rangeinclusive_max_panics() { + &"hello"[1...usize::max_value()]; +} + +#[test] +#[should_panic] +fn test_str_slicemut_rangetoinclusive_max_panics() { + let mut s = "hello".to_owned(); + let s: &mut str = &mut s; + &mut s[...usize::max_value()]; +} + +#[test] +#[should_panic] +fn test_str_slicemut_rangeinclusive_max_panics() { + let mut s = "hello".to_owned(); + let s: &mut str = &mut s; + &mut s[1...usize::max_value()]; +} + +#[test] +fn test_str_get_maxinclusive() { + let mut s = "hello".to_owned(); + { + let s: &str = &s; + assert_eq!(s.get(...usize::max_value()), None); + assert_eq!(s.get(1...usize::max_value()), None); + } + { + let s: &mut str = &mut s; + assert_eq!(s.get(...usize::max_value()), None); + assert_eq!(s.get(1...usize::max_value()), None); + } +} #[test] fn test_is_char_boundary() { diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 76a5d0c0b50b1..34aca592b1e95 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -1918,11 +1918,19 @@ mod traits { type Output = str; #[inline] fn get(self, slice: &str) -> Option<&Self::Output> { - (self.start..self.end+1).get(slice) + if let Some(end) = self.end.checked_add(1) { + (self.start..end).get(slice) + } else { + None + } } #[inline] fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> { - (self.start..self.end+1).get_mut(slice) + if let Some(end) = self.end.checked_add(1) { + (self.start..end).get_mut(slice) + } else { + None + } } #[inline] unsafe fn get_unchecked(self, slice: &str) -> &Self::Output { @@ -1953,7 +1961,7 @@ mod traits { type Output = str; #[inline] fn get(self, slice: &str) -> Option<&Self::Output> { - if slice.is_char_boundary(self.end + 1) { + if self.end < usize::max_value() && slice.is_char_boundary(self.end + 1) { Some(unsafe { self.get_unchecked(slice) }) } else { None @@ -1961,7 +1969,7 @@ mod traits { } #[inline] fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> { - if slice.is_char_boundary(self.end + 1) { + if self.end < usize::max_value() && slice.is_char_boundary(self.end + 1) { Some(unsafe { self.get_unchecked_mut(slice) }) } else { None From 2cadc32b66e135eeb9ac22d433cd931b021792a5 Mon Sep 17 00:00:00 2001 From: Nick Whitney Date: Tue, 6 Jun 2017 01:31:46 -0400 Subject: [PATCH 3/8] Add max and min default fns to Ord trait Pursuant to issue #25663, this commit adds the max and min functions to the Ord trait, enabling items that implement Ord to use UFCS (ex. 1.max(2)) instead of the longer std::cmp::max(1,2) format. --- src/doc/unstable-book/src/SUMMARY.md | 1 + .../src/library-features/ord-max-min.md | 7 ++++ src/libcore/cmp.rs | 36 +++++++++++++++++++ src/libcore/tests/cmp.rs | 10 ++++++ src/libcore/tests/lib.rs | 1 + 5 files changed, 55 insertions(+) create mode 100644 src/doc/unstable-book/src/library-features/ord-max-min.md diff --git a/src/doc/unstable-book/src/SUMMARY.md b/src/doc/unstable-book/src/SUMMARY.md index 2b3ef338fad58..b278b5dbb2ca6 100644 --- a/src/doc/unstable-book/src/SUMMARY.md +++ b/src/doc/unstable-book/src/SUMMARY.md @@ -165,6 +165,7 @@ - [n16](library-features/n16.md) - [never_type_impls](library-features/never-type-impls.md) - [nonzero](library-features/nonzero.md) + - [ord_max_min](library-features/ord-max-min.md) - [offset_to](library-features/offset-to.md) - [once_poison](library-features/once-poison.md) - [oom](library-features/oom.md) diff --git a/src/doc/unstable-book/src/library-features/ord-max-min.md b/src/doc/unstable-book/src/library-features/ord-max-min.md new file mode 100644 index 0000000000000..564cd1ac30b26 --- /dev/null +++ b/src/doc/unstable-book/src/library-features/ord-max-min.md @@ -0,0 +1,7 @@ +# `ord-max-min` + +The tracking issue for this feature is: [#25663] + +[#25663]: https://github.com/rust-lang/rust/issues/25663 + +------------------------ diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 661cf73c7f30e..4c50b11e70507 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -443,6 +443,42 @@ pub trait Ord: Eq + PartialOrd { /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn cmp(&self, other: &Self) -> Ordering; + + /// Compares and returns the maximum of two values. + /// + /// Returns the second argument if the comparison determines them to be equal. + /// + /// # Examples + /// + /// ``` + /// #![feature(ord_max_min)] + /// + /// assert_eq!(2, 1.max(2)); + /// assert_eq!(2, 2.max(2)); + /// ``` + #[unstable(feature = "ord_max_min", issue = "25663")] + fn max(self, other: Self) -> Self + where Self: Sized { + if other >= self { other } else { self } + } + + /// Compares and returns the minimum of two values. + /// + /// Returns the first argument if the comparison determines them to be equal. + /// + /// # Examples + /// + /// ``` + /// #![feature(ord_max_min)] + /// + /// assert_eq!(1, 1.min(2)); + /// assert_eq!(2, 2.min(2)); + /// ``` + #[unstable(feature = "ord_max_min", issue = "25663")] + fn min(self, other: Self) -> Self + where Self: Sized { + if self <= other { self } else { other } + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/tests/cmp.rs b/src/libcore/tests/cmp.rs index e3c65ad8b33c0..8c5179f59932b 100644 --- a/src/libcore/tests/cmp.rs +++ b/src/libcore/tests/cmp.rs @@ -28,6 +28,16 @@ fn test_mut_int_totalord() { assert_eq!((&mut 12).cmp(&&mut -5), Greater); } +#[test] +fn test_ord_max_min() { + assert_eq!(1.max(2), 2); + assert_eq!(2.max(1), 2); + assert_eq!(1.min(2), 1); + assert_eq!(2.min(1), 1); + assert_eq!(1.max(1), 1); + assert_eq!(1.min(1), 1); +} + #[test] fn test_ordering_reverse() { assert_eq!(Less.reverse(), Greater); diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 505e51fa80b33..77a9307f43ecf 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -26,6 +26,7 @@ #![feature(iter_rfind)] #![feature(libc)] #![feature(nonzero)] +#![feature(ord_max_min)] #![feature(rand)] #![feature(raw)] #![feature(sip_hash_13)] From a32ffc679702e3ae307c7fc20873c9e970a8894c Mon Sep 17 00:00:00 2001 From: Nick Whitney Date: Tue, 6 Jun 2017 23:00:09 -0400 Subject: [PATCH 4/8] Alias std::cmp::max/min to Ord::max/min --- src/libcore/cmp.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 4c50b11e70507..6f35d0417f18b 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -714,6 +714,8 @@ pub trait PartialOrd: PartialEq { /// /// Returns the first argument if the comparison determines them to be equal. /// +/// Internally uses an alias to `Ord::min`. +/// /// # Examples /// /// ``` @@ -725,13 +727,15 @@ pub trait PartialOrd: PartialEq { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn min(v1: T, v2: T) -> T { - if v1 <= v2 { v1 } else { v2 } + v1.min(v2) } /// Compares and returns the maximum of two values. /// /// Returns the second argument if the comparison determines them to be equal. /// +/// Internally uses an alias to `Ord::max`. +/// /// # Examples /// /// ``` @@ -743,7 +747,7 @@ pub fn min(v1: T, v2: T) -> T { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn max(v1: T, v2: T) -> T { - if v2 >= v1 { v2 } else { v1 } + v1.max(v2) } // Implementation of PartialEq, Eq, PartialOrd and Ord for primitive types From 0389d40ce0a891bc7d37ca15c12e23df79d71524 Mon Sep 17 00:00:00 2001 From: Mark Buer Date: Mon, 12 Jun 2017 13:33:25 +0930 Subject: [PATCH 5/8] Capture elapsed duration in Thread::park_timeout example --- src/libstd/thread/mod.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 64c31c2a681cf..dda11e50380f5 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -787,12 +787,16 @@ pub fn park_timeout_ms(ms: u32) { /// /// let timeout = Duration::from_secs(2); /// let beginning_park = Instant::now(); -/// park_timeout(timeout); /// -/// while beginning_park.elapsed() < timeout { -/// println!("restarting park_timeout after {:?}", beginning_park.elapsed()); -/// let timeout = timeout - beginning_park.elapsed(); -/// park_timeout(timeout); +/// let mut timeout_remaining = timeout; +/// loop { +/// park_timeout(timeout_remaining); +/// let elapsed = beginning_park.elapsed(); +/// if elapsed >= timeout { +/// break; +/// } +/// println!("restarting park_timeout after {:?}", elapsed); +/// timeout_remaining = timeout - elapsed; /// } /// ``` /// From e75937022e9df6ade583b11ee44038ef32d1299a Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 3 Jun 2017 18:14:29 +0200 Subject: [PATCH 6/8] Add docs to librustc/hir/check_attr.rs --- src/librustc/hir/check_attr.rs | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs index f553c03d09bd6..3034242b59408 100644 --- a/src/librustc/hir/check_attr.rs +++ b/src/librustc/hir/check_attr.rs @@ -8,6 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//! This module implements some validity checks for attributes. +//! In particular it verifies that `#[inline]` and `#[repr]` attributes are +//! attached to items that actually support them and if there are +//! conflicts between multiple such attributes attached to the same +//! item. + use session::Session; use syntax::ast; @@ -40,6 +46,18 @@ struct CheckAttrVisitor<'a> { } impl<'a> CheckAttrVisitor<'a> { + /// Check any attribute. + fn check_attribute(&self, attr: &ast::Attribute, target: Target) { + if let Some(name) = attr.name() { + match &*name.as_str() { + "inline" => self.check_inline(attr, target), + "repr" => self.check_repr(attr, target), + _ => (), + } + } + } + + /// Check if an `#[inline]` is applied to a function. fn check_inline(&self, attr: &ast::Attribute, target: Target) { if target != Target::Fn { struct_span_err!(self.sess, attr.span, E0518, "attribute should be applied to function") @@ -48,6 +66,7 @@ impl<'a> CheckAttrVisitor<'a> { } } + /// Check if an `#[repr]` attr is valid. fn check_repr(&self, attr: &ast::Attribute, target: Target) { let words = match attr.meta_item_list() { Some(words) => words, @@ -135,16 +154,6 @@ impl<'a> CheckAttrVisitor<'a> { "conflicting packed and align representation hints").emit(); } } - - fn check_attribute(&self, attr: &ast::Attribute, target: Target) { - if let Some(name) = attr.name() { - match &*name.as_str() { - "inline" => self.check_inline(attr, target), - "repr" => self.check_repr(attr, target), - _ => (), - } - } - } } impl<'a> Visitor<'a> for CheckAttrVisitor<'a> { From c291e87dae377c3632c6731d618ef1433d79b041 Mon Sep 17 00:00:00 2001 From: Arthur Arnold Date: Tue, 13 Jun 2017 17:08:12 -0300 Subject: [PATCH 7/8] changed upper bound digit in octal rule to 7 --- src/grammar/lexer.l | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/grammar/lexer.l b/src/grammar/lexer.l index 77737c99496f3..91652bfdf2467 100644 --- a/src/grammar/lexer.l +++ b/src/grammar/lexer.l @@ -126,7 +126,7 @@ while { return WHILE; } {ident} { return IDENT; } 0x[0-9a-fA-F_]+ { BEGIN(suffix); return LIT_INTEGER; } -0o[0-8_]+ { BEGIN(suffix); return LIT_INTEGER; } +0o[0-7_]+ { BEGIN(suffix); return LIT_INTEGER; } 0b[01_]+ { BEGIN(suffix); return LIT_INTEGER; } [0-9][0-9_]* { BEGIN(suffix); return LIT_INTEGER; } [0-9][0-9_]*\.(\.|[a-zA-Z]) { yyless(yyleng - 2); BEGIN(suffix); return LIT_INTEGER; } From a5dc96397498cf2c0a05407320ff33d939b652e3 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 13 Jun 2017 21:37:13 +0200 Subject: [PATCH 8/8] 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` } }