Skip to content

Commit

Permalink
Auto merge of #51859 - kennytm:rollup, r=kennytm
Browse files Browse the repository at this point in the history
Rollup of 7 pull requests

Successful merges:

 - #49987 (Add str::split_ascii_whitespace.)
 - #50342 (Document round-off error in `.mod_euc()`-method, see issue #50179)
 - #51658 (Only do sanity check with debug assertions on)
 - #51799 (Lower case some feature gate error messages)
 - #51800 (Add a compiletest header for edition)
 - #51824 (Fix the error reference for LocalKey::try_with)
 - #51842 (Document that Layout::from_size_align does not allow align=0)

Failed merges:

r? @ghost
  • Loading branch information
bors committed Jun 27, 2018
2 parents cd494c1 + 99a0d6b commit 266afeb
Show file tree
Hide file tree
Showing 52 changed files with 271 additions and 67 deletions.
1 change: 1 addition & 0 deletions src/liballoc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@
#![cfg_attr(stage0, feature(repr_transparent))]
#![feature(rustc_attrs)]
#![feature(specialization)]
#![feature(split_ascii_whitespace)]
#![feature(staged_api)]
#![feature(str_internals)]
#![feature(trusted_len)]
Expand Down
2 changes: 2 additions & 0 deletions src/liballoc/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ pub use core::str::SplitWhitespace;
pub use core::str::pattern;
#[stable(feature = "encode_utf16", since = "1.8.0")]
pub use core::str::EncodeUtf16;
#[unstable(feature = "split_ascii_whitespace", issue = "48656")]
pub use core::str::SplitAsciiWhitespace;

#[unstable(feature = "slice_concat_ext",
reason = "trait should not have to exist",
Expand Down
2 changes: 2 additions & 0 deletions src/libcore/alloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ impl Layout {
/// or returns `LayoutErr` if either of the following conditions
/// are not met:
///
/// * `align` must not be zero,
///
/// * `align` must be a power of two,
///
/// * `size`, when rounded up to the nearest multiple of `align`,
Expand Down
159 changes: 155 additions & 4 deletions src/libcore/str/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use char;
use fmt;
use iter::{Map, Cloned, FusedIterator, TrustedLen, Filter};
use iter_private::TrustedRandomAccess;
use slice::{self, SliceIndex};
use slice::{self, SliceIndex, Split as SliceSplit};
use mem;

pub mod pattern;
Expand Down Expand Up @@ -2722,7 +2722,10 @@ impl str {
/// the original string slice, separated by any amount of whitespace.
///
/// 'Whitespace' is defined according to the terms of the Unicode Derived
/// Core Property `White_Space`.
/// Core Property `White_Space`. If you only want to split on ASCII whitespace
/// instead, use [`split_ascii_whitespace`].
///
/// [`split_ascii_whitespace`]: #method.split_ascii_whitespace
///
/// # Examples
///
Expand Down Expand Up @@ -2756,6 +2759,53 @@ impl str {
SplitWhitespace { inner: self.split(IsWhitespace).filter(IsNotEmpty) }
}

/// Split a string slice by ASCII whitespace.
///
/// The iterator returned will return string slices that are sub-slices of
/// the original string slice, separated by any amount of ASCII whitespace.
///
/// To split by Unicode `Whitespace` instead, use [`split_whitespace`].
///
/// [`split_whitespace`]: #method.split_whitespace
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(split_ascii_whitespace)]
/// let mut iter = "A few words".split_ascii_whitespace();
///
/// assert_eq!(Some("A"), iter.next());
/// assert_eq!(Some("few"), iter.next());
/// assert_eq!(Some("words"), iter.next());
///
/// assert_eq!(None, iter.next());
/// ```
///
/// All kinds of ASCII whitespace are considered:
///
/// ```
/// let mut iter = " Mary had\ta little \n\t lamb".split_whitespace();
/// assert_eq!(Some("Mary"), iter.next());
/// assert_eq!(Some("had"), iter.next());
/// assert_eq!(Some("a"), iter.next());
/// assert_eq!(Some("little"), iter.next());
/// assert_eq!(Some("lamb"), iter.next());
///
/// assert_eq!(None, iter.next());
/// ```
#[unstable(feature = "split_ascii_whitespace", issue = "48656")]
#[inline]
pub fn split_ascii_whitespace(&self) -> SplitAsciiWhitespace {
let inner = self
.as_bytes()
.split(IsAsciiWhitespace)
.filter(IsNotEmpty)
.map(UnsafeBytesToStr);
SplitAsciiWhitespace { inner }
}

/// An iterator over the lines of a string, as string slices.
///
/// Lines are ended with either a newline (`\n`) or a carriage return with
Expand Down Expand Up @@ -3895,6 +3945,20 @@ pub struct SplitWhitespace<'a> {
inner: Filter<Split<'a, IsWhitespace>, IsNotEmpty>,
}

