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:
bors 2017-06-14 00:40:10 +00:00
commit e40ef964fe
15 changed files with 233 additions and 86 deletions

View File

@ -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)

View File

@ -0,0 +1,7 @@
# `ord-max-min`
The tracking issue for this feature is: [#25663]
[#25663]: https://github.com/rust-lang/rust/issues/25663
------------------------

View File

@ -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; }

View File

@ -24,6 +24,7 @@
#![feature(repr_align)]
#![feature(slice_rotate)]
#![feature(splice)]
#![feature(str_checked_slicing)]
#![feature(str_escape)]
#![feature(test)]
#![feature(unboxed_closures)]

View File

@ -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() {

View File

@ -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

View File

@ -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 {

View File

@ -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);

View File

@ -26,6 +26,7 @@
#![feature(iter_rfind)]
#![feature(libc)]
#![feature(nonzero)]
#![feature(ord_max_min)]
#![feature(rand)]
#![feature(raw)]
#![feature(sip_hash_13)]

View File

@ -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> {

View File

@ -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));
}
_ => {}
}

View File

@ -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! {

View File

@ -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;
/// }
/// ```
///

View 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]
}
}

View File

@ -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`
}
}