# Documentation tests
`rustdoc` supports executing your documentation examples as tests. This makes sure
-that your tests are up to date and working.
+that examples within your documentation are up to date and working.
The basic idea is this:
Box(ptr.cast().into())
}
+ /// Constructs a new `Box` with uninitialized contents, with the memory
+ /// being filled with `0` bytes.
+ ///
+ /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage
+ /// of this method.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(new_uninit)]
+ ///
+ /// let zero = Box::<u32>::new_zeroed();
+ /// let zero = unsafe { zero.assume_init() };
+ ///
+ /// assert_eq!(*zero, 0)
+ /// ```
+ ///
+ /// [zeroed]: ../../std/mem/union.MaybeUninit.html#method.zeroed
+ #[unstable(feature = "new_uninit", issue = "63291")]
+ pub fn new_zeroed() -> Box<mem::MaybeUninit<T>> {
+ unsafe {
+ let mut uninit = Self::new_uninit();
+ ptr::write_bytes::<T>(uninit.as_mut_ptr(), 0, 1);
+ uninit
+ }
+ }
+
/// Constructs a new `Pin<Box<T>>`. If `T` does not implement `Unpin`, then
/// `x` will be pinned in memory and unable to be moved.
#[stable(feature = "pin", since = "1.33.0")]
}
}
+ /// Constructs a new `Rc` with uninitialized contents, with the memory
+ /// being filled with `0` bytes.
+ ///
+ /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and
+ /// incorrect usage of this method.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(new_uninit)]
+ ///
+ /// use std::rc::Rc;
+ ///
+ /// let zero = Rc::<u32>::new_zeroed();
+ /// let zero = unsafe { zero.assume_init() };
+ ///
+ /// assert_eq!(*zero, 0)
+ /// ```
+ ///
+ /// [zeroed]: ../../std/mem/union.MaybeUninit.html#method.zeroed
+ #[unstable(feature = "new_uninit", issue = "63291")]
+ pub fn new_zeroed() -> Rc<mem::MaybeUninit<T>> {
+ unsafe {
+ let mut uninit = Self::new_uninit();
+ ptr::write_bytes::<T>(Rc::get_mut_unchecked(&mut uninit).as_mut_ptr(), 0, 1);
+ uninit
+ }
+ }
+
/// Constructs a new `Pin<Rc<T>>`. If `T` does not implement `Unpin`, then
/// `value` will be pinned in memory and unable to be moved.
#[stable(feature = "pin", since = "1.33.0")]
}
}
+ /// Constructs a new `Arc` with uninitialized contents, with the memory
+ /// being filled with `0` bytes.
+ ///
+ /// See [`MaybeUninit::zeroed`][zeroed] for examples of correct and incorrect usage
+ /// of this method.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(new_uninit)]
+ ///
+ /// use std::sync::Arc;
+ ///
+ /// let zero = Arc::<u32>::new_zeroed();
+ /// let zero = unsafe { zero.assume_init() };
+ ///
+ /// assert_eq!(*zero, 0)
+ /// ```
+ ///
+ /// [zeroed]: ../../std/mem/union.MaybeUninit.html#method.zeroed
+ #[unstable(feature = "new_uninit", issue = "63291")]
+ pub fn new_zeroed() -> Arc<mem::MaybeUninit<T>> {
+ unsafe {
+ let mut uninit = Self::new_uninit();
+ ptr::write_bytes::<T>(Arc::get_mut_unchecked(&mut uninit).as_mut_ptr(), 0, 1);
+ uninit
+ }
+ }
+
/// Constructs a new `Pin<Arc<T>>`. If `T` does not implement `Unpin`, then
/// `data` will be pinned in memory and unable to be moved.
#[stable(feature = "pin", since = "1.33.0")]
/// The capacity will remain at least as large as both the length
/// and the supplied value.
///
+ /// # Panics
+ ///
/// Panics if the current capacity is smaller than the supplied
/// minimum capacity.
///
#![stable(feature = "core_ascii", since = "1.26.0")]
use crate::fmt;
-use crate::ops::Range;
use crate::iter::FusedIterator;
+use crate::ops::Range;
use crate::str::from_utf8_unchecked;
/// An iterator over the escaped version of a byte.
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,
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Iterator for EscapeDefault {
type Item = u8;
- fn next(&mut self) -> Option<u8> { self.range.next().map(|i| self.data[i]) }
- fn size_hint(&self) -> (usize, Option<usize>) { self.range.size_hint() }
- fn last(mut self) -> Option<u8> { self.next_back() }
+ fn next(&mut self) -> Option<u8> {
+ self.range.next().map(|i| self.data[i])
+ }
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.range.size_hint()
+ }
+ fn last(mut self) -> Option<u8> {
+ self.next_back()
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl DoubleEndedIterator for EscapeDefault {
}
}
-
/// An error which can be returned when parsing a char.
#[stable(feature = "char_from_str", since = "1.20.0")]
#[derive(Clone, Debug, PartialEq, Eq)]
}
impl ParseCharError {
- #[unstable(feature = "char_error_internals",
- reason = "this method should not be available publicly",
- issue = "0")]
+ #[unstable(
+ feature = "char_error_internals",
+ reason = "this method should not be available publicly",
+ issue = "0"
+ )]
#[doc(hidden)]
pub fn __description(&self) -> &str {
match self.kind {
- CharErrorKind::EmptyString => {
- "cannot parse char from empty string"
- },
- CharErrorKind::TooManyChars => "too many characters in string"
+ CharErrorKind::EmptyString => "cannot parse char from empty string",
+ CharErrorKind::TooManyChars => "too many characters in string",
}
}
}
}
}
-
#[stable(feature = "char_from_str", since = "1.20.0")]
impl FromStr for char {
type Err = ParseCharError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut chars = s.chars();
match (chars.next(), chars.next()) {
- (None, _) => {
- Err(ParseCharError { kind: CharErrorKind::EmptyString })
- },
+ (None, _) => Err(ParseCharError { kind: CharErrorKind::EmptyString }),
(Some(c), None) => Ok(c),
- _ => {
- Err(ParseCharError { kind: CharErrorKind::TooManyChars })
- }
+ _ => Err(ParseCharError { kind: CharErrorKind::TooManyChars }),
}
}
}
-
#[stable(feature = "try_from", since = "1.34.0")]
impl TryFrom<u32> for char {
type Error = CharTryFromError;
}
if num < radix {
let num = num as u8;
- if num < 10 {
- Some((b'0' + num) as char)
- } else {
- Some((b'a' + num - 10) as char)
- }
+ if num < 10 { Some((b'0' + num) as char) } else { Some((b'a' + num - 10) as char) }
} else {
None
}
#[stable(feature = "decode_utf16", since = "1.9.0")]
#[derive(Clone, Debug)]
pub struct DecodeUtf16<I>
- where I: Iterator<Item = u16>
+where
+ I: Iterator<Item = u16>,
{
iter: I,
buf: Option<u16>,
#[stable(feature = "decode_utf16", since = "1.9.0")]
#[inline]
pub fn decode_utf16<I: IntoIterator<Item = u16>>(iter: I) -> DecodeUtf16<I::IntoIter> {
- DecodeUtf16 {
- iter: iter.into_iter(),
- buf: None,
- }
+ DecodeUtf16 { iter: iter.into_iter(), buf: None }
}
#[stable(feature = "decode_utf16", since = "1.9.0")]
fn next(&mut self) -> Option<Result<char, DecodeUtf16Error>> {
let u = match self.buf.take() {
Some(buf) => buf,
- None => self.iter.next()?
+ None => self.iter.next()?,
};
if u < 0xD800 || 0xDFFF < u {
}
};
- if val < radix {
- Some(val)
- } else {
- None
- }
+ if val < radix { Some(val) } else { None }
}
/// Returns an iterator that yields the hexadecimal Unicode escape of a
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
#[inline]
pub fn to_ascii_uppercase(&self) -> char {
- if self.is_ascii() {
- (*self as u8).to_ascii_uppercase() as char
- } else {
- *self
- }
+ if self.is_ascii() { (*self as u8).to_ascii_uppercase() as char } else { *self }
}
/// Makes a copy of the value in its ASCII lower case equivalent.
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
#[inline]
pub fn to_ascii_lowercase(&self) -> char {
- if self.is_ascii() {
- (*self as u8).to_ascii_lowercase() as char
- } else {
- *self
- }
+ if self.is_ascii() { (*self as u8).to_ascii_lowercase() as char } else { *self }
}
/// Checks that two values are an ASCII case-insensitive match.
mod methods;
// stable re-exports
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use self::convert::{from_u32, from_digit};
#[stable(feature = "char_from_unchecked", since = "1.5.0")]
pub use self::convert::from_u32_unchecked;
-#[stable(feature = "char_from_str", since = "1.20.0")]
-pub use self::convert::ParseCharError;
#[stable(feature = "try_from", since = "1.34.0")]
pub use self::convert::CharTryFromError;
+#[stable(feature = "char_from_str", since = "1.20.0")]
+pub use self::convert::ParseCharError;
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use self::convert::{from_digit, from_u32};
#[stable(feature = "decode_utf16", since = "1.9.0")]
pub use self::decode::{decode_utf16, DecodeUtf16, DecodeUtf16Error};
use crate::iter::FusedIterator;
// UTF-8 ranges and tags for encoding characters
-const TAG_CONT: u8 = 0b1000_0000;
-const TAG_TWO_B: u8 = 0b1100_0000;
-const TAG_THREE_B: u8 = 0b1110_0000;
-const TAG_FOUR_B: u8 = 0b1111_0000;
-const MAX_ONE_B: u32 = 0x80;
-const MAX_TWO_B: u32 = 0x800;
-const MAX_THREE_B: u32 = 0x10000;
+const TAG_CONT: u8 = 0b1000_0000;
+const TAG_TWO_B: u8 = 0b1100_0000;
+const TAG_THREE_B: u8 = 0b1110_0000;
+const TAG_FOUR_B: u8 = 0b1111_0000;
+const MAX_ONE_B: u32 = 0x80;
+const MAX_TWO_B: u32 = 0x800;
+const MAX_THREE_B: u32 = 0x10000;
/*
Lu Uppercase_Letter an uppercase letter
match self.state {
EscapeUnicodeState::Done => None,
- EscapeUnicodeState::RightBrace |
- EscapeUnicodeState::Value |
- EscapeUnicodeState::LeftBrace |
- EscapeUnicodeState::Type |
- EscapeUnicodeState::Backslash => Some('}'),
+ EscapeUnicodeState::RightBrace
+ | EscapeUnicodeState::Value
+ | EscapeUnicodeState::LeftBrace
+ | EscapeUnicodeState::Type
+ | EscapeUnicodeState::Backslash => Some('}'),
}
}
}
#[inline]
fn len(&self) -> usize {
// The match is a single memory access with no branching
- self.hex_digit_idx + match self.state {
- EscapeUnicodeState::Done => 0,
- EscapeUnicodeState::RightBrace => 1,
- EscapeUnicodeState::Value => 2,
- EscapeUnicodeState::LeftBrace => 3,
- EscapeUnicodeState::Type => 4,
- EscapeUnicodeState::Backslash => 5,
- }
+ self.hex_digit_idx
+ + match self.state {
+ EscapeUnicodeState::Done => 0,
+ EscapeUnicodeState::RightBrace => 1,
+ EscapeUnicodeState::Value => 2,
+ EscapeUnicodeState::LeftBrace => 3,
+ EscapeUnicodeState::Type => 4,
+ EscapeUnicodeState::Backslash => 5,
+ }
}
}
#[derive(Clone, Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct EscapeDefault {
- state: EscapeDefaultState
+ state: EscapeDefaultState,
}
#[derive(Clone, Debug)]
EscapeDefaultState::Backslash(c) if n == 0 => {
self.state = EscapeDefaultState::Char(c);
Some('\\')
- },
+ }
EscapeDefaultState::Backslash(c) if n == 1 => {
self.state = EscapeDefaultState::Done;
Some(c)
- },
+ }
EscapeDefaultState::Backslash(_) => {
self.state = EscapeDefaultState::Done;
None
- },
+ }
EscapeDefaultState::Char(c) => {
self.state = EscapeDefaultState::Done;
- if n == 0 {
- Some(c)
- } else {
- None
- }
- },
+ if n == 0 { Some(c) } else { None }
+ }
EscapeDefaultState::Done => None,
EscapeDefaultState::Unicode(ref mut i) => i.nth(n),
}
#[stable(feature = "char_escape_debug", since = "1.20.0")]
impl Iterator for EscapeDebug {
type Item = char;
- fn next(&mut self) -> Option<char> { self.0.next() }
- fn size_hint(&self) -> (usize, Option<usize>) { self.0.size_hint() }
+ fn next(&mut self) -> Option<char> {
+ self.0.next()
+ }
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.0.size_hint()
+ }
}
#[stable(feature = "char_escape_debug", since = "1.20.0")]
-impl ExactSizeIterator for EscapeDebug { }
+impl ExactSizeIterator for EscapeDebug {}
#[stable(feature = "fused", since = "1.26.0")]
impl FusedIterator for EscapeDebug {}
fn new(chars: [char; 3]) -> CaseMappingIter {
if chars[2] == '\0' {
if chars[1] == '\0' {
- CaseMappingIter::One(chars[0]) // Including if chars[0] == '\0'
+ CaseMappingIter::One(chars[0]) // Including if chars[0] == '\0'
} else {
CaseMappingIter::Two(chars[0], chars[1])
}
f.write_char(b)?;
f.write_char(c)
}
- CaseMappingIter::One(c) => {
- f.write_char(c)
- }
+ CaseMappingIter::One(c) => f.write_char(c),
CaseMappingIter::Zero => Ok(()),
}
}
/// [impls]: #implementors
#[stable(feature = "rust1", since = "1.0.0")]
#[lang = "clone"]
-pub trait Clone : Sized {
+pub trait Clone: Sized {
/// Returns a copy of the value.
///
/// # Examples
#[rustc_builtin_macro]
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
#[allow_internal_unstable(core_intrinsics, derive_clone_copy)]
-pub macro Clone($item:item) { /* compiler built-in */ }
+pub macro Clone($item:item) {
+ /* compiler built-in */
+}
// FIXME(aburka): these structs are used solely by #[derive] to
// assert that every component of a type implements Clone or Copy.
// These structs should never appear in user code.
#[doc(hidden)]
#[allow(missing_debug_implementations)]
-#[unstable(feature = "derive_clone_copy",
- reason = "deriving hack, should not be public",
- issue = "0")]
-pub struct AssertParamIsClone<T: Clone + ?Sized> { _field: crate::marker::PhantomData<T> }
+#[unstable(
+ feature = "derive_clone_copy",
+ reason = "deriving hack, should not be public",
+ issue = "0"
+)]
+pub struct AssertParamIsClone<T: Clone + ?Sized> {
+ _field: crate::marker::PhantomData<T>,
+}
#[doc(hidden)]
#[allow(missing_debug_implementations)]
-#[unstable(feature = "derive_clone_copy",
- reason = "deriving hack, should not be public",
- issue = "0")]
-pub struct AssertParamIsCopy<T: Copy + ?Sized> { _field: crate::marker::PhantomData<T> }
+#[unstable(
+ feature = "derive_clone_copy",
+ reason = "deriving hack, should not be public",
+ issue = "0"
+)]
+pub struct AssertParamIsCopy<T: Copy + ?Sized> {
+ _field: crate::marker::PhantomData<T>,
+}
/// Implementations of `Clone` for primitive types.
///
*self
}
}
-
}
#[inline]
fn le(&self, other: &Self) -> bool { other.0 <= self.0 }
#[inline]
- fn ge(&self, other: &Self) -> bool { other.0 >= self.0 }
- #[inline]
fn gt(&self, other: &Self) -> bool { other.0 > self.0 }
+ #[inline]
+ fn ge(&self, other: &Self) -> bool { other.0 >= self.0 }
}
#[stable(feature = "reverse_cmp_key", since = "1.19.0")]
#[inline]
fn le(&self, other: & &B) -> bool { PartialOrd::le(*self, *other) }
#[inline]
- fn ge(&self, other: & &B) -> bool { PartialOrd::ge(*self, *other) }
- #[inline]
fn gt(&self, other: & &B) -> bool { PartialOrd::gt(*self, *other) }
+ #[inline]
+ fn ge(&self, other: & &B) -> bool { PartialOrd::ge(*self, *other) }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<A: ?Sized> Ord for &A where A: Ord {
#[inline]
fn le(&self, other: &&mut B) -> bool { PartialOrd::le(*self, *other) }
#[inline]
- fn ge(&self, other: &&mut B) -> bool { PartialOrd::ge(*self, *other) }
- #[inline]
fn gt(&self, other: &&mut B) -> bool { PartialOrd::gt(*self, *other) }
+ #[inline]
+ fn ge(&self, other: &&mut B) -> bool { PartialOrd::ge(*self, *other) }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<A: ?Sized> Ord for &mut A where A: Ord {
/// ```
#[stable(feature = "convert_id", since = "1.33.0")]
#[inline]
-pub const fn identity<T>(x: T) -> T { x }
+pub const fn identity<T>(x: T) -> T {
+ x
+}
/// Used to do a cheap reference-to-reference conversion.
///
/// [`from`]: trait.From.html#tymethod.from
/// [book]: ../../book/ch09-00-error-handling.html
#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented(
- on(
- all(_Self="&str", T="std::string::String"),
- note="to coerce a `{T}` into a `{Self}`, use `&*` as a prefix",
- )
-)]
+#[rustc_on_unimplemented(on(
+ all(_Self = "&str", T = "std::string::String"),
+ note = "to coerce a `{T}` into a `{Self}`, use `&*` as a prefix",
+))]
pub trait From<T>: Sized {
/// Performs the conversion.
#[stable(feature = "rust1", since = "1.0.0")]
// As lifts over &
#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: ?Sized, U: ?Sized> AsRef<U> for &T where T: AsRef<U>
+impl<T: ?Sized, U: ?Sized> AsRef<U> for &T
+where
+ T: AsRef<U>,
{
fn as_ref(&self) -> &U {
<T as AsRef<U>>::as_ref(*self)
// As lifts over &mut
#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: ?Sized, U: ?Sized> AsRef<U> for &mut T where T: AsRef<U>
+impl<T: ?Sized, U: ?Sized> AsRef<U> for &mut T
+where
+ T: AsRef<U>,
{
fn as_ref(&self) -> &U {
<T as AsRef<U>>::as_ref(*self)
// AsMut lifts over &mut
#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: ?Sized, U: ?Sized> AsMut<U> for &mut T where T: AsMut<U>
+impl<T: ?Sized, U: ?Sized> AsMut<U> for &mut T
+where
+ T: AsMut<U>,
{
fn as_mut(&mut self) -> &mut U {
(*self).as_mut()
// From implies Into
#[stable(feature = "rust1", since = "1.0.0")]
-impl<T, U> Into<U> for T where U: From<T>
+impl<T, U> Into<U> for T
+where
+ U: From<T>,
{
fn into(self) -> U {
U::from(self)
// From (and thus Into) is reflexive
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> From<T> for T {
- fn from(t: T) -> T { t }
+ fn from(t: T) -> T {
+ t
+ }
}
/// **Stability note:** This impl does not yet exist, but we are
///
/// [#64715]: https://github.com/rust-lang/rust/issues/64715
#[stable(feature = "convert_infallible", since = "1.34.0")]
-#[rustc_reservation_impl="permitting this impl would forbid us from adding \
-`impl<T> From<!> for T` later; see rust-lang/rust#64715 for details"]
+#[rustc_reservation_impl = "permitting this impl would forbid us from adding \
+ `impl<T> From<!> for T` later; see rust-lang/rust#64715 for details"]
impl<T> From<!> for T {
- fn from(t: !) -> T { t }
+ fn from(t: !) -> T {
+ t
+ }
}
// TryFrom implies TryInto
#[stable(feature = "try_from", since = "1.34.0")]
-impl<T, U> TryInto<U> for T where U: TryFrom<T>
+impl<T, U> TryInto<U> for T
+where
+ U: TryFrom<T>,
{
type Error = U::Error;
// Infallible conversions are semantically equivalent to fallible conversions
// with an uninhabited error type.
#[stable(feature = "try_from", since = "1.34.0")]
-impl<T, U> TryFrom<U> for T where U: Into<T> {
+impl<T, U> TryFrom<U> for T
+where
+ U: Into<T>,
+{
type Error = Infallible;
fn try_from(value: U) -> Result<Self, Self::Error> {
#[rustc_builtin_macro]
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
#[allow_internal_unstable(core_intrinsics)]
-pub macro Default($item:item) { /* compiler built-in */ }
+pub macro Default($item:item) {
+ /* compiler built-in */
+}
macro_rules! default_impl {
($t:ty, $v:expr, $doc:tt) => {
#![stable(feature = "", since = "1.30.0")]
-
#![allow(non_camel_case_types)]
//! Utilities related to FFI bindings.
#[repr(u8)]
#[stable(feature = "core_c_void", since = "1.30.0")]
pub enum c_void {
- #[unstable(feature = "c_void_variant", reason = "temporary implementation detail",
- issue = "0")]
- #[doc(hidden)] __variant1,
- #[unstable(feature = "c_void_variant", reason = "temporary implementation detail",
- issue = "0")]
- #[doc(hidden)] __variant2,
+ #[unstable(
+ feature = "c_void_variant",
+ reason = "temporary implementation detail",
+ issue = "0"
+ )]
+ #[doc(hidden)]
+ __variant1,
+ #[unstable(
+ feature = "c_void_variant",
+ reason = "temporary implementation detail",
+ issue = "0"
+ )]
+ #[doc(hidden)]
+ __variant2,
}
#[stable(feature = "std_debug", since = "1.16.0")]
/// Basic implementation of a `va_list`.
// The name is WIP, using `VaListImpl` for now.
-#[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"),
- not(target_arch = "x86_64")),
- all(target_arch = "aarch64", target_os = "ios"),
- target_arch = "wasm32",
- target_arch = "asmjs",
- windows))]
+#[cfg(any(
+ all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), not(target_arch = "x86_64")),
+ all(target_arch = "aarch64", target_os = "ios"),
+ target_arch = "wasm32",
+ target_arch = "asmjs",
+ windows
+))]
#[repr(transparent)]
-#[unstable(feature = "c_variadic",
- reason = "the `c_variadic` feature has not been properly tested on \
- all supported platforms",
- issue = "44930")]
+#[unstable(
+ feature = "c_variadic",
+ reason = "the `c_variadic` feature has not been properly tested on \
+ all supported platforms",
+ issue = "44930"
+)]
#[lang = "va_list"]
pub struct VaListImpl<'f> {
ptr: *mut c_void,
_marker: PhantomData<&'f mut &'f c_void>,
}
-#[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"),
- not(target_arch = "x86_64")),
- all(target_arch = "aarch64", target_os = "ios"),
- target_arch = "wasm32",
- target_arch = "asmjs",
- windows))]
-#[unstable(feature = "c_variadic",
- reason = "the `c_variadic` feature has not been properly tested on \
- all supported platforms",
- issue = "44930")]
+#[cfg(any(
+ all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), not(target_arch = "x86_64")),
+ all(target_arch = "aarch64", target_os = "ios"),
+ target_arch = "wasm32",
+ target_arch = "asmjs",
+ windows
+))]
+#[unstable(
+ feature = "c_variadic",
+ reason = "the `c_variadic` feature has not been properly tested on \
+ all supported platforms",
+ issue = "44930"
+)]
impl<'f> fmt::Debug for VaListImpl<'f> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "va_list* {:p}", self.ptr)
#[cfg(all(target_arch = "aarch64", not(target_os = "ios"), not(windows)))]
#[repr(C)]
#[derive(Debug)]
-#[unstable(feature = "c_variadic",
- reason = "the `c_variadic` feature has not been properly tested on \
- all supported platforms",
- issue = "44930")]
+#[unstable(
+ feature = "c_variadic",
+ reason = "the `c_variadic` feature has not been properly tested on \
+ all supported platforms",
+ issue = "44930"
+)]
#[lang = "va_list"]
pub struct VaListImpl<'f> {
stack: *mut c_void,
#[cfg(all(target_arch = "powerpc", not(windows)))]
#[repr(C)]
#[derive(Debug)]
-#[unstable(feature = "c_variadic",
- reason = "the `c_variadic` feature has not been properly tested on \
- all supported platforms",
- issue = "44930")]
+#[unstable(
+ feature = "c_variadic",
+ reason = "the `c_variadic` feature has not been properly tested on \
+ all supported platforms",
+ issue = "44930"
+)]
#[lang = "va_list"]
pub struct VaListImpl<'f> {
gpr: u8,
#[cfg(all(target_arch = "x86_64", not(windows)))]
#[repr(C)]
#[derive(Debug)]
-#[unstable(feature = "c_variadic",
- reason = "the `c_variadic` feature has not been properly tested on \
- all supported platforms",
- issue = "44930")]
+#[unstable(
+ feature = "c_variadic",
+ reason = "the `c_variadic` feature has not been properly tested on \
+ all supported platforms",
+ issue = "44930"
+)]
#[lang = "va_list"]
pub struct VaListImpl<'f> {
gp_offset: i32,
/// A wrapper for a `va_list`
#[repr(transparent)]
#[derive(Debug)]
-#[unstable(feature = "c_variadic",
- reason = "the `c_variadic` feature has not been properly tested on \
- all supported platforms",
- issue = "44930")]
+#[unstable(
+ feature = "c_variadic",
+ reason = "the `c_variadic` feature has not been properly tested on \
+ all supported platforms",
+ issue = "44930"
+)]
pub struct VaList<'a, 'f: 'a> {
- #[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"),
- not(target_arch = "x86_64")),
- all(target_arch = "aarch64", target_os = "ios"),
- target_arch = "wasm32",
- target_arch = "asmjs",
- windows))]
+ #[cfg(any(
+ all(
+ not(target_arch = "aarch64"),
+ not(target_arch = "powerpc"),
+ not(target_arch = "x86_64")
+ ),
+ all(target_arch = "aarch64", target_os = "ios"),
+ target_arch = "wasm32",
+ target_arch = "asmjs",
+ windows
+ ))]
inner: VaListImpl<'f>,
- #[cfg(all(any(target_arch = "aarch64", target_arch = "powerpc",
- target_arch = "x86_64"),
- any(not(target_arch = "aarch64"), not(target_os = "ios")),
- not(target_arch = "wasm32"),
- not(target_arch = "asmjs"),
- not(windows)))]
+ #[cfg(all(
+ any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"),
+ any(not(target_arch = "aarch64"), not(target_os = "ios")),
+ not(target_arch = "wasm32"),
+ not(target_arch = "asmjs"),
+ not(windows)
+ ))]
inner: &'a mut VaListImpl<'f>,
_marker: PhantomData<&'a mut VaListImpl<'f>>,
}
-#[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"),
- not(target_arch = "x86_64")),
- all(target_arch = "aarch64", target_os = "ios"),
- target_arch = "wasm32",
- target_arch = "asmjs",
- windows))]
-#[unstable(feature = "c_variadic",
- reason = "the `c_variadic` feature has not been properly tested on \
- all supported platforms",
- issue = "44930")]
+#[cfg(any(
+ all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), not(target_arch = "x86_64")),
+ all(target_arch = "aarch64", target_os = "ios"),
+ target_arch = "wasm32",
+ target_arch = "asmjs",
+ windows
+))]
+#[unstable(
+ feature = "c_variadic",
+ reason = "the `c_variadic` feature has not been properly tested on \
+ all supported platforms",
+ issue = "44930"
+)]
impl<'f> VaListImpl<'f> {
/// Convert a `VaListImpl` into a `VaList` that is binary-compatible with C's `va_list`.
#[inline]
pub fn as_va_list<'a>(&'a mut self) -> VaList<'a, 'f> {
- VaList {
- inner: VaListImpl { ..*self },
- _marker: PhantomData,
- }
+ VaList { inner: VaListImpl { ..*self }, _marker: PhantomData }
}
}
-#[cfg(all(any(target_arch = "aarch64", target_arch = "powerpc",
- target_arch = "x86_64"),
- any(not(target_arch = "aarch64"), not(target_os = "ios")),
- not(target_arch = "wasm32"),
- not(target_arch = "asmjs"),
- not(windows)))]
-#[unstable(feature = "c_variadic",
- reason = "the `c_variadic` feature has not been properly tested on \
- all supported platforms",
- issue = "44930")]
+#[cfg(all(
+ any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"),
+ any(not(target_arch = "aarch64"), not(target_os = "ios")),
+ not(target_arch = "wasm32"),
+ not(target_arch = "asmjs"),
+ not(windows)
+))]
+#[unstable(
+ feature = "c_variadic",
+ reason = "the `c_variadic` feature has not been properly tested on \
+ all supported platforms",
+ issue = "44930"
+)]
impl<'f> VaListImpl<'f> {
/// Convert a `VaListImpl` into a `VaList` that is binary-compatible with C's `va_list`.
#[inline]
pub fn as_va_list<'a>(&'a mut self) -> VaList<'a, 'f> {
- VaList {
- inner: self,
- _marker: PhantomData,
- }
+ VaList { inner: self, _marker: PhantomData }
}
}
-#[unstable(feature = "c_variadic",
- reason = "the `c_variadic` feature has not been properly tested on \
- all supported platforms",
- issue = "44930")]
+#[unstable(
+ feature = "c_variadic",
+ reason = "the `c_variadic` feature has not been properly tested on \
+ all supported platforms",
+ issue = "44930"
+)]
impl<'a, 'f: 'a> Deref for VaList<'a, 'f> {
type Target = VaListImpl<'f>;
}
}
-#[unstable(feature = "c_variadic",
- reason = "the `c_variadic` feature has not been properly tested on \
- all supported platforms",
- issue = "44930")]
+#[unstable(
+ feature = "c_variadic",
+ reason = "the `c_variadic` feature has not been properly tested on \
+ all supported platforms",
+ issue = "44930"
+)]
impl<'a, 'f: 'a> DerefMut for VaList<'a, 'f> {
#[inline]
fn deref_mut(&mut self) -> &mut VaListImpl<'f> {
/// Trait which whitelists the allowed types to be used with [VaList::arg]
///
/// [VaList::va_arg]: struct.VaList.html#method.arg
- #[unstable(feature = "c_variadic",
- reason = "the `c_variadic` feature has not been properly tested on \
- all supported platforms",
- issue = "44930")]
+ #[unstable(
+ feature = "c_variadic",
+ reason = "the `c_variadic` feature has not been properly tested on \
+ all supported platforms",
+ issue = "44930"
+ )]
pub trait VaArgSafe {}
}
}
}
-impl_va_arg_safe!{i8, i16, i32, i64, usize}
-impl_va_arg_safe!{u8, u16, u32, u64, isize}
-impl_va_arg_safe!{f64}
+impl_va_arg_safe! {i8, i16, i32, i64, usize}
+impl_va_arg_safe! {u8, u16, u32, u64, isize}
+impl_va_arg_safe! {f64}
-#[unstable(feature = "c_variadic",
- reason = "the `c_variadic` feature has not been properly tested on \
- all supported platforms",
- issue = "44930")]
+#[unstable(
+ feature = "c_variadic",
+ reason = "the `c_variadic` feature has not been properly tested on \
+ all supported platforms",
+ issue = "44930"
+)]
impl<T> sealed_trait::VaArgSafe for *mut T {}
-#[unstable(feature = "c_variadic",
- reason = "the `c_variadic` feature has not been properly tested on \
- all supported platforms",
- issue = "44930")]
+#[unstable(
+ feature = "c_variadic",
+ reason = "the `c_variadic` feature has not been properly tested on \
+ all supported platforms",
+ issue = "44930"
+)]
impl<T> sealed_trait::VaArgSafe for *const T {}
-#[unstable(feature = "c_variadic",
- reason = "the `c_variadic` feature has not been properly tested on \
- all supported platforms",
- issue = "44930")]
+#[unstable(
+ feature = "c_variadic",
+ reason = "the `c_variadic` feature has not been properly tested on \
+ all supported platforms",
+ issue = "44930"
+)]
impl<'f> VaListImpl<'f> {
/// Advance to the next arg.
#[inline]
/// Copies the `va_list` at the current location.
pub unsafe fn with_copy<F, R>(&self, f: F) -> R
- where F: for<'copy> FnOnce(VaList<'copy, 'f>) -> R {
+ where
+ F: for<'copy> FnOnce(VaList<'copy, 'f>) -> R,
+ {
let mut ap = self.clone();
let ret = f(ap.as_va_list());
va_end(&mut ap);
}
}
-#[unstable(feature = "c_variadic",
- reason = "the `c_variadic` feature has not been properly tested on \
- all supported platforms",
- issue = "44930")]
+#[unstable(
+ feature = "c_variadic",
+ reason = "the `c_variadic` feature has not been properly tested on \
+ all supported platforms",
+ issue = "44930"
+)]
impl<'f> Clone for VaListImpl<'f> {
#[inline]
fn clone(&self) -> Self {
}
}
-#[unstable(feature = "c_variadic",
- reason = "the `c_variadic` feature has not been properly tested on \
- all supported platforms",
- issue = "44930")]
+#[unstable(
+ feature = "c_variadic",
+ reason = "the `c_variadic` feature has not been properly tested on \
+ all supported platforms",
+ issue = "44930"
+)]
impl<'f> Drop for VaListImpl<'f> {
fn drop(&mut self) {
// FIXME: this should call `va_end`, but there's no clean way to
-use crate::fmt::{Formatter, Result, LowerExp, UpperExp, Display, Debug};
+use crate::fmt::{Debug, Display, Formatter, LowerExp, Result, UpperExp};
use crate::mem::MaybeUninit;
use crate::num::flt2dec;
// Don't inline this so callers don't use the stack space this function
// requires unless they have to.
#[inline(never)]
-fn float_to_decimal_common_exact<T>(fmt: &mut Formatter<'_>, num: &T,
- sign: flt2dec::Sign, precision: usize) -> Result
- where T: flt2dec::DecodableFloat
+fn float_to_decimal_common_exact<T>(
+ fmt: &mut Formatter<'_>,
+ num: &T,
+ sign: flt2dec::Sign,
+ precision: usize,
+) -> Result
+where
+ T: flt2dec::DecodableFloat,
{
unsafe {
let mut buf = MaybeUninit::<[u8; 1024]>::uninit(); // enough for f32 and f64
// we decided whether that is valid or not.
// We can do this only because we are libstd and coupled to the compiler.
// (FWIW, using `freeze` would not be enough; `flt2dec::Part` is an enum!)
- let formatted = flt2dec::to_exact_fixed_str(flt2dec::strategy::grisu::format_exact,
- *num, sign, precision,
- false, buf.get_mut(), parts.get_mut());
+ let formatted = flt2dec::to_exact_fixed_str(
+ flt2dec::strategy::grisu::format_exact,
+ *num,
+ sign,
+ precision,
+ false,
+ buf.get_mut(),
+ parts.get_mut(),
+ );
fmt.pad_formatted_parts(&formatted)
}
}
// Don't inline this so callers that call both this and the above won't wind
// up using the combined stack space of both functions in some cases.
#[inline(never)]
-fn float_to_decimal_common_shortest<T>(fmt: &mut Formatter<'_>, num: &T,
- sign: flt2dec::Sign, precision: usize) -> Result
- where T: flt2dec::DecodableFloat
+fn float_to_decimal_common_shortest<T>(
+ fmt: &mut Formatter<'_>,
+ num: &T,
+ sign: flt2dec::Sign,
+ precision: usize,
+) -> Result
+where
+ T: flt2dec::DecodableFloat,
{
unsafe {
// enough for f32 and f64
let mut buf = MaybeUninit::<[u8; flt2dec::MAX_SIG_DIGITS]>::uninit();
let mut parts = MaybeUninit::<[flt2dec::Part<'_>; 4]>::uninit();
// FIXME(#53491)
- let formatted = flt2dec::to_shortest_str(flt2dec::strategy::grisu::format_shortest, *num,
- sign, precision, false, buf.get_mut(),
- parts.get_mut());
+ let formatted = flt2dec::to_shortest_str(
+ flt2dec::strategy::grisu::format_shortest,
+ *num,
+ sign,
+ precision,
+ false,
+ buf.get_mut(),
+ parts.get_mut(),
+ );
fmt.pad_formatted_parts(&formatted)
}
}
// Common code of floating point Debug and Display.
-fn float_to_decimal_common<T>(fmt: &mut Formatter<'_>, num: &T,
- negative_zero: bool, min_precision: usize) -> Result
- where T: flt2dec::DecodableFloat
+fn float_to_decimal_common<T>(
+ fmt: &mut Formatter<'_>,
+ num: &T,
+ negative_zero: bool,
+ min_precision: usize,
+) -> Result
+where
+ T: flt2dec::DecodableFloat,
{
let force_sign = fmt.sign_plus();
let sign = match (force_sign, negative_zero) {
(false, false) => flt2dec::Sign::Minus,
- (false, true) => flt2dec::Sign::MinusRaw,
- (true, false) => flt2dec::Sign::MinusPlus,
- (true, true) => flt2dec::Sign::MinusPlusRaw,
+ (false, true) => flt2dec::Sign::MinusRaw,
+ (true, false) => flt2dec::Sign::MinusPlus,
+ (true, true) => flt2dec::Sign::MinusPlusRaw,
};
if let Some(precision) = fmt.precision {
// Don't inline this so callers don't use the stack space this function
// requires unless they have to.
#[inline(never)]
-fn float_to_exponential_common_exact<T>(fmt: &mut Formatter<'_>, num: &T,
- sign: flt2dec::Sign, precision: usize,
- upper: bool) -> Result
- where T: flt2dec::DecodableFloat
+fn float_to_exponential_common_exact<T>(
+ fmt: &mut Formatter<'_>,
+ num: &T,
+ sign: flt2dec::Sign,
+ precision: usize,
+ upper: bool,
+) -> Result
+where
+ T: flt2dec::DecodableFloat,
{
unsafe {
let mut buf = MaybeUninit::<[u8; 1024]>::uninit(); // enough for f32 and f64
let mut parts = MaybeUninit::<[flt2dec::Part<'_>; 6]>::uninit();
// FIXME(#53491)
- let formatted = flt2dec::to_exact_exp_str(flt2dec::strategy::grisu::format_exact,
- *num, sign, precision,
- upper, buf.get_mut(), parts.get_mut());
+ let formatted = flt2dec::to_exact_exp_str(
+ flt2dec::strategy::grisu::format_exact,
+ *num,
+ sign,
+ precision,
+ upper,
+ buf.get_mut(),
+ parts.get_mut(),
+ );
fmt.pad_formatted_parts(&formatted)
}
}
// Don't inline this so callers that call both this and the above won't wind
// up using the combined stack space of both functions in some cases.
#[inline(never)]
-fn float_to_exponential_common_shortest<T>(fmt: &mut Formatter<'_>,
- num: &T, sign: flt2dec::Sign,
- upper: bool) -> Result
- where T: flt2dec::DecodableFloat
+fn float_to_exponential_common_shortest<T>(
+ fmt: &mut Formatter<'_>,
+ num: &T,
+ sign: flt2dec::Sign,
+ upper: bool,
+) -> Result
+where
+ T: flt2dec::DecodableFloat,
{
unsafe {
// enough for f32 and f64
let mut buf = MaybeUninit::<[u8; flt2dec::MAX_SIG_DIGITS]>::uninit();
let mut parts = MaybeUninit::<[flt2dec::Part<'_>; 6]>::uninit();
// FIXME(#53491)
- let formatted = flt2dec::to_shortest_exp_str(flt2dec::strategy::grisu::format_shortest,
- *num, sign, (0, 0), upper,
- buf.get_mut(), parts.get_mut());
+ let formatted = flt2dec::to_shortest_exp_str(
+ flt2dec::strategy::grisu::format_shortest,
+ *num,
+ sign,
+ (0, 0),
+ upper,
+ buf.get_mut(),
+ parts.get_mut(),
+ );
fmt.pad_formatted_parts(&formatted)
}
}
// Common code of floating point LowerExp and UpperExp.
fn float_to_exponential_common<T>(fmt: &mut Formatter<'_>, num: &T, upper: bool) -> Result
- where T: flt2dec::DecodableFloat
+where
+ T: flt2dec::DecodableFloat,
{
let force_sign = fmt.sign_plus();
let sign = match force_sign {
false => flt2dec::Sign::Minus,
- true => flt2dec::Sign::MinusPlus,
+ true => flt2dec::Sign::MinusPlus,
};
if let Some(precision) = fmt.precision {
}
macro_rules! floating {
- ($ty:ident) => (
+ ($ty:ident) => {
#[stable(feature = "rust1", since = "1.0.0")]
impl Debug for $ty {
fn fmt(&self, fmt: &mut Formatter<'_>) -> Result {
float_to_exponential_common(fmt, self, true)
}
}
- )
+ };
}
floating! { f32 }
#![stable(feature = "rust1", since = "1.0.0")]
-use crate::cell::{UnsafeCell, Cell, RefCell, Ref, RefMut};
+use crate::cell::{Cell, Ref, RefCell, RefMut, UnsafeCell};
use crate::marker::PhantomData;
use crate::mem;
use crate::num::flt2dec;
use crate::slice;
use crate::str;
+mod builders;
mod float;
mod num;
-mod builders;
#[stable(feature = "fmt_flags_align", since = "1.28.0")]
/// Possible alignments returned by `Formatter::align`
}
#[stable(feature = "debug_builders", since = "1.2.0")]
-pub use self::builders::{DebugStruct, DebugTuple, DebugSet, DebugList, DebugMap};
+pub use self::builders::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple};
-#[unstable(feature = "fmt_internals", reason = "internal to format_args!",
- issue = "0")]
+#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "0")]
#[doc(hidden)]
pub mod rt {
pub mod v1;
width: Option<usize>,
precision: Option<usize>,
- buf: &'a mut (dyn Write+'a),
+ buf: &'a mut (dyn Write + 'a),
curarg: slice::Iter<'a, ArgumentV1<'a>>,
args: &'a [ArgumentV1<'a>],
}
/// types, and then this struct is used to canonicalize arguments to one type.
#[derive(Copy, Clone)]
#[allow(missing_debug_implementations)]
-#[unstable(feature = "fmt_internals", reason = "internal to format_args!",
- issue = "0")]
+#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "0")]
#[doc(hidden)]
pub struct ArgumentV1<'a> {
value: &'a Void,
}
#[doc(hidden)]
- #[unstable(feature = "fmt_internals", reason = "internal to format_args!",
- issue = "0")]
- pub fn new<'b, T>(x: &'b T,
- f: fn(&T, &mut Formatter<'_>) -> Result) -> ArgumentV1<'b> {
- unsafe {
- ArgumentV1 {
- formatter: mem::transmute(f),
- value: mem::transmute(x)
- }
- }
+ #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "0")]
+ pub fn new<'b, T>(x: &'b T, f: fn(&T, &mut Formatter<'_>) -> Result) -> ArgumentV1<'b> {
+ unsafe { ArgumentV1 { formatter: mem::transmute(f), value: mem::transmute(x) } }
}
#[doc(hidden)]
- #[unstable(feature = "fmt_internals", reason = "internal to format_args!",
- issue = "0")]
+ #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "0")]
pub fn from_usize(x: &usize) -> ArgumentV1<'_> {
ArgumentV1::new(x, ArgumentV1::show_usize)
}
// flags available in the v1 format of format_args
#[derive(Copy, Clone)]
-enum FlagV1 { SignPlus, SignMinus, Alternate, SignAwareZeroPad, DebugLowerHex, DebugUpperHex }
+enum FlagV1 {
+ SignPlus,
+ SignMinus,
+ Alternate,
+ SignAwareZeroPad,
+ DebugLowerHex,
+ DebugUpperHex,
+}
impl<'a> Arguments<'a> {
/// When using the format_args!() macro, this function is used to generate the
/// Arguments structure.
- #[doc(hidden)] #[inline]
- #[unstable(feature = "fmt_internals", reason = "internal to format_args!",
- issue = "0")]
- pub fn new_v1(pieces: &'a [&'a str],
- args: &'a [ArgumentV1<'a>]) -> Arguments<'a> {
- Arguments {
- pieces,
- fmt: None,
- args,
- }
+ #[doc(hidden)]
+ #[inline]
+ #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "0")]
+ pub fn new_v1(pieces: &'a [&'a str], args: &'a [ArgumentV1<'a>]) -> Arguments<'a> {
+ Arguments { pieces, fmt: None, args }
}
/// This function is used to specify nonstandard formatting parameters.
/// `CountIsParam` or `CountIsNextParam` has to point to an argument
/// created with `argumentusize`. However, failing to do so doesn't cause
/// unsafety, but will ignore invalid .
- #[doc(hidden)] #[inline]
- #[unstable(feature = "fmt_internals", reason = "internal to format_args!",
- issue = "0")]
- pub fn new_v1_formatted(pieces: &'a [&'a str],
- args: &'a [ArgumentV1<'a>],
- fmt: &'a [rt::v1::Argument]) -> Arguments<'a> {
- Arguments {
- pieces,
- fmt: Some(fmt),
- args,
- }
+ #[doc(hidden)]
+ #[inline]
+ #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "0")]
+ pub fn new_v1_formatted(
+ pieces: &'a [&'a str],
+ args: &'a [ArgumentV1<'a>],
+ fmt: &'a [rt::v1::Argument],
+ ) -> Arguments<'a> {
+ Arguments { pieces, fmt: Some(fmt), args }
}
/// Estimates the length of the formatted text.
///
/// This is intended to be used for setting initial `String` capacity
/// when using `format!`. Note: this is neither the lower nor upper bound.
- #[doc(hidden)] #[inline]
- #[unstable(feature = "fmt_internals", reason = "internal to format_args!",
- issue = "0")]
+ #[doc(hidden)]
+ #[inline]
+ #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "0")]
pub fn estimated_capacity(&self) -> usize {
- let pieces_length: usize = self.pieces.iter()
- .map(|x| x.len()).sum();
+ let pieces_length: usize = self.pieces.iter().map(|x| x.len()).sum();
if self.args.is_empty() {
pieces_length
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented(
- on(crate_local, label="`{Self}` cannot be formatted using `{{:?}}`",
- note="add `#[derive(Debug)]` or manually implement `{Debug}`"),
- message="`{Self}` doesn't implement `{Debug}`",
- label="`{Self}` cannot be formatted using `{{:?}}` because it doesn't implement `{Debug}`",
+ on(
+ crate_local,
+ label = "`{Self}` cannot be formatted using `{{:?}}`",
+ note = "add `#[derive(Debug)]` or manually implement `{Debug}`"
+ ),
+ message = "`{Self}` doesn't implement `{Debug}`",
+ label = "`{Self}` cannot be formatted using `{{:?}}` because it doesn't implement `{Debug}`"
)]
#[doc(alias = "{:?}")]
#[rustc_diagnostic_item = "debug_trait"]
#[rustc_builtin_macro]
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
#[allow_internal_unstable(core_intrinsics)]
- pub macro Debug($item:item) { /* compiler built-in */ }
+ pub macro Debug($item:item) {
+ /* compiler built-in */
+ }
}
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
#[doc(inline)]
/// ```
#[rustc_on_unimplemented(
on(
- _Self="std::path::Path",
- label="`{Self}` cannot be formatted with the default formatter; call `.display()` on it",
- note="call `.display()` or `.to_string_lossy()` to safely print paths, \
- as they may contain non-Unicode data"
+ _Self = "std::path::Path",
+ label = "`{Self}` cannot be formatted with the default formatter; call `.display()` on it",
+ note = "call `.display()` or `.to_string_lossy()` to safely print paths, \
+ as they may contain non-Unicode data"
),
- message="`{Self}` doesn't implement `{Display}`",
- label="`{Self}` cannot be formatted with the default formatter",
- note="in format strings you may be able to use `{{:?}}` (or {{:#?}} for pretty-print) instead",
+ message = "`{Self}` doesn't implement `{Display}`",
+ label = "`{Self}` cannot be formatted with the default formatter",
+ note = "in format strings you may be able to use `{{:?}}` (or {{:#?}} for pretty-print) instead"
)]
#[doc(alias = "{}")]
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> Formatter<'a> {
fn wrap_buf<'b, 'c, F>(&'b mut self, wrap: F) -> Formatter<'c>
- where 'b: 'c, F: FnOnce(&'b mut (dyn Write+'b)) -> &'c mut (dyn Write+'c)
+ where
+ 'b: 'c,
+ F: FnOnce(&'b mut (dyn Write + 'b)) -> &'c mut (dyn Write + 'c),
{
Formatter {
// We want to change this
// Extract the correct argument
let value = match arg.position {
- rt::v1::Position::Next => { *self.curarg.next().unwrap() }
+ rt::v1::Position::Next => *self.curarg.next().unwrap(),
rt::v1::Position::At(i) => self.args[i],
};
match *cnt {
rt::v1::Count::Is(n) => Some(n),
rt::v1::Count::Implied => None,
- rt::v1::Count::Param(i) => {
- self.args[i].as_usize()
- }
- rt::v1::Count::NextParam => {
- self.curarg.next()?.as_usize()
- }
+ rt::v1::Count::Param(i) => self.args[i].as_usize(),
+ rt::v1::Count::NextParam => self.curarg.next()?.as_usize(),
}
}
/// assert_eq!(&format!("{:0>#8}", Foo::new(-1)), "00-Foo 1");
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
- pub fn pad_integral(&mut self,
- is_nonnegative: bool,
- prefix: &str,
- buf: &str)
- -> Result {
+ pub fn pad_integral(&mut self, is_nonnegative: bool, prefix: &str, buf: &str) -> Result {
let mut width = buf.len();
let mut sign = None;
if !is_nonnegative {
- sign = Some('-'); width += 1;
+ sign = Some('-');
+ width += 1;
} else if self.sign_plus() {
- sign = Some('+'); width += 1;
+ sign = Some('+');
+ width += 1;
}
let prefix = if self.alternate() {
if let Some(c) = sign {
f.buf.write_char(c)?;
}
- if let Some(prefix) = prefix {
- f.buf.write_str(prefix)
- } else {
- Ok(())
- }
+ if let Some(prefix) = prefix { f.buf.write_str(prefix) } else { Ok(()) }
}
// The `width` field is more of a `min-width` parameter at this point.
None => self.buf.write_str(s),
// If we're under the maximum width, check if we're over the minimum
// width, if so it's as easy as just emitting the string.
- Some(width) if s.chars().count() >= width => {
- self.buf.write_str(s)
- }
+ Some(width) if s.chars().count() >= width => self.buf.write_str(s),
// If we're under both the maximum and the minimum width, then fill
// up the minimum width with the specified string + some alignment.
Some(width) => {
fn padding(
&mut self,
padding: usize,
- default: rt::v1::Alignment
+ default: rt::v1::Alignment,
) -> result::Result<PostPadding, Error> {
let align = match self.align {
rt::v1::Alignment::Unknown => default,
- _ => self.align
+ _ => self.align,
};
let (pre_pad, post_pad) = match align {
rt::v1::Alignment::Left => (0, padding),
- rt::v1::Alignment::Right |
- rt::v1::Alignment::Unknown => (padding, 0),
+ rt::v1::Alignment::Right | rt::v1::Alignment::Unknown => (padding, 0),
rt::v1::Alignment::Center => (padding / 2, (padding + 1) / 2),
};
// remaining parts go through the ordinary padding process.
let len = formatted.len();
- let ret = if width <= len { // no padding
+ let ret = if width <= len {
+ // no padding
self.write_formatted_parts(&formatted)
} else {
let post_padding = self.padding(width - len, align)?;
/// Flags for formatting
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_deprecated(since = "1.24.0",
- reason = "use the `sign_plus`, `sign_minus`, `alternate`, \
- or `sign_aware_zero_pad` methods instead")]
- pub fn flags(&self) -> u32 { self.flags }
+ #[rustc_deprecated(
+ since = "1.24.0",
+ reason = "use the `sign_plus`, `sign_minus`, `alternate`, \
+ or `sign_aware_zero_pad` methods instead"
+ )]
+ pub fn flags(&self) -> u32 {
+ self.flags
+ }
/// Character used as 'fill' whenever there is alignment.
///
/// assert_eq!(&format!("{:t>6}", Foo), "tttttt");
/// ```
#[stable(feature = "fmt_flags", since = "1.5.0")]
- pub fn fill(&self) -> char { self.fill }
+ pub fn fill(&self) -> char {
+ self.fill
+ }
/// Flag indicating what form of alignment was requested.
///
/// assert_eq!(&format!("{}", Foo(23)), "Foo(23)");
/// ```
#[stable(feature = "fmt_flags", since = "1.5.0")]
- pub fn width(&self) -> Option<usize> { self.width }
+ pub fn width(&self) -> Option<usize> {
+ self.width
+ }
/// Optionally specified precision for numeric types.
///
/// assert_eq!(&format!("{}", Foo(23.2)), "Foo(23.20)");
/// ```
#[stable(feature = "fmt_flags", since = "1.5.0")]
- pub fn precision(&self) -> Option<usize> { self.precision }
+ pub fn precision(&self) -> Option<usize> {
+ self.precision
+ }
/// Determines if the `+` flag was specified.
///
/// assert_eq!(&format!("{}", Foo(23)), "Foo(23)");
/// ```
#[stable(feature = "fmt_flags", since = "1.5.0")]
- pub fn sign_plus(&self) -> bool { self.flags & (1 << FlagV1::SignPlus as u32) != 0 }
+ pub fn sign_plus(&self) -> bool {
+ self.flags & (1 << FlagV1::SignPlus as u32) != 0
+ }
/// Determines if the `-` flag was specified.
///
/// assert_eq!(&format!("{}", Foo(23)), "Foo(23)");
/// ```
#[stable(feature = "fmt_flags", since = "1.5.0")]
- pub fn sign_minus(&self) -> bool { self.flags & (1 << FlagV1::SignMinus as u32) != 0 }
+ pub fn sign_minus(&self) -> bool {
+ self.flags & (1 << FlagV1::SignMinus as u32) != 0
+ }
/// Determines if the `#` flag was specified.
///
/// assert_eq!(&format!("{}", Foo(23)), "23");
/// ```
#[stable(feature = "fmt_flags", since = "1.5.0")]
- pub fn alternate(&self) -> bool { self.flags & (1 << FlagV1::Alternate as u32) != 0 }
+ pub fn alternate(&self) -> bool {
+ self.flags & (1 << FlagV1::Alternate as u32) != 0
+ }
/// Determines if the `0` flag was specified.
///
// FIXME: Decide what public API we want for these two flags.
// https://github.com/rust-lang/rust/issues/48584
- fn debug_lower_hex(&self) -> bool { self.flags & (1 << FlagV1::DebugLowerHex as u32) != 0 }
+ fn debug_lower_hex(&self) -> bool {
+ self.flags & (1 << FlagV1::DebugLowerHex as u32) != 0
+ }
- fn debug_upper_hex(&self) -> bool { self.flags & (1 << FlagV1::DebugUpperHex as u32) != 0 }
+ fn debug_upper_hex(&self) -> bool {
+ self.flags & (1 << FlagV1::DebugUpperHex as u32) != 0
+ }
/// Creates a [`DebugStruct`] builder designed to assist with creation of
/// [`fmt::Debug`] implementations for structs.
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Debug for *const T {
- fn fmt(&self, f: &mut Formatter<'_>) -> Result { Pointer::fmt(self, f) }
+ fn fmt(&self, f: &mut Formatter<'_>) -> Result {
+ Pointer::fmt(self, f)
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Debug for *mut T {
- fn fmt(&self, f: &mut Formatter<'_>) -> Result { Pointer::fmt(self, f) }
+ fn fmt(&self, f: &mut Formatter<'_>) -> Result {
+ Pointer::fmt(self, f)
+ }
}
macro_rules! peel {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Copy + Debug> Debug for Cell<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
- f.debug_struct("Cell")
- .field("value", &self.get())
- .finish()
+ f.debug_struct("Cell").field("value", &self.get()).finish()
}
}
impl<T: ?Sized + Debug> Debug for RefCell<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
match self.try_borrow() {
- Ok(borrow) => {
- f.debug_struct("RefCell")
- .field("value", &borrow)
- .finish()
- }
+ Ok(borrow) => f.debug_struct("RefCell").field("value", &borrow).finish(),
Err(_) => {
// The RefCell is mutably borrowed so we can't look at its value
// here. Show a placeholder instead.
}
}
- f.debug_struct("RefCell")
- .field("value", &BorrowedPlaceholder)
- .finish()
+ f.debug_struct("RefCell").field("value", &BorrowedPlaceholder).finish()
}
}
}
/// [`Hasher`]: trait.Hasher.html
#[stable(feature = "hash_slice", since = "1.3.0")]
fn hash_slice<H: Hasher>(data: &[Self], state: &mut H)
- where Self: Sized
+ where
+ Self: Sized,
{
for piece in data {
piece.hash(state);
#[rustc_builtin_macro]
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
#[allow_internal_unstable(core_intrinsics)]
- pub macro Hash($item:item) { /* compiler built-in */ }
+ pub macro Hash($item:item) {
+ /* compiler built-in */
+ }
}
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
#[doc(inline)]
}
}
-
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + Hash> Hash for &T {
fn hash<H: Hasher>(&self, state: &mut H) {
state.write_usize(*self as *const () as usize);
} else {
// Fat pointer
- let (a, b) = unsafe {
- *(self as *const Self as *const (usize, usize))
- };
+ let (a, b) = unsafe { *(self as *const Self as *const (usize, usize)) };
state.write_usize(a);
state.write_usize(b);
}
state.write_usize(*self as *const () as usize);
} else {
// Fat pointer
- let (a, b) = unsafe {
- *(self as *const Self as *const (usize, usize))
- };
+ let (a, b) = unsafe { *(self as *const Self as *const (usize, usize)) };
state.write_usize(a);
state.write_usize(b);
}
#![allow(deprecated)] // the types in this module are deprecated
-use crate::marker::PhantomData;
-use crate::ptr;
use crate::cmp;
+use crate::marker::PhantomData;
use crate::mem;
+use crate::ptr;
/// An implementation of SipHash 1-3.
///
///
/// See: <https://131002.net/siphash>
#[unstable(feature = "hashmap_internals", issue = "0")]
-#[rustc_deprecated(since = "1.13.0",
- reason = "use `std::collections::hash_map::DefaultHasher` instead")]
+#[rustc_deprecated(
+ since = "1.13.0",
+ reason = "use `std::collections::hash_map::DefaultHasher` instead"
+)]
#[derive(Debug, Clone, Default)]
#[doc(hidden)]
pub struct SipHasher13 {
///
/// See: <https://131002.net/siphash/>
#[unstable(feature = "hashmap_internals", issue = "0")]
-#[rustc_deprecated(since = "1.13.0",
- reason = "use `std::collections::hash_map::DefaultHasher` instead")]
+#[rustc_deprecated(
+ since = "1.13.0",
+ reason = "use `std::collections::hash_map::DefaultHasher` instead"
+)]
#[derive(Debug, Clone, Default)]
struct SipHasher24 {
hasher: Hasher<Sip24Rounds>,
/// it is not intended for cryptographic purposes. As such, all
/// cryptographic uses of this implementation are _strongly discouraged_.
#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_deprecated(since = "1.13.0",
- reason = "use `std::collections::hash_map::DefaultHasher` instead")]
+#[rustc_deprecated(
+ since = "1.13.0",
+ reason = "use `std::collections::hash_map::DefaultHasher` instead"
+)]
#[derive(Debug, Clone, Default)]
pub struct SipHasher(SipHasher24);
k0: u64,
k1: u64,
length: usize, // how many bytes we've processed
- state: State, // hash State
- tail: u64, // unprocessed bytes le
- ntail: usize, // how many bytes in tail are valid
+ state: State, // hash State
+ tail: u64, // unprocessed bytes le
+ ntail: usize, // how many bytes in tail are valid
_marker: PhantomData<S>,
}
}
macro_rules! compress {
- ($state:expr) => ({
- compress!($state.v0, $state.v1, $state.v2, $state.v3)
- });
- ($v0:expr, $v1:expr, $v2:expr, $v3:expr) =>
- ({
- $v0 = $v0.wrapping_add($v1); $v1 = $v1.rotate_left(13); $v1 ^= $v0;
+ ($state:expr) => {{ compress!($state.v0, $state.v1, $state.v2, $state.v3) }};
+ ($v0:expr, $v1:expr, $v2:expr, $v3:expr) => {{
+ $v0 = $v0.wrapping_add($v1);
+ $v1 = $v1.rotate_left(13);
+ $v1 ^= $v0;
$v0 = $v0.rotate_left(32);
- $v2 = $v2.wrapping_add($v3); $v3 = $v3.rotate_left(16); $v3 ^= $v2;
- $v0 = $v0.wrapping_add($v3); $v3 = $v3.rotate_left(21); $v3 ^= $v0;
- $v2 = $v2.wrapping_add($v1); $v1 = $v1.rotate_left(17); $v1 ^= $v2;
+ $v2 = $v2.wrapping_add($v3);
+ $v3 = $v3.rotate_left(16);
+ $v3 ^= $v2;
+ $v0 = $v0.wrapping_add($v3);
+ $v3 = $v3.rotate_left(21);
+ $v3 ^= $v0;
+ $v2 = $v2.wrapping_add($v1);
+ $v1 = $v1.rotate_left(17);
+ $v1 ^= $v2;
$v2 = $v2.rotate_left(32);
- });
+ }};
}
/// Loads an integer of the desired type from a byte stream, in LE order. Uses
///
/// Unsafe because: unchecked indexing at i..i+size_of(int_ty)
macro_rules! load_int_le {
- ($buf:expr, $i:expr, $int_ty:ident) =>
- ({
- debug_assert!($i + mem::size_of::<$int_ty>() <= $buf.len());
- let mut data = 0 as $int_ty;
- ptr::copy_nonoverlapping($buf.get_unchecked($i),
- &mut data as *mut _ as *mut u8,
- mem::size_of::<$int_ty>());
- data.to_le()
- });
+ ($buf:expr, $i:expr, $int_ty:ident) => {{
+ debug_assert!($i + mem::size_of::<$int_ty>() <= $buf.len());
+ let mut data = 0 as $int_ty;
+ ptr::copy_nonoverlapping(
+ $buf.get_unchecked($i),
+ &mut data as *mut _ as *mut u8,
+ mem::size_of::<$int_ty>(),
+ );
+ data.to_le()
+ }};
}
/// Loads an u64 using up to 7 bytes of a byte slice.
/// Creates a new `SipHasher` with the two initial keys set to 0.
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_deprecated(since = "1.13.0",
- reason = "use `std::collections::hash_map::DefaultHasher` instead")]
+ #[rustc_deprecated(
+ since = "1.13.0",
+ reason = "use `std::collections::hash_map::DefaultHasher` instead"
+ )]
pub fn new() -> SipHasher {
SipHasher::new_with_keys(0, 0)
}
/// Creates a `SipHasher` that is keyed off the provided keys.
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_deprecated(since = "1.13.0",
- reason = "use `std::collections::hash_map::DefaultHasher` instead")]
+ #[rustc_deprecated(
+ since = "1.13.0",
+ reason = "use `std::collections::hash_map::DefaultHasher` instead"
+ )]
pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher {
- SipHasher(SipHasher24 {
- hasher: Hasher::new_with_keys(key0, key1)
- })
+ SipHasher(SipHasher24 { hasher: Hasher::new_with_keys(key0, key1) })
}
}
/// Creates a new `SipHasher13` with the two initial keys set to 0.
#[inline]
#[unstable(feature = "hashmap_internals", issue = "0")]
- #[rustc_deprecated(since = "1.13.0",
- reason = "use `std::collections::hash_map::DefaultHasher` instead")]
+ #[rustc_deprecated(
+ since = "1.13.0",
+ reason = "use `std::collections::hash_map::DefaultHasher` instead"
+ )]
pub fn new() -> SipHasher13 {
SipHasher13::new_with_keys(0, 0)
}
/// Creates a `SipHasher13` that is keyed off the provided keys.
#[inline]
#[unstable(feature = "hashmap_internals", issue = "0")]
- #[rustc_deprecated(since = "1.13.0",
- reason = "use `std::collections::hash_map::DefaultHasher` instead")]
+ #[rustc_deprecated(
+ since = "1.13.0",
+ reason = "use `std::collections::hash_map::DefaultHasher` instead"
+ )]
pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher13 {
- SipHasher13 {
- hasher: Hasher::new_with_keys(key0, key1)
- }
+ SipHasher13 { hasher: Hasher::new_with_keys(key0, key1) }
}
}
k0: key0,
k1: key1,
length: 0,
- state: State {
- v0: 0,
- v1: 0,
- v2: 0,
- v3: 0,
- },
+ state: State { v0: 0, v1: 0, v2: 0, v3: 0 },
tail: 0,
ntail: 0,
_marker: PhantomData,
self.tail |= unsafe { u8to64_le(msg, 0, cmp::min(length, needed)) } << 8 * self.ntail;
if length < needed {
self.ntail += length;
- return
+ return;
} else {
self.state.v3 ^= self.tail;
S::c_rounds(&mut self.state);
use crate::fmt;
use crate::ops::Try;
-use super::super::{Iterator, DoubleEndedIterator, FusedIterator};
+use super::super::{DoubleEndedIterator, FusedIterator, Iterator};
use super::Map;
/// An iterator that maps each element to an iterator, and yields the elements
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct FlatMap<I, U: IntoIterator, F> {
- inner: FlattenCompat<Map<I, F>, <U as IntoIterator>::IntoIter>
+ inner: FlattenCompat<Map<I, F>, <U as IntoIterator>::IntoIter>,
}
impl<I: Iterator, U: IntoIterator, F: FnMut(I::Item) -> U> FlatMap<I, U, F> {
pub(in super::super) fn new(iter: I, f: F) -> FlatMap<I, U, F> {
where
U: Clone + IntoIterator<IntoIter: Clone>,
{
- fn clone(&self) -> Self { FlatMap { inner: self.inner.clone() } }
+ fn clone(&self) -> Self {
+ FlatMap { inner: self.inner.clone() }
+ }
}
#[stable(feature = "core_impl_debug", since = "1.9.0")]
#[stable(feature = "rust1", since = "1.0.0")]
impl<I: Iterator, U: IntoIterator, F> Iterator for FlatMap<I, U, F>
- where F: FnMut(I::Item) -> U,
+where
+ F: FnMut(I::Item) -> U,
{
type Item = U::Item;
#[inline]
- fn next(&mut self) -> Option<U::Item> { self.inner.next() }
+ fn next(&mut self) -> Option<U::Item> {
+ self.inner.next()
+ }
#[inline]
- fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.inner.size_hint()
+ }
#[inline]
- fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
- Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
+ fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
+ where
+ Self: Sized,
+ Fold: FnMut(Acc, Self::Item) -> R,
+ R: Try<Ok = Acc>,
{
self.inner.try_fold(init, fold)
}
#[inline]
fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
- where Fold: FnMut(Acc, Self::Item) -> Acc,
+ where
+ Fold: FnMut(Acc, Self::Item) -> Acc,
{
self.inner.fold(init, fold)
}
U: IntoIterator<IntoIter: DoubleEndedIterator>,
{
#[inline]
- fn next_back(&mut self) -> Option<U::Item> { self.inner.next_back() }
+ fn next_back(&mut self) -> Option<U::Item> {
+ self.inner.next_back()
+ }
#[inline]
- fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
- Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
+ fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
+ where
+ Self: Sized,
+ Fold: FnMut(Acc, Self::Item) -> R,
+ R: Try<Ok = Acc>,
{
self.inner.try_rfold(init, fold)
}
#[inline]
fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
- where Fold: FnMut(Acc, Self::Item) -> Acc,
+ where
+ Fold: FnMut(Acc, Self::Item) -> Acc,
{
self.inner.rfold(init, fold)
}
#[stable(feature = "fused", since = "1.26.0")]
impl<I, U, F> FusedIterator for FlatMap<I, U, F>
- where I: FusedIterator, U: IntoIterator, F: FnMut(I::Item) -> U {}
+where
+ I: FusedIterator,
+ U: IntoIterator,
+ F: FnMut(I::Item) -> U,
+{
+}
/// An iterator that flattens one level of nesting in an iterator of things
/// that can be turned into iterators.
I: Clone + Iterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
U: Clone + Iterator,
{
- fn clone(&self) -> Self { Flatten { inner: self.inner.clone() } }
+ fn clone(&self) -> Self {
+ Flatten { inner: self.inner.clone() }
+ }
}
#[stable(feature = "iterator_flatten", since = "1.29.0")]
type Item = U::Item;
#[inline]
- fn next(&mut self) -> Option<U::Item> { self.inner.next() }
+ fn next(&mut self) -> Option<U::Item> {
+ self.inner.next()
+ }
#[inline]
- fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.inner.size_hint()
+ }
#[inline]
- fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
- Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
+ fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
+ where
+ Self: Sized,
+ Fold: FnMut(Acc, Self::Item) -> R,
+ R: Try<Ok = Acc>,
{
self.inner.try_fold(init, fold)
}
#[inline]
fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
- where Fold: FnMut(Acc, Self::Item) -> Acc,
+ where
+ Fold: FnMut(Acc, Self::Item) -> Acc,
{
self.inner.fold(init, fold)
}
U: DoubleEndedIterator,
{
#[inline]
- fn next_back(&mut self) -> Option<U::Item> { self.inner.next_back() }
+ fn next_back(&mut self) -> Option<U::Item> {
+ self.inner.next_back()
+ }
#[inline]
- fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
- Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
+ fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
+ where
+ Self: Sized,
+ Fold: FnMut(Acc, Self::Item) -> R,
+ R: Try<Ok = Acc>,
{
self.inner.try_rfold(init, fold)
}
#[inline]
fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
- where Fold: FnMut(Acc, Self::Item) -> Acc,
+ where
+ Fold: FnMut(Acc, Self::Item) -> Acc,
{
self.inner.rfold(init, fold)
}
where
I: FusedIterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
U: Iterator,
-{}
+{
+}
/// Real logic of both `Flatten` and `FlatMap` which simply delegate to
/// this type.
fn next(&mut self) -> Option<U::Item> {
loop {
if let Some(ref mut inner) = self.frontiter {
- if let elt@Some(_) = inner.next() { return elt }
+ if let elt @ Some(_) = inner.next() {
+ return elt;
+ }
}
match self.iter.next() {
None => return self.backiter.as_mut()?.next(),
let lo = flo.saturating_add(blo);
match (self.iter.size_hint(), fhi, bhi) {
((0, Some(0)), Some(a), Some(b)) => (lo, a.checked_add(b)),
- _ => (lo, None)
+ _ => (lo, None),
}
}
#[inline]
- fn try_fold<Acc, Fold, R>(&mut self, mut init: Acc, mut fold: Fold) -> R where
- Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
+ fn try_fold<Acc, Fold, R>(&mut self, mut init: Acc, mut fold: Fold) -> R
+ where
+ Self: Sized,
+ Fold: FnMut(Acc, Self::Item) -> R,
+ R: Try<Ok = Acc>,
{
#[inline]
fn flatten<'a, T: IntoIterator, Acc, R: Try<Ok = Acc>>(
#[inline]
fn fold<Acc, Fold>(self, init: Acc, ref mut fold: Fold) -> Acc
- where Fold: FnMut(Acc, Self::Item) -> Acc,
+ where
+ Fold: FnMut(Acc, Self::Item) -> Acc,
{
#[inline]
fn flatten<U: Iterator, Acc>(
move |acc, iter| iter.fold(acc, &mut *fold)
}
- self.frontiter.into_iter()
+ self.frontiter
+ .into_iter()
.chain(self.iter.map(IntoIterator::into_iter))
.chain(self.backiter)
.fold(init, flatten(fold))
fn next_back(&mut self) -> Option<U::Item> {
loop {
if let Some(ref mut inner) = self.backiter {
- if let elt@Some(_) = inner.next_back() { return elt }
+ if let elt @ Some(_) = inner.next_back() {
+ return elt;
+ }
}
match self.iter.next_back() {
None => return self.frontiter.as_mut()?.next_back(),
}
#[inline]
- fn try_rfold<Acc, Fold, R>(&mut self, mut init: Acc, mut fold: Fold) -> R where
- Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
+ fn try_rfold<Acc, Fold, R>(&mut self, mut init: Acc, mut fold: Fold) -> R
+ where
+ Self: Sized,
+ Fold: FnMut(Acc, Self::Item) -> R,
+ R: Try<Ok = Acc>,
{
#[inline]
fn flatten<'a, T: IntoIterator, Acc, R: Try<Ok = Acc>>(
backiter: &'a mut Option<T::IntoIter>,
fold: &'a mut impl FnMut(Acc, T::Item) -> R,
- ) -> impl FnMut(Acc, T) -> R + 'a where
+ ) -> impl FnMut(Acc, T) -> R + 'a
+ where
T::IntoIter: DoubleEndedIterator,
{
move |acc, x| {
#[inline]
fn rfold<Acc, Fold>(self, init: Acc, ref mut fold: Fold) -> Acc
- where Fold: FnMut(Acc, Self::Item) -> Acc,
+ where
+ Fold: FnMut(Acc, Self::Item) -> Acc,
{
#[inline]
fn flatten<U: DoubleEndedIterator, Acc>(
move |acc, iter| iter.rfold(acc, &mut *fold)
}
- self.frontiter.into_iter()
+ self.frontiter
+ .into_iter()
.chain(self.iter.map(IntoIterator::into_iter))
.chain(self.backiter)
.rfold(init, flatten(fold))
#[derive(Clone, Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Repeat<A> {
- element: A
+ element: A,
}
#[stable(feature = "rust1", since = "1.0.0")]
type Item = A;
#[inline]
- fn next(&mut self) -> Option<A> { Some(self.element.clone()) }
+ fn next(&mut self) -> Option<A> {
+ Some(self.element.clone())
+ }
#[inline]
- fn size_hint(&self) -> (usize, Option<usize>) { (usize::MAX, None) }
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (usize::MAX, None)
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<A: Clone> DoubleEndedIterator for Repeat<A> {
#[inline]
- fn next_back(&mut self) -> Option<A> { Some(self.element.clone()) }
+ fn next_back(&mut self) -> Option<A> {
+ Some(self.element.clone())
+ }
}
#[stable(feature = "fused", since = "1.26.0")]
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn repeat<T: Clone>(elt: T) -> Repeat<T> {
- Repeat{element: elt}
+ Repeat { element: elt }
}
/// An iterator that repeats elements of type `A` endlessly by
#[derive(Copy, Clone, Debug)]
#[stable(feature = "iterator_repeat_with", since = "1.28.0")]
pub struct RepeatWith<F> {
- repeater: F
+ repeater: F,
}
#[stable(feature = "iterator_repeat_with", since = "1.28.0")]
type Item = A;
#[inline]
- fn next(&mut self) -> Option<A> { Some((self.repeater)()) }
+ fn next(&mut self) -> Option<A> {
+ Some((self.repeater)())
+ }
#[inline]
- fn size_hint(&self) -> (usize, Option<usize>) { (usize::MAX, None) }
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (usize::MAX, None)
+ }
}
#[stable(feature = "iterator_repeat_with", since = "1.28.0")]
None
}
- fn size_hint(&self) -> (usize, Option<usize>){
+ fn size_hint(&self) -> (usize, Option<usize>) {
(0, Some(0))
}
}
#[derive(Clone, Debug)]
#[stable(feature = "iter_once", since = "1.2.0")]
pub struct Once<T> {
- inner: crate::option::IntoIter<T>
+ inner: crate::option::IntoIter<T>,
}
#[stable(feature = "iter_once", since = "1.2.0")]
#[inline]
#[stable(feature = "iter_from_fn", since = "1.34.0")]
pub fn from_fn<T, F>(f: F) -> FromFn<F>
- where F: FnMut() -> Option<T>
+where
+ F: FnMut() -> Option<T>,
{
FromFn(f)
}
#[stable(feature = "iter_from_fn", since = "1.34.0")]
impl<T, F> Iterator for FromFn<F>
- where F: FnMut() -> Option<T>
+where
+ F: FnMut() -> Option<T>,
{
type Item = T;
/// ```
#[stable(feature = "iter_successors", since = "1.34.0")]
pub fn successors<T, F>(first: Option<T>, succ: F) -> Successors<T, F>
- where F: FnMut(&T) -> Option<T>
+where
+ F: FnMut(&T) -> Option<T>,
{
// If this function returned `impl Iterator<Item=T>`
// it could be based on `unfold` and not need a dedicated type.
// However having a named `Successors<T, F>` type allows it to be `Clone` when `T` and `F` are.
- Successors {
- next: first,
- succ,
- }
+ Successors { next: first, succ }
}
/// An new iterator where each successive item is computed based on the preceding one.
#[stable(feature = "iter_successors", since = "1.34.0")]
impl<T, F> Iterator for Successors<T, F>
- where F: FnMut(&T) -> Option<T>
+where
+ F: FnMut(&T) -> Option<T>,
{
type Item = T;
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
- if self.next.is_some() {
- (1, None)
- } else {
- (0, Some(0))
- }
+ if self.next.is_some() { (1, None) } else { (0, Some(0)) }
}
}
#[stable(feature = "iter_successors", since = "1.34.0")]
-impl<T, F> FusedIterator for Successors<T, F>
- where F: FnMut(&T) -> Option<T>
-{}
+impl<T, F> FusedIterator for Successors<T, F> where F: FnMut(&T) -> Option<T> {}
#[stable(feature = "iter_successors", since = "1.34.0")]
impl<T: fmt::Debug, F> fmt::Debug for Successors<T, F> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("Successors")
- .field("next", &self.next)
- .finish()
+ f.debug_struct("Successors").field("next", &self.next).finish()
}
}
-use crate::ops::{Mul, Add};
-use crate::num::Wrapping;
use crate::iter;
+use crate::num::Wrapping;
+use crate::ops::{Add, Mul};
/// Trait to represent types that can be created by summing up an iterator.
///
/// Method which takes an iterator and generates `Self` from the elements by
/// "summing up" the items.
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
- fn sum<I: Iterator<Item=A>>(iter: I) -> Self;
+ fn sum<I: Iterator<Item = A>>(iter: I) -> Self;
}
/// Trait to represent types that can be created by multiplying elements of an
/// Method which takes an iterator and generates `Self` from the elements by
/// multiplying the items.
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
- fn product<I: Iterator<Item=A>>(iter: I) -> Self;
+ fn product<I: Iterator<Item = A>>(iter: I) -> Self;
}
// N.B., explicitly use Add and Mul here to inherit overflow checks
integer_sum_product! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize }
float_sum_product! { f32 f64 }
-#[stable(feature = "iter_arith_traits_result", since="1.16.0")]
+#[stable(feature = "iter_arith_traits_result", since = "1.16.0")]
impl<T, U, E> Sum<Result<U, E>> for Result<T, E>
- where T: Sum<U>,
+where
+ T: Sum<U>,
{
/// Takes each element in the `Iterator`: if it is an `Err`, no further
/// elements are taken, and the `Err` is returned. Should no `Err` occur,
/// assert_eq!(res, Ok(3));
/// ```
fn sum<I>(iter: I) -> Result<T, E>
- where I: Iterator<Item = Result<U, E>>,
+ where
+ I: Iterator<Item = Result<U, E>>,
{
iter::process_results(iter, |i| i.sum())
}
}
-#[stable(feature = "iter_arith_traits_result", since="1.16.0")]
+#[stable(feature = "iter_arith_traits_result", since = "1.16.0")]
impl<T, U, E> Product<Result<U, E>> for Result<T, E>
- where T: Product<U>,
+where
+ T: Product<U>,
{
/// Takes each element in the `Iterator`: if it is an `Err`, no further
/// elements are taken, and the `Err` is returned. Should no `Err` occur,
/// the product of all elements is returned.
fn product<I>(iter: I) -> Result<T, E>
- where I: Iterator<Item = Result<U, E>>,
+ where
+ I: Iterator<Item = Result<U, E>>,
{
iter::process_results(iter, |i| i.product())
}
-use crate::ops::Try;
use crate::iter::LoopState;
+use crate::ops::Try;
/// An iterator able to yield elements from both ends.
///
#[stable(feature = "iter_nth_back", since = "1.37.0")]
fn nth_back(&mut self, mut n: usize) -> Option<Self::Item> {
for x in self.rev() {
- if n == 0 { return Some(x) }
+ if n == 0 {
+ return Some(x);
+ }
n -= 1;
}
None
where
Self: Sized,
F: FnMut(B, Self::Item) -> R,
- R: Try<Ok=B>
+ R: Try<Ok = B>,
{
let mut accum = init;
while let Some(x) = self.next_back() {
fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
where
Self: Sized,
- P: FnMut(&Self::Item) -> bool
+ P: FnMut(&Self::Item) -> bool,
{
#[inline]
fn check<T>(
#[rustc_deprecated(since = "1.39.0", reason = "use the `?` operator instead")]
#[doc(alias = "?")]
macro_rules! r#try {
- ($expr:expr) => (match $expr {
- $crate::result::Result::Ok(val) => val,
- $crate::result::Result::Err(err) => {
- return $crate::result::Result::Err($crate::convert::From::from(err))
+ ($expr:expr) => {
+ match $expr {
+ $crate::result::Result::Ok(val) => val,
+ $crate::result::Result::Err(err) => {
+ return $crate::result::Result::Err($crate::convert::From::from(err));
+ }
}
- });
- ($expr:expr,) => ($crate::r#try!($expr));
+ };
+ ($expr:expr,) => {
+ $crate::r#try!($expr)
+ };
}
/// Writes formatted data into a buffer.
#[rustc_builtin_macro]
#[macro_export]
macro_rules! compile_error {
- ($msg:expr) => ({ /* compiler built-in */ });
- ($msg:expr,) => ({ /* compiler built-in */ })
+ ($msg:expr) => {{ /* compiler built-in */ }};
+ ($msg:expr,) => {{ /* compiler built-in */ }};
}
/// Constructs parameters for the other string-formatting macros.
#[rustc_builtin_macro]
#[macro_export]
macro_rules! format_args {
- ($fmt:expr) => ({ /* compiler built-in */ });
- ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ })
+ ($fmt:expr) => {{ /* compiler built-in */ }};
+ ($fmt:expr, $($args:tt)*) => {{ /* compiler built-in */ }};
}
/// Same as `format_args`, but adds a newline in the end.
- #[unstable(feature = "format_args_nl", issue = "0",
- reason = "`format_args_nl` is only for internal \
- language use and is subject to change")]
+ #[unstable(
+ feature = "format_args_nl",
+ issue = "0",
+ reason = "`format_args_nl` is only for internal \
+ language use and is subject to change"
+ )]
#[allow_internal_unstable(fmt_internals)]
#[rustc_builtin_macro]
#[macro_export]
macro_rules! format_args_nl {
- ($fmt:expr) => ({ /* compiler built-in */ });
- ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ })
+ ($fmt:expr) => {{ /* compiler built-in */ }};
+ ($fmt:expr, $($args:tt)*) => {{ /* compiler built-in */ }};
}
/// Inspects an environment variable at compile time.
#[rustc_builtin_macro]
#[macro_export]
macro_rules! env {
- ($name:expr) => ({ /* compiler built-in */ });
- ($name:expr,) => ({ /* compiler built-in */ })
+ ($name:expr) => {{ /* compiler built-in */ }};
+ ($name:expr,) => {{ /* compiler built-in */ }};
}
/// Optionally inspects an environment variable at compile time.
#[rustc_builtin_macro]
#[macro_export]
macro_rules! option_env {
- ($name:expr) => ({ /* compiler built-in */ });
- ($name:expr,) => ({ /* compiler built-in */ })
+ ($name:expr) => {{ /* compiler built-in */ }};
+ ($name:expr,) => {{ /* compiler built-in */ }};
}
/// Concatenates identifiers into one identifier.
/// // fn concat_idents!(new, fun, name) { } // not usable in this way!
/// # }
/// ```
- #[unstable(feature = "concat_idents", issue = "29599",
- reason = "`concat_idents` is not stable enough for use and is subject to change")]
+ #[unstable(
+ feature = "concat_idents",
+ issue = "29599",
+ reason = "`concat_idents` is not stable enough for use and is subject to change"
+ )]
#[rustc_builtin_macro]
#[macro_export]
macro_rules! concat_idents {
- ($($e:ident),+) => ({ /* compiler built-in */ });
- ($($e:ident,)+) => ({ /* compiler built-in */ })
+ ($($e:ident),+) => {{ /* compiler built-in */ }};
+ ($($e:ident,)+) => {{ /* compiler built-in */ }};
}
/// Concatenates literals into a static string slice.
#[rustc_builtin_macro]
#[macro_export]
macro_rules! concat {
- ($($e:expr),*) => ({ /* compiler built-in */ });
- ($($e:expr,)*) => ({ /* compiler built-in */ })
+ ($($e:expr),*) => {{ /* compiler built-in */ }};
+ ($($e:expr,)*) => {{ /* compiler built-in */ }};
}
/// Expands to the line number on which it was invoked.
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_builtin_macro]
#[macro_export]
- macro_rules! line { () => { /* compiler built-in */ } }
+ macro_rules! line {
+ () => {
+ /* compiler built-in */
+ };
+ }
/// Expands to the column number at which it was invoked.
///
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_builtin_macro]
#[macro_export]
- macro_rules! column { () => { /* compiler built-in */ } }
+ macro_rules! column {
+ () => {
+ /* compiler built-in */
+ };
+ }
/// Expands to the file name in which it was invoked.
///
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_builtin_macro]
#[macro_export]
- macro_rules! file { () => { /* compiler built-in */ } }
+ macro_rules! file {
+ () => {
+ /* compiler built-in */
+ };
+ }
/// Stringifies its arguments.
///
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_builtin_macro]
#[macro_export]
- macro_rules! stringify { ($($t:tt)*) => { /* compiler built-in */ } }
+ macro_rules! stringify {
+ ($($t:tt)*) => {
+ /* compiler built-in */
+ };
+ }
/// Includes a utf8-encoded file as a string.
///
#[rustc_builtin_macro]
#[macro_export]
macro_rules! include_str {
- ($file:expr) => ({ /* compiler built-in */ });
- ($file:expr,) => ({ /* compiler built-in */ })
+ ($file:expr) => {{ /* compiler built-in */ }};
+ ($file:expr,) => {{ /* compiler built-in */ }};
}
/// Includes a file as a reference to a byte array.
#[rustc_builtin_macro]
#[macro_export]
macro_rules! include_bytes {
- ($file:expr) => ({ /* compiler built-in */ });
- ($file:expr,) => ({ /* compiler built-in */ })
+ ($file:expr) => {{ /* compiler built-in */ }};
+ ($file:expr,) => {{ /* compiler built-in */ }};
}
/// Expands to a string that represents the current module path.
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_builtin_macro]
#[macro_export]
- macro_rules! module_path { () => { /* compiler built-in */ } }
+ macro_rules! module_path {
+ () => {
+ /* compiler built-in */
+ };
+ }
/// Evaluates boolean combinations of configuration flags at compile-time.
///
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_builtin_macro]
#[macro_export]
- macro_rules! cfg { ($($cfg:tt)*) => { /* compiler built-in */ } }
+ macro_rules! cfg {
+ ($($cfg:tt)*) => {
+ /* compiler built-in */
+ };
+ }
/// Parses a file as an expression or an item according to the context.
///
#[rustc_builtin_macro]
#[macro_export]
macro_rules! include {
- ($file:expr) => ({ /* compiler built-in */ });
- ($file:expr,) => ({ /* compiler built-in */ })
+ ($file:expr) => {{ /* compiler built-in */ }};
+ ($file:expr,) => {{ /* compiler built-in */ }};
}
/// Asserts that a boolean expression is `true` at runtime.
#[rustc_builtin_macro]
#[macro_export]
macro_rules! assert {
- ($cond:expr) => ({ /* compiler built-in */ });
- ($cond:expr,) => ({ /* compiler built-in */ });
- ($cond:expr, $($arg:tt)+) => ({ /* compiler built-in */ })
+ ($cond:expr) => {{ /* compiler built-in */ }};
+ ($cond:expr,) => {{ /* compiler built-in */ }};
+ ($cond:expr, $($arg:tt)+) => {{ /* compiler built-in */ }};
}
/// Inline assembly.
/// Read the [unstable book] for the usage.
///
/// [unstable book]: ../unstable-book/library-features/asm.html
- #[unstable(feature = "asm", issue = "29722",
- reason = "inline assembly is not stable enough for use and is subject to change")]
+ #[unstable(
+ feature = "asm",
+ issue = "29722",
+ reason = "inline assembly is not stable enough for use and is subject to change"
+ )]
#[rustc_builtin_macro]
#[macro_export]
- macro_rules! asm { ("assembly template"
+ macro_rules! asm {
+ ("assembly template"
: $("output"(operand),)*
: $("input"(operand),)*
: $("clobbers",)*
- : $("options",)*) => { /* compiler built-in */ } }
+ : $("options",)*) => {
+ /* compiler built-in */
+ };
+ }
/// Module-level inline assembly.
- #[unstable(feature = "global_asm", issue = "35119",
- reason = "`global_asm!` is not stable enough for use and is subject to change")]
+ #[unstable(
+ feature = "global_asm",
+ issue = "35119",
+ reason = "`global_asm!` is not stable enough for use and is subject to change"
+ )]
#[rustc_builtin_macro]
#[macro_export]
- macro_rules! global_asm { ("assembly") => { /* compiler built-in */ } }
+ macro_rules! global_asm {
+ ("assembly") => {
+ /* compiler built-in */
+ };
+ }
/// Prints passed tokens into the standard output.
- #[unstable(feature = "log_syntax", issue = "29598",
- reason = "`log_syntax!` is not stable enough for use and is subject to change")]
+ #[unstable(
+ feature = "log_syntax",
+ issue = "29598",
+ reason = "`log_syntax!` is not stable enough for use and is subject to change"
+ )]
#[rustc_builtin_macro]
#[macro_export]
- macro_rules! log_syntax { ($($arg:tt)*) => { /* compiler built-in */ } }
+ macro_rules! log_syntax {
+ ($($arg:tt)*) => {
+ /* compiler built-in */
+ };
+ }
/// Enables or disables tracing functionality used for debugging other macros.
- #[unstable(feature = "trace_macros", issue = "29598",
- reason = "`trace_macros` is not stable enough for use and is subject to change")]
+ #[unstable(
+ feature = "trace_macros",
+ issue = "29598",
+ reason = "`trace_macros` is not stable enough for use and is subject to change"
+ )]
#[rustc_builtin_macro]
#[macro_export]
macro_rules! trace_macros {
- (true) => ({ /* compiler built-in */ });
- (false) => ({ /* compiler built-in */ })
+ (true) => {{ /* compiler built-in */ }};
+ (false) => {{ /* compiler built-in */ }};
}
/// Attribute macro applied to a function to turn it into a unit test.
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable(test, rustc_attrs)]
#[rustc_builtin_macro]
- pub macro test($item:item) { /* compiler built-in */ }
+ pub macro test($item:item) {
+ /* compiler built-in */
+ }
/// Attribute macro applied to a function to turn it into a benchmark test.
- #[unstable(soft, feature = "test", issue = "50297",
- reason = "`bench` is a part of custom test frameworks which are unstable")]
+ #[unstable(
+ feature = "test",
+ issue = "50297",
+ soft,
+ reason = "`bench` is a part of custom test frameworks which are unstable"
+ )]
#[allow_internal_unstable(test, rustc_attrs)]
#[rustc_builtin_macro]
- pub macro bench($item:item) { /* compiler built-in */ }
+ pub macro bench($item:item) {
+ /* compiler built-in */
+ }
/// An implementation detail of the `#[test]` and `#[bench]` macros.
- #[unstable(feature = "custom_test_frameworks", issue = "50297",
- reason = "custom test frameworks are an unstable feature")]
+ #[unstable(
+ feature = "custom_test_frameworks",
+ issue = "50297",
+ reason = "custom test frameworks are an unstable feature"
+ )]
#[allow_internal_unstable(test, rustc_attrs)]
#[rustc_builtin_macro]
- pub macro test_case($item:item) { /* compiler built-in */ }
+ pub macro test_case($item:item) {
+ /* compiler built-in */
+ }
/// Attribute macro applied to a static to register it as a global allocator.
#[stable(feature = "global_allocator", since = "1.28.0")]
#[allow_internal_unstable(rustc_attrs)]
#[rustc_builtin_macro]
- pub macro global_allocator($item:item) { /* compiler built-in */ }
+ pub macro global_allocator($item:item) {
+ /* compiler built-in */
+ }
/// Unstable implementation detail of the `rustc` compiler, do not use.
#[rustc_builtin_macro]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable(core_intrinsics, libstd_sys_internals)]
- pub macro RustcDecodable($item:item) { /* compiler built-in */ }
+ pub macro RustcDecodable($item:item) {
+ /* compiler built-in */
+ }
/// Unstable implementation detail of the `rustc` compiler, do not use.
#[rustc_builtin_macro]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable(core_intrinsics)]
- pub macro RustcEncodable($item:item) { /* compiler built-in */ }
+ pub macro RustcEncodable($item:item) {
+ /* compiler built-in */
+ }
}
-use crate::ptr;
use crate::ops::{Deref, DerefMut};
+use crate::ptr;
/// A wrapper to inhibit compiler from automatically calling `T`’s destructor.
///
// This module is only for dec2flt and flt2dec, and only public because of coretests.
// It is not intended to ever be stabilized.
#![doc(hidden)]
-#![unstable(feature = "core_private_bignum",
- reason = "internal routines only exposed for testing",
- issue = "0")]
+#![unstable(
+ feature = "core_private_bignum",
+ reason = "internal routines only exposed for testing",
+ issue = "0"
+)]
#![macro_use]
-use crate::mem;
use crate::intrinsics;
+use crate::mem;
/// Arithmetic operations required by bignums.
pub trait FullOps: Sized {
/// Returns `(quo, rem)` such that `borrow * 2^W + self = quo * other + rem`
/// and `0 <= rem < other`, where `W` is the number of bits in `Self`.
- fn full_div_rem(self,
- other: Self,
- borrow: Self)
- -> (Self /* quotient */, Self /* remainder */);
+ fn full_div_rem(self, other: Self, borrow: Self)
+ -> (Self /* quotient */, Self /* remainder */);
}
macro_rules! impl_full_ops {
const SMALL_POW5: [(u64, usize); 3] = [(125, 3), (15625, 6), (1_220_703_125, 13)];
macro_rules! define_bignum {
- ($name:ident: type=$ty:ty, n=$n:expr) => (
+ ($name:ident: type=$ty:ty, n=$n:expr) => {
/// Stack-allocated arbitrary-precision (up to certain limit) integer.
///
/// This is backed by a fixed-size array of given type ("digit").
size: usize,
/// Digits. `[a, b, c, ...]` represents `a + b*2^W + c*2^(2W) + ...`
/// where `W` is the number of bits in the digit type.
- base: [$ty; $n]
+ base: [$ty; $n],
}
impl $name {
}
// This could be optimized with leading_zeros() and bit shifts, but that's
// probably not worth the hassle.
- let digitbits = mem::size_of::<$ty>()* 8;
+ let digitbits = mem::size_of::<$ty>() * 8;
let mut i = nonzero.len() * digitbits - 1;
while self.get_bit(i) == 0 {
i -= 1;
let bits = bits % digitbits;
assert!(digits < $n);
- debug_assert!(self.base[$n-digits..].iter().all(|&v| v == 0));
- debug_assert!(bits == 0 || (self.base[$n-digits-1] >> (digitbits - bits)) == 0);
+ debug_assert!(self.base[$n - digits..].iter().all(|&v| v == 0));
+ debug_assert!(bits == 0 || (self.base[$n - digits - 1] >> (digitbits - bits)) == 0);
// shift by `digits * digitbits` bits
for i in (0..self.size).rev() {
- self.base[i+digits] = self.base[i];
+ self.base[i + digits] = self.base[i];
}
for i in 0..digits {
self.base[i] = 0;
let mut sz = self.size + digits;
if bits > 0 {
let last = sz;
- let overflow = self.base[last-1] >> (digitbits - bits);
+ let overflow = self.base[last - 1] >> (digitbits - bits);
if overflow > 0 {
self.base[last] = overflow;
sz += 1;
}
- for i in (digits+1..last).rev() {
- self.base[i] = (self.base[i] << bits) |
- (self.base[i-1] >> (digitbits - bits));
+ for i in (digits + 1..last).rev() {
+ self.base[i] =
+ (self.base[i] << bits) | (self.base[i - 1] >> (digitbits - bits));
}
self.base[digits] <<= bits;
// self.base[..digits] is zero, no need to shift
self
}
-
/// Multiplies itself by a number described by `other[0] + other[1] * 2^W +
/// other[2] * 2^(2W) + ...` (where `W` is the number of bits in the digit type)
/// and returns its own mutable reference.
let mut retsz = 0;
for (i, &a) in aa.iter().enumerate() {
- if a == 0 { continue; }
+ if a == 0 {
+ continue;
+ }
let mut sz = bb.len();
let mut carry = 0;
for (j, &b) in bb.iter().enumerate() {
}
impl crate::cmp::PartialEq for $name {
- fn eq(&self, other: &$name) -> bool { self.base[..] == other.base[..] }
+ fn eq(&self, other: &$name) -> bool {
+ self.base[..] == other.base[..]
+ }
}
- impl crate::cmp::Eq for $name {
- }
+ impl crate::cmp::Eq for $name {}
impl crate::cmp::PartialOrd for $name {
fn partial_cmp(&self, other: &$name) -> crate::option::Option<crate::cmp::Ordering> {
fn fmt(&self, f: &mut crate::fmt::Formatter<'_>) -> crate::fmt::Result {
use crate::mem;
- let sz = if self.size < 1 {1} else {self.size};
+ let sz = if self.size < 1 { 1 } else { self.size };
let digitlen = mem::size_of::<$ty>() * 2;
- write!(f, "{:#x}", self.base[sz-1])?;
- for &v in self.base[..sz-1].iter().rev() {
+ write!(f, "{:#x}", self.base[sz - 1])?;
+ for &v in self.base[..sz - 1].iter().rev() {
write!(f, "_{:01$x}", v, digitlen)?;
}
crate::result::Result::Ok(())
}
}
- )
+ };
}
/// The digit type for `Big32x40`.
//! The various algorithms from the paper.
use crate::cmp::min;
-use crate::cmp::Ordering::{Less, Equal, Greater};
-use crate::num::diy_float::Fp;
-use crate::num::dec2flt::table;
-use crate::num::dec2flt::rawfp::{self, Unpacked, RawFloat, fp_to_float, next_float, prev_float};
+use crate::cmp::Ordering::{Equal, Greater, Less};
use crate::num::dec2flt::num::{self, Big};
+use crate::num::dec2flt::rawfp::{self, fp_to_float, next_float, prev_float, RawFloat, Unpacked};
+use crate::num::dec2flt::table;
+use crate::num::diy_float::Fp;
/// Number of significand bits in Fp
const P: u32 = 64;
// In most architectures, floating point operations have an explicit bit size, therefore the
// precision of the computation is determined on a per-operation basis.
-#[cfg(any(not(target_arch="x86"), target_feature="sse2"))]
+#[cfg(any(not(target_arch = "x86"), target_feature = "sse2"))]
mod fpu_precision {
- pub fn set_precision<T>() { }
+ pub fn set_precision<T>() {}
}
// On x86, the x87 FPU is used for float operations if the SSE/SSE2 extensions are not available.
// round to 80 bits causing double rounding to happen when values are eventually represented as
// 32/64 bit float values. To overcome this, the FPU control word can be set so that the
// computations are performed in the desired precision.
-#[cfg(all(target_arch="x86", not(target_feature="sse2")))]
+#[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]
mod fpu_precision {
use crate::mem::size_of;
//! turned into {positive,negative} {zero,infinity}.
#![doc(hidden)]
-#![unstable(feature = "dec2flt",
- reason = "internal routines only exposed for testing",
- issue = "0")]
+#![unstable(
+ feature = "dec2flt",
+ reason = "internal routines only exposed for testing",
+ issue = "0"
+)]
use crate::fmt;
use crate::str::FromStr;
-use self::parse::{parse_decimal, Decimal, Sign, ParseResult};
use self::num::digits_to_big;
+use self::parse::{parse_decimal, Decimal, ParseResult, Sign};
use self::rawfp::RawFloat;
mod algorithm;
-mod table;
mod num;
+mod table;
// These two have their own tests.
-pub mod rawfp;
pub mod parse;
+pub mod rawfp;
macro_rules! from_str_float_impl {
($t:ty) => {
dec2flt(src)
}
}
- }
+ };
}
from_str_float_impl!(f32);
from_str_float_impl!(f64);
#[derive(Debug, Clone, PartialEq, Eq)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct ParseFloatError {
- kind: FloatErrorKind
+ kind: FloatErrorKind,
}
#[derive(Debug, Clone, PartialEq, Eq)]
}
impl ParseFloatError {
- #[unstable(feature = "int_error_internals",
- reason = "available through Error trait and this method should \
- not be exposed publicly",
- issue = "0")]
+ #[unstable(
+ feature = "int_error_internals",
+ reason = "available through Error trait and this method should \
+ not be exposed publicly",
+ issue = "0"
+ )]
#[doc(hidden)]
pub fn __description(&self) -> &str {
match self.kind {
/// Converts a decimal string into a floating point number.
fn dec2flt<T: RawFloat>(s: &str) -> Result<T, ParseFloatError> {
if s.is_empty() {
- return Err(pfe_empty())
+ return Err(pfe_empty());
}
let (sign, s) = extract_sign(s);
let flt = match parse_decimal(s) {
ParseResult::Invalid => match s {
"inf" => T::INFINITY,
"NaN" => T::NAN,
- _ => { return Err(pfe_invalid()); }
- }
+ _ => {
+ return Err(pfe_invalid());
+ }
+ },
};
match sign {
// FIXME This module's name is a bit unfortunate, since other modules also import `core::num`.
-use crate::cmp::Ordering::{self, Less, Equal, Greater};
+use crate::cmp::Ordering::{self, Equal, Greater, Less};
pub use crate::num::bignum::Big32x40 as Big;
/// 1. using `FromStr` on `&[u8]` requires `from_utf8_unchecked`, which is bad, and
/// 2. piecing together the results of `integral.parse()` and `fractional.parse()` is
/// more complicated than this entire function.
-pub fn from_str_unchecked<'a, T>(bytes: T) -> u64 where T : IntoIterator<Item=&'a u8> {
+pub fn from_str_unchecked<'a, T>(bytes: T) -> u64
+where
+ T: IntoIterator<Item = &'a u8>,
+{
let mut result = 0;
for &c in bytes {
result = result * 10 + (c - b'0') as u64;
pub fn to_u64(x: &Big) -> u64 {
assert!(x.bit_length() < 64);
let d = x.digits();
- if d.len() < 2 {
- d[0] as u64
- } else {
- (d[1] as u64) << 32 | d[0] as u64
- }
+ if d.len() < 2 { d[0] as u64 } else { (d[1] as u64) << 32 | d[0] as u64 }
}
-
/// Extracts a range of bits.
/// Index 0 is the least significant bit and the range is half-open as usual.
//! modules rely on to not panic (or overflow) in turn.
//! To make matters worse, all that happens in a single pass over the input.
//! So, be careful when modifying anything, and double-check with the other modules.
+use self::ParseResult::{Invalid, ShortcutToInf, ShortcutToZero, Valid};
use super::num;
-use self::ParseResult::{Valid, ShortcutToInf, ShortcutToZero, Invalid};
#[derive(Debug)]
pub enum Sign {
//! Many functions in this module only handle normal numbers. The dec2flt routines conservatively
//! take the universally-correct slow path (Algorithm M) for very small and very large numbers.
//! That algorithm needs only next_float() which does handle subnormals and zeros.
-use crate::cmp::Ordering::{Less, Equal, Greater};
+use crate::cmp::Ordering::{Equal, Greater, Less};
use crate::convert::{TryFrom, TryInto};
-use crate::ops::{Add, Mul, Div, Neg};
use crate::fmt::{Debug, LowerExp};
-use crate::num::diy_float::Fp;
-use crate::num::FpCategory::{Infinite, Zero, Subnormal, Normal, Nan};
-use crate::num::FpCategory;
use crate::num::dec2flt::num::{self, Big};
use crate::num::dec2flt::table;
+use crate::num::diy_float::Fp;
+use crate::num::FpCategory;
+use crate::num::FpCategory::{Infinite, Nan, Normal, Subnormal, Zero};
+use crate::ops::{Add, Div, Mul, Neg};
#[derive(Copy, Clone, Debug)]
pub struct Unpacked {
/// See the parent module's doc comment for why this is necessary.
///
/// Should **never ever** be implemented for other types or be used outside the dec2flt module.
-pub trait RawFloat
- : Copy
- + Debug
- + LowerExp
- + Mul<Output=Self>
- + Div<Output=Self>
- + Neg<Output=Self>
+pub trait RawFloat:
+ Copy + Debug + LowerExp + Mul<Output = Self> + Div<Output = Self> + Neg<Output = Self>
{
const INFINITY: Self;
const NAN: Self;
const INFINITY: Self = $crate::$type::INFINITY;
const NAN: Self = $crate::$type::NAN;
const ZERO: Self = 0.0;
- }
+ };
}
impl RawFloat for f32 {
let bits = self.to_bits();
let sign: i8 = if bits >> 31 == 0 { 1 } else { -1 };
let mut exponent: i16 = ((bits >> 23) & 0xff) as i16;
- let mantissa = if exponent == 0 {
- (bits & 0x7fffff) << 1
- } else {
- (bits & 0x7fffff) | 0x800000
- };
+ let mantissa =
+ if exponent == 0 { (bits & 0x7fffff) << 1 } else { (bits & 0x7fffff) | 0x800000 };
// Exponent bias + mantissa shift
exponent -= 127 + 23;
(mantissa as u64, exponent, sign)
table::F32_SHORT_POWERS[e]
}
- fn classify(self) -> FpCategory { self.classify() }
- fn to_bits(self) -> Self::Bits { self.to_bits() }
- fn from_bits(v: Self::Bits) -> Self { Self::from_bits(v) }
+ fn classify(self) -> FpCategory {
+ self.classify()
+ }
+ fn to_bits(self) -> Self::Bits {
+ self.to_bits()
+ }
+ fn from_bits(v: Self::Bits) -> Self {
+ Self::from_bits(v)
+ }
}
-
impl RawFloat for f64 {
type Bits = u64;
table::F64_SHORT_POWERS[e]
}
- fn classify(self) -> FpCategory { self.classify() }
- fn to_bits(self) -> Self::Bits { self.to_bits() }
- fn from_bits(v: Self::Bits) -> Self { Self::from_bits(v) }
+ fn classify(self) -> FpCategory {
+ self.classify()
+ }
+ fn to_bits(self) -> Self::Bits {
+ self.to_bits()
+ }
+ fn from_bits(v: Self::Bits) -> Self {
+ Self::from_bits(v)
+ }
}
/// Converts an `Fp` to the closest machine float type.
let e = x.e + 63;
if e > T::MAX_EXP {
panic!("fp_to_float: exponent {} too large", e)
- } else if e > T::MIN_EXP {
+ } else if e > T::MIN_EXP {
encode_normal(round_normal::<T>(x))
} else {
panic!("fp_to_float: exponent {} too small", e)
/// Inverse of `RawFloat::unpack()` for normalized numbers.
/// Panics if the significand or exponent are not valid for normalized numbers.
pub fn encode_normal<T: RawFloat>(x: Unpacked) -> T {
- debug_assert!(T::MIN_SIG <= x.sig && x.sig <= T::MAX_SIG,
- "encode_normal: significand not normalized");
+ debug_assert!(
+ T::MIN_SIG <= x.sig && x.sig <= T::MAX_SIG,
+ "encode_normal: significand not normalized"
+ );
// Remove the hidden bit
let sig_enc = x.sig & !(1 << T::EXPLICIT_SIG_BITS);
// Adjust the exponent for exponent bias and mantissa shift
let k_enc = x.k + T::MAX_EXP + T::EXPLICIT_SIG_BITS as i16;
- debug_assert!(k_enc != 0 && k_enc < T::MAX_ENCODED_EXP,
- "encode_normal: exponent out of range");
+ debug_assert!(k_enc != 0 && k_enc < T::MAX_ENCODED_EXP, "encode_normal: exponent out of range");
// Leave sign bit at 0 ("+"), our numbers are all positive
let bits = (k_enc as u64) << T::EXPLICIT_SIG_BITS | sig_enc;
T::from_bits(bits.try_into().unwrap_or_else(|_| unreachable!()))
Equal | Greater => match leading.checked_add(1) {
Some(f) => Fp { f, e }.normalize(),
None => Fp { f: 1 << 63, e: e + 1 },
- }
+ },
}
}
// want, and the mantissa bits become zero. Because of the hidden bit convention, this
// too is exactly what we want!
// Finally, f64::MAX + 1 = 7eff...f + 1 = 7ff0...0 = f64::INFINITY.
- Zero | Subnormal | Normal => {
- T::from_bits(x.to_bits() + T::Bits::from(1u8))
- }
+ Zero | Subnormal | Normal => T::from_bits(x.to_bits() + T::Bits::from(1u8)),
}
}
// This module is only for dec2flt and flt2dec, and only public because of coretests.
// It is not intended to ever be stabilized.
#![doc(hidden)]
-#![unstable(feature = "core_private_diy_float",
- reason = "internal routines only exposed for testing",
- issue = "0")]
+#![unstable(
+ feature = "core_private_diy_float",
+ reason = "internal routines only exposed for testing",
+ issue = "0"
+)]
/// A custom 64-bit floating point type, representing `f * 2^e`.
#[derive(Copy, Clone, Debug)]
assert!(edelta >= 0);
let edelta = edelta as usize;
assert_eq!(self.f << edelta >> edelta, self.f);
- Fp {
- f: self.f << edelta,
- e,
- }
+ Fp { f: self.f << edelta, e }
}
}
#[stable(feature = "rust1", since = "1.0.0")]
pub const PI: f32 = 3.14159265358979323846264338327950288_f32;
+ /// The full circle constant (τ)
+ ///
+ /// Equal to 2π.
+ #[unstable(feature = "tau_constant", issue = "66770")]
+ pub const TAU: f32 = 6.28318530717958647692528676655900577_f32;
+
/// π/2
#[stable(feature = "rust1", since = "1.0.0")]
pub const FRAC_PI_2: f32 = 1.57079632679489661923132169163975144_f32;
#[stable(feature = "rust1", since = "1.0.0")]
pub const PI: f64 = 3.14159265358979323846264338327950288_f64;
+ /// The full circle constant (τ)
+ ///
+ /// Equal to 2π.
+ #[unstable(feature = "tau_constant", issue = "66770")]
+ pub const TAU: f64 = 6.28318530717958647692528676655900577_f64;
+
/// π/2
#[stable(feature = "rust1", since = "1.0.0")]
pub const FRAC_PI_2: f64 = 1.57079632679489661923132169163975144_f64;
//! Decodes a floating-point value into individual parts and error ranges.
-use crate::{f32, f64};
-use crate::num::FpCategory;
use crate::num::dec2flt::rawfp::RawFloat;
+use crate::num::FpCategory;
+use crate::{f32, f64};
/// Decoded unsigned finite value, such that:
///
}
impl DecodableFloat for f32 {
- fn min_pos_norm_value() -> Self { f32::MIN_POSITIVE }
+ fn min_pos_norm_value() -> Self {
+ f32::MIN_POSITIVE
+ }
}
impl DecodableFloat for f64 {
- fn min_pos_norm_value() -> Self { f64::MIN_POSITIVE }
+ fn min_pos_norm_value() -> Self {
+ f64::MIN_POSITIVE
+ }
}
/// Returns a sign (true when negative) and `FullDecoded` value
// neighbors: (mant - 2, exp) -- (mant, exp) -- (mant + 2, exp)
// Float::integer_decode always preserves the exponent,
// so the mantissa is scaled for subnormals.
- FullDecoded::Finite(Decoded { mant, minus: 1, plus: 1,
- exp, inclusive: even })
+ FullDecoded::Finite(Decoded { mant, minus: 1, plus: 1, exp, inclusive: even })
}
FpCategory::Normal => {
let minnorm = <T as DecodableFloat>::min_pos_norm_value().integer_decode();
if mant == minnorm.0 {
// neighbors: (maxmant, exp - 1) -- (minnormmant, exp) -- (minnormmant + 1, exp)
// where maxmant = minnormmant * 2 - 1
- FullDecoded::Finite(Decoded { mant: mant << 2, minus: 1, plus: 2,
- exp: exp - 2, inclusive: even })
+ FullDecoded::Finite(Decoded {
+ mant: mant << 2,
+ minus: 1,
+ plus: 2,
+ exp: exp - 2,
+ inclusive: even,
+ })
} else {
// neighbors: (mant - 1, exp) -- (mant, exp) -- (mant + 1, exp)
- FullDecoded::Finite(Decoded { mant: mant << 1, minus: 1, plus: 1,
- exp: exp - 1, inclusive: even })
+ FullDecoded::Finite(Decoded {
+ mant: mant << 1,
+ minus: 1,
+ plus: 1,
+ exp: exp - 1,
+ inclusive: even,
+ })
}
}
};
// while this is extensively documented, this is in principle private which is
// only made public for testing. do not expose us.
#![doc(hidden)]
-#![unstable(feature = "flt2dec",
- reason = "internal routines only exposed for testing",
- issue = "0")]
+#![unstable(
+ feature = "flt2dec",
+ reason = "internal routines only exposed for testing",
+ issue = "0"
+)]
+pub use self::decoder::{decode, DecodableFloat, Decoded, FullDecoded};
use crate::i16;
-pub use self::decoder::{decode, DecodableFloat, FullDecoded, Decoded};
-pub mod estimator;
pub mod decoder;
+pub mod estimator;
/// Digit-generation algorithms.
pub mod strategy {
#[doc(hidden)]
pub fn round_up(d: &mut [u8], n: usize) -> Option<u8> {
match d[..n].iter().rposition(|&c| c != b'9') {
- Some(i) => { // d[i+1..n] is all nines
+ Some(i) => {
+ // d[i+1..n] is all nines
d[i] += 1;
- for j in i+1..n { d[j] = b'0'; }
+ for j in i + 1..n {
+ d[j] = b'0';
+ }
None
}
- None if n > 0 => { // 999..999 rounds to 1000..000 with an increased exponent
+ None if n > 0 => {
+ // 999..999 rounds to 1000..000 with an increased exponent
d[0] = b'1';
- for j in 1..n { d[j] = b'0'; }
+ for j in 1..n {
+ d[j] = b'0';
+ }
Some(b'0')
}
- None => { // an empty buffer rounds up (a bit strange but reasonable)
+ None => {
+ // an empty buffer rounds up (a bit strange but reasonable)
Some(b'1')
}
}
pub fn len(&self) -> usize {
match *self {
Part::Zero(nzeroes) => nzeroes,
- Part::Num(v) => if v < 1_000 { if v < 10 { 1 } else if v < 100 { 2 } else { 3 } }
- else { if v < 10_000 { 4 } else { 5 } },
+ Part::Num(v) => {
+ if v < 1_000 {
+ if v < 10 {
+ 1
+ } else if v < 100 {
+ 2
+ } else {
+ 3
+ }
+ } else {
+ if v < 10_000 { 4 } else { 5 }
+ }
+ }
Part::Copy(buf) => buf.len(),
}
}
if out.len() >= len {
match *self {
Part::Zero(nzeroes) => {
- for c in &mut out[..nzeroes] { *c = b'0'; }
+ for c in &mut out[..nzeroes] {
+ *c = b'0';
+ }
}
Part::Num(mut v) => {
for c in out[..len].iter_mut().rev() {
/// Returns the number of written bytes, or `None` if the buffer is not enough.
/// (It may still leave partially written bytes in the buffer; do not rely on that.)
pub fn write(&self, out: &mut [u8]) -> Option<usize> {
- if out.len() < self.sign.len() { return None; }
+ if out.len() < self.sign.len() {
+ return None;
+ }
out[..self.sign.len()].copy_from_slice(self.sign);
let mut written = self.sign.len();
/// it will be ignored and full digits will be printed. It is only used to print
/// additional zeroes after rendered digits. Thus `frac_digits` of 0 means that
/// it will only print given digits and nothing else.
-fn digits_to_dec_str<'a>(buf: &'a [u8], exp: i16, frac_digits: usize,
- parts: &'a mut [Part<'a>]) -> &'a [Part<'a>] {
+fn digits_to_dec_str<'a>(
+ buf: &'a [u8],
+ exp: i16,
+ frac_digits: usize,
+ parts: &'a mut [Part<'a>],
+) -> &'a [Part<'a>] {
assert!(!buf.is_empty());
assert!(buf[0] > b'0');
assert!(parts.len() >= 4);
/// it will be ignored and full digits will be printed. It is only used to print
/// additional zeroes after rendered digits. Thus, `min_digits == 0` means that
/// it will only print the given digits and nothing else.
-fn digits_to_exp_str<'a>(buf: &'a [u8], exp: i16, min_ndigits: usize, upper: bool,
- parts: &'a mut [Part<'a>]) -> &'a [Part<'a>] {
+fn digits_to_exp_str<'a>(
+ buf: &'a [u8],
+ exp: i16,
+ min_ndigits: usize,
+ upper: bool,
+ parts: &'a mut [Part<'a>],
+) -> &'a [Part<'a>] {
assert!(!buf.is_empty());
assert!(buf[0] > b'0');
assert!(parts.len() >= 6);
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum Sign {
/// Prints `-` only for the negative non-zero values.
- Minus, // -inf -1 0 0 1 inf nan
+ Minus, // -inf -1 0 0 1 inf nan
/// Prints `-` only for any negative values (including the negative zero).
- MinusRaw, // -inf -1 -0 0 1 inf nan
+ MinusRaw, // -inf -1 -0 0 1 inf nan
/// Prints `-` for the negative non-zero values, or `+` otherwise.
- MinusPlus, // -inf -1 +0 +0 +1 +inf nan
+ MinusPlus, // -inf -1 +0 +0 +1 +inf nan
/// Prints `-` for any negative values (including the negative zero), or `+` otherwise.
MinusPlusRaw, // -inf -1 -0 +0 +1 +inf nan
}
match (*decoded, sign) {
(FullDecoded::Nan, _) => b"",
(FullDecoded::Zero, Sign::Minus) => b"",
- (FullDecoded::Zero, Sign::MinusRaw) => if negative { b"-" } else { b"" },
+ (FullDecoded::Zero, Sign::MinusRaw) => {
+ if negative {
+ b"-"
+ } else {
+ b""
+ }
+ }
(FullDecoded::Zero, Sign::MinusPlus) => b"+",
- (FullDecoded::Zero, Sign::MinusPlusRaw) => if negative { b"-" } else { b"+" },
- (_, Sign::Minus) | (_, Sign::MinusRaw) => if negative { b"-" } else { b"" },
- (_, Sign::MinusPlus) | (_, Sign::MinusPlusRaw) => if negative { b"-" } else { b"+" },
+ (FullDecoded::Zero, Sign::MinusPlusRaw) => {
+ if negative {
+ b"-"
+ } else {
+ b"+"
+ }
+ }
+ (_, Sign::Minus) | (_, Sign::MinusRaw) => {
+ if negative {
+ b"-"
+ } else {
+ b""
+ }
+ }
+ (_, Sign::MinusPlus) | (_, Sign::MinusPlusRaw) => {
+ if negative {
+ b"-"
+ } else {
+ b"+"
+ }
+ }
}
}
/// The byte buffer should be at least `MAX_SIG_DIGITS` bytes long.
/// There should be at least 4 parts available, due to the worst case like
/// `[+][0.][0000][2][0000]` with `frac_digits = 10`.
-pub fn to_shortest_str<'a, T, F>(mut format_shortest: F, v: T,
- sign: Sign, frac_digits: usize, _upper: bool,
- buf: &'a mut [u8], parts: &'a mut [Part<'a>]) -> Formatted<'a>
- where T: DecodableFloat, F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
+pub fn to_shortest_str<'a, T, F>(
+ mut format_shortest: F,
+ v: T,
+ sign: Sign,
+ frac_digits: usize,
+ _upper: bool,
+ buf: &'a mut [u8],
+ parts: &'a mut [Part<'a>],
+) -> Formatted<'a>
+where
+ T: DecodableFloat,
+ F: FnMut(&Decoded, &mut [u8]) -> (usize, i16),
+{
assert!(parts.len() >= 4);
assert!(buf.len() >= MAX_SIG_DIGITS);
Formatted { sign, parts: &parts[..1] }
}
FullDecoded::Zero => {
- if frac_digits > 0 { // [0.][0000]
+ if frac_digits > 0 {
+ // [0.][0000]
parts[0] = Part::Copy(b"0.");
parts[1] = Part::Zero(frac_digits);
Formatted { sign, parts: &parts[..2] }
}
FullDecoded::Finite(ref decoded) => {
let (len, exp) = format_shortest(decoded, buf);
- Formatted { sign,
- parts: digits_to_dec_str(&buf[..len], exp, frac_digits, parts) }
+ Formatted { sign, parts: digits_to_dec_str(&buf[..len], exp, frac_digits, parts) }
}
}
}
/// The byte buffer should be at least `MAX_SIG_DIGITS` bytes long.
/// There should be at least 6 parts available, due to the worst case like
/// `[+][1][.][2345][e][-][6]`.
-pub fn to_shortest_exp_str<'a, T, F>(mut format_shortest: F, v: T,
- sign: Sign, dec_bounds: (i16, i16), upper: bool,
- buf: &'a mut [u8], parts: &'a mut [Part<'a>]) -> Formatted<'a>
- where T: DecodableFloat, F: FnMut(&Decoded, &mut [u8]) -> (usize, i16) {
+pub fn to_shortest_exp_str<'a, T, F>(
+ mut format_shortest: F,
+ v: T,
+ sign: Sign,
+ dec_bounds: (i16, i16),
+ upper: bool,
+ buf: &'a mut [u8],
+ parts: &'a mut [Part<'a>],
+) -> Formatted<'a>
+where
+ T: DecodableFloat,
+ F: FnMut(&Decoded, &mut [u8]) -> (usize, i16),
+{
assert!(parts.len() >= 6);
assert!(buf.len() >= MAX_SIG_DIGITS);
assert!(dec_bounds.0 <= dec_bounds.1);
/// (The tipping point for `f64` is about 800, so 1000 bytes should be enough.)
/// There should be at least 6 parts available, due to the worst case like
/// `[+][1][.][2345][e][-][6]`.
-pub fn to_exact_exp_str<'a, T, F>(mut format_exact: F, v: T,
- sign: Sign, ndigits: usize, upper: bool,
- buf: &'a mut [u8], parts: &'a mut [Part<'a>]) -> Formatted<'a>
- where T: DecodableFloat, F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) {
+pub fn to_exact_exp_str<'a, T, F>(
+ mut format_exact: F,
+ v: T,
+ sign: Sign,
+ ndigits: usize,
+ upper: bool,
+ buf: &'a mut [u8],
+ parts: &'a mut [Part<'a>],
+) -> Formatted<'a>
+where
+ T: DecodableFloat,
+ F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16),
+{
assert!(parts.len() >= 6);
assert!(ndigits > 0);
Formatted { sign, parts: &parts[..1] }
}
FullDecoded::Zero => {
- if ndigits > 1 { // [0.][0000][e0]
+ if ndigits > 1 {
+ // [0.][0000][e0]
parts[0] = Part::Copy(b"0.");
parts[1] = Part::Zero(ndigits - 1);
parts[2] = Part::Copy(if upper { b"E0" } else { b"e0" });
let trunc = if ndigits < maxlen { ndigits } else { maxlen };
let (len, exp) = format_exact(decoded, &mut buf[..trunc], i16::MIN);
- Formatted { sign,
- parts: digits_to_exp_str(&buf[..len], exp, ndigits, upper, parts) }
+ Formatted { sign, parts: digits_to_exp_str(&buf[..len], exp, ndigits, upper, parts) }
}
}
}
/// (The tipping point for `f64` is about 800, and 1000 bytes should be enough.)
/// There should be at least 4 parts available, due to the worst case like
/// `[+][0.][0000][2][0000]` with `frac_digits = 10`.
-pub fn to_exact_fixed_str<'a, T, F>(mut format_exact: F, v: T,
- sign: Sign, frac_digits: usize, _upper: bool,
- buf: &'a mut [u8], parts: &'a mut [Part<'a>]) -> Formatted<'a>
- where T: DecodableFloat, F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16) {
+pub fn to_exact_fixed_str<'a, T, F>(
+ mut format_exact: F,
+ v: T,
+ sign: Sign,
+ frac_digits: usize,
+ _upper: bool,
+ buf: &'a mut [u8],
+ parts: &'a mut [Part<'a>],
+) -> Formatted<'a>
+where
+ T: DecodableFloat,
+ F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16),
+{
assert!(parts.len() >= 4);
let (negative, full_decoded) = decode(v);
Formatted { sign, parts: &parts[..1] }
}
FullDecoded::Zero => {
- if frac_digits > 0 { // [0.][0000]
+ if frac_digits > 0 {
+ // [0.][0000]
parts[0] = Part::Copy(b"0.");
parts[1] = Part::Zero(frac_digits);
Formatted { sign, parts: &parts[..2] }
// `exp` was. this does not include the case that the restriction has been met
// only after the final rounding-up; it's a regular case with `exp = limit + 1`.
debug_assert_eq!(len, 0);
- if frac_digits > 0 { // [0.][0000]
+ if frac_digits > 0 {
+ // [0.][0000]
parts[0] = Part::Copy(b"0.");
parts[1] = Part::Zero(frac_digits);
Formatted { sign, parts: &parts[..2] }
Formatted { sign, parts: &parts[..1] }
}
} else {
- Formatted { sign,
- parts: digits_to_dec_str(&buf[..len], exp, frac_digits, parts) }
+ Formatted { sign, parts: digits_to_dec_str(&buf[..len], exp, frac_digits, parts) }
}
}
}
use crate::cmp::Ordering;
-use crate::num::flt2dec::{Decoded, MAX_SIG_DIGITS, round_up};
-use crate::num::flt2dec::estimator::estimate_scaling_factor;
-use crate::num::bignum::Digit32 as Digit;
use crate::num::bignum::Big32x40 as Big;
+use crate::num::bignum::Digit32 as Digit;
+use crate::num::flt2dec::estimator::estimate_scaling_factor;
+use crate::num::flt2dec::{round_up, Decoded, MAX_SIG_DIGITS};
-static POW10: [Digit; 10] = [1, 10, 100, 1000, 10000, 100000,
- 1000000, 10000000, 100000000, 1000000000];
-static TWOPOW10: [Digit; 10] = [2, 20, 200, 2000, 20000, 200000,
- 2000000, 20000000, 200000000, 2000000000];
+static POW10: [Digit; 10] =
+ [1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000];
+static TWOPOW10: [Digit; 10] =
+ [2, 20, 200, 2000, 20000, 200000, 2000000, 20000000, 200000000, 2000000000];
// precalculated arrays of `Digit`s for 10^(2^n)
static POW10TO16: [Digit; 2] = [0x6fc10000, 0x2386f2];
static POW10TO32: [Digit; 4] = [0, 0x85acef81, 0x2d6d415b, 0x4ee];
static POW10TO64: [Digit; 7] = [0, 0, 0xbf6a1f01, 0x6e38ed64, 0xdaa797ed, 0xe93ff9f4, 0x184f03];
-static POW10TO128: [Digit; 14] =
- [0, 0, 0, 0, 0x2e953e01, 0x3df9909, 0xf1538fd, 0x2374e42f, 0xd3cff5ec, 0xc404dc08,
- 0xbccdb0da, 0xa6337f19, 0xe91f2603, 0x24e];
-static POW10TO256: [Digit; 27] =
- [0, 0, 0, 0, 0, 0, 0, 0, 0x982e7c01, 0xbed3875b, 0xd8d99f72, 0x12152f87, 0x6bde50c6,
- 0xcf4a6e70, 0xd595d80f, 0x26b2716e, 0xadc666b0, 0x1d153624, 0x3c42d35a, 0x63ff540e,
- 0xcc5573c0, 0x65f9ef17, 0x55bc28f2, 0x80dcc7f7, 0xf46eeddc, 0x5fdcefce, 0x553f7];
+static POW10TO128: [Digit; 14] = [
+ 0, 0, 0, 0, 0x2e953e01, 0x3df9909, 0xf1538fd, 0x2374e42f, 0xd3cff5ec, 0xc404dc08, 0xbccdb0da,
+ 0xa6337f19, 0xe91f2603, 0x24e,
+];
+static POW10TO256: [Digit; 27] = [
+ 0, 0, 0, 0, 0, 0, 0, 0, 0x982e7c01, 0xbed3875b, 0xd8d99f72, 0x12152f87, 0x6bde50c6, 0xcf4a6e70,
+ 0xd595d80f, 0x26b2716e, 0xadc666b0, 0x1d153624, 0x3c42d35a, 0x63ff540e, 0xcc5573c0, 0x65f9ef17,
+ 0x55bc28f2, 0x80dcc7f7, 0xf46eeddc, 0x5fdcefce, 0x553f7,
+];
#[doc(hidden)]
pub fn mul_pow10(x: &mut Big, n: usize) -> &mut Big {
debug_assert!(n < 512);
- if n & 7 != 0 { x.mul_small(POW10[n & 7]); }
- if n & 8 != 0 { x.mul_small(POW10[8]); }
- if n & 16 != 0 { x.mul_digits(&POW10TO16); }
- if n & 32 != 0 { x.mul_digits(&POW10TO32); }
- if n & 64 != 0 { x.mul_digits(&POW10TO64); }
- if n & 128 != 0 { x.mul_digits(&POW10TO128); }
- if n & 256 != 0 { x.mul_digits(&POW10TO256); }
+ if n & 7 != 0 {
+ x.mul_small(POW10[n & 7]);
+ }
+ if n & 8 != 0 {
+ x.mul_small(POW10[8]);
+ }
+ if n & 16 != 0 {
+ x.mul_digits(&POW10TO16);
+ }
+ if n & 32 != 0 {
+ x.mul_digits(&POW10TO32);
+ }
+ if n & 64 != 0 {
+ x.mul_digits(&POW10TO64);
+ }
+ if n & 128 != 0 {
+ x.mul_digits(&POW10TO128);
+ }
+ if n & 256 != 0 {
+ x.mul_digits(&POW10TO256);
+ }
x
}
}
// only usable when `x < 16 * scale`; `scaleN` should be `scale.mul_small(N)`
-fn div_rem_upto_16<'a>(x: &'a mut Big, scale: &Big,
- scale2: &Big, scale4: &Big, scale8: &Big) -> (u8, &'a mut Big) {
+fn div_rem_upto_16<'a>(
+ x: &'a mut Big,
+ scale: &Big,
+ scale2: &Big,
+ scale4: &Big,
+ scale8: &Big,
+) -> (u8, &'a mut Big) {
let mut d = 0;
- if *x >= *scale8 { x.sub(scale8); d += 8; }
- if *x >= *scale4 { x.sub(scale4); d += 4; }
- if *x >= *scale2 { x.sub(scale2); d += 2; }
- if *x >= *scale { x.sub(scale); d += 1; }
+ if *x >= *scale8 {
+ x.sub(scale8);
+ d += 8;
+ }
+ if *x >= *scale4 {
+ x.sub(scale4);
+ d += 4;
+ }
+ if *x >= *scale2 {
+ x.sub(scale2);
+ d += 2;
+ }
+ if *x >= *scale {
+ x.sub(scale);
+ d += 1;
+ }
debug_assert!(*x < *scale);
(d, x)
}
assert!(buf.len() >= MAX_SIG_DIGITS);
// `a.cmp(&b) < rounding` is `if d.inclusive {a <= b} else {a < b}`
- let rounding = if d.inclusive {Ordering::Greater} else {Ordering::Equal};
+ let rounding = if d.inclusive { Ordering::Greater } else { Ordering::Equal };
// estimate `k_0` from original inputs satisfying `10^(k_0-1) < high <= 10^(k_0+1)`.
// the tight bound `k` satisfying `10^(k-1) < high <= 10^k` is calculated later.
}
// cache `(2, 4, 8) * scale` for digit generation.
- let mut scale2 = scale.clone(); scale2.mul_pow2(1);
- let mut scale4 = scale.clone(); scale4.mul_pow2(2);
- let mut scale8 = scale.clone(); scale8.mul_pow2(3);
+ let mut scale2 = scale.clone();
+ scale2.mul_pow2(1);
+ let mut scale4 = scale.clone();
+ scale4.mul_pow2(2);
+ let mut scale8 = scale.clone();
+ scale8.mul_pow2(3);
let mut down;
let mut up;
// - keep generating otherwise.
down = mant.cmp(&minus) < rounding;
up = scale.cmp(mant.clone().add(&plus)) < rounding;
- if down || up { break; } // we have the shortest representation, proceed to the rounding
+ if down || up {
+ break;
+ } // we have the shortest representation, proceed to the rounding
// restore the invariants.
// this makes the algorithm always terminating: `minus` and `plus` always increases,
if len > 0 {
// cache `(2, 4, 8) * scale` for digit generation.
// (this can be expensive, so do not calculate them when the buffer is empty.)
- let mut scale2 = scale.clone(); scale2.mul_pow2(1);
- let mut scale4 = scale.clone(); scale4.mul_pow2(2);
- let mut scale8 = scale.clone(); scale8.mul_pow2(3);
+ let mut scale2 = scale.clone();
+ scale2.mul_pow2(1);
+ let mut scale4 = scale.clone();
+ scale4.mul_pow2(2);
+ let mut scale8 = scale.clone();
+ scale8.mul_pow2(3);
for i in 0..len {
- if mant.is_zero() { // following digits are all zeroes, we stop here
+ if mant.is_zero() {
+ // following digits are all zeroes, we stop here
// do *not* try to perform rounding! rather, fill remaining digits.
- for c in &mut buf[i..len] { *c = b'0'; }
+ for c in &mut buf[i..len] {
+ *c = b'0';
+ }
return (len, k);
}
let mut d = 0;
- if mant >= scale8 { mant.sub(&scale8); d += 8; }
- if mant >= scale4 { mant.sub(&scale4); d += 4; }
- if mant >= scale2 { mant.sub(&scale2); d += 2; }
- if mant >= scale { mant.sub(&scale); d += 1; }
+ if mant >= scale8 {
+ mant.sub(&scale8);
+ d += 8;
+ }
+ if mant >= scale4 {
+ mant.sub(&scale4);
+ d += 4;
+ }
+ if mant >= scale2 {
+ mant.sub(&scale2);
+ d += 2;
+ }
+ if mant >= scale {
+ mant.sub(&scale);
+ d += 1;
+ }
debug_assert!(mant < scale);
debug_assert!(d < 10);
buf[i] = b'0' + d;
// if the following digits are exactly 5000..., check the prior digit and try to
// round to even (i.e., avoid rounding up when the prior digit is even).
let order = mant.cmp(scale.mul_small(5));
- if order == Ordering::Greater || (order == Ordering::Equal &&
- (len == 0 || buf[len-1] & 1 == 1)) {
+ if order == Ordering::Greater
+ || (order == Ordering::Equal && (len == 0 || buf[len - 1] & 1 == 1))
+ {
// if rounding up changes the length, the exponent should also change.
// but we've been requested a fixed number of digits, so do not alter the buffer...
if let Some(c) = round_up(buf, len) {
//! accurately with integers. SIGPLAN Not. 45, 6 (June 2010), 233-243.
use crate::num::diy_float::Fp;
-use crate::num::flt2dec::{Decoded, MAX_SIG_DIGITS, round_up};
-
+use crate::num::flt2dec::{round_up, Decoded, MAX_SIG_DIGITS};
// see the comments in `format_shortest_opt` for the rationale.
-#[doc(hidden)] pub const ALPHA: i16 = -60;
-#[doc(hidden)] pub const GAMMA: i16 = -32;
+#[doc(hidden)]
+pub const ALPHA: i16 = -60;
+#[doc(hidden)]
+pub const GAMMA: i16 = -32;
/*
# the following Python code generates this table:
*/
#[doc(hidden)]
-pub static CACHED_POW10: [(u64, i16, i16); 81] = [ // (f, e, k)
+pub static CACHED_POW10: [(u64, i16, i16); 81] = [
+ // (f, e, k)
(0xe61acf033d1a45df, -1087, -308),
(0xab70fe17c79ac6ca, -1060, -300),
(0xff77b1fcbebcdc4f, -1034, -292),
(0xbe5691ef416bd60c, -1007, -284),
- (0x8dd01fad907ffc3c, -980, -276),
- (0xd3515c2831559a83, -954, -268),
- (0x9d71ac8fada6c9b5, -927, -260),
- (0xea9c227723ee8bcb, -901, -252),
- (0xaecc49914078536d, -874, -244),
- (0x823c12795db6ce57, -847, -236),
- (0xc21094364dfb5637, -821, -228),
- (0x9096ea6f3848984f, -794, -220),
- (0xd77485cb25823ac7, -768, -212),
- (0xa086cfcd97bf97f4, -741, -204),
- (0xef340a98172aace5, -715, -196),
- (0xb23867fb2a35b28e, -688, -188),
- (0x84c8d4dfd2c63f3b, -661, -180),
- (0xc5dd44271ad3cdba, -635, -172),
- (0x936b9fcebb25c996, -608, -164),
- (0xdbac6c247d62a584, -582, -156),
- (0xa3ab66580d5fdaf6, -555, -148),
- (0xf3e2f893dec3f126, -529, -140),
- (0xb5b5ada8aaff80b8, -502, -132),
- (0x87625f056c7c4a8b, -475, -124),
- (0xc9bcff6034c13053, -449, -116),
- (0x964e858c91ba2655, -422, -108),
- (0xdff9772470297ebd, -396, -100),
- (0xa6dfbd9fb8e5b88f, -369, -92),
- (0xf8a95fcf88747d94, -343, -84),
- (0xb94470938fa89bcf, -316, -76),
- (0x8a08f0f8bf0f156b, -289, -68),
- (0xcdb02555653131b6, -263, -60),
- (0x993fe2c6d07b7fac, -236, -52),
- (0xe45c10c42a2b3b06, -210, -44),
- (0xaa242499697392d3, -183, -36),
- (0xfd87b5f28300ca0e, -157, -28),
- (0xbce5086492111aeb, -130, -20),
- (0x8cbccc096f5088cc, -103, -12),
- (0xd1b71758e219652c, -77, -4),
- (0x9c40000000000000, -50, 4),
- (0xe8d4a51000000000, -24, 12),
- (0xad78ebc5ac620000, 3, 20),
- (0x813f3978f8940984, 30, 28),
- (0xc097ce7bc90715b3, 56, 36),
- (0x8f7e32ce7bea5c70, 83, 44),
- (0xd5d238a4abe98068, 109, 52),
- (0x9f4f2726179a2245, 136, 60),
- (0xed63a231d4c4fb27, 162, 68),
- (0xb0de65388cc8ada8, 189, 76),
- (0x83c7088e1aab65db, 216, 84),
- (0xc45d1df942711d9a, 242, 92),
- (0x924d692ca61be758, 269, 100),
- (0xda01ee641a708dea, 295, 108),
- (0xa26da3999aef774a, 322, 116),
- (0xf209787bb47d6b85, 348, 124),
- (0xb454e4a179dd1877, 375, 132),
- (0x865b86925b9bc5c2, 402, 140),
- (0xc83553c5c8965d3d, 428, 148),
- (0x952ab45cfa97a0b3, 455, 156),
- (0xde469fbd99a05fe3, 481, 164),
- (0xa59bc234db398c25, 508, 172),
- (0xf6c69a72a3989f5c, 534, 180),
- (0xb7dcbf5354e9bece, 561, 188),
- (0x88fcf317f22241e2, 588, 196),
- (0xcc20ce9bd35c78a5, 614, 204),
- (0x98165af37b2153df, 641, 212),
- (0xe2a0b5dc971f303a, 667, 220),
- (0xa8d9d1535ce3b396, 694, 228),
- (0xfb9b7cd9a4a7443c, 720, 236),
- (0xbb764c4ca7a44410, 747, 244),
- (0x8bab8eefb6409c1a, 774, 252),
- (0xd01fef10a657842c, 800, 260),
- (0x9b10a4e5e9913129, 827, 268),
- (0xe7109bfba19c0c9d, 853, 276),
- (0xac2820d9623bf429, 880, 284),
- (0x80444b5e7aa7cf85, 907, 292),
- (0xbf21e44003acdd2d, 933, 300),
- (0x8e679c2f5e44ff8f, 960, 308),
- (0xd433179d9c8cb841, 986, 316),
- (0x9e19db92b4e31ba9, 1013, 324),
- (0xeb96bf6ebadf77d9, 1039, 332),
+ (0x8dd01fad907ffc3c, -980, -276),
+ (0xd3515c2831559a83, -954, -268),
+ (0x9d71ac8fada6c9b5, -927, -260),
+ (0xea9c227723ee8bcb, -901, -252),
+ (0xaecc49914078536d, -874, -244),
+ (0x823c12795db6ce57, -847, -236),
+ (0xc21094364dfb5637, -821, -228),
+ (0x9096ea6f3848984f, -794, -220),
+ (0xd77485cb25823ac7, -768, -212),
+ (0xa086cfcd97bf97f4, -741, -204),
+ (0xef340a98172aace5, -715, -196),
+ (0xb23867fb2a35b28e, -688, -188),
+ (0x84c8d4dfd2c63f3b, -661, -180),
+ (0xc5dd44271ad3cdba, -635, -172),
+ (0x936b9fcebb25c996, -608, -164),
+ (0xdbac6c247d62a584, -582, -156),
+ (0xa3ab66580d5fdaf6, -555, -148),
+ (0xf3e2f893dec3f126, -529, -140),
+ (0xb5b5ada8aaff80b8, -502, -132),
+ (0x87625f056c7c4a8b, -475, -124),
+ (0xc9bcff6034c13053, -449, -116),
+ (0x964e858c91ba2655, -422, -108),
+ (0xdff9772470297ebd, -396, -100),
+ (0xa6dfbd9fb8e5b88f, -369, -92),
+ (0xf8a95fcf88747d94, -343, -84),
+ (0xb94470938fa89bcf, -316, -76),
+ (0x8a08f0f8bf0f156b, -289, -68),
+ (0xcdb02555653131b6, -263, -60),
+ (0x993fe2c6d07b7fac, -236, -52),
+ (0xe45c10c42a2b3b06, -210, -44),
+ (0xaa242499697392d3, -183, -36),
+ (0xfd87b5f28300ca0e, -157, -28),
+ (0xbce5086492111aeb, -130, -20),
+ (0x8cbccc096f5088cc, -103, -12),
+ (0xd1b71758e219652c, -77, -4),
+ (0x9c40000000000000, -50, 4),
+ (0xe8d4a51000000000, -24, 12),
+ (0xad78ebc5ac620000, 3, 20),
+ (0x813f3978f8940984, 30, 28),
+ (0xc097ce7bc90715b3, 56, 36),
+ (0x8f7e32ce7bea5c70, 83, 44),
+ (0xd5d238a4abe98068, 109, 52),
+ (0x9f4f2726179a2245, 136, 60),
+ (0xed63a231d4c4fb27, 162, 68),
+ (0xb0de65388cc8ada8, 189, 76),
+ (0x83c7088e1aab65db, 216, 84),
+ (0xc45d1df942711d9a, 242, 92),
+ (0x924d692ca61be758, 269, 100),
+ (0xda01ee641a708dea, 295, 108),
+ (0xa26da3999aef774a, 322, 116),
+ (0xf209787bb47d6b85, 348, 124),
+ (0xb454e4a179dd1877, 375, 132),
+ (0x865b86925b9bc5c2, 402, 140),
+ (0xc83553c5c8965d3d, 428, 148),
+ (0x952ab45cfa97a0b3, 455, 156),
+ (0xde469fbd99a05fe3, 481, 164),
+ (0xa59bc234db398c25, 508, 172),
+ (0xf6c69a72a3989f5c, 534, 180),
+ (0xb7dcbf5354e9bece, 561, 188),
+ (0x88fcf317f22241e2, 588, 196),
+ (0xcc20ce9bd35c78a5, 614, 204),
+ (0x98165af37b2153df, 641, 212),
+ (0xe2a0b5dc971f303a, 667, 220),
+ (0xa8d9d1535ce3b396, 694, 228),
+ (0xfb9b7cd9a4a7443c, 720, 236),
+ (0xbb764c4ca7a44410, 747, 244),
+ (0x8bab8eefb6409c1a, 774, 252),
+ (0xd01fef10a657842c, 800, 260),
+ (0x9b10a4e5e9913129, 827, 268),
+ (0xe7109bfba19c0c9d, 853, 276),
+ (0xac2820d9623bf429, 880, 284),
+ (0x80444b5e7aa7cf85, 907, 292),
+ (0xbf21e44003acdd2d, 933, 300),
+ (0x8e679c2f5e44ff8f, 960, 308),
+ (0xd433179d9c8cb841, 986, 316),
+ (0x9e19db92b4e31ba9, 1013, 324),
+ (0xeb96bf6ebadf77d9, 1039, 332),
];
-#[doc(hidden)] pub const CACHED_POW10_FIRST_E: i16 = -1087;
-#[doc(hidden)] pub const CACHED_POW10_LAST_E: i16 = 1039;
+#[doc(hidden)]
+pub const CACHED_POW10_FIRST_E: i16 = -1087;
+#[doc(hidden)]
+pub const CACHED_POW10_LAST_E: i16 = 1039;
#[doc(hidden)]
pub fn cached_power(alpha: i16, gamma: i16) -> (i16, Fp) {
debug_assert!(x > 0);
const X9: u32 = 10_0000_0000;
- const X8: u32 = 1_0000_0000;
- const X7: u32 = 1000_0000;
- const X6: u32 = 100_0000;
- const X5: u32 = 10_0000;
- const X4: u32 = 1_0000;
- const X3: u32 = 1000;
- const X2: u32 = 100;
- const X1: u32 = 10;
+ const X8: u32 = 1_0000_0000;
+ const X7: u32 = 1000_0000;
+ const X6: u32 = 100_0000;
+ const X5: u32 = 10_0000;
+ const X4: u32 = 1_0000;
+ const X3: u32 = 1000;
+ const X2: u32 = 100;
+ const X1: u32 = 10;
if x < X4 {
- if x < X2 { if x < X1 {(0, 1)} else {(1, X1)} }
- else { if x < X3 {(2, X2)} else {(3, X3)} }
+ if x < X2 {
+ if x < X1 { (0, 1) } else { (1, X1) }
+ } else {
+ if x < X3 { (2, X2) } else { (3, X3) }
+ }
} else {
- if x < X6 { if x < X5 {(4, X4)} else {(5, X5)} }
- else if x < X8 { if x < X7 {(6, X6)} else {(7, X7)} }
- else { if x < X9 {(8, X8)} else {(9, X9)} }
+ if x < X6 {
+ if x < X5 { (4, X4) } else { (5, X5) }
+ } else if x < X8 {
+ if x < X7 { (6, X6) } else { (7, X7) }
+ } else {
+ if x < X9 { (8, X8) } else { (9, X9) }
+ }
}
}
/// The shortest mode implementation for Grisu.
///
/// It returns `None` when it would return an inexact representation otherwise.
-pub fn format_shortest_opt(d: &Decoded,
- buf: &mut [u8]) -> Option<(/*#digits*/ usize, /*exp*/ i16)> {
+pub fn format_shortest_opt(
+ d: &Decoded,
+ buf: &mut [u8],
+) -> Option<(/*#digits*/ usize, /*exp*/ i16)> {
assert!(d.mant > 0);
assert!(d.minus > 0);
assert!(d.plus > 0);
// we start with the correct repr within the unsafe region, and try to find the closest repr
// to `v` which is also within the safe region. if we can't, we give up.
let plus1 = plus.f + 1;
-// let plus0 = plus.f - 1; // only for explanation
-// let minus0 = minus.f + 1; // only for explanation
+ // let plus0 = plus.f - 1; // only for explanation
+ // let minus0 = minus.f + 1; // only for explanation
let minus1 = minus.f - 1;
let e = -plus.e as usize; // shared exponent
// (e.g., `x` = 32000, `y` = 32777; `kappa` = 2 since `y mod 10^3 = 777 < y - x = 777`.)
// the algorithm relies on the later verification phase to exclude `y`.
let delta1 = plus1 - minus1;
-// let delta1int = (delta1 >> e) as usize; // only for explanation
+ // let delta1int = (delta1 >> e) as usize; // only for explanation
let delta1frac = delta1 & ((1 << e) - 1);
// render integral parts, while checking for the accuracy at each step.
let mut kappa = max_kappa as i16;
let mut ten_kappa = max_ten_kappa; // 10^kappa
let mut remainder = plus1int; // digits yet to be rendered
- loop { // we always have at least one digit to render, as `plus1 >= 10^kappa`
+ loop {
+ // we always have at least one digit to render, as `plus1 >= 10^kappa`
// invariants:
// - `delta1int <= remainder < 10^(kappa+1)`
// - `plus1int = d[0..n-1] * 10^(kappa+1) + remainder`
let mut remainder = plus1frac;
let mut threshold = delta1frac;
let mut ulp = 1;
- loop { // the next digit should be significant as we've tested that before breaking out
+ loop {
+ // the next digit should be significant as we've tested that before breaking out
// invariants, where `m = max_kappa + 1` (# of digits in the integral part):
// - `remainder < 2^e`
// - `plus1frac * 10^(n-m) = d[m..n-1] * 2^e + remainder`
if r < threshold {
let ten_kappa = 1 << e; // implicit divisor
- return round_and_weed(&mut buf[..i], exp, r, threshold,
- (plus1 - v.f) * ulp, ten_kappa, ulp);
+ return round_and_weed(
+ &mut buf[..i],
+ exp,
+ r,
+ threshold,
+ (plus1 - v.f) * ulp,
+ ten_kappa,
+ ulp,
+ );
}
// restore invariants
// - `plus1v = (plus1 - v) * k` (and also, `threshold > plus1v` from prior invariants)
// - `ten_kappa = 10^kappa * k`
// - `ulp = 2^-e * k`
- fn round_and_weed(buf: &mut [u8], exp: i16, remainder: u64, threshold: u64, plus1v: u64,
- ten_kappa: u64, ulp: u64) -> Option<(usize, i16)> {
+ fn round_and_weed(
+ buf: &mut [u8],
+ exp: i16,
+ remainder: u64,
+ threshold: u64,
+ plus1v: u64,
+ ten_kappa: u64,
+ ulp: u64,
+ ) -> Option<(usize, i16)> {
assert!(!buf.is_empty());
// produce two approximations to `v` (actually `plus1 - v`) within 1.5 ulps.
//
// consequently, we should stop when `TC1 || TC2 || (TC3a && TC3b)`. the following is
// equal to its inverse, `!TC1 && !TC2 && (!TC3a || !TC3b)`.
- while plus1w < plus1v_up &&
- threshold - plus1w >= ten_kappa &&
- (plus1w + ten_kappa < plus1v_up ||
- plus1v_up - plus1w >= plus1w + ten_kappa - plus1v_up) {
+ while plus1w < plus1v_up
+ && threshold - plus1w >= ten_kappa
+ && (plus1w + ten_kappa < plus1v_up
+ || plus1v_up - plus1w >= plus1w + ten_kappa - plus1v_up)
+ {
*last -= 1;
debug_assert!(*last > b'0'); // the shortest repr cannot end with `0`
plus1w += ten_kappa;
//
// this is simply same to the terminating conditions for `v + 1 ulp`, with all `plus1v_up`
// replaced by `plus1v_down` instead. overflow analysis equally holds.
- if plus1w < plus1v_down &&
- threshold - plus1w >= ten_kappa &&
- (plus1w + ten_kappa < plus1v_down ||
- plus1v_down - plus1w >= plus1w + ten_kappa - plus1v_down) {
+ if plus1w < plus1v_down
+ && threshold - plus1w >= ten_kappa
+ && (plus1w + ten_kappa < plus1v_down
+ || plus1v_down - plus1w >= plus1w + ten_kappa - plus1v_down)
+ {
return None;
}
/// The exact and fixed mode implementation for Grisu.
///
/// It returns `None` when it would return an inexact representation otherwise.
-pub fn format_exact_opt(d: &Decoded, buf: &mut [u8], limit: i16)
- -> Option<(/*#digits*/ usize, /*exp*/ i16)> {
+pub fn format_exact_opt(
+ d: &Decoded,
+ buf: &mut [u8],
+ limit: i16,
+) -> Option<(/*#digits*/ usize, /*exp*/ i16)> {
assert!(d.mant > 0);
assert!(d.mant < (1 << 61)); // we need at least three bits of additional precision
assert!(!buf.is_empty());
let mut kappa = max_kappa as i16;
let mut ten_kappa = max_ten_kappa; // 10^kappa
let mut remainder = vint; // digits yet to be rendered
- loop { // we always have at least one digit to render
+ loop {
+ // we always have at least one digit to render
// invariants:
// - `remainder < 10^(kappa+1)`
// - `vint = d[0..n-1] * 10^(kappa+1) + remainder`
// - `remainder = (v % 10^kappa) * k`
// - `ten_kappa = 10^kappa * k`
// - `ulp = 2^-e * k`
- fn possibly_round(buf: &mut [u8], mut len: usize, mut exp: i16, limit: i16,
- remainder: u64, ten_kappa: u64, ulp: u64) -> Option<(usize, i16)> {
+ fn possibly_round(
+ buf: &mut [u8],
+ mut len: usize,
+ mut exp: i16,
+ limit: i16,
+ remainder: u64,
+ ten_kappa: u64,
+ ulp: u64,
+ ) -> Option<(usize, i16)> {
debug_assert!(remainder < ten_kappa);
// 10^kappa
//
// error is too large that there are at least three possible representations
// between `v - 1 ulp` and `v + 1 ulp`. we cannot determine which one is correct.
- if ulp >= ten_kappa { return None; }
+ if ulp >= ten_kappa {
+ return None;
+ }
// 10^kappa
// :<------->:
// in fact, 1/2 ulp is enough to introduce two possible representations.
// (remember that we need a unique representation for both `v - 1 ulp` and `v + 1 ulp`.)
// this won't overflow, as `ulp < ten_kappa` from the first check.
- if ten_kappa - ulp <= ulp { return None; }
+ if ten_kappa - ulp <= ulp {
+ return None;
+ }
// remainder
// :<->| :
#[allow(unused_macros)]
macro_rules! sh_impl_signed {
- ($t:ident, $f:ident) => (
+ ($t:ident, $f:ident) => {
#[stable(feature = "rust1", since = "1.0.0")]
impl Shl<$f> for Wrapping<$t> {
type Output = Wrapping<$t>;
}
}
forward_ref_binop! { impl Shl, shl for Wrapping<$t>, $f,
- #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] }
+ #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] }
#[stable(feature = "op_assign_traits", since = "1.8.0")]
impl ShlAssign<$f> for Wrapping<$t> {
}
}
forward_ref_binop! { impl Shr, shr for Wrapping<$t>, $f,
- #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] }
+ #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] }
#[stable(feature = "op_assign_traits", since = "1.8.0")]
impl ShrAssign<$f> for Wrapping<$t> {
}
}
forward_ref_op_assign! { impl ShrAssign, shr_assign for Wrapping<$t>, $f }
- )
+ };
}
macro_rules! sh_impl_unsigned {
- ($t:ident, $f:ident) => (
+ ($t:ident, $f:ident) => {
#[stable(feature = "rust1", since = "1.0.0")]
impl Shl<$f> for Wrapping<$t> {
type Output = Wrapping<$t>;
}
}
forward_ref_binop! { impl Shl, shl for Wrapping<$t>, $f,
- #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] }
+ #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] }
#[stable(feature = "op_assign_traits", since = "1.8.0")]
impl ShlAssign<$f> for Wrapping<$t> {
}
}
forward_ref_binop! { impl Shr, shr for Wrapping<$t>, $f,
- #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] }
+ #[stable(feature = "wrapping_ref_ops", since = "1.39.0")] }
#[stable(feature = "op_assign_traits", since = "1.8.0")]
impl ShrAssign<$f> for Wrapping<$t> {
}
}
forward_ref_op_assign! { impl ShrAssign, shr_assign for Wrapping<$t>, $f }
- )
+ };
}
// FIXME (#23545): uncomment the remaining impls
#[lang = "add"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented(
- on(
- all(_Self="{integer}", Rhs="{float}"),
- message="cannot add a float to an integer",
- ),
- on(
- all(_Self="{float}", Rhs="{integer}"),
- message="cannot add an integer to a float",
- ),
- message="cannot add `{Rhs}` to `{Self}`",
- label="no implementation for `{Self} + {Rhs}`",
+ on(all(_Self = "{integer}", Rhs = "{float}"), message = "cannot add a float to an integer",),
+ on(all(_Self = "{float}", Rhs = "{integer}"), message = "cannot add an integer to a float",),
+ message = "cannot add `{Rhs}` to `{Self}`",
+ label = "no implementation for `{Self} + {Rhs}`"
)]
#[doc(alias = "+")]
-pub trait Add<Rhs=Self> {
+pub trait Add<Rhs = Self> {
/// The resulting type after applying the `+` operator.
#[stable(feature = "rust1", since = "1.0.0")]
type Output;
/// ```
#[lang = "sub"]
#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented(message="cannot subtract `{Rhs}` from `{Self}`",
- label="no implementation for `{Self} - {Rhs}`")]
+#[rustc_on_unimplemented(
+ message = "cannot subtract `{Rhs}` from `{Self}`",
+ label = "no implementation for `{Self} - {Rhs}`"
+)]
#[doc(alias = "-")]
-pub trait Sub<Rhs=Self> {
+pub trait Sub<Rhs = Self> {
/// The resulting type after applying the `-` operator.
#[stable(feature = "rust1", since = "1.0.0")]
type Output;
/// ```
#[lang = "mul"]
#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented(message="cannot multiply `{Rhs}` to `{Self}`",
- label="no implementation for `{Self} * {Rhs}`")]
+#[rustc_on_unimplemented(
+ message = "cannot multiply `{Rhs}` to `{Self}`",
+ label = "no implementation for `{Self} * {Rhs}`"
+)]
#[doc(alias = "*")]
-pub trait Mul<Rhs=Self> {
+pub trait Mul<Rhs = Self> {
/// The resulting type after applying the `*` operator.
#[stable(feature = "rust1", since = "1.0.0")]
type Output;
/// ```
#[lang = "div"]
#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented(message="cannot divide `{Self}` by `{Rhs}`",
- label="no implementation for `{Self} / {Rhs}`")]
+#[rustc_on_unimplemented(
+ message = "cannot divide `{Self}` by `{Rhs}`",
+ label = "no implementation for `{Self} / {Rhs}`"
+)]
#[doc(alias = "/")]
-pub trait Div<Rhs=Self> {
+pub trait Div<Rhs = Self> {
/// The resulting type after applying the `/` operator.
#[stable(feature = "rust1", since = "1.0.0")]
type Output;
/// ```
#[lang = "rem"]
#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented(message="cannot mod `{Self}` by `{Rhs}`",
- label="no implementation for `{Self} % {Rhs}`")]
+#[rustc_on_unimplemented(
+ message = "cannot mod `{Self}` by `{Rhs}`",
+ label = "no implementation for `{Self} % {Rhs}`"
+)]
#[doc(alias = "%")]
-pub trait Rem<Rhs=Self> {
+pub trait Rem<Rhs = Self> {
/// The resulting type after applying the `%` operator.
#[stable(feature = "rust1", since = "1.0.0")]
type Output;
rem_impl_integer! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
-
macro_rules! rem_impl_float {
($($t:ty)*) => ($(
fn neg(self) -> Self::Output;
}
-
-
macro_rules! neg_impl_core {
($id:ident => $body:expr, $($t:ty)*) => ($(
#[stable(feature = "rust1", since = "1.0.0")]
/// ```
#[lang = "add_assign"]
#[stable(feature = "op_assign_traits", since = "1.8.0")]
-#[rustc_on_unimplemented(message="cannot add-assign `{Rhs}` to `{Self}`",
- label="no implementation for `{Self} += {Rhs}`")]
+#[rustc_on_unimplemented(
+ message = "cannot add-assign `{Rhs}` to `{Self}`",
+ label = "no implementation for `{Self} += {Rhs}`"
+)]
#[doc(alias = "+")]
#[doc(alias = "+=")]
-pub trait AddAssign<Rhs=Self> {
+pub trait AddAssign<Rhs = Self> {
/// Performs the `+=` operation.
#[stable(feature = "op_assign_traits", since = "1.8.0")]
fn add_assign(&mut self, rhs: Rhs);
/// ```
#[lang = "sub_assign"]
#[stable(feature = "op_assign_traits", since = "1.8.0")]
-#[rustc_on_unimplemented(message="cannot subtract-assign `{Rhs}` from `{Self}`",
- label="no implementation for `{Self} -= {Rhs}`")]
+#[rustc_on_unimplemented(
+ message = "cannot subtract-assign `{Rhs}` from `{Self}`",
+ label = "no implementation for `{Self} -= {Rhs}`"
+)]
#[doc(alias = "-")]
#[doc(alias = "-=")]
-pub trait SubAssign<Rhs=Self> {
+pub trait SubAssign<Rhs = Self> {
/// Performs the `-=` operation.
#[stable(feature = "op_assign_traits", since = "1.8.0")]
fn sub_assign(&mut self, rhs: Rhs);
/// ```
#[lang = "mul_assign"]
#[stable(feature = "op_assign_traits", since = "1.8.0")]
-#[rustc_on_unimplemented(message="cannot multiply-assign `{Rhs}` to `{Self}`",
- label="no implementation for `{Self} *= {Rhs}`")]
+#[rustc_on_unimplemented(
+ message = "cannot multiply-assign `{Rhs}` to `{Self}`",
+ label = "no implementation for `{Self} *= {Rhs}`"
+)]
#[doc(alias = "*")]
#[doc(alias = "*=")]
-pub trait MulAssign<Rhs=Self> {
+pub trait MulAssign<Rhs = Self> {
/// Performs the `*=` operation.
#[stable(feature = "op_assign_traits", since = "1.8.0")]
fn mul_assign(&mut self, rhs: Rhs);
/// ```
#[lang = "div_assign"]
#[stable(feature = "op_assign_traits", since = "1.8.0")]
-#[rustc_on_unimplemented(message="cannot divide-assign `{Self}` by `{Rhs}`",
- label="no implementation for `{Self} /= {Rhs}`")]
+#[rustc_on_unimplemented(
+ message = "cannot divide-assign `{Self}` by `{Rhs}`",
+ label = "no implementation for `{Self} /= {Rhs}`"
+)]
#[doc(alias = "/")]
#[doc(alias = "/=")]
-pub trait DivAssign<Rhs=Self> {
+pub trait DivAssign<Rhs = Self> {
/// Performs the `/=` operation.
#[stable(feature = "op_assign_traits", since = "1.8.0")]
fn div_assign(&mut self, rhs: Rhs);
/// ```
#[lang = "rem_assign"]
#[stable(feature = "op_assign_traits", since = "1.8.0")]
-#[rustc_on_unimplemented(message="cannot mod-assign `{Self}` by `{Rhs}``",
- label="no implementation for `{Self} %= {Rhs}`")]
+#[rustc_on_unimplemented(
+ message = "cannot mod-assign `{Self}` by `{Rhs}``",
+ label = "no implementation for `{Self} %= {Rhs}`"
+)]
#[doc(alias = "%")]
#[doc(alias = "%=")]
-pub trait RemAssign<Rhs=Self> {
+pub trait RemAssign<Rhs = Self> {
/// Performs the `%=` operation.
#[stable(feature = "op_assign_traits", since = "1.8.0")]
fn rem_assign(&mut self, rhs: Rhs);
#[lang = "bitand"]
#[doc(alias = "&")]
#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented(message="no implementation for `{Self} & {Rhs}`",
- label="no implementation for `{Self} & {Rhs}`")]
-pub trait BitAnd<Rhs=Self> {
+#[rustc_on_unimplemented(
+ message = "no implementation for `{Self} & {Rhs}`",
+ label = "no implementation for `{Self} & {Rhs}`"
+)]
+pub trait BitAnd<Rhs = Self> {
/// The resulting type after applying the `&` operator.
#[stable(feature = "rust1", since = "1.0.0")]
type Output;
#[lang = "bitor"]
#[doc(alias = "|")]
#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented(message="no implementation for `{Self} | {Rhs}`",
- label="no implementation for `{Self} | {Rhs}`")]
-pub trait BitOr<Rhs=Self> {
+#[rustc_on_unimplemented(
+ message = "no implementation for `{Self} | {Rhs}`",
+ label = "no implementation for `{Self} | {Rhs}`"
+)]
+pub trait BitOr<Rhs = Self> {
/// The resulting type after applying the `|` operator.
#[stable(feature = "rust1", since = "1.0.0")]
type Output;
#[lang = "bitxor"]
#[doc(alias = "^")]
#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented(message="no implementation for `{Self} ^ {Rhs}`",
- label="no implementation for `{Self} ^ {Rhs}`")]
-pub trait BitXor<Rhs=Self> {
+#[rustc_on_unimplemented(
+ message = "no implementation for `{Self} ^ {Rhs}`",
+ label = "no implementation for `{Self} ^ {Rhs}`"
+)]
+pub trait BitXor<Rhs = Self> {
/// The resulting type after applying the `^` operator.
#[stable(feature = "rust1", since = "1.0.0")]
type Output;
#[lang = "shl"]
#[doc(alias = "<<")]
#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented(message="no implementation for `{Self} << {Rhs}`",
- label="no implementation for `{Self} << {Rhs}`")]
-pub trait Shl<Rhs=Self> {
+#[rustc_on_unimplemented(
+ message = "no implementation for `{Self} << {Rhs}`",
+ label = "no implementation for `{Self} << {Rhs}`"
+)]
+pub trait Shl<Rhs = Self> {
/// The resulting type after applying the `<<` operator.
#[stable(feature = "rust1", since = "1.0.0")]
type Output;
}
macro_rules! shl_impl {
- ($t:ty, $f:ty) => (
+ ($t:ty, $f:ty) => {
#[stable(feature = "rust1", since = "1.0.0")]
impl Shl<$f> for $t {
type Output = $t;
}
forward_ref_binop! { impl Shl, shl for $t, $f }
- )
+ };
}
macro_rules! shl_impl_all {
#[lang = "shr"]
#[doc(alias = ">>")]
#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented(message="no implementation for `{Self} >> {Rhs}`",
- label="no implementation for `{Self} >> {Rhs}`")]
-pub trait Shr<Rhs=Self> {
+#[rustc_on_unimplemented(
+ message = "no implementation for `{Self} >> {Rhs}`",
+ label = "no implementation for `{Self} >> {Rhs}`"
+)]
+pub trait Shr<Rhs = Self> {
/// The resulting type after applying the `>>` operator.
#[stable(feature = "rust1", since = "1.0.0")]
type Output;
}
macro_rules! shr_impl {
- ($t:ty, $f:ty) => (
+ ($t:ty, $f:ty) => {
#[stable(feature = "rust1", since = "1.0.0")]
impl Shr<$f> for $t {
type Output = $t;
}
forward_ref_binop! { impl Shr, shr for $t, $f }
- )
+ };
}
macro_rules! shr_impl_all {
#[lang = "bitand_assign"]
#[doc(alias = "&=")]
#[stable(feature = "op_assign_traits", since = "1.8.0")]
-#[rustc_on_unimplemented(message="no implementation for `{Self} &= {Rhs}`",
- label="no implementation for `{Self} &= {Rhs}`")]
-pub trait BitAndAssign<Rhs=Self> {
+#[rustc_on_unimplemented(
+ message = "no implementation for `{Self} &= {Rhs}`",
+ label = "no implementation for `{Self} &= {Rhs}`"
+)]
+pub trait BitAndAssign<Rhs = Self> {
/// Performs the `&=` operation.
#[stable(feature = "op_assign_traits", since = "1.8.0")]
fn bitand_assign(&mut self, rhs: Rhs);
#[lang = "bitor_assign"]
#[doc(alias = "|=")]
#[stable(feature = "op_assign_traits", since = "1.8.0")]
-#[rustc_on_unimplemented(message="no implementation for `{Self} |= {Rhs}`",
- label="no implementation for `{Self} |= {Rhs}`")]
-pub trait BitOrAssign<Rhs=Self> {
+#[rustc_on_unimplemented(
+ message = "no implementation for `{Self} |= {Rhs}`",
+ label = "no implementation for `{Self} |= {Rhs}`"
+)]
+pub trait BitOrAssign<Rhs = Self> {
/// Performs the `|=` operation.
#[stable(feature = "op_assign_traits", since = "1.8.0")]
fn bitor_assign(&mut self, rhs: Rhs);
#[lang = "bitxor_assign"]
#[doc(alias = "^=")]
#[stable(feature = "op_assign_traits", since = "1.8.0")]
-#[rustc_on_unimplemented(message="no implementation for `{Self} ^= {Rhs}`",
- label="no implementation for `{Self} ^= {Rhs}`")]
-pub trait BitXorAssign<Rhs=Self> {
+#[rustc_on_unimplemented(
+ message = "no implementation for `{Self} ^= {Rhs}`",
+ label = "no implementation for `{Self} ^= {Rhs}`"
+)]
+pub trait BitXorAssign<Rhs = Self> {
/// Performs the `^=` operation.
#[stable(feature = "op_assign_traits", since = "1.8.0")]
fn bitxor_assign(&mut self, rhs: Rhs);
#[lang = "shl_assign"]
#[doc(alias = "<<=")]
#[stable(feature = "op_assign_traits", since = "1.8.0")]
-#[rustc_on_unimplemented(message="no implementation for `{Self} <<= {Rhs}`",
- label="no implementation for `{Self} <<= {Rhs}`")]
-pub trait ShlAssign<Rhs=Self> {
+#[rustc_on_unimplemented(
+ message = "no implementation for `{Self} <<= {Rhs}`",
+ label = "no implementation for `{Self} <<= {Rhs}`"
+)]
+pub trait ShlAssign<Rhs = Self> {
/// Performs the `<<=` operation.
#[stable(feature = "op_assign_traits", since = "1.8.0")]
fn shl_assign(&mut self, rhs: Rhs);
}
macro_rules! shl_assign_impl {
- ($t:ty, $f:ty) => (
+ ($t:ty, $f:ty) => {
#[stable(feature = "op_assign_traits", since = "1.8.0")]
impl ShlAssign<$f> for $t {
#[inline]
}
forward_ref_op_assign! { impl ShlAssign, shl_assign for $t, $f }
- )
+ };
}
macro_rules! shl_assign_impl_all {
#[lang = "shr_assign"]
#[doc(alias = ">>=")]
#[stable(feature = "op_assign_traits", since = "1.8.0")]
-#[rustc_on_unimplemented(message="no implementation for `{Self} >>= {Rhs}`",
- label="no implementation for `{Self} >>= {Rhs}`")]
-pub trait ShrAssign<Rhs=Self> {
+#[rustc_on_unimplemented(
+ message = "no implementation for `{Self} >>= {Rhs}`",
+ label = "no implementation for `{Self} >>= {Rhs}`"
+)]
+pub trait ShrAssign<Rhs = Self> {
/// Performs the `>>=` operation.
#[stable(feature = "op_assign_traits", since = "1.8.0")]
fn shr_assign(&mut self, rhs: Rhs);
}
macro_rules! shr_assign_impl {
- ($t:ty, $f:ty) => (
+ ($t:ty, $f:ty) => {
#[stable(feature = "op_assign_traits", since = "1.8.0")]
impl ShrAssign<$f> for $t {
#[inline]
}
forward_ref_op_assign! { impl ShrAssign, shr_assign for $t, $f }
- )
+ };
}
macro_rules! shr_assign_impl_all {
impl<T: ?Sized> Deref for &T {
type Target = T;
- fn deref(&self) -> &T { *self }
+ fn deref(&self) -> &T {
+ *self
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Deref for &mut T {
type Target = T;
- fn deref(&self) -> &T { *self }
+ fn deref(&self) -> &T {
+ *self
+ }
}
/// Used for mutable dereferencing operations, like in `*v = 1;`.
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> DerefMut for &mut T {
- fn deref_mut(&mut self) -> &mut T { *self }
+ fn deref_mut(&mut self) -> &mut T {
+ *self
+ }
}
/// Indicates that a struct can be used as a method receiver, without the
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_paren_sugar]
#[rustc_on_unimplemented(
- on(Args="()", note="wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}"),
- message="expected a `{Fn}<{Args}>` closure, found `{Self}`",
- label="expected an `Fn<{Args}>` closure, found `{Self}`",
+ on(
+ Args = "()",
+ note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}"
+ ),
+ message = "expected a `{Fn}<{Args}>` closure, found `{Self}`",
+ label = "expected an `Fn<{Args}>` closure, found `{Self}`"
)]
#[fundamental] // so that regex can rely that `&str: !FnMut`
#[must_use = "closures are lazy and do nothing unless called"]
-pub trait Fn<Args> : FnMut<Args> {
+pub trait Fn<Args>: FnMut<Args> {
/// Performs the call operation.
#[unstable(feature = "fn_traits", issue = "29625")]
extern "rust-call" fn call(&self, args: Args) -> Self::Output;
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_paren_sugar]
#[rustc_on_unimplemented(
- on(Args="()", note="wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}"),
- message="expected a `{FnMut}<{Args}>` closure, found `{Self}`",
- label="expected an `FnMut<{Args}>` closure, found `{Self}`",
+ on(
+ Args = "()",
+ note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}"
+ ),
+ message = "expected a `{FnMut}<{Args}>` closure, found `{Self}`",
+ label = "expected an `FnMut<{Args}>` closure, found `{Self}`"
)]
#[fundamental] // so that regex can rely that `&str: !FnMut`
#[must_use = "closures are lazy and do nothing unless called"]
-pub trait FnMut<Args> : FnOnce<Args> {
+pub trait FnMut<Args>: FnOnce<Args> {
/// Performs the call operation.
#[unstable(feature = "fn_traits", issue = "29625")]
extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_paren_sugar]
#[rustc_on_unimplemented(
- on(Args="()", note="wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}"),
- message="expected a `{FnOnce}<{Args}>` closure, found `{Self}`",
- label="expected an `FnOnce<{Args}>` closure, found `{Self}`",
+ on(
+ Args = "()",
+ note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}"
+ ),
+ message = "expected a `{FnOnce}<{Args}>` closure, found `{Self}`",
+ label = "expected an `FnOnce<{Args}>` closure, found `{Self}`"
)]
#[fundamental] // so that regex can rely that `&str: !FnMut`
#[must_use = "closures are lazy and do nothing unless called"]
mod impls {
#[stable(feature = "rust1", since = "1.0.0")]
- impl<A,F:?Sized> Fn<A> for &F
- where F : Fn<A>
+ impl<A, F: ?Sized> Fn<A> for &F
+ where
+ F: Fn<A>,
{
extern "rust-call" fn call(&self, args: A) -> F::Output {
(**self).call(args)
}
#[stable(feature = "rust1", since = "1.0.0")]
- impl<A,F:?Sized> FnMut<A> for &F
- where F : Fn<A>
+ impl<A, F: ?Sized> FnMut<A> for &F
+ where
+ F: Fn<A>,
{
extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output {
(**self).call(args)
}
#[stable(feature = "rust1", since = "1.0.0")]
- impl<A,F:?Sized> FnOnce<A> for &F
- where F : Fn<A>
+ impl<A, F: ?Sized> FnOnce<A> for &F
+ where
+ F: Fn<A>,
{
type Output = F::Output;
}
#[stable(feature = "rust1", since = "1.0.0")]
- impl<A,F:?Sized> FnMut<A> for &mut F
- where F : FnMut<A>
+ impl<A, F: ?Sized> FnMut<A> for &mut F
+ where
+ F: FnMut<A>,
{
extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output {
(*self).call_mut(args)
}
#[stable(feature = "rust1", since = "1.0.0")]
- impl<A,F:?Sized> FnOnce<A> for &mut F
- where F : FnMut<A>
+ impl<A, F: ?Sized> FnOnce<A> for &mut F
+ where
+ F: FnMut<A>,
{
type Output = F::Output;
extern "rust-call" fn call_once(self, args: A) -> F::Output {
/// ```
#[lang = "index"]
#[rustc_on_unimplemented(
- message="the type `{Self}` cannot be indexed by `{Idx}`",
- label="`{Self}` cannot be indexed by `{Idx}`",
+ message = "the type `{Self}` cannot be indexed by `{Idx}`",
+ label = "`{Self}` cannot be indexed by `{Idx}`"
)]
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(alias = "]")]
#[lang = "index_mut"]
#[rustc_on_unimplemented(
on(
- _Self="&str",
- note="you can use `.chars().nth()` or `.bytes().nth()`
+ _Self = "&str",
+ note = "you can use `.chars().nth()` or `.bytes().nth()`
see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
),
on(
- _Self="str",
- note="you can use `.chars().nth()` or `.bytes().nth()`
+ _Self = "str",
+ note = "you can use `.chars().nth()` or `.bytes().nth()`
see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
),
on(
- _Self="std::string::String",
- note="you can use `.chars().nth()` or `.bytes().nth()`
+ _Self = "std::string::String",
+ note = "you can use `.chars().nth()` or `.bytes().nth()`
see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
),
- message="the type `{Self}` cannot be mutably indexed by `{Idx}`",
- label="`{Self}` cannot be mutably indexed by `{Idx}`",
+ message = "the type `{Self}` cannot be mutably indexed by `{Idx}`",
+ label = "`{Self}` cannot be mutably indexed by `{Idx}`"
)]
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(alias = "[")]
mod unsize;
#[stable(feature = "rust1", since = "1.0.0")]
-pub use self::arith::{Add, Sub, Mul, Div, Rem, Neg};
+pub use self::arith::{Add, Div, Mul, Neg, Rem, Sub};
#[stable(feature = "op_assign_traits", since = "1.8.0")]
-pub use self::arith::{AddAssign, SubAssign, MulAssign, DivAssign, RemAssign};
+pub use self::arith::{AddAssign, DivAssign, MulAssign, RemAssign, SubAssign};
#[stable(feature = "rust1", since = "1.0.0")]
-pub use self::bit::{Not, BitAnd, BitOr, BitXor, Shl, Shr};
+pub use self::bit::{BitAnd, BitOr, BitXor, Not, Shl, Shr};
#[stable(feature = "op_assign_traits", since = "1.8.0")]
pub use self::bit::{BitAndAssign, BitOrAssign, BitXorAssign, ShlAssign, ShrAssign};
pub use self::range::{Range, RangeFrom, RangeFull, RangeTo};
#[stable(feature = "inclusive_range", since = "1.26.0")]
-pub use self::range::{RangeInclusive, RangeToInclusive, RangeBounds, Bound};
+pub use self::range::{Bound, RangeBounds, RangeInclusive, RangeToInclusive};
#[unstable(feature = "try_trait", issue = "42327")]
pub use self::r#try::Try;
#[inline]
#[rustc_promotable]
pub const fn new(start: Idx, end: Idx) -> Self {
- Self {
- start,
- end,
- is_empty: None,
- }
+ Self { start, end, is_empty: None }
}
/// Returns the lower bound of the range (inclusive).
// &mut T -> &mut U
#[unstable(feature = "coerce_unsized", issue = "27732")]
-impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<&'a mut U> for &'a mut T {}
+impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a mut U> for &'a mut T {}
// &mut T -> &U
#[unstable(feature = "coerce_unsized", issue = "27732")]
-impl<'a, 'b: 'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b mut T {}
+impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b mut T {}
// &mut T -> *mut U
#[unstable(feature = "coerce_unsized", issue = "27732")]
-impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for &'a mut T {}
+impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for &'a mut T {}
// &mut T -> *const U
#[unstable(feature = "coerce_unsized", issue = "27732")]
-impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for &'a mut T {}
+impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for &'a mut T {}
// &T -> &U
#[unstable(feature = "coerce_unsized", issue = "27732")]
-impl<'a, 'b: 'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
+impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
// &T -> *const U
#[unstable(feature = "coerce_unsized", issue = "27732")]
-impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for &'a T {}
+impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for &'a T {}
// *mut T -> *mut U
#[unstable(feature = "coerce_unsized", issue = "27732")]
-impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
+impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
// *mut T -> *const U
#[unstable(feature = "coerce_unsized", issue = "27732")]
-impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *mut T {}
+impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *mut T {}
// *const T -> *const U
#[unstable(feature = "coerce_unsized", issue = "27732")]
-impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *const T {}
-
+impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *const T {}
/// This is used for object safety, to check that a method's receiver type can be dispatched on.
///
// &T -> &U
#[unstable(feature = "dispatch_from_dyn", issue = "0")]
-impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> DispatchFromDyn<&'a U> for &'a T {}
+impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<&'a U> for &'a T {}
// &mut T -> &mut U
#[unstable(feature = "dispatch_from_dyn", issue = "0")]
-impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> DispatchFromDyn<&'a mut U> for &'a mut T {}
+impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<&'a mut U> for &'a mut T {}
// *const T -> *const U
#[unstable(feature = "dispatch_from_dyn", issue = "0")]
-impl<T: ?Sized+Unsize<U>, U: ?Sized> DispatchFromDyn<*const U> for *const T {}
+impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<*const U> for *const T {}
// *mut T -> *mut U
#[unstable(feature = "dispatch_from_dyn", issue = "0")]
-impl<T: ?Sized+Unsize<U>, U: ?Sized> DispatchFromDyn<*mut U> for *mut T {}
+impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<*mut U> for *mut T {}
#![stable(feature = "rust1", since = "1.0.0")]
use crate::iter::{FromIterator, FusedIterator, TrustedLen};
-use crate::{convert, fmt, hint, mem, ops::{self, Deref, DerefMut}};
use crate::pin::Pin;
+use crate::{
+ convert, fmt, hint, mem,
+ ops::{self, Deref, DerefMut},
+};
// Note that this is not a lang item per se, but it has a hidden dependency on
// `Iterator`, which is one. The compiler assumes that the `next` method of
#[must_use]
#[inline]
#[unstable(feature = "option_result_contains", issue = "62358")]
- pub fn contains<U>(&self, x: &U) -> bool where U: PartialEq<T> {
+ pub fn contains<U>(&self, x: &U) -> bool
+ where
+ U: PartialEq<T>,
+ {
match self {
Some(y) => x == y,
None => false,
}
}
-
/// Converts from [`Pin`]`<&Option<T>>` to `Option<`[`Pin`]`<&T>>`.
///
/// [`Pin`]: ../pin/struct.Pin.html
#[inline]
#[stable(feature = "pin", since = "1.33.0")]
pub fn as_pin_ref(self: Pin<&Self>) -> Option<Pin<&T>> {
- unsafe {
- Pin::get_ref(self).as_ref().map(|x| Pin::new_unchecked(x))
- }
+ unsafe { Pin::get_ref(self).as_ref().map(|x| Pin::new_unchecked(x)) }
}
/// Converts from [`Pin`]`<&mut Option<T>>` to `Option<`[`Pin`]`<&mut T>>`.
#[inline]
#[stable(feature = "pin", since = "1.33.0")]
pub fn as_pin_mut(self: Pin<&mut Self>) -> Option<Pin<&mut T>> {
- unsafe {
- Pin::get_unchecked_mut(self).as_mut().map(|x| Pin::new_unchecked(x))
- }
+ unsafe { Pin::get_unchecked_mut(self).as_mut().map(|x| Pin::new_unchecked(x)) }
}
/////////////////////////////////////////////////////////////////////////
pub fn filter<P: FnOnce(&T) -> bool>(self, predicate: P) -> Self {
if let Some(x) = self {
if predicate(&x) {
- return Some(x)
+ return Some(x);
}
}
None
/// assert!(opt.is_none());
/// ```
#[inline]
- fn default() -> Option<T> { None }
+ fn default() -> Option<T> {
+ None
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Clone, Debug)]
struct Item<A> {
- opt: Option<A>
+ opt: Option<A>,
}
impl<A> Iterator for Item<A> {
/// [`Option::iter`]: enum.Option.html#method.iter
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Debug)]
-pub struct Iter<'a, A: 'a> { inner: Item<&'a A> }
+pub struct Iter<'a, A: 'a> {
+ inner: Item<&'a A>,
+}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, A> Iterator for Iter<'a, A> {
type Item = &'a A;
#[inline]
- fn next(&mut self) -> Option<&'a A> { self.inner.next() }
+ fn next(&mut self) -> Option<&'a A> {
+ self.inner.next()
+ }
#[inline]
- fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.inner.size_hint()
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, A> DoubleEndedIterator for Iter<'a, A> {
#[inline]
- fn next_back(&mut self) -> Option<&'a A> { self.inner.next_back() }
+ fn next_back(&mut self) -> Option<&'a A> {
+ self.inner.next_back()
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
/// [`Option::iter_mut`]: enum.Option.html#method.iter_mut
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Debug)]
-pub struct IterMut<'a, A: 'a> { inner: Item<&'a mut A> }
+pub struct IterMut<'a, A: 'a> {
+ inner: Item<&'a mut A>,
+}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, A> Iterator for IterMut<'a, A> {
type Item = &'a mut A;
#[inline]
- fn next(&mut self) -> Option<&'a mut A> { self.inner.next() }
+ fn next(&mut self) -> Option<&'a mut A> {
+ self.inner.next()
+ }
#[inline]
- fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.inner.size_hint()
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, A> DoubleEndedIterator for IterMut<'a, A> {
#[inline]
- fn next_back(&mut self) -> Option<&'a mut A> { self.inner.next_back() }
+ fn next_back(&mut self) -> Option<&'a mut A> {
+ self.inner.next_back()
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
/// [`Option::into_iter`]: enum.Option.html#method.into_iter
#[derive(Clone, Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
-pub struct IntoIter<A> { inner: Item<A> }
+pub struct IntoIter<A> {
+ inner: Item<A>,
+}
#[stable(feature = "rust1", since = "1.0.0")]
impl<A> Iterator for IntoIter<A> {
type Item = A;
#[inline]
- fn next(&mut self) -> Option<A> { self.inner.next() }
+ fn next(&mut self) -> Option<A> {
+ self.inner.next()
+ }
#[inline]
- fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.inner.size_hint()
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<A> DoubleEndedIterator for IntoIter<A> {
#[inline]
- fn next_back(&mut self) -> Option<A> { self.inner.next_back() }
+ fn next_back(&mut self) -> Option<A> {
+ self.inner.next_back()
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
///
/// [`Iterator`]: ../iter/trait.Iterator.html
#[inline]
- fn from_iter<I: IntoIterator<Item=Option<A>>>(iter: I) -> Option<V> {
+ fn from_iter<I: IntoIterator<Item = Option<A>>>(iter: I) -> Option<V> {
// FIXME(#11084): This could be replaced with Iterator::scan when this
// performance bug is closed.
- iter.into_iter()
- .map(|x| x.ok_or(()))
- .collect::<Result<_, _>>()
- .ok()
+ iter.into_iter().map(|x| x.ok_or(())).collect::<Result<_, _>>().ok()
}
}
#![stable(feature = "pin", since = "1.33.0")]
+use crate::cmp::{self, PartialEq, PartialOrd};
use crate::fmt;
use crate::marker::{Sized, Unpin};
-use crate::cmp::{self, PartialEq, PartialOrd};
-use crate::ops::{Deref, DerefMut, Receiver, CoerceUnsized, DispatchFromDyn};
+use crate::ops::{CoerceUnsized, Deref, DerefMut, DispatchFromDyn, Receiver};
/// A pinned pointer.
///
///
/// [`pin` module]: ../../std/pin/index.html#projections-and-structural-pinning
#[stable(feature = "pin", since = "1.33.0")]
- pub unsafe fn map_unchecked<U, F>(self, func: F) -> Pin<&'a U> where
+ pub unsafe fn map_unchecked<U, F>(self, func: F) -> Pin<&'a U>
+ where
F: FnOnce(&T) -> &U,
{
let pointer = &*self.pointer;
#[stable(feature = "pin", since = "1.33.0")]
#[inline(always)]
pub fn get_mut(self) -> &'a mut T
- where T: Unpin,
+ where
+ T: Unpin,
{
self.pointer
}
///
/// [`pin` module]: ../../std/pin/index.html#projections-and-structural-pinning
#[stable(feature = "pin", since = "1.33.0")]
- pub unsafe fn map_unchecked_mut<U, F>(self, func: F) -> Pin<&'a mut U> where
+ pub unsafe fn map_unchecked_mut<U, F>(self, func: F) -> Pin<&'a mut U>
+ where
F: FnOnce(&mut T) -> &mut U,
{
let pointer = Pin::get_unchecked_mut(self);
// for other reasons, though, so we just need to take care not to allow such
// impls to land in std.
#[stable(feature = "pin", since = "1.33.0")]
-impl<P, U> CoerceUnsized<Pin<U>> for Pin<P>
-where
- P: CoerceUnsized<U>,
-{}
+impl<P, U> CoerceUnsized<Pin<U>> for Pin<P> where P: CoerceUnsized<U> {}
#[stable(feature = "pin", since = "1.33.0")]
-impl<P, U> DispatchFromDyn<Pin<U>> for Pin<P>
-where
- P: DispatchFromDyn<U>,
-{}
+impl<P, U> DispatchFromDyn<Pin<U>> for Pin<P> where P: DispatchFromDyn<U> {}
pub use crate::clone::Clone;
#[stable(feature = "core_prelude", since = "1.4.0")]
#[doc(no_inline)]
-pub use crate::cmp::{PartialEq, PartialOrd, Eq, Ord};
+pub use crate::cmp::{Eq, Ord, PartialEq, PartialOrd};
#[stable(feature = "core_prelude", since = "1.4.0")]
#[doc(no_inline)]
-pub use crate::convert::{AsRef, AsMut, Into, From};
+pub use crate::convert::{AsMut, AsRef, From, Into};
#[stable(feature = "core_prelude", since = "1.4.0")]
#[doc(no_inline)]
pub use crate::default::Default;
#[stable(feature = "core_prelude", since = "1.4.0")]
#[doc(no_inline)]
-pub use crate::iter::{Iterator, Extend, IntoIterator};
+pub use crate::iter::{DoubleEndedIterator, ExactSizeIterator};
#[stable(feature = "core_prelude", since = "1.4.0")]
#[doc(no_inline)]
-pub use crate::iter::{DoubleEndedIterator, ExactSizeIterator};
+pub use crate::iter::{Extend, IntoIterator, Iterator};
#[stable(feature = "core_prelude", since = "1.4.0")]
#[doc(no_inline)]
-pub use crate::option::Option::{self, Some, None};
+pub use crate::option::Option::{self, None, Some};
#[stable(feature = "core_prelude", since = "1.4.0")]
#[doc(no_inline)]
-pub use crate::result::Result::{self, Ok, Err};
+pub use crate::result::Result::{self, Err, Ok};
// Re-exported built-in macros
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
#[doc(no_inline)]
pub use crate::{
- asm,
- assert,
- cfg,
- column,
- compile_error,
- concat,
- concat_idents,
- env,
- file,
- format_args,
- format_args_nl,
- global_asm,
- include,
- include_bytes,
- include_str,
- line,
- log_syntax,
- module_path,
- option_env,
- stringify,
- trace_macros,
+ asm, assert, cfg, column, compile_error, concat, concat_idents, env, file, format_args,
+ format_args_nl, global_asm, include, include_bytes, include_str, line, log_syntax, module_path,
+ option_env, stringify, trace_macros,
};
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
#[allow(deprecated)]
#[doc(no_inline)]
pub use crate::macros::builtin::{
- RustcDecodable,
- RustcEncodable,
- bench,
- global_allocator,
- test,
- test_case,
+ bench, global_allocator, test, test_case, RustcDecodable, RustcEncodable,
};
+use crate::cmp::Ordering;
use crate::convert::From;
-use crate::ops::{CoerceUnsized, DispatchFromDyn};
use crate::fmt;
use crate::hash;
use crate::marker::Unsize;
use crate::mem;
+use crate::ops::{CoerceUnsized, DispatchFromDyn};
use crate::ptr::Unique;
-use crate::cmp::Ordering;
// ignore-tidy-undocumented-unsafe
/// `NonNull` pointers are not `Send` because the data they reference may be aliased.
// N.B., this impl is unnecessary, but should provide better error messages.
#[stable(feature = "nonnull", since = "1.25.0")]
-impl<T: ?Sized> !Send for NonNull<T> { }
+impl<T: ?Sized> !Send for NonNull<T> {}
/// `NonNull` pointers are not `Sync` because the data they reference may be aliased.
// N.B., this impl is unnecessary, but should provide better error messages.
#[stable(feature = "nonnull", since = "1.25.0")]
-impl<T: ?Sized> !Sync for NonNull<T> { }
+impl<T: ?Sized> !Sync for NonNull<T> {}
impl<T: Sized> NonNull<T> {
/// Creates a new `NonNull` that is dangling, but well-aligned.
#[stable(feature = "nonnull", since = "1.25.0")]
#[inline]
pub fn new(ptr: *mut T) -> Option<Self> {
- if !ptr.is_null() {
- Some(unsafe { Self::new_unchecked(ptr) })
- } else {
- None
- }
+ if !ptr.is_null() { Some(unsafe { Self::new_unchecked(ptr) }) } else { None }
}
/// Acquires the underlying `*mut` pointer.
#[stable(feature = "nonnull_cast", since = "1.27.0")]
#[inline]
pub const fn cast<U>(self) -> NonNull<U> {
- unsafe {
- NonNull::new_unchecked(self.as_ptr() as *mut U)
- }
+ unsafe { NonNull::new_unchecked(self.as_ptr() as *mut U) }
}
}
}
#[stable(feature = "nonnull", since = "1.25.0")]
-impl<T: ?Sized> Copy for NonNull<T> { }
+impl<T: ?Sized> Copy for NonNull<T> {}
#[unstable(feature = "coerce_unsized", issue = "27732")]
-impl<T: ?Sized, U: ?Sized> CoerceUnsized<NonNull<U>> for NonNull<T> where T: Unsize<U> { }
+impl<T: ?Sized, U: ?Sized> CoerceUnsized<NonNull<U>> for NonNull<T> where T: Unsize<U> {}
#[unstable(feature = "dispatch_from_dyn", issue = "0")]
-impl<T: ?Sized, U: ?Sized> DispatchFromDyn<NonNull<U>> for NonNull<T> where T: Unsize<U> { }
+impl<T: ?Sized, U: ?Sized> DispatchFromDyn<NonNull<U>> for NonNull<T> where T: Unsize<U> {}
#[stable(feature = "nonnull", since = "1.25.0")]
impl<T: ?Sized> fmt::Debug for NonNull<T> {
use crate::convert::From;
-use crate::ops::{CoerceUnsized, DispatchFromDyn};
use crate::fmt;
use crate::marker::{PhantomData, Unsize};
use crate::mem;
+use crate::ops::{CoerceUnsized, DispatchFromDyn};
use crate::ptr::NonNull;
// ignore-tidy-undocumented-unsafe
///
/// Unlike `*mut T`, `Unique<T>` is covariant over `T`. This should always be correct
/// for any type which upholds Unique's aliasing requirements.
-#[unstable(feature = "ptr_internals", issue = "0",
- reason = "use `NonNull` instead and consider `PhantomData<T>` \
- (if you also use `#[may_dangle]`), `Send`, and/or `Sync`")]
+#[unstable(
+ feature = "ptr_internals",
+ issue = "0",
+ reason = "use `NonNull` instead and consider `PhantomData<T>` \
+ (if you also use `#[may_dangle]`), `Send`, and/or `Sync`"
+)]
#[doc(hidden)]
#[repr(transparent)]
#[rustc_layout_scalar_valid_range_start(1)]
/// unenforced by the type system; the abstraction using the
/// `Unique` must enforce it.
#[unstable(feature = "ptr_internals", issue = "0")]
-unsafe impl<T: Send + ?Sized> Send for Unique<T> { }
+unsafe impl<T: Send + ?Sized> Send for Unique<T> {}
/// `Unique` pointers are `Sync` if `T` is `Sync` because the data they
/// reference is unaliased. Note that this aliasing invariant is
/// unenforced by the type system; the abstraction using the
/// `Unique` must enforce it.
#[unstable(feature = "ptr_internals", issue = "0")]
-unsafe impl<T: Sync + ?Sized> Sync for Unique<T> { }
+unsafe impl<T: Sync + ?Sized> Sync for Unique<T> {}
#[unstable(feature = "ptr_internals", issue = "0")]
impl<T: Sized> Unique<T> {
// FIXME: rename to dangling() to match NonNull?
#[inline]
pub const fn empty() -> Self {
- unsafe {
- Unique::new_unchecked(mem::align_of::<T>() as *mut T)
- }
+ unsafe { Unique::new_unchecked(mem::align_of::<T>() as *mut T) }
}
}
/// Casts to a pointer of another type.
#[inline]
pub const fn cast<U>(self) -> Unique<U> {
- unsafe {
- Unique::new_unchecked(self.as_ptr() as *mut U)
- }
+ unsafe { Unique::new_unchecked(self.as_ptr() as *mut U) }
}
}
}
#[unstable(feature = "ptr_internals", issue = "0")]
-impl<T: ?Sized> Copy for Unique<T> { }
+impl<T: ?Sized> Copy for Unique<T> {}
#[unstable(feature = "ptr_internals", issue = "0")]
-impl<T: ?Sized, U: ?Sized> CoerceUnsized<Unique<U>> for Unique<T> where T: Unsize<U> { }
+impl<T: ?Sized, U: ?Sized> CoerceUnsized<Unique<U>> for Unique<T> where T: Unsize<U> {}
#[unstable(feature = "ptr_internals", issue = "0")]
-impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Unique<U>> for Unique<T> where T: Unsize<U> { }
+impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Unique<U>> for Unique<T> where T: Unsize<U> {}
#[unstable(feature = "ptr_internals", issue = "0")]
impl<T: ?Sized> fmt::Debug for Unique<T> {
impl<T> Drop for CopyOnDrop<T> {
fn drop(&mut self) {
- unsafe { ptr::copy_nonoverlapping(self.src, self.dest, 1); }
+ unsafe {
+ ptr::copy_nonoverlapping(self.src, self.dest, 1);
+ }
}
}
/// Shifts the first element to the right until it encounters a greater or equal element.
fn shift_head<T, F>(v: &mut [T], is_less: &mut F)
- where F: FnMut(&T, &T) -> bool
+where
+ F: FnMut(&T, &T) -> bool,
{
let len = v.len();
unsafe {
// operation panics, `hole` will get dropped and automatically write the element back
// into the slice.
let mut tmp = mem::ManuallyDrop::new(ptr::read(v.get_unchecked(0)));
- let mut hole = CopyOnDrop {
- src: &mut *tmp,
- dest: v.get_unchecked_mut(1),
- };
+ let mut hole = CopyOnDrop { src: &mut *tmp, dest: v.get_unchecked_mut(1) };
ptr::copy_nonoverlapping(v.get_unchecked(1), v.get_unchecked_mut(0), 1);
for i in 2..len {
/// Shifts the last element to the left until it encounters a smaller or equal element.
fn shift_tail<T, F>(v: &mut [T], is_less: &mut F)
- where F: FnMut(&T, &T) -> bool
+where
+ F: FnMut(&T, &T) -> bool,
{
let len = v.len();
unsafe {
// operation panics, `hole` will get dropped and automatically write the element back
// into the slice.
let mut tmp = mem::ManuallyDrop::new(ptr::read(v.get_unchecked(len - 1)));
- let mut hole = CopyOnDrop {
- src: &mut *tmp,
- dest: v.get_unchecked_mut(len - 2),
- };
+ let mut hole = CopyOnDrop { src: &mut *tmp, dest: v.get_unchecked_mut(len - 2) };
ptr::copy_nonoverlapping(v.get_unchecked(len - 2), v.get_unchecked_mut(len - 1), 1);
- for i in (0..len-2).rev() {
+ for i in (0..len - 2).rev() {
if !is_less(&*tmp, v.get_unchecked(i)) {
break;
}
/// Returns `true` if the slice is sorted at the end. This function is `O(n)` worst-case.
#[cold]
fn partial_insertion_sort<T, F>(v: &mut [T], is_less: &mut F) -> bool
- where F: FnMut(&T, &T) -> bool
+where
+ F: FnMut(&T, &T) -> bool,
{
// Maximum number of adjacent out-of-order pairs that will get shifted.
const MAX_STEPS: usize = 5;
/// Sorts a slice using insertion sort, which is `O(n^2)` worst-case.
fn insertion_sort<T, F>(v: &mut [T], is_less: &mut F)
- where F: FnMut(&T, &T) -> bool
+where
+ F: FnMut(&T, &T) -> bool,
{
for i in 1..v.len() {
- shift_tail(&mut v[..i+1], is_less);
+ shift_tail(&mut v[..i + 1], is_less);
}
}
/// Sorts `v` using heapsort, which guarantees `O(n log n)` worst-case.
#[cold]
pub fn heapsort<T, F>(v: &mut [T], is_less: &mut F)
- where F: FnMut(&T, &T) -> bool
+where
+ F: FnMut(&T, &T) -> bool,
{
// This binary heap respects the invariant `parent >= child`.
let mut sift_down = |v: &mut [T], mut node| {
let right = 2 * node + 2;
// Choose the greater child.
- let greater = if right < v.len() && is_less(&v[left], &v[right]) {
- right
- } else {
- left
- };
+ let greater =
+ if right < v.len() && is_less(&v[left], &v[right]) { right } else { left };
// Stop if the invariant holds at `node`.
if greater >= v.len() || !is_less(&v[node], &v[greater]) {
};
// Build the heap in linear time.
- for i in (0 .. v.len() / 2).rev() {
+ for i in (0..v.len() / 2).rev() {
sift_down(v, i);
}
// Pop maximal elements from the heap.
- for i in (1 .. v.len()).rev() {
+ for i in (1..v.len()).rev() {
v.swap(0, i);
sift_down(&mut v[..i], 0);
}
///
/// [pdf]: http://drops.dagstuhl.de/opus/volltexte/2016/6389/pdf/LIPIcs-ESA-2016-38.pdf
fn partition_in_blocks<T, F>(v: &mut [T], pivot: &T, is_less: &mut F) -> usize
- where F: FnMut(&T, &T) -> bool
+where
+ F: FnMut(&T, &T) -> bool,
{
// Number of elements in a typical block.
const BLOCK: usize = 128;
let count = cmp::min(width(start_l, end_l), width(start_r, end_r));
if count > 0 {
- macro_rules! left { () => { l.offset(*start_l as isize) } }
- macro_rules! right { () => { r.offset(-(*start_r as isize) - 1) } }
+ macro_rules! left {
+ () => {
+ l.offset(*start_l as isize)
+ };
+ }
+ macro_rules! right {
+ () => {
+ r.offset(-(*start_r as isize) - 1)
+ };
+ }
// Instead of swapping one pair at the time, it is more efficient to perform a cyclic
// permutation. This is not strictly equivalent to swapping, but produces a similar
/// 1. Number of elements smaller than `v[pivot]`.
/// 2. True if `v` was already partitioned.
fn partition<T, F>(v: &mut [T], pivot: usize, is_less: &mut F) -> (usize, bool)
- where F: FnMut(&T, &T) -> bool
+where
+ F: FnMut(&T, &T) -> bool,
{
let (mid, was_partitioned) = {
// Place the pivot at the beginning of slice.
// Read the pivot into a stack-allocated variable for efficiency. If a following comparison
// operation panics, the pivot will be automatically written back into the slice.
let mut tmp = mem::ManuallyDrop::new(unsafe { ptr::read(pivot) });
- let _pivot_guard = CopyOnDrop {
- src: &mut *tmp,
- dest: pivot,
- };
+ let _pivot_guard = CopyOnDrop { src: &mut *tmp, dest: pivot };
let pivot = &*tmp;
// Find the first pair of out-of-order elements.
/// Returns the number of elements equal to the pivot. It is assumed that `v` does not contain
/// elements smaller than the pivot.
fn partition_equal<T, F>(v: &mut [T], pivot: usize, is_less: &mut F) -> usize
- where F: FnMut(&T, &T) -> bool
+where
+ F: FnMut(&T, &T) -> bool,
{
// Place the pivot at the beginning of slice.
v.swap(0, pivot);
// Read the pivot into a stack-allocated variable for efficiency. If a following comparison
// operation panics, the pivot will be automatically written back into the slice.
let mut tmp = mem::ManuallyDrop::new(unsafe { ptr::read(pivot) });
- let _pivot_guard = CopyOnDrop {
- src: &mut *tmp,
- dest: pivot,
- };
+ let _pivot_guard = CopyOnDrop { src: &mut *tmp, dest: pivot };
let pivot = &*tmp;
// Now partition the slice.
///
/// Elements in `v` might be reordered in the process.
fn choose_pivot<T, F>(v: &mut [T], is_less: &mut F) -> (usize, bool)
- where F: FnMut(&T, &T) -> bool
+where
+ F: FnMut(&T, &T) -> bool,
{
// Minimum length to choose the median-of-medians method.
// Shorter slices use the simple median-of-three method.
/// `limit` is the number of allowed imbalanced partitions before switching to `heapsort`. If zero,
/// this function will immediately switch to heapsort.
fn recurse<'a, T, F>(mut v: &'a mut [T], is_less: &mut F, mut pred: Option<&'a T>, mut limit: usize)
- where F: FnMut(&T, &T) -> bool
+where
+ F: FnMut(&T, &T) -> bool,
{
// Slices of up to this length get sorted using insertion sort.
const MAX_INSERTION: usize = 20;
let mid = partition_equal(v, pivot, is_less);
// Continue sorting elements greater than the pivot.
- v = &mut {v}[mid..];
+ v = &mut { v }[mid..];
continue;
}
}
was_partitioned = was_p;
// Split the slice into `left`, `pivot`, and `right`.
- let (left, right) = {v}.split_at_mut(mid);
+ let (left, right) = { v }.split_at_mut(mid);
let (pivot, right) = right.split_at_mut(1);
let pivot = &pivot[0];
/// Sorts `v` using pattern-defeating quicksort, which is `O(n log n)` worst-case.
pub fn quicksort<T, F>(v: &mut [T], mut is_less: F)
- where F: FnMut(&T, &T) -> bool
+where
+ F: FnMut(&T, &T) -> bool,
{
// Sorting has no meaningful behavior on zero-sized types.
if mem::size_of::<T>() == 0 {
recurse(v, &mut is_less, None, limit);
}
-fn partition_at_index_loop<'a, T, F>( mut v: &'a mut [T], mut index: usize, is_less: &mut F
- , mut pred: Option<&'a T>) where F: FnMut(&T, &T) -> bool
+fn partition_at_index_loop<'a, T, F>(
+ mut v: &'a mut [T],
+ mut index: usize,
+ is_less: &mut F,
+ mut pred: Option<&'a T>,
+) where
+ F: FnMut(&T, &T) -> bool,
{
loop {
// For slices of up to this length it's probably faster to simply sort them.
let (mid, _) = partition(v, pivot, is_less);
// Split the slice into `left`, `pivot`, and `right`.
- let (left, right) = {v}.split_at_mut(mid);
+ let (left, right) = { v }.split_at_mut(mid);
let (pivot, right) = right.split_at_mut(1);
let pivot = &pivot[0];
}
}
-pub fn partition_at_index<T, F>(v: &mut [T], index: usize, mut is_less: F)
- -> (&mut [T], &mut T, &mut [T]) where F: FnMut(&T, &T) -> bool
+pub fn partition_at_index<T, F>(
+ v: &mut [T],
+ index: usize,
+ mut is_less: F,
+) -> (&mut [T], &mut T, &mut [T])
+where
+ F: FnMut(&T, &T) -> bool,
{
- use cmp::Ordering::Less;
use cmp::Ordering::Greater;
+ use cmp::Ordering::Less;
if index >= v.len() {
panic!("partition_at_index index {} greater than length of slice {}", index, v.len());
} else if index == v.len() - 1 {
// Find max element and place it in the last position of the array. We're free to use
// `unwrap()` here because we know v must not be empty.
- let (max_index, _) = v.iter().enumerate().max_by(
- |&(_, x), &(_, y)| if is_less(x, y) { Less } else { Greater }).unwrap();
+ let (max_index, _) = v
+ .iter()
+ .enumerate()
+ .max_by(|&(_, x), &(_, y)| if is_less(x, y) { Less } else { Greater })
+ .unwrap();
v.swap(max_index, index);
} else if index == 0 {
// Find min element and place it in the first position of the array. We're free to use
// `unwrap()` here because we know v must not be empty.
- let (min_index, _) = v.iter().enumerate().min_by(
- |&(_, x), &(_, y)| if is_less(x, y) { Less } else { Greater }).unwrap();
+ let (min_index, _) = v
+ .iter()
+ .enumerate()
+ .min_by(|&(_, x), &(_, y)| if is_less(x, y) { Less } else { Greater })
+ .unwrap();
v.swap(min_index, index);
} else {
partition_at_index_loop(v, index, &mut is_less, None);
mod wake;
#[stable(feature = "futures_api", since = "1.36.0")]
-pub use self::wake::{Context, Waker, RawWaker, RawWakerVTable};
+pub use self::wake::{Context, RawWaker, RawWakerVTable, Waker};
pub enum Poll<T> {
/// Represents that a value is immediately ready.
#[stable(feature = "futures_api", since = "1.36.0")]
- Ready(
- #[stable(feature = "futures_api", since = "1.36.0")]
- T
- ),
+ Ready(#[stable(feature = "futures_api", since = "1.36.0")] T),
/// Represents that a value is not ready yet.
///
/// Changes the ready value of this `Poll` with the closure provided.
#[stable(feature = "futures_api", since = "1.36.0")]
pub fn map<U, F>(self, f: F) -> Poll<U>
- where F: FnOnce(T) -> U
+ where
+ F: FnOnce(T) -> U,
{
match self {
Poll::Ready(t) => Poll::Ready(f(t)),
/// Changes the success value of this `Poll` with the closure provided.
#[stable(feature = "futures_api", since = "1.36.0")]
pub fn map_ok<U, F>(self, f: F) -> Poll<Result<U, E>>
- where F: FnOnce(T) -> U
+ where
+ F: FnOnce(T) -> U,
{
match self {
Poll::Ready(Ok(t)) => Poll::Ready(Ok(f(t))),
/// Changes the error value of this `Poll` with the closure provided.
#[stable(feature = "futures_api", since = "1.36.0")]
pub fn map_err<U, F>(self, f: F) -> Poll<Result<T, U>>
- where F: FnOnce(E) -> U
+ where
+ F: FnOnce(E) -> U,
{
match self {
Poll::Ready(Ok(t)) => Poll::Ready(Ok(t)),
/// Changes the success value of this `Poll` with the closure provided.
#[unstable(feature = "poll_map", issue = "63514")]
pub fn map_ok<U, F>(self, f: F) -> Poll<Option<Result<U, E>>>
- where F: FnOnce(T) -> U
+ where
+ F: FnOnce(T) -> U,
{
match self {
Poll::Ready(Some(Ok(t))) => Poll::Ready(Some(Ok(f(t)))),
/// Changes the error value of this `Poll` with the closure provided.
#[unstable(feature = "poll_map", issue = "63514")]
pub fn map_err<U, F>(self, f: F) -> Poll<Option<Result<T, U>>>
- where F: FnOnce(E) -> U
+ where
+ F: FnOnce(E) -> U,
{
match self {
Poll::Ready(Some(Ok(t))) => Poll::Ready(Some(Ok(t))),
#[rustc_promotable]
#[stable(feature = "futures_api", since = "1.36.0")]
pub const fn new(data: *const (), vtable: &'static RawWakerVTable) -> RawWaker {
- RawWaker {
- data,
- vtable,
- }
+ RawWaker { data, vtable }
}
}
wake_by_ref: unsafe fn(*const ()),
drop: unsafe fn(*const ()),
) -> Self {
- Self {
- clone,
- wake,
- wake_by_ref,
- drop,
- }
+ Self { clone, wake, wake_by_ref, drop }
}
}
#[stable(feature = "futures_api", since = "1.36.0")]
#[inline]
pub fn from_waker(waker: &'a Waker) -> Self {
- Context {
- waker,
- _marker: PhantomData,
- }
+ Context { waker, _marker: PhantomData }
}
/// Returns a reference to the `Waker` for the current task.
#[stable(feature = "futures_api", since = "1.36.0")]
impl fmt::Debug for Context<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("Context")
- .field("waker", &self.waker)
- .finish()
+ f.debug_struct("Context").field("waker", &self.waker).finish()
}
}
#[inline]
#[stable(feature = "futures_api", since = "1.36.0")]
pub unsafe fn from_raw(waker: RawWaker) -> Waker {
- Waker {
- waker,
- }
+ Waker { waker }
}
}
//! assert_eq!(Duration::new(5, 0), Duration::from_secs(5));
//! ```
-use crate::{fmt, u64};
use crate::iter::Sum;
-use crate::ops::{Add, Sub, Mul, Div, AddAssign, SubAssign, MulAssign, DivAssign};
+use crate::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
+use crate::{fmt, u64};
const NANOS_PER_SEC: u32 = 1_000_000_000;
const NANOS_PER_MILLI: u32 = 1_000_000;
#[stable(feature = "duration", since = "1.3.0")]
#[inline]
pub fn new(secs: u64, nanos: u32) -> Duration {
- let secs = secs.checked_add((nanos / NANOS_PER_SEC) as u64)
- .expect("overflow in Duration::new");
+ let secs =
+ secs.checked_add((nanos / NANOS_PER_SEC) as u64).expect("overflow in Duration::new");
let nanos = nanos % NANOS_PER_SEC;
Duration { secs, nanos }
}
/// [`subsec_nanos`]: #method.subsec_nanos
#[stable(feature = "duration", since = "1.3.0")]
#[inline]
- pub const fn as_secs(&self) -> u64 { self.secs }
+ pub const fn as_secs(&self) -> u64 {
+ self.secs
+ }
/// Returns the fractional part of this `Duration`, in whole milliseconds.
///
/// ```
#[stable(feature = "duration_extras", since = "1.27.0")]
#[inline]
- pub const fn subsec_millis(&self) -> u32 { self.nanos / NANOS_PER_MILLI }
+ pub const fn subsec_millis(&self) -> u32 {
+ self.nanos / NANOS_PER_MILLI
+ }
/// Returns the fractional part of this `Duration`, in whole microseconds.
///
/// ```
#[stable(feature = "duration_extras", since = "1.27.0")]
#[inline]
- pub const fn subsec_micros(&self) -> u32 { self.nanos / NANOS_PER_MICRO }
+ pub const fn subsec_micros(&self) -> u32 {
+ self.nanos / NANOS_PER_MICRO
+ }
/// Returns the fractional part of this `Duration`, in nanoseconds.
///
/// ```
#[stable(feature = "duration", since = "1.3.0")]
#[inline]
- pub const fn subsec_nanos(&self) -> u32 { self.nanos }
+ pub const fn subsec_nanos(&self) -> u32 {
+ self.nanos
+ }
/// Returns the total number of whole milliseconds contained by this `Duration`.
///
}
}
debug_assert!(nanos < NANOS_PER_SEC);
- Some(Duration {
- secs,
- nanos,
- })
+ Some(Duration { secs, nanos })
} else {
None
}
let total_nanos = self.nanos as u64 * rhs as u64;
let extra_secs = total_nanos / (NANOS_PER_SEC as u64);
let nanos = (total_nanos % (NANOS_PER_SEC as u64)) as u32;
- if let Some(secs) = self.secs
- .checked_mul(rhs as u64)
- .and_then(|s| s.checked_add(extra_secs)) {
+ if let Some(secs) =
+ self.secs.checked_mul(rhs as u64).and_then(|s| s.checked_add(extra_secs))
+ {
debug_assert!(nanos < NANOS_PER_SEC);
- Some(Duration {
- secs,
- nanos,
- })
+ Some(Duration { secs, nanos })
} else {
None
}
#[stable(feature = "duration_float", since = "1.38.0")]
#[inline]
pub fn from_secs_f64(secs: f64) -> Duration {
- const MAX_NANOS_F64: f64 =
- ((u64::MAX as u128 + 1)*(NANOS_PER_SEC as u128)) as f64;
- let nanos = secs * (NANOS_PER_SEC as f64);
+ const MAX_NANOS_F64: f64 = ((u64::MAX as u128 + 1) * (NANOS_PER_SEC as u128)) as f64;
+ let nanos = secs * (NANOS_PER_SEC as f64);
if !nanos.is_finite() {
panic!("got non-finite value when converting float to duration");
}
if nanos < 0.0 {
panic!("underflow when converting float to duration");
}
- let nanos = nanos as u128;
+ let nanos = nanos as u128;
Duration {
secs: (nanos / (NANOS_PER_SEC as u128)) as u64,
nanos: (nanos % (NANOS_PER_SEC as u128)) as u32,
#[stable(feature = "duration_float", since = "1.38.0")]
#[inline]
pub fn from_secs_f32(secs: f32) -> Duration {
- const MAX_NANOS_F32: f32 =
- ((u64::MAX as u128 + 1)*(NANOS_PER_SEC as u128)) as f32;
- let nanos = secs * (NANOS_PER_SEC as f32);
+ const MAX_NANOS_F32: f32 = ((u64::MAX as u128 + 1) * (NANOS_PER_SEC as u128)) as f32;
+ let nanos = secs * (NANOS_PER_SEC as f32);
if !nanos.is_finite() {
panic!("got non-finite value when converting float to duration");
}
if nanos < 0.0 {
panic!("underflow when converting float to duration");
}
- let nanos = nanos as u128;
+ let nanos = nanos as u128;
Duration {
secs: (nanos / (NANOS_PER_SEC as u128)) as u64,
nanos: (nanos % (NANOS_PER_SEC as u128)) as u32,
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_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 => {
.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,
- }
+ 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 {
+ fn sum<I: Iterator<Item = Duration>>(iter: I) -> Duration {
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 {
+ fn sum<I: Iterator<Item = &'a Duration>>(iter: I) -> Duration {
sum_durations!(iter)
}
}
} else {
// SAFETY: We are only writing ASCII digits into the buffer and it was
// initialized with '0's, so it contains valid UTF8.
- let s = unsafe {
- crate::str::from_utf8_unchecked(&buf[..end])
- };
+ let s = unsafe { crate::str::from_utf8_unchecked(&buf[..end]) };
// If the user request a precision > 9, we pad '0's at the end.
let w = f.precision().unwrap_or(pos);
// See src/libstd/primitive_docs.rs for documentation.
-use crate::cmp::*;
use crate::cmp::Ordering::*;
+use crate::cmp::*;
// macro for implementing n-ary tuple functions and operations
macro_rules! tuple_impls {
/// non-BMP range of most Unicode sets.
pub struct BoolTrie {
// 0..0x800 (corresponding to 1 and 2 byte utf-8 sequences)
- pub r1: [u64; 32], // leaves
+ pub r1: [u64; 32], // leaves
// 0x800..0x10000 (corresponding to 3 byte utf-8 sequences)
pub r2: [u8; 992], // first level
- pub r3: &'static [u64], // leaves
+ pub r3: &'static [u64], // leaves
// 0x10000..0x110000 (corresponding to 4 byte utf-8 sequences)
- pub r4: [u8; 256], // first level
- pub r5: &'static [u8], // second level
- pub r6: &'static [u64], // leaves
+ pub r4: [u8; 256], // first level
+ pub r5: &'static [u8], // second level
+ pub r6: &'static [u64], // leaves
}
impl BoolTrie {
pub fn lookup(&self, c: char) -> bool {
pub struct SmallBoolTrie {
pub(crate) r1: &'static [u8], // first level
- pub(crate) r2: &'static [u64], // leaves
+ pub(crate) r2: &'static [u64], // leaves
}
impl SmallBoolTrie {
/// ```
#[stable(feature = "unit_from_iter", since = "1.23.0")]
impl FromIterator<()> for () {
- fn from_iter<I: IntoIterator<Item=()>>(iter: I) -> Self {
+ fn from_iter<I: IntoIterator<Item = ()>>(iter: I) -> Self {
iter.into_iter().for_each(|()| {})
}
}
&self,
err: &mut DiagnosticBuilder<'_>,
terr: &TypeError<'tcx>,
- sp: Span,
) {
use hir::def_id::CrateNum;
use hir::map::DisambiguatedDefPathData;
};
if same_path().unwrap_or(false) {
let crate_name = self.tcx.crate_name(did1.krate);
- err.span_note(
- sp,
- &format!(
- "Perhaps two different versions \
- of crate `{}` are being used?",
- crate_name
- ),
- );
+ err.note(&format!(
+ "perhaps two different versions of crate `{}` are being used?",
+ crate_name
+ ));
}
}
};
.unwrap_or_else(|| {
self.tcx.hir().body_owner_def_id(hir::BodyId { hir_id: cause.body_id })
});
- self.check_and_note_conflicting_crates(diag, terr, span);
+ self.check_and_note_conflicting_crates(diag, terr);
self.tcx.note_and_explain_type_err(diag, terr, span, body_owner_def_id);
// It reads better to have the error origin as the final
}
}
-#[derive(Clone, Copy, Eq, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Copy, Eq, PartialEq, RustcEncodable, RustcDecodable, HashStable, Hash)]
pub enum ScalarMaybeUndef<Tag = (), Id = AllocId> {
Scalar(Scalar<Tag, Id>),
Undef,
/// This is used for the "rust-call" ABI.
pub spread_arg: Option<Local>,
- /// Names and capture modes of all the closure upvars, assuming
- /// the first argument is either the closure or a reference to it.
- //
- // NOTE(eddyb) This is *strictly* a temporary hack for codegen
- // debuginfo generation, and will be removed at some point.
- // Do **NOT** use it for anything else; upvar information should not be
- // in the MIR, so please rely on local crate HIR or other side-channels.
- pub __upvar_debuginfo_codegen_only_do_not_use: Vec<UpvarDebuginfo>,
+ /// Debug information pertaining to user variables, including captures.
+ pub var_debug_info: Vec<VarDebugInfo<'tcx>>,
/// Mark this MIR of a const context other than const functions as having converted a `&&` or
/// `||` expression into `&` or `|` respectively. This is problematic because if we ever stop
basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
source_scopes: IndexVec<SourceScope, SourceScopeData>,
source_scope_local_data: ClearCrossCrate<IndexVec<SourceScope, SourceScopeLocalData>>,
- yield_ty: Option<Ty<'tcx>>,
local_decls: LocalDecls<'tcx>,
user_type_annotations: CanonicalUserTypeAnnotations<'tcx>,
arg_count: usize,
- __upvar_debuginfo_codegen_only_do_not_use: Vec<UpvarDebuginfo>,
+ var_debug_info: Vec<VarDebugInfo<'tcx>>,
span: Span,
control_flow_destroyed: Vec<(Span, String)>,
) -> Self {
basic_blocks,
source_scopes,
source_scope_local_data,
- yield_ty,
+ yield_ty: None,
generator_drop: None,
generator_layout: None,
local_decls,
user_type_annotations,
arg_count,
- __upvar_debuginfo_codegen_only_do_not_use,
spread_arg: None,
+ var_debug_info,
span,
cache: cache::Cache::new(),
control_flow_destroyed,
LocalKind::ReturnPointer
} else if index < self.arg_count + 1 {
LocalKind::Arg
- } else if self.local_decls[local].name.is_some() {
+ } else if self.local_decls[local].is_user_variable() {
LocalKind::Var
} else {
LocalKind::Temp
// FIXME(matthewjasper) Don't store in this in `Body`
pub user_ty: UserTypeProjections,
- /// The name of the local, used in debuginfo and pretty-printing.
- ///
- /// Note that function arguments can also have this set to `Some(_)`
- /// to generate better debuginfo.
- pub name: Option<Name>,
-
/// The *syntactic* (i.e., not visibility) source scope the local is defined
/// in. If the local was defined in a let-statement, this
/// is *within* the let-statement, rather than outside
/// `drop(x)`, we want it to refer to `x: u32`.
///
/// To allow both uses to work, we need to have more than a single scope
- /// for a local. We have the `source_info.scope` represent the
- /// "syntactic" lint scope (with a variable being under its let
- /// block) while the `visibility_scope` represents the "local variable"
+ /// for a local. We have the `source_info.scope` represent the "syntactic"
+ /// lint scope (with a variable being under its let block) while the
+ /// `var_debug_info.source_info.scope` represents the "local variable"
/// scope (where the "rest" of a block is under all prior let-statements).
///
/// The end result looks like this:
/// │ │
/// │ │ │{ let y: u32 }
/// │ │ │
- /// │ │ │← y.visibility_scope
+ /// │ │ │← y.var_debug_info.source_info.scope
/// │ │ │← `y + 2`
/// │
/// │ │{ let x: u32 }
- /// │ │← x.visibility_scope
+ /// │ │← x.var_debug_info.source_info.scope
/// │ │← `drop(x)` // This accesses `x: u32`.
/// ```
pub source_info: SourceInfo,
-
- /// Source scope within which the local is visible (for debuginfo)
- /// (see `source_info` for more details).
- pub visibility_scope: SourceScope,
}
/// Extra information about a local that's used for diagnostics.
mutability,
ty,
user_ty: UserTypeProjections::none(),
- name: None,
source_info: SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE },
- visibility_scope: OUTERMOST_SOURCE_SCOPE,
internal,
local_info: LocalInfo::Other,
is_block_tail: None,
ty: return_ty,
user_ty: UserTypeProjections::none(),
source_info: SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE },
- visibility_scope: OUTERMOST_SOURCE_SCOPE,
internal: false,
is_block_tail: None,
- name: None, // FIXME maybe we do want some name here?
local_info: LocalInfo::Other,
}
}
}
-/// A closure capture, with its name and mode.
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
-pub struct UpvarDebuginfo {
- pub debug_name: Name,
+/// Debug information pertaining to a user variable.
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+pub struct VarDebugInfo<'tcx> {
+ pub name: Name,
- /// If true, the capture is behind a reference.
- pub by_ref: bool,
+ /// Source info of the user variable, including the scope
+ /// within which the variable is visible (to debuginfo)
+ /// (see `LocalDecl`'s `source_info` field for more details).
+ pub source_info: SourceInfo,
+
+ /// Where the data for this user variable is to be found.
+ /// NOTE(eddyb) There's an unenforced invariant that this `Place` is
+ /// based on a `Local`, not a `Static`, and contains no indexing.
+ pub place: Place<'tcx>,
}
///////////////////////////////////////////////////////////////////////////
/// have conflicts with each other are allowed to overlap in the computed
/// layout.
pub storage_conflicts: BitMatrix<GeneratorSavedLocal, GeneratorSavedLocal>,
-
- /// The names and scopes of all the stored generator locals.
- ///
- /// N.B., this is *strictly* a temporary hack for codegen
- /// debuginfo generation, and will be removed at some point.
- /// Do **NOT** use it for anything else, local information should not be
- /// in the MIR, please rely on local crate HIR or other side-channels.
- //
- // FIXME(tmandry): see above.
- pub __local_debuginfo_codegen_only_do_not_use: IndexVec<GeneratorSavedLocal, LocalDecl<'tcx>>,
}
#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
MirPhase,
Mutability,
SourceInfo,
- UpvarDebuginfo,
FakeReadCause,
RetagKind,
SourceScope,
self.super_local_decl(local, local_decl);
}
+ fn visit_var_debug_info(&mut self,
+ var_debug_info: & $($mutability)* VarDebugInfo<'tcx>) {
+ self.super_var_debug_info(var_debug_info);
+ }
+
fn visit_local(&mut self,
_local: & $($mutability)? Local,
_context: PlaceContext,
);
}
+ for var_debug_info in &$($mutability)? body.var_debug_info {
+ self.visit_var_debug_info(var_debug_info);
+ }
+
self.visit_span(&$($mutability)? body.span);
}
mutability: _,
ty,
user_ty,
- name: _,
source_info,
- visibility_scope,
internal: _,
local_info: _,
is_block_tail: _,
self.visit_user_type_projection(user_ty);
}
self.visit_source_info(source_info);
- self.visit_source_scope(visibility_scope);
+ }
+
+ fn super_var_debug_info(&mut self,
+ var_debug_info: & $($mutability)? VarDebugInfo<'tcx>) {
+ let VarDebugInfo {
+ name: _,
+ source_info,
+ place,
+ } = var_debug_info;
+
+ self.visit_source_info(source_info);
+ let location = START_BLOCK.start_location();
+ self.visit_place(
+ place,
+ PlaceContext::NonUse(NonUseContext::VarDebugInfo),
+ location,
+ );
}
fn super_source_scope(&mut self,
StorageDead,
/// User type annotation assertions for NLL.
AscribeUserTy,
+ /// The data of an user variable, for debug info.
+ VarDebugInfo,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
use rustc_target::spec::{Target, TargetTriple};
use syntax;
-use syntax::ast::{self, IntTy, UintTy};
+use syntax::ast;
use syntax::source_map::{FileName, FilePathMapping};
use syntax::edition::{Edition, EDITION_NAME_LIST, DEFAULT_EDITION};
use syntax::symbol::{sym, Symbol};
pub struct Config {
pub target: Target,
- pub isize_ty: IntTy,
- pub usize_ty: UintTy,
+ pub ptr_width: u32,
}
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
FatalError.raise();
});
- let (isize_ty, usize_ty) = match &target.target_pointer_width[..] {
- "16" => (ast::IntTy::I16, ast::UintTy::U16),
- "32" => (ast::IntTy::I32, ast::UintTy::U32),
- "64" => (ast::IntTy::I64, ast::UintTy::U64),
+ let ptr_width = match &target.target_pointer_width[..] {
+ "16" => 16,
+ "32" => 32,
+ "64" => 64,
w => sp.fatal(&format!(
"target specification was invalid: \
unrecognized target-pointer-width {}",
Config {
target,
- isize_ty,
- usize_ty,
+ ptr_width,
}
}
body_id: Option<hir::BodyId>,
fallback_has_occurred: bool,
) {
- debug!("report_fulfillment_errors({:?})", error);
+ debug!("report_fulfillment_error({:?})", error);
match error.code {
FulfillmentErrorCode::CodeSelectionError(ref selection_error) => {
self.report_selection_error(
use std::time::{Duration, Instant};
use syntax::symbol::{Symbol, sym};
-use rustc_macros::HashStable;
use crate::session::Session;
#[cfg(test)]
// The name of the associated type for `Fn` return types.
pub const FN_OUTPUT_NAME: Symbol = sym::Output;
-// Useful type to use with `Result<>` indicate that an error has already
-// been reported to the user, so no need to continue checking.
-#[derive(Clone, Copy, Debug, RustcEncodable, RustcDecodable, HashStable)]
-pub struct ErrorReported;
+pub use errors::ErrorReported;
thread_local!(static TIME_DEPTH: Cell<usize> = Cell::new(0));
use rustc::ty::{Int, Uint};
let new_kind = match ty.kind {
- Int(Isize) => Int(self.tcx.sess.target.isize_ty),
- Uint(Usize) => Uint(self.tcx.sess.target.usize_ty),
+ Int(t @ Isize) => Int(t.normalize(self.tcx.sess.target.ptr_width)),
+ Uint(t @ Usize) => Uint(t.normalize(self.tcx.sess.target.ptr_width)),
ref t @ Uint(_) | ref t @ Int(_) => t.clone(),
_ => panic!("tried to get overflow intrinsic for op applied to non-int type")
};
ref attrs, span, kind: hir::ItemKind::Static(..), ..
}) => {
let sym_str = sym.as_str();
- if self.get_declared_value(&sym_str).is_some() {
- span_bug!(span, "Conflicting symbol names for static?");
+ if let Some(g) = self.get_declared_value(&sym_str) {
+ if self.val_ty(g) != self.type_ptr_to(llty) {
+ span_bug!(span, "Conflicting types for static");
+ }
}
- let g = self.define_global(&sym_str, llty).unwrap();
+ let g = self.declare_global(&sym_str, llty);
if !self.tcx.is_reachable_non_generic(def_id) {
unsafe {
) {
// Find all the scopes with variables defined in them.
let mut has_variables = BitSet::new_empty(mir.source_scopes.len());
- // FIXME(eddyb) base this on `decl.name`, or even better, on debuginfo.
// FIXME(eddyb) take into account that arguments always have debuginfo,
// irrespective of their name (assuming full debuginfo is enabled).
- for var in mir.vars_iter() {
- let decl = &mir.local_decls[var];
- has_variables.insert(decl.visibility_scope);
+ for var_debug_info in &mir.var_debug_info {
+ has_variables.insert(var_debug_info.source_info.scope);
}
// Instantiate all scopes.
use crate::value::Value;
use rustc_codegen_ssa::traits::*;
+use rustc_index::vec::{Idx, IndexVec};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc::hir::CodegenFnAttrFlags;
use rustc::hir::def::CtorKind;
use rustc::hir::def_id::{DefId, CrateNum, LOCAL_CRATE};
use rustc::ich::NodeIdHashingMode;
-use rustc::mir::Field;
-use rustc::mir::GeneratorLayout;
+use rustc::mir::{self, Field, GeneratorLayout};
use rustc::mir::interpret::truncate;
use rustc_data_structures::fingerprint::Fingerprint;
use rustc::ty::Instance;
|| llvm_util::get_major_version() < 8;
}
+// FIXME(eddyb) maybe precompute this? Right now it's computed once
+// per generator monomorphization, but it doesn't depend on substs.
+fn generator_layout_and_saved_local_names(
+ tcx: TyCtxt<'tcx>,
+ def_id: DefId,
+) -> (&'tcx GeneratorLayout<'tcx>, IndexVec<mir::GeneratorSavedLocal, Option<ast::Name>>) {
+ let body = tcx.optimized_mir(def_id);
+ let generator_layout = body.generator_layout.as_ref().unwrap();
+ let mut generator_saved_local_names =
+ IndexVec::from_elem(None, &generator_layout.field_tys);
+
+ let state_arg = mir::PlaceBase::Local(mir::Local::new(1));
+ for var in &body.var_debug_info {
+ if var.place.base != state_arg {
+ continue;
+ }
+ match var.place.projection[..] {
+ [
+ // Deref of the `Pin<&mut Self>` state argument.
+ mir::ProjectionElem::Field(..),
+ mir::ProjectionElem::Deref,
+
+ // Field of a variant of the state.
+ mir::ProjectionElem::Downcast(_, variant),
+ mir::ProjectionElem::Field(field, _),
+ ] => {
+ let name = &mut generator_saved_local_names[
+ generator_layout.variant_fields[variant][field]
+ ];
+ if name.is_none() {
+ name.replace(var.name);
+ }
+ }
+ _ => {}
+ }
+ }
+ (generator_layout, generator_saved_local_names)
+}
+
/// Describes the members of an enum value; an enum is described as a union of
/// structs in DWARF. This `MemberDescriptionFactory` provides the description for
/// the members of this union; so for every variant of the given enum, this
impl EnumMemberDescriptionFactory<'ll, 'tcx> {
fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>)
-> Vec<MemberDescription<'ll>> {
+ let generator_variant_info_data = match self.enum_type.kind {
+ ty::Generator(def_id, ..) => {
+ Some(generator_layout_and_saved_local_names(cx.tcx, def_id))
+ }
+ _ => None,
+ };
+
let variant_info_for = |index: VariantIdx| {
- match &self.enum_type.kind {
+ match self.enum_type.kind {
ty::Adt(adt, _) => VariantInfo::Adt(&adt.variants[index]),
- ty::Generator(def_id, substs, _) => {
- let generator_layout = cx.tcx.generator_layout(*def_id);
- VariantInfo::Generator(substs, generator_layout, index)
+ ty::Generator(_, substs, _) => {
+ let (generator_layout, generator_saved_local_names) =
+ generator_variant_info_data.as_ref().unwrap();
+ VariantInfo::Generator {
+ substs,
+ generator_layout: *generator_layout,
+ generator_saved_local_names,
+ variant_index: index,
+ }
}
_ => bug!(),
}
}
#[derive(Copy, Clone)]
-enum VariantInfo<'tcx> {
+enum VariantInfo<'a, 'tcx> {
Adt(&'tcx ty::VariantDef),
- Generator(SubstsRef<'tcx>, &'tcx GeneratorLayout<'tcx>, VariantIdx),
+ Generator {
+ substs: SubstsRef<'tcx>,
+ generator_layout: &'tcx GeneratorLayout<'tcx>,
+ generator_saved_local_names: &'a IndexVec<mir::GeneratorSavedLocal, Option<ast::Name>>,
+ variant_index: VariantIdx,
+ },
}
-impl<'tcx> VariantInfo<'tcx> {
+impl<'tcx> VariantInfo<'_, 'tcx> {
fn map_struct_name<R>(&self, f: impl FnOnce(&str) -> R) -> R {
match self {
VariantInfo::Adt(variant) => f(&variant.ident.as_str()),
- VariantInfo::Generator(substs, _, variant_index) =>
+ VariantInfo::Generator { substs, variant_index, .. } =>
f(&substs.as_generator().variant_name(*variant_index)),
}
}
fn variant_name(&self) -> String {
match self {
VariantInfo::Adt(variant) => variant.ident.to_string(),
- VariantInfo::Generator(_, _, variant_index) => {
+ VariantInfo::Generator { variant_index, .. } => {
// Since GDB currently prints out the raw discriminant along
// with every variant, make each variant name be just the value
// of the discriminant. The struct name for the variant includes
}
fn field_name(&self, i: usize) -> String {
- let field_name = match self {
+ let field_name = match *self {
VariantInfo::Adt(variant) if variant.ctor_kind != CtorKind::Fn =>
- Some(variant.fields[i].ident.to_string()),
- VariantInfo::Generator(_, generator_layout, variant_index) => {
- let field = generator_layout.variant_fields[*variant_index][i.into()];
- let decl = &generator_layout.__local_debuginfo_codegen_only_do_not_use[field];
- decl.name.map(|name| name.to_string())
- }
+ Some(variant.fields[i].ident.name),
+ VariantInfo::Generator {
+ generator_layout,
+ generator_saved_local_names,
+ variant_index,
+ ..
+ } => generator_saved_local_names[
+ generator_layout.variant_fields[variant_index][i.into()]
+ ],
_ => None,
};
- field_name.unwrap_or_else(|| format!("__{}", i))
+ field_name.map(|name| name.to_string()).unwrap_or_else(|| format!("__{}", i))
}
}
fn describe_enum_variant(
cx: &CodegenCx<'ll, 'tcx>,
layout: layout::TyLayout<'tcx>,
- variant: VariantInfo<'tcx>,
+ variant: VariantInfo<'_, 'tcx>,
discriminant_info: EnumDiscriminantInfo<'ll>,
containing_scope: &'ll DIScope,
span: Span,
fn int_type_width_signed(ty: Ty<'_>, cx: &CodegenCx<'_, '_>) -> Option<(u64, bool)> {
match ty.kind {
ty::Int(t) => Some((match t {
- ast::IntTy::Isize => cx.tcx.sess.target.isize_ty.bit_width().unwrap() as u64,
+ ast::IntTy::Isize => cx.tcx.sess.target.ptr_width as u64,
ast::IntTy::I8 => 8,
ast::IntTy::I16 => 16,
ast::IntTy::I32 => 32,
ast::IntTy::I128 => 128,
}, true)),
ty::Uint(t) => Some((match t {
- ast::UintTy::Usize => cx.tcx.sess.target.usize_ty.bit_width().unwrap() as u64,
+ ast::UintTy::Usize => cx.tcx.sess.target.ptr_width as u64,
ast::UintTy::U8 => 8,
ast::UintTy::U16 => 16,
ast::UintTy::U32 => 32,
use rustc_data_structures::graph::dominators::Dominators;
use rustc_index::vec::{Idx, IndexVec};
use rustc::mir::{self, Location, TerminatorKind};
-use rustc::mir::visit::{Visitor, PlaceContext, MutatingUseContext, NonMutatingUseContext};
+use rustc::mir::visit::{
+ Visitor, PlaceContext, MutatingUseContext, NonMutatingUseContext, NonUseContext,
+};
use rustc::mir::traversal;
use rustc::session::config::DebugInfo;
use rustc::ty;
// FIXME(eddyb): We should figure out how to use llvm.dbg.value instead
// of putting everything in allocas just so we can use llvm.dbg.declare.
if fx.cx.sess().opts.debuginfo == DebugInfo::Full {
- if mir.local_kind(local) == mir::LocalKind::Arg || decl.name.is_some() {
+ if mir.local_kind(local) == mir::LocalKind::Arg {
analyzer.not_ssa(local);
continue;
}
let cx = self.fx.cx;
if let [proj_base @ .., elem] = place_ref.projection {
+ let mut base_context = if context.is_mutating_use() {
+ PlaceContext::MutatingUse(MutatingUseContext::Projection)
+ } else {
+ PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
+ };
+
// Allow uses of projections that are ZSTs or from scalar fields.
let is_consume = match context {
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) |
// Recurse with the same context, instead of `Projection`,
// potentially stopping at non-operand projections,
// which would trigger `not_ssa` on locals.
- self.process_place(
- &mir::PlaceRef {
- base: place_ref.base,
- projection: proj_base,
- },
- context,
- location,
- );
- return;
+ base_context = context;
}
}
}
- // A deref projection only reads the pointer, never needs the place.
if let mir::ProjectionElem::Deref = elem {
- self.process_place(
- &mir::PlaceRef {
- base: place_ref.base,
- projection: proj_base,
- },
+ // Deref projections typically only read the pointer.
+ // (the exception being `VarDebugInfo` contexts, handled below)
+ base_context = PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy);
+
+ // Indirect debuginfo requires going through memory, that only
+ // the debugger accesses, following our emitted DWARF pointer ops.
+ //
+ // FIXME(eddyb) Investigate the possibility of relaxing this, but
+ // note that `llvm.dbg.declare` *must* be used for indirect places,
+ // even if we start using `llvm.dbg.value` for all other cases,
+ // as we don't necessarily know when the value changes, but only
+ // where it lives in memory.
+ //
+ // It's possible `llvm.dbg.declare` could support starting from
+ // a pointer that doesn't point to an `alloca`, but this would
+ // only be useful if we know the pointer being `Deref`'d comes
+ // from an immutable place, and if `llvm.dbg.declare` calls
+ // must be at the very start of the function, then only function
+ // arguments could contain such pointers.
+ if context == PlaceContext::NonUse(NonUseContext::VarDebugInfo) {
+ // We use `NonUseContext::VarDebugInfo` for the base,
+ // which might not force the base local to memory,
+ // so we have to do it manually.
+ if let mir::PlaceBase::Local(local) = place_ref.base {
+ self.visit_local(&local, context, location);
+ }
+ }
+ }
+
+ // `NonUseContext::VarDebugInfo` needs to flow all the
+ // way down to the base local (see `visit_local`).
+ if context == PlaceContext::NonUse(NonUseContext::VarDebugInfo) {
+ base_context = context;
+ }
+
+ self.process_place(
+ &mir::PlaceRef {
+ base: place_ref.base,
+ projection: proj_base,
+ },
+ base_context,
+ location
+ );
+ // HACK(eddyb) this emulates the old `visit_projection_elem`, this
+ // entire `visit_place`-like `process_place` method should be rewritten,
+ // now that we have moved to the "slice of projections" representation.
+ if let mir::ProjectionElem::Index(local) = elem {
+ self.visit_local(
+ local,
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
location
);
- return;
}
- }
+ } else {
+ // FIXME this is super_place code, is repeated here to avoid cloning place or changing
+ // visit_place API
+ let mut context = context;
- // FIXME this is super_place code, is repeated here to avoid cloning place or changing
- // visit_place API
- let mut context = context;
+ if !place_ref.projection.is_empty() {
+ context = if context.is_mutating_use() {
+ PlaceContext::MutatingUse(MutatingUseContext::Projection)
+ } else {
+ PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
+ };
+ }
- if !place_ref.projection.is_empty() {
- context = if context.is_mutating_use() {
- PlaceContext::MutatingUse(MutatingUseContext::Projection)
- } else {
- PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
- };
+ self.visit_place_base(place_ref.base, context, location);
+ self.visit_projection(place_ref.base, place_ref.projection, context, location);
}
-
- self.visit_place_base(place_ref.base, context, location);
- self.visit_projection(place_ref.base, place_ref.projection, context, location);
}
}
self.assign(local, location);
}
+ PlaceContext::NonUse(NonUseContext::VarDebugInfo) => {
+ // We need to keep locals in `alloca`s for debuginfo.
+ // FIXME(eddyb): We should figure out how to use `llvm.dbg.value` instead
+ // of putting everything in allocas just so we can use `llvm.dbg.declare`.
+ if self.fx.cx.sess().opts.debuginfo == DebugInfo::Full {
+ self.not_ssa(local);
+ }
+ }
+
PlaceContext::NonUse(_) |
PlaceContext::MutatingUse(MutatingUseContext::Retag) => {}
-use rustc_index::vec::{Idx, IndexVec};
+use rustc_index::vec::IndexVec;
use rustc::hir::def_id::CrateNum;
use rustc::mir;
use rustc::session::config::DebugInfo;
-use rustc::ty::{self, TyCtxt};
-use rustc::ty::layout::{LayoutOf, Size, VariantIdx};
+use rustc::ty::TyCtxt;
+use rustc::ty::layout::{LayoutOf, Size};
use crate::traits::*;
-use syntax_pos::{BytePos, Span, Symbol};
+use syntax_pos::{BytePos, Span};
use syntax::symbol::kw;
use super::{FunctionCx, LocalRef};
Some(per_local) => &per_local[local],
None => return,
};
- let whole_local_var = vars.iter().find(|var| {
+ let whole_local_var = vars.iter().copied().find(|var| {
var.place.projection.is_empty()
});
let has_proj = || vars.iter().any(|var| {
// be offset to account for the hidden environment?
None
} else {
- Some(VarDebugInfo {
+ Some(mir::VarDebugInfo {
name: kw::Invalid,
source_info: self.mir.local_decls[local].source_info,
place: local.into(),
_ => return,
};
- let vars = vars.iter().chain(if whole_local_var.is_none() {
+ let vars = vars.iter().copied().chain(if whole_local_var.is_none() {
fallback_var.as_ref()
} else {
None
}
}
+/// Partition all `VarDebuginfo` in `body`, by their base `Local`.
pub fn per_local_var_debug_info(
tcx: TyCtxt<'tcx>,
- body: &mir::Body<'tcx>,
-) -> Option<IndexVec<mir::Local, Vec<VarDebugInfo<'tcx>>>> {
+ body: &'a mir::Body<'tcx>,
+) -> Option<IndexVec<mir::Local, Vec<&'a mir::VarDebugInfo<'tcx>>>> {
if tcx.sess.opts.debuginfo == DebugInfo::Full || !tcx.sess.fewer_names() {
let mut per_local = IndexVec::from_elem(vec![], &body.local_decls);
- for (local, decl) in body.local_decls.iter_enumerated() {
- if let Some(name) = decl.name {
- per_local[local].push(VarDebugInfo {
- name,
- source_info: mir::SourceInfo {
- span: decl.source_info.span,
- scope: decl.visibility_scope,
- },
- place: local.into(),
- });
- }
- }
-
- let upvar_debuginfo = &body.__upvar_debuginfo_codegen_only_do_not_use;
- if !upvar_debuginfo.is_empty() {
-
- let env_arg = mir::Local::new(1);
- let mut env_projs = vec![];
-
- let pin_did = tcx.lang_items().pin_type();
- match body.local_decls[env_arg].ty.kind {
- ty::RawPtr(_) |
- ty::Ref(..) => {
- env_projs.push(mir::ProjectionElem::Deref);
- }
- ty::Adt(def, substs) if Some(def.did) == pin_did => {
- if let ty::Ref(..) = substs.type_at(0).kind {
- env_projs.push(mir::ProjectionElem::Field(
- mir::Field::new(0),
- // HACK(eddyb) field types aren't used or needed here.
- tcx.types.err,
- ));
- env_projs.push(mir::ProjectionElem::Deref);
- }
- }
- _ => {}
- }
-
- let extra_locals = {
- let upvars = upvar_debuginfo
- .iter()
- .enumerate()
- .map(|(i, upvar)| {
- let source_info = mir::SourceInfo {
- span: body.span,
- scope: mir::OUTERMOST_SOURCE_SCOPE,
- };
- (None, i, upvar.debug_name, upvar.by_ref, source_info)
- });
-
- let generator_fields = body.generator_layout.as_ref().map(|generator_layout| {
- generator_layout.variant_fields.iter()
- .enumerate()
- .flat_map(move |(variant_idx, fields)| {
- let variant_idx = Some(VariantIdx::from(variant_idx));
- fields.iter()
- .enumerate()
- .filter_map(move |(i, field)| {
- let decl = &generator_layout.
- __local_debuginfo_codegen_only_do_not_use[*field];
- if let Some(name) = decl.name {
- let source_info = mir::SourceInfo {
- span: decl.source_info.span,
- scope: decl.visibility_scope,
- };
- Some((variant_idx, i, name, false, source_info))
- } else {
- None
- }
- })
- })
- }).into_iter().flatten();
-
- upvars.chain(generator_fields)
- };
-
- for (variant_idx, field, name, by_ref, source_info) in extra_locals {
- let mut projs = env_projs.clone();
-
- if let Some(variant_idx) = variant_idx {
- projs.push(mir::ProjectionElem::Downcast(None, variant_idx));
- }
-
- projs.push(mir::ProjectionElem::Field(
- mir::Field::new(field),
- // HACK(eddyb) field types aren't used or needed here.
- tcx.types.err,
- ));
-
- if by_ref {
- projs.push(mir::ProjectionElem::Deref);
- }
-
- per_local[env_arg].push(VarDebugInfo {
- name,
- source_info,
- place: mir::Place {
- base: mir::PlaceBase::Local(env_arg),
- projection: tcx.intern_place_elems(&projs),
- },
- });
+ for var in &body.var_debug_info {
+ if let mir::PlaceBase::Local(local) = var.place.base {
+ per_local[local].push(var);
}
}
-
Some(per_local)
} else {
None
}
}
-
-/// Debug information relatating to an user variable.
-// FIXME(eddyb) move this to the MIR bodies themselves.
-#[derive(Clone)]
-pub struct VarDebugInfo<'tcx> {
- pub name: Symbol,
-
- /// Source info of the user variable, including the scope
- /// within which the variable is visible (to debuginfo)
- /// (see `LocalDecl`'s `source_info` field for more details).
- pub source_info: mir::SourceInfo,
-
- /// Where the data for this user variable is to be found.
- pub place: mir::Place<'tcx>,
-}
/// notably `expect`.
locals: IndexVec<mir::Local, LocalRef<'tcx, Bx::Value>>,
- per_local_var_debug_info: Option<IndexVec<mir::Local, Vec<debuginfo::VarDebugInfo<'tcx>>>>,
+ /// All `VarDebuginfo` from the MIR body, partitioned by `Local`.
+ /// This is `None` if no variable debuginfo/names are needed.
+ per_local_var_debug_info: Option<IndexVec<mir::Local, Vec<&'a mir::VarDebugInfo<'tcx>>>>,
}
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
-A constant item was initialized with something that is not a constant expression.
+A constant item was initialized with something that is not a constant
+expression.
Erroneous code example:
-This error indicates that during an attempt to build a struct or struct-like
-enum variant, one of the fields was specified more than once. Erroneous code
-example:
+A struct's or struct-like enum variant's field was specified more than once.
+
+Erroneous code example:
```compile_fail,E0062
struct Foo {
}
```
-Each field should be specified exactly one time. Example:
+This error indicates that during an attempt to build a struct or struct-like
+enum variant, one of the fields was specified more than once. Each field should
+be specified exactly one time. Example:
```
struct Foo {
-This error indicates that during an attempt to build a struct or struct-like
-enum variant, one of the fields was not provided. Erroneous code example:
+A struct's or struct-like enum variant's field was not provided.
+
+Erroneous code example:
```compile_fail,E0063
struct Foo {
-The left-hand side of a compound assignment expression must be a place
-expression. A place expression represents a memory location and includes
-item paths (ie, namespaced variables), dereferences, indexing expressions,
-and field references.
+An invalid left-hand side expression was used on an assignment operation.
-Let's start with some erroneous code examples:
+Erroneous code example:
```compile_fail,E0067
-use std::collections::LinkedList;
-
-// Bad: assignment to non-place expression
-LinkedList::new() += 1;
-
-// ...
-
-fn some_func(i: &mut i32) {
- i += 12; // Error : '+=' operation cannot be applied on a reference !
-}
+12 += 1; // error!
```
-And now some working examples:
+You need to have a place expression to be able to assign it something. For
+example:
```
-let mut i : i32 = 0;
-
-i += 12; // Good !
-
-// ...
-
-fn some_func(i: &mut i32) {
- *i += 12; // Good !
-}
+let mut x: i8 = 12;
+x += 1; // ok!
```
The compiler found a function whose body contains a `return;` statement but
-whose return type is not `()`. An example of this is:
+whose return type is not `()`.
+
+Erroneous code example:
```compile_fail,E0069
// error
-The left-hand side of an assignment operator must be a place expression. A
-place expression represents a memory location and can be a variable (with
-optional namespacing), a dereference, an indexing expression or a field
-reference.
+An assignment operator was used on a non-place expression.
-More details can be found in the [Expressions] section of the Reference.
-
-[Expressions]: https://doc.rust-lang.org/reference/expressions.html#places-rvalues-and-temporaries
-
-Now, we can go further. Here are some erroneous code examples:
+Erroneous code examples:
```compile_fail,E0070
struct SomeStruct {
x: i32,
- y: i32
+ y: i32,
}
-const SOME_CONST : i32 = 12;
+const SOME_CONST: i32 = 12;
fn some_other_func() {}
fn some_function() {
- SOME_CONST = 14; // error : a constant value cannot be changed!
- 1 = 3; // error : 1 isn't a valid place!
- some_other_func() = 4; // error : we cannot assign value to a function!
- SomeStruct.x = 12; // error : SomeStruct a structure name but it is used
- // like a variable!
+ SOME_CONST = 14; // error: a constant value cannot be changed!
+ 1 = 3; // error: 1 isn't a valid place!
+ some_other_func() = 4; // error: we cannot assign value to a function!
+ SomeStruct::x = 12; // error: SomeStruct a structure name but it is used
+ // like a variable!
}
```
+The left-hand side of an assignment operator must be a place expression. A
+place expression represents a memory location and can be a variable (with
+optional namespacing), a dereference, an indexing expression or a field
+reference.
+
+More details can be found in the [Expressions] section of the Reference.
+
+[Expressions]: https://doc.rust-lang.org/reference/expressions.html#places-rvalues-and-temporaries
+
And now let's give working examples:
```
struct SomeStruct {
x: i32,
- y: i32
+ y: i32,
}
-let mut s = SomeStruct {x: 0, y: 0};
+let mut s = SomeStruct { x: 0, y: 0 };
s.x = 3; // that's good !
-You tried to use structure-literal syntax to create an item that is
-not a structure or enum variant.
+A structure-literal syntax was used to create an item that is not a structure
+or enum variant.
Example of erroneous code:
// found builtin type `u32`
```
-To fix this, ensure that the name was correctly spelled, and that
-the correct form of initializer was used.
+To fix this, ensure that the name was correctly spelled, and that the correct
+form of initializer was used.
For example, the code above can be fixed to:
-When defining a recursive struct or enum, any use of the type being defined
-from inside the definition must occur behind a pointer (like `Box` or `&`).
-This is because structs and enums must have a well-defined size, and without
-the pointer, the size of the type would need to be unbounded.
+A recursive type has infinite size because it doesn't have an indirection.
-Consider the following erroneous definition of a type for a list of bytes:
+Erroneous code example:
```compile_fail,E0072
-// error, invalid recursive struct type
struct ListNode {
head: u8,
- tail: Option<ListNode>,
+ tail: Option<ListNode>, // error: no indirection here so impossible to
+ // compute the type's size
}
```
-This type cannot have a well-defined size, because it needs to be arbitrarily
-large (since we would be able to nest `ListNode`s to any depth). Specifically,
+When defining a recursive struct or enum, any use of the type being defined
+from inside the definition must occur behind a pointer (like `Box`, `&` or
+`Rc`). This is because structs and enums must have a well-defined size, and
+without the pointer, the size of the type would need to be unbounded.
+
+In the example, the type cannot have a well-defined size, because it needs to be
+arbitrarily large (since we would be able to nest `ListNode`s to any depth).
+Specifically,
```plain
size of `ListNode` = 1 byte for `head`
-The `#[simd]` attribute can only be applied to non empty tuple structs, because
-it doesn't make sense to try to use SIMD operations when there are no values to
-operate on.
+A `#[simd]` attribute was applied to an empty tuple struct.
-This will cause an error:
+Erroneous code example:
```compile_fail,E0075
#![feature(repr_simd)]
#[repr(simd)]
-struct Bad;
+struct Bad; // error!
```
-This will not:
+The `#[simd]` attribute can only be applied to non empty tuple structs, because
+it doesn't make sense to try to use SIMD operations when there are no values to
+operate on.
+
+Fixed example:
```
#![feature(repr_simd)]
#[repr(simd)]
-struct Good(u32);
+struct Good(u32); // ok!
```
-When using the `#[simd]` attribute to automatically use SIMD operations in tuple
-struct, the types in the struct must all be of the same type, or the compiler
-will trigger this error.
+All types in a tuple struct aren't the same when using the `#[simd]`
+attribute.
-This will cause an error:
+Erroneous code example:
```compile_fail,E0076
#![feature(repr_simd)]
#[repr(simd)]
-struct Bad(u16, u32, u32);
+struct Bad(u16, u32, u32); // error!
```
-This will not:
+When using the `#[simd]` attribute to automatically use SIMD operations in tuple
+struct, the types in the struct must all be of the same type, or the compiler
+will trigger this error.
+
+Fixed example:
```
#![feature(repr_simd)]
#[repr(simd)]
-struct Good(u32, u32, u32);
+struct Good(u32, u32, u32); // ok!
```
-When using the `#[simd]` attribute on a tuple struct, the elements in the tuple
-must be machine types so SIMD operations can be applied to them.
+A tuple struct's element isn't a machine type when using the `#[simd]`
+attribute.
-This will cause an error:
+Erroneous code example:
```compile_fail,E0077
#![feature(repr_simd)]
#[repr(simd)]
-struct Bad(String);
+struct Bad(String); // error!
```
-This will not:
+When using the `#[simd]` attribute on a tuple struct, the elements in the tuple
+must be machine types so SIMD operations can be applied to them.
+
+Fixed example:
```
#![feature(repr_simd)]
#[repr(simd)]
-struct Good(u32, u32, u32);
+struct Good(u32, u32, u32); // ok!
```
// expected 0, found 1
}
```
-
on the left. If something should be added to a string literal, move the
literal to the heap by allocating it with `to_owned()` like in
`"Your text".to_owned()`.
-
fn bar<T: Foo>(t: T) {} // ok!
```
-
* static
* dylib
* framework
-
NB. The default behavior here is "allowed", but this is unspecified
and likely to change in the future.
-
```compile_fail,E0635
#![feature(nonexistent_rust_feature)] // error: unknown feature
```
-
#![feature(rust1)]
#![feature(rust1)] // error: the feature `rust1` has already been declared
```
-
let b = 0 as *const i32; // Ok
let c: *const i32 = 0 as *const _; // Ok
-```
\ No newline at end of file
+```
that refers to itself. That is permitting, since the closure would be
invoking itself via a virtual call, and hence does not directly
reference its own *type*.
-
- `async fn`s are not yet supported in traits in Rust.
+`async fn`s are not yet supported in traits in Rust.
Erroneous code example:
}
```
-`async fn`s return an `impl Future`, making the following two examples equivalent:
+`async fn`s return an `impl Future`, making the following two examples
+equivalent:
```edition2018,ignore (example-of-desugaring-equivalence)
async fn foo() -> User {
```
But when it comes to supporting this in traits, there are [a few implementation
-issues][async-is-hard]. One of them is returning `impl Trait` in traits is not supported,
-as it would require [Generic Associated Types] to be supported:
+issues][async-is-hard]. One of them is returning `impl Trait` in traits is not
+supported, as it would require [Generic Associated Types] to be supported:
```edition2018,ignore (example-of-desugaring-equivalence)
impl MyDatabase {
}
```
-Until these issues are resolved, you can use the [`async-trait` crate], allowing you to use
-`async fn` in traits by desugaring to "boxed futures"
+Until these issues are resolved, you can use the [`async-trait` crate], allowing
+you to use `async fn` in traits by desugaring to "boxed futures"
(`Pin<Box<dyn Future + Send + 'async>>`).
-Note that using these trait methods will result in a heap allocation per-function-call. This is not
-a significant cost for the vast majority of applications, but should be considered when deciding
-whether to use this functionality in the public API of a low-level function that is expected to be
+Note that using these trait methods will result in a heap allocation
+per-function-call. This is not a significant cost for the vast majority of
+applications, but should be considered when deciding whether to use this
+functionality in the public API of a low-level function that is expected to be
called millions of times a second.
You might be interested in visiting the [async book] for further information.
To avoid the error, first bind the temporary to a named local variable.
-```ignore
+```ignore (not yet implemented)
# #![feature(raw_ref_op)]
fn temp_address() {
let val = 2;
if $x != 1 { "s" } else { "" }
};
}
+
+// Useful type to use with `Result<>` indicate that an error has already
+// been reported to the user, so no need to continue checking.
+#[derive(Clone, Copy, Debug, RustcEncodable, RustcDecodable, Hash, PartialEq, Eq)]
+pub struct ErrorReported;
+
+rustc_data_structures::impl_stable_hash_via_hash!(ErrorReported);
t: ast::IntTy,
v: u128,
) {
- let int_type = if let ast::IntTy::Isize = t {
- cx.sess().target.isize_ty
- } else {
- t
- };
-
+ let int_type = t.normalize(cx.sess().target.ptr_width);
let (_, max) = int_ty_range(int_type);
let max = max as u128;
let negative = type_limits.negated_expr_id == e.hir_id;
lit: &hir::Lit,
t: ast::UintTy,
) {
- let uint_type = if let ast::UintTy::Usize = t {
- cx.sess().target.usize_ty
- } else {
- t
- };
+ let uint_type = t.normalize(cx.sess().target.ptr_width);
let (min, max) = uint_ty_range(uint_type);
let lit_val: u128 = match lit.node {
// _v is u8, within range by definition
}
impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
+
+ /// Check if the type is array and emit an unsafe type lint.
+ fn check_for_array_ty(&mut self, sp: Span, ty: Ty<'tcx>) -> bool {
+ if let ty::Array(..) = ty.kind {
+ self.emit_ffi_unsafe_type_lint(
+ ty,
+ sp,
+ "passing raw arrays by value is not FFI-safe",
+ Some("consider passing a pointer to the array"),
+ );
+ true
+ } else {
+ false
+ }
+ }
+
+
/// Checks if the given type is "ffi-safe" (has a stable, well-defined
/// representation which can be exported to C code).
fn check_type_for_ffi(&self,
ty::RawPtr(ty::TypeAndMut { ty, .. }) |
ty::Ref(_, ty, _) => self.check_type_for_ffi(cache, ty),
- ty::Array(ty, _) => self.check_type_for_ffi(cache, ty),
+ ty::Array(inner_ty, _) => self.check_type_for_ffi(cache, inner_ty),
ty::FnPtr(sig) => {
match sig.abi() {
}
}
- fn check_type_for_ffi_and_report_errors(&mut self, sp: Span, ty: Ty<'tcx>) {
+ fn check_type_for_ffi_and_report_errors(&mut self, sp: Span, ty: Ty<'tcx>, is_static: bool) {
// We have to check for opaque types before `normalize_erasing_regions`,
// which will replace opaque types with their underlying concrete type.
if self.check_for_opaque_ty(sp, ty) {
// it is only OK to use this function because extern fns cannot have
// any generic types right now:
let ty = self.cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty);
+ // C doesn't really support passing arrays by value.
+ // The only way to pass an array by value is through a struct.
+ // So we first test that the top level isn't an array,
+ // and then recursively check the types inside.
+ if !is_static && self.check_for_array_ty(sp, ty) {
+ return;
+ }
match self.check_type_for_ffi(&mut FxHashSet::default(), ty) {
FfiResult::FfiSafe => {}
let sig = self.cx.tcx.erase_late_bound_regions(&sig);
for (input_ty, input_hir) in sig.inputs().iter().zip(&decl.inputs) {
- self.check_type_for_ffi_and_report_errors(input_hir.span, input_ty);
+ self.check_type_for_ffi_and_report_errors(input_hir.span, input_ty, false);
}
if let hir::Return(ref ret_hir) = decl.output {
let ret_ty = sig.output();
if !ret_ty.is_unit() {
- self.check_type_for_ffi_and_report_errors(ret_hir.span, ret_ty);
+ self.check_type_for_ffi_and_report_errors(ret_hir.span, ret_ty, false);
}
}
}
fn check_foreign_static(&mut self, id: hir::HirId, span: Span) {
let def_id = self.cx.tcx.hir().local_def_id(id);
let ty = self.cx.tcx.type_of(def_id);
- self.check_type_for_ffi_and_report_errors(span, ty);
+ self.check_type_for_ffi_and_report_errors(span, ty, true);
}
}
let has_global_allocator = match &*global_allocator_spans(krate) {
[span1, span2, ..] => {
self.sess.struct_span_err(*span2, "cannot define multiple global allocators")
- .span_note(*span1, "the previous global allocator is defined here").emit();
+ .span_label(*span2, "cannot define a new global allocator")
+ .span_label(*span1, "previous global allocator is defined here")
+ .emit();
true
}
spans => !spans.is_empty()
// Decoding metadata from a single crate's metadata
use crate::rmeta::*;
-use crate::rmeta::table::{FixedSizeEncoding, PerDefTable};
+use crate::rmeta::table::{FixedSizeEncoding, Table};
-use rustc_index::vec::IndexVec;
+use rustc_index::vec::{Idx, IndexVec};
use rustc_data_structures::sync::{Lrc, Lock, Once, AtomicCell};
use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash};
use rustc::hir::map::definitions::DefPathTable;
use std::num::NonZeroUsize;
use std::u32;
-use rustc_serialize::{Decodable, Decoder, Encodable, SpecializedDecoder, opaque};
+use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque};
use syntax::attr;
use syntax::ast::{self, Ident};
use syntax::source_map::{self, respan, Spanned};
}
}
-impl<'a, 'tcx, T: Encodable + Decodable> Lazy<T> {
+impl<'a, 'tcx, T: Decodable> Lazy<T> {
fn decode<M: Metadata<'a, 'tcx>>(self, metadata: M) -> T {
let mut dcx = metadata.decoder(self.position.get());
dcx.lazy_state = LazyState::NodeStart(self.position);
}
}
-impl<'a: 'x, 'tcx: 'x, 'x, T: Encodable + Decodable> Lazy<[T]> {
+impl<'a: 'x, 'tcx: 'x, 'x, T: Decodable> Lazy<[T]> {
fn decode<M: Metadata<'a, 'tcx>>(
self,
metadata: M,
}
}
-impl<'a, 'tcx, T: Encodable> SpecializedDecoder<Lazy<T>> for DecodeContext<'a, 'tcx> {
+impl<'a, 'tcx, T> SpecializedDecoder<Lazy<T>> for DecodeContext<'a, 'tcx> {
fn specialized_decode(&mut self) -> Result<Lazy<T>, Self::Error> {
self.read_lazy_with_meta(())
}
}
-impl<'a, 'tcx, T: Encodable> SpecializedDecoder<Lazy<[T]>> for DecodeContext<'a, 'tcx> {
+impl<'a, 'tcx, T> SpecializedDecoder<Lazy<[T]>> for DecodeContext<'a, 'tcx> {
fn specialized_decode(&mut self) -> Result<Lazy<[T]>, Self::Error> {
let len = self.read_usize()?;
if len == 0 {
}
}
-impl<'a, 'tcx, T> SpecializedDecoder<Lazy<PerDefTable<T>>> for DecodeContext<'a, 'tcx>
+impl<'a, 'tcx, I: Idx, T> SpecializedDecoder<Lazy<Table<I, T>>> for DecodeContext<'a, 'tcx>
where Option<T>: FixedSizeEncoding,
{
- fn specialized_decode(&mut self) -> Result<Lazy<PerDefTable<T>>, Self::Error> {
+ fn specialized_decode(&mut self) -> Result<Lazy<Table<I, T>>, Self::Error> {
let len = self.read_usize()?;
self.read_lazy_with_meta(len)
}
use crate::rmeta::*;
-use crate::rmeta::table::{FixedSizeEncoding, PerDefTable};
+use crate::rmeta::table::FixedSizeEncoding;
use rustc::middle::cstore::{LinkagePreference, NativeLibrary,
EncodedMetadata, ForeignModule};
use rustc::hir::{GenericParamKind, AnonConst};
use rustc::hir::map::definitions::DefPathTable;
use rustc_data_structures::fingerprint::Fingerprint;
-use rustc_index::vec::IndexVec;
+use rustc_index::vec::Idx;
use rustc::middle::dependency_format::Linkage;
use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel,
metadata_symbol_name};
opaque: opaque::Encoder,
tcx: TyCtxt<'tcx>,
- per_def: PerDefTables<'tcx>,
+ per_def: PerDefTableBuilders<'tcx>,
lazy_state: LazyState,
type_shorthands: FxHashMap<Ty<'tcx>, usize>,
source_file_cache: Lrc<SourceFile>,
}
-#[derive(Default)]
-struct PerDefTables<'tcx> {
- kind: PerDefTable<Lazy<EntryKind<'tcx>>>,
- visibility: PerDefTable<Lazy<ty::Visibility>>,
- span: PerDefTable<Lazy<Span>>,
- attributes: PerDefTable<Lazy<[ast::Attribute]>>,
- children: PerDefTable<Lazy<[DefIndex]>>,
- stability: PerDefTable<Lazy<attr::Stability>>,
- deprecation: PerDefTable<Lazy<attr::Deprecation>>,
-
- ty: PerDefTable<Lazy<Ty<'tcx>>>,
- fn_sig: PerDefTable<Lazy<ty::PolyFnSig<'tcx>>>,
- impl_trait_ref: PerDefTable<Lazy<ty::TraitRef<'tcx>>>,
- inherent_impls: PerDefTable<Lazy<[DefIndex]>>,
- variances: PerDefTable<Lazy<[ty::Variance]>>,
- generics: PerDefTable<Lazy<ty::Generics>>,
- explicit_predicates: PerDefTable<Lazy<ty::GenericPredicates<'tcx>>>,
- inferred_outlives: PerDefTable<Lazy<&'tcx [(ty::Predicate<'tcx>, Span)]>>,
- super_predicates: PerDefTable<Lazy<ty::GenericPredicates<'tcx>>>,
-
- mir: PerDefTable<Lazy<mir::Body<'tcx>>>,
- promoted_mir: PerDefTable<Lazy<IndexVec<mir::Promoted, mir::Body<'tcx>>>>,
-}
-
macro_rules! encoder_methods {
($($name:ident($ty:ty);)*) => {
$(fn $name(&mut self, value: $ty) -> Result<(), Self::Error> {
}
}
-impl<'tcx, T: Encodable> SpecializedEncoder<Lazy<T>> for EncodeContext<'tcx> {
+impl<'tcx, T> SpecializedEncoder<Lazy<T>> for EncodeContext<'tcx> {
fn specialized_encode(&mut self, lazy: &Lazy<T>) -> Result<(), Self::Error> {
self.emit_lazy_distance(*lazy)
}
}
-impl<'tcx, T: Encodable> SpecializedEncoder<Lazy<[T]>> for EncodeContext<'tcx> {
+impl<'tcx, T> SpecializedEncoder<Lazy<[T]>> for EncodeContext<'tcx> {
fn specialized_encode(&mut self, lazy: &Lazy<[T]>) -> Result<(), Self::Error> {
self.emit_usize(lazy.meta)?;
if lazy.meta == 0 {
}
}
-impl<'tcx, T> SpecializedEncoder<Lazy<PerDefTable<T>>> for EncodeContext<'tcx>
+impl<'tcx, I: Idx, T> SpecializedEncoder<Lazy<Table<I, T>>> for EncodeContext<'tcx>
where Option<T>: FixedSizeEncoding,
{
- fn specialized_encode(&mut self, lazy: &Lazy<PerDefTable<T>>) -> Result<(), Self::Error> {
+ fn specialized_encode(&mut self, lazy: &Lazy<Table<I, T>>) -> Result<(), Self::Error> {
self.emit_usize(lazy.meta)?;
self.emit_lazy_distance(*lazy)
}
}
}
-// Shorthand for `$self.$tables.$table.set($key, $self.lazy($value))`, which would
+// Shorthand for `$self.$tables.$table.set($def_id.index, $self.lazy($value))`, which would
// normally need extra variables to avoid errors about multiple mutable borrows.
macro_rules! record {
- ($self:ident.$tables:ident.$table:ident[$key:expr] <- $value:expr) => {{
+ ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{
{
let value = $value;
let lazy = $self.lazy(value);
- $self.$tables.$table.set($key, lazy);
+ $self.$tables.$table.set($def_id.index, lazy);
}
}}
}
i = self.position();
- let per_def = LazyPerDefTables {
- kind: self.per_def.kind.encode(&mut self.opaque),
- visibility: self.per_def.visibility.encode(&mut self.opaque),
- span: self.per_def.span.encode(&mut self.opaque),
- attributes: self.per_def.attributes.encode(&mut self.opaque),
- children: self.per_def.children.encode(&mut self.opaque),
- stability: self.per_def.stability.encode(&mut self.opaque),
- deprecation: self.per_def.deprecation.encode(&mut self.opaque),
-
- ty: self.per_def.ty.encode(&mut self.opaque),
- fn_sig: self.per_def.fn_sig.encode(&mut self.opaque),
- impl_trait_ref: self.per_def.impl_trait_ref.encode(&mut self.opaque),
- inherent_impls: self.per_def.inherent_impls.encode(&mut self.opaque),
- variances: self.per_def.variances.encode(&mut self.opaque),
- generics: self.per_def.generics.encode(&mut self.opaque),
- explicit_predicates: self.per_def.explicit_predicates.encode(&mut self.opaque),
- inferred_outlives: self.per_def.inferred_outlives.encode(&mut self.opaque),
- super_predicates: self.per_def.super_predicates.encode(&mut self.opaque),
-
- mir: self.per_def.mir.encode(&mut self.opaque),
- promoted_mir: self.per_def.promoted_mir.encode(&mut self.opaque),
- };
+ let per_def = self.per_def.encode(&mut self.opaque);
let per_def_bytes = self.position() - i;
// Encode the proc macro data
use decoder::Metadata;
-use table::PerDefTable;
+use table::{Table, TableBuilder};
use rustc::hir;
use rustc::hir::def::{self, CtorKind};
use rustc_index::vec::IndexVec;
use rustc_data_structures::svh::Svh;
use rustc_data_structures::sync::MetadataRef;
-use rustc_serialize::Encodable;
+use rustc_serialize::opaque::Encoder;
use syntax::{ast, attr};
use syntax::edition::Edition;
use syntax::symbol::Symbol;
fn min_size(meta: Self::Meta) -> usize;
}
-impl<T: Encodable> LazyMeta for T {
+impl<T> LazyMeta for T {
type Meta = ();
fn min_size(_: ()) -> usize {
}
}
-impl<T: Encodable> LazyMeta for [T] {
+impl<T> LazyMeta for [T] {
type Meta = usize;
fn min_size(len: usize) -> usize {
}
}
-impl<T: Encodable> Lazy<T> {
+impl<T> Lazy<T> {
fn from_position(position: NonZeroUsize) -> Lazy<T> {
Lazy::from_position_and_meta(position, ())
}
}
-impl<T: Encodable> Lazy<[T]> {
+impl<T> Lazy<[T]> {
fn empty() -> Lazy<[T]> {
Lazy::from_position_and_meta(NonZeroUsize::new(1).unwrap(), 0)
}
// manually, instead of relying on the default, to get the correct variance.
// Only needed when `T` itself contains a parameter (e.g. `'tcx`).
macro_rules! Lazy {
- (Table<$T:ty>) => {Lazy<Table<$T>, usize>};
- (PerDefTable<$T:ty>) => {Lazy<PerDefTable<$T>, usize>};
+ (Table<$I:ty, $T:ty>) => {Lazy<Table<$I, $T>, usize>};
([$T:ty]) => {Lazy<[$T], usize>};
($T:ty) => {Lazy<$T, ()>};
}
impls: Lazy<[DefIndex]>,
}
-#[derive(RustcEncodable, RustcDecodable)]
-crate struct LazyPerDefTables<'tcx> {
- kind: Lazy!(PerDefTable<Lazy!(EntryKind<'tcx>)>),
- visibility: Lazy!(PerDefTable<Lazy<ty::Visibility>>),
- span: Lazy!(PerDefTable<Lazy<Span>>),
- attributes: Lazy!(PerDefTable<Lazy<[ast::Attribute]>>),
- children: Lazy!(PerDefTable<Lazy<[DefIndex]>>),
- stability: Lazy!(PerDefTable<Lazy<attr::Stability>>),
- deprecation: Lazy!(PerDefTable<Lazy<attr::Deprecation>>),
- ty: Lazy!(PerDefTable<Lazy!(Ty<'tcx>)>),
- fn_sig: Lazy!(PerDefTable<Lazy!(ty::PolyFnSig<'tcx>)>),
- impl_trait_ref: Lazy!(PerDefTable<Lazy!(ty::TraitRef<'tcx>)>),
- inherent_impls: Lazy!(PerDefTable<Lazy<[DefIndex]>>),
- variances: Lazy!(PerDefTable<Lazy<[ty::Variance]>>),
- generics: Lazy!(PerDefTable<Lazy<ty::Generics>>),
- explicit_predicates: Lazy!(PerDefTable<Lazy!(ty::GenericPredicates<'tcx>)>),
+/// Define `LazyPerDefTables` and `PerDefTableBuilders` at the same time.
+macro_rules! define_per_def_tables {
+ ($($name:ident: Table<DefIndex, $T:ty>),+ $(,)?) => {
+ #[derive(RustcEncodable, RustcDecodable)]
+ crate struct LazyPerDefTables<'tcx> {
+ $($name: Lazy!(Table<DefIndex, $T>)),+
+ }
+
+ #[derive(Default)]
+ struct PerDefTableBuilders<'tcx> {
+ $($name: TableBuilder<DefIndex, $T>),+
+ }
+
+ impl PerDefTableBuilders<'tcx> {
+ fn encode(&self, buf: &mut Encoder) -> LazyPerDefTables<'tcx> {
+ LazyPerDefTables {
+ $($name: self.$name.encode(buf)),+
+ }
+ }
+ }
+ }
+}
+
+define_per_def_tables! {
+ kind: Table<DefIndex, Lazy!(EntryKind<'tcx>)>,
+ visibility: Table<DefIndex, Lazy<ty::Visibility>>,
+ span: Table<DefIndex, Lazy<Span>>,
+ attributes: Table<DefIndex, Lazy<[ast::Attribute]>>,
+ children: Table<DefIndex, Lazy<[DefIndex]>>,
+ stability: Table<DefIndex, Lazy<attr::Stability>>,
+ deprecation: Table<DefIndex, Lazy<attr::Deprecation>>,
+ ty: Table<DefIndex, Lazy!(Ty<'tcx>)>,
+ fn_sig: Table<DefIndex, Lazy!(ty::PolyFnSig<'tcx>)>,
+ impl_trait_ref: Table<DefIndex, Lazy!(ty::TraitRef<'tcx>)>,
+ inherent_impls: Table<DefIndex, Lazy<[DefIndex]>>,
+ variances: Table<DefIndex, Lazy<[ty::Variance]>>,
+ generics: Table<DefIndex, Lazy<ty::Generics>>,
+ explicit_predicates: Table<DefIndex, Lazy!(ty::GenericPredicates<'tcx>)>,
// FIXME(eddyb) this would ideally be `Lazy<[...]>` but `ty::Predicate`
// doesn't handle shorthands in its own (de)serialization impls,
// as it's an `enum` for which we want to derive (de)serialization,
// so the `ty::codec` APIs handle the whole `&'tcx [...]` at once.
// Also, as an optimization, a missing entry indicates an empty `&[]`.
- inferred_outlives: Lazy!(PerDefTable<Lazy!(&'tcx [(ty::Predicate<'tcx>, Span)])>),
- super_predicates: Lazy!(PerDefTable<Lazy!(ty::GenericPredicates<'tcx>)>),
- mir: Lazy!(PerDefTable<Lazy!(mir::Body<'tcx>)>),
- promoted_mir: Lazy!(PerDefTable<Lazy!(IndexVec<mir::Promoted, mir::Body<'tcx>>)>),
+ inferred_outlives: Table<DefIndex, Lazy!(&'tcx [(ty::Predicate<'tcx>, Span)])>,
+ super_predicates: Table<DefIndex, Lazy!(ty::GenericPredicates<'tcx>)>,
+ mir: Table<DefIndex, Lazy!(mir::Body<'tcx>)>,
+ promoted_mir: Table<DefIndex, Lazy!(IndexVec<mir::Promoted, mir::Body<'tcx>>)>,
}
#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
use crate::rmeta::*;
-use rustc::hir::def_id::{DefId, DefIndex};
+use rustc_index::vec::Idx;
use rustc_serialize::{Encodable, opaque::Encoder};
use std::convert::TryInto;
use std::marker::PhantomData;
}
}
-/// Random-access table (i.e. offeringconstant-time `get`/`set`), similar to
+/// Random-access table (i.e. offering constant-time `get`/`set`), similar to
/// `Vec<Option<T>>`, but without requiring encoding or decoding all the values
/// eagerly and in-order.
/// A total of `(max_idx + 1) * <Option<T> as FixedSizeEncoding>::BYTE_LEN` bytes
-/// are used for a table, where `max_idx` is the largest index passed to `set`.
-// FIXME(eddyb) replace `Vec` with `[_]` here, such that `Box<Table<T>>` would be used
-// when building it, and `Lazy<Table<T>>` or `&Table<T>` when reading it.
-// (not sure if that is possible given that the `Vec` is being resized now)
-pub(super) struct Table<T> where Option<T>: FixedSizeEncoding {
- // FIXME(eddyb) store `[u8; <Option<T>>::BYTE_LEN]` instead of `u8` in `Vec`,
- // once that starts being allowed by the compiler (i.e. lazy normalization).
+/// are used for a table, where `max_idx` is the largest index passed to
+/// `TableBuilder::set`.
+pub(super) struct Table<I: Idx, T> where Option<T>: FixedSizeEncoding {
+ _marker: PhantomData<(fn(&I), T)>,
+ // NOTE(eddyb) this makes `Table` not implement `Sized`, but no
+ // value of `Table` is ever created (it's always behind `Lazy`).
+ _bytes: [u8],
+}
+
+/// Helper for constructing a table's serialization (also see `Table`).
+pub(super) struct TableBuilder<I: Idx, T> where Option<T>: FixedSizeEncoding {
+ // FIXME(eddyb) use `IndexVec<I, [u8; <Option<T>>::BYTE_LEN]>` instead of
+ // `Vec<u8>`, once that starts working (i.e. lazy normalization).
+ // Then again, that has the downside of not allowing `TableBuilder::encode` to
+ // obtain a `&[u8]` entirely in safe code, for writing the bytes out.
bytes: Vec<u8>,
- _marker: PhantomData<T>,
+ _marker: PhantomData<(fn(&I), T)>,
}
-impl<T> Default for Table<T> where Option<T>: FixedSizeEncoding {
+impl<I: Idx, T> Default for TableBuilder<I, T> where Option<T>: FixedSizeEncoding {
fn default() -> Self {
- Table {
+ TableBuilder {
bytes: vec![],
_marker: PhantomData,
}
}
}
-impl<T> Table<T> where Option<T>: FixedSizeEncoding {
- fn set(&mut self, i: usize, value: T) {
+impl<I: Idx, T> TableBuilder<I, T> where Option<T>: FixedSizeEncoding {
+ pub(super) fn set(&mut self, i: I, value: T) {
// FIXME(eddyb) investigate more compact encodings for sparse tables.
// On the PR @michaelwoerister mentioned:
// > Space requirements could perhaps be optimized by using the HAMT `popcnt`
// > trick (i.e. divide things into buckets of 32 or 64 items and then
// > store bit-masks of which item in each bucket is actually serialized).
+ let i = i.index();
let needed = (i + 1) * <Option<T>>::BYTE_LEN;
if self.bytes.len() < needed {
self.bytes.resize(needed, 0);
Some(value).write_to_bytes_at(&mut self.bytes, i);
}
- fn encode(&self, buf: &mut Encoder) -> Lazy<Self> {
+ pub(super) fn encode(&self, buf: &mut Encoder) -> Lazy<Table<I, T>> {
let pos = buf.position();
buf.emit_raw_bytes(&self.bytes);
Lazy::from_position_and_meta(
}
}
-impl<T> LazyMeta for Table<T> where Option<T>: FixedSizeEncoding {
+impl<I: Idx, T> LazyMeta for Table<I, T> where Option<T>: FixedSizeEncoding {
type Meta = usize;
fn min_size(len: usize) -> usize {
}
}
-impl<T> Lazy<Table<T>> where Option<T>: FixedSizeEncoding {
+impl<I: Idx, T> Lazy<Table<I, T>> where Option<T>: FixedSizeEncoding {
/// Given the metadata, extract out the value at a particular index (if any).
#[inline(never)]
- fn get<'a, 'tcx, M: Metadata<'a, 'tcx>>(
+ pub(super) fn get<'a, 'tcx, M: Metadata<'a, 'tcx>>(
&self,
metadata: M,
- i: usize,
+ i: I,
) -> Option<T> {
debug!("Table::lookup: index={:?} len={:?}", i, self.meta);
let start = self.position.get();
let bytes = &metadata.raw_bytes()[start..start + self.meta];
- <Option<T>>::maybe_read_from_bytes_at(bytes, i)?
- }
-}
-
-/// Like a `Table` but using `DefIndex` instead of `usize` as keys.
-// FIXME(eddyb) replace by making `Table` behave like `IndexVec`,
-// and by using `newtype_index!` to define `DefIndex`.
-pub(super) struct PerDefTable<T>(Table<T>) where Option<T>: FixedSizeEncoding;
-
-impl<T> Default for PerDefTable<T> where Option<T>: FixedSizeEncoding {
- fn default() -> Self {
- PerDefTable(Table::default())
- }
-}
-
-impl<T> PerDefTable<T> where Option<T>: FixedSizeEncoding {
- pub(super) fn set(&mut self, def_id: DefId, value: T) {
- assert!(def_id.is_local());
- self.0.set(def_id.index.index(), value);
- }
-
- pub(super) fn encode(&self, buf: &mut Encoder) -> Lazy<Self> {
- let lazy = self.0.encode(buf);
- Lazy::from_position_and_meta(lazy.position, lazy.meta)
- }
-}
-
-impl<T> LazyMeta for PerDefTable<T> where Option<T>: FixedSizeEncoding {
- type Meta = <Table<T> as LazyMeta>::Meta;
-
- fn min_size(meta: Self::Meta) -> usize {
- Table::<T>::min_size(meta)
- }
-}
-
-impl<T> Lazy<PerDefTable<T>> where Option<T>: FixedSizeEncoding {
- fn as_table(&self) -> Lazy<Table<T>> {
- Lazy::from_position_and_meta(self.position, self.meta)
- }
-
- /// Given the metadata, extract out the value at a particular DefIndex (if any).
- #[inline(never)]
- pub(super) fn get<'a, 'tcx, M: Metadata<'a, 'tcx>>(
- &self,
- metadata: M,
- def_index: DefIndex,
- ) -> Option<T> {
- self.as_table().get(metadata, def_index.index())
+ <Option<T>>::maybe_read_from_bytes_at(bytes, i.index())?
}
}
location,
borrow,
None,
- ).add_explanation_to_diagnostic(self.infcx.tcx, self.body, &mut err, "", Some(borrow_span));
+ ).add_explanation_to_diagnostic(
+ self.infcx.tcx,
+ self.body,
+ &self.local_names,
+ &mut err,
+ "",
+ Some(borrow_span),
+ );
err.buffer(&mut self.errors_buffer);
}
});
self.explain_why_borrow_contains_point(location, borrow, None)
- .add_explanation_to_diagnostic(self.infcx.tcx, self.body, &mut err, "", None);
+ .add_explanation_to_diagnostic(
+ self.infcx.tcx,
+ self.body,
+ &self.local_names,
+ &mut err,
+ "",
+ None,
+ );
err
}
explanation.add_explanation_to_diagnostic(
self.infcx.tcx,
self.body,
+ &self.local_names,
&mut err,
first_borrow_desc,
None,
explanation.add_explanation_to_diagnostic(
self.infcx.tcx,
self.body,
+ &self.local_names,
&mut err,
"",
None,
);
explanation.add_explanation_to_diagnostic(
- self.infcx.tcx, self.body, &mut err, "", None);
+ self.infcx.tcx, self.body, &self.local_names, &mut err, "", None);
}
err
_ => {}
}
- explanation.add_explanation_to_diagnostic(self.infcx.tcx, self.body, &mut err, "", None);
+ explanation.add_explanation_to_diagnostic(
+ self.infcx.tcx,
+ self.body,
+ &self.local_names,
+ &mut err,
+ "",
+ None,
+ );
err.buffer(&mut self.errors_buffer);
}
}
_ => {}
}
- explanation.add_explanation_to_diagnostic(self.infcx.tcx, self.body, &mut err, "", None);
+ explanation.add_explanation_to_diagnostic(
+ self.infcx.tcx,
+ self.body,
+ &self.local_names,
+ &mut err,
+ "",
+ None,
+ );
let within = if borrow_spans.for_generator() {
" by generator"
Applicability::MachineApplicable,
);
- match category {
- ConstraintCategory::Return => {
- err.span_note(constraint_span, "closure is returned here");
- }
- ConstraintCategory::OpaqueType => {
- err.span_note(constraint_span, "generator is returned here");
- }
+ let msg = match category {
+ ConstraintCategory::Return => "closure is returned here".to_string(),
+ ConstraintCategory::OpaqueType => "generator is returned here".to_string(),
ConstraintCategory::CallArgument => {
fr_name.highlight_region_name(&mut err);
- err.span_note(
- constraint_span,
- &format!("function requires argument type to outlive `{}`", fr_name),
- );
+ format!("function requires argument type to outlive `{}`", fr_name)
}
_ => bug!("report_escaping_closure_capture called with unexpected constraint \
category: `{:?}`", category),
- }
+ };
+ err.span_note(constraint_span, &msg);
err
}
);
self.explain_why_borrow_contains_point(location, loan, None)
- .add_explanation_to_diagnostic(self.infcx.tcx, self.body, &mut err, "", None);
+ .add_explanation_to_diagnostic(
+ self.infcx.tcx,
+ self.body,
+ &self.local_names,
+ &mut err,
+ "",
+ None,
+ );
err.buffer(&mut self.errors_buffer);
}
assigned_span: Span,
err_place: &Place<'tcx>,
) {
- let (from_arg, local_decl) = if let Some(local) = err_place.as_local() {
- if let LocalKind::Arg = self.body.local_kind(local) {
- (true, Some(&self.body.local_decls[local]))
- } else {
- (false, Some(&self.body.local_decls[local]))
- }
- } else {
- (false, None)
+ let (from_arg, local_decl, local_name) = match err_place.as_local() {
+ Some(local) => (
+ self.body.local_kind(local) == LocalKind::Arg,
+ Some(&self.body.local_decls[local]),
+ self.local_names[local],
+ ),
+ None => (false, None, None),
};
// If root local is initialized immediately (everything apart from let
}
}
if let Some(decl) = local_decl {
- if let Some(name) = decl.name {
+ if let Some(name) = local_name {
if decl.can_be_made_mutable() {
err.span_suggestion(
decl.source_info.span,
/// Appends end-user visible description of the `local` place to `buf`. If `local` doesn't have
/// a name, or its name was generated by the compiler, then `Err` is returned
- fn append_local_to_string(&self, local_index: Local, buf: &mut String) -> Result<(), ()> {
- let local = &self.body.local_decls[local_index];
- match local.name {
- Some(name) if !local.from_compiler_desugaring() => {
+ fn append_local_to_string(&self, local: Local, buf: &mut String) -> Result<(), ()> {
+ let decl = &self.body.local_decls[local];
+ match self.local_names[local] {
+ Some(name) if !decl.from_compiler_desugaring() => {
buf.push_str(&name.as_str());
Ok(())
}
.as_local_hir_id(def_id)
.expect("do_mir_borrowck: non-local DefId");
+ let mut local_names = IndexVec::from_elem(None, &input_body.local_decls);
+ for var_debug_info in &input_body.var_debug_info {
+ if let Some(local) = var_debug_info.place.as_local() {
+ if let Some(prev_name) = local_names[local] {
+ if var_debug_info.name != prev_name {
+ span_bug!(var_debug_info.source_info.span,
+ "local {:?} has many names (`{}` vs `{}`)",
+ local, prev_name, var_debug_info.name);
+ }
+ }
+ local_names[local] = Some(var_debug_info.name);
+ }
+ }
+
// Gather the upvars of a closure, if any.
let tables = tcx.typeck_tables_of(def_id);
let upvars: Vec<_> = tables
free_regions,
body,
&promoted,
+ &local_names,
&upvars,
location_table,
param_env,
borrow_set,
dominators,
upvars,
+ local_names,
};
let mut state = Flows::new(
if let ClearCrossCrate::Set(ref vsi) = mbcx.body.source_scope_local_data {
let local_decl = &mbcx.body.local_decls[local];
- // Skip implicit `self` argument for closures
- if local.index() == 1 && tcx.is_closure(mbcx.mir_def_id) {
- continue;
- }
-
// Skip over locals that begin with an underscore or have no name
- match local_decl.name {
+ match mbcx.local_names[local] {
Some(name) => if name.as_str().starts_with("_") {
continue;
},
/// Information about upvars not necessarily preserved in types or MIR
upvars: Vec<Upvar>,
+
+ /// Names of local (user) variables (extracted from `var_debug_info`).
+ local_names: IndexVec<Local, Option<Name>>,
}
// Check that:
if decl.is_ref_for_guard() {
let mut err = self.cannot_move_out_of(
span,
- &format!("`{}` in pattern guard", decl.name.unwrap()),
+ &format!("`{}` in pattern guard", self.local_names[*local].unwrap()),
);
err.note(
"variables bound in patterns cannot be moved from \
err: &mut DiagnosticBuilder<'a>,
binds_to: &[Local],
) {
- let mut noncopy_var_spans = Vec::new();
for (j, local) in binds_to.into_iter().enumerate() {
let bind_to = &self.body.local_decls[*local];
let binding_span = bind_to.source_info.span;
if binds_to.len() == 1 {
self.note_type_does_not_implement_copy(
err,
- &format!("`{}`", bind_to.name.unwrap()),
+ &format!("`{}`", self.local_names[*local].unwrap()),
bind_to.ty,
Some(binding_span)
);
- } else {
- noncopy_var_spans.push(binding_span);
}
}
if binds_to.len() > 1 {
- err.span_note(
- noncopy_var_spans,
- "move occurs because these variables have types that \
- don't implement the `Copy` trait",
+ err.note("move occurs because these variables have types that \
+ don't implement the `Copy` trait",
);
}
}
if access_place.as_local().is_some() {
reason = ", as it is not declared as mutable".to_string();
} else {
- let name = self.body.local_decls[*local]
- .name
+ let name = self.local_names[*local]
.expect("immutable unnamed local");
reason = format!(", as `{}` is not declared as mutable", name);
}
// Deliberately fall into this case for all implicit self types,
// so that we don't fall in to the next case with them.
kind == mir::ImplicitSelfKind::MutRef
- } else if Some(kw::SelfLower) == local_decl.name {
+ } else if Some(kw::SelfLower) == self.local_names[*local] {
// Otherwise, check if the name is the self kewyord - in which case
// we have an explicit self. Do the same thing in this case and check
// for a `self: &mut Self` to suggest removing the `&mut`.
err.span_suggestion(
local_decl.source_info.span,
"consider changing this to be mutable",
- format!("mut {}", local_decl.name.unwrap()),
+ format!("mut {}", self.local_names[*local].unwrap()),
Applicability::MachineApplicable,
);
}
);
}
- match local_decl.name {
+ match self.local_names[*local] {
Some(name) if !local_decl.from_compiler_desugaring() => {
err.span_label(
span,
};
use rustc::ty::{self, TyCtxt};
use rustc::ty::adjustment::{PointerCast};
+use rustc_index::vec::IndexVec;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::DiagnosticBuilder;
use syntax_pos::Span;
+use syntax_pos::symbol::Symbol;
mod find_use;
&self,
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>,
+ local_names: &IndexVec<Local, Option<Symbol>>,
err: &mut DiagnosticBuilder<'_>,
borrow_desc: &str,
borrow_span: Option<Span>,
_ => ("destructor", format!("type `{}`", local_decl.ty)),
};
- match local_decl.name {
+ match local_names[dropped_local] {
Some(local_name) if !local_decl.from_compiler_desugaring() => {
let message = format!(
"{B}borrow might be used here, when `{LOC}` is dropped \
Some(Cause::DropVar(local, location)) => {
let mut should_note_order = false;
- if body.local_decls[local].name.is_some() {
+ if self.local_names[local].is_some() {
if let Some((WriteKind::StorageDeadOrDrop, place)) = kind_place {
if let Some(borrowed_local) = place.as_local() {
- if body.local_decls[borrowed_local].name.is_some()
+ if self.local_names[borrowed_local].is_some()
&& local != borrowed_local
{
should_note_order = true;
let (category, from_closure, span, region_name) =
self.nonlexical_regioncx.free_region_constraint_info(
self.body,
+ &self.local_names,
&self.upvars,
self.mir_def_id,
self.infcx,
Operand::Move(place) => {
if let Some(l) = place.as_local() {
let local_decl = &self.body.local_decls[l];
- if local_decl.name.is_none() {
+ if self.local_names[l].is_none() {
local_decl.source_info.span
} else {
span
use rustc::ty::{self, RegionKind, RegionVid};
use rustc_index::vec::IndexVec;
use rustc_errors::Diagnostic;
+use syntax_pos::symbol::Symbol;
use std::fmt::Debug;
use std::env;
use std::io;
universal_regions: UniversalRegions<'tcx>,
body: &Body<'tcx>,
promoted: &IndexVec<Promoted, Body<'tcx>>,
+ local_names: &IndexVec<Local, Option<Symbol>>,
upvars: &[Upvar],
location_table: &LocationTable,
param_env: ty::ParamEnv<'tcx>,
// Solve the region constraints.
let closure_region_requirements =
- regioncx.solve(infcx, &body, upvars, def_id, errors_buffer);
+ regioncx.solve(infcx, body, local_names, upvars, def_id, errors_buffer);
// Dump MIR results into a file, if that is enabled. This let us
// write unit-tests, as well as helping with debugging.
use rustc::infer::error_reporting::nice_region_error::NiceRegionError;
use rustc::infer::InferCtxt;
use rustc::infer::NLLRegionVariableOrigin;
-use rustc::mir::{ConstraintCategory, Location, Body};
+use rustc::mir::{ConstraintCategory, Local, Location, Body};
use rustc::ty::{self, RegionVid};
use rustc_index::vec::IndexVec;
use rustc_errors::DiagnosticBuilder;
use syntax::errors::Applicability;
use syntax::symbol::kw;
use syntax_pos::Span;
+use syntax_pos::symbol::Symbol;
use self::outlives_suggestion::OutlivesSuggestionBuilder;
/// The MIR body we are reporting errors on (for convenience).
body: &'b Body<'tcx>,
+ /// User variable names for MIR locals (where applicable).
+ local_names: &'b IndexVec<Local, Option<Symbol>>,
+
/// Any upvars for the MIR body we have kept track of during borrow checking.
upvars: &'b [Upvar],
}
pub(super) fn report_error<'a>(
&'a self,
body: &Body<'tcx>,
+ local_names: &IndexVec<Local, Option<Symbol>>,
upvars: &[Upvar],
infcx: &'a InferCtxt<'a, 'tcx>,
mir_def_id: DefId,
fr: RegionVid,
fr_origin: NLLRegionVariableOrigin,
outlived_fr: RegionVid,
- outlives_suggestion: &mut OutlivesSuggestionBuilder,
+ outlives_suggestion: &mut OutlivesSuggestionBuilder<'_>,
renctx: &mut RegionErrorNamingCtx,
) -> DiagnosticBuilder<'a> {
debug!("report_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr);
infcx,
mir_def_id,
body,
+ local_names,
upvars,
};
renctx: &mut RegionErrorNamingCtx,
) -> DiagnosticBuilder<'_> {
let ErrorReportingCtx {
- infcx, body, upvars, ..
+ infcx, body, upvars, local_names, ..
} = errctx;
let ErrorConstraintInfo {
} = errci;
let fr_name_and_span =
- self.get_var_name_and_span_for_region(infcx.tcx, body, upvars, errci.fr);
- let outlived_fr_name_and_span =
- self.get_var_name_and_span_for_region(infcx.tcx, body, upvars, errci.outlived_fr);
+ self.get_var_name_and_span_for_region(infcx.tcx, body, local_names, upvars, errci.fr);
+ let outlived_fr_name_and_span = self.get_var_name_and_span_for_region(
+ infcx.tcx,
+ body,
+ local_names,
+ upvars,
+ errci.outlived_fr,
+ );
let escapes_from = match self.universal_regions.defining_ty {
DefiningTy::Closure(..) => "closure",
crate fn free_region_constraint_info(
&self,
body: &Body<'tcx>,
+ local_names: &IndexVec<Local, Option<Symbol>>,
upvars: &[Upvar],
mir_def_id: DefId,
infcx: &InferCtxt<'_, 'tcx>,
let mut renctx = RegionErrorNamingCtx::new();
let errctx = ErrorReportingCtx {
- infcx, body, upvars, mir_def_id,
+ infcx, body, local_names, upvars, mir_def_id,
region_infcx: self,
};
let outlived_fr_name = self.give_region_a_name(&errctx, &mut renctx, outlived_region);
use std::collections::BTreeMap;
use log::debug;
-use rustc::{hir::def_id::DefId, infer::InferCtxt, mir::Body, ty::RegionVid};
+use rustc::{hir::def_id::DefId, infer::InferCtxt, ty::RegionVid};
+use rustc::mir::{Body, Local};
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{Diagnostic, DiagnosticBuilder};
+use rustc_index::vec::IndexVec;
+use syntax_pos::symbol::Symbol;
use smallvec::SmallVec;
/// corresponding to a function definition.
///
/// Adds a help note suggesting adding a where clause with the needed constraints.
-pub struct OutlivesSuggestionBuilder {
+pub struct OutlivesSuggestionBuilder<'a> {
/// The MIR DefId of the fn with the lifetime error.
mir_def_id: DefId,
+ local_names: &'a IndexVec<Local, Option<Symbol>>,
+
/// The list of outlives constraints that need to be added. Specifically, we map each free
/// region to all other regions that it must outlive. I will use the shorthand `fr:
/// outlived_frs`. Not all of these regions will already have names necessarily. Some could be
constraints_to_add: BTreeMap<RegionVid, Vec<RegionVid>>,
}
-impl OutlivesSuggestionBuilder {
+impl OutlivesSuggestionBuilder<'a> {
/// Create a new builder for the given MIR node representing a fn definition.
- crate fn new(mir_def_id: DefId) -> Self {
- OutlivesSuggestionBuilder { mir_def_id, constraints_to_add: BTreeMap::default() }
+ crate fn new(
+ mir_def_id: DefId,
+ local_names: &'a IndexVec<Local, Option<Symbol>>,
+ ) -> Self {
+ OutlivesSuggestionBuilder {
+ mir_def_id,
+ local_names,
+ constraints_to_add: BTreeMap::default(),
+ }
}
/// Returns `true` iff the `RegionNameSource` is a valid source for an outlives
infcx,
body,
mir_def_id: self.mir_def_id,
+ local_names: self.local_names,
// We should not be suggesting naming upvars, so we pass in a dummy set of upvars that
// should never be used.
use rustc::hir::def::{Res, DefKind};
use rustc::hir::def_id::DefId;
use rustc::infer::InferCtxt;
-use rustc::mir::Body;
+use rustc::mir::{Local, Body};
use rustc::ty::subst::{SubstsRef, GenericArgKind};
use rustc::ty::{self, RegionKind, RegionVid, Ty, TyCtxt};
use rustc::ty::print::RegionHighlightMode;
+use rustc_index::vec::IndexVec;
use rustc_errors::DiagnosticBuilder;
use syntax::symbol::kw;
use rustc_data_structures::fx::FxHashMap;
fr: RegionVid,
) -> Option<RegionName> {
let ErrorReportingCtx {
- infcx, body, mir_def_id, upvars, ..
+ infcx, body, mir_def_id, local_names, upvars, ..
} = errctx;
debug!("give_region_a_name(fr={:?}, counter={:?})", fr, renctx.counter);
.give_name_from_error_region(infcx.tcx, *mir_def_id, fr, renctx)
.or_else(|| {
self.give_name_if_anonymous_region_appears_in_arguments(
- infcx, body, *mir_def_id, fr, renctx,
+ infcx, body, local_names, *mir_def_id, fr, renctx,
)
})
.or_else(|| {
&self,
infcx: &InferCtxt<'_, 'tcx>,
body: &Body<'tcx>,
+ local_names: &IndexVec<Local, Option<Symbol>>,
mir_def_id: DefId,
fr: RegionVid,
renctx: &mut RegionErrorNamingCtx,
return Some(region_name);
}
- self.give_name_if_we_cannot_match_hir_ty(infcx, body, fr, arg_ty, renctx)
+ self.give_name_if_we_cannot_match_hir_ty(infcx, body, local_names, fr, arg_ty, renctx)
}
fn give_name_if_we_can_match_hir_ty_from_argument(
&self,
infcx: &InferCtxt<'_, 'tcx>,
body: &Body<'tcx>,
+ local_names: &IndexVec<Local, Option<Symbol>>,
needle_fr: RegionVid,
argument_ty: Ty<'tcx>,
renctx: &mut RegionErrorNamingCtx,
let assigned_region_name = if type_name.find(&format!("'{}", counter)).is_some() {
// Only add a label if we can confirm that a region was labelled.
let argument_index = self.get_argument_index_for_region(infcx.tcx, needle_fr)?;
- let (_, span) = self.get_argument_name_and_span_for_region(body, argument_index);
+ let (_, span) =
+ self.get_argument_name_and_span_for_region(body, local_names, argument_index);
Some(RegionName {
// This counter value will already have been used, so this function will increment
use crate::borrow_check::Upvar;
use rustc::mir::{Local, Body};
use rustc::ty::{RegionVid, TyCtxt};
-use rustc_index::vec::Idx;
+use rustc_index::vec::{Idx, IndexVec};
use syntax::source_map::Span;
use syntax_pos::symbol::Symbol;
&self,
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>,
+ local_names: &IndexVec<Local, Option<Symbol>>,
upvars: &[Upvar],
fr: RegionVid,
) -> Option<(Option<Symbol>, Span)> {
})
.or_else(|| {
debug!("get_var_name_and_span_for_region: attempting argument");
- self.get_argument_index_for_region(tcx, fr)
- .map(|index| self.get_argument_name_and_span_for_region(body, index))
+ self.get_argument_index_for_region(tcx, fr).map(|index| {
+ self.get_argument_name_and_span_for_region(body, local_names, index)
+ })
})
}
crate fn get_argument_name_and_span_for_region(
&self,
body: &Body<'tcx>,
+ local_names: &IndexVec<Local, Option<Symbol>>,
argument_index: usize,
) -> (Option<Symbol>, Span) {
let implicit_inputs = self.universal_regions.defining_ty.implicit_inputs();
let argument_local = Local::new(implicit_inputs + argument_index + 1);
debug!("get_argument_name_and_span_for_region: argument_local={:?}", argument_local);
- let argument_name = body.local_decls[argument_local].name;
+ let argument_name = local_names[argument_local];
let argument_span = body.local_decls[argument_local].source_info.span;
debug!("get_argument_name_and_span_for_region: argument_name={:?} argument_span={:?}",
argument_name, argument_span);
use rustc_index::vec::IndexVec;
use rustc_errors::{Diagnostic, DiagnosticBuilder};
use syntax_pos::Span;
+use syntax_pos::symbol::Symbol;
crate use self::error_reporting::{RegionName, RegionNameSource, RegionErrorNamingCtx};
use self::values::{LivenessValues, RegionValueElements, RegionValues};
&mut self,
infcx: &InferCtxt<'_, 'tcx>,
body: &Body<'tcx>,
+ local_names: &IndexVec<Local, Option<Symbol>>,
upvars: &[Upvar],
mir_def_id: DefId,
errors_buffer: &mut Vec<Diagnostic>,
self.check_universal_regions(
infcx,
body,
+ local_names,
upvars,
mir_def_id,
outlives_requirements.as_mut(),
&self,
infcx: &InferCtxt<'_, 'tcx>,
body: &Body<'tcx>,
+ local_names: &IndexVec<Local, Option<Symbol>>,
upvars: &[Upvar],
mir_def_id: DefId,
mut propagated_outlives_requirements: Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>,
errors_buffer: &mut Vec<Diagnostic>,
region_naming: &mut RegionErrorNamingCtx,
) {
- let mut outlives_suggestion = OutlivesSuggestionBuilder::new(mir_def_id);
+ let mut outlives_suggestion = OutlivesSuggestionBuilder::new(mir_def_id, local_names);
for (fr, fr_definition) in self.definitions.iter_enumerated() {
match fr_definition.origin {
self.check_universal_region(
infcx,
body,
+ local_names,
upvars,
mir_def_id,
fr,
&self,
infcx: &InferCtxt<'_, 'tcx>,
body: &Body<'tcx>,
+ local_names: &IndexVec<Local, Option<Symbol>>,
upvars: &[Upvar],
mir_def_id: DefId,
longer_fr: RegionVid,
propagated_outlives_requirements: &mut Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>,
- outlives_suggestion: &mut OutlivesSuggestionBuilder,
+ outlives_suggestion: &mut OutlivesSuggestionBuilder<'_>,
errors_buffer: &mut Vec<Diagnostic>,
region_naming: &mut RegionErrorNamingCtx,
) {
representative,
infcx,
body,
+ local_names,
upvars,
mir_def_id,
propagated_outlives_requirements,
shorter_fr,
infcx,
body,
+ local_names,
upvars,
mir_def_id,
propagated_outlives_requirements,
shorter_fr: RegionVid,
infcx: &InferCtxt<'_, 'tcx>,
body: &Body<'tcx>,
+ local_names: &IndexVec<Local, Option<Symbol>>,
upvars: &[Upvar],
mir_def_id: DefId,
propagated_outlives_requirements: &mut Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>,
- outlives_suggestion: &mut OutlivesSuggestionBuilder,
+ outlives_suggestion: &mut OutlivesSuggestionBuilder<'_>,
errors_buffer: &mut Vec<Diagnostic>,
region_naming: &mut RegionErrorNamingCtx,
) -> Option<ErrorReported> {
// error. This gives better error messages in some cases.
let db = self.report_error(
body,
+ local_names,
upvars,
infcx,
mir_def_id,
};
// If the user explicitly annotated the output types, enforce those.
+ // Note that this only happens for closures.
if let Some(user_provided_sig) = user_provided_sig {
let user_provided_output_ty = user_provided_sig.output();
let user_provided_output_ty =
self.normalize(user_provided_output_ty, Locations::All(output_span));
- self.equate_normalized_input_or_output(
- user_provided_output_ty,
+ if let Err(err) = self.eq_opaque_type_and_type(
mir_output_ty,
- output_span,
- );
+ user_provided_output_ty,
+ self.mir_def_id,
+ Locations::All(output_span),
+ ConstraintCategory::BoringNoLocation
+ ) {
+ span_mirbug!(
+ self,
+ Location::START,
+ "equate_inputs_and_outputs: `{:?}=={:?}` failed with `{:?}`",
+ mir_output_ty,
+ user_provided_output_ty,
+ err
+ );
+ }
}
}
mutability: Mutability::Mut,
ty: ptr_ty,
user_ty: UserTypeProjections::none(),
- name: None,
source_info,
- visibility_scope: source_info.scope,
internal: true,
local_info: LocalInfo::Other,
is_block_tail: None,
);
let tcx = self.hir.tcx();
+ let debug_source_info = SourceInfo {
+ span: source_info.span,
+ scope: visibility_scope,
+ };
let binding_mode = match mode {
BindingMode::ByValue => ty::BindingMode::BindByValue(mutability.into()),
BindingMode::ByRef(_) => ty::BindingMode::BindByReference(mutability.into()),
mutability,
ty: var_ty,
user_ty,
- name: Some(name),
source_info,
- visibility_scope,
internal: false,
is_block_tail: None,
local_info: LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
))),
};
let for_arm_body = self.local_decls.push(local);
+ self.var_debug_info.push(VarDebugInfo {
+ name,
+ source_info: debug_source_info,
+ place: for_arm_body.into(),
+ });
let locals = if has_guard.0 {
let ref_for_guard = self.local_decls.push(LocalDecl::<'tcx> {
// This variable isn't mutated but has a name, so has to be
mutability: Mutability::Not,
ty: tcx.mk_imm_ref(tcx.lifetimes.re_erased, var_ty),
user_ty: UserTypeProjections::none(),
- name: Some(name),
source_info,
- visibility_scope,
internal: false,
is_block_tail: None,
local_info: LocalInfo::User(ClearCrossCrate::Set(BindingForm::RefForGuard)),
});
+ self.var_debug_info.push(VarDebugInfo {
+ name,
+ source_info: debug_source_info,
+ place: ref_for_guard.into(),
+ });
LocalsForNode::ForGuard {
ref_for_guard,
for_arm_body,
self.hir.tcx().features().exhaustive_patterns &&
!v.uninhabited_from(self.hir.tcx(), substs, adt_def.adt_kind()).is_empty()
}
- });
+ }) && (adt_def.did.is_local() || !adt_def.is_variant_list_non_exhaustive());
if irrefutable {
let place = tcx.mk_place_downcast(match_pair.place, adt_def, variant_index);
candidate.match_pairs.extend(self.field_match_pairs(place, subpatterns));
(None, fn_sig.output())
};
- build::construct_fn(cx, id, arguments, safety, abi,
- return_ty, yield_ty, return_ty_span, body)
+ let mut mir = build::construct_fn(
+ cx,
+ id,
+ arguments,
+ safety,
+ abi,
+ return_ty,
+ return_ty_span,
+ body,
+ );
+ mir.yield_ty = yield_ty;
+ mir
} else {
// Get the revealed type of this const. This is *not* the adjusted
// type of its body, which may be a subtype of this type. For
var_indices: HirIdMap<LocalsForNode>,
local_decls: IndexVec<Local, LocalDecl<'tcx>>,
canonical_user_type_annotations: ty::CanonicalUserTypeAnnotations<'tcx>,
- __upvar_debuginfo_codegen_only_do_not_use: Vec<UpvarDebuginfo>,
upvar_mutbls: Vec<Mutability>,
unit_temp: Option<Place<'tcx>>,
+ var_debug_info: Vec<VarDebugInfo<'tcx>>,
+
/// Cached block with the `RESUME` terminator; this is created
/// when first set of cleanups are built.
cached_resume_block: Option<BasicBlock>,
safety: Safety,
abi: Abi,
return_ty: Ty<'tcx>,
- yield_ty: Option<Ty<'tcx>>,
return_ty_span: Span,
body: &'tcx hir::Body,
) -> Body<'tcx>
let tcx_hir = tcx.hir();
let span = tcx_hir.span(fn_id);
- let hir_tables = hir.tables();
let fn_def_id = tcx_hir.local_def_id(fn_id);
- // Gather the upvars of a closure, if any.
- let mut upvar_mutbls = vec![];
- // In analyze_closure() in upvar.rs we gathered a list of upvars used by a
- // closure and we stored in a map called upvar_list in TypeckTables indexed
- // with the closure's DefId. Here, we run through that vec of UpvarIds for
- // the given closure and use the necessary information to create UpvarDecl.
- let upvar_debuginfo: Vec<_> = hir_tables
- .upvar_list
- .get(&fn_def_id)
- .into_iter()
- .flatten()
- .map(|(&var_hir_id, &upvar_id)| {
- let capture = hir_tables.upvar_capture(upvar_id);
- let by_ref = match capture {
- ty::UpvarCapture::ByValue => false,
- ty::UpvarCapture::ByRef(..) => true,
- };
- let mut debuginfo = UpvarDebuginfo {
- debug_name: kw::Invalid,
- by_ref,
- };
- let mut mutability = Mutability::Not;
- if let Some(Node::Binding(pat)) = tcx_hir.find(var_hir_id) {
- if let hir::PatKind::Binding(_, _, ident, _) = pat.kind {
- debuginfo.debug_name = ident.name;
- if let Some(&bm) = hir.tables.pat_binding_modes().get(pat.hir_id) {
- if bm == ty::BindByValue(hir::Mutability::Mutable) {
- mutability = Mutability::Mut;
- } else {
- mutability = Mutability::Not;
- }
- } else {
- tcx.sess.delay_span_bug(pat.span, "missing binding mode");
- }
- }
- }
- upvar_mutbls.push(mutability);
- debuginfo
- })
- .collect();
-
let mut builder = Builder::new(hir,
span,
arguments.len(),
safety,
return_ty,
return_ty_span,
- upvar_debuginfo,
- upvar_mutbls,
body.generator_kind.is_some());
let call_site_scope = region::Scope {
Place::return_place(),
|builder| {
builder.in_scope(arg_scope_s, LintLevel::Inherited, |builder| {
- builder.args_and_body(block, &arguments, arg_scope, &body.value)
+ builder.args_and_body(block, fn_def_id, &arguments, arg_scope, &body.value)
})
},
));
info!("fn_id {:?} has attrs {:?}", fn_def_id,
tcx.get_attrs(fn_def_id));
- let mut body = builder.finish(yield_ty);
+ let mut body = builder.finish();
body.spread_arg = spread_arg;
body
}
Safety::Safe,
const_ty,
const_ty_span,
- vec![],
- vec![],
false,
);
TerminatorKind::Unreachable);
}
- builder.finish(None)
+ builder.finish()
}
fn construct_error<'a, 'tcx>(
let owner_id = hir.tcx().hir().body_owner(body_id);
let span = hir.tcx().hir().span(owner_id);
let ty = hir.tcx().types.err;
- let mut builder = Builder::new(hir, span, 0, Safety::Safe, ty, span, vec![], vec![], false);
+ let mut builder = Builder::new(hir, span, 0, Safety::Safe, ty, span, false);
let source_info = builder.source_info(span);
builder.cfg.terminate(START_BLOCK, source_info, TerminatorKind::Unreachable);
- builder.finish(None)
+ builder.finish()
}
impl<'a, 'tcx> Builder<'a, 'tcx> {
safety: Safety,
return_ty: Ty<'tcx>,
return_span: Span,
- __upvar_debuginfo_codegen_only_do_not_use: Vec<UpvarDebuginfo>,
- upvar_mutbls: Vec<Mutability>,
is_generator: bool)
-> Builder<'a, 'tcx> {
let lint_level = LintLevel::Explicit(hir.root_lint_level);
1,
),
canonical_user_type_annotations: IndexVec::new(),
- __upvar_debuginfo_codegen_only_do_not_use,
- upvar_mutbls,
+ upvar_mutbls: vec![],
var_indices: Default::default(),
unit_temp: None,
+ var_debug_info: vec![],
cached_resume_block: None,
cached_return_block: None,
cached_unreachable_block: None,
builder
}
- fn finish(self,
- yield_ty: Option<Ty<'tcx>>)
- -> Body<'tcx> {
+ fn finish(self) -> Body<'tcx> {
for (index, block) in self.cfg.basic_blocks.iter().enumerate() {
if block.terminator.is_none() {
span_bug!(self.fn_span, "no terminator on block {:?}", index);
self.cfg.basic_blocks,
self.source_scopes,
ClearCrossCrate::Set(self.source_scope_local_data),
- yield_ty,
self.local_decls,
self.canonical_user_type_annotations,
self.arg_count,
- self.__upvar_debuginfo_codegen_only_do_not_use,
+ self.var_debug_info,
self.fn_span,
self.hir.control_flow_destroyed(),
)
fn args_and_body(&mut self,
mut block: BasicBlock,
+ fn_def_id: DefId,
arguments: &[ArgInfo<'tcx>],
argument_scope: region::Scope,
ast_body: &'tcx hir::Expr)
{
// Allocate locals for the function arguments
for &ArgInfo(ty, _, arg_opt, _) in arguments.iter() {
- // If this is a simple binding pattern, give the local a name for
- // debuginfo and so that error reporting knows that this is a user
- // variable. For any other pattern the pattern introduces new
- // variables which will be named instead.
- let (name, span) = if let Some(arg) = arg_opt {
- (arg.pat.simple_ident().map(|ident| ident.name), arg.pat.span)
- } else {
- (None, self.fn_span)
+ let source_info = SourceInfo {
+ scope: OUTERMOST_SOURCE_SCOPE,
+ span: arg_opt.map_or(self.fn_span, |arg| arg.pat.span)
};
-
- let source_info = SourceInfo { scope: OUTERMOST_SOURCE_SCOPE, span, };
- self.local_decls.push(LocalDecl {
+ let arg_local = self.local_decls.push(LocalDecl {
mutability: Mutability::Mut,
ty,
user_ty: UserTypeProjections::none(),
source_info,
- visibility_scope: source_info.scope,
- name,
internal: false,
local_info: LocalInfo::Other,
is_block_tail: None,
});
+
+ // If this is a simple binding pattern, give debuginfo a nice name.
+ if let Some(arg) = arg_opt {
+ if let Some(ident) = arg.pat.simple_ident() {
+ self.var_debug_info.push(VarDebugInfo {
+ name: ident.name,
+ source_info,
+ place: arg_local.into(),
+ });
+ }
+ }
+ }
+
+ let tcx = self.hir.tcx();
+ let tcx_hir = tcx.hir();
+ let hir_tables = self.hir.tables();
+
+ // In analyze_closure() in upvar.rs we gathered a list of upvars used by a
+ // closure and we stored in a map called upvar_list in TypeckTables indexed
+ // with the closure's DefId. Here, we run through that vec of UpvarIds for
+ // the given closure and use the necessary information to create upvar
+ // debuginfo and to fill `self.upvar_mutbls`.
+ if let Some(upvars) = hir_tables.upvar_list.get(&fn_def_id) {
+ let closure_env_arg = Local::new(1);
+ let mut closure_env_projs = vec![];
+ let mut closure_ty = self.local_decls[closure_env_arg].ty;
+ if let ty::Ref(_, ty, _) = closure_ty.kind {
+ closure_env_projs.push(ProjectionElem::Deref);
+ closure_ty = ty;
+ }
+ let (def_id, upvar_substs) = match closure_ty.kind {
+ ty::Closure(def_id, substs) => (def_id, ty::UpvarSubsts::Closure(substs)),
+ ty::Generator(def_id, substs, _) => (def_id, ty::UpvarSubsts::Generator(substs)),
+ _ => span_bug!(self.fn_span, "upvars with non-closure env ty {:?}", closure_ty)
+ };
+ let upvar_tys = upvar_substs.upvar_tys(def_id, tcx);
+ let upvars_with_tys = upvars.iter().zip(upvar_tys);
+ self.upvar_mutbls = upvars_with_tys.enumerate().map(|(i, ((&var_id, &upvar_id), ty))| {
+ let capture = hir_tables.upvar_capture(upvar_id);
+
+ let mut mutability = Mutability::Not;
+ let mut name = kw::Invalid;
+ if let Some(Node::Binding(pat)) = tcx_hir.find(var_id) {
+ if let hir::PatKind::Binding(_, _, ident, _) = pat.kind {
+ name = ident.name;
+
+ if let Some(&bm) = hir_tables.pat_binding_modes().get(pat.hir_id) {
+ if bm == ty::BindByValue(hir::Mutability::Mutable) {
+ mutability = Mutability::Mut;
+ } else {
+ mutability = Mutability::Not;
+ }
+ } else {
+ tcx.sess.delay_span_bug(pat.span, "missing binding mode");
+ }
+ }
+ }
+
+ let mut projs = closure_env_projs.clone();
+ projs.push(ProjectionElem::Field(Field::new(i), ty));
+ match capture {
+ ty::UpvarCapture::ByValue => {}
+ ty::UpvarCapture::ByRef(..) => {
+ projs.push(ProjectionElem::Deref);
+ }
+ };
+
+ self.var_debug_info.push(VarDebugInfo {
+ name,
+ source_info: SourceInfo {
+ scope: OUTERMOST_SOURCE_SCOPE,
+ span: tcx_hir.span(var_id),
+ },
+ place: Place {
+ base: closure_env_arg.into(),
+ projection: tcx.intern_place_elems(&projs),
+ },
+ });
+
+ mutability
+ }).collect();
}
let mut scope = None;
if let LocalValue::Live(Operand::Indirect(MemPlace { ptr, .. })) = local {
trace!("deallocating local");
let ptr = ptr.to_ptr()?;
- self.memory.dump_alloc(ptr.alloc_id);
+ if log_enabled!(::log::Level::Trace) {
+ self.memory.dump_alloc(ptr.alloc_id);
+ }
self.memory.deallocate_local(ptr)?;
};
Ok(())
//! After a const evaluation has computed a value, before we destroy the const evaluator's session
//! memory, we need to extract all memory allocations to the global memory pool so they stay around.
-use rustc::ty::{Ty, self};
-use rustc::mir::interpret::{InterpResult, ErrorHandled};
-use rustc::hir;
use super::validity::RefTracking;
-use rustc_data_structures::fx::FxHashSet;
+use rustc::hir;
+use rustc::mir::interpret::{ErrorHandled, InterpResult};
+use rustc::ty::{self, Ty};
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use syntax::ast::Mutability;
use super::{
- ValueVisitor, MemoryKind, AllocId, MPlaceTy, Scalar,
+ AllocId, Allocation, InterpCx, Machine, MemoryKind, MPlaceTy, Scalar, ValueVisitor,
};
-use crate::const_eval::{CompileTimeInterpreter, CompileTimeEvalContext};
-struct InternVisitor<'rt, 'mir, 'tcx> {
+pub trait CompileTimeMachine<'mir, 'tcx> =
+ Machine<
+ 'mir,
+ 'tcx,
+ MemoryKinds = !,
+ PointerTag = (),
+ ExtraFnVal = !,
+ FrameExtra = (),
+ MemoryExtra = (),
+ AllocExtra = (),
+ MemoryMap = FxHashMap<AllocId, (MemoryKind<!>, Allocation)>,
+ >;
+
+struct InternVisitor<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>> {
/// The ectx from which we intern.
- ecx: &'rt mut CompileTimeEvalContext<'mir, 'tcx>,
+ ecx: &'rt mut InterpCx<'mir, 'tcx, M>,
/// Previously encountered safe references.
ref_tracking: &'rt mut RefTracking<(MPlaceTy<'tcx>, Mutability, InternMode)>,
/// A list of all encountered allocations. After type-based interning, we traverse this list to
/// `immutable` things might become mutable if `ty` is not frozen.
/// `ty` can be `None` if there is no potential interior mutability
/// to account for (e.g. for vtables).
-fn intern_shallow<'rt, 'mir, 'tcx>(
- ecx: &'rt mut CompileTimeEvalContext<'mir, 'tcx>,
+fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>(
+ ecx: &'rt mut InterpCx<'mir, 'tcx, M>,
leftover_allocations: &'rt mut FxHashSet<AllocId>,
mode: InternMode,
alloc_id: AllocId,
mutability: Mutability,
ty: Option<Ty<'tcx>>,
) -> InterpResult<'tcx, Option<IsStaticOrFn>> {
- trace!(
- "InternVisitor::intern {:?} with {:?}",
- alloc_id, mutability,
- );
+ trace!("InternVisitor::intern {:?} with {:?}", alloc_id, mutability,);
// remove allocation
let tcx = ecx.tcx;
let (kind, mut alloc) = match ecx.memory.alloc_map.remove(&alloc_id) {
Ok(None)
}
-impl<'rt, 'mir, 'tcx> InternVisitor<'rt, 'mir, 'tcx> {
+impl<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>> InternVisitor<'rt, 'mir, 'tcx, M> {
fn intern_shallow(
&mut self,
alloc_id: AllocId,
}
}
-impl<'rt, 'mir, 'tcx>
- ValueVisitor<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>
+impl<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>
+ ValueVisitor<'mir, 'tcx, M>
for
- InternVisitor<'rt, 'mir, 'tcx>
+ InternVisitor<'rt, 'mir, 'tcx, M>
{
type V = MPlaceTy<'tcx>;
#[inline(always)]
- fn ecx(&self) -> &CompileTimeEvalContext<'mir, 'tcx> {
+ fn ecx(&self) -> &InterpCx<'mir, 'tcx, M> {
&self.ecx
}
}
}
-pub fn intern_const_alloc_recursive(
- ecx: &mut CompileTimeEvalContext<'mir, 'tcx>,
+pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>(
+ ecx: &mut InterpCx<'mir, 'tcx, M>,
// The `mutability` of the place, ignoring the type.
place_mut: Option<hir::Mutability>,
ret: MPlaceTy<'tcx>,
Ok(())
}
- /// For debugging, print an allocation and all allocations it points to, recursively.
+ /// Print an allocation and all allocations it points to, recursively.
+ /// This prints directly to stderr, ignoring RUSTC_LOG! It is up to the caller to
+ /// control for this.
pub fn dump_alloc(&self, id: AllocId) {
self.dump_allocs(vec![id]);
}
}
}
- trace!(
+ eprintln!(
"{}({} bytes, alignment {}){}",
msg,
alloc.size.bytes(),
write!(msg, "└{0:─^1$}┘ ", target, relocation_width as usize).unwrap();
pos = i + self.pointer_size();
}
- trace!("{}", msg);
+ eprintln!("{}", msg);
}
}
- /// For debugging, print a list of allocations and all allocations they point to, recursively.
+ /// Print a list of allocations and all allocations they point to, recursively.
+ /// This prints directly to stderr, ignoring RUSTC_LOG! It is up to the caller to
+ /// control for this.
pub fn dump_allocs(&self, mut allocs: Vec<AllocId>) {
- if !log_enabled!(::log::Level::Trace) {
- return;
- }
allocs.sort();
allocs.dedup();
let mut allocs_to_print = VecDeque::from(allocs);
);
}
Some(GlobalAlloc::Function(func)) => {
- trace!("{} {}", msg, func);
+ eprintln!("{} {}", msg, func);
}
Some(GlobalAlloc::Static(did)) => {
- trace!("{} {:?}", msg, did);
+ eprintln!("{} {:?}", msg, did);
}
None => {
- trace!("{} (deallocated)", msg);
+ eprintln!("{} (deallocated)", msg);
}
}
},
}
pub fn leak_report(&self) -> usize {
- trace!("### LEAK REPORT ###");
let leaks: Vec<_> = self.alloc_map.filter_map_collect(|&id, &(kind, _)| {
if kind.may_leak() { None } else { Some(id) }
});
let n = leaks.len();
- self.dump_allocs(leaks);
+ if n > 0 {
+ eprintln!("### LEAK REPORT ###");
+ self.dump_allocs(leaks);
+ }
n
}
/// operations and fat pointers. This idea was taken from rustc's codegen.
/// In particular, thanks to `ScalarPair`, arithmetic operations and casts can be entirely
/// defined on `Immediate`, and do not have to work with a `Place`.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable, Hash)]
pub enum Immediate<Tag=(), Id=AllocId> {
Scalar(ScalarMaybeUndef<Tag, Id>),
ScalarPair(ScalarMaybeUndef<Tag, Id>, ScalarMaybeUndef<Tag, Id>),
/// An `Operand` is the result of computing a `mir::Operand`. It can be immediate,
/// or still in memory. The latter is an optimization, to delay reading that chunk of
/// memory and to avoid having to store arbitrary-sized data here.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable, Hash)]
pub enum Operand<Tag=(), Id=AllocId> {
Immediate(Immediate<Tag, Id>),
Indirect(MemPlace<Tag, Id>),
}
}
-#[derive(Copy, Clone, Debug, PartialEq)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct OpTy<'tcx, Tag=()> {
op: Operand<Tag>, // Keep this private; it helps enforce invariants.
pub layout: TyLayout<'tcx>,
#![feature(range_is_empty)]
#![feature(stmt_expr_attributes)]
#![feature(bool_to_option)]
+#![feature(trait_alias)]
#![recursion_limit="256"]
mutability,
ty,
user_ty: UserTypeProjections::none(),
- name: None,
source_info,
- visibility_scope: source_info.scope,
internal: false,
local_info: LocalInfo::Other,
is_block_tail: None,
SourceScopeData { span: span, parent_scope: None }, 1
),
ClearCrossCrate::Clear,
- None,
local_decls_for_sig(&sig, span),
IndexVec::new(),
sig.inputs().len(),
SourceScopeData { span: self.span, parent_scope: None }, 1
),
ClearCrossCrate::Clear,
- None,
self.local_decls,
IndexVec::new(),
self.sig.inputs().len(),
SourceScopeData { span: span, parent_scope: None }, 1
),
ClearCrossCrate::Clear,
- None,
local_decls,
IndexVec::new(),
sig.inputs().len(),
SourceScopeData { span: span, parent_scope: None }, 1
),
ClearCrossCrate::Clear,
- None,
local_decls,
IndexVec::new(),
sig.inputs().len(),
self, InterpCx, ScalarMaybeUndef, Immediate, OpTy,
StackPopCleanup, LocalValue, LocalState, AllocId, Frame,
Allocation, MemoryKind, ImmTy, Pointer, Memory, PlaceTy,
- Operand as InterpOperand,
+ Operand as InterpOperand, intern_const_alloc_recursive,
};
use crate::const_eval::error_to_const_error;
use crate::transform::{MirPass, MirSource};
body.basic_blocks().clone(),
Default::default(),
ClearCrossCrate::Clear,
- None,
body.local_decls.clone(),
Default::default(),
body.arg_count,
}
fn should_const_prop(&mut self, op: OpTy<'tcx>) -> bool {
- if self.tcx.sess.opts.debugging_opts.mir_opt_level >= 2 {
- return true;
- } else if self.tcx.sess.opts.debugging_opts.mir_opt_level == 0 {
+ let mir_opt_level = self.tcx.sess.opts.debugging_opts.mir_opt_level;
+
+ if mir_opt_level == 0 {
return false;
}
interpret::Operand::Immediate(Immediate::ScalarPair(ScalarMaybeUndef::Scalar(l),
ScalarMaybeUndef::Scalar(r))) =>
l.is_bits() && r.is_bits(),
+ interpret::Operand::Indirect(_) if mir_opt_level >= 2 => {
+ intern_const_alloc_recursive(
+ &mut self.ecx,
+ None,
+ op.assert_mem_place()
+ ).expect("failed to intern alloc");
+ true
+ },
_ => false
}
}
use rustc_index::bit_set::{BitSet, BitMatrix};
use std::borrow::Cow;
use std::iter;
-use std::mem;
use crate::transform::{MirPass, MirSource};
use crate::transform::simplify;
use crate::transform::no_landing_pads::no_landing_pads;
mutability: Mutability::Mut,
ty: ret_ty,
user_ty: UserTypeProjections::none(),
- name: None,
source_info,
- visibility_scope: source_info.scope,
internal: false,
is_block_tail: None,
local_info: LocalInfo::Other
}
}
- let dummy_local = LocalDecl::new_internal(tcx.mk_unit(), body.span);
-
- // Gather live locals and their indices replacing values in body.local_decls
- // with a dummy to avoid changing local indices.
+ // Gather live local types and their indices.
let mut locals = IndexVec::<GeneratorSavedLocal, _>::new();
let mut tys = IndexVec::<GeneratorSavedLocal, _>::new();
- let mut decls = IndexVec::<GeneratorSavedLocal, _>::new();
for (idx, local) in live_locals.iter().enumerate() {
- let var = mem::replace(&mut body.local_decls[local], dummy_local.clone());
locals.push(local);
- tys.push(var.ty);
- decls.push(var);
+ tys.push(body.local_decls[local].ty);
debug!("generator saved local {:?} => {:?}", GeneratorSavedLocal::from(idx), local);
}
field_tys: tys,
variant_fields,
storage_conflicts,
- __local_debuginfo_codegen_only_do_not_use: decls,
};
(remap, layout, storage_liveness)
mutability: Mutability::Mut,
ty: tcx.mk_unit(),
user_ty: UserTypeProjections::none(),
- name: None,
source_info,
- visibility_scope: source_info.scope,
internal: false,
is_block_tail: None,
local_info: LocalInfo::Other
mutbl: hir::Mutability::Mutable,
}),
user_ty: UserTypeProjections::none(),
- name: None,
source_info,
- visibility_scope: source_info.scope,
internal: false,
is_block_tail: None,
local_info: LocalInfo::Other
debug!("should_inline({:?})", callsite);
let tcx = self.tcx;
- // Don't inline closures that have capture debuginfo
- // FIXME: Handle closures better
- if callee_body.__upvar_debuginfo_codegen_only_do_not_use.len() > 0 {
- debug!(" upvar debuginfo present - not inlining");
- return false;
- }
-
// Cannot inline generators which haven't been transformed yet
if callee_body.yield_ty.is_some() {
debug!(" yield ty present - not inlining");
local.source_info.scope =
scope_map[local.source_info.scope];
local.source_info.span = callsite.location.span;
- local.visibility_scope = scope_map[local.visibility_scope];
let idx = caller_body.local_decls.push(local);
local_map.push(idx);
tcx: self.tcx,
};
+ for mut var_debug_info in callee_body.var_debug_info.drain(..) {
+ integrator.visit_var_debug_info(&mut var_debug_info);
+ caller_body.var_debug_info.push(var_debug_info);
+ }
for (bb, mut block) in callee_body.basic_blocks_mut().drain_enumerated(..) {
integrator.visit_basic_block_data(bb, &mut block);
// memory usage?
body.source_scopes.clone(),
body.source_scope_local_data.clone(),
- None,
initial_locals,
IndexVec::new(),
0,
check_operand(tcx, discr, span, def_id, body)
}
+ // FIXME(ecstaticmorse): We probably want to allow `Unreachable` unconditionally.
+ TerminatorKind::Unreachable if tcx.features().const_if_match => Ok(()),
+
| TerminatorKind::Abort | TerminatorKind::Unreachable => {
Err((span, "const fn with unreachable code is not stable".into()))
}
use rustc::ty::TyCtxt;
use rustc::mir::*;
use rustc::mir::visit::{MutVisitor, Visitor, PlaceContext, MutatingUseContext};
-use rustc::session::config::DebugInfo;
use std::borrow::Cow;
use crate::transform::{MirPass, MirSource};
marker.locals.insert(arg);
}
- // We may need to keep dead user variables live for debuginfo.
- if tcx.sess.opts.debuginfo == DebugInfo::Full {
- for local in body.vars_iter() {
- marker.locals.insert(local);
- }
- }
-
marker.locals
};
match context {
PlaceContext::NonUse(NonUseContext::StorageLive) => local_use.alive = Some(location),
PlaceContext::NonUse(NonUseContext::StorageDead) => local_use.dead = Some(location),
+ PlaceContext::NonUse(NonUseContext::VarDebugInfo) => {}
_ => {
local_use.use_count += 1;
if local_use.first_use.is_none() {
//! Def-use analysis.
-use rustc::mir::{Body, Local, Location, PlaceElem};
+use rustc::mir::{Body, Local, Location, PlaceElem, VarDebugInfo};
use rustc::mir::visit::{PlaceContext, MutVisitor, Visitor};
use rustc::ty::TyCtxt;
use rustc_index::vec::IndexVec;
#[derive(Clone)]
pub struct Info {
+ // FIXME(eddyb) use smallvec where possible.
pub defs_and_uses: Vec<Use>,
+ var_debug_info_indices: Vec<usize>,
}
#[derive(Clone)]
let mut finder = DefUseFinder {
info: mem::take(&mut self.info),
+ var_debug_info_index: 0,
+ in_var_debug_info: false,
};
finder.visit_body(body);
self.info = finder.info
new_local: Local,
tcx: TyCtxt<'tcx>,
) {
- for place_use in &self.info[local].defs_and_uses {
- MutateUseVisitor::new(local, new_local, body, tcx)
- .visit_location(body, place_use.location)
+ let mut visitor = MutateUseVisitor::new(local, new_local, body, tcx);
+ let info = &self.info[local];
+ for place_use in &info.defs_and_uses {
+ visitor.visit_location(body, place_use.location)
+ }
+ // Update debuginfo as well, alongside defs/uses.
+ for &i in &info.var_debug_info_indices {
+ visitor.visit_var_debug_info(&mut body.var_debug_info[i]);
}
}
struct DefUseFinder {
info: IndexVec<Local, Info>,
+ var_debug_info_index: usize,
+ in_var_debug_info: bool,
}
impl Visitor<'_> for DefUseFinder {
&local: &Local,
context: PlaceContext,
location: Location) {
- self.info[local].defs_and_uses.push(Use {
- context,
- location,
- });
+ let info = &mut self.info[local];
+ if self.in_var_debug_info {
+ info.var_debug_info_indices.push(self.var_debug_info_index);
+ } else {
+ info.defs_and_uses.push(Use {
+ context,
+ location,
+ });
+ }
+ }
+ fn visit_var_debug_info(&mut self, var_debug_info: &VarDebugInfo<'tcx>) {
+ assert!(!self.in_var_debug_info);
+ self.in_var_debug_info = true;
+ self.super_var_debug_info(var_debug_info);
+ self.in_var_debug_info = false;
+ self.var_debug_info_index += 1;
}
}
fn new() -> Info {
Info {
defs_and_uses: vec![],
+ var_debug_info_indices: vec![],
}
}
fn clear(&mut self) {
self.defs_and_uses.clear();
+ self.var_debug_info_indices.clear();
}
pub fn def_count(&self) -> usize {
write!(w, "mut ")?;
}
- if let Some(name) = decl.name {
- write!(w, r#"{:?}: {}; // {}<br align="left"/>"#,
- Place::from(local), escape(&decl.ty), name)?;
- } else {
- write!(w, r#"{:?}: {};<br align="left"/>"#,
- Place::from(local), escape(&decl.ty))?;
- }
+ write!(w, r#"{:?}: {};<br align="left"/>"#,
+ Place::from(local), escape(&decl.ty))?;
+ }
+
+ for var_debug_info in &body.var_debug_info {
+ write!(w, r#"debug {} => {};<br align="left"/>"#,
+ var_debug_info.name, escape(&var_debug_info.place))?;
}
writeln!(w, ">;")
PlaceContext::MutatingUse(MutatingUseContext::Drop) =>
Some(DefUse::Drop),
+
+ // Debug info is neither def nor use.
+ PlaceContext::NonUse(NonUseContext::VarDebugInfo) => None,
}
}
) -> io::Result<()> {
let indent = depth * INDENT.len();
+ // Local variable debuginfo.
+ for var_debug_info in &body.var_debug_info {
+ if var_debug_info.source_info.scope != parent {
+ // Not declared in this scope.
+ continue;
+ }
+
+ let indented_debug_info = format!(
+ "{0:1$}debug {2} => {3:?};",
+ INDENT,
+ indent,
+ var_debug_info.name,
+ var_debug_info.place,
+ );
+
+ writeln!(
+ w,
+ "{0:1$} // in {2}",
+ indented_debug_info,
+ ALIGN,
+ comment(tcx, var_debug_info.source_info),
+ )?;
+ }
+
// Local variable types (including the user's name in a comment).
for (local, local_decl) in body.local_decls.iter_enumerated() {
if (1..body.arg_count+1).contains(&local.index()) {
let local_name = if local == RETURN_PLACE {
format!(" return place")
- } else if let Some(name) = local_decl.name {
- format!(" \"{}\"", name)
} else {
String::new()
};
use syntax::ast::{ItemKind, ImplItem, ImplItemKind, TraitItem, TraitItemKind, UseTree, UseTreeKind};
use syntax::ast::{PathSegment, IsAuto, Constness, IsAsync, Unsafety, Defaultness, Extern, StrLit};
use syntax::ast::{Visibility, VisibilityKind, Mutability, FnHeader, ForeignItem, ForeignItemKind};
-use syntax::ast::{Ty, TyKind, Generics, TraitRef, EnumDef, VariantData, StructField};
+use syntax::ast::{Ty, TyKind, Generics, TraitRef, EnumDef, Variant, VariantData, StructField};
use syntax::ast::{Mac, MacDelimiter, Block, BindingMode, FnDecl, FnSig, SelfKind, Param};
use syntax::print::pprust;
use syntax::ptr::P;
}
/// Parses a macro invocation inside a `trait`, `impl` or `extern` block.
- fn parse_assoc_macro_invoc(&mut self, item_kind: &str, vis: Option<&Visibility>,
- at_end: &mut bool) -> PResult<'a, Option<Mac>>
- {
+ fn parse_assoc_macro_invoc(
+ &mut self,
+ item_kind: &str,
+ vis: Option<&Visibility>,
+ at_end: &mut bool,
+ ) -> PResult<'a, Option<Mac>> {
if self.token.is_path_start() &&
!(self.is_async_fn() && self.token.span.rust_2015()) {
let prev_span = self.prev_span;
}
}
- fn missing_assoc_item_kind_err(&self, item_type: &str, prev_span: Span)
- -> DiagnosticBuilder<'a>
- {
+ fn missing_assoc_item_kind_err(
+ &self,
+ item_type: &str,
+ prev_span: Span,
+ ) -> DiagnosticBuilder<'a> {
let expected_kinds = if item_type == "extern" {
"missing `fn`, `type`, or `static`"
} else {
let id = self.parse_ident()?;
let mut generics = self.parse_generics()?;
generics.where_clause = self.parse_where_clause()?;
- self.expect(&token::OpenDelim(token::Brace))?;
- let enum_definition = self.parse_enum_def(&generics).map_err(|e| {
+ let (variants, _) = self.parse_delim_comma_seq(
+ token::Brace,
+ |p| p.parse_enum_item(),
+ ).map_err(|e| {
self.recover_stmt();
- self.eat(&token::CloseDelim(token::Brace));
e
})?;
+
+ let enum_definition = EnumDef {
+ variants: variants.into_iter().filter_map(|v| v).collect(),
+ };
Ok((id, ItemKind::Enum(enum_definition, generics), None))
}
- /// Parses the part of an enum declaration following the `{`.
- fn parse_enum_def(&mut self, _generics: &Generics) -> PResult<'a, EnumDef> {
- let mut variants = Vec::new();
- // FIXME: Consider using `parse_delim_comma_seq`.
- // We could then remove eating comma in `recover_nested_adt_item`.
- while self.token != token::CloseDelim(token::Brace) {
- let variant_attrs = self.parse_outer_attributes()?;
- let vlo = self.token.span;
-
- let vis = self.parse_visibility(FollowedByType::No)?;
- if !self.recover_nested_adt_item(kw::Enum)? {
- // Item already parsed, we need to skip this variant.
- continue
- }
- let ident = self.parse_ident()?;
+ fn parse_enum_item(&mut self) -> PResult<'a, Option<Variant>> {
+ let variant_attrs = self.parse_outer_attributes()?;
+ let vlo = self.token.span;
- let struct_def = if self.check(&token::OpenDelim(token::Brace)) {
- // Parse a struct variant.
- let (fields, recovered) = self.parse_record_struct_body()?;
- VariantData::Struct(fields, recovered)
- } else if self.check(&token::OpenDelim(token::Paren)) {
- VariantData::Tuple(
- self.parse_tuple_struct_body()?,
- DUMMY_NODE_ID,
- )
- } else {
- VariantData::Unit(DUMMY_NODE_ID)
- };
+ let vis = self.parse_visibility(FollowedByType::No)?;
+ if !self.recover_nested_adt_item(kw::Enum)? {
+ return Ok(None)
+ }
+ let ident = self.parse_ident()?;
- let disr_expr = if self.eat(&token::Eq) {
- Some(AnonConst {
- id: DUMMY_NODE_ID,
- value: self.parse_expr()?,
- })
- } else {
- None
- };
+ let struct_def = if self.check(&token::OpenDelim(token::Brace)) {
+ // Parse a struct variant.
+ let (fields, recovered) = self.parse_record_struct_body()?;
+ VariantData::Struct(fields, recovered)
+ } else if self.check(&token::OpenDelim(token::Paren)) {
+ VariantData::Tuple(
+ self.parse_tuple_struct_body()?,
+ DUMMY_NODE_ID,
+ )
+ } else {
+ VariantData::Unit(DUMMY_NODE_ID)
+ };
- let vr = ast::Variant {
- ident,
- vis,
+ let disr_expr = if self.eat(&token::Eq) {
+ Some(AnonConst {
id: DUMMY_NODE_ID,
- attrs: variant_attrs,
- data: struct_def,
- disr_expr,
- span: vlo.to(self.prev_span),
- is_placeholder: false,
- };
- variants.push(vr);
+ value: self.parse_expr()?,
+ })
+ } else {
+ None
+ };
- if !self.eat(&token::Comma) {
- if self.token.is_ident() && !self.token.is_reserved_ident() {
- let sp = self.sess.source_map().next_point(self.prev_span);
- self.struct_span_err(sp, "missing comma")
- .span_suggestion_short(
- sp,
- "missing comma",
- ",".to_owned(),
- Applicability::MaybeIncorrect,
- )
- .emit();
- } else {
- break;
- }
- }
- }
- self.expect(&token::CloseDelim(token::Brace))?;
+ let vr = ast::Variant {
+ ident,
+ vis,
+ id: DUMMY_NODE_ID,
+ attrs: variant_attrs,
+ data: struct_def,
+ disr_expr,
+ span: vlo.to(self.prev_span),
+ is_placeholder: false,
+ };
- Ok(ast::EnumDef { variants })
+ Ok(Some(vr))
}
/// Parses `struct Foo { ... }`.
let kw_token = self.token.clone();
let kw_str = pprust::token_to_string(&kw_token);
let item = self.parse_item()?;
- self.eat(&token::Comma);
self.struct_span_err(
kw_token.span,
recovered = true;
break;
}
- Err(mut e) => {
+ Err(mut expect_err) => {
+ let sp = self.sess.source_map().next_point(self.prev_span);
+ let token_str = pprust::token_kind_to_string(t);
+
// Attempt to keep parsing if it was a similar separator.
if let Some(ref tokens) = t.similar_tokens() {
if tokens.contains(&self.token.kind) {
self.bump();
}
}
- e.emit();
+
// Attempt to keep parsing if it was an omitted separator.
match f(self) {
Ok(t) => {
+ // Parsed successfully, therefore most probably the code only
+ // misses a separator.
+ expect_err
+ .span_suggestion_short(
+ sp,
+ &format!("missing `{}`", token_str),
+ token_str,
+ Applicability::MaybeIncorrect,
+ )
+ .emit();
+
v.push(t);
continue;
},
Err(mut e) => {
+ // Parsing failed, therefore it must be something more serious
+ // than just a missing separator.
+ expect_err.emit();
+
e.cancel();
break;
}
"`continue` pointing to a labeled block")
.span_label(e.span,
"labeled blocks cannot be `continue`'d")
- .span_note(block.span,
- "labeled block the continue points to")
+ .span_label(block.span,
+ "labeled block the `continue` points to")
.emit();
}
}
.emit();
} else {
let msg = format!("`{}` is private, and cannot be re-exported", ident);
- let note_msg =
- format!("consider marking `{}` as `pub` in the imported module", ident);
+ let note_msg = format!(
+ "consider marking `{}` as `pub` in the imported module",
+ ident,
+ );
struct_span_err!(self.r.session, directive.span, E0364, "{}", &msg)
.span_note(directive.span, ¬e_msg)
.emit();
let mut base = super::windows_msvc_base::opts();
base.max_atomic_width = Some(64);
base.has_elf_tls = true;
+ base.features = "+neon,+fp-armv8".to_string();
// FIXME: this shouldn't be panic=abort, it should be panic=unwind
base.panic_strategy = PanicStrategy::Abort;
--- /dev/null
+use crate::spec::{LldFlavor, LinkArgs, LinkerFlavor, PanicStrategy, TargetOptions};
+use std::default::Default;
+
+pub fn opts() -> TargetOptions {
+ let mut pre_link_args = LinkArgs::new();
+ pre_link_args.insert(LinkerFlavor::Lld(LldFlavor::Ld), vec![
+ "--build-id".to_string(),
+ "--hash-style=gnu".to_string(),
+ "--Bstatic".to_string(),
+ ]);
+
+ TargetOptions {
+ disable_redzone: true,
+ linker: Some("rust-lld".to_owned()),
+ executables: true,
+ has_elf_tls: true,
+ linker_is_gnu: true,
+ pre_link_args,
+ no_default_libraries: true,
+ panic_strategy: PanicStrategy::Abort,
+ position_independent_executables: true,
+ relocation_model: "static".to_string(),
+ target_family: None,
+ tls_model: "initial-exec".to_string(),
+ .. Default::default()
+ }
+}
mod freebsd_base;
mod haiku_base;
mod hermit_base;
+mod hermit_kernel_base;
mod linux_base;
mod linux_kernel_base;
mod linux_musl_base;
("aarch64-unknown-hermit", aarch64_unknown_hermit),
("x86_64-unknown-hermit", x86_64_unknown_hermit),
+ ("x86_64-unknown-hermit-kernel", x86_64_unknown_hermit_kernel),
("riscv32i-unknown-none-elf", riscv32i_unknown_none_elf),
("riscv32imc-unknown-none-elf", riscv32imc_unknown_none_elf),
("riscv32imac-unknown-none-elf", riscv32imac_unknown_none_elf),
("riscv64imac-unknown-none-elf", riscv64imac_unknown_none_elf),
("riscv64gc-unknown-none-elf", riscv64gc_unknown_none_elf),
+ ("riscv64gc-unknown-linux-gnu", riscv64gc_unknown_linux_gnu),
("aarch64-unknown-none", aarch64_unknown_none),
("aarch64-unknown-none-softfloat", aarch64_unknown_none_softfloat),
--- /dev/null
+use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
+
+pub fn target() -> TargetResult {
+ Ok(Target {
+ llvm_target: "riscv64-unknown-linux-gnu".to_string(),
+ target_endian: "little".to_string(),
+ target_pointer_width: "64".to_string(),
+ target_c_int_width: "32".to_string(),
+ target_env: "gnu".to_string(),
+ data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".to_string(),
+ arch: "riscv64".to_string(),
+ target_os: "linux".to_string(),
+ target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
+ options: TargetOptions {
+ abi_blacklist: super::riscv_base::abi_blacklist(),
+ code_model: Some("medium".to_string()),
+ cpu: "generic-rv64".to_string(),
+ features: "+m,+a,+f,+d,+c".to_string(),
+ llvm_abiname: "lp64d".to_string(),
+ max_atomic_width: Some(64),
+ ..super::linux_base::opts()
+ },
+ })
+}
--- /dev/null
+use crate::spec::{LldFlavor, LinkerFlavor, Target, TargetResult};
+
+pub fn target() -> TargetResult {
+ let mut base = super::hermit_kernel_base::opts();
+ base.cpu = "x86-64".to_string();
+ base.max_atomic_width = Some(64);
+ base.features =
+ "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float"
+ .to_string();
+ base.stack_probes = true;
+
+ Ok(Target {
+ llvm_target: "x86_64-unknown-hermit".to_string(),
+ target_endian: "little".to_string(),
+ target_pointer_width: "64".to_string(),
+ target_c_int_width: "32".to_string(),
+ data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(),
+ arch: "x86_64".to_string(),
+ target_os: "hermit".to_string(),
+ target_env: String::new(),
+ target_vendor: "unknown".to_string(),
+ linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ options: base,
+ })
+}
formal_tys.clone()
};
- let mut final_arg_types: Vec<(usize, Ty<'_>)> = vec![];
+ let mut final_arg_types: Vec<(usize, Ty<'_>, Ty<'_>)> = vec![];
// Check the arguments.
// We do this in a pretty awful way: first we type-check any arguments
// We're processing function arguments so we definitely want to use
// two-phase borrows.
self.demand_coerce(&arg, checked_ty, coerce_ty, AllowTwoPhase::Yes);
- final_arg_types.push((i, coerce_ty));
+ final_arg_types.push((i, checked_ty, coerce_ty));
// 3. Relate the expected type and the formal one,
// if the expected type was used for the coercion.
vec![self.tcx.types.err; len]
}
- /// Given a vec of evaluated `FullfillmentError`s and an `fn` call argument expressions, we
- /// walk the resolved types for each argument to see if any of the `FullfillmentError`s
- /// reference a type argument. If they do, and there's only *one* argument that does, we point
- /// at the corresponding argument's expression span instead of the `fn` call path span.
+ /// Given a vec of evaluated `FulfillmentError`s and an `fn` call argument expressions, we walk
+ /// the checked and coerced types for each argument to see if any of the `FulfillmentError`s
+ /// reference a type argument. The reason to walk also the checked type is that the coerced type
+ /// can be not easily comparable with predicate type (because of coercion). If the types match
+ /// for either checked or coerced type, and there's only *one* argument that does, we point at
+ /// the corresponding argument's expression span instead of the `fn` call path span.
fn point_at_arg_instead_of_call_if_possible(
&self,
errors: &mut Vec<traits::FulfillmentError<'_>>,
- final_arg_types: &[(usize, Ty<'tcx>)],
+ final_arg_types: &[(usize, Ty<'tcx>, Ty<'tcx>)],
call_sp: Span,
args: &'tcx [hir::Expr],
) {
for error in errors {
if let ty::Predicate::Trait(predicate) = error.obligation.predicate {
// Collect the argument position for all arguments that could have caused this
- // `FullfillmentError`.
+ // `FulfillmentError`.
let mut referenced_in = final_arg_types.iter()
+ .map(|(i, checked_ty, _)| (i, checked_ty))
+ .chain(final_arg_types.iter().map(|(i, _, coerced_ty)| (i, coerced_ty)))
.flat_map(|(i, ty)| {
let ty = self.resolve_vars_if_possible(ty);
// We walk the argument type because the argument's type could have
- // been `Option<T>`, but the `FullfillmentError` references `T`.
+ // been `Option<T>`, but the `FulfillmentError` references `T`.
ty.walk()
.filter(|&ty| ty == predicate.skip_binder().self_ty())
.map(move |_| *i)
- });
- if let (Some(ref_in), None) = (referenced_in.next(), referenced_in.next()) {
+ })
+ .collect::<Vec<_>>();
+
+ // Both checked and coerced types could have matched, thus we need to remove
+ // duplicates.
+ referenced_in.dedup();
+
+ if let (Some(ref_in), None) = (referenced_in.pop(), referenced_in.pop()) {
// We make sure that only *one* argument matches the obligation failure
- // and thet the obligation's span to its expression's.
+ // and we assign the obligation's span to its expression's.
error.obligation.cause.span = args[ref_in].span;
error.points_at_arg_span = true;
}
}
}
- /// Given a vec of evaluated `FullfillmentError`s and an `fn` call expression, we walk the
- /// `PathSegment`s and resolve their type parameters to see if any of the `FullfillmentError`s
+ /// Given a vec of evaluated `FulfillmentError`s and an `fn` call expression, we walk the
+ /// `PathSegment`s and resolve their type parameters to see if any of the `FulfillmentError`s
/// were caused by them. If they were, we point at the corresponding type argument's span
/// instead of the `fn` call path span.
fn point_at_type_arg_instead_of_call_if_possible(
use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
use crate::hir::def_id::DefId;
-use rustc::traits::{self, ObligationCauseCode};
+use rustc::traits::{self, ObligationCause, ObligationCauseCode};
use rustc::ty::{self, Ty, TyCtxt, GenericParamDefKind, TypeFoldable, ToPredicate};
use rustc::ty::subst::{Subst, InternalSubsts};
use rustc::util::nodemap::{FxHashSet, FxHashMap};
// The first type is `receiver_ty`, which we know its not equal to `self_ty`; skip it.
autoderef.next();
+ let receiver_trait_def_id = fcx.tcx.require_lang_item(
+ lang_items::ReceiverTraitLangItem,
+ None,
+ );
+
// Keep dereferencing `receiver_ty` until we get to `self_ty`.
loop {
if let Some((potential_self_ty, _)) = autoderef.next() {
}
break
+ } else {
+ // Without `feature(arbitrary_self_types)`, we require that each step in the
+ // deref chain implement `receiver`
+ if !arbitrary_self_types_enabled
+ && !receiver_is_implemented(
+ fcx,
+ receiver_trait_def_id,
+ cause.clone(),
+ potential_self_ty,
+ )
+ {
+ return false
+ }
}
} else {
debug!("receiver_is_valid: type `{:?}` does not deref to `{:?}`",
// unecessary errors (#58712).
return receiver_ty.references_error();
}
-
- // Without the `arbitrary_self_types` feature, `receiver_ty` must directly deref to
- // `self_ty`. Enforce this by only doing one iteration of the loop.
- if !arbitrary_self_types_enabled {
- return false
- }
}
// Without `feature(arbitrary_self_types)`, we require that `receiver_ty` implements `Receiver`.
- if !arbitrary_self_types_enabled {
- let trait_def_id = match fcx.tcx.lang_items().receiver_trait() {
- Some(did) => did,
- None => {
- debug!("receiver_is_valid: missing Receiver trait");
- return false
- }
- };
+ if !arbitrary_self_types_enabled
+ && !receiver_is_implemented(fcx, receiver_trait_def_id, cause.clone(), receiver_ty)
+ {
+ return false
+ }
- let trait_ref = ty::TraitRef{
- def_id: trait_def_id,
- substs: fcx.tcx.mk_substs_trait(receiver_ty, &[]),
- };
+ true
+}
+
+fn receiver_is_implemented(
+ fcx: &FnCtxt<'_, 'tcx>,
+ receiver_trait_def_id: DefId,
+ cause: ObligationCause<'tcx>,
+ receiver_ty: Ty<'tcx>,
+) -> bool {
+ let trait_ref = ty::TraitRef{
+ def_id: receiver_trait_def_id,
+ substs: fcx.tcx.mk_substs_trait(receiver_ty, &[]),
+ };
- let obligation = traits::Obligation::new(
- cause,
- fcx.param_env,
- trait_ref.to_predicate()
- );
+ let obligation = traits::Obligation::new(
+ cause,
+ fcx.param_env,
+ trait_ref.to_predicate()
+ );
- if !fcx.predicate_must_hold_modulo_regions(&obligation) {
- debug!("receiver_is_valid: type `{:?}` does not implement `Receiver` trait",
- receiver_ty);
- return false
- }
+ if fcx.predicate_must_hold_modulo_regions(&obligation) {
+ true
+ } else {
+ debug!("receiver_is_implemented: type `{:?}` does not implement `Receiver` trait",
+ receiver_ty);
+ false
}
-
- true
}
fn check_variances_for_type_defn<'tcx>(
}
}
+enum ErrorKind {
+ ResolutionFailure,
+ AnchorFailure(&'static str),
+}
+
struct LinkCollector<'a, 'tcx> {
cx: &'a DocContext<'tcx>,
mod_ids: Vec<hir::HirId>,
}
}
+ fn variant_field(
+ &self,
+ path_str: &str,
+ current_item: &Option<String>,
+ module_id: syntax::ast::NodeId,
+ ) -> Result<(Res, Option<String>), ErrorKind> {
+ let cx = self.cx;
+
+ let mut split = path_str.rsplitn(3, "::");
+ let variant_field_name = split
+ .next()
+ .map(|f| Symbol::intern(f))
+ .ok_or(ErrorKind::ResolutionFailure)?;
+ let variant_name = split
+ .next()
+ .map(|f| Symbol::intern(f))
+ .ok_or(ErrorKind::ResolutionFailure)?;
+ let path = split.next().map(|f| {
+ if f == "self" || f == "Self" {
+ if let Some(name) = current_item.as_ref() {
+ return name.clone();
+ }
+ }
+ f.to_owned()
+ }).ok_or(ErrorKind::ResolutionFailure)?;
+ let (_, ty_res) = cx.enter_resolver(|resolver| {
+ resolver.resolve_str_path_error(DUMMY_SP, &path, TypeNS, module_id)
+ }).map_err(|_| ErrorKind::ResolutionFailure)?;
+ if let Res::Err = ty_res {
+ return Err(ErrorKind::ResolutionFailure);
+ }
+ let ty_res = ty_res.map_id(|_| panic!("unexpected node_id"));
+ match ty_res {
+ Res::Def(DefKind::Enum, did) => {
+ if cx.tcx.inherent_impls(did)
+ .iter()
+ .flat_map(|imp| cx.tcx.associated_items(*imp))
+ .any(|item| item.ident.name == variant_name) {
+ return Err(ErrorKind::ResolutionFailure);
+ }
+ match cx.tcx.type_of(did).kind {
+ ty::Adt(def, _) if def.is_enum() => {
+ if def.all_fields()
+ .any(|item| item.ident.name == variant_field_name) {
+ Ok((ty_res,
+ Some(format!("variant.{}.field.{}",
+ variant_name, variant_field_name))))
+ } else {
+ Err(ErrorKind::ResolutionFailure)
+ }
+ }
+ _ => Err(ErrorKind::ResolutionFailure),
+ }
+ }
+ _ => Err(ErrorKind::ResolutionFailure)
+ }
+ }
+
/// Resolves a string as a path within a particular namespace. Also returns an optional
/// URL fragment in the case of variants and methods.
- fn resolve(&self,
- path_str: &str,
- ns: Namespace,
- current_item: &Option<String>,
- parent_id: Option<hir::HirId>)
- -> Result<(Res, Option<String>), ()>
- {
+ fn resolve(
+ &self,
+ path_str: &str,
+ ns: Namespace,
+ current_item: &Option<String>,
+ parent_id: Option<hir::HirId>,
+ extra_fragment: &Option<String>,
+ ) -> Result<(Res, Option<String>), ErrorKind> {
let cx = self.cx;
// In case we're in a module, try to resolve the relative path.
resolver.resolve_str_path_error(DUMMY_SP, &path_str, ns, module_id)
});
let result = match result {
- Ok((_, Res::Err)) => Err(()),
- _ => result,
+ Ok((_, Res::Err)) => Err(ErrorKind::ResolutionFailure),
+ _ => result.map_err(|_| ErrorKind::ResolutionFailure),
};
if let Ok((_, res)) = result {
let value = match res {
Res::Def(DefKind::Method, _) | Res::Def(DefKind::AssocConst, _) => true,
Res::Def(DefKind::AssocTy, _) => false,
- Res::Def(DefKind::Variant, _) => return handle_variant(cx, res),
+ Res::Def(DefKind::Variant, _) => {
+ return handle_variant(cx, res, extra_fragment);
+ }
// Not a trait item; just return what we found.
- Res::PrimTy(..) => return Ok((res, Some(path_str.to_owned()))),
- _ => return Ok((res, None))
+ Res::PrimTy(..) => {
+ if extra_fragment.is_some() {
+ return Err(
+ ErrorKind::AnchorFailure(
+ "primitive types cannot be followed by anchors"));
+ }
+ return Ok((res, Some(path_str.to_owned())));
+ }
+ _ => return Ok((res, extra_fragment.clone()))
};
if value != (ns == ValueNS) {
- return Err(())
+ return Err(ErrorKind::ResolutionFailure)
}
} else if let Some(prim) = is_primitive(path_str, ns) {
+ if extra_fragment.is_some() {
+ return Err(
+ ErrorKind::AnchorFailure("primitive types cannot be followed by anchors"));
+ }
return Ok((prim, Some(path_str.to_owned())))
} else {
// If resolution failed, it may still be a method
// because methods are not handled by the resolver
// If so, bail when we're not looking for a value.
if ns != ValueNS {
- return Err(())
+ return Err(ErrorKind::ResolutionFailure)
}
}
// Try looking for methods and associated items.
let mut split = path_str.rsplitn(2, "::");
- let item_name = if let Some(first) = split.next() {
- Symbol::intern(first)
- } else {
- return Err(())
- };
-
- let mut path = if let Some(second) = split.next() {
- second.to_owned()
- } else {
- return Err(())
- };
-
- if path == "self" || path == "Self" {
- if let Some(name) = current_item.as_ref() {
- path = name.clone();
+ let item_name = split.next()
+ .map(|f| Symbol::intern(f))
+ .ok_or(ErrorKind::ResolutionFailure)?;
+ let path = split.next().map(|f| {
+ if f == "self" || f == "Self" {
+ if let Some(name) = current_item.as_ref() {
+ return name.clone();
+ }
}
- }
+ f.to_owned()
+ }).ok_or(ErrorKind::ResolutionFailure)?;
+
if let Some(prim) = is_primitive(&path, TypeNS) {
- let did = primitive_impl(cx, &path).ok_or(())?;
+ let did = primitive_impl(cx, &path).ok_or(ErrorKind::ResolutionFailure)?;
return cx.tcx.associated_items(did)
.find(|item| item.ident.name == item_name)
.and_then(|item| match item.kind {
_ => None,
})
.map(|out| (prim, Some(format!("{}#{}.{}", path, out, item_name))))
- .ok_or(());
+ .ok_or(ErrorKind::ResolutionFailure);
}
let (_, ty_res) = cx.enter_resolver(|resolver| {
resolver.resolve_str_path_error(DUMMY_SP, &path, TypeNS, module_id)
- })?;
+ }).map_err(|_| ErrorKind::ResolutionFailure)?;
if let Res::Err = ty_res {
- return Err(());
+ return self.variant_field(path_str, current_item, module_id);
}
let ty_res = ty_res.map_id(|_| panic!("unexpected node_id"));
match ty_res {
let out = match item.kind {
ty::AssocKind::Method if ns == ValueNS => "method",
ty::AssocKind::Const if ns == ValueNS => "associatedconstant",
- _ => return Err(())
+ _ => return self.variant_field(path_str, current_item, module_id),
};
- Ok((ty_res, Some(format!("{}.{}", out, item_name))))
+ if extra_fragment.is_some() {
+ Err(ErrorKind::AnchorFailure(
+ if item.kind == ty::AssocKind::Method {
+ "methods cannot be followed by anchors"
+ } else {
+ "associated constants cannot be followed by anchors"
+ }))
+ } else {
+ Ok((ty_res, Some(format!("{}.{}", out, item_name))))
+ }
} else {
match cx.tcx.type_of(did).kind {
ty::Adt(def, _) => {
.iter()
.find(|item| item.ident.name == item_name)
} {
- Ok((ty_res,
- Some(format!("{}.{}",
- if def.is_enum() {
- "variant"
- } else {
- "structfield"
- },
- item.ident))))
+ if extra_fragment.is_some() {
+ Err(ErrorKind::AnchorFailure(
+ if def.is_enum() {
+ "enum variants cannot be followed by anchors"
+ } else {
+ "struct fields cannot be followed by anchors"
+ }))
+ } else {
+ Ok((ty_res,
+ Some(format!("{}.{}",
+ if def.is_enum() {
+ "variant"
+ } else {
+ "structfield"
+ },
+ item.ident))))
+ }
} else {
- Err(())
+ self.variant_field(path_str, current_item, module_id)
}
}
- _ => Err(()),
+ _ => self.variant_field(path_str, current_item, module_id),
}
}
}
"tymethod"
}
}
- _ => return Err(())
+ _ => return self.variant_field(path_str, current_item, module_id),
};
- Ok((ty_res, Some(format!("{}.{}", kind, item_name))))
+ if extra_fragment.is_some() {
+ Err(ErrorKind::AnchorFailure(
+ if item.kind == ty::AssocKind::Const {
+ "associated constants cannot be followed by anchors"
+ } else if item.kind == ty::AssocKind::Type {
+ "associated types cannot be followed by anchors"
+ } else {
+ "methods cannot be followed by anchors"
+ }))
+ } else {
+ Ok((ty_res, Some(format!("{}.{}", kind, item_name))))
+ }
} else {
- Err(())
+ self.variant_field(path_str, current_item, module_id)
}
}
- _ => Err(())
+ _ => self.variant_field(path_str, current_item, module_id),
}
} else {
debug!("attempting to resolve item without parent module: {}", path_str);
- Err(())
+ Err(ErrorKind::ResolutionFailure)
}
}
}
}
let link = ori_link.replace("`", "");
+ let parts = link.split('#').collect::<Vec<_>>();
+ let (link, extra_fragment) = if parts.len() > 2 {
+ build_diagnostic(cx, &item, &link, &dox, link_range,
+ "has an issue with the link anchor.",
+ "only one `#` is allowed in a link",
+ None);
+ continue;
+ } else if parts.len() == 2 {
+ if parts[0].trim().is_empty() {
+ // This is an anchor to an element of the current page, nothing to do in here!
+ continue;
+ }
+ (parts[0].to_owned(), Some(parts[1].to_owned()))
+ } else {
+ (parts[0].to_owned(), None)
+ };
let (res, fragment) = {
let mut kind = None;
let path_str = if let Some(prefix) =
match kind {
Some(ns @ ValueNS) => {
- if let Ok(res) = self.resolve(path_str, ns, ¤t_item, base_node) {
- res
- } else {
- resolution_failure(cx, &item, path_str, &dox, link_range);
- // This could just be a normal link or a broken link
- // we could potentially check if something is
- // "intra-doc-link-like" and warn in that case.
- continue;
+ match self.resolve(path_str, ns, ¤t_item, base_node,
+ &extra_fragment) {
+ Ok(res) => res,
+ Err(ErrorKind::ResolutionFailure) => {
+ resolution_failure(cx, &item, path_str, &dox, link_range);
+ // This could just be a normal link or a broken link
+ // we could potentially check if something is
+ // "intra-doc-link-like" and warn in that case.
+ continue;
+ }
+ Err(ErrorKind::AnchorFailure(msg)) => {
+ anchor_failure(cx, &item, &ori_link, &dox, link_range, msg);
+ continue
+ }
}
}
Some(ns @ TypeNS) => {
- if let Ok(res) = self.resolve(path_str, ns, ¤t_item, base_node) {
- res
- } else {
- resolution_failure(cx, &item, path_str, &dox, link_range);
- // This could just be a normal link.
- continue;
+ match self.resolve(path_str, ns, ¤t_item, base_node,
+ &extra_fragment) {
+ Ok(res) => res,
+ Err(ErrorKind::ResolutionFailure) => {
+ resolution_failure(cx, &item, path_str, &dox, link_range);
+ // This could just be a normal link.
+ continue;
+ }
+ Err(ErrorKind::AnchorFailure(msg)) => {
+ anchor_failure(cx, &item, &ori_link, &dox, link_range, msg);
+ continue
+ }
}
}
None => {
// Try everything!
let candidates = PerNS {
- macro_ns: macro_resolve(cx, path_str).map(|res| (res, None)),
- type_ns: self
- .resolve(path_str, TypeNS, ¤t_item, base_node)
- .ok(),
- value_ns: self
- .resolve(path_str, ValueNS, ¤t_item, base_node)
- .ok()
- .and_then(|(res, fragment)| {
- // Constructors are picked up in the type namespace.
- match res {
- Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) => None,
- _ => Some((res, fragment))
- }
- }),
+ macro_ns: macro_resolve(cx, path_str)
+ .map(|res| (res, extra_fragment.clone())),
+ type_ns: match self.resolve(path_str, TypeNS, ¤t_item, base_node,
+ &extra_fragment) {
+ Err(ErrorKind::AnchorFailure(msg)) => {
+ anchor_failure(cx, &item, &ori_link, &dox, link_range, msg);
+ continue;
+ }
+ x => x.ok(),
+ },
+ value_ns: match self.resolve(path_str, ValueNS, ¤t_item,
+ base_node, &extra_fragment) {
+ Err(ErrorKind::AnchorFailure(msg)) => {
+ anchor_failure(cx, &item, &ori_link, &dox, link_range, msg);
+ continue;
+ }
+ x => x.ok(),
+ }
+ .and_then(|(res, fragment)| {
+ // Constructors are picked up in the type namespace.
+ match res {
+ Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) => None,
+ _ => match (fragment, extra_fragment) {
+ (Some(fragment), Some(_)) => {
+ // Shouldn't happen but who knows?
+ Some((res, Some(fragment)))
+ }
+ (fragment, None) | (None, fragment) => {
+ Some((res, fragment))
+ }
+ },
+ }
+ }),
};
if candidates.is_empty() {
}
Some(MacroNS) => {
if let Some(res) = macro_resolve(cx, path_str) {
- (res, None)
+ (res, extra_fragment)
} else {
resolution_failure(cx, &item, path_str, &dox, link_range);
continue
})
}
-/// Reports a resolution failure diagnostic.
-///
-/// If we cannot find the exact source span of the resolution failure, we use the span of the
-/// documentation attributes themselves. This is a little heavy-handed, so we display the markdown
-/// line containing the failure as a note as well.
-fn resolution_failure(
+fn build_diagnostic(
cx: &DocContext<'_>,
item: &Item,
path_str: &str,
dox: &str,
link_range: Option<Range<usize>>,
+ err_msg: &str,
+ short_err_msg: &str,
+ help_msg: Option<&str>,
) {
let hir_id = match cx.as_local_hir_id(item.def_id) {
Some(hir_id) => hir_id,
lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE,
hir_id,
sp,
- &format!("`[{}]` cannot be resolved, ignoring it...", path_str),
+ &format!("`[{}]` {}", path_str, err_msg),
);
if let Some(link_range) = link_range {
if let Some(sp) = super::source_span_for_markdown_range(cx, dox, &link_range, attrs) {
diag.set_span(sp);
- diag.span_label(sp, "cannot be resolved, ignoring");
+ diag.span_label(sp, short_err_msg);
} else {
// blah blah blah\nblah\nblah [blah] blah blah\nblah blah
// ^ ~~~~
));
}
};
- diag.help("to escape `[` and `]` characters, just add '\\' before them like \
- `\\[` or `\\]`");
+ if let Some(help_msg) = help_msg {
+ diag.help(help_msg);
+ }
diag.emit();
}
+/// Reports a resolution failure diagnostic.
+///
+/// If we cannot find the exact source span of the resolution failure, we use the span of the
+/// documentation attributes themselves. This is a little heavy-handed, so we display the markdown
+/// line containing the failure as a note as well.
+fn resolution_failure(
+ cx: &DocContext<'_>,
+ item: &Item,
+ path_str: &str,
+ dox: &str,
+ link_range: Option<Range<usize>>,
+) {
+ build_diagnostic(cx, item, path_str, dox, link_range,
+ "cannot be resolved, ignoring it.",
+ "cannot be resolved, ignoring",
+ Some("to escape `[` and `]` characters, just add '\\' before them like `\\[` or `\\]`"));
+}
+
+fn anchor_failure(
+ cx: &DocContext<'_>,
+ item: &Item,
+ path_str: &str,
+ dox: &str,
+ link_range: Option<Range<usize>>,
+ msg: &str,
+) {
+ build_diagnostic(cx, item, path_str, dox, link_range,
+ "has an issue with the link anchor.",
+ msg,
+ None);
+}
+
fn ambiguity_error(
cx: &DocContext<'_>,
item: &Item,
}
/// Given an enum variant's res, return the res of its enum and the associated fragment.
-fn handle_variant(cx: &DocContext<'_>, res: Res) -> Result<(Res, Option<String>), ()> {
+fn handle_variant(
+ cx: &DocContext<'_>,
+ res: Res,
+ extra_fragment: &Option<String>,
+) -> Result<(Res, Option<String>), ErrorKind> {
use rustc::ty::DefIdTree;
+ if extra_fragment.is_some() {
+ return Err(ErrorKind::AnchorFailure("variants cannot be followed by anchors"));
+ }
let parent = if let Some(parent) = cx.tcx.parent(res.def_id()) {
parent
} else {
- return Err(())
+ return Err(ErrorKind::ResolutionFailure)
};
let parent_def = Res::Def(DefKind::Enum, parent);
let variant = cx.tcx.expect_variant_res(res);
lint::builtin::MISSING_DOC_CODE_EXAMPLES,
hir_id,
sp,
- "Missing code example in this documentation");
+ "missing code example in this documentation");
diag.emit();
} else if check_missing_code == false &&
tests.found_tests > 0 &&
lint::builtin::PRIVATE_DOC_TESTS,
hir_id,
span_of_attrs(&item.attrs).unwrap_or(item.source.span()),
- "Documentation test in private item");
+ "documentation test in private item");
diag.emit();
}
}
if start == DUMMY_SP {
return None;
}
- let end = attrs.doc_strings.last().expect("No doc strings provided").span();
+ let end = attrs.doc_strings.last().expect("no doc strings provided").span();
Some(start.to(end))
}
IntTy::I128 => 128,
})
}
+
+ pub fn normalize(&self, target_width: u32) -> Self {
+ match self {
+ IntTy::Isize => match target_width {
+ 16 => IntTy::I16,
+ 32 => IntTy::I32,
+ 64 => IntTy::I64,
+ _ => unreachable!(),
+ },
+ _ => *self,
+ }
+ }
}
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable_Generic,
UintTy::U128 => 128,
})
}
+
+ pub fn normalize(&self, target_width: u32) -> Self {
+ match self {
+ UintTy::Usize => match target_width {
+ 16 => UintTy::U16,
+ 32 => UintTy::U32,
+ 64 => UintTy::U64,
+ _ => unreachable!(),
+ },
+ _ => *self,
+ }
+ }
}
/// A constraint on an associated type (e.g., `A = Bar` in `Foo<A = Bar>` or
crate_edition: Edition, allow_features: &Option<Vec<String>>) -> Features {
fn feature_removed(span_handler: &Handler, span: Span, reason: Option<&str>) {
let mut err = struct_span_err!(span_handler, span, E0557, "feature has been removed");
+ err.span_label(span, "feature has been removed");
if let Some(reason) = reason {
- err.span_note(span, reason);
- } else {
- err.span_label(span, "feature has been removed");
+ err.note(reason);
}
err.emit();
}
// for nested macro definitions.
sess.span_diagnostic
.struct_span_err(span, "duplicate matcher binding")
- .span_note(prev_info.span, "previous declaration was here")
+ .span_label(span, "duplicate binding")
+ .span_label(prev_info.span, "previous binding")
.emit();
*valid = false;
} else {
let e = p.parse_expr()?;
if let Some(prev) = names.get(&name) {
ecx.struct_span_err(e.span, &format!("duplicate argument named `{}`", name))
- .span_note(args[*prev].span, "previously here")
+ .span_label(args[*prev].span, "previously here")
+ .span_label(e.span, "duplicate argument")
.emit();
continue;
}
};
self.handler.struct_span_err(attr.span, &msg)
- .span_note(prev_attr.span, "previous attribute here")
+ .span_label(prev_attr.span, "previous attribute here")
.emit();
return;
// Apparently `addPassesToEmitFile` adds a pointer to our on-the-stack output
// stream (OS), so the only real safe place to delete this is here? Don't we
// wish this was written in Rust?
- delete PM;
+ LLVMDisposePassManager(PMR);
return LLVMRustResult::Success;
}
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn change_loop_body() {
let mut _x = 0;
#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
- except="HirBody,mir_built")]
+ except="HirBody,mir_built,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn change_name() {
let _y = 2u64;
#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
- except="HirBody,typeck_tables_of,mir_built")]
+ except="HirBody,typeck_tables_of,mir_built,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn change_mutability_of_slot() {
let _x: u64 = 0;
#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
- except="HirBody,typeck_tables_of,mir_built")]
+ except="HirBody,typeck_tables_of,mir_built,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn add_initializer() {
let _x: i16 = 3i16;
#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2",
- except="HirBody,mir_built")]
+ except="HirBody,mir_built,optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn change_initializer() {
let _x = 5u16;
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn change_loop_body() {
let mut _x = 0;
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn change_loop_body() {
let mut _x = 0;
}
#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="HirBody, mir_built")]
+#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
#[rustc_clean(cfg="cfail3")]
pub fn change_loop_condition() {
let mut _x = 0;
// let _3: ();
// let mut _4: std::boxed::Box<S>;
// scope 1 {
+// debug x => _1;
// }
// bb0: {
// StorageLive(_1);
// START rustc.main.ConstProp.after.mir
// bb0: {
// ...
-// _4 = const Scalar(AllocId(1).0x0) : &i32;
-// _3 = const Scalar(AllocId(1).0x0) : &i32;
-// _2 = const Value(Scalar(AllocId(1).0x0)) : *const i32;
+// _4 = const main::FOO;
+// _3 = _4;
+// _2 = move _3 as *const i32 (Misc);
// ...
// _1 = move _2 as usize (Misc);
// ...
// START rustc.main.ConstProp.after.mir
// bb0: {
// ...
-// _2 = const Scalar(AllocId(0).0x0) : &i32;
+// _2 = &(promoted[0]: i32);
// _1 = const 4i32;
// ...
// }
// START rustc.main.ConstProp.after.mir
// bb0: {
// ...
-// _3 = const main;
+// _3 = const main as fn() (Pointer(ReifyFnPointer));
// _2 = move _3 as usize (Misc);
// ...
// _1 = move _2 as *const fn() (Misc);
// START rustc.main.ConstProp.after.mir
// bb0: {
// ...
-// _4 = const Scalar(AllocId(0).0x0) : &[u32; 3];
-// _3 = const Scalar(AllocId(0).0x0) : &[u32; 3];
+// _4 = &(promoted[0]: [u32; 3]);
+// _3 = _4;
// _2 = move _3 as &[u32] (Pointer(Unsize));
// ...
// _6 = const 1usize;
// ...
// let mut _9: Bar;
// scope 1 {
+// debug a => _2;
// let _3: Bar;
// scope 2 {
+// debug b => _3;
// }
// }
// bb0: {
// END RUST SOURCE
// START rustc.foo.Inline.after.mir
-// ...
-// bb0: {
-// ...
-// _3 = [closure@HirId { owner: DefIndex(4), local_id: 31 }];
-// ...
-// _4 = &_3;
-// ...
-// _6 = &(*_2);
-// ...
-// _7 = &(*_2);
-// _5 = (move _6, move _7);
-// _8 = move (_5.0: &i32);
-// _9 = move (_5.1: &i32);
-// ...
-// _0 = (*_8);
-// ...
-// return;
+// fn foo(_1: T, _2: &i32) -> i32{
+// debug _t => _1;
+// debug q => _2;
+// let mut _0: i32;
+// let _3: [closure@HirId { owner: DefIndex(4), local_id: 31 }];
+// let mut _4: &[closure@HirId { owner: DefIndex(4), local_id: 31 }];
+// let mut _5: (&i32, &i32);
+// let mut _6: &i32;
+// let mut _7: &i32;
+// let mut _8: &i32;
+// let mut _9: &i32;
+// scope 1 {
+// debug x => _3;
+// scope 2 {
+// debug r => _8;
+// debug _s => _9;
+// }
+// }
+// scope 3 {
+// debug variable => _8;
+// }
+// bb0: {
+// ...
+// _3 = [closure@HirId { owner: DefIndex(4), local_id: 31 }];
+// ...
+// _4 = &_3;
+// ...
+// _6 = &(*_2);
+// ...
+// _7 = &(*_2);
+// _5 = (move _6, move _7);
+// _8 = move (_5.0: &i32);
+// _9 = move (_5.1: &i32);
+// ...
+// _0 = (*_8);
+// ...
+// return;
+// }
// }
-// ...
// END rustc.foo.Inline.after.mir
--- /dev/null
+// compile-flags: -Z span_free_formats
+
+// Tests that MIR inliner can handle closure captures.
+
+fn main() {
+ println!("{:?}", foo(0, 14));
+}
+
+fn foo<T: Copy>(t: T, q: i32) -> (i32, T) {
+ let x = |_q| (q, t);
+ x(q)
+}
+
+// END RUST SOURCE
+// START rustc.foo.Inline.after.mir
+// fn foo(_1: T, _2: i32) -> (i32, T){
+// debug t => _1;
+// debug q => _2;
+// let mut _0: (i32, T);
+// let _3: [closure@HirId { owner: DefIndex(4), local_id: 15 } q:&i32, t:&T];
+// let mut _4: &i32;
+// let mut _5: &T;
+// let mut _6: &[closure@HirId { owner: DefIndex(4), local_id: 15 } q:&i32, t:&T];
+// let mut _7: (i32,);
+// let mut _8: i32;
+// let mut _11: i32;
+// scope 1 {
+// debug x => _3;
+// scope 2 {
+// debug _q => _11;
+// debug q => (*((*_6).0: &i32));
+// debug t => (*((*_6).1: &T));
+// let mut _9: i32;
+// let mut _10: T;
+// }
+// }
+// bb0: {
+// ...
+// _4 = &_2;
+// ...
+// _5 = &_1;
+// _3 = [closure@HirId { owner: DefIndex(4), local_id: 15 }] { q: move _4, t: move _5 };
+// ...
+// _6 = &_3;
+// ...
+// ...
+// _8 = _2;
+// _7 = (move _8,);
+// _11 = move (_7.0: i32);
+// ...
+// _9 = (*((*_6).0: &i32));
+// ...
+// _10 = (*((*_6).1: &T));
+// (_0.0: i32) = move _9;
+// (_0.1: T) = move _10;
+// ...
+// return;
+// }
+// }
+// END rustc.foo.Inline.after.mir
// END RUST SOURCE
// START rustc.foo.Inline.after.mir
-// ...
-// bb0: {
-// ...
-// _3 = [closure@HirId { owner: DefIndex(4), local_id: 15 }];
-// ...
-// _4 = &_3;
-// ...
-// _6 = _2;
-// ...
-// _7 = _2;
-// _5 = (move _6, move _7);
-// _8 = move (_5.0: i32);
-// _9 = move (_5.1: i32);
-// _0 = _8;
-// ...
-// return;
-// }
-// ...
+// fn foo(_1: T, _2: i32) -> i32{
+// debug _t => _1;
+// debug q => _2;
+// let mut _0: i32;
+// let _3: [closure@HirId { owner: DefIndex(4), local_id: 15 }];
+// let mut _4: &[closure@HirId { owner: DefIndex(4), local_id: 15 }];
+// let mut _5: (i32, i32);
+// let mut _6: i32;
+// let mut _7: i32;
+// let mut _8: i32;
+// let mut _9: i32;
+// scope 1 {
+// debug x => _3;
+// scope 2 {
+// debug _t => _8;
+// debug _q => _9;
+// }
+// }
+// bb0: {
+// ...
+// _3 = [closure@HirId { owner: DefIndex(4), local_id: 15 }];
+// ...
+// _4 = &_3;
+// ...
+// _6 = _2;
+// ...
+// _7 = _2;
+// _5 = (move _6, move _7);
+// _8 = move (_5.0: i32);
+// _9 = move (_5.1: i32);
+// _0 = _8;
+// ...
+// return;
+// }
// END rustc.foo.Inline.after.mir
// let mut _4: S;
// let mut _5: bool;
// scope 1 {
+// debug x => _1;
// }
// ...
// bb0: {
// let mut _5: S;
// let mut _6: bool;
// ...
+// debug u => _1;
+// ...
// let mut _2: S;
// ...
+// debug v => _2;
+// ...
// bb0: {
// END rustc.test.ElaborateDrops.after.mir
// fn main() -> () {
// let mut _0: ();
// scope 1 {
-// let _1: E; // `e`
+// let _1: E;
+// debug e => _1;
// scope 2 {
// let _6: K;
+// debug _k => _6;
// }
// }
// let mut _2: bool;
// let _5: ();
// let mut _6: &i32;
// scope 1 {
+// debug beacon => _2;
// }
// bb0: {
// goto -> bb1;
// let _15: bool; // `b`
// let _16: std::string::String; // `t`
// scope 1 {
+// debug a => _5;
+// debug a => _6;
+// debug s => _7;
+// debug s => _8;
// }
// scope 2 {
+// debug b => _15;
+// debug t => _16;
// }
// bb0: {
// FakeRead(ForMatchedPlace, _2);
// START rustc.main.nll.0.mir
// let _2: &'_#3r usize;
// ...
+// debug p => _2;
+// ...
// let _6: &'_#4r usize;
// ...
+// debug q => _6;
+// ...
// _2 = &'_#2r _1[_3];
// ...
// _6 = _2;
// let mut _5: Droppy;
// let mut _6: Aligned;
// scope 1 {
+// debug x => _1;
// }
//
// bb0: {
// END RUST SOURCE
// START rustc.try_identity.SimplifyArmIdentity.before.mir
// fn try_identity(_1: std::result::Result<u32, i32>) -> std::result::Result<u32, i32> {
+// debug x => _1;
// let mut _0: std::result::Result<u32, i32>;
// let _2: u32;
// let mut _3: std::result::Result<u32, i32>;
// let _10: u32;
// let mut _11: u32;
// scope 1 {
+// debug y => _10;
// }
// scope 2 {
+// debug err => _6;
// scope 3 {
// scope 7 {
+// debug t => _6;
// }
// scope 8 {
+// debug v => _6;
// let mut _12: i32;
// }
// }
// }
// scope 4 {
+// debug val => _10;
// scope 5 {
// }
// }
// scope 6 {
+// debug self => _1;
// }
// bb0: {
// _5 = discriminant(_1);
// START rustc.try_identity.SimplifyArmIdentity.after.mir
// fn try_identity(_1: std::result::Result<u32, i32>) -> std::result::Result<u32, i32> {
+// debug x => _1;
// let mut _0: std::result::Result<u32, i32>;
// let _2: u32;
// let mut _3: std::result::Result<u32, i32>;
// let _10: u32;
// let mut _11: u32;
// scope 1 {
+// debug y => _10;
// }
// scope 2 {
+// debug err => _6;
// scope 3 {
// scope 7 {
+// debug t => _6;
// }
// scope 8 {
+// debug v => _6;
// let mut _12: i32;
// }
// }
// }
// scope 4 {
+// debug val => _10;
// scope 5 {
// }
// }
// scope 6 {
+// debug self => _1;
// }
// bb0: {
// _5 = discriminant(_1);
// START rustc.try_identity.SimplifyBranchSame.after.mir
// fn try_identity(_1: std::result::Result<u32, i32>) -> std::result::Result<u32, i32> {
+// debug x => _1;
// let mut _0: std::result::Result<u32, i32>;
// let _2: u32;
// let mut _3: std::result::Result<u32, i32>;
// let _10: u32;
// let mut _11: u32;
// scope 1 {
+// debug y => _10;
// }
// scope 2 {
+// debug err => _6;
// scope 3 {
// scope 7 {
+// debug t => _6;
// }
// scope 8 {
+// debug v => _6;
// let mut _12: i32;
// }
// }
// }
// scope 4 {
+// debug val => _10;
// scope 5 {
// }
// }
// scope 6 {
+// debug self => _1;
// }
// bb0: {
// _5 = discriminant(_1);
// START rustc.try_identity.SimplifyLocals.after.mir
// fn try_identity(_1: std::result::Result<u32, i32>) -> std::result::Result<u32, i32> {
+// debug x => _1;
// let mut _0: std::result::Result<u32, i32>;
// let mut _2: isize;
+// let _3: i32;
+// let _4: u32;
// scope 1 {
+// debug y => _4;
// }
// scope 2 {
+// debug err => _3;
// scope 3 {
// scope 7 {
+// debug t => _3;
// }
// scope 8 {
+// debug v => _3;
// }
// }
// }
// scope 4 {
+// debug val => _4;
// scope 5 {
// }
// }
// scope 6 {
+// debug self => _1;
// }
// bb0: {
// _2 = discriminant(_1);
-error: `[v2]` cannot be resolved, ignoring it...
+error: `[v2]` cannot be resolved, ignoring it.
--> $DIR/deny-intra-link-resolution-failure.rs:3:6
|
LL | /// [v2]
-#![deny(missing_doc_code_examples)] //~ ERROR Missing code example in this documentation
+#![deny(missing_doc_code_examples)] //~ ERROR missing code example in this documentation
/// Some docs.
-//~^ ERROR Missing code example in this documentation
+//~^ ERROR missing code example in this documentation
pub struct Foo;
/// And then, the princess died.
-//~^ ERROR Missing code example in this documentation
+//~^ ERROR missing code example in this documentation
pub mod foo {
/// Or maybe not because she saved herself!
- //~^ ERROR Missing code example in this documentation
+ //~^ ERROR missing code example in this documentation
pub fn bar() {}
}
-error: Missing code example in this documentation
+error: missing code example in this documentation
--> $DIR/doc-without-codeblock.rs:1:1
|
LL | / #![deny(missing_doc_code_examples)]
LL | #![deny(missing_doc_code_examples)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
-error: Missing code example in this documentation
+error: missing code example in this documentation
--> $DIR/doc-without-codeblock.rs:3:1
|
LL | /// Some docs.
| ^^^^^^^^^^^^^^
-error: Missing code example in this documentation
+error: missing code example in this documentation
--> $DIR/doc-without-codeblock.rs:7:1
|
LL | /// And then, the princess died.
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: Missing code example in this documentation
+error: missing code example in this documentation
--> $DIR/doc-without-codeblock.rs:10:5
|
LL | /// Or maybe not because she saved herself!
-error: `[TypeAlias::hoge]` cannot be resolved, ignoring it...
+error: `[TypeAlias::hoge]` cannot be resolved, ignoring it.
--> $DIR/intra-doc-alias-ice.rs:5:30
|
LL | /// [broken cross-reference](TypeAlias::hoge)
/// ## For example:
///
/// (arr[i])
-//~^ ERROR `[i]` cannot be resolved, ignoring it...
+//~^ ERROR `[i]` cannot be resolved, ignoring it.
pub fn test_ice() {
unimplemented!();
}
-error: `[i]` cannot be resolved, ignoring it...
+error: `[i]` cannot be resolved, ignoring it.
--> $DIR/intra-link-span-ice-55723.rs:9:10
|
LL | /// (arr[i])
--- /dev/null
+#![deny(intra_doc_link_resolution_failure)]
+
+// A few tests on anchors.
+
+/// Hello people.
+///
+/// You can anchors? Here's one!
+///
+/// # hola
+///
+/// Isn't it amazing?
+pub struct Foo {
+ pub f: u8,
+}
+
+pub enum Enum {
+ A,
+ B,
+}
+
+/// Have you heard about stuff?
+///
+/// Like [Foo#hola].
+///
+/// Or maybe [Foo::f#hola].
+//~^ ERROR `[Foo::f#hola]` has an issue with the link anchor.
+pub fn foo() {}
+
+/// Empty.
+///
+/// Another anchor error: [hello#people#!].
+//~^ ERROR `[hello#people#!]` has an issue with the link anchor.
+pub fn bar() {}
+
+/// Empty?
+///
+/// Damn enum's variants: [Enum::A#whatever].
+//~^ ERROR `[Enum::A#whatever]` has an issue with the link anchor.
+pub fn enum_link() {}
+
+/// Primitives?
+///
+/// [u32#hello]
+//~^ ERROR `[u32#hello]` has an issue with the link anchor.
+pub fn x() {}
--- /dev/null
+error: `[Foo::f#hola]` has an issue with the link anchor.
+ --> $DIR/intra-links-anchors.rs:25:15
+ |
+LL | /// Or maybe [Foo::f#hola].
+ | ^^^^^^^^^^^ struct fields cannot be followed by anchors
+ |
+note: lint level defined here
+ --> $DIR/intra-links-anchors.rs:1:9
+ |
+LL | #![deny(intra_doc_link_resolution_failure)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `[hello#people#!]` has an issue with the link anchor.
+ --> $DIR/intra-links-anchors.rs:31:28
+ |
+LL | /// Another anchor error: [hello#people#!].
+ | ^^^^^^^^^^^^^^ only one `#` is allowed in a link
+
+error: `[Enum::A#whatever]` has an issue with the link anchor.
+ --> $DIR/intra-links-anchors.rs:37:28
+ |
+LL | /// Damn enum's variants: [Enum::A#whatever].
+ | ^^^^^^^^^^^^^^^^ variants cannot be followed by anchors
+
+error: `[u32#hello]` has an issue with the link anchor.
+ --> $DIR/intra-links-anchors.rs:43:6
+ |
+LL | /// [u32#hello]
+ | ^^^^^^^^^ primitive types cannot be followed by anchors
+
+error: aborting due to 4 previous errors
+
-warning: `[error]` cannot be resolved, ignoring it...
+warning: `[error]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning-crlf.rs:7:6
|
LL | /// [error]
= note: `#[warn(intra_doc_link_resolution_failure)]` on by default
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
-warning: `[error1]` cannot be resolved, ignoring it...
+warning: `[error1]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning-crlf.rs:12:11
|
LL | /// docs [error1]
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
-warning: `[error2]` cannot be resolved, ignoring it...
+warning: `[error2]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning-crlf.rs:15:11
|
LL | /// docs [error2]
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
-warning: `[error]` cannot be resolved, ignoring it...
+warning: `[error]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning-crlf.rs:23:20
|
LL | * It also has an [error].
-warning: `[Foo::baz]` cannot be resolved, ignoring it...
+warning: `[Foo::baz]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning.rs:3:23
|
LL | //! Test with [Foo::baz], [Bar::foo], ...
= note: `#[warn(intra_doc_link_resolution_failure)]` on by default
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
-warning: `[Bar::foo]` cannot be resolved, ignoring it...
+warning: `[Bar::foo]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning.rs:3:35
|
LL | //! Test with [Foo::baz], [Bar::foo], ...
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
-warning: `[Uniooon::X]` cannot be resolved, ignoring it...
+warning: `[Uniooon::X]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning.rs:6:13
|
LL | //! , [Uniooon::X] and [Qux::Z].
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
-warning: `[Qux::Z]` cannot be resolved, ignoring it...
+warning: `[Qux::Z]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning.rs:6:30
|
LL | //! , [Uniooon::X] and [Qux::Z].
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
-warning: `[Uniooon::X]` cannot be resolved, ignoring it...
+warning: `[Uniooon::X]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning.rs:10:14
|
LL | //! , [Uniooon::X] and [Qux::Z].
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
-warning: `[Qux::Z]` cannot be resolved, ignoring it...
+warning: `[Qux::Z]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning.rs:10:31
|
LL | //! , [Uniooon::X] and [Qux::Z].
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
-warning: `[Qux:Y]` cannot be resolved, ignoring it...
+warning: `[Qux:Y]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning.rs:14:13
|
LL | /// [Qux:Y]
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
-warning: `[error]` cannot be resolved, ignoring it...
+warning: `[error]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning.rs:58:30
|
LL | * time to introduce a link [error]*/
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
-warning: `[error]` cannot be resolved, ignoring it...
+warning: `[error]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning.rs:64:30
|
LL | * time to introduce a link [error]
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
-warning: `[error]` cannot be resolved, ignoring it...
+warning: `[error]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning.rs:68:1
|
LL | #[doc = "single line [error]"]
^^^^^
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
-warning: `[error]` cannot be resolved, ignoring it...
+warning: `[error]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning.rs:71:1
|
LL | #[doc = "single line with \"escaping\" [error]"]
^^^^^
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
-warning: `[error]` cannot be resolved, ignoring it...
+warning: `[error]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning.rs:74:1
|
LL | / /// Item docs.
^^^^^
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
-warning: `[error1]` cannot be resolved, ignoring it...
+warning: `[error1]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning.rs:80:11
|
LL | /// docs [error1]
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
-warning: `[error2]` cannot be resolved, ignoring it...
+warning: `[error2]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning.rs:82:11
|
LL | /// docs [error2]
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
-warning: `[BarA]` cannot be resolved, ignoring it...
+warning: `[BarA]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning.rs:21:10
|
LL | /// bar [BarA] bar
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
-warning: `[BarB]` cannot be resolved, ignoring it...
+warning: `[BarB]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning.rs:27:9
|
LL | * bar [BarB] bar
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
-warning: `[BarC]` cannot be resolved, ignoring it...
+warning: `[BarC]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning.rs:34:6
|
LL | bar [BarC] bar
|
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
-warning: `[BarD]` cannot be resolved, ignoring it...
+warning: `[BarD]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning.rs:45:1
|
LL | #[doc = "Foo\nbar [BarD] bar\nbaz"]
^^^^
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
-warning: `[BarF]` cannot be resolved, ignoring it...
+warning: `[BarF]` cannot be resolved, ignoring it.
--> $DIR/intra-links-warning.rs:50:9
|
LL | #[doc = $f]
pub fn link_error() {} //~^^^^^ ERROR cannot be resolved, ignoring it
/// wait, this doesn't have a doctest?
-pub fn no_doctest() {} //~^ ERROR Missing code example in this documentation
+pub fn no_doctest() {} //~^ ERROR missing code example in this documentation
/// wait, this *does* have a doctest?
///
/// ```
/// println!("sup");
/// ```
-fn private_doctest() {} //~^^^^^ ERROR Documentation test in private item
+fn private_doctest() {} //~^^^^^ ERROR documentation test in private item
-error: Documentation test in private item
+error: documentation test in private item
--> $DIR/lint-group.rs:19:1
|
LL | / /// wait, this *does* have a doctest?
| ^^^^^^^
= note: `#[deny(private_doc_tests)]` implied by `#[deny(rustdoc)]`
-error: `[error]` cannot be resolved, ignoring it...
+error: `[error]` cannot be resolved, ignoring it.
--> $DIR/lint-group.rs:9:29
|
LL | /// what up, let's make an [error]
= note: `#[deny(intra_doc_link_resolution_failure)]` implied by `#[deny(rustdoc)]`
= help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
-error: Missing code example in this documentation
+error: missing code example in this documentation
--> $DIR/lint-group.rs:16:1
|
LL | /// wait, this doesn't have a doctest?
-error: Missing code example in this documentation
+error: missing code example in this documentation
--> $DIR/lint-missing-doc-code-example.rs:19:1
|
LL | / mod module1 {
LL | #![deny(missing_doc_code_examples)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
-error: Missing code example in this documentation
+error: missing code example in this documentation
--> $DIR/lint-missing-doc-code-example.rs:37:3
|
LL | /// doc
/// ```
/// assert!(false);
/// ```
- //~^^^^^ ERROR Documentation test in private item
+ //~^^^^^ ERROR documentation test in private item
fn bar() {}
}
-error: Documentation test in private item
+error: documentation test in private item
--> $DIR/private-item-doc-test.rs:4:5
|
LL | / /// private doc test
--- /dev/null
+#![crate_name = "foo"]
+
+pub enum Foo {
+ X {
+ y: u8,
+ }
+}
+
+/// Hello
+///
+/// I want [Foo::X::y].
+pub fn foo() {}
+
+// @has foo/fn.foo.html '//a/@href' '../foo/enum.Foo.html#variant.X.field.y'
--- /dev/null
+/// I want...
+///
+/// # Anchor!
+pub struct Something;
+
+// @has intra_links_anchors/struct.SomeOtherType.html
+// @has - '//a/@href' '../intra_links_anchors/struct.Something.html#Anchor!'
+
+/// I want...
+///
+/// To link to [Something#Anchor!]
+pub struct SomeOtherType;
error: cannot define multiple global allocators
--> $DIR/two-allocators.rs:6:1
|
-LL | static B: System = System;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
-note: the previous global allocator is defined here
- --> $DIR/two-allocators.rs:4:1
- |
LL | static A: System = System;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | -------------------------- previous global allocator is defined here
+LL | #[global_allocator]
+LL | static B: System = System;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot define a new global allocator
error: aborting due to previous error
LL | Foo::Foo2(num) => (),
| --- ...and here
|
-note: move occurs because these variables have types that don't implement the `Copy` trait
- --> $DIR/borrowck-move-error-with-note.rs:12:19
- |
-LL | Foo::Foo1(num1,
- | ^^^^
-LL | num2) => (),
- | ^^^^
-LL | Foo::Foo2(num) => (),
- | ^^^
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
--> $DIR/borrowck-move-error-with-note.rs:28:11
LL | g: _t
| -- ...and here
|
-note: move occurs because these variables have types that don't implement the `Copy` trait
- --> $DIR/borrowck-move-error-with-note.rs:31:16
- |
-LL | f: _s,
- | ^^
-LL | g: _t
- | ^^
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
error[E0507]: cannot move out of `a.a` which is behind a shared reference
--> $DIR/borrowck-move-error-with-note.rs:46:11
LL | Foo { string: b }] => {
| - ...and here
|
-note: move occurs because these variables have types that don't implement the `Copy` trait
- --> $DIR/borrowck-move-out-of-vec-tail.rs:21:33
- |
-LL | &[Foo { string: a },
- | ^
-LL | Foo { string: b }] => {
- | ^
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
help: consider removing the `&`
|
LL | [Foo { string: a },
match vec {
//~^ ERROR cannot move out
//~| NOTE cannot move out
+ //~| NOTE move occurs because these variables have types
&mut [_a, _b, _c] => {}
//~^ NOTE data moved here
//~| NOTE and here
//~| NOTE and here
//~| HELP consider removing the `&mut`
- //~| NOTE move occurs because these variables have types
_ => {}
}
let a = vec[0]; //~ ERROR cannot move out
| | data moved here
| help: consider removing the `&mut`: `[_a, _b, _c]`
|
-note: move occurs because these variables have types that don't implement the `Copy` trait
- --> $DIR/borrowck-vec-pattern-nesting.rs:78:15
- |
-LL | &mut [_a, _b, _c] => {}
- | ^^ ^^ ^^
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
--> $DIR/borrowck-vec-pattern-nesting.rs:86:13
--- /dev/null
+// Test for <https://github.com/rust-lang/rust/issues/66756>
+
+// check-pass
+
+#![feature(const_if_match)]
+
+enum E {
+ A,
+ B,
+ C
+}
+
+const fn f(e: E) {
+ match e {
+ E::A => {}
+ E::B => {}
+ E::C => {}
+ }
+}
+
+fn main() {}
--- /dev/null
+// check-pass
+
+#![feature(const_if_match)]
+
+enum E {
+ A,
+ B,
+ C
+}
+
+const fn f(e: E) -> usize {
+ match e {
+ _ => 0
+ }
+}
+
+fn main() {
+ const X: usize = f(E::C);
+ assert_eq!(X, 0);
+ assert_eq!(f(E::A), 0);
+}
--- /dev/null
+// run-pass
+// compile-flags: -Z mir-opt-level=3
+
+// Checks that the compiler does not ICE when passing references to field of by-value struct
+// with -Z mir-opt-level=3
+
+fn do_nothing(_: &()) {}
+
+pub struct Foo {
+ bar: (),
+}
+
+pub fn by_value_1(foo: Foo) {
+ do_nothing(&foo.bar);
+}
+
+pub fn by_value_2<T>(foo: Foo) {
+ do_nothing(&foo.bar);
+}
+
+fn main() {
+ by_value_1(Foo { bar: () });
+ by_value_2::<()>(Foo { bar: () });
+}
--> $DIR/ifmt-bad-arg.rs:40:33
|
LL | format!("{foo}", foo=1, foo=2);
- | ^
- |
-note: previously here
- --> $DIR/ifmt-bad-arg.rs:40:26
- |
-LL | format!("{foo}", foo=1, foo=2);
- | ^
+ | - ^ duplicate argument
+ | |
+ | previously here
error: positional arguments cannot follow named arguments
--> $DIR/ifmt-bad-arg.rs:41:35
LL | (&[hd1, ..], &[hd2, ..])
| --- ...and here
|
-note: move occurs because these variables have types that don't implement the `Copy` trait
- --> $DIR/issue-12567.rs:8:17
- |
-LL | (&[], &[hd, ..]) | (&[hd, ..], &[])
- | ^^
-LL | => println!("one empty"),
-LL | (&[hd1, ..], &[hd2, ..])
- | ^^^
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
error[E0508]: cannot move out of type `[T]`, a non-copy slice
--> $DIR/issue-12567.rs:4:11
LL | (&[hd1, ..], &[hd2, ..])
| --- ...and here
|
-note: move occurs because these variables have types that don't implement the `Copy` trait
- --> $DIR/issue-12567.rs:8:17
- |
-LL | (&[], &[hd, ..]) | (&[hd, ..], &[])
- | ^^
-LL | => println!("one empty"),
-LL | (&[hd1, ..], &[hd2, ..])
- | ^^^
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
error: aborting due to 2 previous errors
| | ...and here
| data moved here
|
-note: move occurs because these variables have types that don't implement the `Copy` trait
- --> $DIR/issue-40402-2.rs:5:10
- |
-LL | let (a, b) = x[0];
- | ^ ^
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
error: aborting due to previous error
error[E0696]: `continue` pointing to a labeled block
--> $DIR/label_break_value_continue.rs:14:9
|
-LL | continue 'b;
- | ^^^^^^^^^^^ labeled blocks cannot be `continue`'d
- |
-note: labeled block the continue points to
- --> $DIR/label_break_value_continue.rs:13:5
- |
LL | / 'b: {
LL | | continue 'b;
+ | | ^^^^^^^^^^^ labeled blocks cannot be `continue`'d
LL | | }
- | |_____^
+ | |_____- labeled block the `continue` points to
error[E0695]: unlabeled `continue` inside of a labeled block
--> $DIR/label_break_value_continue.rs:22:13
pub fn transparent_i128(p: TransparentI128); //~ ERROR: uses type `i128`
pub fn transparent_str(p: TransparentStr); //~ ERROR: uses type `str`
pub fn transparent_fn(p: TransparentBadFn); //~ ERROR: uses type `std::boxed::Box<u32>`
+ pub fn raw_array(arr: [u8; 8]); //~ ERROR: uses type `[u8; 8]`
+
+ pub static static_u128_type: u128; //~ ERROR: uses type `u128`
+ pub static static_u128_array_type: [u128; 16]; //~ ERROR: uses type `u128`
pub fn good3(fptr: Option<extern fn()>);
pub fn good4(aptr: &[u8; 4 as usize]);
pub fn good17(p: TransparentCustomZst);
#[allow(improper_ctypes)]
pub fn good18(_: &String);
+ pub fn good20(arr: *const [u8; 8]);
+ pub static good21: [u8; 8];
+
}
#[allow(improper_ctypes)]
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
= note: this struct has unspecified layout
-error: aborting due to 20 previous errors
+error: `extern` block uses type `[u8; 8]`, which is not FFI-safe
+ --> $DIR/lint-ctypes.rs:68:27
+ |
+LL | pub fn raw_array(arr: [u8; 8]);
+ | ^^^^^^^ not FFI-safe
+ |
+ = help: consider passing a pointer to the array
+ = note: passing raw arrays by value is not FFI-safe
+
+error: `extern` block uses type `u128`, which is not FFI-safe
+ --> $DIR/lint-ctypes.rs:70:34
+ |
+LL | pub static static_u128_type: u128;
+ | ^^^^ not FFI-safe
+ |
+ = note: 128-bit integers don't currently have a known stable ABI
+
+error: `extern` block uses type `u128`, which is not FFI-safe
+ --> $DIR/lint-ctypes.rs:71:40
+ |
+LL | pub static static_u128_array_type: [u128; 16];
+ | ^^^^^^^^^^ not FFI-safe
+ |
+ = note: 128-bit integers don't currently have a known stable ABI
+
+error: aborting due to 23 previous errors
--> $DIR/macro-multiple-matcher-bindings.rs:7:16
|
LL | ($a:ident, $a:ident) => {};
- | ^^^^^^^^
- |
-note: previous declaration was here
- --> $DIR/macro-multiple-matcher-bindings.rs:7:6
- |
-LL | ($a:ident, $a:ident) => {};
- | ^^^^^^^^
+ | -------- ^^^^^^^^ duplicate binding
+ | |
+ | previous binding
error: duplicate matcher binding
--> $DIR/macro-multiple-matcher-bindings.rs:8:16
|
LL | ($a:ident, $a:path) => {};
- | ^^^^^^^
- |
-note: previous declaration was here
- --> $DIR/macro-multiple-matcher-bindings.rs:8:6
- |
-LL | ($a:ident, $a:path) => {};
- | ^^^^^^^^
+ | -------- ^^^^^^^ duplicate binding
+ | |
+ | previous binding
error: duplicate matcher binding
--> $DIR/macro-multiple-matcher-bindings.rs:17:18
|
LL | ($a:ident, $($a:ident),*) => {};
- | ^^^^^^^^
- |
-note: previous declaration was here
- --> $DIR/macro-multiple-matcher-bindings.rs:17:6
- |
-LL | ($a:ident, $($a:ident),*) => {};
- | ^^^^^^^^
+ | -------- ^^^^^^^^ duplicate binding
+ | |
+ | previous binding
error: duplicate matcher binding
--> $DIR/macro-multiple-matcher-bindings.rs:18:25
|
LL | ($($a:ident)+ # $($($a:path),+);*) => {};
- | ^^^^^^^
- |
-note: previous declaration was here
- --> $DIR/macro-multiple-matcher-bindings.rs:18:8
- |
-LL | ($($a:ident)+ # $($($a:path),+);*) => {};
- | ^^^^^^^^
+ | -------- ^^^^^^^ duplicate binding
+ | |
+ | previous binding
error: aborting due to 4 previous errors
--> $DIR/macro-reexport-removed.rs:3:12
|
LL | #![feature(macro_reexport)]
- | ^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^ feature has been removed
|
-note: subsumed by `pub use`
- --> $DIR/macro-reexport-removed.rs:3:12
- |
-LL | #![feature(macro_reexport)]
- | ^^^^^^^^^^^^^^
+ = note: subsumed by `pub use`
error: cannot find attribute `macro_reexport` in this scope
--> $DIR/macro-reexport-removed.rs:5:3
error: cannot find a built-in macro with name `line`
--> <::core::macros::builtin::line macros>:1:1
|
-LL | () => { }
- | ^^^^^^^^^
+LL | () => { } ;
+ | ^^^^^^^^^^^
error: aborting due to 2 previous errors
LL | B::V(s) => (),
| - ...and here
|
-note: move occurs because these variables have types that don't implement the `Copy` trait
- --> $DIR/move-errors.rs:76:14
- |
-LL | B::U(d) => (),
- | ^
-LL | B::V(s) => (),
- | ^
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
error[E0509]: cannot move out of type `D`, which implements the `Drop` trait
--> $DIR/move-errors.rs:83:11
| |
| data moved here
|
-note: move occurs because these variables have types that don't implement the `Copy` trait
- --> $DIR/move-errors.rs:104:11
- |
-LL | F(s, mut t) => (),
- | ^ ^^^^^
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
error[E0507]: cannot move out of `x.0` which is behind a shared reference
--> $DIR/move-errors.rs:110:11
--> $DIR/expected-comma-found-token.rs:9:5
|
LL | message="the message"
- | - expected one of `)` or `,`
+ | -
+ | |
+ | expected one of `)` or `,`
+ | help: missing `,`
LL | label="the label"
| ^^^^^ unexpected token
--> $DIR/pat-lt-bracket-6.rs:5:19
|
LL | let Test(&desc[..]) = x;
- | ^ expected one of `)`, `,`, `@`, or `|`
+ | ^
+ | |
+ | expected one of `)`, `,`, `@`, or `|`
+ | help: missing `,`
error[E0658]: subslice patterns are unstable
--> $DIR/pat-lt-bracket-6.rs:5:20
--> $DIR/pat-lt-bracket-7.rs:5:16
|
LL | for Thing(x[]) in foo {}
- | ^ expected one of `)`, `,`, `@`, or `|`
+ | ^
+ | |
+ | expected one of `)`, `,`, `@`, or `|`
+ | help: missing `,`
error[E0308]: mismatched types
--> $DIR/pat-lt-bracket-7.rs:9:30
fn main() {
enum Test {
- Very
- //~^ ERROR missing comma
- Bad(usize)
- //~^ ERROR missing comma
- Stuff { a: usize }
- //~^ ERROR missing comma
+ Very //~ HELP missing `,`
+ Bad(usize) //~ HELP missing `,`
+ //~^ ERROR expected one of `(`, `,`, `=`, `{`, or `}`, found `Bad`
+ Stuff { a: usize } //~ HELP missing `,`
+ //~^ ERROR expected one of `,`, `=`, or `}`, found `Stuff`
Here
+ //~^ ERROR expected one of `,`, `=`, or `}`, found `Here`
}
}
-error: missing comma
- --> $DIR/recover-enum.rs:3:13
+error: expected one of `(`, `,`, `=`, `{`, or `}`, found `Bad`
+ --> $DIR/recover-enum.rs:4:9
|
LL | Very
- | ^ help: missing comma
+ | -
+ | |
+ | expected one of `(`, `,`, `=`, `{`, or `}`
+ | help: missing `,`
+LL | Bad(usize)
+ | ^^^ unexpected token
-error: missing comma
- --> $DIR/recover-enum.rs:5:19
+error: expected one of `,`, `=`, or `}`, found `Stuff`
+ --> $DIR/recover-enum.rs:6:9
|
LL | Bad(usize)
- | ^ help: missing comma
+ | -
+ | |
+ | expected one of `,`, `=`, or `}`
+ | help: missing `,`
+LL |
+LL | Stuff { a: usize }
+ | ^^^^^ unexpected token
-error: missing comma
- --> $DIR/recover-enum.rs:7:27
+error: expected one of `,`, `=`, or `}`, found `Here`
+ --> $DIR/recover-enum.rs:8:9
|
LL | Stuff { a: usize }
- | ^ help: missing comma
+ | -
+ | |
+ | expected one of `,`, `=`, or `}`
+ | help: missing `,`
+LL |
+LL | Here
+ | ^^^^ unexpected token
error: aborting due to 3 previous errors
--- /dev/null
+#[non_exhaustive]
+pub enum NonExhaustiveMonovariant {
+ Variant(u32),
+}
+
+pub enum ExhaustiveMonovariant {
+ Variant(u32),
+}
--- /dev/null
+// Test that the borrow checker doesn't consider checking an exhaustive pattern
+// as an access.
+
+// check-pass
+
+// aux-build:monovariants.rs
+extern crate monovariants;
+
+use monovariants::ExhaustiveMonovariant;
+
+enum Local {
+ Variant(u32),
+}
+
+#[non_exhaustive]
+enum LocalNonExhaustive {
+ Variant(u32),
+}
+
+fn main() {
+ let mut x = ExhaustiveMonovariant::Variant(1);
+ let y = &mut x;
+ match x {
+ ExhaustiveMonovariant::Variant(_) => {},
+ _ => {},
+ }
+ drop(y);
+ let mut x = Local::Variant(1);
+ let y = &mut x;
+ match x {
+ Local::Variant(_) => {},
+ _ => {},
+ }
+ drop(y);
+ let mut x = LocalNonExhaustive::Variant(1);
+ let y = &mut x;
+ match x {
+ LocalNonExhaustive::Variant(_) => {},
+ _ => {},
+ }
+ drop(y);
+}
--- /dev/null
+// Test that the borrow checker considers `#[non_exhaustive]` when checking
+// whether a match contains a discriminant read.
+
+// aux-build:monovariants.rs
+extern crate monovariants;
+
+use monovariants::NonExhaustiveMonovariant;
+
+fn main() {
+ let mut x = NonExhaustiveMonovariant::Variant(1);
+ let y = &mut x;
+ match x {
+ NonExhaustiveMonovariant::Variant(_) => {},
+ //~^ ERROR cannot use `x` because it was mutably borrowed
+ _ => {},
+ }
+ drop(y);
+}
--- /dev/null
+error[E0503]: cannot use `x` because it was mutably borrowed
+ --> $DIR/borrowck-non-exhaustive.rs:13:9
+ |
+LL | let y = &mut x;
+ | ------ borrow of `x` occurs here
+LL | match x {
+LL | NonExhaustiveMonovariant::Variant(_) => {},
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ use of borrowed `x`
+...
+LL | drop(y);
+ | - borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0503`.
error[E0038]: the trait `Foo` cannot be made into an object
- --> $DIR/arbitrary-self-types-not-object-safe.rs:34:32
+ --> $DIR/arbitrary-self-types-not-object-safe.rs:33:32
|
LL | fn foo(self: &Rc<Self>) -> usize;
| --- method `foo`'s `self` parameter cannot be dispatched on
| ^^^^^^^^^^^ the trait `Foo` cannot be made into an object
error[E0038]: the trait `Foo` cannot be made into an object
- --> $DIR/arbitrary-self-types-not-object-safe.rs:34:13
+ --> $DIR/arbitrary-self-types-not-object-safe.rs:33:13
|
LL | fn foo(self: &Rc<Self>) -> usize;
| --- method `foo`'s `self` parameter cannot be dispatched on
error[E0038]: the trait `Foo` cannot be made into an object
- --> $DIR/arbitrary-self-types-not-object-safe.rs:34:13
+ --> $DIR/arbitrary-self-types-not-object-safe.rs:33:13
|
LL | fn foo(self: &Rc<Self>) -> usize;
| --- method `foo`'s `self` parameter cannot be dispatched on
// revisions: curr object_safe_for_dispatch
#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))]
-#![feature(arbitrary_self_types)]
use std::rc::Rc;
error[E0038]: the trait `Foo` cannot be made into an object
- --> $DIR/arbitrary-self-types-not-object-safe.rs:31:32
+ --> $DIR/arbitrary-self-types-not-object-safe.rs:29:32
|
LL | fn foo(self: &Rc<Self>) -> usize;
| --- method `foo`'s `self` parameter cannot be dispatched on
| ^^^^^^^^^^^ the trait `Foo` cannot be made into an object
error[E0038]: the trait `Foo` cannot be made into an object
- --> $DIR/arbitrary-self-types-not-object-safe.rs:31:13
+ --> $DIR/arbitrary-self-types-not-object-safe.rs:29:13
|
LL | fn foo(self: &Rc<Self>) -> usize;
| --- method `foo`'s `self` parameter cannot be dispatched on
--- /dev/null
+// run-pass
+
+use {
+ std::{
+ rc::Rc,
+ sync::Arc,
+ },
+};
+
+#[derive(Default)]
+struct Ty;
+
+trait Trait {
+ fn receive_trait(self: &Arc<Rc<Box<Self>>>) -> u32;
+}
+
+const TRAIT_MAGIC: u32 = 42;
+const INHERENT_MAGIC: u32 = 1995;
+
+impl Trait for Ty {
+ fn receive_trait(self: &Arc<Rc<Box<Self>>>) -> u32 {
+ TRAIT_MAGIC
+ }
+}
+
+impl Ty {
+ fn receive_inherent(self: &Arc<Rc<Box<Self>>>) -> u32 {
+ INHERENT_MAGIC
+ }
+}
+
+fn main() {
+ let ty = <Arc<Rc<Box<Ty>>>>::default();
+ assert_eq!(TRAIT_MAGIC, ty.receive_trait());
+ assert_eq!(INHERENT_MAGIC, ty.receive_inherent());
+}
// run-pass
-#![feature(arbitrary_self_types)]
use std::rc::Rc;
// run-pass
-#![feature(arbitrary_self_types)]
use std::rc::Rc;
// run-pass
-#![feature(arbitrary_self_types)]
use std::rc::Rc;
// check-pass
// edition:2018
-#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]
use std::rc::Rc;
// check-pass
-#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]
use std::rc::Rc;
// check-pass
// edition:2018
-#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]
use std::rc::Rc;
// check-pass
-#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]
use std::rc::Rc;
// check-pass
// edition:2018
-#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]
use std::rc::Rc;
// check-pass
-#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]
use std::rc::Rc;
// check-pass
// edition:2018
-#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]
use std::rc::Rc;
// check-pass
-#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]
use std::rc::Rc;
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
- --> $DIR/lt-ref-self-async.rs:13:42
+ --> $DIR/lt-ref-self-async.rs:12:42
|
LL | async fn ref_self(&self, f: &u32) -> &u32 {
| ^^^^
= note: hidden type `impl std::future::Future` captures lifetime '_#23r
error: lifetime may not live long enough
- --> $DIR/lt-ref-self-async.rs:14:9
+ --> $DIR/lt-ref-self-async.rs:13:9
|
LL | async fn ref_self(&self, f: &u32) -> &u32 {
| -
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
- --> $DIR/lt-ref-self-async.rs:19:48
+ --> $DIR/lt-ref-self-async.rs:18:48
|
LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 {
| ^^^^
= note: hidden type `impl std::future::Future` captures lifetime '_#23r
error: lifetime may not live long enough
- --> $DIR/lt-ref-self-async.rs:20:9
+ --> $DIR/lt-ref-self-async.rs:19:9
|
LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 {
| -
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
- --> $DIR/lt-ref-self-async.rs:23:57
+ --> $DIR/lt-ref-self-async.rs:22:57
|
LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
| ^^^^
= note: hidden type `impl std::future::Future` captures lifetime '_#23r
error: lifetime may not live long enough
- --> $DIR/lt-ref-self-async.rs:24:9
+ --> $DIR/lt-ref-self-async.rs:23:9
|
LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
| -
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
- --> $DIR/lt-ref-self-async.rs:27:57
+ --> $DIR/lt-ref-self-async.rs:26:57
|
LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
| ^^^^
= note: hidden type `impl std::future::Future` captures lifetime '_#23r
error: lifetime may not live long enough
- --> $DIR/lt-ref-self-async.rs:28:9
+ --> $DIR/lt-ref-self-async.rs:27:9
|
LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
| -
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
- --> $DIR/lt-ref-self-async.rs:31:66
+ --> $DIR/lt-ref-self-async.rs:30:66
|
LL | async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
| ^^^^
= note: hidden type `impl std::future::Future` captures lifetime '_#23r
error: lifetime may not live long enough
- --> $DIR/lt-ref-self-async.rs:32:9
+ --> $DIR/lt-ref-self-async.rs:31:9
|
LL | async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
| -
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
- --> $DIR/lt-ref-self-async.rs:35:62
+ --> $DIR/lt-ref-self-async.rs:34:62
|
LL | async fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
| ^^^^
= note: hidden type `impl std::future::Future` captures lifetime '_#23r
error: lifetime may not live long enough
- --> $DIR/lt-ref-self-async.rs:36:9
+ --> $DIR/lt-ref-self-async.rs:35:9
|
LL | async fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
| -
// edition:2018
-#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]
use std::pin::Pin;
error[E0623]: lifetime mismatch
- --> $DIR/lt-ref-self-async.rs:14:9
+ --> $DIR/lt-ref-self-async.rs:13:9
|
LL | async fn ref_self(&self, f: &u32) -> &u32 {
| ----- ----
| ^ ...but data from `f` is returned here
error[E0623]: lifetime mismatch
- --> $DIR/lt-ref-self-async.rs:20:9
+ --> $DIR/lt-ref-self-async.rs:19:9
|
LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 {
| ----- ----
| ^ ...but data from `f` is returned here
error[E0623]: lifetime mismatch
- --> $DIR/lt-ref-self-async.rs:24:9
+ --> $DIR/lt-ref-self-async.rs:23:9
|
LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
| ----- ----
| ^ ...but data from `f` is returned here
error[E0623]: lifetime mismatch
- --> $DIR/lt-ref-self-async.rs:28:9
+ --> $DIR/lt-ref-self-async.rs:27:9
|
LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
| ----- ----
| ^ ...but data from `f` is returned here
error[E0623]: lifetime mismatch
- --> $DIR/lt-ref-self-async.rs:32:9
+ --> $DIR/lt-ref-self-async.rs:31:9
|
LL | async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
| ----- ----
| ^ ...but data from `f` is returned here
error[E0623]: lifetime mismatch
- --> $DIR/lt-ref-self-async.rs:36:9
+ --> $DIR/lt-ref-self-async.rs:35:9
|
LL | async fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
| ----- ----
error: lifetime may not live long enough
- --> $DIR/lt-ref-self.rs:12:9
+ --> $DIR/lt-ref-self.rs:11:9
|
LL | fn ref_self(&self, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/lt-ref-self.rs:18:9
+ --> $DIR/lt-ref-self.rs:17:9
|
LL | fn ref_Self(self: &Self, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/lt-ref-self.rs:22:9
+ --> $DIR/lt-ref-self.rs:21:9
|
LL | fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/lt-ref-self.rs:26:9
+ --> $DIR/lt-ref-self.rs:25:9
|
LL | fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/lt-ref-self.rs:30:9
+ --> $DIR/lt-ref-self.rs:29:9
|
LL | fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/lt-ref-self.rs:34:9
+ --> $DIR/lt-ref-self.rs:33:9
|
LL | fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
-#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]
use std::pin::Pin;
error[E0623]: lifetime mismatch
- --> $DIR/lt-ref-self.rs:12:9
+ --> $DIR/lt-ref-self.rs:11:9
|
LL | fn ref_self(&self, f: &u32) -> &u32 {
| ---- ----
| ^ ...but data from `f` is returned here
error[E0623]: lifetime mismatch
- --> $DIR/lt-ref-self.rs:18:9
+ --> $DIR/lt-ref-self.rs:17:9
|
LL | fn ref_Self(self: &Self, f: &u32) -> &u32 {
| ---- ----
| ^ ...but data from `f` is returned here
error[E0623]: lifetime mismatch
- --> $DIR/lt-ref-self.rs:22:9
+ --> $DIR/lt-ref-self.rs:21:9
|
LL | fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
| ---- ----
| ^ ...but data from `f` is returned here
error[E0623]: lifetime mismatch
- --> $DIR/lt-ref-self.rs:26:9
+ --> $DIR/lt-ref-self.rs:25:9
|
LL | fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
| ---- ----
| ^ ...but data from `f` is returned here
error[E0623]: lifetime mismatch
- --> $DIR/lt-ref-self.rs:30:9
+ --> $DIR/lt-ref-self.rs:29:9
|
LL | fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
| ---- ----
| ^ ...but data from `f` is returned here
error[E0623]: lifetime mismatch
- --> $DIR/lt-ref-self.rs:34:9
+ --> $DIR/lt-ref-self.rs:33:9
|
LL | fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
| ---- ----
// check-pass
// edition:2018
-#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]
use std::pin::Pin;
// check-pass
-#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]
use std::pin::Pin;
// check-pass
// edition:2018
-#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]
use std::rc::Rc;
// check-pass
-#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]
use std::rc::Rc;
// edition:2018
// check-pass
-#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]
use std::pin::Pin;
// check-pass
-#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]
use std::pin::Pin;
// edition:2018
// check-pass
-#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]
use std::pin::Pin;
// check-pass
-#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]
use std::pin::Pin;
// edition:2018
// check-pass
-#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]
use std::pin::Pin;
// check-pass
-#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]
use std::pin::Pin;
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
- --> $DIR/ref-mut-self-async.rs:13:46
+ --> $DIR/ref-mut-self-async.rs:12:46
|
LL | async fn ref_self(&mut self, f: &u32) -> &u32 {
| ^^^^
= note: hidden type `impl std::future::Future` captures lifetime '_#15r
error: lifetime may not live long enough
- --> $DIR/ref-mut-self-async.rs:14:9
+ --> $DIR/ref-mut-self-async.rs:13:9
|
LL | async fn ref_self(&mut self, f: &u32) -> &u32 {
| -
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
- --> $DIR/ref-mut-self-async.rs:19:52
+ --> $DIR/ref-mut-self-async.rs:18:52
|
LL | async fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
| ^^^^
= note: hidden type `impl std::future::Future` captures lifetime '_#15r
error: lifetime may not live long enough
- --> $DIR/ref-mut-self-async.rs:20:9
+ --> $DIR/ref-mut-self-async.rs:19:9
|
LL | async fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
| -
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
- --> $DIR/ref-mut-self-async.rs:23:61
+ --> $DIR/ref-mut-self-async.rs:22:61
|
LL | async fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
| ^^^^
= note: hidden type `impl std::future::Future` captures lifetime '_#15r
error: lifetime may not live long enough
- --> $DIR/ref-mut-self-async.rs:24:9
+ --> $DIR/ref-mut-self-async.rs:23:9
|
LL | async fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
| -
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
- --> $DIR/ref-mut-self-async.rs:27:61
+ --> $DIR/ref-mut-self-async.rs:26:61
|
LL | async fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
| ^^^^
= note: hidden type `impl std::future::Future` captures lifetime '_#15r
error: lifetime may not live long enough
- --> $DIR/ref-mut-self-async.rs:28:9
+ --> $DIR/ref-mut-self-async.rs:27:9
|
LL | async fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
| -
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
- --> $DIR/ref-mut-self-async.rs:31:70
+ --> $DIR/ref-mut-self-async.rs:30:70
|
LL | async fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
| ^^^^
= note: hidden type `impl std::future::Future` captures lifetime '_#15r
error: lifetime may not live long enough
- --> $DIR/ref-mut-self-async.rs:32:9
+ --> $DIR/ref-mut-self-async.rs:31:9
|
LL | async fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
| -
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
- --> $DIR/ref-mut-self-async.rs:35:70
+ --> $DIR/ref-mut-self-async.rs:34:70
|
LL | async fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
| ^^^^
= note: hidden type `impl std::future::Future` captures lifetime '_#15r
error: lifetime may not live long enough
- --> $DIR/ref-mut-self-async.rs:36:9
+ --> $DIR/ref-mut-self-async.rs:35:9
|
LL | async fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
| -
// edition:2018
-#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]
use std::pin::Pin;
error[E0623]: lifetime mismatch
- --> $DIR/ref-mut-self-async.rs:14:9
+ --> $DIR/ref-mut-self-async.rs:13:9
|
LL | async fn ref_self(&mut self, f: &u32) -> &u32 {
| --------- ----
| ^ ...but data from `f` is returned here
error[E0623]: lifetime mismatch
- --> $DIR/ref-mut-self-async.rs:20:9
+ --> $DIR/ref-mut-self-async.rs:19:9
|
LL | async fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
| --------- ----
| ^ ...but data from `f` is returned here
error[E0623]: lifetime mismatch
- --> $DIR/ref-mut-self-async.rs:24:9
+ --> $DIR/ref-mut-self-async.rs:23:9
|
LL | async fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
| --------- ----
| ^ ...but data from `f` is returned here
error[E0623]: lifetime mismatch
- --> $DIR/ref-mut-self-async.rs:28:9
+ --> $DIR/ref-mut-self-async.rs:27:9
|
LL | async fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
| --------- ----
| ^ ...but data from `f` is returned here
error[E0623]: lifetime mismatch
- --> $DIR/ref-mut-self-async.rs:32:9
+ --> $DIR/ref-mut-self-async.rs:31:9
|
LL | async fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
| --------- ----
| ^ ...but data from `f` is returned here
error[E0623]: lifetime mismatch
- --> $DIR/ref-mut-self-async.rs:36:9
+ --> $DIR/ref-mut-self-async.rs:35:9
|
LL | async fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
| --------- ----
error: lifetime may not live long enough
- --> $DIR/ref-mut-self.rs:12:9
+ --> $DIR/ref-mut-self.rs:11:9
|
LL | fn ref_self(&mut self, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-mut-self.rs:18:9
+ --> $DIR/ref-mut-self.rs:17:9
|
LL | fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-mut-self.rs:22:9
+ --> $DIR/ref-mut-self.rs:21:9
|
LL | fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-mut-self.rs:26:9
+ --> $DIR/ref-mut-self.rs:25:9
|
LL | fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-mut-self.rs:30:9
+ --> $DIR/ref-mut-self.rs:29:9
|
LL | fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-mut-self.rs:34:9
+ --> $DIR/ref-mut-self.rs:33:9
|
LL | fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
-#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]
use std::pin::Pin;
error[E0623]: lifetime mismatch
- --> $DIR/ref-mut-self.rs:12:9
+ --> $DIR/ref-mut-self.rs:11:9
|
LL | fn ref_self(&mut self, f: &u32) -> &u32 {
| ---- ----
| ^ ...but data from `f` is returned here
error[E0623]: lifetime mismatch
- --> $DIR/ref-mut-self.rs:18:9
+ --> $DIR/ref-mut-self.rs:17:9
|
LL | fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
| ---- ----
| ^ ...but data from `f` is returned here
error[E0623]: lifetime mismatch
- --> $DIR/ref-mut-self.rs:22:9
+ --> $DIR/ref-mut-self.rs:21:9
|
LL | fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
| ---- ----
| ^ ...but data from `f` is returned here
error[E0623]: lifetime mismatch
- --> $DIR/ref-mut-self.rs:26:9
+ --> $DIR/ref-mut-self.rs:25:9
|
LL | fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
| ---- ----
| ^ ...but data from `f` is returned here
error[E0623]: lifetime mismatch
- --> $DIR/ref-mut-self.rs:30:9
+ --> $DIR/ref-mut-self.rs:29:9
|
LL | fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
| ---- ----
| ^ ...but data from `f` is returned here
error[E0623]: lifetime mismatch
- --> $DIR/ref-mut-self.rs:34:9
+ --> $DIR/ref-mut-self.rs:33:9
|
LL | fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
| ---- ----
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
- --> $DIR/ref-mut-struct-async.rs:13:56
+ --> $DIR/ref-mut-struct-async.rs:12:56
|
LL | async fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 {
| ^^^^
= note: hidden type `impl std::future::Future` captures lifetime '_#15r
error: lifetime may not live long enough
- --> $DIR/ref-mut-struct-async.rs:14:9
+ --> $DIR/ref-mut-struct-async.rs:13:9
|
LL | async fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 {
| -
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
- --> $DIR/ref-mut-struct-async.rs:17:65
+ --> $DIR/ref-mut-struct-async.rs:16:65
|
LL | async fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 {
| ^^^^
= note: hidden type `impl std::future::Future` captures lifetime '_#15r
error: lifetime may not live long enough
- --> $DIR/ref-mut-struct-async.rs:18:9
+ --> $DIR/ref-mut-struct-async.rs:17:9
|
LL | async fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 {
| -
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
- --> $DIR/ref-mut-struct-async.rs:21:65
+ --> $DIR/ref-mut-struct-async.rs:20:65
|
LL | async fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 {
| ^^^^
= note: hidden type `impl std::future::Future` captures lifetime '_#15r
error: lifetime may not live long enough
- --> $DIR/ref-mut-struct-async.rs:22:9
+ --> $DIR/ref-mut-struct-async.rs:21:9
|
LL | async fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 {
| -
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
- --> $DIR/ref-mut-struct-async.rs:25:74
+ --> $DIR/ref-mut-struct-async.rs:24:74
|
LL | async fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 {
| ^^^^
= note: hidden type `impl std::future::Future` captures lifetime '_#15r
error: lifetime may not live long enough
- --> $DIR/ref-mut-struct-async.rs:26:9
+ --> $DIR/ref-mut-struct-async.rs:25:9
|
LL | async fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 {
| -
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
- --> $DIR/ref-mut-struct-async.rs:29:74
+ --> $DIR/ref-mut-struct-async.rs:28:74
|
LL | async fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 {
| ^^^^
= note: hidden type `impl std::future::Future` captures lifetime '_#15r
error: lifetime may not live long enough
- --> $DIR/ref-mut-struct-async.rs:30:9
+ --> $DIR/ref-mut-struct-async.rs:29:9
|
LL | async fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 {
| -
// edition:2018
-#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]
use std::pin::Pin;
error[E0623]: lifetime mismatch
- --> $DIR/ref-mut-struct-async.rs:14:9
+ --> $DIR/ref-mut-struct-async.rs:13:9
|
LL | async fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 {
| ----------- ----
| ^ ...but data from `f` is returned here
error[E0623]: lifetime mismatch
- --> $DIR/ref-mut-struct-async.rs:18:9
+ --> $DIR/ref-mut-struct-async.rs:17:9
|
LL | async fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 {
| ----------- ----
| ^ ...but data from `f` is returned here
error[E0623]: lifetime mismatch
- --> $DIR/ref-mut-struct-async.rs:22:9
+ --> $DIR/ref-mut-struct-async.rs:21:9
|
LL | async fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 {
| ----------- ----
| ^ ...but data from `f` is returned here
error[E0623]: lifetime mismatch
- --> $DIR/ref-mut-struct-async.rs:26:9
+ --> $DIR/ref-mut-struct-async.rs:25:9
|
LL | async fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 {
| ----------- ----
| ^ ...but data from `f` is returned here
error[E0623]: lifetime mismatch
- --> $DIR/ref-mut-struct-async.rs:30:9
+ --> $DIR/ref-mut-struct-async.rs:29:9
|
LL | async fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 {
| ----------- ----
error: lifetime may not live long enough
- --> $DIR/ref-mut-struct.rs:12:9
+ --> $DIR/ref-mut-struct.rs:11:9
|
LL | fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-mut-struct.rs:16:9
+ --> $DIR/ref-mut-struct.rs:15:9
|
LL | fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-mut-struct.rs:20:9
+ --> $DIR/ref-mut-struct.rs:19:9
|
LL | fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-mut-struct.rs:24:9
+ --> $DIR/ref-mut-struct.rs:23:9
|
LL | fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-mut-struct.rs:28:9
+ --> $DIR/ref-mut-struct.rs:27:9
|
LL | fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
-#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]
use std::pin::Pin;
error[E0623]: lifetime mismatch
- --> $DIR/ref-mut-struct.rs:12:9
+ --> $DIR/ref-mut-struct.rs:11:9
|
LL | fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 {
| ---- ----
| ^ ...but data from `f` is returned here
error[E0623]: lifetime mismatch
- --> $DIR/ref-mut-struct.rs:16:9
+ --> $DIR/ref-mut-struct.rs:15:9
|
LL | fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 {
| ---- ----
| ^ ...but data from `f` is returned here
error[E0623]: lifetime mismatch
- --> $DIR/ref-mut-struct.rs:20:9
+ --> $DIR/ref-mut-struct.rs:19:9
|
LL | fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 {
| ---- ----
| ^ ...but data from `f` is returned here
error[E0623]: lifetime mismatch
- --> $DIR/ref-mut-struct.rs:24:9
+ --> $DIR/ref-mut-struct.rs:23:9
|
LL | fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 {
| ---- ----
| ^ ...but data from `f` is returned here
error[E0623]: lifetime mismatch
- --> $DIR/ref-mut-struct.rs:28:9
+ --> $DIR/ref-mut-struct.rs:27:9
|
LL | fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 {
| ---- ----
-error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
- --> $DIR/ref-self-async.rs:22:42
- |
-LL | async fn ref_self(&self, f: &u32) -> &u32 {
- | ^^^^
- |
- = note: hidden type `impl std::future::Future` captures lifetime '_#15r
-
-error: lifetime may not live long enough
- --> $DIR/ref-self-async.rs:23:9
- |
-LL | async fn ref_self(&self, f: &u32) -> &u32 {
- | -
- | |
- | lifetime `'_` defined here
- | lifetime `'_` defined here
-LL | f
- | ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
-
-error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
- --> $DIR/ref-self-async.rs:28:48
- |
-LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 {
- | ^^^^
- |
- = note: hidden type `impl std::future::Future` captures lifetime '_#15r
-
-error: lifetime may not live long enough
- --> $DIR/ref-self-async.rs:29:9
- |
-LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 {
- | -
- | |
- | lifetime `'_` defined here
- | lifetime `'_` defined here
-LL | f
- | ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
-
-error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
- --> $DIR/ref-self-async.rs:32:57
- |
-LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
- | ^^^^
- |
- = note: hidden type `impl std::future::Future` captures lifetime '_#15r
-
-error: lifetime may not live long enough
- --> $DIR/ref-self-async.rs:33:9
- |
-LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
- | -
- | |
- | lifetime `'_` defined here
- | lifetime `'_` defined here
-LL | f
- | ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
-
-error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
- --> $DIR/ref-self-async.rs:36:57
- |
-LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
- | ^^^^
- |
- = note: hidden type `impl std::future::Future` captures lifetime '_#15r
-
-error: lifetime may not live long enough
- --> $DIR/ref-self-async.rs:37:9
- |
-LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
- | -
- | |
- | lifetime `'_` defined here
- | lifetime `'_` defined here
-LL | f
- | ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
-
-error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
- --> $DIR/ref-self-async.rs:40:66
- |
-LL | async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
- | ^^^^
- |
- = note: hidden type `impl std::future::Future` captures lifetime '_#15r
-
-error: lifetime may not live long enough
- --> $DIR/ref-self-async.rs:41:9
- |
-LL | async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
- | -
- | |
- | lifetime `'_` defined here
- | lifetime `'_` defined here
-LL | f
- | ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
-
-error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
- --> $DIR/ref-self-async.rs:44:66
- |
-LL | async fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
- | ^^^^
- |
- = note: hidden type `impl std::future::Future` captures lifetime '_#15r
-
-error: lifetime may not live long enough
- --> $DIR/ref-self-async.rs:45:9
- |
-LL | async fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
- | -
- | |
- | lifetime `'_` defined here
- | lifetime `'_` defined here
-LL | f
- | ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
-
-error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
- --> $DIR/ref-self-async.rs:48:69
+error[E0658]: `Wrap<&Struct, Struct>` cannot be used as the type of `self` without the `arbitrary_self_types` feature
+ --> $DIR/ref-self-async.rs:47:39
|
LL | async fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 {
- | ^^^
- |
- = note: hidden type `impl std::future::Future` captures lifetime '_#15r
-
-error: lifetime may not live long enough
- --> $DIR/ref-self-async.rs:49:9
+ | ^^^^^^^^^^^^^^^^^
|
-LL | async fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 {
- | -
- | |
- | lifetime `'_` defined here
- | lifetime `'_` defined here
-LL | f
- | ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
+ = note: for more information, see https://github.com/rust-lang/rust/issues/44874
+ = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable
+ = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
-error: aborting due to 14 previous errors
+error: aborting due to previous error
-For more information about this error, try `rustc --explain E0700`.
+For more information about this error, try `rustc --explain E0658`.
// edition:2018
-#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]
use std::marker::PhantomData;
error[E0623]: lifetime mismatch
- --> $DIR/ref-self-async.rs:23:9
+ --> $DIR/ref-self-async.rs:22:9
|
LL | async fn ref_self(&self, f: &u32) -> &u32 {
| ----- ----
| ^ ...but data from `f` is returned here
error[E0623]: lifetime mismatch
- --> $DIR/ref-self-async.rs:29:9
+ --> $DIR/ref-self-async.rs:28:9
|
LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 {
| ----- ----
| ^ ...but data from `f` is returned here
error[E0623]: lifetime mismatch
- --> $DIR/ref-self-async.rs:33:9
+ --> $DIR/ref-self-async.rs:32:9
|
LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
| ----- ----
| ^ ...but data from `f` is returned here
error[E0623]: lifetime mismatch
- --> $DIR/ref-self-async.rs:37:9
+ --> $DIR/ref-self-async.rs:36:9
|
LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
| ----- ----
| ^ ...but data from `f` is returned here
error[E0623]: lifetime mismatch
- --> $DIR/ref-self-async.rs:41:9
+ --> $DIR/ref-self-async.rs:40:9
|
LL | async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
| ----- ----
| ^ ...but data from `f` is returned here
error[E0623]: lifetime mismatch
- --> $DIR/ref-self-async.rs:45:9
+ --> $DIR/ref-self-async.rs:44:9
|
LL | async fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
| ----- ----
| ^ ...but data from `f` is returned here
error[E0623]: lifetime mismatch
- --> $DIR/ref-self-async.rs:49:9
+ --> $DIR/ref-self-async.rs:48:9
|
LL | async fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 {
| ----- ---
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
- --> $DIR/ref-struct-async.rs:13:52
+ --> $DIR/ref-struct-async.rs:12:52
|
LL | async fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
| ^^^^
= note: hidden type `impl std::future::Future` captures lifetime '_#15r
error: lifetime may not live long enough
- --> $DIR/ref-struct-async.rs:14:9
+ --> $DIR/ref-struct-async.rs:13:9
|
LL | async fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
| -
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
- --> $DIR/ref-struct-async.rs:17:61
+ --> $DIR/ref-struct-async.rs:16:61
|
LL | async fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 {
| ^^^^
= note: hidden type `impl std::future::Future` captures lifetime '_#15r
error: lifetime may not live long enough
- --> $DIR/ref-struct-async.rs:18:9
+ --> $DIR/ref-struct-async.rs:17:9
|
LL | async fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 {
| -
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
- --> $DIR/ref-struct-async.rs:21:61
+ --> $DIR/ref-struct-async.rs:20:61
|
LL | async fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 {
| ^^^^
= note: hidden type `impl std::future::Future` captures lifetime '_#15r
error: lifetime may not live long enough
- --> $DIR/ref-struct-async.rs:22:9
+ --> $DIR/ref-struct-async.rs:21:9
|
LL | async fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 {
| -
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
- --> $DIR/ref-struct-async.rs:25:70
+ --> $DIR/ref-struct-async.rs:24:70
|
LL | async fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 {
| ^^^^
= note: hidden type `impl std::future::Future` captures lifetime '_#15r
error: lifetime may not live long enough
- --> $DIR/ref-struct-async.rs:26:9
+ --> $DIR/ref-struct-async.rs:25:9
|
LL | async fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 {
| -
| ^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_`
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
- --> $DIR/ref-struct-async.rs:29:66
+ --> $DIR/ref-struct-async.rs:28:66
|
LL | async fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 {
| ^^^^
= note: hidden type `impl std::future::Future` captures lifetime '_#15r
error: lifetime may not live long enough
- --> $DIR/ref-struct-async.rs:30:9
+ --> $DIR/ref-struct-async.rs:29:9
|
LL | async fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 {
| -
// edition:2018
-#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]
use std::pin::Pin;
error[E0623]: lifetime mismatch
- --> $DIR/ref-struct-async.rs:14:9
+ --> $DIR/ref-struct-async.rs:13:9
|
LL | async fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
| ------- ----
| ^ ...but data from `f` is returned here
error[E0623]: lifetime mismatch
- --> $DIR/ref-struct-async.rs:18:9
+ --> $DIR/ref-struct-async.rs:17:9
|
LL | async fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 {
| ------- ----
| ^ ...but data from `f` is returned here
error[E0623]: lifetime mismatch
- --> $DIR/ref-struct-async.rs:22:9
+ --> $DIR/ref-struct-async.rs:21:9
|
LL | async fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 {
| ------- ----
| ^ ...but data from `f` is returned here
error[E0623]: lifetime mismatch
- --> $DIR/ref-struct-async.rs:26:9
+ --> $DIR/ref-struct-async.rs:25:9
|
LL | async fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 {
| ------- ----
| ^ ...but data from `f` is returned here
error[E0623]: lifetime mismatch
- --> $DIR/ref-struct-async.rs:30:9
+ --> $DIR/ref-struct-async.rs:29:9
|
LL | async fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 {
| ------- ----
error: lifetime may not live long enough
- --> $DIR/ref-struct.rs:12:9
+ --> $DIR/ref-struct.rs:11:9
|
LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-struct.rs:16:9
+ --> $DIR/ref-struct.rs:15:9
|
LL | fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-struct.rs:20:9
+ --> $DIR/ref-struct.rs:19:9
|
LL | fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-struct.rs:24:9
+ --> $DIR/ref-struct.rs:23:9
|
LL | fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
| ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
error: lifetime may not live long enough
- --> $DIR/ref-struct.rs:28:9
+ --> $DIR/ref-struct.rs:27:9
|
LL | fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 {
| - - let's call the lifetime of this reference `'1`
-#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]
use std::pin::Pin;
error[E0623]: lifetime mismatch
- --> $DIR/ref-struct.rs:12:9
+ --> $DIR/ref-struct.rs:11:9
|
LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
| ---- ----
| ^ ...but data from `f` is returned here
error[E0623]: lifetime mismatch
- --> $DIR/ref-struct.rs:16:9
+ --> $DIR/ref-struct.rs:15:9
|
LL | fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 {
| ---- ----
| ^ ...but data from `f` is returned here
error[E0623]: lifetime mismatch
- --> $DIR/ref-struct.rs:20:9
+ --> $DIR/ref-struct.rs:19:9
|
LL | fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 {
| ---- ----
| ^ ...but data from `f` is returned here
error[E0623]: lifetime mismatch
- --> $DIR/ref-struct.rs:24:9
+ --> $DIR/ref-struct.rs:23:9
|
LL | fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 {
| ---- ----
| ^ ...but data from `f` is returned here
error[E0623]: lifetime mismatch
- --> $DIR/ref-struct.rs:28:9
+ --> $DIR/ref-struct.rs:27:9
|
LL | fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 {
| ---- ----
// check-pass
// edition:2018
-#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]
use std::rc::Rc;
// check-pass
-#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]
use std::rc::Rc;
// check-pass
// edition:2018
-#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]
use std::rc::Rc;
// check-pass
-#![feature(arbitrary_self_types)]
#![allow(non_snake_case)]
use std::rc::Rc;
--> $DIR/similar-tokens.rs:7:10
|
LL | use x::{A. B};
- | ^ expected one of `,`, `::`, `as`, or `}`
+ | ^
+ | |
+ | expected one of `,`, `::`, `as`, or `}`
+ | help: missing `,`
error: aborting due to previous error
| | data moved here
| help: consider removing the `&`: `(X(_t), X(_u))`
|
-note: move occurs because these variables have types that don't implement the `Copy` trait
- --> $DIR/duplicate-suggestions.rs:39:13
- |
-LL | let &(X(_t), X(_u)) = &(x.clone(), x.clone());
- | ^^ ^^
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
error[E0507]: cannot move out of a shared reference
--> $DIR/duplicate-suggestions.rs:43:50
| | data moved here
| help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))`
|
-note: move occurs because these variables have types that don't implement the `Copy` trait
- --> $DIR/duplicate-suggestions.rs:43:26
- |
-LL | if let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
- | ^^ ^^
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
error[E0507]: cannot move out of a shared reference
--> $DIR/duplicate-suggestions.rs:47:53
| | data moved here
| help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))`
|
-note: move occurs because these variables have types that don't implement the `Copy` trait
- --> $DIR/duplicate-suggestions.rs:47:29
- |
-LL | while let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
- | ^^ ^^
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
error[E0507]: cannot move out of a shared reference
--> $DIR/duplicate-suggestions.rs:51:11
LL | &(Either::Two(_t), Either::One(_u)) => (),
| -- ...and here -- ...and here
|
-note: move occurs because these variables have types that don't implement the `Copy` trait
- --> $DIR/duplicate-suggestions.rs:53:23
- |
-LL | &(Either::One(_t), Either::Two(_u)) => (),
- | ^^ ^^
-...
-LL | &(Either::Two(_t), Either::One(_u)) => (),
- | ^^ ^^
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
help: consider removing the `&`
|
LL | (Either::One(_t), Either::Two(_u)) => (),
| | data moved here
| help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))`
|
-note: move occurs because these variables have types that don't implement the `Copy` trait
- --> $DIR/duplicate-suggestions.rs:63:23
- |
-LL | &(Either::One(_t), Either::Two(_u))
- | ^^ ^^
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
error[E0507]: cannot move out of a shared reference
--> $DIR/duplicate-suggestions.rs:70:11
| | data moved here
| help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))`
|
-note: move occurs because these variables have types that don't implement the `Copy` trait
- --> $DIR/duplicate-suggestions.rs:72:23
- |
-LL | &(Either::One(_t), Either::Two(_u)) => (),
- | ^^ ^^
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
error[E0507]: cannot move out of a shared reference
--> $DIR/duplicate-suggestions.rs:78:11
| | data moved here
| help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))`
|
-note: move occurs because these variables have types that don't implement the `Copy` trait
- --> $DIR/duplicate-suggestions.rs:80:23
- |
-LL | &(Either::One(_t), Either::Two(_u)) => (),
- | ^^ ^^
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
error[E0507]: cannot move out of a mutable reference
--> $DIR/duplicate-suggestions.rs:91:31
| | data moved here
| help: consider removing the `&mut`: `(X(_t), X(_u))`
|
-note: move occurs because these variables have types that don't implement the `Copy` trait
- --> $DIR/duplicate-suggestions.rs:91:17
- |
-LL | let &mut (X(_t), X(_u)) = &mut (xm.clone(), xm.clone());
- | ^^ ^^
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
error[E0507]: cannot move out of a mutable reference
--> $DIR/duplicate-suggestions.rs:95:54
| | data moved here
| help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
|
-note: move occurs because these variables have types that don't implement the `Copy` trait
- --> $DIR/duplicate-suggestions.rs:95:30
- |
-LL | if let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
- | ^^ ^^
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
error[E0507]: cannot move out of a mutable reference
--> $DIR/duplicate-suggestions.rs:99:57
| | data moved here
| help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
|
-note: move occurs because these variables have types that don't implement the `Copy` trait
- --> $DIR/duplicate-suggestions.rs:99:33
- |
-LL | while let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
- | ^^ ^^
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
error[E0507]: cannot move out of a mutable reference
--> $DIR/duplicate-suggestions.rs:103:11
LL | &mut (Either::Two(_t), Either::One(_u)) => (),
| -- ...and here -- ...and here
|
-note: move occurs because these variables have types that don't implement the `Copy` trait
- --> $DIR/duplicate-suggestions.rs:105:27
- |
-LL | &mut (Either::One(_t), Either::Two(_u)) => (),
- | ^^ ^^
-...
-LL | &mut (Either::Two(_t), Either::One(_u)) => (),
- | ^^ ^^
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
help: consider removing the `&mut`
|
LL | (Either::One(_t), Either::Two(_u)) => (),
| | data moved here
| help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
|
-note: move occurs because these variables have types that don't implement the `Copy` trait
- --> $DIR/duplicate-suggestions.rs:115:27
- |
-LL | &mut (Either::One(_t), Either::Two(_u))
- | ^^ ^^
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
error[E0507]: cannot move out of a mutable reference
--> $DIR/duplicate-suggestions.rs:122:11
| | data moved here
| help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
|
-note: move occurs because these variables have types that don't implement the `Copy` trait
- --> $DIR/duplicate-suggestions.rs:124:27
- |
-LL | &mut (Either::One(_t), Either::Two(_u)) => (),
- | ^^ ^^
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
error[E0507]: cannot move out of a mutable reference
--> $DIR/duplicate-suggestions.rs:130:11
| | data moved here
| help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
|
-note: move occurs because these variables have types that don't implement the `Copy` trait
- --> $DIR/duplicate-suggestions.rs:132:27
- |
-LL | &mut (Either::One(_t), Either::Two(_u)) => (),
- | ^^ ^^
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
error[E0507]: cannot move out of a mutable reference
--> $DIR/duplicate-suggestions.rs:138:11
| | data moved here
| help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
|
-note: move occurs because these variables have types that don't implement the `Copy` trait
- --> $DIR/duplicate-suggestions.rs:140:27
- |
-LL | &mut (Either::One(_t), Either::Two(_u)) => (),
- | ^^ ^^
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
error[E0507]: cannot move out of a shared reference
--> $DIR/duplicate-suggestions.rs:86:11
| | data moved here
| help: consider removing the `&`: `(X(_t), X(_u))`
|
-note: move occurs because these variables have types that don't implement the `Copy` trait
- --> $DIR/duplicate-suggestions.rs:86:15
- |
-LL | fn f5(&(X(_t), X(_u)): &(X, X)) { }
- | ^^ ^^
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
error[E0507]: cannot move out of a mutable reference
--> $DIR/duplicate-suggestions.rs:146:11
| | data moved here
| help: consider removing the `&mut`: `(X(_t), X(_u))`
|
-note: move occurs because these variables have types that don't implement the `Copy` trait
- --> $DIR/duplicate-suggestions.rs:146:19
- |
-LL | fn f6(&mut (X(_t), X(_u)): &mut (X, X)) { }
- | ^^ ^^
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
error: aborting due to 17 previous errors
LL | &mut Either::Two(_t) => (),
| -- ...and here
|
-note: move occurs because these variables have types that don't implement the `Copy` trait
- --> $DIR/simple.rs:221:26
- |
-LL | &mut Either::One(_t) => (),
- | ^^
-...
-LL | &mut Either::Two(_t) => (),
- | ^^
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
help: consider removing the `&mut`
|
LL | Either::One(_t) => (),
LL | (&mut Either::Two(_t),) => (),
| -- ...and here
|
-note: move occurs because these variables have types that don't implement the `Copy` trait
- --> $DIR/simple.rs:280:27
- |
-LL | (&mut Either::One(_t),) => (),
- | ^^
-LL | (&mut Either::Two(_t),) => (),
- | ^^
+ = note: move occurs because these variables have types that don't implement the `Copy` trait
error[E0507]: cannot move out of a shared reference
--> $DIR/simple.rs:288:18
--> $DIR/test.rs:4:26
|
LL | struct S2(pub((foo)) ());
- | ^ expected one of `)` or `,`
+ | -^ expected one of `)` or `,`
+ | |
+ | help: missing `,`
error[E0412]: cannot find type `foo` in this scope
--> $DIR/test.rs:4:20
--> $DIR/test2.rs:5:26
|
LL | struct S3(pub $t ());
- | ^ expected one of `)` or `,`
+ | -^ expected one of `)` or `,`
+ | |
+ | help: missing `,`
...
LL | define_struct! { (foo) }
| ------------------------ in this macro invocation
--> $DIR/test3.rs:5:27
|
LL | struct S3(pub($t) ());
- | ^ expected one of `)` or `,`
+ | -^ expected one of `)` or `,`
+ | |
+ | help: missing `,`
...
LL | define_struct! { foo }
| ---------------------- in this macro invocation
--- /dev/null
+// Regression test for issue #63263.
+// Tests that we properly handle closures with an explicit return type
+// that return an opaque type.
+
+// check-pass
+
+#![feature(type_alias_impl_trait)]
+
+pub type Closure = impl FnOnce();
+
+fn main() {
+ || -> Closure { || () };
+}
extern crate crate_a1 as a;
a::try_foo(foo2);
//~^ ERROR mismatched types
- //~| Perhaps two different versions of crate `crate_a1`
+ //~| perhaps two different versions of crate `crate_a1`
//~| expected struct `main::a::Foo`
a::try_bar(bar2);
//~^ ERROR mismatched types
- //~| Perhaps two different versions of crate `crate_a1`
+ //~| perhaps two different versions of crate `crate_a1`
//~| expected trait `main::a::Bar`
//~| expected struct `std::boxed::Box<(dyn main::a::Bar + 'static)>`
//~| found struct `std::boxed::Box<dyn main::a::Bar>`
LL | a::try_foo(foo2);
| ^^^^ expected struct `main::a::Foo`, found a different struct `main::a::Foo`
|
-note: Perhaps two different versions of crate `crate_a1` are being used?
- --> $DIR/type-mismatch-same-crate-name.rs:16:20
- |
-LL | a::try_foo(foo2);
- | ^^^^
+ = note: perhaps two different versions of crate `crate_a1` are being used?
error[E0308]: mismatched types
--> $DIR/type-mismatch-same-crate-name.rs:20:20
|
= note: expected struct `std::boxed::Box<(dyn main::a::Bar + 'static)>`
found struct `std::boxed::Box<dyn main::a::Bar>`
-note: Perhaps two different versions of crate `crate_a1` are being used?
- --> $DIR/type-mismatch-same-crate-name.rs:20:20
- |
-LL | a::try_bar(bar2);
- | ^^^^
+ = note: perhaps two different versions of crate `crate_a1` are being used?
error: aborting due to 2 previous errors
--- /dev/null
+use std::convert::AsRef;
+use std::path::Path;
+
+fn foo11(_bar: &dyn AsRef<Path>, _baz: &str) {}
+fn foo12(_bar: &str, _baz: &dyn AsRef<Path>) {}
+
+fn foo21(_bar: &dyn AsRef<str>, _baz: &str) {}
+fn foo22(_bar: &str, _baz: &dyn AsRef<str>) {}
+
+fn main() {
+ foo11("bar", &"baz"); //~ ERROR the size for values of type
+ foo11(&"bar", &"baz");
+ foo12(&"bar", "baz"); //~ ERROR the size for values of type
+ foo12(&"bar", &"baz");
+
+ foo21("bar", &"baz"); //~ ERROR the size for values of type
+ foo21(&"bar", &"baz");
+ foo22(&"bar", "baz"); //~ ERROR the size for values of type
+ foo22(&"bar", &"baz");
+}
--- /dev/null
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+ --> $DIR/unsized-fn-param.rs:11:11
+ |
+LL | foo11("bar", &"baz");
+ | ^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `std::marker::Sized` is not implemented for `str`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+ = note: required for the cast to the object type `dyn std::convert::AsRef<std::path::Path>`
+
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+ --> $DIR/unsized-fn-param.rs:13:19
+ |
+LL | foo12(&"bar", "baz");
+ | ^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `std::marker::Sized` is not implemented for `str`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+ = note: required for the cast to the object type `dyn std::convert::AsRef<std::path::Path>`
+
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+ --> $DIR/unsized-fn-param.rs:16:11
+ |
+LL | foo21("bar", &"baz");
+ | ^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `std::marker::Sized` is not implemented for `str`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+ = note: required for the cast to the object type `dyn std::convert::AsRef<str>`
+
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+ --> $DIR/unsized-fn-param.rs:18:19
+ |
+LL | foo22(&"bar", "baz");
+ | ^^^^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `std::marker::Sized` is not implemented for `str`
+ = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+ = note: required for the cast to the object type `dyn std::convert::AsRef<str>`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
}
let mut becoming_feature: Option<(&str, Feature)> = None;
- for (i, line) in contents.lines().enumerate() {
+ let mut iter_lines = contents.lines().enumerate().peekable();
+ while let Some((i, line)) = iter_lines.next() {
macro_rules! err {
($msg:expr) => {{
mf(Err($msg), file, i + 1);
}
if line.ends_with(']') {
mf(Ok((name, f.clone())), file, i + 1);
- } else if !line.ends_with(',') && !line.ends_with('\\') {
+ } else if !line.ends_with(',') && !line.ends_with('\\') && !line.ends_with('"') {
// We need to bail here because we might have missed the
// end of a stability attribute above because the ']'
// might not have been at the end of the line.
} else {
continue;
};
- let feature_name = match find_attr_val(line, "feature") {
+ let feature_name = match find_attr_val(line, "feature")
+ .or_else(|| iter_lines.peek().and_then(|next| find_attr_val(next.1, "feature")))
+ {
Some(name) => name,
None => err!("malformed stability attribute: missing `feature` key"),
};
super::walk(path, &mut super::filter_dirs, &mut |entry, contents| {
let file = entry.path();
let filename = file.file_name().unwrap().to_string_lossy();
- let extensions = [".rs", ".py", ".js", ".sh", ".c", ".cpp", ".h"];
+ let extensions = [".rs", ".py", ".js", ".sh", ".c", ".cpp", ".h", ".md"];
if extensions.iter().all(|e| !filename.ends_with(e)) ||
filename.starts_with(".#") {
return
}
+ if filename.ends_with(".md") &&
+ file.parent()
+ .unwrap()
+ .file_name()
+ .unwrap()
+ .to_string_lossy() != "error_codes" {
+ // We don't want to check all ".md" files (almost of of them aren't compliant
+ // currently), just the long error code explanation ones.
+ return;
+ }
+
if contents.is_empty() {
tidy_error!(bad, "{}: empty file", file.display());
}
- let max_columns = if filename == "error_codes.rs" {
+ let max_columns = if filename == "error_codes.rs" || filename.ends_with(".md") {
ERROR_CODE_COLS
} else {
COLS