/// An iterator over the non-ASCII-whitespace substrings of a string,
/// separated by any amount of ASCII whitespace.
///
/// This struct is created by the [`split_ascii_whitespace`] method on [`str`].
/// See its documentation for more.
///
/// [`split_ascii_whitespace`]: ../../std/primitive.str.html#method.split_ascii_whitespace
/// [`str`]: ../../std/primitive.str.html
#[unstable(feature = "split_ascii_whitespace", issue = "48656")]
#[derive(Clone, Debug)]
pub struct SplitAsciiWhitespace<'a> {
inner: Map<Filter<SliceSplit<'a, u8, IsAsciiWhitespace>, IsNotEmpty>, UnsafeBytesToStr>,
}

#[derive(Clone)]
struct IsWhitespace;

Expand All @@ -3914,37 +3978,98 @@ impl FnMut<(char, )> for IsWhitespace {
}
}

#[derive(Clone)]
struct IsAsciiWhitespace;

impl<'a> FnOnce<(&'a u8, )> for IsAsciiWhitespace {
type Output = bool;

#[inline]
extern "rust-call" fn call_once(mut self, arg: (&u8, )) -> bool {
self.call_mut(arg)
}
}

impl<'a> FnMut<(&'a u8, )> for IsAsciiWhitespace {
#[inline]
extern "rust-call" fn call_mut(&mut self, arg: (&u8, )) -> bool {
arg.0.is_ascii_whitespace()
}
}

#[derive(Clone)]
struct IsNotEmpty;

