[[package]]
name = "minifier"
-version = "0.0.11"
+version = "0.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
name = "rustdoc"
version = "0.0.0"
dependencies = [
- "minifier 0.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "minifier 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
"pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"tempfile 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
"checksum mdbook 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "90b5a8d7e341ceee5db3882a06078d42661ddcfa2b3687319cc5da76ec4e782f"
"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d"
"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3"
-"checksum minifier 0.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "26f3e36a4db1981b16567e4abfd6ddc3641bc9b950bdc868701f656bf9b74bdd"
+"checksum minifier 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "78cb57f9a385530d60f2d67f6e108050b478b7a0ffd0bb9c350803e1356535dd"
"checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4"
"checksum miow 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9224c91f82b3c47cf53dcf78dfaa20d6888fbcc5d272d5f2fcdf8a697f3c987d"
"checksum nibble_vec 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c8d77f3db4bce033f4d04db08079b2ef1c3d02b44e86f25d08886fafa7756ffa"
/// Whether this tool requires LLVM to run
pub fn uses_llvm_tools(&self) -> bool {
match self {
- $(Tool::$name => true $(&& $llvm)*,)+
+ $(Tool::$name => false $(|| $llvm)*,)+
}
}
}
}
}
-// FIXME(#51459): We have only checked that RustInstaller does not require
-// the LLVM binaries when running. We should go through all tools to determine
-// if they really need LLVM binaries, and make `llvm_tools` a required argument.
tool!(
Rustbook, "src/tools/rustbook", "rustbook", Mode::ToolRustc;
ErrorIndex, "src/tools/error_index_generator", "error_index_generator", Mode::ToolRustc;
Tidy, "src/tools/tidy", "tidy", Mode::ToolStd;
Linkchecker, "src/tools/linkchecker", "linkchecker", Mode::ToolStd;
CargoTest, "src/tools/cargotest", "cargotest", Mode::ToolStd;
- Compiletest, "src/tools/compiletest", "compiletest", Mode::ToolTest;
+ Compiletest, "src/tools/compiletest", "compiletest", Mode::ToolTest, llvm_tools = true;
BuildManifest, "src/tools/build-manifest", "build-manifest", Mode::ToolStd;
RemoteTestClient, "src/tools/remote-test-client", "remote-test-client", Mode::ToolStd;
- RustInstaller, "src/tools/rust-installer", "fabricate", Mode::ToolStd, llvm_tools = false;
+ RustInstaller, "src/tools/rust-installer", "fabricate", Mode::ToolStd;
RustdocTheme, "src/tools/rustdoc-themes", "rustdoc-themes", Mode::ToolStd;
);
--- /dev/null
+# `irrefutable_let_patterns`
+
+The tracking issue for this feature is: [#44495]
+
+[#44495]: https://github.com/rust-lang/rust/issues/44495
+
+------------------------
+
+This feature changes the way that "irrefutable patterns" are handled
+in the `if let` and `while let` forms. An *irrefutable pattern* is one
+that cannot fail to match -- for example, the `_` pattern matches any
+value, and hence it is "irrefutable". Without this feature, using an
+irrefutable pattern in an `if let` gives a hard error (since often
+this indicates programmer error). But when the feature is enabled, the
+error becomes a lint (since in some cases irrefutable patterns are
+expected). This means you can use `#[allow]` to silence the lint:
+
+```rust
+#![feature(irrefutable_let_patterns)]
+
+#[allow(irrefutable_let_patterns)]
+fn main() {
+ // These two examples used to be errors, but now they
+ // trigger a lint (that is allowed):
+ if let _ = 5 {}
+ while let _ = 5 { break; }
+}
+```
use core::mem::{self, PinMut};
use core::ops::{CoerceUnsized, Deref, DerefMut, Generator, GeneratorState};
use core::ptr::{self, NonNull, Unique};
-use core::task::{Context, Poll, UnsafeTask, TaskObj};
+use core::task::{Context, Poll, UnsafeTask, TaskObj, LocalTaskObj};
use core::convert::From;
use raw_vec::RawVec;
}
#[unstable(feature = "futures_api", issue = "50547")]
-unsafe impl<F: Future<Output = ()> + Send + 'static> UnsafeTask for PinBox<F> {
+unsafe impl<F: Future<Output = ()> + 'static> UnsafeTask for PinBox<F> {
fn into_raw(self) -> *mut () {
PinBox::into_raw(self) as *mut ()
}
TaskObj::new(PinBox::from(boxed))
}
}
+
+#[unstable(feature = "futures_api", issue = "50547")]
+impl<F: Future<Output = ()> + 'static> From<PinBox<F>> for LocalTaskObj {
+ fn from(boxed: PinBox<F>) -> Self {
+ LocalTaskObj::new(boxed)
+ }
+}
+
+#[unstable(feature = "futures_api", issue = "50547")]
+impl<F: Future<Output = ()> + 'static> From<Box<F>> for LocalTaskObj {
+ fn from(boxed: Box<F>) -> Self {
+ LocalTaskObj::new(PinBox::from(boxed))
+ }
+}
#![cfg_attr(stage0, feature(repr_transparent))]
#![feature(rustc_attrs)]
#![feature(specialization)]
+#![feature(split_ascii_whitespace)]
#![feature(staged_api)]
#![feature(str_internals)]
#![feature(trusted_len)]
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",
b'\\' => ([b'\\', b'\\', 0, 0], 2),
b'\'' => ([b'\\', b'\'', 0, 0], 2),
b'"' => ([b'\\', b'"', 0, 0], 2),
- b'\x20' ... b'\x7e' => ([c, 0, 0, 0], 1),
+ b'\x20' ..= b'\x7e' => ([c, 0, 0, 0], 1),
_ => ([b'\\', b'x', hexify(c >> 4), hexify(c & 0xf)], 4),
};
fn hexify(b: u8) -> u8 {
match b {
- 0 ... 9 => b'0' + b,
+ 0 ..= 9 => b'0' + b,
_ => b'a' + b - 10,
}
}
}
}
macro_rules! continuation_byte {
- () => { continuation_byte!(0x80...0xBF) };
+ () => { continuation_byte!(0x80..=0xBF) };
($range: pat) => {
match self.0.peek() {
Some(&byte @ $range) => {
}
match first_byte {
- 0x00...0x7F => {
+ 0x00..=0x7F => {
first_byte!(0b1111_1111);
}
- 0xC2...0xDF => {
+ 0xC2..=0xDF => {
first_byte!(0b0001_1111);
continuation_byte!();
}
0xE0 => {
first_byte!(0b0000_1111);
- continuation_byte!(0xA0...0xBF); // 0x80...0x9F here are overlong
+ continuation_byte!(0xA0..=0xBF); // 0x80..=0x9F here are overlong
continuation_byte!();
}
- 0xE1...0xEC | 0xEE...0xEF => {
+ 0xE1..=0xEC | 0xEE..=0xEF => {
first_byte!(0b0000_1111);
continuation_byte!();
continuation_byte!();
}
0xED => {
first_byte!(0b0000_1111);
- continuation_byte!(0x80...0x9F); // 0xA0..0xBF here are surrogates
+ continuation_byte!(0x80..=0x9F); // 0xA0..0xBF here are surrogates
continuation_byte!();
}
0xF0 => {
first_byte!(0b0000_0111);
- continuation_byte!(0x90...0xBF); // 0x80..0x8F here are overlong
+ continuation_byte!(0x90..=0xBF); // 0x80..0x8F here are overlong
continuation_byte!();
continuation_byte!();
}
- 0xF1...0xF3 => {
+ 0xF1..=0xF3 => {
first_byte!(0b0000_0111);
continuation_byte!();
continuation_byte!();
}
0xF4 => {
first_byte!(0b0000_0111);
- continuation_byte!(0x80...0x8F); // 0x90..0xBF here are beyond char::MAX
+ continuation_byte!(0x80..=0x8F); // 0x90..0xBF here are beyond char::MAX
continuation_byte!();
continuation_byte!();
}
panic!("to_digit: radix is too high (maximum 36)");
}
let val = match self {
- '0' ... '9' => self as u32 - '0' as u32,
- 'a' ... 'z' => self as u32 - 'a' as u32 + 10,
- 'A' ... 'Z' => self as u32 - 'A' as u32 + 10,
+ '0' ..= '9' => self as u32 - '0' as u32,
+ 'a' ..= 'z' => self as u32 - 'a' as u32 + 10,
+ 'A' ..= 'Z' => self as u32 - 'A' as u32 + 10,
_ => return None,
};
if val < radix { Some(val) }
'\r' => EscapeDefaultState::Backslash('r'),
'\n' => EscapeDefaultState::Backslash('n'),
'\\' | '\'' | '"' => EscapeDefaultState::Backslash(self),
- '\x20' ... '\x7e' => EscapeDefaultState::Char(self),
+ '\x20' ..= '\x7e' => EscapeDefaultState::Char(self),
_ => EscapeDefaultState::Unicode(self.escape_unicode())
};
EscapeDefault { state: init_state }
#[inline]
pub fn is_alphabetic(self) -> bool {
match self {
- 'a'...'z' | 'A'...'Z' => true,
+ 'a'..='z' | 'A'..='Z' => true,
c if c > '\x7f' => derived_property::Alphabetic(c),
_ => false,
}
#[inline]
pub fn is_lowercase(self) -> bool {
match self {
- 'a'...'z' => true,
+ 'a'..='z' => true,
c if c > '\x7f' => derived_property::Lowercase(c),
_ => false,
}
#[inline]
pub fn is_uppercase(self) -> bool {
match self {
- 'A'...'Z' => true,
+ 'A'..='Z' => true,
c if c > '\x7f' => derived_property::Uppercase(c),
_ => false,
}
#[inline]
pub fn is_whitespace(self) -> bool {
match self {
- ' ' | '\x09'...'\x0d' => true,
+ ' ' | '\x09'..='\x0d' => true,
c if c > '\x7f' => property::White_Space(c),
_ => false,
}
#[inline]
pub fn is_numeric(self) -> bool {
match self {
- '0'...'9' => true,
+ '0'..='9' => true,
c if c > '\x7f' => general_category::N(c),
_ => false,
}
fn digit(x: u8) -> u8 {
match x {
$($x => $conv,)+
- x => panic!("number not in the range 0..{}: {}", Self::BASE - 1, x),
+ x => panic!("number not in the range 0..={}: {}", Self::BASE - 1, x),
}
}
}
}
}
-radix! { Binary, 2, "0b", x @ 0 ... 1 => b'0' + x }
-radix! { Octal, 8, "0o", x @ 0 ... 7 => b'0' + x }
-radix! { LowerHex, 16, "0x", x @ 0 ... 9 => b'0' + x,
- x @ 10 ... 15 => b'a' + (x - 10) }
-radix! { UpperHex, 16, "0x", x @ 0 ... 9 => b'0' + x,
- x @ 10 ... 15 => b'A' + (x - 10) }
+radix! { Binary, 2, "0b", x @ 0 ..= 1 => b'0' + x }
+radix! { Octal, 8, "0o", x @ 0 ..= 7 => b'0' + x }
+radix! { LowerHex, 16, "0x", x @ 0 ..= 9 => b'0' + x,
+ x @ 10 ..= 15 => b'a' + (x - 10) }
+radix! { UpperHex, 16, "0x", x @ 0 ..= 9 => b'0' + x,
+ x @ 10 ..= 15 => b'A' + (x - 10) }
macro_rules! int_base {
($Trait:ident for $T:ident as $U:ident -> $Radix:ident) => {
pub fn new(reference: &'a mut T) -> PinMut<'a, T> {
PinMut { inner: reference }
}
+
+ /// Get a mutable reference to the data inside of this `PinMut`.
+ #[unstable(feature = "pin", issue = "49150")]
+ pub fn get_mut(this: PinMut<'a, T>) -> &'a mut T {
+ this.inner
+ }
}
/// the data out of the mutable reference you receive when you call this
/// function.
#[unstable(feature = "pin", issue = "49150")]
- pub unsafe fn get_mut(this: PinMut<'a, T>) -> &'a mut T {
+ pub unsafe fn get_mut_unchecked(this: PinMut<'a, T>) -> &'a mut T {
this.inner
}
/// Construct a new pin by mapping the interior value.
///
- /// For example, if you wanted to get a `PinMut` of a field of something, you
- /// could use this to get access to that field in one line of code.
+ /// For example, if you wanted to get a `PinMut` of a field of something,
+ /// you could use this to get access to that field in one line of code.
///
/// This function is unsafe. You must guarantee that the data you return
/// will not move so long as the argument value does not move (for example,
/// because it is one of the fields of that value), and also that you do
/// not move out of the argument you receive to the interior function.
#[unstable(feature = "pin", issue = "49150")]
- pub unsafe fn map<U, F>(this: PinMut<'a, T>, f: F) -> PinMut<'a, U> where
+ pub unsafe fn map_unchecked<U, F>(this: PinMut<'a, T>, f: F) -> PinMut<'a, U> where
F: FnOnce(&mut T) -> &mut U
{
PinMut { inner: f(this.inner) }
/// # Examples
///
/// ```
- /// #![feature(int_to_from_bytes)]
- ///
/// let bytes = i32::min_value().to_be().to_bytes();
/// assert_eq!(bytes, [0x80, 0, 0, 0]);
/// ```
- #[unstable(feature = "int_to_from_bytes", issue = "49792")]
+ #[stable(feature = "int_to_from_bytes", since = "1.29.0")]
#[inline]
pub fn to_bytes(self) -> [u8; mem::size_of::<Self>()] {
unsafe { mem::transmute(self) }
/// # Examples
///
/// ```
- /// #![feature(int_to_from_bytes)]
- ///
/// let int = i32::from_be(i32::from_bytes([0x80, 0, 0, 0]));
/// assert_eq!(int, i32::min_value());
/// ```
- #[unstable(feature = "int_to_from_bytes", issue = "49792")]
+ #[stable(feature = "int_to_from_bytes", since = "1.29.0")]
#[inline]
pub fn from_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
unsafe { mem::transmute(bytes) }
/// # Examples
///
/// ```
- /// #![feature(int_to_from_bytes)]
- ///
/// let bytes = 0x1234_5678_u32.to_be().to_bytes();
/// assert_eq!(bytes, [0x12, 0x34, 0x56, 0x78]);
/// ```
- #[unstable(feature = "int_to_from_bytes", issue = "49792")]
+ #[stable(feature = "int_to_from_bytes", since = "1.29.0")]
#[inline]
pub fn to_bytes(self) -> [u8; mem::size_of::<Self>()] {
unsafe { mem::transmute(self) }
/// # Examples
///
/// ```
- /// #![feature(int_to_from_bytes)]
- ///
/// let int = u32::from_be(u32::from_bytes([0x12, 0x34, 0x56, 0x78]));
/// assert_eq!(int, 0x1234_5678_u32);
/// ```
- #[unstable(feature = "int_to_from_bytes", issue = "49792")]
+ #[stable(feature = "int_to_from_bytes", since = "1.29.0")]
#[inline]
pub fn from_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
unsafe { mem::transmute(bytes) }
#[unstable(feature = "pin", issue = "49150")]
pub fn as_pin_mut<'a>(self: PinMut<'a, Self>) -> Option<PinMut<'a, T>> {
unsafe {
- PinMut::get_mut(self).as_mut().map(|x| PinMut::new_unchecked(x))
+ PinMut::get_mut_unchecked(self).as_mut().map(|x| PinMut::new_unchecked(x))
}
}
/// assert_eq!(s.binary_search(&4), Err(7));
/// assert_eq!(s.binary_search(&100), Err(13));
/// let r = s.binary_search(&1);
- /// assert!(match r { Ok(1...4) => true, _ => false, });
+ /// assert!(match r { Ok(1..=4) => true, _ => false, });
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn binary_search(&self, x: &T) -> Result<usize, usize>
/// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Err(13));
/// let seek = 1;
/// let r = s.binary_search_by(|probe| probe.cmp(&seek));
- /// assert!(match r { Ok(1...4) => true, _ => false, });
+ /// assert!(match r { Ok(1..=4) => true, _ => false, });
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
/// assert_eq!(s.binary_search_by_key(&4, |&(a,b)| b), Err(7));
/// assert_eq!(s.binary_search_by_key(&100, |&(a,b)| b), Err(13));
/// let r = s.binary_search_by_key(&1, |&(a,b)| b);
- /// assert!(match r { Ok(1...4) => true, _ => false, });
+ /// assert!(match r { Ok(1..=4) => true, _ => false, });
/// ```
#[stable(feature = "slice_binary_search_by_key", since = "1.10.0")]
#[inline]
}
3 => {
match (byte, safe_get(self.source, i)) {
- (0xE0, 0xA0 ... 0xBF) => (),
- (0xE1 ... 0xEC, 0x80 ... 0xBF) => (),
- (0xED, 0x80 ... 0x9F) => (),
- (0xEE ... 0xEF, 0x80 ... 0xBF) => (),
+ (0xE0, 0xA0 ..= 0xBF) => (),
+ (0xE1 ..= 0xEC, 0x80 ..= 0xBF) => (),
+ (0xED, 0x80 ..= 0x9F) => (),
+ (0xEE ..= 0xEF, 0x80 ..= 0xBF) => (),
_ => {
error!();
}
}
4 => {
match (byte, safe_get(self.source, i)) {
- (0xF0, 0x90 ... 0xBF) => (),
- (0xF1 ... 0xF3, 0x80 ... 0xBF) => (),
- (0xF4, 0x80 ... 0x8F) => (),
+ (0xF0, 0x90 ..= 0xBF) => (),
+ (0xF1 ..= 0xF3, 0x80 ..= 0xBF) => (),
+ (0xF4, 0x80 ..= 0x8F) => (),
_ => {
error!();
}
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;
},
3 => {
match (first, next!()) {
- (0xE0 , 0xA0 ... 0xBF) |
- (0xE1 ... 0xEC, 0x80 ... 0xBF) |
- (0xED , 0x80 ... 0x9F) |
- (0xEE ... 0xEF, 0x80 ... 0xBF) => {}
+ (0xE0 , 0xA0 ..= 0xBF) |
+ (0xE1 ..= 0xEC, 0x80 ..= 0xBF) |
+ (0xED , 0x80 ..= 0x9F) |
+ (0xEE ..= 0xEF, 0x80 ..= 0xBF) => {}
_ => err!(Some(1))
}
if next!() & !CONT_MASK != TAG_CONT_U8 {
}
4 => {
match (first, next!()) {
- (0xF0 , 0x90 ... 0xBF) |
- (0xF1 ... 0xF3, 0x80 ... 0xBF) |
- (0xF4 , 0x80 ... 0x8F) => {}
+ (0xF0 , 0x90 ..= 0xBF) |
+ (0xF1 ..= 0xF3, 0x80 ..= 0xBF) |
+ (0xF4 , 0x80 ..= 0x8F) => {}
_ => err!(Some(1))
}
if next!() & !CONT_MASK != TAG_CONT_U8 {
/// 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
///
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
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;
}
}
+#[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;
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()
}
#[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
+++ /dev/null
-// Copyright 2018 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.
-
-#![unstable(feature = "futures_api",
- reason = "futures in libcore are unstable",
- issue = "50547")]
-
-//! Types and Traits for working with asynchronous tasks.
-
-use fmt;
-use ptr::NonNull;
-use future::Future;
-use mem::PinMut;
-
-/// Indicates whether a value is available or if the current task has been
-/// scheduled to receive a wakeup instead.
-#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
-pub enum Poll<T> {
- /// Represents that a value is immediately ready.
- Ready(T),
-
- /// Represents that a value is not ready yet.
- ///
- /// When a function returns `Pending`, the function *must* also
- /// ensure that the current task is scheduled to be awoken when
- /// progress can be made.
- Pending,
-}
-
-impl<T> Poll<T> {
- /// Change the ready value of this `Poll` with the closure provided
- pub fn map<U, F>(self, f: F) -> Poll<U>
- where F: FnOnce(T) -> U
- {
- match self {
- Poll::Ready(t) => Poll::Ready(f(t)),
- Poll::Pending => Poll::Pending,
- }
- }
-
- /// Returns whether this is `Poll::Ready`
- pub fn is_ready(&self) -> bool {
- match *self {
- Poll::Ready(_) => true,
- Poll::Pending => false,
- }
- }
-
- /// Returns whether this is `Poll::Pending`
- pub fn is_pending(&self) -> bool {
- !self.is_ready()
- }
-}
-
-impl<T, E> Poll<Result<T, E>> {
- /// Change the success value of this `Poll` with the closure provided
- pub fn map_ok<U, F>(self, f: F) -> Poll<Result<U, E>>
- where F: FnOnce(T) -> U
- {
- match self {
- Poll::Ready(Ok(t)) => Poll::Ready(Ok(f(t))),
- Poll::Ready(Err(e)) => Poll::Ready(Err(e)),
- Poll::Pending => Poll::Pending,
- }
- }
-
- /// Change the error value of this `Poll` with the closure provided
- pub fn map_err<U, F>(self, f: F) -> Poll<Result<T, U>>
- where F: FnOnce(E) -> U
- {
- match self {
- Poll::Ready(Ok(t)) => Poll::Ready(Ok(t)),
- Poll::Ready(Err(e)) => Poll::Ready(Err(f(e))),
- Poll::Pending => Poll::Pending,
- }
- }
-}
-
-impl<T> From<T> for Poll<T> {
- fn from(t: T) -> Poll<T> {
- Poll::Ready(t)
- }
-}
-
-/// A `Waker` is a handle for waking up a task by notifying its executor that it
-/// is ready to be run.
-///
-/// This handle contains a trait object pointing to an instance of the `UnsafeWake`
-/// trait, allowing notifications to get routed through it.
-#[repr(transparent)]
-pub struct Waker {
- inner: NonNull<UnsafeWake>,
-}
-
-unsafe impl Send for Waker {}
-unsafe impl Sync for Waker {}
-
-impl Waker {
- /// Constructs a new `Waker` directly.
- ///
- /// Note that most code will not need to call this. Implementers of the
- /// `UnsafeWake` trait will typically provide a wrapper that calls this
- /// but you otherwise shouldn't call it directly.
- ///
- /// If you're working with the standard library then it's recommended to
- /// use the `Waker::from` function instead which works with the safe
- /// `Arc` type and the safe `Wake` trait.
- #[inline]
- pub unsafe fn new(inner: NonNull<UnsafeWake>) -> Self {
- Waker { inner: inner }
- }
-
- /// Wake up the task associated with this `Waker`.
- #[inline]
- pub fn wake(&self) {
- unsafe { self.inner.as_ref().wake() }
- }
-
- /// Returns whether or not this `Waker` and `other` awaken the same task.
- ///
- /// This function works on a best-effort basis, and may return false even
- /// when the `Waker`s would awaken the same task. However, if this function
- /// returns true, it is guaranteed that the `Waker`s will awaken the same
- /// task.
- ///
- /// This function is primarily used for optimization purposes.
- #[inline]
- pub fn will_wake(&self, other: &Waker) -> bool {
- self.inner == other.inner
- }
-}
-
-impl Clone for Waker {
- #[inline]
- fn clone(&self) -> Self {
- unsafe {
- self.inner.as_ref().clone_raw()
- }
- }
-}
-
-impl fmt::Debug for Waker {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- f.debug_struct("Waker")
- .finish()
- }
-}
-
-impl Drop for Waker {
- #[inline]
- fn drop(&mut self) {
- unsafe {
- self.inner.as_ref().drop_raw()
- }
- }
-}
-
-/// A `LocalWaker` is a handle for waking up a task by notifying its executor that it
-/// is ready to be run.
-///
-/// This is similar to the `Waker` type, but cannot be sent across threads.
-/// Task executors can use this type to implement more optimized singlethreaded wakeup
-/// behavior.
-#[repr(transparent)]
-pub struct LocalWaker {
- inner: NonNull<UnsafeWake>,
-}
-
-impl !Send for LocalWaker {}
-impl !Sync for LocalWaker {}
-
-impl LocalWaker {
- /// Constructs a new `LocalWaker` directly.
- ///
- /// Note that most code will not need to call this. Implementers of the
- /// `UnsafeWake` trait will typically provide a wrapper that calls this
- /// but you otherwise shouldn't call it directly.
- ///
- /// If you're working with the standard library then it's recommended to
- /// use the `LocalWaker::from` function instead which works with the safe
- /// `Rc` type and the safe `LocalWake` trait.
- ///
- /// For this function to be used safely, it must be sound to call `inner.wake_local()`
- /// on the current thread.
- #[inline]
- pub unsafe fn new(inner: NonNull<UnsafeWake>) -> Self {
- LocalWaker { inner: inner }
- }
-
- /// Wake up the task associated with this `LocalWaker`.
- #[inline]
- pub fn wake(&self) {
- unsafe { self.inner.as_ref().wake_local() }
- }
-
- /// Returns whether or not this `LocalWaker` and `other` `LocalWaker` awaken the same task.
- ///
- /// This function works on a best-effort basis, and may return false even
- /// when the `LocalWaker`s would awaken the same task. However, if this function
- /// returns true, it is guaranteed that the `LocalWaker`s will awaken the same
- /// task.
- ///
- /// This function is primarily used for optimization purposes.
- #[inline]
- pub fn will_wake(&self, other: &LocalWaker) -> bool {
- self.inner == other.inner
- }
-
- /// Returns whether or not this `LocalWaker` and `other` `Waker` awaken the same task.
- ///
- /// This function works on a best-effort basis, and may return false even
- /// when the `Waker`s would awaken the same task. However, if this function
- /// returns true, it is guaranteed that the `LocalWaker`s will awaken the same
- /// task.
- ///
- /// This function is primarily used for optimization purposes.
- #[inline]
- pub fn will_wake_nonlocal(&self, other: &Waker) -> bool {
- self.inner == other.inner
- }
-}
-
-impl From<LocalWaker> for Waker {
- #[inline]
- fn from(local_waker: LocalWaker) -> Self {
- Waker { inner: local_waker.inner }
- }
-}
-
-impl Clone for LocalWaker {
- #[inline]
- fn clone(&self) -> Self {
- unsafe {
- LocalWaker { inner: self.inner.as_ref().clone_raw().inner }
- }
- }
-}
-
-impl fmt::Debug for LocalWaker {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- f.debug_struct("Waker")
- .finish()
- }
-}
-
-impl Drop for LocalWaker {
- #[inline]
- fn drop(&mut self) {
- unsafe {
- self.inner.as_ref().drop_raw()
- }
- }
-}
-
-/// An unsafe trait for implementing custom memory management for a `Waker` or `LocalWaker`.
-///
-/// A `Waker` conceptually is a cloneable trait object for `Wake`, and is
-/// most often essentially just `Arc<dyn Wake>`. However, in some contexts
-/// (particularly `no_std`), it's desirable to avoid `Arc` in favor of some
-/// custom memory management strategy. This trait is designed to allow for such
-/// customization.
-///
-/// When using `std`, a default implementation of the `UnsafeWake` trait is provided for
-/// `Arc<T>` where `T: Wake` and `Rc<T>` where `T: LocalWake`.
-///
-/// Although the methods on `UnsafeWake` take pointers rather than references,
-pub unsafe trait UnsafeWake: Send + Sync {
- /// Creates a clone of this `UnsafeWake` and stores it behind a `Waker`.
- ///
- /// This function will create a new uniquely owned handle that under the
- /// hood references the same notification instance. In other words calls
- /// to `wake` on the returned handle should be equivalent to calls to
- /// `wake` on this handle.
- ///
- /// # Unsafety
- ///
- /// This function is unsafe to call because it's asserting the `UnsafeWake`
- /// value is in a consistent state, i.e. hasn't been dropped.
- unsafe fn clone_raw(&self) -> Waker;
-
- /// Drops this instance of `UnsafeWake`, deallocating resources
- /// associated with it.
- ///
- /// FIXME(cramertj)
- /// This method is intended to have a signature such as:
- ///
- /// ```ignore (not-a-doctest)
- /// fn drop_raw(self: *mut Self);
- /// ```
- ///
- /// Unfortunately in Rust today that signature is not object safe.
- /// Nevertheless it's recommended to implement this function *as if* that
- /// were its signature. As such it is not safe to call on an invalid
- /// pointer, nor is the validity of the pointer guaranteed after this
- /// function returns.
- ///
- /// # Unsafety
- ///
- /// This function is unsafe to call because it's asserting the `UnsafeWake`
- /// value is in a consistent state, i.e. hasn't been dropped.
- unsafe fn drop_raw(&self);
-
- /// Indicates that the associated task is ready to make progress and should
- /// be `poll`ed.
- ///
- /// Executors generally maintain a queue of "ready" tasks; `wake` should place
- /// the associated task onto this queue.
- ///
- /// # Panics
- ///
- /// Implementations should avoid panicking, but clients should also be prepared
- /// for panics.
- ///
- /// # Unsafety
- ///
- /// This function is unsafe to call because it's asserting the `UnsafeWake`
- /// value is in a consistent state, i.e. hasn't been dropped.
- unsafe fn wake(&self);
-
- /// Indicates that the associated task is ready to make progress and should
- /// be `poll`ed. This function is the same as `wake`, but can only be called
- /// from the thread that this `UnsafeWake` is "local" to. This allows for
- /// implementors to provide specialized wakeup behavior specific to the current
- /// thread. This function is called by `LocalWaker::wake`.
- ///
- /// Executors generally maintain a queue of "ready" tasks; `wake_local` should place
- /// the associated task onto this queue.
- ///
- /// # Panics
- ///
- /// Implementations should avoid panicking, but clients should also be prepared
- /// for panics.
- ///
- /// # Unsafety
- ///
- /// This function is unsafe to call because it's asserting the `UnsafeWake`
- /// value is in a consistent state, i.e. hasn't been dropped, and that the
- /// `UnsafeWake` hasn't moved from the thread on which it was created.
- unsafe fn wake_local(&self) {
- self.wake()
- }
-}
-
-/// Information about the currently-running task.
-///
-/// Contexts are always tied to the stack, since they are set up specifically
-/// when performing a single `poll` step on a task.
-pub struct Context<'a> {
- local_waker: &'a LocalWaker,
- executor: &'a mut Executor,
-}
-
-impl<'a> fmt::Debug for Context<'a> {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- f.debug_struct("Context")
- .finish()
- }
-}
-
-impl<'a> Context<'a> {
- /// Create a new task `Context` with the provided `local_waker`, `waker`, and `executor`.
- #[inline]
- pub fn new(local_waker: &'a LocalWaker, executor: &'a mut Executor) -> Context<'a> {
- Context {
- local_waker,
- executor,
- }
- }
-
- /// Get the `LocalWaker` associated with the current task.
- #[inline]
- pub fn local_waker(&self) -> &'a LocalWaker {
- self.local_waker
- }
-
- /// Get the `Waker` associated with the current task.
- #[inline]
- pub fn waker(&self) -> &'a Waker {
- unsafe { &*(self.local_waker as *const LocalWaker as *const Waker) }
- }
-
- /// Get the default executor associated with this task.
- ///
- /// This method is useful primarily if you want to explicitly handle
- /// spawn failures.
- #[inline]
- pub fn executor(&mut self) -> &mut Executor {
- self.executor
- }
-
- /// Produce a context like the current one, but using the given waker instead.
- ///
- /// This advanced method is primarily used when building "internal
- /// schedulers" within a task, where you want to provide some customized
- /// wakeup logic.
- #[inline]
- pub fn with_waker<'b>(&'b mut self, local_waker: &'b LocalWaker) -> Context<'b> {
- Context {
- local_waker,
- executor: self.executor,
- }
- }
-
- /// Produce a context like the current one, but using the given executor
- /// instead.
- ///
- /// This advanced method is primarily used when building "internal
- /// schedulers" within a task.
- #[inline]
- pub fn with_executor<'b, E>(&'b mut self, executor: &'b mut E) -> Context<'b>
- where E: Executor
- {
- Context {
- local_waker: self.local_waker,
- executor: executor,
- }
- }
-}
-
-/// A task executor.
-///
-/// A *task* is a `()`-producing async value that runs at the top level, and will
-/// be `poll`ed until completion. It's also the unit at which wake-up
-/// notifications occur. Executors, such as thread pools, allow tasks to be
-/// spawned and are responsible for putting tasks onto ready queues when
-/// they are woken up, and polling them when they are ready.
-pub trait Executor {
- /// Spawn the given task, polling it until completion.
- ///
- /// # Errors
- ///
- /// The executor may be unable to spawn tasks, either because it has
- /// been shut down or is resource-constrained.
- fn spawn_obj(&mut self, task: TaskObj) -> Result<(), SpawnObjError>;
-
- /// Determine whether the executor is able to spawn new tasks.
- ///
- /// # Returns
- ///
- /// An `Ok` return means the executor is *likely* (but not guaranteed)
- /// to accept a subsequent spawn attempt. Likewise, an `Err` return
- /// means that `spawn` is likely, but not guaranteed, to yield an error.
- #[inline]
- fn status(&self) -> Result<(), SpawnErrorKind> {
- Ok(())
- }
-}
-
-/// A custom trait object for polling tasks, roughly akin to
-/// `Box<Future<Output = ()> + Send>`.
-pub struct TaskObj {
- ptr: *mut (),
- poll_fn: unsafe fn(*mut (), &mut Context) -> Poll<()>,
- drop_fn: unsafe fn(*mut ()),
-}
-
-impl fmt::Debug for TaskObj {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- f.debug_struct("TaskObj")
- .finish()
- }
-}
-
-unsafe impl Send for TaskObj {}
-
-/// A custom implementation of a task trait object for `TaskObj`, providing
-/// a hand-rolled vtable.
-///
-/// This custom representation is typically used only in `no_std` contexts,
-/// where the default `Box`-based implementation is not available.
-///
-/// The implementor must guarantee that it is safe to call `poll` repeatedly (in
-/// a non-concurrent fashion) with the result of `into_raw` until `drop` is
-/// called.
-pub unsafe trait UnsafeTask: Send + 'static {
- /// Convert a owned instance into a (conceptually owned) void pointer.
- fn into_raw(self) -> *mut ();
-
- /// Poll the task represented by the given void pointer.
- ///
- /// # Safety
- ///
- /// The trait implementor must guarantee that it is safe to repeatedly call
- /// `poll` with the result of `into_raw` until `drop` is called; such calls
- /// are not, however, allowed to race with each other or with calls to `drop`.
- unsafe fn poll(task: *mut (), cx: &mut Context) -> Poll<()>;
-
- /// Drops the task represented by the given void pointer.
- ///
- /// # Safety
- ///
- /// The trait implementor must guarantee that it is safe to call this
- /// function once per `into_raw` invocation; that call cannot race with
- /// other calls to `drop` or `poll`.
- unsafe fn drop(task: *mut ());
-}
-
-impl TaskObj {
- /// Create a `TaskObj` from a custom trait object representation.
- #[inline]
- pub fn new<T: UnsafeTask>(t: T) -> TaskObj {
- TaskObj {
- ptr: t.into_raw(),
- poll_fn: T::poll,
- drop_fn: T::drop,
- }
- }
-}
-
-impl Future for TaskObj {
- type Output = ();
-
- #[inline]
- fn poll(self: PinMut<Self>, cx: &mut Context) -> Poll<()> {
- unsafe {
- (self.poll_fn)(self.ptr, cx)
- }
- }
-}
-
-impl Drop for TaskObj {
- fn drop(&mut self) {
- unsafe {
- (self.drop_fn)(self.ptr)
- }
- }
-}
-
-/// Provides the reason that an executor was unable to spawn.
-pub struct SpawnErrorKind {
- _hidden: (),
-}
-
-impl fmt::Debug for SpawnErrorKind {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- f.debug_tuple("SpawnErrorKind")
- .field(&"shutdown")
- .finish()
- }
-}
-
-impl SpawnErrorKind {
- /// Spawning is failing because the executor has been shut down.
- pub fn shutdown() -> SpawnErrorKind {
- SpawnErrorKind { _hidden: () }
- }
-
- /// Check whether this error is the `shutdown` error.
- pub fn is_shutdown(&self) -> bool {
- true
- }
-}
-
-/// The result of a failed spawn
-#[derive(Debug)]
-pub struct SpawnObjError {
- /// The kind of error
- pub kind: SpawnErrorKind,
-
- /// The task for which spawning was attempted
- pub task: TaskObj,
-}
--- /dev/null
+// Copyright 2018 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.
+
+#![unstable(feature = "futures_api",
+ reason = "futures in libcore are unstable",
+ issue = "50547")]
+
+use fmt;
+use super::{Executor, Waker, LocalWaker};
+
+/// Information about the currently-running task.
+///
+/// Contexts are always tied to the stack, since they are set up specifically
+/// when performing a single `poll` step on a task.
+pub struct Context<'a> {
+ local_waker: &'a LocalWaker,
+ executor: &'a mut Executor,
+}
+
+impl<'a> fmt::Debug for Context<'a> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_struct("Context")
+ .finish()
+ }
+}
+
+impl<'a> Context<'a> {
+ /// Create a new task `Context` with the provided `local_waker`, `waker`, and `executor`.
+ #[inline]
+ pub fn new(local_waker: &'a LocalWaker, executor: &'a mut Executor) -> Context<'a> {
+ Context {
+ local_waker,
+ executor,
+ }
+ }
+
+ /// Get the `LocalWaker` associated with the current task.
+ #[inline]
+ pub fn local_waker(&self) -> &'a LocalWaker {
+ self.local_waker
+ }
+
+ /// Get the `Waker` associated with the current task.
+ #[inline]
+ pub fn waker(&self) -> &'a Waker {
+ unsafe { &*(self.local_waker as *const LocalWaker as *const Waker) }
+ }
+
+ /// Get the default executor associated with this task.
+ ///
+ /// This method is useful primarily if you want to explicitly handle
+ /// spawn failures.
+ #[inline]
+ pub fn executor(&mut self) -> &mut Executor {
+ self.executor
+ }
+
+ /// Produce a context like the current one, but using the given waker instead.
+ ///
+ /// This advanced method is primarily used when building "internal
+ /// schedulers" within a task, where you want to provide some customized
+ /// wakeup logic.
+ #[inline]
+ pub fn with_waker<'b>(&'b mut self, local_waker: &'b LocalWaker) -> Context<'b> {
+ Context {
+ local_waker,
+ executor: self.executor,
+ }
+ }
+
+ /// Produce a context like the current one, but using the given executor
+ /// instead.
+ ///
+ /// This advanced method is primarily used when building "internal
+ /// schedulers" within a task.
+ #[inline]
+ pub fn with_executor<'b, E>(&'b mut self, executor: &'b mut E) -> Context<'b>
+ where E: Executor
+ {
+ Context {
+ local_waker: self.local_waker,
+ executor: executor,
+ }
+ }
+}
--- /dev/null
+// Copyright 2018 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.
+
+#![unstable(feature = "futures_api",
+ reason = "futures in libcore are unstable",
+ issue = "50547")]
+
+use fmt;
+use super::{TaskObj, LocalTaskObj};
+
+/// A task executor.
+///
+/// A *task* is a `()`-producing async value that runs at the top level, and will
+/// be `poll`ed until completion. It's also the unit at which wake-up
+/// notifications occur. Executors, such as thread pools, allow tasks to be
+/// spawned and are responsible for putting tasks onto ready queues when
+/// they are woken up, and polling them when they are ready.
+pub trait Executor {
+ /// Spawn the given task, polling it until completion.
+ ///
+ /// # Errors
+ ///
+ /// The executor may be unable to spawn tasks, either because it has
+ /// been shut down or is resource-constrained.
+ fn spawn_obj(&mut self, task: TaskObj) -> Result<(), SpawnObjError>;
+
+ /// Determine whether the executor is able to spawn new tasks.
+ ///
+ /// # Returns
+ ///
+ /// An `Ok` return means the executor is *likely* (but not guaranteed)
+ /// to accept a subsequent spawn attempt. Likewise, an `Err` return
+ /// means that `spawn` is likely, but not guaranteed, to yield an error.
+ #[inline]
+ fn status(&self) -> Result<(), SpawnErrorKind> {
+ Ok(())
+ }
+}
+
+/// Provides the reason that an executor was unable to spawn.
+pub struct SpawnErrorKind {
+ _hidden: (),
+}
+
+impl fmt::Debug for SpawnErrorKind {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_tuple("SpawnErrorKind")
+ .field(&"shutdown")
+ .finish()
+ }
+}
+
+impl SpawnErrorKind {
+ /// Spawning is failing because the executor has been shut down.
+ pub fn shutdown() -> SpawnErrorKind {
+ SpawnErrorKind { _hidden: () }
+ }
+
+ /// Check whether this error is the `shutdown` error.
+ pub fn is_shutdown(&self) -> bool {
+ true
+ }
+}
+
+/// The result of a failed spawn
+#[derive(Debug)]
+pub struct SpawnObjError {
+ /// The kind of error
+ pub kind: SpawnErrorKind,
+
+ /// The task for which spawning was attempted
+ pub task: TaskObj,
+}
+
+/// The result of a failed spawn
+#[derive(Debug)]
+pub struct SpawnLocalObjError {
+ /// The kind of error
+ pub kind: SpawnErrorKind,
+
+ /// The task for which spawning was attempted
+ pub task: LocalTaskObj,
+}
--- /dev/null
+// Copyright 2018 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.
+
+#![unstable(feature = "futures_api",
+ reason = "futures in libcore are unstable",
+ issue = "50547")]
+
+//! Types and Traits for working with asynchronous tasks.
+
+mod context;
+pub use self::context::Context;
+
+mod executor;
+pub use self::executor::{
+ Executor, SpawnErrorKind, SpawnObjError, SpawnLocalObjError
+};
+
+mod poll;
+pub use self::poll::Poll;
+
+mod task;
+pub use self::task::{TaskObj, LocalTaskObj, UnsafeTask};
+
+mod wake;
+pub use self::wake::{Waker, LocalWaker, UnsafeWake};
--- /dev/null
+// Copyright 2018 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.
+
+#![unstable(feature = "futures_api",
+ reason = "futures in libcore are unstable",
+ issue = "50547")]
+
+/// Indicates whether a value is available or if the current task has been
+/// scheduled to receive a wakeup instead.
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
+pub enum Poll<T> {
+ /// Represents that a value is immediately ready.
+ Ready(T),
+
+ /// Represents that a value is not ready yet.
+ ///
+ /// When a function returns `Pending`, the function *must* also
+ /// ensure that the current task is scheduled to be awoken when
+ /// progress can be made.
+ Pending,
+}
+
+impl<T> Poll<T> {
+ /// Change the ready value of this `Poll` with the closure provided
+ pub fn map<U, F>(self, f: F) -> Poll<U>
+ where F: FnOnce(T) -> U
+ {
+ match self {
+ Poll::Ready(t) => Poll::Ready(f(t)),
+ Poll::Pending => Poll::Pending,
+ }
+ }
+
+ /// Returns whether this is `Poll::Ready`
+ pub fn is_ready(&self) -> bool {
+ match *self {
+ Poll::Ready(_) => true,
+ Poll::Pending => false,
+ }
+ }
+
+ /// Returns whether this is `Poll::Pending`
+ pub fn is_pending(&self) -> bool {
+ !self.is_ready()
+ }
+}
+
+impl<T, E> Poll<Result<T, E>> {
+ /// Change the success value of this `Poll` with the closure provided
+ pub fn map_ok<U, F>(self, f: F) -> Poll<Result<U, E>>
+ where F: FnOnce(T) -> U
+ {
+ match self {
+ Poll::Ready(Ok(t)) => Poll::Ready(Ok(f(t))),
+ Poll::Ready(Err(e)) => Poll::Ready(Err(e)),
+ Poll::Pending => Poll::Pending,
+ }
+ }
+
+ /// Change the error value of this `Poll` with the closure provided
+ pub fn map_err<U, F>(self, f: F) -> Poll<Result<T, U>>
+ where F: FnOnce(E) -> U
+ {
+ match self {
+ Poll::Ready(Ok(t)) => Poll::Ready(Ok(t)),
+ Poll::Ready(Err(e)) => Poll::Ready(Err(f(e))),
+ Poll::Pending => Poll::Pending,
+ }
+ }
+}
+
+impl<T> From<T> for Poll<T> {
+ fn from(t: T) -> Poll<T> {
+ Poll::Ready(t)
+ }
+}
--- /dev/null
+// Copyright 2018 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.
+
+#![unstable(feature = "futures_api",
+ reason = "futures in libcore are unstable",
+ issue = "50547")]
+
+use fmt;
+use future::Future;
+use mem::PinMut;
+use super::{Context, Poll};
+
+/// A custom trait object for polling tasks, roughly akin to
+/// `Box<Future<Output = ()>>`.
+/// Contrary to `TaskObj`, `LocalTaskObj` does not have a `Send` bound.
+pub struct LocalTaskObj {
+ ptr: *mut (),
+ poll_fn: unsafe fn(*mut (), &mut Context) -> Poll<()>,
+ drop_fn: unsafe fn(*mut ()),
+}
+
+impl LocalTaskObj {
+ /// Create a `LocalTaskObj` from a custom trait object representation.
+ #[inline]
+ pub fn new<T: UnsafeTask>(t: T) -> LocalTaskObj {
+ LocalTaskObj {
+ ptr: t.into_raw(),
+ poll_fn: T::poll,
+ drop_fn: T::drop,
+ }
+ }
+
+ /// Converts the `LocalTaskObj` into a `TaskObj`
+ /// To make this operation safe one has to ensure that the `UnsafeTask`
+ /// instance from which this `LocalTaskObj` was created actually implements
+ /// `Send`.
+ pub unsafe fn as_task_obj(self) -> TaskObj {
+ TaskObj(self)
+ }
+}
+
+impl fmt::Debug for LocalTaskObj {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_struct("LocalTaskObj")
+ .finish()
+ }
+}
+
+impl From<TaskObj> for LocalTaskObj {
+ fn from(task: TaskObj) -> LocalTaskObj {
+ task.0
+ }
+}
+
+impl Future for LocalTaskObj {
+ type Output = ();
+
+ #[inline]
+ fn poll(self: PinMut<Self>, cx: &mut Context) -> Poll<()> {
+ unsafe {
+ (self.poll_fn)(self.ptr, cx)
+ }
+ }
+}
+
+impl Drop for LocalTaskObj {
+ fn drop(&mut self) {
+ unsafe {
+ (self.drop_fn)(self.ptr)
+ }
+ }
+}
+
+/// A custom trait object for polling tasks, roughly akin to
+/// `Box<Future<Output = ()> + Send>`.
+pub struct TaskObj(LocalTaskObj);
+
+unsafe impl Send for TaskObj {}
+
+impl TaskObj {
+ /// Create a `TaskObj` from a custom trait object representation.
+ #[inline]
+ pub fn new<T: UnsafeTask + Send>(t: T) -> TaskObj {
+ TaskObj(LocalTaskObj::new(t))
+ }
+}
+
+impl fmt::Debug for TaskObj {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_struct("TaskObj")
+ .finish()
+ }
+}
+
+impl Future for TaskObj {
+ type Output = ();
+
+ #[inline]
+ fn poll(self: PinMut<Self>, cx: &mut Context) -> Poll<()> {
+ let pinned_field = unsafe { PinMut::map_unchecked(self, |x| &mut x.0) };
+ pinned_field.poll(cx)
+ }
+}
+
+/// A custom implementation of a task trait object for `TaskObj`, providing
+/// a hand-rolled vtable.
+///
+/// This custom representation is typically used only in `no_std` contexts,
+/// where the default `Box`-based implementation is not available.
+///
+/// The implementor must guarantee that it is safe to call `poll` repeatedly (in
+/// a non-concurrent fashion) with the result of `into_raw` until `drop` is
+/// called.
+pub unsafe trait UnsafeTask: 'static {
+ /// Convert a owned instance into a (conceptually owned) void pointer.
+ fn into_raw(self) -> *mut ();
+
+ /// Poll the task represented by the given void pointer.
+ ///
+ /// # Safety
+ ///
+ /// The trait implementor must guarantee that it is safe to repeatedly call
+ /// `poll` with the result of `into_raw` until `drop` is called; such calls
+ /// are not, however, allowed to race with each other or with calls to `drop`.
+ unsafe fn poll(task: *mut (), cx: &mut Context) -> Poll<()>;
+
+ /// Drops the task represented by the given void pointer.
+ ///
+ /// # Safety
+ ///
+ /// The trait implementor must guarantee that it is safe to call this
+ /// function once per `into_raw` invocation; that call cannot race with
+ /// other calls to `drop` or `poll`.
+ unsafe fn drop(task: *mut ());
+}
--- /dev/null
+// Copyright 2018 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.
+
+#![unstable(feature = "futures_api",
+ reason = "futures in libcore are unstable",
+ issue = "50547")]
+
+use fmt;
+use ptr::NonNull;
+
+/// A `Waker` is a handle for waking up a task by notifying its executor that it
+/// is ready to be run.
+///
+/// This handle contains a trait object pointing to an instance of the `UnsafeWake`
+/// trait, allowing notifications to get routed through it.
+#[repr(transparent)]
+pub struct Waker {
+ inner: NonNull<UnsafeWake>,
+}
+
+unsafe impl Send for Waker {}
+unsafe impl Sync for Waker {}
+
+impl Waker {
+ /// Constructs a new `Waker` directly.
+ ///
+ /// Note that most code will not need to call this. Implementers of the
+ /// `UnsafeWake` trait will typically provide a wrapper that calls this
+ /// but you otherwise shouldn't call it directly.
+ ///
+ /// If you're working with the standard library then it's recommended to
+ /// use the `Waker::from` function instead which works with the safe
+ /// `Arc` type and the safe `Wake` trait.
+ #[inline]
+ pub unsafe fn new(inner: NonNull<UnsafeWake>) -> Self {
+ Waker { inner: inner }
+ }
+
+ /// Wake up the task associated with this `Waker`.
+ #[inline]
+ pub fn wake(&self) {
+ unsafe { self.inner.as_ref().wake() }
+ }
+
+ /// Returns whether or not this `Waker` and `other` awaken the same task.
+ ///
+ /// This function works on a best-effort basis, and may return false even
+ /// when the `Waker`s would awaken the same task. However, if this function
+ /// returns true, it is guaranteed that the `Waker`s will awaken the same
+ /// task.
+ ///
+ /// This function is primarily used for optimization purposes.
+ #[inline]
+ pub fn will_wake(&self, other: &Waker) -> bool {
+ self.inner == other.inner
+ }
+}
+
+impl Clone for Waker {
+ #[inline]
+ fn clone(&self) -> Self {
+ unsafe {
+ self.inner.as_ref().clone_raw()
+ }
+ }
+}
+
+impl fmt::Debug for Waker {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_struct("Waker")
+ .finish()
+ }
+}
+
+impl Drop for Waker {
+ #[inline]
+ fn drop(&mut self) {
+ unsafe {
+ self.inner.as_ref().drop_raw()
+ }
+ }
+}
+
+/// A `LocalWaker` is a handle for waking up a task by notifying its executor that it
+/// is ready to be run.
+///
+/// This is similar to the `Waker` type, but cannot be sent across threads.
+/// Task executors can use this type to implement more optimized singlethreaded wakeup
+/// behavior.
+#[repr(transparent)]
+pub struct LocalWaker {
+ inner: NonNull<UnsafeWake>,
+}
+
+impl !Send for LocalWaker {}
+impl !Sync for LocalWaker {}
+
+impl LocalWaker {
+ /// Constructs a new `LocalWaker` directly.
+ ///
+ /// Note that most code will not need to call this. Implementers of the
+ /// `UnsafeWake` trait will typically provide a wrapper that calls this
+ /// but you otherwise shouldn't call it directly.
+ ///
+ /// If you're working with the standard library then it's recommended to
+ /// use the `LocalWaker::from` function instead which works with the safe
+ /// `Rc` type and the safe `LocalWake` trait.
+ ///
+ /// For this function to be used safely, it must be sound to call `inner.wake_local()`
+ /// on the current thread.
+ #[inline]
+ pub unsafe fn new(inner: NonNull<UnsafeWake>) -> Self {
+ LocalWaker { inner: inner }
+ }
+
+ /// Wake up the task associated with this `LocalWaker`.
+ #[inline]
+ pub fn wake(&self) {
+ unsafe { self.inner.as_ref().wake_local() }
+ }
+
+ /// Returns whether or not this `LocalWaker` and `other` `LocalWaker` awaken the same task.
+ ///
+ /// This function works on a best-effort basis, and may return false even
+ /// when the `LocalWaker`s would awaken the same task. However, if this function
+ /// returns true, it is guaranteed that the `LocalWaker`s will awaken the same
+ /// task.
+ ///
+ /// This function is primarily used for optimization purposes.
+ #[inline]
+ pub fn will_wake(&self, other: &LocalWaker) -> bool {
+ self.inner == other.inner
+ }
+
+ /// Returns whether or not this `LocalWaker` and `other` `Waker` awaken the same task.
+ ///
+ /// This function works on a best-effort basis, and may return false even
+ /// when the `Waker`s would awaken the same task. However, if this function
+ /// returns true, it is guaranteed that the `LocalWaker`s will awaken the same
+ /// task.
+ ///
+ /// This function is primarily used for optimization purposes.
+ #[inline]
+ pub fn will_wake_nonlocal(&self, other: &Waker) -> bool {
+ self.inner == other.inner
+ }
+}
+
+impl From<LocalWaker> for Waker {
+ #[inline]
+ fn from(local_waker: LocalWaker) -> Self {
+ Waker { inner: local_waker.inner }
+ }
+}
+
+impl Clone for LocalWaker {
+ #[inline]
+ fn clone(&self) -> Self {
+ unsafe {
+ LocalWaker { inner: self.inner.as_ref().clone_raw().inner }
+ }
+ }
+}
+
+impl fmt::Debug for LocalWaker {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.debug_struct("Waker")
+ .finish()
+ }
+}
+
+impl Drop for LocalWaker {
+ #[inline]
+ fn drop(&mut self) {
+ unsafe {
+ self.inner.as_ref().drop_raw()
+ }
+ }
+}
+
+/// An unsafe trait for implementing custom memory management for a `Waker` or `LocalWaker`.
+///
+/// A `Waker` conceptually is a cloneable trait object for `Wake`, and is
+/// most often essentially just `Arc<dyn Wake>`. However, in some contexts
+/// (particularly `no_std`), it's desirable to avoid `Arc` in favor of some
+/// custom memory management strategy. This trait is designed to allow for such
+/// customization.
+///
+/// When using `std`, a default implementation of the `UnsafeWake` trait is provided for
+/// `Arc<T>` where `T: Wake` and `Rc<T>` where `T: LocalWake`.
+///
+/// Although the methods on `UnsafeWake` take pointers rather than references,
+pub unsafe trait UnsafeWake: Send + Sync {
+ /// Creates a clone of this `UnsafeWake` and stores it behind a `Waker`.
+ ///
+ /// This function will create a new uniquely owned handle that under the
+ /// hood references the same notification instance. In other words calls
+ /// to `wake` on the returned handle should be equivalent to calls to
+ /// `wake` on this handle.
+ ///
+ /// # Unsafety
+ ///
+ /// This function is unsafe to call because it's asserting the `UnsafeWake`
+ /// value is in a consistent state, i.e. hasn't been dropped.
+ unsafe fn clone_raw(&self) -> Waker;
+
+ /// Drops this instance of `UnsafeWake`, deallocating resources
+ /// associated with it.
+ ///
+ /// FIXME(cramertj)
+ /// This method is intended to have a signature such as:
+ ///
+ /// ```ignore (not-a-doctest)
+ /// fn drop_raw(self: *mut Self);
+ /// ```
+ ///
+ /// Unfortunately in Rust today that signature is not object safe.
+ /// Nevertheless it's recommended to implement this function *as if* that
+ /// were its signature. As such it is not safe to call on an invalid
+ /// pointer, nor is the validity of the pointer guaranteed after this
+ /// function returns.
+ ///
+ /// # Unsafety
+ ///
+ /// This function is unsafe to call because it's asserting the `UnsafeWake`
+ /// value is in a consistent state, i.e. hasn't been dropped.
+ unsafe fn drop_raw(&self);
+
+ /// Indicates that the associated task is ready to make progress and should
+ /// be `poll`ed.
+ ///
+ /// Executors generally maintain a queue of "ready" tasks; `wake` should place
+ /// the associated task onto this queue.
+ ///
+ /// # Panics
+ ///
+ /// Implementations should avoid panicking, but clients should also be prepared
+ /// for panics.
+ ///
+ /// # Unsafety
+ ///
+ /// This function is unsafe to call because it's asserting the `UnsafeWake`
+ /// value is in a consistent state, i.e. hasn't been dropped.
+ unsafe fn wake(&self);
+
+ /// Indicates that the associated task is ready to make progress and should
+ /// be `poll`ed. This function is the same as `wake`, but can only be called
+ /// from the thread that this `UnsafeWake` is "local" to. This allows for
+ /// implementors to provide specialized wakeup behavior specific to the current
+ /// thread. This function is called by `LocalWaker::wake`.
+ ///
+ /// Executors generally maintain a queue of "ready" tasks; `wake_local` should place
+ /// the associated task onto this queue.
+ ///
+ /// # Panics
+ ///
+ /// Implementations should avoid panicking, but clients should also be prepared
+ /// for panics.
+ ///
+ /// # Unsafety
+ ///
+ /// This function is unsafe to call because it's asserting the `UnsafeWake`
+ /// value is in a consistent state, i.e. hasn't been dropped, and that the
+ /// `UnsafeWake` hasn't moved from the thread on which it was created.
+ unsafe fn wake_local(&self) {
+ self.wake()
+ }
+}
assert_eq!(b.binary_search(&0), Err(0));
assert_eq!(b.binary_search(&1), Ok(0));
assert_eq!(b.binary_search(&2), Err(1));
- assert!(match b.binary_search(&3) { Ok(1...3) => true, _ => false });
- assert!(match b.binary_search(&3) { Ok(1...3) => true, _ => false });
+ assert!(match b.binary_search(&3) { Ok(1..=3) => true, _ => false });
+ assert!(match b.binary_search(&3) { Ok(1..=3) => true, _ => false });
assert_eq!(b.binary_search(&4), Err(4));
assert_eq!(b.binary_search(&5), Err(4));
assert_eq!(b.binary_search(&6), Err(4));
assert_eq!(Duration::new(2, 0).checked_div(0), None);
}
+#[test]
+fn correct_sum() {
+ let durations = [
+ Duration::new(1, 999_999_999),
+ Duration::new(2, 999_999_999),
+ Duration::new(0, 999_999_999),
+ Duration::new(0, 999_999_999),
+ Duration::new(0, 999_999_999),
+ Duration::new(5, 0),
+ ];
+ let sum = durations.iter().sum::<Duration>();
+ assert_eq!(sum, Duration::new(1+2+5+4, 1_000_000_000 - 5));
+}
+
#[test]
fn debug_formatting_extreme_values() {
assert_eq!(
}
}
+macro_rules! sum_durations {
+ ($iter:expr) => {{
+ let mut total_secs: u64 = 0;
+ let mut total_nanos: u64 = 0;
+
+ for entry in $iter {
+ total_secs = total_secs
+ .checked_add(entry.secs)
+ .expect("overflow in iter::sum over durations");
+ total_nanos = match total_nanos.checked_add(entry.nanos as u64) {
+ Some(n) => n,
+ None => {
+ total_secs = total_secs
+ .checked_add(total_nanos / NANOS_PER_SEC as u64)
+ .expect("overflow in iter::sum over durations");
+ (total_nanos % NANOS_PER_SEC as u64) + entry.nanos as u64
+ }
+ };
+ }
+ total_secs = total_secs
+ .checked_add(total_nanos / NANOS_PER_SEC as u64)
+ .expect("overflow in iter::sum over durations");
+ total_nanos = total_nanos % NANOS_PER_SEC as u64;
+ Duration {
+ secs: total_secs,
+ nanos: total_nanos as u32,
+ }
+ }};
+}
+
#[stable(feature = "duration_sum", since = "1.16.0")]
impl Sum for Duration {
fn sum<I: Iterator<Item=Duration>>(iter: I) -> Duration {
- iter.fold(Duration::new(0, 0), |a, b| a + b)
+ sum_durations!(iter)
}
}
#[stable(feature = "duration_sum", since = "1.16.0")]
impl<'a> Sum<&'a Duration> for Duration {
fn sum<I: Iterator<Item=&'a Duration>>(iter: I) -> Duration {
- iter.fold(Duration::new(0, 0), |a, b| a + *b)
+ sum_durations!(iter)
}
}
format: codemap::CompilerDesugaring(reason),
allow_internal_unstable: true,
allow_internal_unsafe: false,
+ local_inner_macros: false,
edition: codemap::hygiene::default_edition(),
});
span.with_ctxt(SyntaxContext::empty().apply_mark(mark))
-> hir::GenericArg {
match arg {
ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(<)),
- ast::GenericArg::Type(ty) => GenericArg::Type(self.lower_ty(&ty, itctx)),
+ ast::GenericArg::Type(ty) => GenericArg::Type(self.lower_ty_direct(&ty, itctx)),
}
}
fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> P<hir::Ty> {
+ P(self.lower_ty_direct(t, itctx))
+ }
+
+ fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty {
let kind = match t.node {
TyKind::Infer => hir::TyInfer,
TyKind::Err => hir::TyErr,
),
TyKind::Never => hir::TyNever,
TyKind::Tup(ref tys) => {
- hir::TyTup(tys.iter().map(|ty| self.lower_ty(ty, itctx)).collect())
+ hir::TyTup(tys.iter().map(|ty| self.lower_ty_direct(ty, itctx)).collect())
}
TyKind::Paren(ref ty) => {
- return self.lower_ty(ty, itctx);
+ return self.lower_ty_direct(ty, itctx);
}
TyKind::Path(ref qself, ref path) => {
let id = self.lower_node_id(t.id);
};
let LoweredNodeId { node_id, hir_id } = self.lower_node_id(t.id);
- P(hir::Ty {
+ hir::Ty {
id: node_id,
node: kind,
span: t.span,
hir_id,
- })
+ }
}
fn lower_existential_impl_trait(
// e.g. `Vec` in `Vec::new` or `<I as Iterator>::Item` in
// `<I as Iterator>::Item::default`.
let new_id = self.next_id();
- self.ty_path(new_id, p.span, hir::QPath::Resolved(qself, path))
+ P(self.ty_path(new_id, p.span, hir::QPath::Resolved(qself, path)))
};
// Anything after the base path are associated "extensions",
// Wrap the associated extension in another type node.
let new_id = self.next_id();
- ty = self.ty_path(new_id, p.span, qpath);
+ ty = P(self.ty_path(new_id, p.span, qpath));
}
// Should've returned in the for loop above.
|this| {
const DISALLOWED: ImplTraitContext = ImplTraitContext::Disallowed;
let &ParenthesisedArgs { ref inputs, ref output, span } = data;
- let inputs = inputs.iter().map(|ty| this.lower_ty(ty, DISALLOWED)).collect();
+ let inputs = inputs.iter().map(|ty| this.lower_ty_direct(ty, DISALLOWED)).collect();
let mk_tup = |this: &mut Self, tys, span| {
let LoweredNodeId { node_id, hir_id } = this.next_id();
- P(hir::Ty { node: hir::TyTup(tys), id: node_id, hir_id, span })
+ hir::Ty { node: hir::TyTup(tys), id: node_id, hir_id, span }
};
(
ty: output
.as_ref()
.map(|ty| this.lower_ty(&ty, DISALLOWED))
- .unwrap_or_else(|| mk_tup(this, hir::HirVec::new(), span)),
+ .unwrap_or_else(|| P(mk_tup(this, hir::HirVec::new(), span))),
span: output.as_ref().map_or(span, |ty| ty.span),
}
],
.iter()
.map(|arg| {
if let Some(def_id) = fn_def_id {
- self.lower_ty(&arg.ty, ImplTraitContext::Universal(def_id))
+ self.lower_ty_direct(&arg.ty, ImplTraitContext::Universal(def_id))
} else {
- self.lower_ty(&arg.ty, ImplTraitContext::Disallowed)
+ self.lower_ty_direct(&arg.ty, ImplTraitContext::Disallowed)
}
})
.collect::<HirVec<_>>();
// fn_def_id: DefId of the parent function. Used to create child impl trait definition.
fn lower_async_fn_ret_ty(
&mut self,
- inputs: &[P<hir::Ty>],
+ inputs: &[hir::Ty],
output: &FunctionRetTy,
fn_def_id: DefId,
) -> hir::FunctionRetTy {
PatKind::Ref(ref inner, mutbl) => {
hir::PatKind::Ref(self.lower_pat(inner), self.lower_mutability(mutbl))
}
- PatKind::Range(ref e1, ref e2, ref end) => hir::PatKind::Range(
+ PatKind::Range(ref e1, ref e2, Spanned { node: ref end, .. }) => hir::PatKind::Range(
P(self.lower_expr(e1)),
P(self.lower_expr(e2)),
self.lower_range_end(end),
this.expr_block(block, ThinVec::new())
})
})
- },
+ }
ExprKind::Closure(
- capture_clause, asyncness, movability, ref decl, ref body, fn_decl_span) =>
- {
- self.with_new_scopes(|this| {
- if let IsAsync::Async(async_closure_node_id) = asyncness {
+ capture_clause, asyncness, movability, ref decl, ref body, fn_decl_span
+ ) => {
+ if let IsAsync::Async(async_closure_node_id) = asyncness {
+ let outer_decl = FnDecl {
+ inputs: decl.inputs.clone(),
+ output: FunctionRetTy::Default(fn_decl_span),
+ variadic: false,
+ };
+ // We need to lower the declaration outside the new scope, because we
+ // have to conserve the state of being inside a loop condition for the
+ // closure argument types.
+ let fn_decl = self.lower_fn_decl(&outer_decl, None, false, false);
+
+ self.with_new_scopes(|this| {
// FIXME(cramertj) allow `async` non-`move` closures with
if capture_clause == CaptureBy::Ref &&
!decl.inputs.is_empty()
// Transform `async |x: u8| -> X { ... }` into
// `|x: u8| future_from_generator(|| -> X { ... })`
- let outer_decl = FnDecl {
- inputs: decl.inputs.clone(),
- output: FunctionRetTy::Default(fn_decl_span),
- variadic: false,
- };
let body_id = this.lower_body(Some(&outer_decl), |this| {
let async_ret_ty = if let FunctionRetTy::Ty(ty) = &decl.output {
Some(&**ty)
});
hir::ExprClosure(
this.lower_capture_clause(capture_clause),
- this.lower_fn_decl(&outer_decl, None, false, false),
+ fn_decl,
body_id,
fn_decl_span,
None,
)
- } else {
+ })
+ } else {
+ // Lower outside new scope to preserve `is_in_loop_condition`.
+ let fn_decl = self.lower_fn_decl(decl, None, false, false);
+
+ self.with_new_scopes(|this| {
let mut is_generator = false;
let body_id = this.lower_body(Some(decl), |this| {
let e = this.lower_expr(body);
};
hir::ExprClosure(
this.lower_capture_clause(capture_clause),
- this.lower_fn_decl(decl, None, false, false),
+ fn_decl,
body_id,
fn_decl_span,
generator_option,
)
- }
- })
+ })
+ }
}
ExprKind::Block(ref blk, opt_label) => {
hir::ExprBlock(self.lower_block(blk,
let e1 = self.lower_expr(e1);
let e2 = self.lower_expr(e2);
let ty_path = P(self.std_path(span, &["ops", "RangeInclusive"], None, false));
- let ty = self.ty_path(id, span, hir::QPath::Resolved(None, ty_path));
+ let ty = P(self.ty_path(id, span, hir::QPath::Resolved(None, ty_path)));
let new_seg = P(hir::PathSegment::from_name(Symbol::intern("new")));
let new_path = hir::QPath::TypeRelative(ty, new_seg);
let new = P(self.expr(span, hir::ExprPath(new_path), ThinVec::new()));
.resolve_str_path(span, self.crate_root, components, params, is_value)
}
- fn ty_path(&mut self, id: LoweredNodeId, span: Span, qpath: hir::QPath) -> P<hir::Ty> {
+ fn ty_path(&mut self, id: LoweredNodeId, span: Span, qpath: hir::QPath) -> hir::Ty {
let mut id = id;
let node = match qpath {
hir::QPath::Resolved(None, path) => {
}
_ => hir::TyPath(qpath),
};
- P(hir::Ty {
+ hir::Ty {
id: id.node_id,
hir_id: id.hir_id,
node,
span,
- })
+ }
}
/// Invoked to create the lifetime argument for a type `&T`
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum GenericArg {
Lifetime(Lifetime),
- Type(P<Ty>),
+ Type(Ty),
}
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
self.args.is_empty() && self.bindings.is_empty() && !self.parenthesized
}
- pub fn inputs(&self) -> &[P<Ty>] {
+ pub fn inputs(&self) -> &[Ty] {
if self.parenthesized {
for arg in &self.args {
match arg {
/// The never type (`!`)
TyNever,
/// A tuple (`(A, B, C, D,...)`)
- TyTup(HirVec<P<Ty>>),
+ TyTup(HirVec<Ty>),
/// A path to a type definition (`module::module::...::Type`), or an
/// associated type, e.g. `<Vec<T> as Trait>::Type` or `<T>::Target`.
///
/// Represents the header (not the body) of a function declaration
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct FnDecl {
- pub inputs: HirVec<P<Ty>>,
+ pub inputs: HirVec<Ty>,
pub output: FunctionRetTy,
pub variadic: bool,
/// True if this function has an `self`, `&self` or `&mut self` receiver
pub fn encode_opaque(&self, encoder: &mut Encoder) -> EncodeResult {
let bytes: [u8; 16] = unsafe { mem::transmute([self.0.to_le(), self.1.to_le()]) };
- encoder.emit_raw_bytes(&bytes)
+ encoder.emit_raw_bytes(&bytes);
+ Ok(())
}
pub fn decode_opaque<'a>(decoder: &mut Decoder<'a>) -> Result<Fingerprint, String> {
impl serialize::UseSpecializedDecodable for Fingerprint { }
-impl<'a> serialize::SpecializedEncoder<Fingerprint> for serialize::opaque::Encoder<'a> {
+impl serialize::SpecializedEncoder<Fingerprint> for serialize::opaque::Encoder {
fn specialized_encode(&mut self, f: &Fingerprint) -> Result<(), Self::Error> {
f.encode_opaque(self)
}
format,
allow_internal_unstable,
allow_internal_unsafe,
+ local_inner_macros,
edition
});
//! For a more detailed look at what is happening here, check
//! out the [chapter in the rustc guide][c].
//!
-//! [c]: https://rust-lang-nursery.github.io/rustc-guide/traits-canonicalization.html
+//! [c]: https://rust-lang-nursery.github.io/rustc-guide/traits/canonicalization.html
use infer::{InferCtxt, InferOk, InferResult, RegionVariableOrigin, TypeVariableOrigin};
use rustc_data_structures::indexed_vec::Idx;
/// To get a good understanding of what is happening here, check
/// out the [chapter in the rustc guide][c].
///
- /// [c]: https://rust-lang-nursery.github.io/rustc-guide/traits-canonicalization.html#processing-the-canonicalized-query-result
+ /// [c]: https://rust-lang-nursery.github.io/rustc-guide/traits/canonicalization.html#processing-the-canonicalized-query-result
pub fn instantiate_query_result<R>(
&self,
cause: &ObligationCause<'tcx>,
/// To get a good understanding of what is happening here, check
/// out the [chapter in the rustc guide][c].
///
- /// [c]: https://rust-lang-nursery.github.io/rustc-guide/traits-canonicalization.html#canonicalizing-the-query
+ /// [c]: https://rust-lang-nursery.github.io/rustc-guide/traits/canonicalization.html#canonicalizing-the-query
pub fn canonicalize_query<V>(&self, value: &V) -> (V::Canonicalized, CanonicalVarValues<'tcx>)
where
V: Canonicalize<'gcx, 'tcx>,
/// To get a good understanding of what is happening here, check
/// out the [chapter in the rustc guide][c].
///
- /// [c]: https://rust-lang-nursery.github.io/rustc-guide/traits-canonicalization.html#canonicalizing-the-query-result
+ /// [c]: https://rust-lang-nursery.github.io/rustc-guide/traits/canonicalization.html#canonicalizing-the-query-result
pub fn canonicalize_response<V>(
&self,
value: &V,
/// For more information about how skolemization for HRTBs works, see
/// the [rustc guide].
///
- /// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/trait-hrtb.html
+ /// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/traits/hrtb.html
pub fn skolemize_late_bound_regions<T>(&self,
binder: &ty::Binder<T>)
-> (T, SkolemizationMap<'tcx>)
> WARNING: This README is obsolete and will be removed soon! For
> more info on how the current borrowck works, see the [rustc guide].
-[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir-borrowck.html
+[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir/borrowck.html
## Terminology
> WARNING: This README is obsolete and will be removed soon! For
> more info on how the current borrowck works, see the [rustc guide].
-[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir-borrowck.html
+[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir/borrowck.html
## Terminology
"detects name collision with an existing but unstable method"
}
+declare_lint! {
+ pub IRREFUTABLE_LET_PATTERNS,
+ Deny,
+ "detects irrefutable patterns in if-let and while-let statements"
+}
+
declare_lint! {
pub UNUSED_LABELS,
Allow,
BARE_TRAIT_OBJECTS,
ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
UNSTABLE_NAME_COLLISIONS,
+ IRREFUTABLE_LET_PATTERNS,
DUPLICATE_ASSOCIATED_TYPE_BINDINGS,
DUPLICATE_MACRO_EXPORTS,
INTRA_DOC_LINK_RESOLUTION_FAILURE,
sess: Option<&Session>,
from_plugin: bool,
pass: &Box<P>) {
- for &lint in pass.get_lints() {
- self.lints.push((*lint, from_plugin));
+ for lint in pass.get_lints() {
+ self.lints.push((lint, from_plugin));
- let id = LintId::of(*lint);
+ let id = LintId::of(lint);
if self.by_name.insert(lint.name_lower(), Id(id)).is_some() {
let msg = format!("duplicate specification of lint {}", lint.name_lower());
match (sess, from_plugin) {
use errors::{DiagnosticBuilder, DiagnosticId};
use hir::def_id::{CrateNum, LOCAL_CRATE};
-use hir::intravisit::{self, FnKind};
+use hir::intravisit;
use hir;
use lint::builtin::BuiltinLintDiagnostics;
use session::{Session, DiagnosticMessageId};
#[macro_export]
macro_rules! lint_array {
($( $lint:expr ),* $(,)?) => {{
- static ARRAY: LintArray = &[ $( &$lint ),* ];
- ARRAY
+ vec![$($lint),*]
}}
}
-pub type LintArray = &'static [&'static &'static Lint];
+pub type LintArray = Vec<&'static Lint>;
pub trait LintPass {
/// Get descriptions of the lints this `LintPass` object can emit.
fn get_lints(&self) -> LintArray;
}
+#[macro_export]
+macro_rules! late_lint_methods {
+ ($macro:path, $args:tt, [$hir:tt]) => (
+ $macro!($args, [$hir], [
+ fn check_body(a: &$hir hir::Body);
+ fn check_body_post(a: &$hir hir::Body);
+ fn check_name(a: Span, b: ast::Name);
+ fn check_crate(a: &$hir hir::Crate);
+ fn check_crate_post(a: &$hir hir::Crate);
+ fn check_mod(a: &$hir hir::Mod, b: Span, c: ast::NodeId);
+ fn check_mod_post(a: &$hir hir::Mod, b: Span, c: ast::NodeId);
+ fn check_foreign_item(a: &$hir hir::ForeignItem);
+ fn check_foreign_item_post(a: &$hir hir::ForeignItem);
+ fn check_item(a: &$hir hir::Item);
+ fn check_item_post(a: &$hir hir::Item);
+ fn check_local(a: &$hir hir::Local);
+ fn check_block(a: &$hir hir::Block);
+ fn check_block_post(a: &$hir hir::Block);
+ fn check_stmt(a: &$hir hir::Stmt);
+ fn check_arm(a: &$hir hir::Arm);
+ fn check_pat(a: &$hir hir::Pat);
+ fn check_decl(a: &$hir hir::Decl);
+ fn check_expr(a: &$hir hir::Expr);
+ fn check_expr_post(a: &$hir hir::Expr);
+ fn check_ty(a: &$hir hir::Ty);
+ fn check_generic_param(a: &$hir hir::GenericParam);
+ fn check_generics(a: &$hir hir::Generics);
+ fn check_where_predicate(a: &$hir hir::WherePredicate);
+ fn check_poly_trait_ref(a: &$hir hir::PolyTraitRef, b: hir::TraitBoundModifier);
+ fn check_fn(
+ a: hir::intravisit::FnKind<$hir>,
+ b: &$hir hir::FnDecl,
+ c: &$hir hir::Body,
+ d: Span,
+ e: ast::NodeId);
+ fn check_fn_post(
+ a: hir::intravisit::FnKind<$hir>,
+ b: &$hir hir::FnDecl,
+ c: &$hir hir::Body,
+ d: Span,
+ e: ast::NodeId
+ );
+ fn check_trait_item(a: &$hir hir::TraitItem);
+ fn check_trait_item_post(a: &$hir hir::TraitItem);
+ fn check_impl_item(a: &$hir hir::ImplItem);
+ fn check_impl_item_post(a: &$hir hir::ImplItem);
+ fn check_struct_def(
+ a: &$hir hir::VariantData,
+ b: ast::Name,
+ c: &$hir hir::Generics,
+ d: ast::NodeId
+ );
+ fn check_struct_def_post(
+ a: &$hir hir::VariantData,
+ b: ast::Name,
+ c: &$hir hir::Generics,
+ d: ast::NodeId
+ );
+ fn check_struct_field(a: &$hir hir::StructField);
+ fn check_variant(a: &$hir hir::Variant, b: &$hir hir::Generics);
+ fn check_variant_post(a: &$hir hir::Variant, b: &$hir hir::Generics);
+ fn check_lifetime(a: &$hir hir::Lifetime);
+ fn check_path(a: &$hir hir::Path, b: ast::NodeId);
+ fn check_attribute(a: &$hir ast::Attribute);
+
+ /// Called when entering a syntax node that can have lint attributes such
+ /// as `#[allow(...)]`. Called with *all* the attributes of that node.
+ fn enter_lint_attrs(a: &$hir [ast::Attribute]);
+
+ /// Counterpart to `enter_lint_attrs`.
+ fn exit_lint_attrs(a: &$hir [ast::Attribute]);
+ ]);
+ )
+}
/// Trait for types providing lint checks.
///
//
// FIXME: eliminate the duplication with `Visitor`. But this also
// contains a few lint-specific methods with no equivalent in `Visitor`.
-pub trait LateLintPass<'a, 'tcx>: LintPass {
- fn check_body(&mut self, _: &LateContext, _: &'tcx hir::Body) { }
- fn check_body_post(&mut self, _: &LateContext, _: &'tcx hir::Body) { }
- fn check_name(&mut self, _: &LateContext, _: Span, _: ast::Name) { }
- fn check_crate(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Crate) { }
- fn check_crate_post(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Crate) { }
- fn check_mod(&mut self,
- _: &LateContext<'a, 'tcx>,
- _: &'tcx hir::Mod,
- _: Span,
- _: ast::NodeId) { }
- fn check_mod_post(&mut self,
- _: &LateContext<'a, 'tcx>,
- _: &'tcx hir::Mod,
- _: Span,
- _: ast::NodeId) { }
- fn check_foreign_item(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::ForeignItem) { }
- fn check_foreign_item_post(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::ForeignItem) { }
- fn check_item(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Item) { }
- fn check_item_post(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Item) { }
- fn check_local(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Local) { }
- fn check_block(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Block) { }
- fn check_block_post(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Block) { }
- fn check_stmt(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Stmt) { }
- fn check_arm(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Arm) { }
- fn check_pat(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Pat) { }
- fn check_decl(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Decl) { }
- fn check_expr(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Expr) { }
- fn check_expr_post(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Expr) { }
- fn check_ty(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Ty) { }
- fn check_generic_param(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::GenericParam) { }
- fn check_generics(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Generics) { }
- fn check_where_predicate(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::WherePredicate) { }
- fn check_poly_trait_ref(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::PolyTraitRef,
- _: hir::TraitBoundModifier) { }
- fn check_fn(&mut self,
- _: &LateContext<'a, 'tcx>,
- _: FnKind<'tcx>,
- _: &'tcx hir::FnDecl,
- _: &'tcx hir::Body,
- _: Span,
- _: ast::NodeId) { }
- fn check_fn_post(&mut self,
- _: &LateContext<'a, 'tcx>,
- _: FnKind<'tcx>,
- _: &'tcx hir::FnDecl,
- _: &'tcx hir::Body,
- _: Span,
- _: ast::NodeId) { }
- fn check_trait_item(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::TraitItem) { }
- fn check_trait_item_post(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::TraitItem) { }
- fn check_impl_item(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::ImplItem) { }
- fn check_impl_item_post(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::ImplItem) { }
- fn check_struct_def(&mut self,
- _: &LateContext<'a, 'tcx>,
- _: &'tcx hir::VariantData,
- _: ast::Name,
- _: &'tcx hir::Generics,
- _: ast::NodeId) { }
- fn check_struct_def_post(&mut self,
- _: &LateContext<'a, 'tcx>,
- _: &'tcx hir::VariantData,
- _: ast::Name,
- _: &'tcx hir::Generics,
- _: ast::NodeId) { }
- fn check_struct_field(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::StructField) { }
- fn check_variant(&mut self,
- _: &LateContext<'a, 'tcx>,
- _: &'tcx hir::Variant,
- _: &'tcx hir::Generics) { }
- fn check_variant_post(&mut self,
- _: &LateContext<'a, 'tcx>,
- _: &'tcx hir::Variant,
- _: &'tcx hir::Generics) { }
- fn check_lifetime(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Lifetime) { }
- fn check_path(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Path, _: ast::NodeId) { }
- fn check_attribute(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx ast::Attribute) { }
- /// Called when entering a syntax node that can have lint attributes such
- /// as `#[allow(...)]`. Called with *all* the attributes of that node.
- fn enter_lint_attrs(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx [ast::Attribute]) { }
+macro_rules! expand_lint_pass_methods {
+ ($context:ty, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
+ $(#[inline(always)] fn $name(&mut self, $context, $(_: $arg),*) {})*
+ )
+}
- /// Counterpart to `enter_lint_attrs`.
- fn exit_lint_attrs(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx [ast::Attribute]) { }
+macro_rules! declare_late_lint_pass {
+ ([], [$hir:tt], [$($methods:tt)*]) => (
+ pub trait LateLintPass<'a, $hir>: LintPass {
+ expand_lint_pass_methods!(&LateContext<'a, $hir>, [$($methods)*]);
+ }
+ )
+}
+
+late_lint_methods!(declare_late_lint_pass, [], ['tcx]);
+
+#[macro_export]
+macro_rules! expand_combined_late_lint_pass_method {
+ ([$($passes:ident),*], $self: ident, $name: ident, $params:tt) => ({
+ $($self.$passes.$name $params;)*
+ })
+}
+
+#[macro_export]
+macro_rules! expand_combined_late_lint_pass_methods {
+ ($passes:tt, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
+ $(fn $name(&mut self, context: &LateContext<'a, 'tcx>, $($param: $arg),*) {
+ expand_combined_late_lint_pass_method!($passes, self, $name, (context, $($param),*));
+ })*
+ )
+}
+
+#[macro_export]
+macro_rules! declare_combined_late_lint_pass {
+ ([$name:ident, [$($passes:ident: $constructor:expr,)*]], [$hir:tt], $methods:tt) => (
+ #[allow(non_snake_case)]
+ struct $name {
+ $($passes: $passes,)*
+ }
+
+ impl $name {
+ fn new() -> Self {
+ Self {
+ $($passes: $constructor,)*
+ }
+ }
+ }
+
+ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for $name {
+ expand_combined_late_lint_pass_methods!([$($passes),*], $methods);
+ }
+
+ impl LintPass for $name {
+ fn get_lints(&self) -> LintArray {
+ let mut lints = Vec::new();
+ $(lints.extend_from_slice(&self.$passes.get_lints());)*
+ lints
+ }
+ }
+ )
}
pub trait EarlyLintPass: LintPass {
//! For more information about how MIR-based region-checking works,
//! see the [rustc guide].
//!
-//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir-borrowck.html
+//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir/borrowck.html
use ich::{StableHashingContext, NodeIdHashingMode};
use util::nodemap::{FxHashMap, FxHashSet};
fn visit_fn_like_elision(
&mut self,
- inputs: &'tcx [P<hir::Ty>],
+ inputs: &'tcx [hir::Ty],
output: Option<&'tcx P<hir::Ty>>,
) {
debug!("visit_fn_like_elision: enter");
//! MIR datatypes and passes. See the [rustc guide] for more info.
//!
-//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir.html
+//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir/index.html
use graphviz::IntoCow;
use hir::def::CtorKind;
//! See rustc guide chapters on [trait-resolution] and [trait-specialization] for more info on how
//! this works.
//!
-//! [trait-resolution]: https://rust-lang-nursery.github.io/rustc-guide/trait-resolution.html
-//! [trait-specialization]: https://rust-lang-nursery.github.io/rustc-guide/trait-specialization.html
+//! [trait-resolution]: https://rust-lang-nursery.github.io/rustc-guide/traits/resolution.html
+//! [trait-specialization]: https://rust-lang-nursery.github.io/rustc-guide/traits/specialization.html
use hir::def_id::{DefId, LOCAL_CRATE};
use syntax_pos::DUMMY_SP;
..
}) => {
(self.tcx.sess.codemap().def_span(span), decl.inputs.iter()
- .map(|arg| match arg.clone().into_inner().node {
+ .map(|arg| match arg.clone().node {
hir::TyTup(ref tys) => ArgKind::Tuple(
Some(arg.span),
tys.iter()
//! Trait Resolution. See [rustc guide] for more info on how this works.
//!
-//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/trait-resolution.html
+//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/traits/resolution.html
pub use self::SelectionError::*;
pub use self::FulfillmentErrorCode::*;
//! See [rustc guide] for more info on how this works.
//!
-//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/trait-resolution.html#selection
+//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/traits/resolution.html#selection
use self::SelectionCandidate::*;
use self::EvaluationResult::*;
// candidates. See [rustc guide] for more details.
//
// [rustc guide]:
- // https://rust-lang-nursery.github.io/rustc-guide/trait-resolution.html#candidate-assembly
+ // https://rust-lang-nursery.github.io/rustc-guide/traits/resolution.html#candidate-assembly
fn candidate_from_obligation<'o>(&mut self,
stack: &TraitObligationStack<'o, 'tcx>)
// type error. See [rustc guide] for more details.
//
// [rustc guide]:
- // https://rust-lang-nursery.github.io/rustc-guide/trait-resolution.html#confirmation
+ // https://rust-lang-nursery.github.io/rustc-guide/traits/resolution.html#confirmation
fn confirm_candidate(&mut self,
obligation: &TraitObligation<'tcx>,
//! See the [rustc guide] for a bit more detail on how specialization
//! fits together with the rest of the trait machinery.
//!
-//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/trait-specialization.html
+//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/traits/specialization.html
use super::{SelectionContext, FulfillmentContext};
use super::util::impl_trait_ref_and_oblig;
fn position(&self) -> usize;
}
-impl<'buf> TyEncoder for opaque::Encoder<'buf> {
+impl TyEncoder for opaque::Encoder {
#[inline]
fn position(&self) -> usize {
self.position()
}
impl<'enc, 'a, 'tcx> SpecializedEncoder<Fingerprint>
-for CacheEncoder<'enc, 'a, 'tcx, opaque::Encoder<'enc>>
+for CacheEncoder<'enc, 'a, 'tcx, opaque::Encoder>
{
fn specialized_encode(&mut self, f: &Fingerprint) -> Result<(), Self::Error> {
f.encode_opaque(&mut self.encoder)
impl UseSpecializedEncodable for IntEncodedWithFixedSize {}
impl UseSpecializedDecodable for IntEncodedWithFixedSize {}
-impl<'enc> SpecializedEncoder<IntEncodedWithFixedSize> for opaque::Encoder<'enc> {
+impl SpecializedEncoder<IntEncodedWithFixedSize> for opaque::Encoder {
fn specialized_encode(&mut self, x: &IntEncodedWithFixedSize) -> Result<(), Self::Error> {
let start_pos = self.position();
for i in 0 .. IntEncodedWithFixedSize::ENCODED_SIZE {
///
/// [1]: http://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/
/// [2]: http://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/
-/// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/trait-hrtb.html
+/// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/traits/hrtb.html
#[derive(Clone, PartialEq, Eq, Hash, Copy, RustcEncodable, RustcDecodable, PartialOrd, Ord)]
pub enum RegionKind {
// Region bound in a type or fn declaration which will be
TyParam(ref param_ty) => write!(f, "{}", param_ty),
TyAdt(def, substs) => cx.parameterized(f, substs, def.did, &[]),
TyDynamic(data, r) => {
- data.print(f, cx)?;
let r = r.print_to_string(cx);
if !r.is_empty() {
- write!(f, " + {}", r)
+ write!(f, "(")?;
+ }
+ write!(f, "dyn ")?;
+ data.print(f, cx)?;
+ if !r.is_empty() {
+ write!(f, " + {})", r)
} else {
Ok(())
}
format: MacroAttribute(Symbol::intern(name)),
allow_internal_unstable: true,
allow_internal_unsafe: false,
+ local_inner_macros: false,
edition: hygiene::default_edition(),
});
} else {
loss = Some(match hex_value {
0 => Loss::ExactlyZero,
- 1...7 => Loss::LessThanHalf,
+ 1..=7 => Loss::LessThanHalf,
8 => Loss::ExactlyHalf,
- 9...15 => Loss::MoreThanHalf,
+ 9..=15 => Loss::MoreThanHalf,
_ => unreachable!(),
});
}
> WARNING: This README is more or less obsolete, and will be removed
> soon! The new system is described in the [rustc guide].
-[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir-borrowck.html
+[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir/borrowck.html
This pass has the job of enforcing memory safety. This is a subtle
topic. This docs aim to explain both the practice and the theory
}
fn u32(&mut self, val: u32) {
- let at = self.data.len();
- leb128::write_u32_leb128(&mut self.data, at, val);
+ leb128::write_u32_leb128(&mut self.data, val);
}
fn byte(&mut self, val: u8) {
"##,
}
-
-
-register_diagnostics! {
- E0558
-}
'-' | ':' => result.push('.'),
// These are legal symbols
- 'a'...'z' | 'A'...'Z' | '0'...'9' | '_' | '.' | '$' => result.push(c),
+ 'a'..='z' | 'A'..='Z' | '0'..='9' | '_' | '.' | '$' => result.push(c),
_ => {
result.push('$');
use std::env;
use rustc::session::config::nightly_options;
+use rustc_serialize::opaque::Encoder;
/// The first few bytes of files generated by incremental compilation
const FILE_MAGIC: &'static [u8] = b"RSIC";
/// the git commit hash.
const RUSTC_VERSION: Option<&'static str> = option_env!("CFG_VERSION");
-pub fn write_file_header<W: io::Write>(stream: &mut W) -> io::Result<()> {
- stream.write_all(FILE_MAGIC)?;
- stream.write_all(&[(HEADER_FORMAT_VERSION >> 0) as u8,
- (HEADER_FORMAT_VERSION >> 8) as u8])?;
+pub fn write_file_header(stream: &mut Encoder) {
+ stream.emit_raw_bytes(FILE_MAGIC);
+ stream.emit_raw_bytes(&[(HEADER_FORMAT_VERSION >> 0) as u8,
+ (HEADER_FORMAT_VERSION >> 8) as u8]);
let rustc_version = rustc_version();
assert_eq!(rustc_version.len(), (rustc_version.len() as u8) as usize);
- stream.write_all(&[rustc_version.len() as u8])?;
- stream.write_all(rustc_version.as_bytes())?;
-
- Ok(())
+ stream.emit_raw_bytes(&[rustc_version.len() as u8]);
+ stream.emit_raw_bytes(rustc_version.as_bytes());
}
/// Reads the contents of a file with a file header as defined in this module.
use rustc_data_structures::sync::join;
use rustc_serialize::Encodable as RustcEncodable;
use rustc_serialize::opaque::Encoder;
-use std::io::{self, Cursor};
use std::fs;
use std::path::PathBuf;
}
fn save_in<F>(sess: &Session, path_buf: PathBuf, encode: F)
- where F: FnOnce(&mut Encoder) -> io::Result<()>
+ where F: FnOnce(&mut Encoder)
{
debug!("save: storing data in {}", path_buf.display());
}
// generate the data in a memory buffer
- let mut wr = Cursor::new(Vec::new());
- file_format::write_file_header(&mut wr).unwrap();
- match encode(&mut Encoder::new(&mut wr)) {
- Ok(()) => {}
- Err(err) => {
- sess.err(&format!("could not encode dep-graph to `{}`: {}",
- path_buf.display(),
- err));
- return;
- }
- }
+ let mut encoder = Encoder::new(Vec::new());
+ file_format::write_file_header(&mut encoder);
+ encode(&mut encoder);
// write the data out
- let data = wr.into_inner();
+ let data = encoder.into_inner();
match fs::write(&path_buf, data) {
Ok(_) => {
debug!("save: data written to disk successfully");
}
fn encode_dep_graph(tcx: TyCtxt,
- encoder: &mut Encoder)
- -> io::Result<()> {
+ encoder: &mut Encoder) {
// First encode the commandline arguments hash
- tcx.sess.opts.dep_tracking_hash().encode(encoder)?;
+ tcx.sess.opts.dep_tracking_hash().encode(encoder).unwrap();
// Encode the graph data.
let serialized_graph = time(tcx.sess, "getting serialized graph", || {
}
time(tcx.sess, "encoding serialized graph", || {
- serialized_graph.encode(encoder)
- })?;
-
- Ok(())
+ serialized_graph.encode(encoder).unwrap();
+ });
}
fn encode_work_product_index(work_products: &FxHashMap<WorkProductId, WorkProduct>,
- encoder: &mut Encoder) -> io::Result<()> {
+ encoder: &mut Encoder) {
let serialized_products: Vec<_> = work_products
.iter()
.map(|(id, work_product)| {
})
.collect();
- serialized_products.encode(encoder)
+ serialized_products.encode(encoder).unwrap();
}
fn encode_query_cache(tcx: TyCtxt,
- encoder: &mut Encoder)
- -> io::Result<()> {
+ encoder: &mut Encoder) {
time(tcx.sess, "serialize query result cache", || {
- tcx.serialize_query_result_cache(encoder)
+ tcx.serialize_query_result_cache(encoder).unwrap();
})
}
use syntax::ast;
use syntax::attr;
+use syntax::codemap::Spanned;
use syntax::edition::Edition;
use syntax::feature_gate::{AttributeGate, AttributeType, Stability, deprecated_attributes};
use syntax_pos::{BytePos, Span, SyntaxContext};
}
}
+
/// Does nothing as a lint pass, but registers some `Lint`s
/// which are used by other parts of the compiler.
#[derive(Copy, Clone)]
)
}
}
+
+
+declare_lint! {
+ pub ELLIPSIS_INCLUSIVE_RANGE_PATTERNS,
+ Allow,
+ "`...` range patterns are deprecated"
+}
+
+
+pub struct EllipsisInclusiveRangePatterns;
+
+impl LintPass for EllipsisInclusiveRangePatterns {
+ fn get_lints(&self) -> LintArray {
+ lint_array!(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS)
+ }
+}
+
+impl EarlyLintPass for EllipsisInclusiveRangePatterns {
+ fn check_pat(&mut self, cx: &EarlyContext, pat: &ast::Pat) {
+ use self::ast::{PatKind, RangeEnd, RangeSyntax};
+
+ if let PatKind::Range(
+ _, _, Spanned { span, node: RangeEnd::Included(RangeSyntax::DotDotDot) }
+ ) = pat.node {
+ let msg = "`...` range patterns are deprecated";
+ let mut err = cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, span, msg);
+ err.span_suggestion_short_with_applicability(
+ span, "use `..=` for an inclusive range", "..=".to_owned(),
+ // FIXME: outstanding problem with precedence in ref patterns:
+ // https://github.com/rust-lang/rust/issues/51043#issuecomment-392252285
+ Applicability::MaybeIncorrect
+ );
+ err.emit()
+ }
+ }
+}
extern crate syntax_pos;
use rustc::lint;
+use rustc::lint::{LateContext, LateLintPass, LintPass, LintArray};
use rustc::lint::builtin::{BARE_TRAIT_OBJECTS, ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE};
use rustc::session;
use rustc::util;
+use rustc::hir;
+
+use syntax::ast;
+use syntax_pos::Span;
use session::Session;
use syntax::edition::Edition;
/// defined in this crate and the ones defined in
/// `rustc::lint::builtin`).
pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
- macro_rules! add_builtin {
- ($sess:ident, $($name:ident),*,) => (
- {$(
- store.register_late_pass($sess, false, box $name);
- )*}
- )
- }
-
macro_rules! add_early_builtin {
($sess:ident, $($name:ident),*,) => (
{$(
)
}
- macro_rules! add_builtin_with_new {
- ($sess:ident, $($name:ident),*,) => (
- {$(
- store.register_late_pass($sess, false, box $name::new());
- )*}
- )
- }
-
macro_rules! add_early_builtin_with_new {
($sess:ident, $($name:ident),*,) => (
{$(
AnonymousParameters,
UnusedDocComment,
BadRepr,
+ EllipsisInclusiveRangePatterns,
);
add_early_builtin_with_new!(sess,
DeprecatedAttr,
);
- add_builtin!(sess,
- HardwiredLints,
- WhileTrue,
- ImproperCTypes,
- VariantSizeDifferences,
- BoxPointers,
- UnusedAttributes,
- PathStatements,
- UnusedResults,
- NonCamelCaseTypes,
- NonSnakeCase,
- NonUpperCaseGlobals,
- NonShorthandFieldPatterns,
- UnsafeCode,
- UnusedAllocation,
- MissingCopyImplementations,
- UnstableFeatures,
- UnconditionalRecursion,
- InvalidNoMangleItems,
- PluginAsLibrary,
- MutableTransmutes,
- UnionsWithDropFields,
- UnreachablePub,
- TypeAliasBounds,
- UnusedBrokenConst,
- TrivialConstraints,
- );
+ late_lint_methods!(declare_combined_late_lint_pass, [BuiltinCombinedLateLintPass, [
+ HardwiredLints: HardwiredLints,
+ WhileTrue: WhileTrue,
+ ImproperCTypes: ImproperCTypes,
+ VariantSizeDifferences: VariantSizeDifferences,
+ BoxPointers: BoxPointers,
+ UnusedAttributes: UnusedAttributes,
+ PathStatements: PathStatements,
+ UnusedResults: UnusedResults,
+ NonCamelCaseTypes: NonCamelCaseTypes,
+ NonSnakeCase: NonSnakeCase,
+ NonUpperCaseGlobals: NonUpperCaseGlobals,
+ NonShorthandFieldPatterns: NonShorthandFieldPatterns,
+ UnsafeCode: UnsafeCode,
+ UnusedAllocation: UnusedAllocation,
+ MissingCopyImplementations: MissingCopyImplementations,
+ UnstableFeatures: UnstableFeatures,
+ UnconditionalRecursion: UnconditionalRecursion,
+ InvalidNoMangleItems: InvalidNoMangleItems,
+ PluginAsLibrary: PluginAsLibrary,
+ MutableTransmutes: MutableTransmutes,
+ UnionsWithDropFields: UnionsWithDropFields,
+ UnreachablePub: UnreachablePub,
+ TypeAliasBounds: TypeAliasBounds,
+ UnusedBrokenConst: UnusedBrokenConst,
+ TrivialConstraints: TrivialConstraints,
+ TypeLimits: TypeLimits::new(),
+ MissingDoc: MissingDoc::new(),
+ MissingDebugImplementations: MissingDebugImplementations::new(),
+ ]], ['tcx]);
- add_builtin_with_new!(sess,
- TypeLimits,
- MissingDoc,
- MissingDebugImplementations,
- );
+ store.register_late_pass(sess, false, box BuiltinCombinedLateLintPass::new());
add_lint_group!(sess,
"bad_style",
"rust_2018_idioms",
BARE_TRAIT_OBJECTS,
UNREACHABLE_PUB,
- UNUSED_EXTERN_CRATES);
+ UNUSED_EXTERN_CRATES,
+ ELLIPSIS_INCLUSIVE_RANGE_PATTERNS);
// Guidelines for creating a future incompatibility lint:
//
use rustc_serialize::{Encodable, Encoder, SpecializedEncoder, opaque};
use std::hash::Hash;
-use std::io::prelude::*;
-use std::io::Cursor;
use std::path::Path;
use rustc_data_structures::sync::Lrc;
use std::u32;
use rustc::hir::intravisit;
pub struct EncodeContext<'a, 'tcx: 'a> {
- opaque: opaque::Encoder<'a>,
+ opaque: opaque::Encoder,
pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
link_meta: &'a LinkMeta,
}
impl<'a, 'tcx> Encoder for EncodeContext<'a, 'tcx> {
- type Error = <opaque::Encoder<'a> as Encoder>::Error;
+ type Error = <opaque::Encoder as Encoder>::Error;
fn emit_nil(&mut self) -> Result<(), Self::Error> {
Ok(())
// Index the items
i = self.position();
- let index = items.write_index(&mut self.opaque.cursor);
+ let index = items.write_index(&mut self.opaque);
let index_bytes = self.position() - i;
let attrs = tcx.hir.krate_attrs();
if self.tcx.sess.meta_stats() {
let mut zero_bytes = 0;
- for e in self.opaque.cursor.get_ref() {
+ for e in self.opaque.data.iter() {
if *e == 0 {
zero_bytes += 1;
}
link_meta: &LinkMeta)
-> EncodedMetadata
{
- let mut cursor = Cursor::new(vec![]);
- cursor.write_all(METADATA_HEADER).unwrap();
+ let mut encoder = opaque::Encoder::new(vec![]);
+ encoder.emit_raw_bytes(METADATA_HEADER);
// Will be filled with the root position after encoding everything.
- cursor.write_all(&[0, 0, 0, 0]).unwrap();
+ encoder.emit_raw_bytes(&[0, 0, 0, 0]);
- let root = {
+ let (root, mut result) = {
let mut ecx = EncodeContext {
- opaque: opaque::Encoder::new(&mut cursor),
+ opaque: encoder,
tcx,
link_meta,
lazy_state: LazyState::NoNode,
// Encode all the entries and extra information in the crate,
// culminating in the `CrateRoot` which points to all of it.
- ecx.encode_crate_root()
+ let root = ecx.encode_crate_root();
+ (root, ecx.opaque.into_inner())
};
- let mut result = cursor.into_inner();
// Encode the root position.
let header = METADATA_HEADER.len();
use schema::*;
use rustc::hir::def_id::{DefId, DefIndex, DefIndexAddressSpace};
-use std::io::{Cursor, Write};
+use rustc_serialize::opaque::Encoder;
use std::slice;
use std::u32;
self.positions[space_index][array_index] = position.to_le();
}
- pub fn write_index(&self, buf: &mut Cursor<Vec<u8>>) -> LazySeq<Index> {
+ pub fn write_index(&self, buf: &mut Encoder) -> LazySeq<Index> {
let pos = buf.position();
// First we write the length of the lower range ...
- buf.write_all(words_to_bytes(&[(self.positions[0].len() as u32).to_le()])).unwrap();
+ buf.emit_raw_bytes(words_to_bytes(&[(self.positions[0].len() as u32).to_le()]));
// ... then the values in the lower range ...
- buf.write_all(words_to_bytes(&self.positions[0][..])).unwrap();
+ buf.emit_raw_bytes(words_to_bytes(&self.positions[0][..]));
// ... then the values in the higher range.
- buf.write_all(words_to_bytes(&self.positions[1][..])).unwrap();
+ buf.emit_raw_bytes(words_to_bytes(&self.positions[1][..]));
LazySeq::with_position_and_length(pos as usize,
self.positions[0].len() + self.positions[1].len() + 1)
}
// ==============
/// Finds the breakable scope for a given label. This is used for
/// resolving `break` and `continue`.
- pub fn find_breakable_scope(&mut self,
+ pub fn find_breakable_scope(&self,
span: Span,
label: region::Scope)
- -> &mut BreakableScope<'tcx> {
+ -> &BreakableScope<'tcx> {
// find the loop-scope with the correct id
- self.breakable_scopes.iter_mut()
+ self.breakable_scopes.iter()
.rev()
.filter(|breakable_scope| breakable_scope.region_scope == label)
.next()
```compile_fail
match 5u32 {
// This range is ok, albeit pointless.
- 1 ... 1 => {}
+ 1 ..= 1 => {}
// This range is empty, and the compiler can tell.
- 1000 ... 5 => {}
+ 1000 ..= 5 => {}
}
```
"##,
NotUseful => {
match source {
hir::MatchSource::IfLetDesugar { .. } => {
- if printed_if_let_err {
- // we already printed an irrefutable if-let pattern error.
- // We don't want two, that's just confusing.
+ if cx.tcx.features().irrefutable_let_patterns {
+ cx.tcx.lint_node(
+ lint::builtin::IRREFUTABLE_LET_PATTERNS,
+ hir_pat.id, pat.span,
+ "irrefutable if-let pattern");
} else {
- // find the first arm pattern so we can use its span
- let &(ref first_arm_pats, _) = &arms[0];
- let first_pat = &first_arm_pats[0];
- let span = first_pat.0.span;
- struct_span_err!(cx.tcx.sess, span, E0162,
- "irrefutable if-let pattern")
- .span_label(span, "irrefutable pattern")
- .emit();
- printed_if_let_err = true;
+ if printed_if_let_err {
+ // we already printed an irrefutable if-let pattern error.
+ // We don't want two, that's just confusing.
+ } else {
+ // find the first arm pattern so we can use its span
+ let &(ref first_arm_pats, _) = &arms[0];
+ let first_pat = &first_arm_pats[0];
+ let span = first_pat.0.span;
+ struct_span_err!(cx.tcx.sess, span, E0162,
+ "irrefutable if-let pattern")
+ .span_label(span, "irrefutable pattern")
+ .emit();
+ printed_if_let_err = true;
+ }
}
},
hir::MatchSource::WhileLetDesugar => {
- // find the first arm pattern so we can use its span
- let &(ref first_arm_pats, _) = &arms[0];
- let first_pat = &first_arm_pats[0];
- let span = first_pat.0.span;
-
// check which arm we're on.
match arm_index {
// The arm with the user-specified pattern.
0 => {
cx.tcx.lint_node(
- lint::builtin::UNREACHABLE_PATTERNS,
+ lint::builtin::UNREACHABLE_PATTERNS,
hir_pat.id, pat.span,
"unreachable pattern");
},
// The arm with the wildcard pattern.
1 => {
- struct_span_err!(cx.tcx.sess, span, E0165,
- "irrefutable while-let pattern")
- .span_label(span, "irrefutable pattern")
- .emit();
+ if cx.tcx.features().irrefutable_let_patterns {
+ cx.tcx.lint_node(
+ lint::builtin::IRREFUTABLE_LET_PATTERNS,
+ hir_pat.id, pat.span,
+ "irrefutable while-let pattern");
+ } else {
+ // find the first arm pattern so we can use its span
+ let &(ref first_arm_pats, _) = &arms[0];
+ let first_pat = &first_arm_pats[0];
+ let span = first_pat.0.span;
+ struct_span_err!(cx.tcx.sess, span, E0165,
+ "irrefutable while-let pattern")
+ .span_label(span, "irrefutable pattern")
+ .emit();
+ }
},
_ => bug!(),
}
let joined_patterns = match witnesses.len() {
0 => bug!(),
1 => format!("`{}`", witnesses[0]),
- 2...LIMIT => {
+ 2..=LIMIT => {
let (tail, head) = witnesses.split_last().unwrap();
let head: Vec<_> = head.iter().map(|w| w.to_string()).collect();
format!("`{}` and `{}`", head.join("`, `"), tail)
}
PatKind::Slice(ref prefix, ref slice, ref suffix) => {
- let ty = self.tables.node_id_to_type(pat.hir_id);
match ty.sty {
ty::TyRef(_, ty, _) =>
PatternKind::Deref {
pat.span, ty, prefix, slice, suffix))
},
},
-
ty::TySlice(..) |
ty::TyArray(..) =>
self.slice_or_array_pattern(pat.span, ty, prefix, slice, suffix),
-
+ ty::TyError => { // Avoid ICE
+ return Pattern { span: pat.span, ty, kind: Box::new(PatternKind::Wild) };
+ }
ref sty =>
span_bug!(
pat.span,
}
PatKind::Tuple(ref subpatterns, ddpos) => {
- let ty = self.tables.node_id_to_type(pat.hir_id);
match ty.sty {
ty::TyTuple(ref tys) => {
let subpatterns =
PatternKind::Leaf { subpatterns: subpatterns }
}
-
+ ty::TyError => { // Avoid ICE (#50577)
+ return Pattern { span: pat.span, ty, kind: Box::new(PatternKind::Wild) };
+ }
ref sty => span_bug!(pat.span, "unexpected type for tuple pattern: {:?}", sty),
}
}
let var_ty = self.tables.node_id_to_type(pat.hir_id);
let region = match var_ty.sty {
ty::TyRef(r, _, _) => Some(r),
+ ty::TyError => { // Avoid ICE
+ return Pattern { span: pat.span, ty, kind: Box::new(PatternKind::Wild) };
+ }
_ => None,
};
let bm = *self.tables.pat_binding_modes().get(pat.hir_id)
let def = self.tables.qpath_def(qpath, pat.hir_id);
let adt_def = match ty.sty {
ty::TyAdt(adt_def, _) => adt_def,
- ty::TyError => { // Avoid ICE (#50585)
- return Pattern {
- span: pat.span,
- ty,
- kind: Box::new(PatternKind::Wild),
- };
+ ty::TyError => { // Avoid ICE (#50585)
+ return Pattern { span: pat.span, ty, kind: Box::new(PatternKind::Wild) };
}
_ => span_bug!(pat.span,
"tuple struct pattern not applied to an ADT {:?}",
val: Value,
ty: Ty<'tcx>,
) -> &'tcx ty::Const<'tcx> {
- let layout = ecx.tcx.layout_of(ty::ParamEnv::reveal_all().and(ty)).unwrap();
+ let layout = ecx.layout_of(ty).unwrap();
match (val, &layout.abi) {
(Value::Scalar(Scalar::Bits { defined: 0, ..}), _) if layout.is_zst() => {},
(Value::ByRef(..), _) |
def_info: _,
allow_internal_unstable,
allow_internal_unsafe,
+ local_inner_macros,
unstable_feature,
edition,
} => {
def_info: Some((nid, self.krate_span)),
allow_internal_unstable,
allow_internal_unsafe,
+ local_inner_macros,
unstable_feature,
edition,
}
def_info: None,
allow_internal_unstable: false,
allow_internal_unsafe: false,
+ local_inner_macros: false,
unstable_feature: None,
edition: hygiene::default_edition(),
});
kind: MacroKind, force: bool)
-> Result<Def, Determinacy> {
let ast::Path { ref segments, span } = *path;
- let path: Vec<_> = segments.iter().map(|seg| seg.ident).collect();
+ let mut path: Vec<_> = segments.iter().map(|seg| seg.ident).collect();
let invocation = self.invocations[&scope];
let module = invocation.module.get();
self.current_module = if module.is_trait() { module.parent.unwrap() } else { module };
+ // Possibly apply the macro helper hack
+ if self.use_extern_macros && kind == MacroKind::Bang && path.len() == 1 &&
+ path[0].span.ctxt().outer().expn_info().map_or(false, |info| info.local_inner_macros) {
+ let root = Ident::new(keywords::DollarCrate.name(), path[0].span);
+ path.insert(0, root);
+ }
+
if path.len() > 1 {
if !self.use_extern_macros && self.gated_errors.insert(span) {
let msg = "non-ident macro paths are experimental";
RegKind::Integer => {
match self.size.bits() {
1 => dl.i1_align,
- 2...8 => dl.i8_align,
- 9...16 => dl.i16_align,
- 17...32 => dl.i32_align,
- 33...64 => dl.i64_align,
- 65...128 => dl.i128_align,
+ 2..=8 => dl.i8_align,
+ 9..=16 => dl.i16_align,
+ 17..=32 => dl.i32_align,
+ 33..=64 => dl.i64_align,
+ 65..=128 => dl.i128_align,
_ => panic!("unsupported integer: {:?}", self)
}
}
/// Find the smallest Integer type which can represent the signed value.
pub fn fit_signed(x: i128) -> Integer {
match x {
- -0x0000_0000_0000_0080...0x0000_0000_0000_007f => I8,
- -0x0000_0000_0000_8000...0x0000_0000_0000_7fff => I16,
- -0x0000_0000_8000_0000...0x0000_0000_7fff_ffff => I32,
- -0x8000_0000_0000_0000...0x7fff_ffff_ffff_ffff => I64,
+ -0x0000_0000_0000_0080..=0x0000_0000_0000_007f => I8,
+ -0x0000_0000_0000_8000..=0x0000_0000_0000_7fff => I16,
+ -0x0000_0000_8000_0000..=0x0000_0000_7fff_ffff => I32,
+ -0x8000_0000_0000_0000..=0x7fff_ffff_ffff_ffff => I64,
_ => I128
}
}
/// Find the smallest Integer type which can represent the unsigned value.
pub fn fit_unsigned(x: u128) -> Integer {
match x {
- 0...0x0000_0000_0000_00ff => I8,
- 0...0x0000_0000_0000_ffff => I16,
- 0...0x0000_0000_ffff_ffff => I32,
- 0...0xffff_ffff_ffff_ffff => I64,
+ 0..=0x0000_0000_0000_00ff => I8,
+ 0..=0x0000_0000_0000_ffff => I16,
+ 0..=0x0000_0000_ffff_ffff => I32,
+ 0..=0xffff_ffff_ffff_ffff => I64,
_ => I128,
}
}
}
}
- hir::ExprContinue(_) => { tcx.types.never }
+ hir::ExprContinue(destination) => {
+ if let Ok(_) = destination.target_id {
+ tcx.types.never
+ } else {
+ // There was an error, make typecheck fail
+ tcx.types.err
+ }
+ }
hir::ExprRet(ref expr_opt) => {
if self.ret_coercion.is_none() {
struct_span_err!(self.tcx.sess, expr.span, E0572,
convert_variant_ctor(tcx, struct_def.id());
}
},
- hir::ItemExistential(..) |
+ hir::ItemExistential(..) => {}
hir::ItemTy(..) | hir::ItemStatic(..) | hir::ItemConst(..) | hir::ItemFn(..) => {
tcx.generics_of(def_id);
tcx.type_of(def_id);
ItemExistential(hir::ExistTy { impl_trait_fn: None, .. }) => unimplemented!(),
// existential types desugared from impl Trait
ItemExistential(hir::ExistTy { impl_trait_fn: Some(owner), .. }) => {
- tcx.typeck_tables_of(owner).concrete_existential_types
- .get(&def_id)
- .cloned()
- .unwrap_or_else(|| {
- // This can occur if some error in the
- // owner fn prevented us from populating
- // the `concrete_existential_types` table.
- tcx.sess.delay_span_bug(
- DUMMY_SP,
- &format!(
- "owner {:?} has no existential type for {:?} in its tables",
- owner,
- def_id,
- ),
- );
-
- tcx.types.err
- })
+ tcx.typeck_tables_of(owner).concrete_existential_types[&def_id]
},
ItemTrait(..) | ItemTraitAlias(..) |
ItemMod(..) |
}
});
} else if attr.check_name("export_name") {
- if let s @ Some(_) = attr.value_str() {
- codegen_fn_attrs.export_name = s;
+ if let Some(s) = attr.value_str() {
+ if s.as_str().contains("\0") {
+ // `#[export_name = ...]` will be converted to a null-terminated string,
+ // so it may not contain any null characters.
+ struct_span_err!(tcx.sess, attr.span, E0648,
+ "`export_name` may not contain null characters")
+ .emit();
+ }
+ codegen_fn_attrs.export_name = Some(s);
} else {
struct_span_err!(tcx.sess, attr.span, E0558,
- "export_name attribute has invalid format")
+ "`export_name` attribute has invalid format")
.span_label(attr.span, "did you mean #[export_name=\"*\"]?")
.emit();
}
// The ordering relation for strings can't be evaluated at compile time,
// so this doesn't work:
match string {
- "hello" ... "world" => {}
+ "hello" ..= "world" => {}
_ => {}
}
let x = 1u8;
match x {
- 0u8...3i8 => (),
+ 0u8..=3i8 => (),
// error: mismatched types in range: expected u8, found i8
_ => ()
}
let x = 1u8;
match x {
- 0u8...3u8 => (), // ok!
+ 0u8..=3u8 => (), // ok!
_ => ()
}
```
Erroneous code example:
```ignore (error-emitted-at-codegen-which-cannot-be-handled-by-compile_fail)
-#[export_name] // error: export_name attribute has invalid format
+#[export_name] // error: `export_name` attribute has invalid format
pub fn something() {}
fn main() {}
```
"##,
+E0648: r##"
+`export_name` attributes may not contain null characters (`\0`).
+
+```compile_fail,E0648
+#[export_name="\0foo"] // error: `export_name` may not contain null characters
+pub fn bar() {}
+```
+"##,
+
E0689: r##"
This error indicates that the numeric value for the method being passed exists
but the type of the numeric value or binding could not be identified.
[dependencies]
pulldown-cmark = { version = "0.1.2", default-features = false }
-minifier = "0.0.11"
+minifier = "0.0.14"
tempfile = "3"
}));
}
ty::GenericParamDefKind::Type {..} => {
- args.push(hir::GenericArg::Type(P(self.ty_param_to_ty(param.clone()))));
+ args.push(hir::GenericArg::Type(self.ty_param_to_ty(param.clone())));
}
}
}
pub values: Vec<Argument>,
}
-impl<'a> Clean<Arguments> for (&'a [P<hir::Ty>], &'a [Spanned<ast::Name>]) {
+impl<'a> Clean<Arguments> for (&'a [hir::Ty], &'a [Spanned<ast::Name>]) {
fn clean(&self, cx: &DocContext) -> Arguments {
Arguments {
values: self.0.iter().enumerate().map(|(i, ty)| {
}
}
-impl<'a> Clean<Arguments> for (&'a [P<hir::Ty>], hir::BodyId) {
+impl<'a> Clean<Arguments> for (&'a [hir::Ty], hir::BodyId) {
fn clean(&self, cx: &DocContext) -> Arguments {
let body = cx.tcx.hir.body(self.1);
}
impl<'a, A: Copy> Clean<FnDecl> for (&'a hir::FnDecl, A)
- where (&'a [P<hir::Ty>], A): Clean<Arguments>
+ where (&'a [hir::Ty], A): Clean<Arguments>
{
fn clean(&self, cx: &DocContext) -> FnDecl {
FnDecl {
}
});
if let Some(ty) = type_.cloned() {
- ty_substs.insert(ty_param_def, ty.into_inner().clean(cx));
+ ty_substs.insert(ty_param_def, ty.clean(cx));
} else if let Some(default) = default.clone() {
ty_substs.insert(ty_param_def,
default.into_inner().clean(cx));
let intra_link_resolution_failure_name = lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE.name;
let warnings_lint_name = lint::builtin::WARNINGS.name;
let lints = lint::builtin::HardwiredLints.get_lints()
- .iter()
- .chain(rustc_lint::SoftLints.get_lints())
+ .into_iter()
+ .chain(rustc_lint::SoftLints.get_lints().into_iter())
.filter_map(|lint| {
if lint.name == warnings_lint_name ||
lint.name == intra_link_resolution_failure_name {
use std::default::Default;
use std::error;
use std::fmt::{self, Display, Formatter, Write as FmtWrite};
+use std::ffi::OsStr;
use std::fs::{self, File, OpenOptions};
use std::io::prelude::*;
use std::io::{self, BufWriter, BufReader};
// Add all the static files. These may already exist, but we just
// overwrite them anyway to make sure that they're fresh and up-to-date.
- write(cx.dst.join(&format!("rustdoc{}.css", cx.shared.resource_suffix)),
- include_bytes!("static/rustdoc.css"))?;
- write(cx.dst.join(&format!("settings{}.css", cx.shared.resource_suffix)),
- include_bytes!("static/settings.css"))?;
+ write_minify(cx.dst.join(&format!("rustdoc{}.css", cx.shared.resource_suffix)),
+ include_str!("static/rustdoc.css"),
+ enable_minification)?;
+ write_minify(cx.dst.join(&format!("settings{}.css", cx.shared.resource_suffix)),
+ include_str!("static/settings.css"),
+ enable_minification)?;
// To avoid "light.css" to be overwritten, we'll first run over the received themes and only
// then we'll run over the "official" styles.
include_bytes!("static/brush.svg"))?;
write(cx.dst.join(&format!("wheel{}.svg", cx.shared.resource_suffix)),
include_bytes!("static/wheel.svg"))?;
- write(cx.dst.join(&format!("light{}.css", cx.shared.resource_suffix)),
- include_bytes!("static/themes/light.css"))?;
+ write_minify(cx.dst.join(&format!("light{}.css", cx.shared.resource_suffix)),
+ include_str!("static/themes/light.css"),
+ enable_minification)?;
themes.insert("light".to_owned());
- write(cx.dst.join(&format!("dark{}.css", cx.shared.resource_suffix)),
- include_bytes!("static/themes/dark.css"))?;
+ write_minify(cx.dst.join(&format!("dark{}.css", cx.shared.resource_suffix)),
+ include_str!("static/themes/dark.css"),
+ enable_minification)?;
themes.insert("dark".to_owned());
let mut themes: Vec<&String> = themes.iter().collect();
if let Some(ref css) = cx.shared.css_file_extension {
let out = cx.dst.join(&format!("theme{}.css", cx.shared.resource_suffix));
- try_err!(fs::copy(css, out), css);
+ if !enable_minification {
+ try_err!(fs::copy(css, out), css);
+ } else {
+ let mut f = try_err!(File::open(css), css);
+ let mut buffer = String::with_capacity(1000);
+
+ try_err!(f.read_to_string(&mut buffer), css);
+ write_minify(out, &buffer, enable_minification)?;
+ }
}
- write(cx.dst.join(&format!("normalize{}.css", cx.shared.resource_suffix)),
- include_bytes!("static/normalize.css"))?;
+ write_minify(cx.dst.join(&format!("normalize{}.css", cx.shared.resource_suffix)),
+ include_str!("static/normalize.css"),
+ enable_minification)?;
write(cx.dst.join("FiraSans-Regular.woff"),
include_bytes!("static/FiraSans-Regular.woff"))?;
write(cx.dst.join("FiraSans-Medium.woff"),
fn write_minify(dst: PathBuf, contents: &str, enable_minification: bool) -> Result<(), Error> {
if enable_minification {
- write(dst, minifier::js::minify(contents).as_bytes())
+ if dst.extension() == Some(&OsStr::new("css")) {
+ let res = try_none!(minifier::css::minify(contents).ok(), &dst);
+ write(dst, res.as_bytes())
+ } else {
+ write(dst, minifier::js::minify(contents).as_bytes())
+ }
} else {
write(dst, contents.as_bytes())
}
}
pub fn main() {
- const STACK_SIZE: usize = 32_000_000; // 32MB
+ let thread_stack_size: usize = if cfg!(target_os = "haiku") {
+ 16_000_000 // 16MB on Haiku
+ } else {
+ 32_000_000 // 32MB on other platforms
+ };
rustc_driver::set_sigpipe_handler();
env_logger::init();
- let res = std::thread::Builder::new().stack_size(STACK_SIZE).spawn(move || {
+ let res = std::thread::Builder::new().stack_size(thread_stack_size).spawn(move || {
syntax::with_globals(move || {
get_args().map(|args| main_args(&args)).unwrap_or(1)
})
buf <<= 4;
match byte {
- b'A'...b'F' => buf |= byte - b'A' + 10,
- b'a'...b'f' => buf |= byte - b'a' + 10,
- b'0'...b'9' => buf |= byte - b'0',
+ b'A'..=b'F' => buf |= byte - b'A' + 10,
+ b'a'..=b'f' => buf |= byte - b'a' + 10,
+ b'0'..=b'9' => buf |= byte - b'0',
b' '|b'\r'|b'\n'|b'\t' => {
buf >>= 4;
continue
self.bump();
// A leading '0' must be the only digit before the decimal point.
- if let '0' ... '9' = self.ch_or_null() {
+ if let '0' ..= '9' = self.ch_or_null() {
return self.error(InvalidNumber)
}
},
- '1' ... '9' => {
+ '1' ..= '9' => {
while !self.eof() {
match self.ch_or_null() {
- c @ '0' ... '9' => {
+ c @ '0' ..= '9' => {
accum = accum.wrapping_mul(10);
accum = accum.wrapping_add((c as u64) - ('0' as u64));
// Make sure a digit follows the decimal place.
match self.ch_or_null() {
- '0' ... '9' => (),
+ '0' ..= '9' => (),
_ => return self.error(InvalidNumber)
}
let mut dec = 1.0;
while !self.eof() {
match self.ch_or_null() {
- c @ '0' ... '9' => {
+ c @ '0' ..= '9' => {
dec /= 10.0;
res += (((c as isize) - ('0' as isize)) as f64) * dec;
self.bump();
// Make sure a digit follows the exponent place.
match self.ch_or_null() {
- '0' ... '9' => (),
+ '0' ..= '9' => (),
_ => return self.error(InvalidNumber)
}
while !self.eof() {
match self.ch_or_null() {
- c @ '0' ... '9' => {
+ c @ '0' ..= '9' => {
exp *= 10;
exp += (c as usize) - ('0' as usize);
while i < 4 && !self.eof() {
self.bump();
n = match self.ch_or_null() {
- c @ '0' ... '9' => n * 16 + ((c as u16) - ('0' as u16)),
+ c @ '0' ..= '9' => n * 16 + ((c as u16) - ('0' as u16)),
'a' | 'A' => n * 16 + 10,
'b' | 'B' => n * 16 + 11,
'c' | 'C' => n * 16 + 12,
'r' => res.push('\r'),
't' => res.push('\t'),
'u' => match self.decode_hex_escape()? {
- 0xDC00 ... 0xDFFF => {
+ 0xDC00 ..= 0xDFFF => {
return self.error(LoneLeadingSurrogateInHexEscape)
}
// Non-BMP characters are encoded as a sequence of
// two hex escapes, representing UTF-16 surrogates.
- n1 @ 0xD800 ... 0xDBFF => {
+ n1 @ 0xD800 ..= 0xDBFF => {
match (self.next_char(), self.next_char()) {
(Some('\\'), Some('u')) => (),
_ => return self.error(UnexpectedEndOfHexEscape),
'n' => { self.parse_ident("ull", NullValue) }
't' => { self.parse_ident("rue", BooleanValue(true)) }
'f' => { self.parse_ident("alse", BooleanValue(false)) }
- '0' ... '9' | '-' => self.parse_number(),
+ '0' ..= '9' | '-' => self.parse_number(),
'"' => match self.parse_str() {
Ok(s) => StringValue(s),
Err(e) => Error(e),
// except according to those terms.
#[inline]
-pub fn write_to_vec(vec: &mut Vec<u8>, position: usize, byte: u8) {
- if position == vec.len() {
- vec.push(byte);
- } else {
- vec[position] = byte;
- }
+pub fn write_to_vec(vec: &mut Vec<u8>, byte: u8) {
+ vec.push(byte);
}
#[cfg(target_pointer_width = "32")]
macro_rules! impl_write_unsigned_leb128 {
($fn_name:ident, $int_ty:ident) => (
#[inline]
- pub fn $fn_name(out: &mut Vec<u8>, start_position: usize, mut value: $int_ty) -> usize {
- let mut position = start_position;
+ pub fn $fn_name(out: &mut Vec<u8>, mut value: $int_ty) {
for _ in 0 .. leb128_size!($int_ty) {
let mut byte = (value & 0x7F) as u8;
value >>= 7;
byte |= 0x80;
}
- write_to_vec(out, position, byte);
- position += 1;
+ write_to_vec(out, byte);
if value == 0 {
break;
}
}
-
- position - start_position
}
)
}
/// The callback `write` is called once for each position
/// that is to be written to with the byte to be encoded
/// at that position.
-pub fn write_signed_leb128_to<W>(mut value: i128, mut write: W) -> usize
- where W: FnMut(usize, u8)
+pub fn write_signed_leb128_to<W>(mut value: i128, mut write: W)
+ where W: FnMut(u8)
{
- let mut position = 0;
-
loop {
let mut byte = (value as u8) & 0x7f;
value >>= 7;
byte |= 0x80; // Mark this byte to show that more bytes will follow.
}
- write(position, byte);
- position += 1;
+ write(byte);
if !more {
break;
}
}
- position
}
-pub fn write_signed_leb128(out: &mut Vec<u8>, start_position: usize, value: i128) -> usize {
- write_signed_leb128_to(value, |i, v| write_to_vec(out, start_position+i, v))
+pub fn write_signed_leb128(out: &mut Vec<u8>, value: i128) {
+ write_signed_leb128_to(value, |v| write_to_vec(out, v))
}
#[inline]
let mut stream = Vec::new();
for x in 0..62 {
- let pos = stream.len();
- let bytes_written = $write_fn_name(&mut stream, pos, (3u64 << x) as $int_ty);
- assert_eq!(stream.len(), pos + bytes_written);
+ $write_fn_name(&mut stream, (3u64 << x) as $int_ty);
}
let mut position = 0;
let values: Vec<_> = (-500..500).map(|i| i * 0x12345789ABCDEF).collect();
let mut stream = Vec::new();
for &x in &values {
- let pos = stream.len();
- let bytes_written = write_signed_leb128(&mut stream, pos, x);
- assert_eq!(stream.len(), pos + bytes_written);
+ write_signed_leb128(&mut stream, x);
}
let mut pos = 0;
for &x in &values {
#![feature(box_syntax)]
#![feature(core_intrinsics)]
#![feature(specialization)]
+#![feature(never_type)]
#![cfg_attr(test, feature(test))]
pub use self::serialize::{Decoder, Encoder, Decodable, Encodable};
use leb128::{self, read_signed_leb128, write_signed_leb128};
use std::borrow::Cow;
-use std::io::{self, Write};
use serialize;
// -----------------------------------------------------------------------------
// Encoder
// -----------------------------------------------------------------------------
-pub type EncodeResult = io::Result<()>;
+pub type EncodeResult = Result<(), !>;
-pub struct Encoder<'a> {
- pub cursor: &'a mut io::Cursor<Vec<u8>>,
+pub struct Encoder {
+ pub data: Vec<u8>,
}
-impl<'a> Encoder<'a> {
- pub fn new(cursor: &'a mut io::Cursor<Vec<u8>>) -> Encoder<'a> {
- Encoder { cursor: cursor }
+impl Encoder {
+ pub fn new(data: Vec<u8>) -> Encoder {
+ Encoder { data }
}
- pub fn emit_raw_bytes(&mut self, s: &[u8]) -> EncodeResult {
- self.cursor.write_all(s)
+ pub fn into_inner(self) -> Vec<u8> {
+ self.data
}
-}
+ pub fn emit_raw_bytes(&mut self, s: &[u8]) {
+ self.data.extend_from_slice(s);
+ }
+}
macro_rules! write_uleb128 {
($enc:expr, $value:expr, $fun:ident) => {{
- let pos = $enc.cursor.position() as usize;
- let bytes_written = leb128::$fun($enc.cursor.get_mut(), pos, $value);
- $enc.cursor.set_position((pos + bytes_written) as u64);
+ leb128::$fun(&mut $enc.data, $value);
Ok(())
}}
}
macro_rules! write_sleb128 {
($enc:expr, $value:expr) => {{
- let pos = $enc.cursor.position() as usize;
- let bytes_written = write_signed_leb128($enc.cursor.get_mut(), pos, $value as i128);
- $enc.cursor.set_position((pos + bytes_written) as u64);
+ write_signed_leb128(&mut $enc.data, $value as i128);
Ok(())
}}
}
-impl<'a> serialize::Encoder for Encoder<'a> {
- type Error = io::Error;
+impl serialize::Encoder for Encoder {
+ type Error = !;
#[inline]
fn emit_nil(&mut self) -> EncodeResult {
#[inline]
fn emit_u8(&mut self, v: u8) -> EncodeResult {
- let pos = self.cursor.position() as usize;
- leb128::write_to_vec(self.cursor.get_mut(), pos, v);
- self.cursor.set_position((pos + 1) as u64);
+ self.data.push(v);
Ok(())
}
#[inline]
fn emit_str(&mut self, v: &str) -> EncodeResult {
self.emit_usize(v.len())?;
- let _ = self.cursor.write_all(v.as_bytes());
+ self.emit_raw_bytes(v.as_bytes());
Ok(())
}
}
-impl<'a> Encoder<'a> {
+impl Encoder {
#[inline]
pub fn position(&self) -> usize {
- self.cursor.position() as usize
+ self.data.len()
}
}
#[cfg(test)]
mod tests {
use serialize::{Encodable, Decodable};
- use std::io::Cursor;
use std::fmt::Debug;
use super::{Encoder, Decoder};
fn check_round_trip<T: Encodable + Decodable + PartialEq + Debug>(values: Vec<T>) {
- let mut cursor = Cursor::new(Vec::new());
+ let mut encoder = Encoder::new(Vec::new());
for value in &values {
- let mut encoder = Encoder::new(&mut cursor);
Encodable::encode(&value, &mut encoder).unwrap();
}
- let data = cursor.into_inner();
+ let data = encoder.into_inner();
let mut decoder = Decoder::new(&data[..], 0);
for value in values {
impl<T: Generator<Yield = ()>> Future for GenFuture<T> {
type Output = T::Return;
fn poll(self: PinMut<Self>, cx: &mut task::Context) -> Poll<Self::Output> {
- set_task_cx(cx, || match unsafe { PinMut::get_mut(self).0.resume() } {
+ set_task_cx(cx, || match unsafe { PinMut::get_mut_unchecked(self).0.resume() } {
GeneratorState::Yielded(()) => Poll::Pending,
GeneratorState::Complete(x) => Poll::Ready(x),
})
/// The multi-argument form of this macro panics with a string and has the
/// [`format!`] syntax for building a string.
///
+/// See also the macro [`compile_error!`], for raising errors during compilation.
+///
/// [runwrap]: ../std/result/enum.Result.html#method.unwrap
/// [`Option`]: ../std/option/enum.Option.html#method.unwrap
/// [`Result`]: ../std/result/enum.Result.html
/// [`format!`]: ../std/macro.format.html
+/// [`compile_error!`]: ../std/macro.compile_error.html
/// [book]: ../book/second-edition/ch09-01-unrecoverable-errors-with-panic.html
///
/// # Current implementation
/// Unconditionally causes compilation to fail with the given error message when encountered.
///
/// This macro should be used when a crate uses a conditional compilation strategy to provide
- /// better error messages for erroneous conditions.
+ /// better error messages for erroneous conditions. It's the compiler-level form of [`panic!`],
+ /// which emits an error at *runtime*, rather than during compilation.
///
/// # Examples
///
/// Two such examples are macros and `#[cfg]` environments.
///
- /// Emit better compiler error if a macro is passed invalid values.
+ /// Emit better compiler error if a macro is passed invalid values. Without the final branch,
+ /// the compiler would still emit an error, but the error's message would not mention the two
+ /// valid values.
///
/// ```compile_fail
/// macro_rules! give_me_foo_or_bar {
/// #[cfg(not(any(feature = "foo", feature = "bar")))]
/// compile_error!("Either feature \"foo\" or \"bar\" must be enabled for this crate.")
/// ```
+ ///
+ /// [`panic!`]: ../std/macro.panic.html
#[stable(feature = "compile_error_macro", since = "1.20.0")]
#[macro_export]
macro_rules! compile_error {
impl<'a, F: Future> Future for AssertUnwindSafe<F> {
type Output = F::Output;
- fn poll(mut self: PinMut<Self>, cx: &mut task::Context) -> Poll<Self::Output> {
- unsafe {
- let pinned_field = PinMut::new_unchecked(
- &mut PinMut::get_mut(self.reborrow()).0
- );
-
- pinned_field.poll(cx)
- }
+ fn poll(self: PinMut<Self>, cx: &mut task::Context) -> Poll<Self::Output> {
+ let pinned_field = unsafe { PinMut::map_unchecked(self, |x| &mut x.0) };
+ pinned_field.poll(cx)
}
}
// (missing things in `libc` which is empty) so just omit everything
// with an empty module
#[unstable(issue = "0", feature = "std_internals")]
+ #[allow(missing_docs)]
pub mod unix_ext {}
} else {
// On other platforms like Windows document the bare bones of unix
cfg_if! {
if #[cfg(windows)] {
// On windows we'll just be documenting what's already available
+ #[allow(missing_docs)]
pub use self::ext as windows_ext;
} else if #[cfg(any(target_os = "cloudabi", target_arch = "wasm32"))] {
// On CloudABI and wasm right now the shim below doesn't compile, so
// just omit it
#[unstable(issue = "0", feature = "std_internals")]
+ #[allow(missing_docs)]
pub mod windows_ext {}
} else {
// On all other platforms (aka linux/osx/etc) then pull in a "minimal"
let p = cstr(p)?;
let mut stat: stat64 = unsafe { mem::zeroed() };
cvt(unsafe {
- stat64(p.as_ptr(), &mut stat as *mut _ as *mut _)
+ stat64(p.as_ptr(), &mut stat)
})?;
Ok(FileAttr { stat: stat })
}
let p = cstr(p)?;
let mut stat: stat64 = unsafe { mem::zeroed() };
cvt(unsafe {
- lstat64(p.as_ptr(), &mut stat as *mut _ as *mut _)
+ lstat64(p.as_ptr(), &mut stat)
})?;
Ok(FileAttr { stat: stat })
}
mod imp {
#[link(name = "zircon")]
extern {
- fn zx_cprng_draw_new(buffer: *mut u8, len: usize) -> i32;
- }
-
- fn getrandom(buf: &mut [u8]) -> Result<usize, i32> {
- unsafe {
- let status = zx_cprng_draw_new(buf.as_mut_ptr(), buf.len());
- if status == 0 {
- Ok(buf.len())
- } else {
- Err(status)
- }
- }
+ fn zx_cprng_draw(buffer: *mut u8, len: usize);
}
pub fn fill_bytes(v: &mut [u8]) {
- let mut buf = v;
- while !buf.is_empty() {
- let ret = getrandom(buf);
- match ret {
- Err(err) => {
- panic!("kernel zx_cprng_draw call failed! (returned {}, buf.len() {})",
- err, buf.len())
- }
- Ok(actual) => {
- let move_buf = buf;
- buf = &mut move_buf[(actual as usize)..];
- }
- }
- }
+ unsafe { zx_cprng_draw(v.as_mut_ptr(), v.len()) }
}
}
let candidate = &s[i + llvm.len()..];
let all_hex = candidate.chars().all(|c| {
match c {
- 'A' ... 'F' | '0' ... '9' => true,
+ 'A' ..= 'F' | '0' ..= '9' => true,
_ => false,
}
});
#[inline]
pub fn from_u32(value: u32) -> Option<CodePoint> {
match value {
- 0 ... 0x10FFFF => Some(CodePoint { value: value }),
+ 0 ..= 0x10FFFF => Some(CodePoint { value: value }),
_ => None
}
}
#[inline]
pub fn to_char(&self) -> Option<char> {
match self.value {
- 0xD800 ... 0xDFFF => None,
+ 0xD800 ..= 0xDFFF => None,
_ => Some(unsafe { char::from_u32_unchecked(self.value) })
}
}
/// like concatenating ill-formed UTF-16 strings effectively would.
#[inline]
pub fn push(&mut self, code_point: CodePoint) {
- if let trail @ 0xDC00...0xDFFF = code_point.to_u32() {
+ if let trail @ 0xDC00..=0xDFFF = code_point.to_u32() {
if let Some(lead) = (&*self).final_lead_surrogate() {
let len_without_lead_surrogate = self.len() - 3;
self.bytes.truncate(len_without_lead_surrogate);
#[inline]
pub fn ascii_byte_at(&self, position: usize) -> u8 {
match self.bytes[position] {
- ascii_byte @ 0x00 ... 0x7F => ascii_byte,
+ ascii_byte @ 0x00 ..= 0x7F => ascii_byte,
_ => 0xFF
}
}
return None
}
match &self.bytes[(len - 3)..] {
- &[0xED, b2 @ 0xA0...0xAF, b3] => Some(decode_surrogate(b2, b3)),
+ &[0xED, b2 @ 0xA0..=0xAF, b3] => Some(decode_surrogate(b2, b3)),
_ => None
}
}
return None
}
match &self.bytes[..3] {
- &[0xED, b2 @ 0xB0...0xBF, b3] => Some(decode_surrogate(b2, b3)),
+ &[0xED, b2 @ 0xB0..=0xBF, b3] => Some(decode_surrogate(b2, b3)),
_ => None
}
}
/// A literal
Lit(P<Expr>),
/// A range pattern, e.g. `1...2`, `1..=2` or `1..2`
- Range(P<Expr>, P<Expr>, RangeEnd),
+ Range(P<Expr>, P<Expr>, Spanned<RangeEnd>),
/// `[a, b, ..i, y, z]` is represented as:
/// `PatKind::Slice(box [a, b], Some(i), box [y, z])`
Slice(Vec<P<Pat>>, Option<P<Pat>>, Vec<P<Pat>>),
/// An arm of a 'match'.
///
-/// E.g. `0...10 => { println!("match!") }` as in
+/// E.g. `0..=10 => { println!("match!") }` as in
///
/// ```
/// match 123 {
-/// 0...10 => { println!("match!") },
+/// 0..=10 => { println!("match!") },
/// _ => { println!("no match!") },
/// }
/// ```
/// Whether the contents of the macro can use `unsafe`
/// without triggering the `unsafe_code` lint.
allow_internal_unsafe: bool,
+ /// Enables the macro helper hack (`ident!(...)` -> `$crate::ident!(...)`)
+ /// for a given macro.
+ local_inner_macros: bool,
/// The macro's feature name if it is unstable, and the stability feature
unstable_feature: Option<(Symbol, u32)>,
/// Edition of the crate in which the macro is defined
format: ExpnFormat::MacroAttribute(Symbol::intern(&pretty_name)),
allow_internal_unstable: true,
allow_internal_unsafe: false,
+ local_inner_macros: false,
edition: hygiene::default_edition(),
});
format: MacroAttribute(Symbol::intern(&format!("{}", attr.path))),
allow_internal_unstable: false,
allow_internal_unsafe: false,
+ local_inner_macros: false,
edition: ext.edition(),
});
def_site_span: Option<Span>,
allow_internal_unstable,
allow_internal_unsafe,
+ local_inner_macros,
// can't infer this type
unstable_feature: Option<(Symbol, u32)>,
edition| {
format: macro_bang_format(path),
allow_internal_unstable,
allow_internal_unsafe,
+ local_inner_macros,
edition,
});
Ok(())
let opt_expanded = match *ext {
DeclMacro(ref expand, def_span, edition) => {
if let Err(dummy_span) = validate_and_set_expn_info(self, def_span.map(|(_, s)| s),
- false, false, None,
+ false, false, false, None,
edition) {
dummy_span
} else {
def_info,
allow_internal_unstable,
allow_internal_unsafe,
+ local_inner_macros,
unstable_feature,
edition,
} => {
if let Err(dummy_span) = validate_and_set_expn_info(self, def_info.map(|(_, s)| s),
allow_internal_unstable,
allow_internal_unsafe,
+ local_inner_macros,
unstable_feature,
edition) {
dummy_span
format: macro_bang_format(path),
allow_internal_unstable,
allow_internal_unsafe: false,
+ local_inner_macros: false,
edition: hygiene::default_edition(),
});
// FIXME probably want to follow macro_rules macros here.
allow_internal_unstable,
allow_internal_unsafe: false,
+ local_inner_macros: false,
edition,
});
format: MacroAttribute(pretty_name),
allow_internal_unstable: false,
allow_internal_unsafe: false,
+ local_inner_macros: false,
edition: ext.edition(),
};
if body.legacy {
let allow_internal_unstable = attr::contains_name(&def.attrs, "allow_internal_unstable");
let allow_internal_unsafe = attr::contains_name(&def.attrs, "allow_internal_unsafe");
+ let mut local_inner_macros = false;
+ if let Some(macro_export) = attr::find_by_name(&def.attrs, "macro_export") {
+ if let Some(l) = macro_export.meta_item_list() {
+ local_inner_macros = attr::list_contains_name(&l, "local_inner_macros");
+ }
+ }
let unstable_feature = attr::find_stability(&sess.span_diagnostic,
&def.attrs, def.span).and_then(|stability| {
def_info: Some((def.id, def.span)),
allow_internal_unstable,
allow_internal_unsafe,
+ local_inner_macros,
unstable_feature,
edition,
}
use rustc_target::spec::abi::Abi;
use ast::{self, NodeId, PatKind, RangeEnd};
use attr;
+use codemap::Spanned;
use edition::{ALL_EDITIONS, Edition};
use syntax_pos::{Span, DUMMY_SP};
use errors::{DiagnosticBuilder, Handler, FatalError};
// Scoped attributes
(active, tool_attributes, "1.25.0", Some(44690), None),
+ // allow irrefutable patterns in if-let and while-let statements (RFC 2086)
+ (active, irrefutable_let_patterns, "1.27.0", Some(44495), None),
+
// Allows use of the :literal macro fragment specifier (RFC 1576)
(active, macro_literal_matcher, "1.27.0", Some(35625), None),
pattern.span,
"box pattern syntax is experimental");
}
- PatKind::Range(_, _, RangeEnd::Excluded) => {
+ PatKind::Range(_, _, Spanned { node: RangeEnd::Excluded, .. }) => {
gate_feature_post!(&self, exclusive_range_pattern, pattern.span,
"exclusive range pattern syntax is experimental");
}
}
PatKind::Box(inner) => PatKind::Box(folder.fold_pat(inner)),
PatKind::Ref(inner, mutbl) => PatKind::Ref(folder.fold_pat(inner), mutbl),
- PatKind::Range(e1, e2, end) => {
+ PatKind::Range(e1, e2, Spanned { span, node: end }) => {
PatKind::Range(folder.fold_expr(e1),
folder.fold_expr(e2),
- folder.fold_range_end(end))
+ Spanned { span, node: folder.fold_range_end(end) })
},
PatKind::Slice(before, slice, after) => {
PatKind::Slice(before.move_map(|x| folder.fold_pat(x)),
/// Pushes a character to a message string for error reporting
fn push_escaped_char_for_msg(m: &mut String, c: char) {
match c {
- '\u{20}'...'\u{7e}' => {
+ '\u{20}'..='\u{7e}' => {
// Don't escape \, ' or " for user-facing messages
m.push(c);
}
base = 16;
num_digits = self.scan_digits(16, 16);
}
- '0'...'9' | '_' | '.' | 'e' | 'E' => {
+ '0'..='9' | '_' | '.' | 'e' | 'E' => {
num_digits = self.scan_digits(10, 10) + 1;
}
_ => {
_ => panic!("can only parse `..`/`...`/`..=` for ranges \
(checked above)"),
};
+ let op_span = self.span;
// Parse range
let span = lo.to(self.prev_span);
let begin = self.mk_expr(span, ExprKind::Path(qself, path), ThinVec::new());
self.bump();
let end = self.parse_pat_range_end()?;
- pat = PatKind::Range(begin, end, end_kind);
+ let op = Spanned { span: op_span, node: end_kind };
+ pat = PatKind::Range(begin, end, op);
}
token::OpenDelim(token::Brace) => {
if qself.is_some() {
// Try to parse everything else as literal with optional minus
match self.parse_literal_maybe_minus() {
Ok(begin) => {
- if self.eat(&token::DotDotDot) {
+ let op_span = self.span;
+ if self.check(&token::DotDot) || self.check(&token::DotDotEq) ||
+ self.check(&token::DotDotDot) {
+ let end_kind = if self.eat(&token::DotDotDot) {
+ RangeEnd::Included(RangeSyntax::DotDotDot)
+ } else if self.eat(&token::DotDotEq) {
+ RangeEnd::Included(RangeSyntax::DotDotEq)
+ } else if self.eat(&token::DotDot) {
+ RangeEnd::Excluded
+ } else {
+ panic!("impossible case: we already matched \
+ on a range-operator token")
+ };
let end = self.parse_pat_range_end()?;
- pat = PatKind::Range(begin, end,
- RangeEnd::Included(RangeSyntax::DotDotDot));
- } else if self.eat(&token::DotDotEq) {
- let end = self.parse_pat_range_end()?;
- pat = PatKind::Range(begin, end,
- RangeEnd::Included(RangeSyntax::DotDotEq));
- } else if self.eat(&token::DotDot) {
- let end = self.parse_pat_range_end()?;
- pat = PatKind::Range(begin, end, RangeEnd::Excluded);
+ let op = Spanned { span: op_span, node: end_kind };
+ pat = PatKind::Range(begin, end, op);
} else {
pat = PatKind::Lit(begin);
}
if !allow_range_pat {
match pat.node {
- PatKind::Range(_, _, RangeEnd::Included(RangeSyntax::DotDotDot)) => {}
+ PatKind::Range(
+ _, _, Spanned { node: RangeEnd::Included(RangeSyntax::DotDotDot), .. }
+ ) => {},
PatKind::Range(..) => {
let mut err = self.struct_span_err(
pat.span,
use ast::{Attribute, MacDelimiter, GenericArg};
use util::parser::{self, AssocOp, Fixity};
use attr;
-use codemap::{self, CodeMap};
+use codemap::{self, CodeMap, Spanned};
use syntax_pos::{self, BytePos};
use syntax_pos::hygiene::{Mark, SyntaxContext};
use parse::token::{self, BinOpToken, Token};
self.print_pat(inner)?;
}
PatKind::Lit(ref e) => self.print_expr(&**e)?,
- PatKind::Range(ref begin, ref end, ref end_kind) => {
+ PatKind::Range(ref begin, ref end, Spanned { node: ref end_kind, .. }) => {
self.print_expr(begin)?;
self.s.space()?;
match *end_kind {
format: MacroAttribute(Symbol::intern("std_inject")),
allow_internal_unstable: true,
allow_internal_unsafe: false,
+ local_inner_macros: false,
edition: hygiene::default_edition(),
});
sp.with_ctxt(SyntaxContext::empty().apply_mark(mark))
format: MacroAttribute(Symbol::intern("test")),
allow_internal_unstable: true,
allow_internal_unsafe: false,
+ local_inner_macros: false,
edition: hygiene::default_edition(),
});
if let Start = state {
match c {
- '1'...'9' => {
+ '1'..='9' => {
let end = at_next_cp_while(next, is_digit);
match end.next_cp() {
// Yes, this *is* the parameter.
state = WidthArg;
move_to!(next);
},
- '1' ... '9' => {
+ '1' ..= '9' => {
let end = at_next_cp_while(next, is_digit);
state = Prec;
width = Some(Num::from_str(at.slice_between(end).unwrap(), None));
}
}
},
- '0' ... '9' => {
+ '0' ..= '9' => {
let end = at_next_cp_while(next, is_digit);
state = Length;
precision = Some(Num::from_str(at.slice_between(end).unwrap(), None));
fn is_digit(c: char) -> bool {
match c {
- '0' ... '9' => true,
+ '0' ..= '9' => true,
_ => false
}
}
let start = s.find('$')?;
match s[start+1..].chars().next()? {
'$' => return Some((Substitution::Escape, &s[start+2..])),
- c @ '0' ... '9' => {
+ c @ '0' ..= '9' => {
let n = (c as u8) - b'0';
return Some((Substitution::Ordinal(n), &s[start+2..]));
},
fn is_ident_head(c: char) -> bool {
match c {
- 'a' ... 'z' | 'A' ... 'Z' | '_' => true,
+ 'a' ..= 'z' | 'A' ..= 'Z' | '_' => true,
_ => false
}
}
fn is_ident_tail(c: char) -> bool {
match c {
- '0' ... '9' => true,
+ '0' ..= '9' => true,
c => is_ident_head(c)
}
}
def_info: None,
allow_internal_unstable: false,
allow_internal_unsafe: false,
+ local_inner_macros: false,
unstable_feature: None,
edition: hygiene::default_edition(),
});
def_info: None,
allow_internal_unstable: true,
allow_internal_unsafe: false,
+ local_inner_macros: false,
unstable_feature: None,
edition: hygiene::default_edition(),
});
format: MacroAttribute(Symbol::intern("proc_macro")),
allow_internal_unstable: true,
allow_internal_unsafe: false,
+ local_inner_macros: false,
edition: hygiene::default_edition(),
});
let span = DUMMY_SP.apply_mark(mark);
/// Whether the macro is allowed to use `unsafe` internally
/// even if the user crate has `#![forbid(unsafe_code)]`.
pub allow_internal_unsafe: bool,
+ /// Enables the macro helper hack (`ident!(...)` -> `$crate::ident!(...)`)
+ /// for a given macro.
+ pub local_inner_macros: bool,
/// Edition of the crate in which the macro is defined.
pub edition: Edition,
}
CompilerDesugaringKind::DotFill => "...",
CompilerDesugaringKind::QuestionMark => "?",
CompilerDesugaringKind::Catch => "do catch",
- CompilerDesugaringKind::ExistentialReturnType => "existental type",
+ CompilerDesugaringKind::ExistentialReturnType => "existential type",
})
}
}
};
let bytes_per_diff: u8 = match max_line_length {
- 0 ... 0xFF => 1,
- 0x100 ... 0xFFFF => 2,
+ 0 ..= 0xFF => 1,
+ 0x100 ..= 0xFFFF => 2,
_ => 4
};
return Err("stack is empty".to_string());
}
}
- ':' | '#' | ' ' | '.' | '0'...'9' => {
+ ':' | '#' | ' ' | '.' | '0'..='9' => {
let mut flags = Flags::new();
let mut fstate = FormatStateFlags;
match cur {
'#' => flags.alternate = true,
' ' => flags.space = true,
'.' => fstate = FormatStatePrecision,
- '0'...'9' => {
+ '0'..='9' => {
flags.width = cur as usize - '0' as usize;
fstate = FormatStateWidth;
}
(FormatStateFlags, ' ') => {
flags.space = true;
}
- (FormatStateFlags, '0'...'9') => {
+ (FormatStateFlags, '0'..='9') => {
flags.width = cur as usize - '0' as usize;
*fstate = FormatStateWidth;
}
(FormatStateFlags, '.') => {
*fstate = FormatStatePrecision;
}
- (FormatStateWidth, '0'...'9') => {
+ (FormatStateWidth, '0'..='9') => {
let old = flags.width;
flags.width = flags.width * 10 + (cur as usize - '0' as usize);
if flags.width < old {
(FormatStateWidth, '.') => {
*fstate = FormatStatePrecision;
}
- (FormatStatePrecision, '0'...'9') => {
+ (FormatStatePrecision, '0'..='9') => {
let old = flags.precision;
flags.precision = flags.precision * 10 + (cur as usize - '0' as usize);
if flags.precision < old {
let _: <<A>::B>::C; //~ ERROR cannot find type `A` in this scope
let _ = <<A>::B>::C; //~ ERROR cannot find type `A` in this scope
let <<A>::B>::C; //~ ERROR cannot find type `A` in this scope
- let 0 ... <<A>::B>::C; //~ ERROR cannot find type `A` in this scope
+ let 0 ..= <<A>::B>::C; //~ ERROR cannot find type `A` in this scope
//~^ ERROR only char and numeric types are allowed in range patterns
<<A>::B>::C; //~ ERROR cannot find type `A` in this scope
}
pub fn main() {
let x: Box<Trait> = Box::new(Foo);
let _y: &Trait = x; //~ ERROR E0308
- //~| expected type `&Trait`
- //~| found type `std::boxed::Box<Trait>`
+ //~| expected type `&dyn Trait`
+ //~| found type `std::boxed::Box<dyn Trait>`
}
let &&x = &&(&1isize as &T);
// n == m
- let &x = &1isize as &T; //~ ERROR type `&T` cannot be dereferenced
- let &&x = &(&1isize as &T); //~ ERROR type `&T` cannot be dereferenced
- let box x = box 1isize as Box<T>; //~ ERROR type `std::boxed::Box<T>` cannot be dereferenced
+ let &x = &1isize as &T; //~ ERROR type `&dyn T` cannot be dereferenced
+ let &&x = &(&1isize as &T); //~ ERROR type `&dyn T` cannot be dereferenced
+ let box x = box 1isize as Box<T>; //~ ERROR type `std::boxed::Box<dyn T>` cannot be dereferenced
// n > m
let &&x = &1isize as &T;
//~^ ERROR mismatched types
- //~| expected type `T`
+ //~| expected type `dyn T`
//~| found type `&_`
//~| expected trait T, found reference
let &&&x = &(&1isize as &T);
//~^ ERROR mismatched types
- //~| expected type `T`
+ //~| expected type `dyn T`
//~| found type `&_`
//~| expected trait T, found reference
let box box x = box 1isize as Box<T>;
//~^ ERROR mismatched types
- //~| expected type `T`
+ //~| expected type `dyn T`
//~| found type `std::boxed::Box<_>`
}
let z: Box<ToBar> = Box::new(Bar1 {f: 36});
f5.2 = Bar1 {f: 36};
//~^ ERROR mismatched types
- //~| expected type `ToBar`
+ //~| expected type `dyn ToBar`
//~| found type `Bar1`
//~| expected trait ToBar, found struct `Bar1`
//~| ERROR the size for value values of type
let z: Box<ToBar> = Box::new(Bar1 {f: 36});
f5.ptr = Bar1 {f: 36};
//~^ ERROR mismatched types
- //~| expected type `ToBar`
+ //~| expected type `dyn ToBar`
//~| found type `Bar1`
//~| expected trait ToBar, found struct `Bar1`
//~| ERROR the size for value values of type
--- /dev/null
+// gate-test-irrefutable_let_patterns
+
+// Copyright 2015 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.
+
+#[allow(irrefutable_let_patterns)]
+fn main() {
+ if let _ = 5 {}
+ //~^ ERROR 15:12: 15:13: irrefutable if-let pattern [E0162]
+}
let _: () = (box |_: isize| {}) as Box<FnOnce(isize)>;
//~^ ERROR mismatched types
//~| expected type `()`
- //~| found type `std::boxed::Box<std::ops::FnOnce(isize)>`
+ //~| found type `std::boxed::Box<dyn std::ops::FnOnce(isize)>`
let _: () = (box |_: isize, isize| {}) as Box<Fn(isize, isize)>;
//~^ ERROR mismatched types
//~| expected type `()`
- //~| found type `std::boxed::Box<std::ops::Fn(isize, isize)>`
+ //~| found type `std::boxed::Box<dyn std::ops::Fn(isize, isize)>`
let _: () = (box || -> isize { unimplemented!() }) as Box<FnMut() -> isize>;
//~^ ERROR mismatched types
//~| expected type `()`
- //~| found type `std::boxed::Box<std::ops::FnMut() -> isize>`
+ //~| found type `std::boxed::Box<dyn std::ops::FnMut() -> isize>`
needs_fn(1);
//~^ ERROR : std::ops::Fn<(isize,)>`
impl Foo for Baz {
fn bar(&mut self, other: &Foo) {}
//~^ ERROR method `bar` has an incompatible type for trait
- //~| expected type `fn(&mut Baz, &mut Foo)`
- //~| found type `fn(&mut Baz, &Foo)`
+ //~| expected type `fn(&mut Baz, &mut dyn Foo)`
+ //~| found type `fn(&mut Baz, &dyn Foo)`
}
fn main() {}
trait Foo {}
impl<'a> Foo for Foo+'a {}
-//~^ ERROR the object type `Foo + 'a` automatically implements the trait `Foo`
+//~^ ERROR the object type `(dyn Foo + 'a)` automatically implements the trait `Foo`
fn main() {}
let index = 6;
match i {
- 0...index => println!("winner"),
+ 0..=index => println!("winner"),
//~^ ERROR runtime values cannot be referenced in patterns
_ => println!("hello"),
}
fn main() {
size_of_copy::<Misc+Copy>();
//~^ ERROR only auto traits can be used as additional traits in a trait object
- //~| ERROR the trait bound `Misc: std::marker::Copy` is not satisfied
+ //~| ERROR the trait bound `dyn Misc: std::marker::Copy` is not satisfied
}
fn main() {
let t : &Trait = &get_function()();
- //~^ ERROR cannot move a value of type Trait + 'static
+ //~^ ERROR cannot move a value of type (dyn Trait + 'static)
}
//~| WARNING hard error
//~| ERROR floating-point types cannot be used in patterns
//~| WARNING hard error
- 39.0 ... 70.0 => {}, //~ ERROR floating-point types cannot be used in patterns
+ 39.0 ..= 70.0 => {}, //~ ERROR floating-point types cannot be used in patterns
//~| WARNING hard error
//~| ERROR floating-point types cannot be used in patterns
//~| WARNING hard error
fn main() {
(&5isize as &Foo).foo();
- //~^ ERROR: no method named `foo` found for type `&Foo` in the current scope
+ //~^ ERROR: no method named `foo` found for type `&dyn Foo` in the current scope
}
fn object_ref_with_static_bound_not_ok() {
assert_send::<&'static (Dummy+'static)>();
- //~^ ERROR `Dummy + 'static` cannot be shared between threads safely [E0277]
+ //~^ ERROR `(dyn Dummy + 'static)` cannot be shared between threads safely [E0277]
}
fn box_object_with_no_bound_not_ok<'a>() {
assert_send::<Box<Dummy>>();
- //~^ ERROR `Dummy` cannot be sent between threads safely
+ //~^ ERROR `dyn Dummy` cannot be sent between threads safely
}
fn object_with_send_bound_ok() {
// careful with object types, who knows what they close over...
fn test51<'a>() {
assert_send::<&'a Dummy>();
- //~^ ERROR `Dummy + 'a` cannot be shared between threads safely [E0277]
+ //~^ ERROR `(dyn Dummy + 'a)` cannot be shared between threads safely [E0277]
}
fn test52<'a>() {
assert_send::<&'a (Dummy+Sync)>();
// them not ok
fn test_71<'a>() {
assert_send::<Box<Dummy+'a>>();
- //~^ ERROR `Dummy + 'a` cannot be sent between threads safely
+ //~^ ERROR `(dyn Dummy + 'a)` cannot be sent between threads safely
}
fn main() { }
fn test50() {
assert_send::<&'static Dummy>();
- //~^ ERROR `Dummy + 'static` cannot be shared between threads safely [E0277]
+ //~^ ERROR `(dyn Dummy + 'static)` cannot be shared between threads safely [E0277]
}
fn test53() {
assert_send::<Box<Dummy>>();
- //~^ ERROR `Dummy` cannot be sent between threads safely
+ //~^ ERROR `dyn Dummy` cannot be sent between threads safely
}
// ...unless they are properly bounded
let x: Box<HashMap<isize, isize>> = box HashMap::new();
let x: Box<Map<isize, isize>> = x;
let y: Box<Map<usize, isize>> = Box::new(x);
- //~^ ERROR `std::boxed::Box<Map<isize, isize>>: Map<usize, isize>` is not satisfied
+ //~^ ERROR `std::boxed::Box<dyn Map<isize, isize>>: Map<usize, isize>` is not satisfied
}
fn main() {
match 5 {
- 6 ... 1 => { }
+ 6 ..= 1 => { }
_ => { }
};
//~^^^ ERROR lower range bound must be less than or equal to upper
//~^^^ ERROR lower range bound must be less than upper
match 5u64 {
- 0xFFFF_FFFF_FFFF_FFFF ... 1 => { }
+ 0xFFFF_FFFF_FFFF_FFFF ..= 1 => { }
_ => { }
};
//~^^^ ERROR lower range bound must be less than or equal to upper
fn main() {
match "wow" {
- "bar" ... "foo" => { }
+ "bar" ..= "foo" => { }
};
//~^^ ERROR only char and numeric types are allowed in range
//~| start type: &'static str
//~| end type: &'static str
match "wow" {
- 10 ... "what" => ()
+ 10 ..= "what" => ()
};
//~^^ ERROR only char and numeric types are allowed in range
//~| start type: {integer}
//~| end type: &'static str
match 5 {
- 'c' ... 100 => { }
+ 'c' ..= 100 => { }
_ => { }
};
//~^^^ ERROR mismatched types
fn main() {
let x = 0;
match 1 {
- 0 ... x => {}
+ 0 ..= x => {}
//~^ ERROR runtime values cannot be referenced in patterns
};
}
pub unsafe fn test_Bar_load(p: &mut Bar, v: Bar) {
intrinsics::atomic_load(p);
- //~^ ERROR expected basic integer type, found `&std::ops::Fn()`
+ //~^ ERROR expected basic integer type, found `&dyn std::ops::Fn()`
}
pub unsafe fn test_Bar_store(p: &mut Bar, v: Bar) {
intrinsics::atomic_store(p, v);
- //~^ ERROR expected basic integer type, found `&std::ops::Fn()`
+ //~^ ERROR expected basic integer type, found `&dyn std::ops::Fn()`
}
pub unsafe fn test_Bar_xchg(p: &mut Bar, v: Bar) {
intrinsics::atomic_xchg(p, v);
- //~^ ERROR expected basic integer type, found `&std::ops::Fn()`
+ //~^ ERROR expected basic integer type, found `&dyn std::ops::Fn()`
}
pub unsafe fn test_Bar_cxchg(p: &mut Bar, v: Bar) {
intrinsics::atomic_cxchg(p, v, v);
- //~^ ERROR expected basic integer type, found `&std::ops::Fn()`
+ //~^ ERROR expected basic integer type, found `&dyn std::ops::Fn()`
}
pub unsafe fn test_Quux_load(p: &mut Quux, v: Quux) {
trait Foo {}
fn take_foo<F:Foo>(f: F) {}
fn take_object(f: Box<Foo>) { take_foo(f); }
-//~^ ERROR `std::boxed::Box<Foo>: Foo` is not satisfied
+//~^ ERROR `std::boxed::Box<dyn Foo>: Foo` is not satisfied
fn main() {}
}
fn use_bar(t: Box<Bar>) {
- t.bar() //~ ERROR cannot move a value of type Bar
+ t.bar() //~ ERROR cannot move a value of type (dyn Bar + 'static)
}
fn main() { }
fn foo(value: i32) -> Option<$name> {
match value {
$( $value => Some($name::$variant), )* // PatKind::Lit
- $( $value ... 42 => Some($name::$variant), )* // PatKind::Range
+ $( $value ..= 42 => Some($name::$variant), )* // PatKind::Range
_ => None
}
}
});
fn main() {}
-
pub macro mac1() {
let _: Box<PubTr<AssocTy = u8>>;
- //~^ ERROR type `priv_trait::PubTr<AssocTy=u8> + '<empty>` is private
- //~| ERROR type `priv_trait::PubTr<AssocTy=u8> + '<empty>` is private
+ //~^ ERROR type `(dyn priv_trait::PubTr<AssocTy=u8> + '<empty>)` is private
+ //~| ERROR type `(dyn priv_trait::PubTr<AssocTy=u8> + '<empty>)` is private
type InSignatureTy2 = Box<PubTr<AssocTy = u8>>;
- //~^ ERROR type `priv_trait::PubTr<AssocTy=u8> + 'static` is private
+ //~^ ERROR type `(dyn priv_trait::PubTr<AssocTy=u8> + 'static)` is private
trait InSignatureTr2: PubTr<AssocTy = u8> {}
//~^ ERROR trait `priv_trait::PrivTr` is private
}
pub macro mac2() {
let _: Box<PrivTr<AssocTy = u8>>;
- //~^ ERROR type `priv_trait::PrivTr<AssocTy=u8> + '<empty>` is private
- //~| ERROR type `priv_trait::PrivTr<AssocTy=u8> + '<empty>` is private
+ //~^ ERROR type `(dyn priv_trait::PrivTr<AssocTy=u8> + '<empty>)` is private
+ //~| ERROR type `(dyn priv_trait::PrivTr<AssocTy=u8> + '<empty>)` is private
type InSignatureTy1 = Box<PrivTr<AssocTy = u8>>;
- //~^ ERROR type `priv_trait::PrivTr<AssocTy=u8> + 'static` is private
+ //~^ ERROR type `(dyn priv_trait::PrivTr<AssocTy=u8> + 'static)` is private
trait InSignatureTr1: PrivTr<AssocTy = u8> {}
//~^ ERROR trait `priv_trait::PrivTr` is private
}
m::leak_anon2(); //~ ERROR type `m::Priv` is private
m::leak_anon3(); //~ ERROR type `m::Priv` is private
- m::leak_dyn1(); //~ ERROR type `m::Trait + 'static` is private
+ m::leak_dyn1(); //~ ERROR type `(dyn m::Trait + 'static)` is private
m::leak_dyn2(); //~ ERROR type `m::Priv` is private
m::leak_dyn3(); //~ ERROR type `m::Priv` is private
match 10 {
<S as Tr>::A::f::<u8> => {}
//~^ ERROR expected unit struct/variant or constant, found method `<<S as Tr>::A>::f<u8>`
- 0 ... <S as Tr>::A::f::<u8> => {} //~ ERROR only char and numeric types are allowed in range
+ 0 ..= <S as Tr>::A::f::<u8> => {} //~ ERROR only char and numeric types are allowed in range
}
}
// except according to those terms.
-fn func((1, (Some(1), 2...3)): (isize, (Option<isize>, isize))) { }
+fn func((1, (Some(1), 2..=3)): (isize, (Option<isize>, isize))) { }
//~^ ERROR refutable pattern in function argument: `(_, _)` not covered
fn main() {
- let (1, (Some(1), 2...3)) = (1, (None, 2));
+ let (1, (Some(1), 2..=3)) = (1, (None, 2));
//~^ ERROR refutable pattern in local binding: `(_, _)` not covered
}
--- /dev/null
+// Copyright 2015 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.
+
+// should-fail-irrefutable_let_patterns
+fn main() {
+ if let _ = 5 {}
+ //~^ ERROR irrefutable if-let pattern [E0162]
+}
--- /dev/null
+// Copyright 2015 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.
+
+#![feature(irrefutable_let_patterns)]
+
+// should-fail-irrefutable_let_patterns_with_gate
+fn main() {
+ if let _ = 5 {}
+ //~^ ERROR irrefutable if-let pattern [irrefutable_let_patterns]
+}
// A, B, C are resolved as inherent items, their traits don't need to be in scope
C::A; //~ ERROR associated constant `A` is private
//~^ ERROR the trait `assoc_const::C` cannot be made into an object
- //~| ERROR the trait bound `assoc_const::C: assoc_const::A` is not satisfied
+ //~| ERROR the trait bound `dyn assoc_const::C: assoc_const::A` is not satisfied
C::B; // ERROR the trait `assoc_const::C` cannot be made into an object
- //~^ ERROR the trait bound `assoc_const::C: assoc_const::B` is not satisfied
+ //~^ ERROR the trait bound `dyn assoc_const::C: assoc_const::B` is not satisfied
C::C; // OK
}
impl CompareToInts for i64 { }
fn with_obj(c: &CompareToInts) -> bool {
- c.same_as(22) //~ ERROR `CompareToInts: CompareTo<i32>` is not satisfied
+ c.same_as(22) //~ ERROR `dyn CompareToInts: CompareTo<i32>` is not satisfied
}
fn with_trait<C:CompareToInts>(c: &C) -> bool {
}
fn with_ufcs1<C:CompareToInts>(c: &C) -> bool {
- CompareToInts::same_as(c, 22) //~ ERROR `CompareToInts: CompareTo<i32>` is not satisfied
+ CompareToInts::same_as(c, 22) //~ ERROR `dyn CompareToInts: CompareTo<i32>` is not satisfied
}
fn with_ufcs2<C:CompareToInts>(c: &C) -> bool {
// unsize trait
let x: &Bar = &Bar;
- let _ = x as &Foo; //~ERROR trivial cast: `&Bar` as `&Foo`
- let _ = x as *const Foo; //~ERROR trivial cast: `&Bar` as `*const Foo`
+ let _ = x as &Foo; //~ERROR trivial cast: `&Bar` as `&dyn Foo`
+ let _ = x as *const Foo; //~ERROR trivial cast: `&Bar` as `*const dyn Foo`
let _: &Foo = x;
let _: *const Foo = x;
let x: &mut Bar = &mut Bar;
- let _ = x as &mut Foo; //~ERROR trivial cast: `&mut Bar` as `&mut Foo`
- let _ = x as *mut Foo; //~ERROR trivial cast: `&mut Bar` as `*mut Foo`
+ let _ = x as &mut Foo; //~ERROR trivial cast: `&mut Bar` as `&mut dyn Foo`
+ let _ = x as *mut Foo; //~ERROR trivial cast: `&mut Bar` as `*mut dyn Foo`
let _: &mut Foo = x;
let _: *mut Foo = x;
let x: Box<Bar> = Box::new(Bar);
- let _ = x as Box<Foo>; //~ERROR trivial cast: `std::boxed::Box<Bar>` as `std::boxed::Box<Foo>`
+ let _ = x as Box<Foo>; //~ERROR `std::boxed::Box<Bar>` as `std::boxed::Box<dyn Foo>`
let x: Box<Bar> = Box::new(Bar);
let _: Box<Foo> = x;
// functions
fn baz(_x: i32) {}
- let _ = &baz as &Fn(i32); //~ERROR trivial cast: `&fn(i32) {main::baz}` as `&std::ops::Fn(i32)`
+ let _ = &baz as &Fn(i32); //~ERROR `&fn(i32) {main::baz}` as `&dyn std::ops::Fn(i32)`
let _: &Fn(i32) = &baz;
let x = |_x: i32| {};
let _ = &x as &Fn(i32); //~ERROR trivial cast
//~^ ERROR mismatched types
//~| Perhaps two different versions of crate `crate_a1`
//~| expected trait `main::a::Bar`
- //~| expected type `std::boxed::Box<main::a::Bar + 'static>`
- //~| found type `std::boxed::Box<main::a::Bar>`
+ //~| expected type `std::boxed::Box<(dyn main::a::Bar + 'static)>`
+ //~| found type `std::boxed::Box<dyn main::a::Bar>`
}
}
let x: i32 = 5;
let y = x as MyAdd<i32>;
//~^ ERROR E0038
- //~| ERROR cast to unsized type: `i32` as `MyAdd<i32>`
+ //~| ERROR cast to unsized type: `i32` as `dyn MyAdd<i32>`
}
// fn main::{{closure}}(_1: [closure@NodeId(22) d:&'19s D]) -> i32 {
// let mut _0: i32;
// ...
-// let _2: &'15_0rs D;
+// let _2: &'16_0rs D;
// ...
// let mut _3: i32;
// bb0: {
// StorageLive(_2);
-// _2 = &'15_0rs (*(_1.0: &'19s D));
+// _2 = &'16_0rs (*(_1.0: &'19s D));
// StorageLive(_3);
// _3 = ((*_2).0: i32);
// _0 = move _3;
// StorageDead(_3);
-// EndRegion('15_0rs);
+// EndRegion('16_0rs);
// StorageDead(_2);
// return;
// }
// fn main::{{closure}}(_1: [closure@NodeId(22) d:D]) -> i32 {
// let mut _0: i32;
// ...
-// let _2: &'15_0rs D;
+// let _2: &'16_0rs D;
// ...
// let mut _3: i32;
// bb0: {
// StorageLive(_2);
-// _2 = &'15_0rs (_1.0: D);
+// _2 = &'16_0rs (_1.0: D);
// StorageLive(_3);
// _3 = ((*_2).0: i32);
// _0 = move _3;
// StorageDead(_3);
-// EndRegion('15_0rs);
+// EndRegion('16_0rs);
// StorageDead(_2);
// drop(_1) -> [return: bb2, unwind: bb1];
// }
// bb0: {
// Validate(Acquire, [_1: &ReFree(DefId(0/1:11 ~ validate_1[317d]::main[0]::{{closure}}[0]), BrEnv) [closure@NodeId(50)], _2: &ReFree(DefId(0/1:11 ~ validate_1[317d]::main[0]::{{closure}}[0]), BrAnon(0)) mut i32]);
// StorageLive(_3);
-// Validate(Suspend(ReScope(Remainder(BlockRemainder { block: ItemLocalId(22), first_statement_index: 0 }))), [(*_2): i32]);
+// Validate(Suspend(ReScope(Remainder(BlockRemainder { block: ItemLocalId(25), first_statement_index: 0 }))), [(*_2): i32]);
// _3 = &ReErased (*_2);
-// Validate(Acquire, [(*_3): i32/ReScope(Remainder(BlockRemainder { block: ItemLocalId(22), first_statement_index: 0 })) (imm)]);
+// Validate(Acquire, [(*_3): i32/ReScope(Remainder(BlockRemainder { block: ItemLocalId(25), first_statement_index: 0 })) (imm)]);
// StorageLive(_4);
// _4 = (*_3);
// _0 = move _4;
// StorageDead(_4);
-// EndRegion(ReScope(Remainder(BlockRemainder { block: ItemLocalId(22), first_statement_index: 0 })));
+// EndRegion(ReScope(Remainder(BlockRemainder { block: ItemLocalId(25), first_statement_index: 0 })));
// StorageDead(_3);
// return;
// }
// StorageLive(_3);
// StorageLive(_4);
// StorageLive(_5);
-// Validate(Suspend(ReScope(Node(ItemLocalId(9)))), [(*_2): i32]);
+// Validate(Suspend(ReScope(Node(ItemLocalId(12)))), [(*_2): i32]);
// _5 = &ReErased mut (*_2);
-// Validate(Acquire, [(*_5): i32/ReScope(Node(ItemLocalId(9)))]);
+// Validate(Acquire, [(*_5): i32/ReScope(Node(ItemLocalId(12)))]);
// _4 = move _5 as *mut i32 (Misc);
// _3 = move _4;
-// EndRegion(ReScope(Node(ItemLocalId(9))));
+// EndRegion(ReScope(Node(ItemLocalId(12))));
// StorageDead(_4);
// StorageDead(_5);
// Validate(Release, [_0: bool, _3: *mut i32]);
// FIXME: Allow attributes in pattern constexprs?
// would require parens in patterns to allow disambiguation...
+ // —which is now available under the `pattern_parentheses` feature gate
+ // (tracking issue #51087)
reject_expr_parse("match 0 {
- 0...#[attr] 10 => ()
+ 0..=#[attr] 10 => ()
}");
reject_expr_parse("match 0 {
- 0...#[attr] -10 => ()
+ 0..=#[attr] -10 => ()
}");
reject_expr_parse("match 0 {
- 0...-#[attr] 10 => ()
+ 0..=-#[attr] 10 => ()
}");
reject_expr_parse("match 0 {
- 0...#[attr] FOO => ()
+ 0..=#[attr] FOO => ()
}");
// make sure we don't catch this bug again...
def_info: None,
allow_internal_unstable: false,
allow_internal_unsafe: false,
+ local_inner_macros: false,
unstable_feature: None,
edition: hygiene::default_edition(),
});
fn encode_json<T: Encodable>(val: &T, wr: &mut Cursor<Vec<u8>>) {
write!(wr, "{}", json::as_json(val));
}
-fn encode_opaque<T: Encodable>(val: &T, wr: &mut Cursor<Vec<u8>>) {
+fn encode_opaque<T: Encodable>(val: &T, wr: Vec<u8>) {
let mut encoder = opaque::Encoder::new(wr);
val.encode(&mut encoder);
}
pub fn main() {
let target = Foo{baz: false,};
- let mut wr = Cursor::new(Vec::new());
let proto = WireProtocol::JSON;
match proto {
- WireProtocol::JSON => encode_json(&target, &mut wr),
- WireProtocol::Opaque => encode_opaque(&target, &mut wr)
+ WireProtocol::JSON => encode_json(&target, &mut Cursor::new(Vec::new())),
+ WireProtocol::Opaque => encode_opaque(&target, Vec::new())
}
}
--- /dev/null
+// Copyright 2015 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.
+
+#![feature(irrefutable_let_patterns)]
+
+// must-compile-successfully-irrefutable_let_patterns_with_gate
+#[allow(irrefutable_let_patterns)]
+fn main() {
+ if let _ = 5 {}
+
+ while let _ = 5 {
+ break;
+ }
+}
}
match 100 {
- b'a' ... b'z' => {},
+ b'a' ..= b'z' => {},
_ => panic!()
}
pub fn main() {
let x = 2;
let x_message = match x {
- 0 ... 1 => { "not many".to_string() }
+ 0 ..= 1 => { "not many".to_string() }
_ => { "lots".to_string() }
};
assert_eq!(x_message, "lots".to_string());
let y = 2;
let y_message = match y {
- 0 ... 1 => { "not many".to_string() }
+ 0 ..= 1 => { "not many".to_string() }
_ => { "lots".to_string() }
};
assert_eq!(y_message, "lots".to_string());
let z = 1u64;
let z_message = match z {
- 0 ... 1 => { "not many".to_string() }
+ 0 ..= 1 => { "not many".to_string() }
_ => { "lots".to_string() }
};
assert_eq!(z_message, "not many".to_string());
assert_eq!(3, match (x, y) {
(1, 1) => 1,
(2, 2) => 2,
- (1...2, 2) => 3,
+ (1..=2, 2) => 3,
_ => 4,
});
assert_eq!(3, match ((x, y),) {
((1, 1),) => 1,
((2, 2),) => 2,
- ((1...2, 2),) => 3,
+ ((1..=2, 2),) => 3,
_ => 4,
});
}
fn lit_shadow_range() {
assert_eq!(2, match 1 {
1 if false => 1,
- 1...2 => 2,
+ 1..=2 => 2,
_ => 3
});
assert_eq!(2, match x+1 {
0 => 0,
1 if false => 1,
- 1...2 => 2,
+ 1..=2 => 2,
_ => 3
});
assert_eq!(2, match val() {
1 if false => 1,
- 1...2 => 2,
+ 1..=2 => 2,
_ => 3
});
assert_eq!(2, match CONST {
0 => 0,
1 if false => 1,
- 1...2 => 2,
+ 1..=2 => 2,
_ => 3
});
// value is out of the range of second arm, should match wildcard pattern
assert_eq!(3, match 3 {
1 if false => 1,
- 1...2 => 2,
+ 1..=2 => 2,
_ => 3
});
}
fn range_shadow_lit() {
assert_eq!(2, match 1 {
- 1...2 if false => 1,
+ 1..=2 if false => 1,
1 => 2,
_ => 3
});
let x = 0;
assert_eq!(2, match x+1 {
0 => 0,
- 1...2 if false => 1,
+ 1..=2 if false => 1,
1 => 2,
_ => 3
});
assert_eq!(2, match val() {
- 1...2 if false => 1,
+ 1..=2 if false => 1,
1 => 2,
_ => 3
});
assert_eq!(2, match CONST {
0 => 0,
- 1...2 if false => 1,
+ 1..=2 if false => 1,
1 => 2,
_ => 3
});
// ditto
assert_eq!(3, match 3 {
- 1...2 if false => 1,
+ 1..=2 if false => 1,
1 => 2,
_ => 3
});
fn range_shadow_range() {
assert_eq!(2, match 1 {
- 0...2 if false => 1,
- 1...3 => 2,
+ 0..=2 if false => 1,
+ 1..=3 => 2,
_ => 3,
});
let x = 0;
assert_eq!(2, match x+1 {
100 => 0,
- 0...2 if false => 1,
- 1...3 => 2,
+ 0..=2 if false => 1,
+ 1..=3 => 2,
_ => 3,
});
assert_eq!(2, match val() {
- 0...2 if false => 1,
- 1...3 => 2,
+ 0..=2 if false => 1,
+ 1..=3 => 2,
_ => 3,
});
assert_eq!(2, match CONST {
100 => 0,
- 0...2 if false => 1,
- 1...3 => 2,
+ 0..=2 if false => 1,
+ 1..=3 => 2,
_ => 3,
});
// ditto
assert_eq!(3, match 5 {
- 0...2 if false => 1,
- 1...3 => 2,
+ 0..=2 if false => 1,
+ 1..=3 => 2,
_ => 3,
});
}
fn multi_pats_shadow_lit() {
assert_eq!(2, match 1 {
100 => 0,
- 0 | 1...10 if false => 1,
+ 0 | 1..=10 if false => 1,
1 => 2,
_ => 3,
});
fn multi_pats_shadow_range() {
assert_eq!(2, match 1 {
100 => 0,
- 0 | 1...10 if false => 1,
- 1...3 => 2,
+ 0 | 1..=10 if false => 1,
+ 1..=3 => 2,
_ => 3,
});
}
assert_eq!(2, match 1 {
100 => 0,
1 if false => 1,
- 0 | 1...10 => 2,
+ 0 | 1..=10 => 2,
_ => 3,
});
}
fn range_shadow_multi_pats() {
assert_eq!(2, match 1 {
100 => 0,
- 1...3 if false => 1,
- 0 | 1...10 => 2,
+ 1..=3 if false => 1,
+ 0 | 1..=10 => 2,
_ => 3,
});
}
fn main() {
let r = match (Foo::FooNullary, 'a') {
- (Foo::FooUint(..), 'a'...'z') => 1,
+ (Foo::FooUint(..), 'a'..='z') => 1,
(Foo::FooNullary, 'x') => 2,
_ => 0
};
assert_eq!(r, 0);
let r = match (Foo::FooUint(0), 'a') {
- (Foo::FooUint(1), 'a'...'z') => 1,
+ (Foo::FooUint(1), 'a'..='z') => 1,
(Foo::FooUint(..), 'x') => 2,
(Foo::FooNullary, 'a') => 3,
_ => 0
assert_eq!(r, 0);
let r = match ('a', Foo::FooUint(0)) {
- ('a'...'z', Foo::FooUint(1)) => 1,
+ ('a'..='z', Foo::FooUint(1)) => 1,
('x', Foo::FooUint(..)) => 2,
('a', Foo::FooNullary) => 3,
_ => 0
assert_eq!(r, 0);
let r = match ('a', 'a') {
- ('a'...'z', 'b') => 1,
- ('x', 'a'...'z') => 2,
+ ('a'..='z', 'b') => 1,
+ ('x', 'a'..='z') => 2,
_ => 0
};
assert_eq!(r, 0);
let r = match ('a', 'a') {
- ('a'...'z', 'b') => 1,
- ('x', 'a'...'z') => 2,
+ ('a'..='z', 'b') => 1,
+ ('x', 'a'..='z') => 2,
('a', 'a') => 3,
_ => 0
};
// Regression test for #18060: match arms were matching in the wrong order.
fn main() {
- assert_eq!(2, match (1, 3) { (0, 2...5) => 1, (1, 3) => 2, (_, 2...5) => 3, (_, _) => 4 });
- assert_eq!(2, match (1, 3) { (1, 3) => 2, (_, 2...5) => 3, (_, _) => 4 });
- assert_eq!(2, match (1, 7) { (0, 2...5) => 1, (1, 7) => 2, (_, 2...5) => 3, (_, _) => 4 });
+ assert_eq!(2, match (1, 3) { (0, 2..=5) => 1, (1, 3) => 2, (_, 2..=5) => 3, (_, _) => 4 });
+ assert_eq!(2, match (1, 3) { (1, 3) => 2, (_, 2..=5) => 3, (_, _) => 4 });
+ assert_eq!(2, match (1, 7) { (0, 2..=5) => 1, (1, 7) => 2, (_, 2..=5) => 3, (_, _) => 4 });
}
fn main() {
match '5' {
- LOW_RANGE...HIGH_RANGE => (),
+ LOW_RANGE..=HIGH_RANGE => (),
_ => ()
};
}
std::intrinsics::type_name::<NT>(),
// DST
std::intrinsics::type_name::<DST>()
- )}, ("[u8]", "str", "std::marker::Send", "NT", "DST"));
+ )}, ("[u8]", "str", "dyn std::marker::Send", "NT", "DST"));
}
fn main() {
match 42 {
- m::START...m::END => {},
- 0...m::END => {},
- m::START...59 => {},
+ m::START..=m::END => {},
+ 0..=m::END => {},
+ m::START..=59 => {},
_ => {},
}
}
let x = 'a';
let y = match x {
- 'a'...'b' if false => "one",
+ 'a'..='b' if false => "one",
'a' => "two",
- 'a'...'b' => "three",
+ 'a'..='b' => "three",
_ => panic!("what?"),
};
let x = 4;
match x {
ref r if *r < 0 => println!("got negative num {} < 0", r),
- e @ 1 ... 100 => println!("got number within range [1,100] {}", e),
+ e @ 1 ..= 100 => println!("got number within range [1,100] {}", e),
_ => println!("no"),
}
}
const FOO: f64 = 10.0;
match 0.0 {
- 0.0 ... FOO => (),
+ 0.0 ..= FOO => (),
_ => ()
}
}
}
macro_rules! catch_range {
- ($s:literal ... $e:literal) => {
- &format!("macro caught literal: {} ... {}", $s, $e)
+ ($s:literal ..= $e:literal) => {
+ &format!("macro caught literal: {} ..= {}", $s, $e)
};
- (($s:expr) ... ($e:expr)) => { // Must use ')' before '...'
- &format!("macro caught expr: {} ... {}", $s, $e)
+ (($s:expr) ..= ($e:expr)) => { // Must use ')' before '..='
+ &format!("macro caught expr: {} ..= {}", $s, $e)
};
}
macro_rules! pat_match {
- ($s:literal ... $e:literal) => {
+ ($s:literal ..= $e:literal) => {
match 3 {
- $s ... $e => "literal, in range",
+ $s ..= $e => "literal, in range",
_ => "literal, other",
}
};
assert_eq!(mtester!('c'), "macro caught literal: c");
assert_eq!(mtester!(-1.2), "macro caught literal: -1.2");
assert_eq!(two_negative_literals!(-2 -3), "macro caught literals: -2, -3");
- assert_eq!(catch_range!(2 ... 3), "macro caught literal: 2 ... 3");
+ assert_eq!(catch_range!(2 ..= 3), "macro caught literal: 2 ..= 3");
assert_eq!(match_attr!(#[attr] 1), "attr matched literal");
assert_eq!(test_user!(10, 20), "literal");
assert_eq!(mtester!(false), "macro caught literal: false");
assert_eq!(mtester!(true), "macro caught literal: true");
match_produced_attr!("a");
let _a = LiteralProduced;
- assert_eq!(pat_match!(1 ... 3), "literal, in range");
- assert_eq!(pat_match!(4 ... 6), "literal, other");
+ assert_eq!(pat_match!(1 ..= 3), "literal, in range");
+ assert_eq!(pat_match!(4 ..= 6), "literal, other");
// Cases where 'expr' catches
assert_eq!(mtester!((-1.2)), "macro caught expr: -1.2");
assert_eq!(only_expr!(-1.2), "macro caught expr: -1.2");
assert_eq!(mtester!((1 + 3)), "macro caught expr: 4");
assert_eq!(mtester_dbg!(()), "macro caught expr: ()");
- assert_eq!(catch_range!((1 + 1) ... (2 + 2)), "macro caught expr: 2 ... 4");
+ assert_eq!(catch_range!((1 + 1) ..= (2 + 2)), "macro caught expr: 2 ..= 4");
assert_eq!(match_attr!(#[attr] (1 + 2)), "attr matched expr");
assert_eq!(test_user!(10, (20 + 2)), "expr");
pub fn main() {
match 1 {
- 1 ... 3 => {}
+ 1 ..= 3 => {}
_ => panic!("should match range")
}
match 1 {
- 1 ... 3u16 => {}
+ 1 ..= 3u16 => {}
_ => panic!("should match range with inferred start type")
}
match 1 {
- 1u16 ... 3 => {}
+ 1u16 ..= 3 => {}
_ => panic!("should match range with inferred end type")
}
}
pub fn main() {
match 7 {
- s...e => (),
+ s..=e => (),
_ => (),
}
}
pub fn main() {
match 5_usize {
- 1_usize...5_usize => {}
+ 1_usize..=5_usize => {}
_ => panic!("should match range"),
}
match 1_usize {
_ => panic!("should match range start"),
}
match 5_usize {
- 6_usize...7_usize => panic!("shouldn't match range"),
+ 6_usize..=7_usize => panic!("shouldn't match range"),
_ => {}
}
match 7_usize {
}
match 5_usize {
1_usize => panic!("should match non-first range"),
- 2_usize...6_usize => {}
+ 2_usize..=6_usize => {}
_ => panic!("math is broken")
}
match 'c' {
- 'a'...'z' => {}
+ 'a'..='z' => {}
_ => panic!("should suppport char ranges")
}
match -3 {
- -7...5 => {}
+ -7..=5 => {}
_ => panic!("should match signed range")
}
match 3.0f64 {
- 1.0...5.0 => {}
+ 1.0..=5.0 => {}
_ => panic!("should match float range")
}
match -1.5f64 {
- -3.6...3.6 => {}
+ -3.6..=3.6 => {}
_ => panic!("should match negative float range")
}
match 3.5 {
pub fn main() {
let i = 5;
match &&&&i {
- 1 ... 3 => panic!(),
- 3 ... 8 => {},
+ 1 ..= 3 => panic!(),
+ 3 ..= 8 => {},
_ => panic!(),
}
}
LL | g1(|_: (), _: ()| {}); //~ ERROR type mismatch
| ^^ -------------- found signature of `fn((), ()) -> _`
| |
- | expected signature of `for<'r> fn(&'r (), std::boxed::Box<for<'s> std::ops::Fn(&'s ()) + 'static>) -> _`
+ | expected signature of `for<'r> fn(&'r (), std::boxed::Box<(dyn for<'s> std::ops::Fn(&'s ()) + 'static)>) -> _`
|
note: required by `g1`
--> $DIR/anonymous-higher-ranked-lifetime.rs:33:1
LL | g3(|_: (), _: ()| {}); //~ ERROR type mismatch
| ^^ -------------- found signature of `fn((), ()) -> _`
| |
- | expected signature of `for<'s> fn(&'s (), std::boxed::Box<for<'r> std::ops::Fn(&'r ()) + 'static>) -> _`
+ | expected signature of `for<'s> fn(&'s (), std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r ()) + 'static)>) -> _`
|
note: required by `g3`
--> $DIR/anonymous-higher-ranked-lifetime.rs:35:1
LL | h1(|_: (), _: (), _: (), _: ()| {}); //~ ERROR type mismatch
| ^^ ---------------------------- found signature of `fn((), (), (), ()) -> _`
| |
- | expected signature of `for<'r, 's> fn(&'r (), std::boxed::Box<for<'t0> std::ops::Fn(&'t0 ()) + 'static>, &'s (), for<'t0, 't1> fn(&'t0 (), &'t1 ())) -> _`
+ | expected signature of `for<'r, 's> fn(&'r (), std::boxed::Box<(dyn for<'t0> std::ops::Fn(&'t0 ()) + 'static)>, &'s (), for<'t0, 't1> fn(&'t0 (), &'t1 ())) -> _`
|
note: required by `h1`
--> $DIR/anonymous-higher-ranked-lifetime.rs:39:1
LL | h2(|_: (), _: (), _: (), _: ()| {}); //~ ERROR type mismatch
| ^^ ---------------------------- found signature of `fn((), (), (), ()) -> _`
| |
- | expected signature of `for<'r, 't0> fn(&'r (), std::boxed::Box<for<'s> std::ops::Fn(&'s ()) + 'static>, &'t0 (), for<'s, 't1> fn(&'s (), &'t1 ())) -> _`
+ | expected signature of `for<'r, 't0> fn(&'r (), std::boxed::Box<(dyn for<'s> std::ops::Fn(&'s ()) + 'static)>, &'t0 (), for<'s, 't1> fn(&'s (), &'t1 ())) -> _`
|
note: required by `h2`
--> $DIR/anonymous-higher-ranked-lifetime.rs:40:1
| ^^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object
|
= note: method `foo` has a non-standard `self` type
- = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::boxed::Box<Foo>>` for `std::boxed::Box<usize>`
+ = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::boxed::Box<dyn Foo>>` for `std::boxed::Box<usize>`
error: aborting due to 2 previous errors
-error[E0620]: cast to unsized type: `&{integer}` as `std::marker::Send`
+error[E0620]: cast to unsized type: `&{integer}` as `dyn std::marker::Send`
--> $DIR/cast-to-unsized-trait-object-suggestion.rs:12:5
|
LL | &1 as Send; //~ ERROR cast to unsized
| |
| help: try casting to a reference instead: `&Send`
-error[E0620]: cast to unsized type: `std::boxed::Box<{integer}>` as `std::marker::Send`
+error[E0620]: cast to unsized type: `std::boxed::Box<{integer}>` as `dyn std::marker::Send`
--> $DIR/cast-to-unsized-trait-object-suggestion.rs:13:5
|
LL | Box::new(1) as Send; //~ ERROR cast to unsized
match 10 {
1..10 => {},
- 9...10 => {},
+ 9..=10 => {},
_ => {},
}
match 10 {
1..10 => {},
- 10...10 => {},
+ 10..=10 => {},
_ => {},
}
match 10 {
1..10 => {},
- 8...9 => {},
+ 8..=9 => {},
_ => {},
}
match 10 {
1..10 => {},
- 9...9 => {},
+ 9..=9 => {},
_ => {},
}
}
warning: unreachable pattern
--> $DIR/issue-43253.rs:45:9
|
-LL | 8...9 => {},
+LL | 8..=9 => {},
| ^^^^^
warning: unreachable pattern
--> $DIR/issue-43253.rs:51:9
|
-LL | 9...9 => {},
+LL | 9..=9 => {},
| ^^^^^
--- /dev/null
+// Copyright 2018 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.
+
+fn main() {
+ |_: [_; continue]| {}; //~ ERROR: `continue` outside of loop
+
+ while |_: [_; continue]| {} {} //~ ERROR: `break` or `continue` with no label
+
+ while |_: [_; break]| {} {} //~ ERROR: `break` or `continue` with no label
+}
--- /dev/null
+error[E0268]: `continue` outside of loop
+ --> $DIR/closure-array-break-length.rs:12:13
+ |
+LL | |_: [_; continue]| {}; //~ ERROR: `continue` outside of loop
+ | ^^^^^^^^ cannot break outside of a loop
+
+error[E0590]: `break` or `continue` with no label in the condition of a `while` loop
+ --> $DIR/closure-array-break-length.rs:14:19
+ |
+LL | while |_: [_; continue]| {} {} //~ ERROR: `break` or `continue` with no label
+ | ^^^^^^^^ unlabeled `continue` in the condition of a `while` loop
+
+error[E0590]: `break` or `continue` with no label in the condition of a `while` loop
+ --> $DIR/closure-array-break-length.rs:16:19
+ |
+LL | while |_: [_; break]| {} {} //~ ERROR: `break` or `continue` with no label
+ | ^^^^^ unlabeled `break` in the condition of a `while` loop
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0268, E0590.
+For more information about an error, try `rustc --explain E0268`.
fn main() {
const MIN: i8 = -5;
match 5i8 {
- MIN...-1 => {},
+ MIN..=-1 => {},
_ => {},
}
}
--- /dev/null
+// Copyright 2018 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.
+
+// compile-pass
+
+pub trait Nullable {
+ const NULL: Self;
+
+ fn is_null(&self) -> bool;
+}
+
+impl<T> Nullable for *const T {
+ const NULL: Self = 0 as *const T;
+
+ fn is_null(&self) -> bool {
+ *self == Self::NULL
+ }
+}
+
+fn main() {
+}
fn main() {
let n: Int = 40;
match n {
- 0...10 => {},
- 10...BAR => {}, //~ ERROR lower range bound must be less than or equal to upper
+ 0..=10 => {},
+ 10..=BAR => {}, //~ ERROR lower range bound must be less than or equal to upper
_ => {},
}
}
error[E0030]: lower range bound must be less than or equal to upper
--> $DIR/ref_to_int_match.rs:15:9
|
-LL | 10...BAR => {}, //~ ERROR lower range bound must be less than or equal to upper
+LL | 10..=BAR => {}, //~ ERROR lower range bound must be less than or equal to upper
| ^^ lower bound larger than upper bound
error: aborting due to previous error
-error[E0277]: the size for value values of type `std::fmt::Debug + std::marker::Sync + 'static` cannot be known at compilation time
+error[E0277]: the size for value values of type `(dyn std::fmt::Debug + std::marker::Sync + 'static)` cannot be known at compilation time
--> $DIR/const-unsized.rs:13:29
|
LL | const CONST_0: Debug+Sync = *(&0 as &(Debug+Sync));
| ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
- = help: the trait `std::marker::Sized` is not implemented for `std::fmt::Debug + std::marker::Sync + 'static`
+ = help: the trait `std::marker::Sized` is not implemented for `(dyn std::fmt::Debug + std::marker::Sync + 'static)`
= note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= note: constant expressions must have a statically known size
= note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= note: constant expressions must have a statically known size
-error[E0277]: the size for value values of type `std::fmt::Debug + std::marker::Sync + 'static` cannot be known at compilation time
+error[E0277]: the size for value values of type `(dyn std::fmt::Debug + std::marker::Sync + 'static)` cannot be known at compilation time
--> $DIR/const-unsized.rs:19:31
|
LL | static STATIC_1: Debug+Sync = *(&1 as &(Debug+Sync));
| ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
- = help: the trait `std::marker::Sized` is not implemented for `std::fmt::Debug + std::marker::Sync + 'static`
+ = help: the trait `std::marker::Sized` is not implemented for `(dyn std::fmt::Debug + std::marker::Sync + 'static)`
= note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= note: constant expressions must have a statically known size
LL | type G = 'static + (Send)::AssocTy;
| ^^^^^^^^^^^^^^^^^^^^^^^^^ ambiguous associated type
|
- = note: specify the type using the syntax `<std::marker::Send + 'static as Trait>::AssocTy`
+ = note: specify the type using the syntax `<(dyn std::marker::Send + 'static) as Trait>::AssocTy`
error[E0223]: ambiguous associated type
--> $DIR/bad-assoc-ty.rs:43:10
LL | type H = Fn(u8) -> (u8)::Output;
| ^^^^^^^^^^^^^^^^^^^^^^ ambiguous associated type
|
- = note: specify the type using the syntax `<std::ops::Fn(u8) -> u8 + 'static as Trait>::Output`
+ = note: specify the type using the syntax `<(dyn std::ops::Fn(u8) -> u8 + 'static) as Trait>::Output`
error: aborting due to 15 previous errors
let s = "hoho";
match s {
- "hello" ... "world" => {}
+ "hello" ..= "world" => {}
//~^ ERROR only char and numeric types are allowed in range patterns
_ => {}
}
error[E0029]: only char and numeric types are allowed in range patterns
--> $DIR/E0029-teach.rs:17:9
|
-LL | "hello" ... "world" => {}
+LL | "hello" ..= "world" => {}
| ^^^^^^^^^^^^^^^^^^^ ranges require char or numeric types
|
= note: start type: &'static str
let s = "hoho";
match s {
- "hello" ... "world" => {}
+ "hello" ..= "world" => {}
//~^ ERROR only char and numeric types are allowed in range patterns
_ => {}
}
error[E0029]: only char and numeric types are allowed in range patterns
--> $DIR/E0029.rs:15:9
|
-LL | "hello" ... "world" => {}
+LL | "hello" ..= "world" => {}
| ^^^^^^^^^^^^^^^^^^^ ranges require char or numeric types
|
= note: start type: &'static str
fn main() {
match 5u32 {
- 1000 ... 5 => {}
+ 1000 ..= 5 => {}
//~^ ERROR lower range bound must be less than or equal to upper
}
}
error[E0030]: lower range bound must be less than or equal to upper
--> $DIR/E0030-teach.rs:15:9
|
-LL | 1000 ... 5 => {}
+LL | 1000 ..= 5 => {}
| ^^^^ lower bound larger than upper bound
|
= note: When matching against a range, the compiler verifies that the range is non-empty. Range patterns include both end-points, so this is equivalent to requiring the start of the range to be less than or equal to the end of the range.
fn main() {
match 5u32 {
- 1000 ... 5 => {}
+ 1000 ..= 5 => {}
//~^ ERROR lower range bound must be less than or equal to upper
}
}
error[E0030]: lower range bound must be less than or equal to upper
--> $DIR/E0030.rs:14:9
|
-LL | 1000 ... 5 => {}
+LL | 1000 ..= 5 => {}
| ^^^^ lower bound larger than upper bound
error: aborting due to previous error
|
= note: method `foo` has no receiver
-error[E0033]: type `&SomeTrait` cannot be dereferenced
+error[E0033]: type `&dyn SomeTrait` cannot be dereferenced
--> $DIR/E0033-teach.rs:23:9
|
LL | let &invalid = trait_obj;
- | ^^^^^^^^ type `&SomeTrait` cannot be dereferenced
+ | ^^^^^^^^ type `&dyn SomeTrait` cannot be dereferenced
|
= note: This error indicates that a pointer to a trait type cannot be implicitly dereferenced by a pattern. Every trait defines a type, but because the size of trait implementors isn't fixed, this type has no compile-time size. Therefore, all accesses to trait types must be through pointers. If you encounter this error you should try to avoid dereferencing the pointer.
|
= note: method `foo` has no receiver
-error[E0033]: type `&SomeTrait` cannot be dereferenced
+error[E0033]: type `&dyn SomeTrait` cannot be dereferenced
--> $DIR/E0033.rs:21:9
|
LL | let &invalid = trait_obj;
- | ^^^^^^^^ type `&SomeTrait` cannot be dereferenced
+ | ^^^^^^^^ type `&dyn SomeTrait` cannot be dereferenced
error: aborting due to 3 previous errors
fn main() {
let x = 1u8;
match x {
- 0u8...3i8 => (), //~ ERROR E0308
+ 0u8..=3i8 => (), //~ ERROR E0308
_ => ()
}
}
error[E0308]: mismatched types
--> $DIR/E0308-4.rs:14:9
|
-LL | 0u8...3i8 => (), //~ ERROR E0308
+LL | 0u8..=3i8 => (), //~ ERROR E0308
| ^^^^^^^^^ expected u8, found i8
error: aborting due to previous error
-error[E0558]: export_name attribute has invalid format
+error[E0558]: `export_name` attribute has invalid format
--> $DIR/E0558.rs:11:1
|
LL | #[export_name]
--- /dev/null
+// Copyright 2018 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.
+
+#[export_name="\0foo"] //~ ERROR E0648
+pub fn bar() {}
+
+fn main() {}
--- /dev/null
+error[E0648]: `export_name` may not contain null characters
+ --> $DIR/E0648.rs:11:1
+ |
+LL | #[export_name="/0foo"] //~ ERROR E0648
+ | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0648`.
-> Box<for<'a> Id<impl Lt<'a>>>
//~^ ERROR `impl Trait` can only capture lifetimes bound at the fn or impl level [E0657]
{
- () //~ ERROR mismatched types
+ Box::new(())
}
struct Foo;
-> Box<for<'a> Id<impl Lt<'a>>>
//~^ ERROR `impl Trait` can only capture lifetimes bound at the fn or impl level
{
- () //~ ERROR mismatched types
+ Box::new(())
}
}
LL | -> Box<for<'a> Id<impl Lt<'a>>>
| ^^
-error[E0308]: mismatched types
- --> $DIR/E0657.rs:22:5
- |
-LL | () //~ ERROR mismatched types
- | ^^ expected struct `std::boxed::Box`, found ()
- |
- = note: expected type `std::boxed::Box<Id<_> + 'static>`
- found type `()`
-
-error[E0308]: mismatched types
- --> $DIR/E0657.rs:31:9
- |
-LL | () //~ ERROR mismatched types
- | ^^ expected struct `std::boxed::Box`, found ()
- |
- = note: expected type `std::boxed::Box<Id<_> + 'static>`
- found type `()`
-
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
-Some errors occurred: E0308, E0657.
-For more information about an error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0657`.
LL | q as *const [i32]; //~ ERROR cannot cast
| ^^^^^^^^^^^^^^^^^
-error[E0606]: casting `usize` as `*mut Trait + 'static` is invalid
+error[E0606]: casting `usize` as `*mut (dyn Trait + 'static)` is invalid
--> $DIR/fat-ptr-cast.rs:32:37
|
LL | let t: *mut (Trait + 'static) = 0 as *mut _; //~ ERROR casting
= help: see issue #48214
= help: add #![feature(trivial_bounds)] to the crate attributes to enable
-error[E0277]: the size for value values of type `A + 'static` cannot be known at compilation time
+error[E0277]: the size for value values of type `(dyn A + 'static)` cannot be known at compilation time
--> $DIR/feature-gate-trivial_bounds.rs:65:1
|
LL | / fn unsized_local() where Dst<A>: Sized { //~ ERROR
LL | | }
| |_^ doesn't have a size known at compile-time
|
- = help: within `Dst<A + 'static>`, the trait `std::marker::Sized` is not implemented for `A + 'static`
+ = help: within `Dst<(dyn A + 'static)>`, the trait `std::marker::Sized` is not implemented for `(dyn A + 'static)`
= note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
- = note: required because it appears within the type `Dst<A + 'static>`
+ = note: required because it appears within the type `Dst<(dyn A + 'static)>`
= help: see issue #48214
= help: add #![feature(trivial_bounds)] to the crate attributes to enable
-error[E0277]: `*mut std::ops::Fn() + 'static` cannot be shared between threads safely
+error[E0277]: `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely
--> $DIR/send-sync.rs:18:5
|
LL | send(format_args!("{:?}", c)); //~ ERROR E0277
- | ^^^^ `*mut std::ops::Fn() + 'static` cannot be shared between threads safely
+ | ^^^^ `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely
|
- = help: within `[std::fmt::ArgumentV1<'_>]`, the trait `std::marker::Sync` is not implemented for `*mut std::ops::Fn() + 'static`
- = note: required because it appears within the type `std::marker::PhantomData<*mut std::ops::Fn() + 'static>`
+ = help: within `[std::fmt::ArgumentV1<'_>]`, the trait `std::marker::Sync` is not implemented for `*mut (dyn std::ops::Fn() + 'static)`
+ = note: required because it appears within the type `std::marker::PhantomData<*mut (dyn std::ops::Fn() + 'static)>`
= note: required because it appears within the type `core::fmt::Void`
= note: required because it appears within the type `&core::fmt::Void`
= note: required because it appears within the type `std::fmt::ArgumentV1<'_>`
LL | fn send<T: Send>(_: T) {}
| ^^^^^^^^^^^^^^^^^^^^^^
-error[E0277]: `*mut std::ops::Fn() + 'static` cannot be shared between threads safely
+error[E0277]: `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely
--> $DIR/send-sync.rs:19:5
|
LL | sync(format_args!("{:?}", c)); //~ ERROR E0277
- | ^^^^ `*mut std::ops::Fn() + 'static` cannot be shared between threads safely
+ | ^^^^ `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely
|
- = help: within `std::fmt::Arguments<'_>`, the trait `std::marker::Sync` is not implemented for `*mut std::ops::Fn() + 'static`
- = note: required because it appears within the type `std::marker::PhantomData<*mut std::ops::Fn() + 'static>`
+ = help: within `std::fmt::Arguments<'_>`, the trait `std::marker::Sync` is not implemented for `*mut (dyn std::ops::Fn() + 'static)`
+ = note: required because it appears within the type `std::marker::PhantomData<*mut (dyn std::ops::Fn() + 'static)>`
= note: required because it appears within the type `core::fmt::Void`
= note: required because it appears within the type `&core::fmt::Void`
= note: required because it appears within the type `std::fmt::ArgumentV1<'_>`
--- /dev/null
+// Copyright 2018 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.
+
+#[macro_export]
+macro_rules! helper1 {
+ () => ( struct S; )
+}
+
+#[macro_export(local_inner_macros)]
+macro_rules! helper2 {
+ () => ( helper1!(); )
+}
+
+#[macro_export(local_inner_macros)]
+macro_rules! public_macro {
+ () => ( helper2!(); )
+}
+
+#[macro_export(local_inner_macros)]
+macro_rules! public_macro_dynamic {
+ ($helper: ident) => ( $helper!(); )
+}
--- /dev/null
+// Copyright 2018 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.
+
+// compile-pass
+// aux-build:local_inner_macros.rs
+
+#![feature(use_extern_macros)]
+
+extern crate local_inner_macros;
+
+use local_inner_macros::{public_macro, public_macro_dynamic};
+
+public_macro!();
+
+macro_rules! local_helper {
+ () => ( struct Z; )
+}
+
+public_macro_dynamic!(local_helper);
+
+fn main() {
+ let s = S;
+ let z = Z;
+}
--- /dev/null
+// Copyright 2018 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.
+
+// `local_inner_macros` has no effect if `feature(use_extern_macros)` is not enabled
+
+// aux-build:local_inner_macros.rs
+// error-pattern: cannot find macro `helper2!` in this scope
+
+#[macro_use(public_macro)]
+extern crate local_inner_macros;
+
+public_macro!();
+
+fn main() {}
--- /dev/null
+error: cannot find macro `helper2!` in this scope
+ --> $DIR/local_inner_macros_disabled.rs:19:1
+ |
+LL | public_macro!();
+ | ^^^^^^^^^^^^^^^^
+ |
+ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
// return type, which can't depend on the obligation.
fn cycle1() -> impl Clone {
//~^ ERROR cycle detected
- //~| ERROR cycle detected
send(cycle2().clone());
- //~^ ERROR `std::rc::Rc<std::string::String>` cannot be sent between threads safely
Rc::new(Cell::new(5))
}
-error[E0391]: cycle detected when processing `cycle1::{{exist-impl-Trait}}`
- --> $DIR/auto-trait-leak.rs:24:16
- |
-LL | fn cycle1() -> impl Clone {
- | ^^^^^^^^^^
- |
-note: ...which requires processing `cycle1`...
+error[E0391]: cycle detected when processing `cycle1`
--> $DIR/auto-trait-leak.rs:24:1
|
LL | fn cycle1() -> impl Clone {
| ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
note: ...which requires processing `cycle2::{{exist-impl-Trait}}`...
- --> $DIR/auto-trait-leak.rs:33:16
+ --> $DIR/auto-trait-leak.rs:31:16
|
LL | fn cycle2() -> impl Clone {
| ^^^^^^^^^^
note: ...which requires processing `cycle2`...
- --> $DIR/auto-trait-leak.rs:33:1
+ --> $DIR/auto-trait-leak.rs:31:1
|
LL | fn cycle2() -> impl Clone {
| ^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
- = note: ...which again requires processing `cycle1::{{exist-impl-Trait}}`, completing the cycle
-
-error[E0391]: cycle detected when processing `cycle1::{{exist-impl-Trait}}`
+note: ...which requires processing `cycle1::{{exist-impl-Trait}}`...
--> $DIR/auto-trait-leak.rs:24:16
|
LL | fn cycle1() -> impl Clone {
| ^^^^^^^^^^
- |
-note: ...which requires processing `cycle1`...
- --> $DIR/auto-trait-leak.rs:24:1
- |
-LL | fn cycle1() -> impl Clone {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
-note: ...which requires processing `cycle2::{{exist-impl-Trait}}`...
- --> $DIR/auto-trait-leak.rs:33:16
- |
-LL | fn cycle2() -> impl Clone {
- | ^^^^^^^^^^
-note: ...which requires processing `cycle2`...
- --> $DIR/auto-trait-leak.rs:33:1
- |
-LL | fn cycle2() -> impl Clone {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: ...which again requires processing `cycle1::{{exist-impl-Trait}}`, completing the cycle
-
-error[E0277]: `std::rc::Rc<std::string::String>` cannot be sent between threads safely
- --> $DIR/auto-trait-leak.rs:27:5
- |
-LL | send(cycle2().clone());
- | ^^^^ `std::rc::Rc<std::string::String>` cannot be sent between threads safely
- |
- = help: within `impl std::clone::Clone`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<std::string::String>`
- = note: required because it appears within the type `impl std::clone::Clone`
-note: required by `send`
- --> $DIR/auto-trait-leak.rs:16:1
- |
-LL | fn send<T: Send>(_: T) {}
- | ^^^^^^^^^^^^^^^^^^^^^^
+ = note: ...which again requires processing `cycle1`, completing the cycle
+note: cycle used when type-checking all item bodies
-error: aborting due to 3 previous errors
+error: aborting due to previous error
-Some errors occurred: E0277, E0391.
-For more information about an error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0391`.
fn projection_with_named_trait_inside_path_is_disallowed()
-> <::std::ops::Range<impl Debug> as Iterator>::Item
//~^ ERROR `impl Trait` is not allowed in path parameters
-//~| ERROR trait bound `impl std::fmt::Debug: std::iter::Step` is not satisfied
-{ //~ ERROR trait bound `impl std::fmt::Debug: std::iter::Step` is not satisfied
- (1i32..100).next().unwrap() //~ ERROR mismatched types
+{
+ (1i32..100).next().unwrap()
}
fn projection_from_impl_trait_inside_dyn_trait_is_disallowed()
| ^^^^^^^^^^
error[E0667]: `impl Trait` is not allowed in path parameters
- --> $DIR/impl_trait_projections.rs:43:29
+ --> $DIR/impl_trait_projections.rs:42:29
|
LL | -> <dyn Iterator<Item = impl Debug> as Iterator>::Item
| ^^^^^^^^^^
|
= note: specify the type using the syntax `<impl std::iter::Iterator as Trait>::Item`
-error[E0277]: the trait bound `impl std::fmt::Debug: std::iter::Step` is not satisfied
- --> $DIR/impl_trait_projections.rs:38:1
- |
-LL | / { //~ ERROR trait bound `impl std::fmt::Debug: std::iter::Step` is not satisfied
-LL | | (1i32..100).next().unwrap() //~ ERROR mismatched types
-LL | | }
- | |_^ the trait `std::iter::Step` is not implemented for `impl std::fmt::Debug`
- |
- = note: required because of the requirements on the impl of `std::iter::Iterator` for `std::ops::Range<impl std::fmt::Debug>`
-
-error[E0308]: mismatched types
- --> $DIR/impl_trait_projections.rs:39:5
- |
-LL | (1i32..100).next().unwrap() //~ ERROR mismatched types
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected anonymized type, found i32
- |
- = note: expected type `impl std::fmt::Debug`
- found type `i32`
-
-error[E0277]: the trait bound `impl std::fmt::Debug: std::iter::Step` is not satisfied
- --> $DIR/impl_trait_projections.rs:35:8
- |
-LL | -> <::std::ops::Range<impl Debug> as Iterator>::Item
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::iter::Step` is not implemented for `impl std::fmt::Debug`
- |
- = note: required because of the requirements on the impl of `std::iter::Iterator` for `std::ops::Range<impl std::fmt::Debug>`
-
-error: aborting due to 8 previous errors
+error: aborting due to 5 previous errors
-Some errors occurred: E0223, E0277, E0308, E0667.
+Some errors occurred: E0223, E0667.
For more information about an error, try `rustc --explain E0223`.
LL | fn with_dyn_debug_static<'a>(x: Box<dyn Debug + 'a>) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: ...so that the expression is assignable:
- expected std::boxed::Box<std::fmt::Debug>
- found std::boxed::Box<std::fmt::Debug + 'a>
+ expected std::boxed::Box<dyn std::fmt::Debug>
+ found std::boxed::Box<(dyn std::fmt::Debug + 'a)>
= note: but, the lifetime must be valid for the static lifetime...
= note: ...so that the types are compatible:
expected StaticTrait
| |_____^
= note: ...but the lifetime must also be valid for the static lifetime...
= note: ...so that the method type is compatible with trait:
- expected fn(&Struct) -> &Trait + 'static
- found fn(&Struct) -> &Trait
+ expected fn(&Struct) -> &(dyn Trait + 'static)
+ found fn(&Struct) -> &dyn Trait
error: aborting due to previous error
//~^ ERROR cast to unsized type: `&[usize; 2]` as `[usize]`
let _bar = Box::new(1_usize) as std::fmt::Debug;
- //~^ ERROR cast to unsized type: `std::boxed::Box<usize>` as `std::fmt::Debug`
+ //~^ ERROR cast to unsized type: `std::boxed::Box<usize>` as `dyn std::fmt::Debug`
let _baz = 1_usize as std::fmt::Debug;
- //~^ ERROR cast to unsized type: `usize` as `std::fmt::Debug`
+ //~^ ERROR cast to unsized type: `usize` as `dyn std::fmt::Debug`
let _quux = [1_usize, 2] as [usize];
//~^ ERROR cast to unsized type: `[usize; 2]` as `[usize]`
LL | let _foo = &[1_usize, 2] as [usize];
| ^^^^^^^^^^^^^^^^^^^^^^^^
-error[E0620]: cast to unsized type: `std::boxed::Box<usize>` as `std::fmt::Debug`
+error[E0620]: cast to unsized type: `std::boxed::Box<usize>` as `dyn std::fmt::Debug`
--> $DIR/issue-17441.rs:15:16
|
LL | let _bar = Box::new(1_usize) as std::fmt::Debug;
| |
| help: try casting to a `Box` instead: `Box<std::fmt::Debug>`
-error[E0620]: cast to unsized type: `usize` as `std::fmt::Debug`
+error[E0620]: cast to unsized type: `usize` as `dyn std::fmt::Debug`
--> $DIR/issue-17441.rs:18:16
|
LL | let _baz = 1_usize as std::fmt::Debug;
| ^ the trait `Array` cannot be made into an object
|
= note: the trait cannot require that `Self : Sized`
- = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&Array>` for `&T`
+ = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Array>` for `&T`
error: aborting due to 2 previous errors
--- /dev/null
+// Copyright 2018 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.
+
+fn main() {
+ enum Foo {
+ Drop = assert_eq!(1, 1)
+ }
+}
--- /dev/null
+error[E0317]: if may be missing an else clause
+ --> $DIR/issue-50577.rs:13:16
+ |
+LL | Drop = assert_eq!(1, 1)
+ | ^^^^^^^^^^^^^^^^ expected (), found isize
+ |
+ = note: expected type `()`
+ found type `isize`
+ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0317`.
pub fn char_type(p: char); //~ ERROR uses type `char`
pub fn i128_type(p: i128); //~ ERROR uses type `i128`
pub fn u128_type(p: u128); //~ ERROR uses type `u128`
- pub fn trait_type(p: &Clone); //~ ERROR uses type `std::clone::Clone`
+ pub fn trait_type(p: &Clone); //~ ERROR uses type `dyn std::clone::Clone`
pub fn tuple_type(p: (i32, i32)); //~ ERROR uses type `(i32, i32)`
pub fn tuple_type2(p: I32Pair); //~ ERROR uses type `(i32, i32)`
pub fn zero_size(p: ZeroSize); //~ ERROR struct has no fields
LL | pub fn u128_type(p: u128); //~ ERROR uses type `u128`
| ^^^^
-error: `extern` block uses type `std::clone::Clone` which is not FFI-safe: trait objects have no C equivalent
+error: `extern` block uses type `dyn std::clone::Clone` which is not FFI-safe: trait objects have no C equivalent
--> $DIR/lint-ctypes.rs:62:26
|
-LL | pub fn trait_type(p: &Clone); //~ ERROR uses type `std::clone::Clone`
+LL | pub fn trait_type(p: &Clone); //~ ERROR uses type `dyn std::clone::Clone`
| ^^^^^^
error: `extern` block uses type `(i32, i32)` which is not FFI-safe: tuples have unspecified layout
--- /dev/null
+// Copyright 2018 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.
+
+// compile-pass
+// run-rustfix
+
+#![warn(ellipsis_inclusive_range_patterns)]
+
+fn main() {
+ let despondency = 2;
+ match despondency {
+ 1..=2 => {}
+ //~^ WARN `...` range patterns are deprecated
+ _ => {}
+ }
+}
--- /dev/null
+// Copyright 2018 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.
+
+// compile-pass
+// run-rustfix
+
+#![warn(ellipsis_inclusive_range_patterns)]
+
+fn main() {
+ let despondency = 2;
+ match despondency {
+ 1...2 => {}
+ //~^ WARN `...` range patterns are deprecated
+ _ => {}
+ }
+}
--- /dev/null
+warning: `...` range patterns are deprecated
+ --> $DIR/inclusive-range-pattern-syntax.rs:19:10
+ |
+LL | 1...2 => {}
+ | ^^^ help: use `..=` for an inclusive range
+ |
+note: lint level defined here
+ --> $DIR/inclusive-range-pattern-syntax.rs:14:9
+ |
+LL | #![warn(ellipsis_inclusive_range_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
LL | | };
| |_____^ expected bound lifetime parameter 'a, found concrete lifetime
|
- = note: expected type `&for<'a, 'b> Foo<&'a u8, &'b u8>`
- found type `&for<'a> Foo<&'a u8, &'a u8>`
+ = note: expected type `&dyn for<'a, 'b> Foo<&'a u8, &'b u8>`
+ found type `&dyn for<'a> Foo<&'a u8, &'a u8>`
= note: this was previously accepted by the compiler but has been phased out
= note: for more information, see https://github.com/rust-lang/rust/issues/45852
LL | let _ = v as *const [u8]; //~ ERROR cannot cast
| ^^^^^^^^^^^^^^^^
-error[E0606]: casting `&Foo` as `*const str` is invalid
+error[E0606]: casting `&dyn Foo` as `*const str` is invalid
--> $DIR/cast-rfc0401.rs:64:13
|
LL | let _ = foo as *const str; //~ ERROR is invalid
| ^^^^^^^^^^^^^^^^^
-error[E0606]: casting `&Foo` as `*mut str` is invalid
+error[E0606]: casting `&dyn Foo` as `*mut str` is invalid
--> $DIR/cast-rfc0401.rs:65:13
|
LL | let _ = foo as *mut str; //~ ERROR is invalid
|
= help: cast through a thin pointer first
-error[E0606]: casting `*const Foo` as `*const [u16]` is invalid
+error[E0606]: casting `*const dyn Foo` as `*const [u16]` is invalid
--> $DIR/cast-rfc0401.rs:78:13
|
LL | let _ = cf as *const [u16]; //~ ERROR is invalid
|
= note: vtable kinds may not match
-error[E0606]: casting `*const Foo` as `*const Bar` is invalid
+error[E0606]: casting `*const dyn Foo` as `*const dyn Bar` is invalid
--> $DIR/cast-rfc0401.rs:79:13
|
LL | let _ = cf as *const Bar; //~ ERROR is invalid
|
= help: the trait `std::marker::Sized` is not implemented for `[u8]`
= note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
- = note: required for the cast to the object type `Foo`
+ = note: required for the cast to the object type `dyn Foo`
error[E0277]: the size for value values of type `str` cannot be known at compilation time
--> $DIR/cast-rfc0401.rs:72:13
|
= help: the trait `std::marker::Sized` is not implemented for `str`
= note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
- = note: required for the cast to the object type `Foo`
+ = note: required for the cast to the object type `dyn Foo`
error[E0606]: casting `&{float}` as `f32` is invalid
--> $DIR/cast-rfc0401.rs:81:30
--> $DIR/issue-19109.rs:14:5
|
LL | fn function(t: &mut Trait) {
- | - help: try adding a return type: `-> *mut Trait`
+ | - help: try adding a return type: `-> *mut dyn Trait`
LL | t as *mut Trait
| ^^^^^^^^^^^^^^^ expected (), found *-ptr
|
= note: expected type `()`
- found type `*mut Trait`
+ found type `*mut dyn Trait`
error: aborting due to previous error
LL | a(x); //~ ERROR mismatched types [E0308]
| ^ expected trait `Foo + std::marker::Send`, found trait `Foo`
|
- = note: expected type `std::boxed::Box<Foo + std::marker::Send + 'static>`
- found type `std::boxed::Box<Foo + 'static>`
+ = note: expected type `std::boxed::Box<(dyn Foo + std::marker::Send + 'static)>`
+ found type `std::boxed::Box<(dyn Foo + 'static)>`
error: aborting due to previous error
'_#1r,
T,
i32,
- extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<Anything + '_#2r>
+ extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<(dyn Anything + '_#2r)>
]
= note: number of external vids: 3
= note: where <T as std::iter::Iterator>::Item: '_#2r
'_#1r,
T,
i32,
- extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<Anything + '_#2r>
+ extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<(dyn Anything + '_#2r)>
]
= note: number of external vids: 3
= note: where <T as std::iter::Iterator>::Item: '_#2r
'_#2r,
T,
i32,
- extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<Anything + '_#3r>
+ extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<(dyn Anything + '_#3r)>
]
= note: number of external vids: 4
= note: where <T as std::iter::Iterator>::Item: '_#3r
'_#2r,
T,
i32,
- extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<Anything + '_#3r>
+ extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<(dyn Anything + '_#3r)>
]
= note: number of external vids: 4
= note: where <T as std::iter::Iterator>::Item: '_#3r
'_#1r,
T,
i32,
- extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<std::fmt::Debug + '_#2r>
+ extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<(dyn std::fmt::Debug + '_#2r)>
]
= note: number of external vids: 3
= note: where T: '_#2r
// older ... syntax is still allowed as a stability guarantee.
#![feature(box_patterns)]
+#![warn(ellipsis_inclusive_range_patterns)]
+
pub fn main() {
match &12 {
&0...9 => {}
+ //~^ WARN `...` range patterns are deprecated
+ //~| HELP use `..=` for an inclusive range
&10..=15 => {}
//~^ ERROR the range pattern here has ambiguous interpretation
//~^^ HELP add parentheses to clarify the precedence
match Box::new(12) {
box 0...9 => {}
+ //~^ WARN `...` range patterns are deprecated
+ //~| HELP use `..=` for an inclusive range
box 10..=15 => {}
//~^ ERROR the range pattern here has ambiguous interpretation
//~^^ HELP add parentheses to clarify the precedence
error: the range pattern here has ambiguous interpretation
- --> $DIR/range-inclusive-pattern-precedence.rs:23:10
+ --> $DIR/range-inclusive-pattern-precedence.rs:27:10
|
LL | &10..=15 => {}
| ^^^^^^^ help: add parentheses to clarify the precedence: `(10 ..=15)`
error: the range pattern here has ambiguous interpretation
- --> $DIR/range-inclusive-pattern-precedence.rs:32:13
+ --> $DIR/range-inclusive-pattern-precedence.rs:38:13
|
LL | box 10..=15 => {}
| ^^^^^^^ help: add parentheses to clarify the precedence: `(10 ..=15)`
+warning: `...` range patterns are deprecated
+ --> $DIR/range-inclusive-pattern-precedence.rs:24:11
+ |
+LL | &0...9 => {}
+ | ^^^ help: use `..=` for an inclusive range
+ |
+note: lint level defined here
+ --> $DIR/range-inclusive-pattern-precedence.rs:19:9
+ |
+LL | #![warn(ellipsis_inclusive_range_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: `...` range patterns are deprecated
+ --> $DIR/range-inclusive-pattern-precedence.rs:35:14
+ |
+LL | box 0...9 => {}
+ | ^^^ help: use `..=` for an inclusive range
+
error: aborting due to 2 previous errors
-error[E0277]: the size for value values of type `I + 'static` cannot be known at compilation time
+error[E0277]: the size for value values of type `(dyn I + 'static)` cannot be known at compilation time
--> $DIR/issue-5035-2.rs:14:8
|
LL | fn foo(_x: K) {}
| ^^ doesn't have a size known at compile-time
|
- = help: the trait `std::marker::Sized` is not implemented for `I + 'static`
+ = help: the trait `std::marker::Sized` is not implemented for `(dyn I + 'static)`
= note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= note: all local variables must have a statically known size
--> $DIR/borrowck-object-mutability.rs:19:5
|
LL | fn borrowed_receiver(x: &Foo) {
- | ---- help: consider changing this to be a mutable reference: `&mut Foo`
+ | ---- help: consider changing this to be a mutable reference: `&mut dyn Foo`
LL | x.borrowed();
LL | x.borrowed_mut(); //~ ERROR cannot borrow
| ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
|
= help: did you mean to write `w.wrap.not_closure` instead of `w.wrap.not_closure(...)`?
-error[E0599]: no method named `closure` found for type `Obj<std::boxed::Box<std::boxed::FnBox<(), Output=u32> + 'static>>` in the current scope
+error[E0599]: no method named `closure` found for type `Obj<std::boxed::Box<(dyn std::boxed::FnBox<(), Output=u32> + 'static)>>` in the current scope
--> $DIR/issue-2392.rs:72:24
|
LL | struct Obj<F> where F: FnOnce() -> u32 {
|
= note: #[warn(trivial_bounds)] on by default
-warning: Trait bound for<'a> T<A + 'a>: std::marker::Sized does not depend on any type or lifetime parameters
+warning: Trait bound for<'a> T<(dyn A + 'a)>: std::marker::Sized does not depend on any type or lifetime parameters
--> $DIR/trivial-bounds-inconsistent-sized.rs:26:1
|
LL | / fn unsized_local() where for<'a> T<A + 'a>: Sized {
LL | struct TwoStrs(str, str) where str: Sized;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-warning: Trait bound for<'a> Dst<A + 'a>: std::marker::Sized does not depend on any type or lifetime parameters
+warning: Trait bound for<'a> Dst<(dyn A + 'a)>: std::marker::Sized does not depend on any type or lifetime parameters
--> $DIR/trivial-bounds-inconsistent.rs:65:1
|
LL | / fn unsized_local() where for<'a> Dst<A + 'a>: Sized {
| ^^^^^
= note: but, the lifetime must be valid for the static lifetime...
= note: ...so that the expression is assignable:
- expected std::boxed::Box<std::iter::Iterator<Item=&T> + 'static>
- found std::boxed::Box<std::iter::Iterator<Item=&T>>
+ expected std::boxed::Box<(dyn std::iter::Iterator<Item=&T> + 'static)>
+ found std::boxed::Box<dyn std::iter::Iterator<Item=&T>>
error: aborting due to previous error
= note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= note: no field of an enum variant may have a dynamically sized type
-error[E0277]: the size for value values of type `Foo + 'static` cannot be known at compilation time
+error[E0277]: the size for value values of type `(dyn Foo + 'static)` cannot be known at compilation time
--> $DIR/unsized-enum2.rs:63:8
|
LL | VM(Foo),
| ^^^ doesn't have a size known at compile-time
|
- = help: the trait `std::marker::Sized` is not implemented for `Foo + 'static`
+ = help: the trait `std::marker::Sized` is not implemented for `(dyn Foo + 'static)`
= note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= note: no field of an enum variant may have a dynamically sized type
-error[E0277]: the size for value values of type `Bar + 'static` cannot be known at compilation time
+error[E0277]: the size for value values of type `(dyn Bar + 'static)` cannot be known at compilation time
--> $DIR/unsized-enum2.rs:65:8
|
LL | VN{x: Bar},
| ^^^^^^ doesn't have a size known at compile-time
|
- = help: the trait `std::marker::Sized` is not implemented for `Bar + 'static`
+ = help: the trait `std::marker::Sized` is not implemented for `(dyn Bar + 'static)`
= note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= note: no field of an enum variant may have a dynamically sized type
-error[E0277]: the size for value values of type `FooBar + 'static` cannot be known at compilation time
+error[E0277]: the size for value values of type `(dyn FooBar + 'static)` cannot be known at compilation time
--> $DIR/unsized-enum2.rs:67:15
|
LL | VO(isize, FooBar),
| ^^^^^^ doesn't have a size known at compile-time
|
- = help: the trait `std::marker::Sized` is not implemented for `FooBar + 'static`
+ = help: the trait `std::marker::Sized` is not implemented for `(dyn FooBar + 'static)`
= note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= note: no field of an enum variant may have a dynamically sized type
-error[E0277]: the size for value values of type `BarFoo + 'static` cannot be known at compilation time
+error[E0277]: the size for value values of type `(dyn BarFoo + 'static)` cannot be known at compilation time
--> $DIR/unsized-enum2.rs:69:18
|
LL | VP{u: isize, x: BarFoo},
| ^^^^^^^^^ doesn't have a size known at compile-time
|
- = help: the trait `std::marker::Sized` is not implemented for `BarFoo + 'static`
+ = help: the trait `std::marker::Sized` is not implemented for `(dyn BarFoo + 'static)`
= note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= note: no field of an enum variant may have a dynamically sized type
= note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= note: no field of an enum variant may have a dynamically sized type
-error[E0277]: the size for value values of type `PathHelper1 + 'static` cannot be known at compilation time
+error[E0277]: the size for value values of type `(dyn PathHelper1 + 'static)` cannot be known at compilation time
--> $DIR/unsized-enum2.rs:53:8
|
LL | VI(Path1),
| ^^^^^ doesn't have a size known at compile-time
|
- = help: within `Path1`, the trait `std::marker::Sized` is not implemented for `PathHelper1 + 'static`
+ = help: within `Path1`, the trait `std::marker::Sized` is not implemented for `(dyn PathHelper1 + 'static)`
= note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= note: required because it appears within the type `Path1`
= note: no field of an enum variant may have a dynamically sized type
-error[E0277]: the size for value values of type `PathHelper2 + 'static` cannot be known at compilation time
+error[E0277]: the size for value values of type `(dyn PathHelper2 + 'static)` cannot be known at compilation time
--> $DIR/unsized-enum2.rs:55:8
|
LL | VJ{x: Path2},
| ^^^^^^^^ doesn't have a size known at compile-time
|
- = help: within `Path2`, the trait `std::marker::Sized` is not implemented for `PathHelper2 + 'static`
+ = help: within `Path2`, the trait `std::marker::Sized` is not implemented for `(dyn PathHelper2 + 'static)`
= note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= note: required because it appears within the type `Path2`
= note: no field of an enum variant may have a dynamically sized type
-error[E0277]: the size for value values of type `PathHelper3 + 'static` cannot be known at compilation time
+error[E0277]: the size for value values of type `(dyn PathHelper3 + 'static)` cannot be known at compilation time
--> $DIR/unsized-enum2.rs:57:15
|
LL | VK(isize, Path3),
| ^^^^^ doesn't have a size known at compile-time
|
- = help: within `Path3`, the trait `std::marker::Sized` is not implemented for `PathHelper3 + 'static`
+ = help: within `Path3`, the trait `std::marker::Sized` is not implemented for `(dyn PathHelper3 + 'static)`
= note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= note: required because it appears within the type `Path3`
= note: no field of an enum variant may have a dynamically sized type
-error[E0277]: the size for value values of type `PathHelper4 + 'static` cannot be known at compilation time
+error[E0277]: the size for value values of type `(dyn PathHelper4 + 'static)` cannot be known at compilation time
--> $DIR/unsized-enum2.rs:59:18
|
LL | VL{u: isize, x: Path4},
| ^^^^^^^^ doesn't have a size known at compile-time
|
- = help: within `Path4`, the trait `std::marker::Sized` is not implemented for `PathHelper4 + 'static`
+ = help: within `Path4`, the trait `std::marker::Sized` is not implemented for `(dyn PathHelper4 + 'static)`
= note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized>
= note: required because it appears within the type `Path4`
= note: no field of an enum variant may have a dynamically sized type