Auto merge of #42644 - frewsxcv:rollup, r=frewsxcv
Rollup of 6 pull requests - Successful merges: #42408, #42428, #42496, #42597, #42636, #42638 - Failed merges: #42612
This commit is contained in:
commit
e40ef964fe
@ -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)
|
||||
|
@ -0,0 +1,7 @@
|
||||
# `ord-max-min`
|
||||
|
||||
The tracking issue for this feature is: [#25663]
|
||||
|
||||
[#25663]: https://github.com/rust-lang/rust/issues/25663
|
||||
|
||||
------------------------
|
@ -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; }
|
||||
|
@ -24,6 +24,7 @@
|
||||
#![feature(repr_align)]
|
||||
#![feature(slice_rotate)]
|
||||
#![feature(splice)]
|
||||
#![feature(str_checked_slicing)]
|
||||
#![feature(str_escape)]
|
||||
#![feature(test)]
|
||||
#![feature(unboxed_closures)]
|
||||
|
@ -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() {
|
||||
|
@ -443,6 +443,42 @@ pub trait Ord: Eq + PartialOrd<Self> {
|
||||
/// ```
|
||||
#[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")]
|
||||
@ -678,6 +714,8 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
|
||||
///
|
||||
/// Returns the first argument if the comparison determines them to be equal.
|
||||
///
|
||||
/// Internally uses an alias to `Ord::min`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
@ -689,13 +727,15 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn min<T: Ord>(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
|
||||
///
|
||||
/// ```
|
||||
@ -707,7 +747,7 @@ pub fn min<T: Ord>(v1: T, v2: T) -> T {
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn max<T: Ord>(v1: T, v2: T) -> T {
|
||||
if v2 >= v1 { v2 } else { v1 }
|
||||
v1.max(v2)
|
||||
}
|
||||
|
||||
// Implementation of PartialEq, Eq, PartialOrd and Ord for primitive types
|
||||
|
@ -1617,12 +1617,7 @@ mod traits {
|
||||
|
||||
#[inline]
|
||||
fn index(&self, index: ops::RangeTo<usize>) -> &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<ops::RangeTo<usize>> for str {
|
||||
#[inline]
|
||||
fn index_mut(&mut self, index: ops::RangeTo<usize>) -> &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<usize>) -> &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<ops::RangeFrom<usize>> for str {
|
||||
#[inline]
|
||||
fn index_mut(&mut self, index: ops::RangeFrom<usize>) -> &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<usize>) -> &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<usize>) -> &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<ops::RangeInclusive<usize>> for str {
|
||||
#[inline]
|
||||
fn index_mut(&mut self, index: ops::RangeInclusive<usize>) -> &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<ops::RangeToInclusive<usize>> for str {
|
||||
#[inline]
|
||||
fn index_mut(&mut self, index: ops::RangeToInclusive<usize>) -> &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 {
|
||||
@ -1945,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 {
|
||||
@ -1961,10 +1942,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)
|
||||
}
|
||||
}
|
||||
@ -1976,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
|
||||
@ -1984,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
|
||||
@ -2002,11 +1987,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 {
|
||||
|
@ -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);
|
||||
|
@ -26,6 +26,7 @@
|
||||
#![feature(iter_rfind)]
|
||||
#![feature(libc)]
|
||||
#![feature(nonzero)]
|
||||
#![feature(ord_max_min)]
|
||||
#![feature(rand)]
|
||||
#![feature(raw)]
|
||||
#![feature(sip_hash_13)]
|
||||
|
@ -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> {
|
||||
|
@ -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));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
@ -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! {
|
||||
|
@ -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;
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
|
32
src/test/compile-fail/E0617.rs
Normal file
32
src/test/compile-fail/E0617.rs
Normal file
@ -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]
|
||||
}
|
||||
}
|
@ -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`
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user