impl<'a, 'b> FnOnce<(&'a &'b str, )> for IsNotEmpty {
type Output = bool;

#[inline]
extern "rust-call" fn call_once(mut self, arg: (&&str, )) -> bool {
extern "rust-call" fn call_once(mut self, arg: (&'a &'b str, )) -> bool {
self.call_mut(arg)
}
}

impl<'a, 'b> FnMut<(&'a &'b str, )> for IsNotEmpty {
#[inline]
extern "rust-call" fn call_mut(&mut self, arg: (&&str, )) -> bool {
extern "rust-call" fn call_mut(&mut self, arg: (&'a &'b str, )) -> bool {
!arg.0.is_empty()
}
}

impl<'a, 'b> FnOnce<(&'a &'b [u8], )> for IsNotEmpty {
type Output = bool;

#[inline]
extern "rust-call" fn call_once(mut self, arg: (&'a &'b [u8], )) -> bool {
self.call_mut(arg)
}
}

impl<'a, 'b> FnMut<(&'a &'b [u8], )> for IsNotEmpty {
#[inline]
extern "rust-call" fn call_mut(&mut self, arg: (&'a &'b [u8], )) -> bool {
!arg.0.is_empty()
}
}

#[derive(Clone)]
struct UnsafeBytesToStr;

impl<'a> FnOnce<(&'a [u8], )> for UnsafeBytesToStr {
type Output = &'a str;

#[inline]
extern "rust-call" fn call_once(mut self, arg: (&'a [u8], )) -> &'a str {
self.call_mut(arg)
}
}

impl<'a> FnMut<(&'a [u8], )> for UnsafeBytesToStr {
#[inline]
extern "rust-call" fn call_mut(&mut self, arg: (&'a [u8], )) -> &'a str {
unsafe { from_utf8_unchecked(arg.0) }
}
}


#[stable(feature = "split_whitespace", since = "1.1.0")]
impl<'a> Iterator for SplitWhitespace<'a> {
type Item = &'a str;

#[inline]
fn next(&mut self) -> Option<&'a str> {
self.inner.next()
}

#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}

#[stable(feature = "split_whitespace", since = "1.1.0")]
impl<'a> DoubleEndedIterator for SplitWhitespace<'a> {
#[inline]
fn next_back(&mut self) -> Option<&'a str> {
self.inner.next_back()
}
Expand All @@ -3953,6 +4078,32 @@ impl<'a> DoubleEndedIterator for SplitWhitespace<'a> {
#[stable(feature = "fused", since = "1.26.0")]
impl<'a> FusedIterator for SplitWhitespace<'a> {}

#[unstable(feature = "split_ascii_whitespace", issue = "48656")]
impl<'a> Iterator for SplitAsciiWhitespace<'a> {
type Item = &'a str;

#[inline]
fn next(&mut self) -> Option<&'a str> {
self.inner.next()
}

#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}

#[unstable(feature = "split_ascii_whitespace", issue = "48656")]
impl<'a> DoubleEndedIterator for SplitAsciiWhitespace<'a> {
#[inline]
fn next_back(&mut self) -> Option<&'a str> {
self.inner.next_back()
}
}

#[unstable(feature = "split_ascii_whitespace", issue = "48656")]
impl<'a> FusedIterator for SplitAsciiWhitespace<'a> {}

/// An iterator of [`u16`] over the string encoded as UTF-16.
///
/// [`u16`]: ../../std/primitive.u16.html
Expand Down
19 changes: 19 additions & 0 deletions src/libcore/tests/num/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,25 @@ macro_rules! test_float {
assert_eq!((-9.0 as $fty).max($nan), -9.0);
assert!(($nan as $fty).max($nan).is_nan());
}
#[test]
fn mod_euc() {
let a: $fty = 42.0;
assert!($inf.mod_euc(a).is_nan());
assert_eq!(a.mod_euc($inf), a);
assert!(a.mod_euc($nan).is_nan());
assert!($inf.mod_euc($inf).is_nan());
assert!($inf.mod_euc($nan).is_nan());
assert!($nan.mod_euc($inf).is_nan());
}
#[test]
fn div_euc() {
let a: $fty = 42.0;
assert_eq!(a.div_euc($inf), 0.0);
assert!(a.div_euc($nan).is_nan());
assert!($inf.div_euc($inf).is_nan());
assert!($inf.div_euc($nan).is_nan());
assert!($nan.div_euc($inf).is_nan());
}
} }
}

Expand Down
6 changes: 3 additions & 3 deletions src/librustc/traits/query/normalize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,10 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx
let concrete_ty = generic_ty.subst(self.tcx(), substs);
self.anon_depth += 1;
if concrete_ty == ty {
println!("generic_ty: {:#?}", generic_ty);
println!("substs {:#?}", substs);
bug!("infinite recursion generic_ty: {:#?}, substs: {:#?}, \
concrete_ty: {:#?}, ty: {:#?}", generic_ty, substs, concrete_ty,
ty);
}
assert_ne!(concrete_ty, ty, "infinite recursion");
let folded_ty = self.fold_ty(concrete_ty);
self.anon_depth -= 1;
folded_ty
Expand Down
11 changes: 10 additions & 1 deletion src/libstd/f32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,14 @@ impl f32 {

/// Calculates the Euclidean modulo (self mod rhs), which is never negative.
///
/// In particular, the result `n` satisfies `0 <= n < rhs.abs()`.
/// In particular, the return value `r` satisfies `0.0 <= r < rhs.abs()` in
/// most cases. However, due to a floating point round-off error it can
/// result in `r == rhs.abs()`, violating the mathematical definition, if
/// `self` is much smaller than `rhs.abs()` in magnitude and `self < 0.0`.
/// This result is not an element of the function's codomain, but it is the
/// closest floating point number in the real numbers and thus fulfills the
/// property `self == self.div_euc(rhs) * rhs + self.mod_euc(rhs)`
/// approximatively.
///
/// # Examples
///
Expand All @@ -266,6 +273,8 @@ impl f32 {
/// assert_eq!((-a).mod_euc(b), 1.0);
/// assert_eq!(a.mod_euc(-b), 3.0);
/// assert_eq!((-a).mod_euc(-b), 1.0);
/// // limitation due to round-off error
/// assert!((-std::f32::EPSILON).mod_euc(3.0) != 0.0);
/// ```
#[inline]
#[unstable(feature = "euclidean_division", issue = "49048")]
Expand Down
11 changes: 10 additions & 1 deletion src/libstd/f64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,14 @@ impl f64 {

/// Calculates the Euclidean modulo (self mod rhs), which is never negative.
///
/// In particular, the result `n` satisfies `0 <= n < rhs.abs()`.
/// In particular, the return value `r` satisfies `0.0 <= r < rhs.abs()` in
/// most cases. However, due to a floating point round-off error it can
/// result in `r == rhs.abs()`, violating the mathematical definition, if
/// `self` is much smaller than `rhs.abs()` in magnitude and `self < 0.0`.
/// This result is not an element of the function's codomain, but it is the
/// closest floating point number in the real numbers and thus fulfills the
/// property `self == self.div_euc(rhs) * rhs + self.mod_euc(rhs)`
/// approximatively.
///
/// # Examples
///
Expand All @@ -242,6 +249,8 @@ impl f64 {
/// assert_eq!((-a).mod_euc(b), 1.0);
/// assert_eq!(a.mod_euc(-b), 3.0);
/// assert_eq!((-a).mod_euc(-b), 1.0);
/// // limitation due to round-off error
/// assert!((-std::f64::EPSILON).mod_euc(3.0) != 0.0);
/// ```
#[inline]
#[unstable(feature = "euclidean_division", issue = "49048")]
Expand Down
2 changes: 1 addition & 1 deletion src/libstd/thread/local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ impl<T: 'static> LocalKey<T> {
///
/// This will lazily initialize the value if this thread has not referenced
/// this key yet. If the key has been destroyed (which may happen if this is called
/// in a destructor), this function will return a `ThreadLocalError`.
/// in a destructor), this function will return an [`AccessError`](struct.AccessError.html).
///
/// # Panics
///
Expand Down
8 changes: 4 additions & 4 deletions src/libsyntax/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1359,17 +1359,17 @@ pub const EXPLAIN_LITERAL_MATCHER: &'static str =
":literal fragment specifier is experimental and subject to change";

pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &'static str =
"Unsized tuple coercion is not stable enough for use and is subject to change";
"unsized tuple coercion is not stable enough for use and is subject to change";

pub const EXPLAIN_MACRO_AT_MOST_ONCE_REP: &'static str =
"Using the `?` macro Kleene operator for \"at most one\" repetition is unstable";
"using the `?` macro Kleene operator for \"at most one\" repetition is unstable";

pub const EXPLAIN_MACROS_IN_EXTERN: &'static str =
"Macro invocations in `extern {}` blocks are experimental.";
"macro invocations in `extern {}` blocks are experimental.";

// mention proc-macros when enabled
pub const EXPLAIN_PROC_MACROS_IN_EXTERN: &'static str =
"Macro and proc-macro invocations in `extern {}` blocks are experimental.";
"macro and proc-macro invocations in `extern {}` blocks are experimental.";

struct PostExpansionVisitor<'a> {
context: &'a Context<'a>,
Expand Down
6 changes: 3 additions & 3 deletions src/test/compile-fail-fulldeps/proc-macro/macros-in-extern.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ fn main() {
#[link(name = "rust_test_helpers", kind = "static")]
extern {
#[no_output]
//~^ ERROR Macro and proc-macro invocations in `extern {}` blocks are experimental.
//~^ ERROR macro and proc-macro invocations in `extern {}` blocks are experimental.
fn some_definitely_unknown_symbol_which_should_be_removed();

#[nop_attr]
//~^ ERROR Macro and proc-macro invocations in `extern {}` blocks are experimental.
//~^ ERROR macro and proc-macro invocations in `extern {}` blocks are experimental.
fn rust_get_test_int() -> isize;

emit_input!(fn rust_dbg_extern_identity_u32(arg: u32) -> u32;);
//~^ ERROR Macro and proc-macro invocations in `extern {}` blocks are experimental.
//~^ ERROR macro and proc-macro invocations in `extern {}` blocks are experimental.
}
Loading

0 comments on commit 266afeb

Please sign in to comment.