Auto merge of #57063 - kennytm:rollup, r=kennytm

Rollup of 25 pull requests

Successful merges:

 - #56802 (Add DoubleEndedIterator::nth_back)
 - #56909 (static eval: Do not ICE on layout size overflow)
 - #56914 (Ignore ui/target-feature-gate on sparc, sparc64, powerpc, powerpc64 and powerpc64le)
 - #56919 (Remove a wrong multiplier on relocation offset computation)
 - #56933 (Add --progress to git submodule commands in x.py)
 - #56936 (rename div_euc -> div_euclid, and mod_euc -> rem_euclid)
 - #56941 (deny intra-doc link resolution failures in libstd)
 - #56945 (Fix rustdoc-js tests)
 - #56967 (Replace current crate's searchIndex when regenerating)
 - #56970 (Mem uninit doc ptr drop)
 - #56973 (make basic CTFE tracing available on release builds)
 - #56979 (Adding unwinding support for x86_64_fortanix_unknown_sgx target.)
 - #56981 (miri: allocation is infallible)
 - #56984 (A few tweaks to dropck_outlives)
 - #56989 (Fix compiletest `trim` deprecation warnings)
 - #56992 (suggest similar lint names for unknown lints)
 - #57002 (Stabilize Vec(Deque)::resize_with)
 - #57011 (rustdoc: add new CLI flag to load static files from a different location)
 - #57027 (Optimize away a move)
 - #57034 (Inline tweaks)
 - #57039 (Update migrate warning wording.)
 - #57040 (Fix feature gate to point to 1.32.0 for `path_from_str`)
 - #57049 (Stabilize #[repr(packed(N))])
 - #57050 (Fixed typo in HashMap documentation)
 - #57052 (Fix stabilization version numbers (exhaustive_integer_patterns + macro_literal_matcher))
This commit is contained in:
bors 2018-12-22 23:12:23 +00:00
commit 16329b0ad3
99 changed files with 869 additions and 450 deletions

View file

@ -678,10 +678,10 @@ class RustBuild(object):
print("Updating submodule", module) print("Updating submodule", module)
run(["git", "submodule", "-q", "sync", module], run(["git", "submodule", "-q", "sync", "--progress", module],
cwd=self.rust_root, verbose=self.verbose) cwd=self.rust_root, verbose=self.verbose)
run(["git", "submodule", "update", run(["git", "submodule", "update",
"--init", "--recursive", module], "--init", "--recursive", "--progress", module],
cwd=self.rust_root, verbose=self.verbose) cwd=self.rust_root, verbose=self.verbose)
run(["git", "reset", "-q", "--hard"], run(["git", "reset", "-q", "--hard"],
cwd=module_path, verbose=self.verbose) cwd=module_path, verbose=self.verbose)

View file

@ -402,3 +402,18 @@ Using `index-page` option enables `enable-index-page` option as well.
### `--enable-index-page`: generate a default index page for docs ### `--enable-index-page`: generate a default index page for docs
This feature allows the generation of a default index-page which lists the generated crates. This feature allows the generation of a default index-page which lists the generated crates.
### `--static-root-path`: control how static files are loaded in HTML output
Using this flag looks like this:
```bash
$ rustdoc src/lib.rs -Z unstable-options --static-root-path '/cache/'
```
This flag controls how rustdoc links to its static files on HTML pages. If you're hosting a lot of
crates' docs generated by the same version of rustdoc, you can use this flag to cache rustdoc's CSS,
JavaScript, and font files in a single location, rather than duplicating it once per "doc root"
(grouping of crate docs generated into the same output directory, like with `cargo doc`). Per-crate
files like the search index will still load from the documentation root, but anything that gets
renamed with `--resource-suffix` will load from the given path.

View file

@ -1,8 +0,0 @@
# `repr_packed`
The tracking issue for this feature is [#33158]
[#33158]: https://github.com/rust-lang/rust/issues/33158
------------------------

View file

@ -1897,8 +1897,6 @@ impl<T> VecDeque<T> {
/// # Examples /// # Examples
/// ///
/// ``` /// ```
/// #![feature(vec_resize_with)]
///
/// use std::collections::VecDeque; /// use std::collections::VecDeque;
/// ///
/// let mut buf = VecDeque::new(); /// let mut buf = VecDeque::new();
@ -1917,7 +1915,7 @@ impl<T> VecDeque<T> {
/// buf.resize_with(5, || { state += 1; state }); /// buf.resize_with(5, || { state += 1; state });
/// assert_eq!(buf, [5, 10, 101, 102, 103]); /// assert_eq!(buf, [5, 10, 101, 102, 103]);
/// ``` /// ```
#[unstable(feature = "vec_resize_with", issue = "41758")] #[stable(feature = "vec_resize_with", since = "1.33.0")]
pub fn resize_with(&mut self, new_len: usize, generator: impl FnMut()->T) { pub fn resize_with(&mut self, new_len: usize, generator: impl FnMut()->T) {
let len = self.len(); let len = self.len();

View file

@ -72,6 +72,8 @@
test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))] test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))]
#![no_std] #![no_std]
#![needs_allocator] #![needs_allocator]
#![deny(intra_doc_link_resolution_failure)]
#![deny(missing_debug_implementations)] #![deny(missing_debug_implementations)]
#![cfg_attr(not(test), feature(fn_traits))] #![cfg_attr(not(test), feature(fn_traits))]

View file

@ -843,6 +843,8 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Rc<T> {
/// drop(foo); // Doesn't print anything /// drop(foo); // Doesn't print anything
/// drop(foo2); // Prints "dropped!" /// drop(foo2); // Prints "dropped!"
/// ``` /// ```
///
/// [`Weak`]: ../../std/rc/struct.Weak.html
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
self.dec_strong(); self.dec_strong();
@ -1422,9 +1424,10 @@ impl<T: ?Sized + fmt::Debug> fmt::Debug for Weak<T> {
#[stable(feature = "downgraded_weak", since = "1.10.0")] #[stable(feature = "downgraded_weak", since = "1.10.0")]
impl<T> Default for Weak<T> { impl<T> Default for Weak<T> {
/// Constructs a new `Weak<T>`, allocating memory for `T` without initializing /// Constructs a new `Weak<T>`, allocating memory for `T` without initializing
/// it. Calling [`upgrade`][Weak::upgrade] on the return value always gives [`None`]. /// it. Calling [`upgrade`] on the return value always gives [`None`].
/// ///
/// [`None`]: ../../std/option/enum.Option.html /// [`None`]: ../../std/option/enum.Option.html
/// [`upgrade`]: ../../std/rc/struct.Weak.html#method.upgrade
/// ///
/// # Examples /// # Examples
/// ///

View file

@ -955,6 +955,8 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Arc<T> {
/// drop(foo); // Doesn't print anything /// drop(foo); // Doesn't print anything
/// drop(foo2); // Prints "dropped!" /// drop(foo2); // Prints "dropped!"
/// ``` /// ```
///
/// [`Weak`]: ../../std/sync/struct.Weak.html
#[inline] #[inline]
fn drop(&mut self) { fn drop(&mut self) {
// Because `fetch_sub` is already atomic, we do not need to synchronize // Because `fetch_sub` is already atomic, we do not need to synchronize
@ -1222,10 +1224,11 @@ impl<T: ?Sized> Clone for Weak<T> {
#[stable(feature = "downgraded_weak", since = "1.10.0")] #[stable(feature = "downgraded_weak", since = "1.10.0")]
impl<T> Default for Weak<T> { impl<T> Default for Weak<T> {
/// Constructs a new `Weak<T>`, without allocating memory. /// Constructs a new `Weak<T>`, without allocating memory.
/// Calling [`upgrade`][Weak::upgrade] on the return value always /// Calling [`upgrade`] on the return value always
/// gives [`None`]. /// gives [`None`].
/// ///
/// [`None`]: ../../std/option/enum.Option.html#variant.None /// [`None`]: ../../std/option/enum.Option.html#variant.None
/// [`upgrade`]: ../../std/sync/struct.Weak.html#method.upgrade
/// ///
/// # Examples /// # Examples
/// ///

View file

@ -1241,8 +1241,6 @@ impl<T> Vec<T> {
/// # Examples /// # Examples
/// ///
/// ``` /// ```
/// #![feature(vec_resize_with)]
///
/// let mut vec = vec![1, 2, 3]; /// let mut vec = vec![1, 2, 3];
/// vec.resize_with(5, Default::default); /// vec.resize_with(5, Default::default);
/// assert_eq!(vec, [1, 2, 3, 0, 0]); /// assert_eq!(vec, [1, 2, 3, 0, 0]);
@ -1255,7 +1253,7 @@ impl<T> Vec<T> {
/// ///
/// [`resize`]: #method.resize /// [`resize`]: #method.resize
/// [`Clone`]: ../../std/clone/trait.Clone.html /// [`Clone`]: ../../std/clone/trait.Clone.html
#[unstable(feature = "vec_resize_with", issue = "41758")] #[stable(feature = "vec_resize_with", since = "1.33.0")]
pub fn resize_with<F>(&mut self, new_len: usize, f: F) pub fn resize_with<F>(&mut self, new_len: usize, f: F)
where F: FnMut() -> T where F: FnMut() -> T
{ {

View file

@ -429,6 +429,9 @@ impl<I> Iterator for Rev<I> where I: DoubleEndedIterator {
#[inline] #[inline]
fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() } fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
#[inline]
fn nth(&mut self, n: usize) -> Option<<I as Iterator>::Item> { self.iter.nth_back(n) }
fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R where fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R where
Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B> Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B>
{ {
@ -461,6 +464,9 @@ impl<I> DoubleEndedIterator for Rev<I> where I: DoubleEndedIterator {
#[inline] #[inline]
fn next_back(&mut self) -> Option<<I as Iterator>::Item> { self.iter.next() } fn next_back(&mut self) -> Option<<I as Iterator>::Item> { self.iter.next() }
#[inline]
fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item> { self.iter.nth(n) }
fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R where fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R where
Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B> Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B>
{ {

View file

@ -427,6 +427,62 @@ pub trait DoubleEndedIterator: Iterator {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
fn next_back(&mut self) -> Option<Self::Item>; fn next_back(&mut self) -> Option<Self::Item>;
/// Returns the `n`th element from the end of the iterator.
///
/// This is essentially the reversed version of [`nth`]. Although like most indexing
/// operations, the count starts from zero, so `nth_back(0)` returns the first value fro
/// the end, `nth_back(1)` the second, and so on.
///
/// Note that all elements between the end and the returned element will be
/// consumed, including the returned element. This also means that calling
/// `nth_back(0)` multiple times on the same iterator will return different
/// elements.
///
/// `nth_back()` will return [`None`] if `n` is greater than or equal to the length of the
/// iterator.
///
/// [`None`]: ../../std/option/enum.Option.html#variant.None
/// [`nth`]: ../../std/iter/trait.Iterator.html#method.nth
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(iter_nth_back)]
/// let a = [1, 2, 3];
/// assert_eq!(a.iter().nth_back(2), Some(&1));
/// ```
///
/// Calling `nth_back()` multiple times doesn't rewind the iterator:
///
/// ```
/// #![feature(iter_nth_back)]
/// let a = [1, 2, 3];
///
/// let mut iter = a.iter();
///
/// assert_eq!(iter.nth_back(1), Some(&2));
/// assert_eq!(iter.nth_back(1), None);
/// ```
///
/// Returning `None` if there are less than `n + 1` elements:
///
/// ```
/// #![feature(iter_nth_back)]
/// let a = [1, 2, 3];
/// assert_eq!(a.iter().nth_back(10), None);
/// ```
#[inline]
#[unstable(feature = "iter_nth_back", issue = "56995")]
fn nth_back(&mut self, mut n: usize) -> Option<Self::Item> {
for x in self.rev() {
if n == 0 { return Some(x) }
n -= 1;
}
None
}
/// This is the reverse version of [`try_fold()`]: it takes elements /// This is the reverse version of [`try_fold()`]: it takes elements
/// starting from the back of the iterator. /// starting from the back of the iterator.
/// ///
@ -461,8 +517,11 @@ pub trait DoubleEndedIterator: Iterator {
/// ``` /// ```
#[inline] #[inline]
#[stable(feature = "iterator_try_fold", since = "1.27.0")] #[stable(feature = "iterator_try_fold", since = "1.27.0")]
fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R where fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B> where
Self: Sized,
F: FnMut(B, Self::Item) -> R,
R: Try<Ok=B>
{ {
let mut accum = init; let mut accum = init;
while let Some(x) = self.next_back() { while let Some(x) = self.next_back() {
@ -524,8 +583,10 @@ pub trait DoubleEndedIterator: Iterator {
/// ``` /// ```
#[inline] #[inline]
#[stable(feature = "iter_rfold", since = "1.27.0")] #[stable(feature = "iter_rfold", since = "1.27.0")]
fn rfold<B, F>(mut self, accum: B, mut f: F) -> B where fn rfold<B, F>(mut self, accum: B, mut f: F) -> B
Self: Sized, F: FnMut(B, Self::Item) -> B, where
Self: Sized,
F: FnMut(B, Self::Item) -> B,
{ {
self.try_rfold(accum, move |acc, x| Ok::<B, !>(f(acc, x))).unwrap() self.try_rfold(accum, move |acc, x| Ok::<B, !>(f(acc, x))).unwrap()
} }
@ -574,7 +635,8 @@ pub trait DoubleEndedIterator: Iterator {
/// ``` /// ```
#[inline] #[inline]
#[stable(feature = "iter_rfind", since = "1.27.0")] #[stable(feature = "iter_rfind", since = "1.27.0")]
fn rfind<P>(&mut self, mut predicate: P) -> Option<Self::Item> where fn rfind<P>(&mut self, mut predicate: P) -> Option<Self::Item>
where
Self: Sized, Self: Sized,
P: FnMut(&Self::Item) -> bool P: FnMut(&Self::Item) -> bool
{ {
@ -587,7 +649,12 @@ pub trait DoubleEndedIterator: Iterator {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl<'a, I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for &'a mut I { impl<'a, I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for &'a mut I {
fn next_back(&mut self) -> Option<I::Item> { (**self).next_back() } fn next_back(&mut self) -> Option<I::Item> {
(**self).next_back()
}
fn nth_back(&mut self, n: usize) -> Option<I::Item> {
(**self).nth_back(n)
}
} }
/// An iterator that knows its exact length. /// An iterator that knows its exact length.

View file

@ -71,6 +71,7 @@
#![no_core] #![no_core]
#![deny(missing_docs)] #![deny(missing_docs)]
#![deny(intra_doc_link_resolution_failure)]
#![deny(missing_debug_implementations)] #![deny(missing_debug_implementations)]
#![feature(allow_internal_unstable)] #![feature(allow_internal_unstable)]

View file

@ -530,6 +530,12 @@ pub unsafe fn zeroed<T>() -> T {
/// it goes out of scope (and therefore would be dropped). Note that this /// it goes out of scope (and therefore would be dropped). Note that this
/// includes a `panic` occurring and unwinding the stack suddenly. /// includes a `panic` occurring and unwinding the stack suddenly.
/// ///
/// If you partially initialize an array, you may need to use
/// [`ptr::drop_in_place`][drop_in_place] to remove the elements you have fully
/// initialized followed by [`mem::forget`][mem_forget] to prevent drop running
/// on the array. If a partially allocated array is dropped this will lead to
/// undefined behaviour.
///
/// # Examples /// # Examples
/// ///
/// Here's how to safely initialize an array of [`Vec`]s. /// Here's how to safely initialize an array of [`Vec`]s.
@ -583,11 +589,44 @@ pub unsafe fn zeroed<T>() -> T {
/// println!("{:?}", &data[0]); /// println!("{:?}", &data[0]);
/// ``` /// ```
/// ///
/// This example shows how to handle partially initialized arrays, which could
/// be found in low-level datastructures.
///
/// ```
/// use std::mem;
/// use std::ptr;
///
/// // Count the number of elements we have assigned.
/// let mut data_len: usize = 0;
/// let mut data: [String; 1000];
///
/// unsafe {
/// data = mem::uninitialized();
///
/// for elem in &mut data[0..500] {
/// ptr::write(elem, String::from("hello"));
/// data_len += 1;
/// }
///
/// // For each item in the array, drop if we allocated it.
/// for i in &mut data[0..data_len] {
/// ptr::drop_in_place(i);
/// }
/// }
/// // Forget the data. If this is allowed to drop, you may see a crash such as:
/// // 'mem_uninit_test(2457,0x7fffb55dd380) malloc: *** error for object
/// // 0x7ff3b8402920: pointer being freed was not allocated'
/// mem::forget(data);
/// ```
///
/// [`Vec`]: ../../std/vec/struct.Vec.html /// [`Vec`]: ../../std/vec/struct.Vec.html
/// [`vec!`]: ../../std/macro.vec.html /// [`vec!`]: ../../std/macro.vec.html
/// [`Clone`]: ../../std/clone/trait.Clone.html /// [`Clone`]: ../../std/clone/trait.Clone.html
/// [ub]: ../../reference/behavior-considered-undefined.html /// [ub]: ../../reference/behavior-considered-undefined.html
/// [write]: ../ptr/fn.write.html /// [write]: ../ptr/fn.write.html
/// [drop_in_place]: ../ptr/fn.drop_in_place.html
/// [mem_zeroed]: fn.zeroed.html
/// [mem_forget]: fn.forget.html
/// [copy]: ../intrinsics/fn.copy.html /// [copy]: ../intrinsics/fn.copy.html
/// [copy_no]: ../intrinsics/fn.copy_nonoverlapping.html /// [copy_no]: ../intrinsics/fn.copy_nonoverlapping.html
/// [`Drop`]: ../ops/trait.Drop.html /// [`Drop`]: ../ops/trait.Drop.html
@ -984,6 +1023,9 @@ impl<T> ManuallyDrop<T> {
/// ///
/// This function semantically moves out the contained value without preventing further usage. /// This function semantically moves out the contained value without preventing further usage.
/// It is up to the user of this method to ensure that this container is not used again. /// It is up to the user of this method to ensure that this container is not used again.
///
/// [`ManuallyDrop::drop`]: #method.drop
/// [`ManuallyDrop::into_inner`]: #method.into_inner
#[must_use = "if you don't need the value, you can use `ManuallyDrop::drop` instead"] #[must_use = "if you don't need the value, you can use `ManuallyDrop::drop` instead"]
#[unstable(feature = "manually_drop_take", issue = "55422")] #[unstable(feature = "manually_drop_take", issue = "55422")]
#[inline] #[inline]

View file

@ -673,7 +673,7 @@ $EndFeature, "
} }
doc_comment! { doc_comment! {
concat!("Checked Euclidean division. Computes `self.div_euc(rhs)`, concat!("Checked Euclidean division. Computes `self.div_euclid(rhs)`,
returning `None` if `rhs == 0` or the division results in overflow. returning `None` if `rhs == 0` or the division results in overflow.
# Examples # Examples
@ -683,17 +683,17 @@ Basic usage:
``` ```
#![feature(euclidean_division)] #![feature(euclidean_division)]
assert_eq!((", stringify!($SelfT), assert_eq!((", stringify!($SelfT),
"::min_value() + 1).checked_div_euc(-1), Some(", stringify!($Max), ")); "::min_value() + 1).checked_div_euclid(-1), Some(", stringify!($Max), "));
assert_eq!(", stringify!($SelfT), "::min_value().checked_div_euc(-1), None); assert_eq!(", stringify!($SelfT), "::min_value().checked_div_euclid(-1), None);
assert_eq!((1", stringify!($SelfT), ").checked_div_euc(0), None); assert_eq!((1", stringify!($SelfT), ").checked_div_euclid(0), None);
```"), ```"),
#[unstable(feature = "euclidean_division", issue = "49048")] #[unstable(feature = "euclidean_division", issue = "49048")]
#[inline] #[inline]
pub fn checked_div_euc(self, rhs: Self) -> Option<Self> { pub fn checked_div_euclid(self, rhs: Self) -> Option<Self> {
if rhs == 0 || (self == Self::min_value() && rhs == -1) { if rhs == 0 || (self == Self::min_value() && rhs == -1) {
None None
} else { } else {
Some(self.div_euc(rhs)) Some(self.div_euclid(rhs))
} }
} }
} }
@ -726,8 +726,8 @@ $EndFeature, "
} }
doc_comment! { doc_comment! {
concat!("Checked Euclidean modulo. Computes `self.mod_euc(rhs)`, returning `None` if concat!("Checked Euclidean remainder. Computes `self.rem_euclid(rhs)`, returning `None`
`rhs == 0` or the division results in overflow. if `rhs == 0` or the division results in overflow.
# Examples # Examples
@ -737,17 +737,17 @@ Basic usage:
#![feature(euclidean_division)] #![feature(euclidean_division)]
use std::", stringify!($SelfT), "; use std::", stringify!($SelfT), ";
assert_eq!(5", stringify!($SelfT), ".checked_mod_euc(2), Some(1)); assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(2), Some(1));
assert_eq!(5", stringify!($SelfT), ".checked_mod_euc(0), None); assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(0), None);
assert_eq!(", stringify!($SelfT), "::MIN.checked_mod_euc(-1), None); assert_eq!(", stringify!($SelfT), "::MIN.checked_rem_euclid(-1), None);
```"), ```"),
#[unstable(feature = "euclidean_division", issue = "49048")] #[unstable(feature = "euclidean_division", issue = "49048")]
#[inline] #[inline]
pub fn checked_mod_euc(self, rhs: Self) -> Option<Self> { pub fn checked_rem_euclid(self, rhs: Self) -> Option<Self> {
if rhs == 0 || (self == Self::min_value() && rhs == -1) { if rhs == 0 || (self == Self::min_value() && rhs == -1) {
None None
} else { } else {
Some(self.mod_euc(rhs)) Some(self.rem_euclid(rhs))
} }
} }
} }
@ -1089,7 +1089,7 @@ $EndFeature, "
} }
doc_comment! { doc_comment! {
concat!("Wrapping Euclidean division. Computes `self.div_euc(rhs)`, concat!("Wrapping Euclidean division. Computes `self.div_euclid(rhs)`,
wrapping around at the boundary of the type. wrapping around at the boundary of the type.
Wrapping will only occur in `MIN / -1` on a signed type (where `MIN` is the negative minimal value Wrapping will only occur in `MIN / -1` on a signed type (where `MIN` is the negative minimal value
@ -1106,13 +1106,13 @@ Basic usage:
``` ```
#![feature(euclidean_division)] #![feature(euclidean_division)]
assert_eq!(100", stringify!($SelfT), ".wrapping_div_euc(10), 10); assert_eq!(100", stringify!($SelfT), ".wrapping_div_euclid(10), 10);
assert_eq!((-128i8).wrapping_div_euc(-1), -128); assert_eq!((-128i8).wrapping_div_euclid(-1), -128);
```"), ```"),
#[unstable(feature = "euclidean_division", issue = "49048")] #[unstable(feature = "euclidean_division", issue = "49048")]
#[inline] #[inline]
pub fn wrapping_div_euc(self, rhs: Self) -> Self { pub fn wrapping_div_euclid(self, rhs: Self) -> Self {
self.overflowing_div_euc(rhs).0 self.overflowing_div_euclid(rhs).0
} }
} }
@ -1145,8 +1145,8 @@ $EndFeature, "
} }
doc_comment! { doc_comment! {
concat!("Wrapping Euclidean modulo. Computes `self.mod_euc(rhs)`, wrapping around at the concat!("Wrapping Euclidean remainder. Computes `self.rem_euclid(rhs)`, wrapping around
boundary of the type. at the boundary of the type.
Wrapping will only occur in `MIN % -1` on a signed type (where `MIN` is the negative minimal value Wrapping will only occur in `MIN % -1` on a signed type (where `MIN` is the negative minimal value
for the type). In this case, this method returns 0. for the type). In this case, this method returns 0.
@ -1161,13 +1161,13 @@ Basic usage:
``` ```
#![feature(euclidean_division)] #![feature(euclidean_division)]
assert_eq!(100", stringify!($SelfT), ".wrapping_mod_euc(10), 0); assert_eq!(100", stringify!($SelfT), ".wrapping_rem_euclid(10), 0);
assert_eq!((-128i8).wrapping_mod_euc(-1), 0); assert_eq!((-128i8).wrapping_rem_euclid(-1), 0);
```"), ```"),
#[unstable(feature = "euclidean_division", issue = "49048")] #[unstable(feature = "euclidean_division", issue = "49048")]
#[inline] #[inline]
pub fn wrapping_mod_euc(self, rhs: Self) -> Self { pub fn wrapping_rem_euclid(self, rhs: Self) -> Self {
self.overflowing_mod_euc(rhs).0 self.overflowing_rem_euclid(rhs).0
} }
} }
@ -1442,7 +1442,7 @@ $EndFeature, "
} }
doc_comment! { doc_comment! {
concat!("Calculates the quotient of Euclidean division `self.div_euc(rhs)`. concat!("Calculates the quotient of Euclidean division `self.div_euclid(rhs)`.
Returns a tuple of the divisor along with a boolean indicating whether an arithmetic overflow would Returns a tuple of the divisor along with a boolean indicating whether an arithmetic overflow would
occur. If an overflow would occur then `self` is returned. occur. If an overflow would occur then `self` is returned.
@ -1459,17 +1459,17 @@ Basic usage:
#![feature(euclidean_division)] #![feature(euclidean_division)]
use std::", stringify!($SelfT), "; use std::", stringify!($SelfT), ";
assert_eq!(5", stringify!($SelfT), ".overflowing_div_euc(2), (2, false)); assert_eq!(5", stringify!($SelfT), ".overflowing_div_euclid(2), (2, false));
assert_eq!(", stringify!($SelfT), "::MIN.overflowing_div_euc(-1), (", stringify!($SelfT), assert_eq!(", stringify!($SelfT), "::MIN.overflowing_div_euclid(-1), (", stringify!($SelfT),
"::MIN, true)); "::MIN, true));
```"), ```"),
#[inline] #[inline]
#[unstable(feature = "euclidean_division", issue = "49048")] #[unstable(feature = "euclidean_division", issue = "49048")]
pub fn overflowing_div_euc(self, rhs: Self) -> (Self, bool) { pub fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) {
if self == Self::min_value() && rhs == -1 { if self == Self::min_value() && rhs == -1 {
(self, true) (self, true)
} else { } else {
(self.div_euc(rhs), false) (self.div_euclid(rhs), false)
} }
} }
} }
@ -1508,7 +1508,7 @@ $EndFeature, "
doc_comment! { doc_comment! {
concat!("Calculates the remainder `self.mod_euc(rhs)` by Euclidean division. concat!("Overflowing Euclidean remainder. Calculates `self.rem_euclid(rhs)`.
Returns a tuple of the remainder after dividing along with a boolean indicating whether an Returns a tuple of the remainder after dividing along with a boolean indicating whether an
arithmetic overflow would occur. If an overflow would occur then 0 is returned. arithmetic overflow would occur. If an overflow would occur then 0 is returned.
@ -1525,16 +1525,16 @@ Basic usage:
#![feature(euclidean_division)] #![feature(euclidean_division)]
use std::", stringify!($SelfT), "; use std::", stringify!($SelfT), ";
assert_eq!(5", stringify!($SelfT), ".overflowing_mod_euc(2), (1, false)); assert_eq!(5", stringify!($SelfT), ".overflowing_rem_euclid(2), (1, false));
assert_eq!(", stringify!($SelfT), "::MIN.overflowing_mod_euc(-1), (0, true)); assert_eq!(", stringify!($SelfT), "::MIN.overflowing_rem_euclid(-1), (0, true));
```"), ```"),
#[unstable(feature = "euclidean_division", issue = "49048")] #[unstable(feature = "euclidean_division", issue = "49048")]
#[inline] #[inline]
pub fn overflowing_mod_euc(self, rhs: Self) -> (Self, bool) { pub fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) {
if self == Self::min_value() && rhs == -1 { if self == Self::min_value() && rhs == -1 {
(0, true) (0, true)
} else { } else {
(self.mod_euc(rhs), false) (self.rem_euclid(rhs), false)
} }
} }
} }
@ -1739,9 +1739,13 @@ $EndFeature, "
doc_comment! { doc_comment! {
concat!("Calculates the quotient of Euclidean division of `self` by `rhs`. concat!("Calculates the quotient of Euclidean division of `self` by `rhs`.
This computes the integer `n` such that `self = n * rhs + self.mod_euc(rhs)`. This computes the integer `n` such that `self = n * rhs + self.rem_euclid(rhs)`,
with `0 <= self.rem_euclid(rhs) < rhs`.
In other words, the result is `self / rhs` rounded to the integer `n` In other words, the result is `self / rhs` rounded to the integer `n`
such that `self >= n * rhs`. such that `self >= n * rhs`.
If `self > 0`, this is equal to round towards zero (the default in Rust);
if `self < 0`, this is equal to round towards +/- infinity.
# Panics # Panics
@ -1756,15 +1760,15 @@ Basic usage:
let a: ", stringify!($SelfT), " = 7; // or any other integer type let a: ", stringify!($SelfT), " = 7; // or any other integer type
let b = 4; let b = 4;
assert_eq!(a.div_euc(b), 1); // 7 >= 4 * 1 assert_eq!(a.div_euclid(b), 1); // 7 >= 4 * 1
assert_eq!(a.div_euc(-b), -1); // 7 >= -4 * -1 assert_eq!(a.div_euclid(-b), -1); // 7 >= -4 * -1
assert_eq!((-a).div_euc(b), -2); // -7 >= 4 * -2 assert_eq!((-a).div_euclid(b), -2); // -7 >= 4 * -2
assert_eq!((-a).div_euc(-b), 2); // -7 >= -4 * 2 assert_eq!((-a).div_euclid(-b), 2); // -7 >= -4 * 2
```"), ```"),
#[unstable(feature = "euclidean_division", issue = "49048")] #[unstable(feature = "euclidean_division", issue = "49048")]
#[inline] #[inline]
#[rustc_inherit_overflow_checks] #[rustc_inherit_overflow_checks]
pub fn div_euc(self, rhs: Self) -> Self { pub fn div_euclid(self, rhs: Self) -> Self {
let q = self / rhs; let q = self / rhs;
if self % rhs < 0 { if self % rhs < 0 {
return if rhs > 0 { q - 1 } else { q + 1 } return if rhs > 0 { q - 1 } else { q + 1 }
@ -1775,9 +1779,11 @@ assert_eq!((-a).div_euc(-b), 2); // -7 >= -4 * 2
doc_comment! { doc_comment! {
concat!("Calculates the remainder `self mod rhs` by Euclidean division. concat!("Calculates the least nonnegative remainder of `self (mod rhs)`.
In particular, the result `n` satisfies `0 <= n < rhs.abs()`. This is done as if by the Euclidean division algorithm -- given
`r = self.rem_euclid(rhs)`, `self = rhs * self.div_euclid(rhs) + r`, and
`0 <= r < abs(rhs)`.
# Panics # Panics
@ -1792,15 +1798,15 @@ Basic usage:
let a: ", stringify!($SelfT), " = 7; // or any other integer type let a: ", stringify!($SelfT), " = 7; // or any other integer type
let b = 4; let b = 4;
assert_eq!(a.mod_euc(b), 3); assert_eq!(a.rem_euclid(b), 3);
assert_eq!((-a).mod_euc(b), 1); assert_eq!((-a).rem_euclid(b), 1);
assert_eq!(a.mod_euc(-b), 3); assert_eq!(a.rem_euclid(-b), 3);
assert_eq!((-a).mod_euc(-b), 1); assert_eq!((-a).rem_euclid(-b), 1);
```"), ```"),
#[unstable(feature = "euclidean_division", issue = "49048")] #[unstable(feature = "euclidean_division", issue = "49048")]
#[inline] #[inline]
#[rustc_inherit_overflow_checks] #[rustc_inherit_overflow_checks]
pub fn mod_euc(self, rhs: Self) -> Self { pub fn rem_euclid(self, rhs: Self) -> Self {
let r = self % rhs; let r = self % rhs;
if r < 0 { if r < 0 {
if rhs < 0 { if rhs < 0 {
@ -2611,7 +2617,7 @@ assert_eq!(1", stringify!($SelfT), ".checked_div(0), None);", $EndFeature, "
} }
doc_comment! { doc_comment! {
concat!("Checked Euclidean division. Computes `self.div_euc(rhs)`, returning `None` concat!("Checked Euclidean division. Computes `self.div_euclid(rhs)`, returning `None`
if `rhs == 0`. if `rhs == 0`.
# Examples # Examples
@ -2620,16 +2626,16 @@ Basic usage:
``` ```
#![feature(euclidean_division)] #![feature(euclidean_division)]
assert_eq!(128", stringify!($SelfT), ".checked_div(2), Some(64)); assert_eq!(128", stringify!($SelfT), ".checked_div_euclid(2), Some(64));
assert_eq!(1", stringify!($SelfT), ".checked_div_euc(0), None); assert_eq!(1", stringify!($SelfT), ".checked_div_euclid(0), None);
```"), ```"),
#[unstable(feature = "euclidean_division", issue = "49048")] #[unstable(feature = "euclidean_division", issue = "49048")]
#[inline] #[inline]
pub fn checked_div_euc(self, rhs: Self) -> Option<Self> { pub fn checked_div_euclid(self, rhs: Self) -> Option<Self> {
if rhs == 0 { if rhs == 0 {
None None
} else { } else {
Some(self.div_euc(rhs)) Some(self.div_euclid(rhs))
} }
} }
} }
@ -2659,7 +2665,7 @@ assert_eq!(5", stringify!($SelfT), ".checked_rem(0), None);", $EndFeature, "
} }
doc_comment! { doc_comment! {
concat!("Checked Euclidean modulo. Computes `self.mod_euc(rhs)`, returning `None` concat!("Checked Euclidean modulo. Computes `self.rem_euclid(rhs)`, returning `None`
if `rhs == 0`. if `rhs == 0`.
# Examples # Examples
@ -2668,16 +2674,16 @@ Basic usage:
``` ```
#![feature(euclidean_division)] #![feature(euclidean_division)]
assert_eq!(5", stringify!($SelfT), ".checked_mod_euc(2), Some(1)); assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(2), Some(1));
assert_eq!(5", stringify!($SelfT), ".checked_mod_euc(0), None); assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(0), None);
```"), ```"),
#[unstable(feature = "euclidean_division", issue = "49048")] #[unstable(feature = "euclidean_division", issue = "49048")]
#[inline] #[inline]
pub fn checked_mod_euc(self, rhs: Self) -> Option<Self> { pub fn checked_rem_euclid(self, rhs: Self) -> Option<Self> {
if rhs == 0 { if rhs == 0 {
None None
} else { } else {
Some(self.mod_euc(rhs)) Some(self.rem_euclid(rhs))
} }
} }
} }
@ -2965,11 +2971,14 @@ Basic usage:
} }
doc_comment! { doc_comment! {
concat!("Wrapping Euclidean division. Computes `self.div_euc(rhs)`. concat!("Wrapping Euclidean division. Computes `self.div_euclid(rhs)`.
Wrapped division on unsigned types is just normal division. Wrapped division on unsigned types is just normal division.
There's no way wrapping could ever happen. There's no way wrapping could ever happen.
This function exists, so that all operations This function exists, so that all operations
are accounted for in the wrapping operations. are accounted for in the wrapping operations.
Since, for the positive integers, all common
definitions of division are equal, this
is exactly equal to `self.wrapping_div(rhs)`.
# Examples # Examples
@ -2977,11 +2986,11 @@ Basic usage:
``` ```
#![feature(euclidean_division)] #![feature(euclidean_division)]
assert_eq!(100", stringify!($SelfT), ".wrapping_div_euc(10), 10); assert_eq!(100", stringify!($SelfT), ".wrapping_div_euclid(10), 10);
```"), ```"),
#[unstable(feature = "euclidean_division", issue = "49048")] #[unstable(feature = "euclidean_division", issue = "49048")]
#[inline] #[inline]
pub fn wrapping_div_euc(self, rhs: Self) -> Self { pub fn wrapping_div_euclid(self, rhs: Self) -> Self {
self / rhs self / rhs
} }
} }
@ -3009,12 +3018,15 @@ Basic usage:
} }
doc_comment! { doc_comment! {
concat!("Wrapping Euclidean modulo. Computes `self.mod_euc(rhs)`. concat!("Wrapping Euclidean modulo. Computes `self.rem_euclid(rhs)`.
Wrapped modulo calculation on unsigned types is Wrapped modulo calculation on unsigned types is
just the regular remainder calculation. just the regular remainder calculation.
There's no way wrapping could ever happen. There's no way wrapping could ever happen.
This function exists, so that all operations This function exists, so that all operations
are accounted for in the wrapping operations. are accounted for in the wrapping operations.
Since, for the positive integers, all common
definitions of division are equal, this
is exactly equal to `self.wrapping_rem(rhs)`.
# Examples # Examples
@ -3022,11 +3034,11 @@ Basic usage:
``` ```
#![feature(euclidean_division)] #![feature(euclidean_division)]
assert_eq!(100", stringify!($SelfT), ".wrapping_mod_euc(10), 0); assert_eq!(100", stringify!($SelfT), ".wrapping_rem_euclid(10), 0);
```"), ```"),
#[unstable(feature = "euclidean_division", issue = "49048")] #[unstable(feature = "euclidean_division", issue = "49048")]
#[inline] #[inline]
pub fn wrapping_mod_euc(self, rhs: Self) -> Self { pub fn wrapping_rem_euclid(self, rhs: Self) -> Self {
self % rhs self % rhs
} }
} }
@ -3270,12 +3282,15 @@ Basic usage
} }
doc_comment! { doc_comment! {
concat!("Calculates the quotient of Euclidean division `self.div_euc(rhs)`. concat!("Calculates the quotient of Euclidean division `self.div_euclid(rhs)`.
Returns a tuple of the divisor along with a boolean indicating Returns a tuple of the divisor along with a boolean indicating
whether an arithmetic overflow would occur. Note that for unsigned whether an arithmetic overflow would occur. Note that for unsigned
integers overflow never occurs, so the second value is always integers overflow never occurs, so the second value is always
`false`. `false`.
Since, for the positive integers, all common
definitions of division are equal, this
is exactly equal to `self.overflowing_div(rhs)`.
# Panics # Panics
@ -3287,11 +3302,11 @@ Basic usage
``` ```
#![feature(euclidean_division)] #![feature(euclidean_division)]
assert_eq!(5", stringify!($SelfT), ".overflowing_div_euc(2), (2, false)); assert_eq!(5", stringify!($SelfT), ".overflowing_div_euclid(2), (2, false));
```"), ```"),
#[inline] #[inline]
#[unstable(feature = "euclidean_division", issue = "49048")] #[unstable(feature = "euclidean_division", issue = "49048")]
pub fn overflowing_div_euc(self, rhs: Self) -> (Self, bool) { pub fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) {
(self / rhs, false) (self / rhs, false)
} }
} }
@ -3323,12 +3338,15 @@ Basic usage
} }
doc_comment! { doc_comment! {
concat!("Calculates the remainder `self.mod_euc(rhs)` by Euclidean division. concat!("Calculates the remainder `self.rem_euclid(rhs)` as if by Euclidean division.
Returns a tuple of the modulo after dividing along with a boolean Returns a tuple of the modulo after dividing along with a boolean
indicating whether an arithmetic overflow would occur. Note that for indicating whether an arithmetic overflow would occur. Note that for
unsigned integers overflow never occurs, so the second value is unsigned integers overflow never occurs, so the second value is
always `false`. always `false`.
Since, for the positive integers, all common
definitions of division are equal, this operation
is exactly equal to `self.overflowing_rem(rhs)`.
# Panics # Panics
@ -3340,11 +3358,11 @@ Basic usage
``` ```
#![feature(euclidean_division)] #![feature(euclidean_division)]
assert_eq!(5", stringify!($SelfT), ".overflowing_mod_euc(2), (1, false)); assert_eq!(5", stringify!($SelfT), ".overflowing_rem_euclid(2), (1, false));
```"), ```"),
#[inline] #[inline]
#[unstable(feature = "euclidean_division", issue = "49048")] #[unstable(feature = "euclidean_division", issue = "49048")]
pub fn overflowing_mod_euc(self, rhs: Self) -> (Self, bool) { pub fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) {
(self % rhs, false) (self % rhs, false)
} }
} }
@ -3511,7 +3529,9 @@ Basic usage:
doc_comment! { doc_comment! {
concat!("Performs Euclidean division. concat!("Performs Euclidean division.
For unsigned types, this is just the same as `self / rhs`. Since, for the positive integers, all common
definitions of division are equal, this
is exactly equal to `self / rhs`.
# Examples # Examples
@ -3519,21 +3539,23 @@ Basic usage:
``` ```
#![feature(euclidean_division)] #![feature(euclidean_division)]
assert_eq!(7", stringify!($SelfT), ".div_euc(4), 1); // or any other integer type assert_eq!(7", stringify!($SelfT), ".div_euclid(4), 1); // or any other integer type
```"), ```"),
#[unstable(feature = "euclidean_division", issue = "49048")] #[unstable(feature = "euclidean_division", issue = "49048")]
#[inline] #[inline]
#[rustc_inherit_overflow_checks] #[rustc_inherit_overflow_checks]
pub fn div_euc(self, rhs: Self) -> Self { pub fn div_euclid(self, rhs: Self) -> Self {
self / rhs self / rhs
} }
} }
doc_comment! { doc_comment! {
concat!("Calculates the remainder `self mod rhs` by Euclidean division. concat!("Calculates the least remainder of `self (mod rhs)`.
For unsigned types, this is just the same as `self % rhs`. Since, for the positive integers, all common
definitions of division are equal, this
is exactly equal to `self % rhs`.
# Examples # Examples
@ -3541,12 +3563,12 @@ Basic usage:
``` ```
#![feature(euclidean_division)] #![feature(euclidean_division)]
assert_eq!(7", stringify!($SelfT), ".mod_euc(4), 3); // or any other integer type assert_eq!(7", stringify!($SelfT), ".rem_euclid(4), 3); // or any other integer type
```"), ```"),
#[unstable(feature = "euclidean_division", issue = "49048")] #[unstable(feature = "euclidean_division", issue = "49048")]
#[inline] #[inline]
#[rustc_inherit_overflow_checks] #[rustc_inherit_overflow_checks]
pub fn mod_euc(self, rhs: Self) -> Self { pub fn rem_euclid(self, rhs: Self) -> Self {
self % rhs self % rhs
} }
} }

View file

@ -877,6 +877,7 @@ impl<T> [T] {
/// assert_eq!(iter.remainder(), &['l']); /// assert_eq!(iter.remainder(), &['l']);
/// ``` /// ```
/// ///
/// [`chunks`]: #method.chunks
/// [`rchunks`]: #method.rchunks /// [`rchunks`]: #method.rchunks
/// [`chunks_exact`]: #method.chunks_exact /// [`chunks_exact`]: #method.chunks_exact
#[stable(feature = "rchunks", since = "1.31.0")] #[stable(feature = "rchunks", since = "1.31.0")]
@ -921,6 +922,7 @@ impl<T> [T] {
/// assert_eq!(v, &[0, 2, 2, 1, 1]); /// assert_eq!(v, &[0, 2, 2, 1, 1]);
/// ``` /// ```
/// ///
/// [`chunks_mut`]: #method.chunks_mut
/// [`rchunks_mut`]: #method.rchunks_mut /// [`rchunks_mut`]: #method.rchunks_mut
/// [`chunks_exact_mut`]: #method.chunks_exact_mut /// [`chunks_exact_mut`]: #method.chunks_exact_mut
#[stable(feature = "rchunks", since = "1.31.0")] #[stable(feature = "rchunks", since = "1.31.0")]

View file

@ -1016,6 +1016,33 @@ fn test_iterator_nth() {
assert_eq!(v.iter().nth(v.len()), None); assert_eq!(v.iter().nth(v.len()), None);
} }
#[test]
fn test_iterator_nth_back() {
let v: &[_] = &[0, 1, 2, 3, 4];
for i in 0..v.len() {
assert_eq!(v.iter().nth_back(i).unwrap(), &v[v.len() - 1 - i]);
}
assert_eq!(v.iter().nth_back(v.len()), None);
}
#[test]
fn test_iterator_rev_nth_back() {
let v: &[_] = &[0, 1, 2, 3, 4];
for i in 0..v.len() {
assert_eq!(v.iter().rev().nth_back(i).unwrap(), &v[i]);
}
assert_eq!(v.iter().rev().nth_back(v.len()), None);
}
#[test]
fn test_iterator_rev_nth() {
let v: &[_] = &[0, 1, 2, 3, 4];
for i in 0..v.len() {
assert_eq!(v.iter().rev().nth(i).unwrap(), &v[v.len() - 1 - i]);
}
assert_eq!(v.iter().rev().nth(v.len()), None);
}
#[test] #[test]
fn test_iterator_last() { fn test_iterator_last() {
let v: &[_] = &[0, 1, 2, 3, 4]; let v: &[_] = &[0, 1, 2, 3, 4];

View file

@ -19,6 +19,7 @@
#![feature(flt2dec)] #![feature(flt2dec)]
#![feature(fmt_internals)] #![feature(fmt_internals)]
#![feature(hashmap_internals)] #![feature(hashmap_internals)]
#![feature(iter_nth_back)]
#![feature(iter_unfold)] #![feature(iter_unfold)]
#![feature(pattern)] #![feature(pattern)]
#![feature(range_is_empty)] #![feature(range_is_empty)]

View file

@ -31,8 +31,8 @@ mod tests {
} }
#[test] #[test]
fn test_mod_euc() { fn test_rem_euclid() {
assert!((-1 as $T).mod_euc(MIN) == MAX); assert!((-1 as $T).rem_euclid(MIN) == MAX);
} }
#[test] #[test]

View file

@ -694,23 +694,23 @@ macro_rules! test_float {
assert!(($nan as $fty).max($nan).is_nan()); assert!(($nan as $fty).max($nan).is_nan());
} }
#[test] #[test]
fn mod_euc() { fn rem_euclid() {
let a: $fty = 42.0; let a: $fty = 42.0;
assert!($inf.mod_euc(a).is_nan()); assert!($inf.rem_euclid(a).is_nan());
assert_eq!(a.mod_euc($inf), a); assert_eq!(a.rem_euclid($inf), a);
assert!(a.mod_euc($nan).is_nan()); assert!(a.rem_euclid($nan).is_nan());
assert!($inf.mod_euc($inf).is_nan()); assert!($inf.rem_euclid($inf).is_nan());
assert!($inf.mod_euc($nan).is_nan()); assert!($inf.rem_euclid($nan).is_nan());
assert!($nan.mod_euc($inf).is_nan()); assert!($nan.rem_euclid($inf).is_nan());
} }
#[test] #[test]
fn div_euc() { fn div_euclid() {
let a: $fty = 42.0; let a: $fty = 42.0;
assert_eq!(a.div_euc($inf), 0.0); assert_eq!(a.div_euclid($inf), 0.0);
assert!(a.div_euc($nan).is_nan()); assert!(a.div_euclid($nan).is_nan());
assert!($inf.div_euc($inf).is_nan()); assert!($inf.div_euclid($inf).is_nan());
assert!($inf.div_euc($nan).is_nan()); assert!($inf.div_euclid($nan).is_nan());
assert!($nan.div_euc($inf).is_nan()); assert!($nan.div_euclid($inf).is_nan());
} }
} } } }
} }

View file

@ -62,7 +62,7 @@ cfg_if! {
if #[cfg(target_os = "emscripten")] { if #[cfg(target_os = "emscripten")] {
#[path = "emcc.rs"] #[path = "emcc.rs"]
mod imp; mod imp;
} else if #[cfg(any(target_arch = "wasm32", target_env = "sgx"))] { } else if #[cfg(target_arch = "wasm32")] {
#[path = "dummy.rs"] #[path = "dummy.rs"]
mod imp; mod imp;
} else if #[cfg(all(target_env = "msvc", target_arch = "aarch64"))] { } else if #[cfg(all(target_env = "msvc", target_arch = "aarch64"))] {

View file

@ -42,11 +42,12 @@ use util::nodemap::FxHashMap;
use std::default::Default as StdDefault; use std::default::Default as StdDefault;
use syntax::ast; use syntax::ast;
use syntax::edition; use syntax::edition;
use syntax_pos::{MultiSpan, Span, symbol::LocalInternedString}; use syntax_pos::{MultiSpan, Span, symbol::{LocalInternedString, Symbol}};
use errors::DiagnosticBuilder; use errors::DiagnosticBuilder;
use hir; use hir;
use hir::def_id::LOCAL_CRATE; use hir::def_id::LOCAL_CRATE;
use hir::intravisit as hir_visit; use hir::intravisit as hir_visit;
use syntax::util::lev_distance::find_best_match_for_name;
use syntax::visit as ast_visit; use syntax::visit as ast_visit;
/// Information about the registered lints. /// Information about the registered lints.
@ -139,8 +140,8 @@ struct LintGroup {
pub enum CheckLintNameResult<'a> { pub enum CheckLintNameResult<'a> {
Ok(&'a [LintId]), Ok(&'a [LintId]),
/// Lint doesn't exist /// Lint doesn't exist. Potentially contains a suggestion for a correct lint name.
NoLint, NoLint(Option<Symbol>),
/// The lint is either renamed or removed. This is the warning /// The lint is either renamed or removed. This is the warning
/// message, and an optional new name (`None` if removed). /// message, and an optional new name (`None` if removed).
Warning(String, Option<String>), Warning(String, Option<String>),
@ -359,8 +360,14 @@ impl LintStore {
CheckLintNameResult::Warning(ref msg, _) => { CheckLintNameResult::Warning(ref msg, _) => {
Some(sess.struct_warn(msg)) Some(sess.struct_warn(msg))
}, },
CheckLintNameResult::NoLint => { CheckLintNameResult::NoLint(suggestion) => {
Some(struct_err!(sess, E0602, "unknown lint: `{}`", lint_name)) let mut err = struct_err!(sess, E0602, "unknown lint: `{}`", lint_name);
if let Some(suggestion) = suggestion {
err.help(&format!("did you mean: `{}`", suggestion));
}
Some(err)
} }
CheckLintNameResult::Tool(result) => match result { CheckLintNameResult::Tool(result) => match result {
Err((Some(_), new_name)) => Some(sess.struct_warn(&format!( Err((Some(_), new_name)) => Some(sess.struct_warn(&format!(
@ -464,7 +471,16 @@ impl LintStore {
match self.by_name.get(&complete_name) { match self.by_name.get(&complete_name) {
None => match self.lint_groups.get(&*complete_name) { None => match self.lint_groups.get(&*complete_name) {
// Now we are sure, that this lint exists nowhere // Now we are sure, that this lint exists nowhere
None => CheckLintNameResult::NoLint, None => {
let symbols = self.by_name.keys()
.map(|name| Symbol::intern(&name))
.collect::<Vec<_>>();
let suggestion =
find_best_match_for_name(symbols.iter(), &lint_name.to_lowercase(), None);
CheckLintNameResult::NoLint(suggestion)
}
Some(LintGroup { lint_ids, depr, .. }) => { Some(LintGroup { lint_ids, depr, .. }) => {
// Reaching this would be weird, but let's cover this case anyway // Reaching this would be weird, but let's cover this case anyway
if let Some(LintAlias { name, silent }) = depr { if let Some(LintAlias { name, silent }) = depr {
@ -484,7 +500,7 @@ impl LintStore {
Some(&Id(ref id)) => { Some(&Id(ref id)) => {
CheckLintNameResult::Tool(Err((Some(slice::from_ref(id)), complete_name))) CheckLintNameResult::Tool(Err((Some(slice::from_ref(id)), complete_name)))
} }
_ => CheckLintNameResult::NoLint, _ => CheckLintNameResult::NoLint(None),
} }
} }
} }

View file

@ -385,7 +385,7 @@ impl<'a> LintLevelsBuilder<'a> {
} }
err.emit(); err.emit();
} }
CheckLintNameResult::NoLint => { CheckLintNameResult::NoLint(suggestion) => {
let lint = builtin::UNKNOWN_LINTS; let lint = builtin::UNKNOWN_LINTS;
let (level, src) = self.sets.get_lint_level(lint, let (level, src) = self.sets.get_lint_level(lint,
self.cur, self.cur,
@ -398,22 +398,17 @@ impl<'a> LintLevelsBuilder<'a> {
src, src,
Some(li.span.into()), Some(li.span.into()),
&msg); &msg);
if name.as_str().chars().any(|c| c.is_uppercase()) {
let name_lower = name.as_str().to_lowercase().to_string(); if let Some(suggestion) = suggestion {
if let CheckLintNameResult::NoLint = db.span_suggestion_with_applicability(
store.check_lint_name(&name_lower, tool_name) { li.span,
db.emit(); "did you mean",
} else { suggestion.to_string(),
db.span_suggestion_with_applicability( Applicability::MachineApplicable,
li.span, );
"lowercase the lint name",
name_lower,
Applicability::MachineApplicable
).emit();
}
} else {
db.emit();
} }
db.emit();
} }
} }
} }

View file

@ -55,8 +55,8 @@ impl<'cx, 'gcx, 'tcx> At<'cx, 'gcx, 'tcx> {
let c_ty = self.infcx.canonicalize_query(&self.param_env.and(ty), &mut orig_values); let c_ty = self.infcx.canonicalize_query(&self.param_env.and(ty), &mut orig_values);
let span = self.cause.span; let span = self.cause.span;
debug!("c_ty = {:?}", c_ty); debug!("c_ty = {:?}", c_ty);
match &gcx.dropck_outlives(c_ty) { if let Ok(result) = &gcx.dropck_outlives(c_ty) {
Ok(result) if result.is_proven() => { if result.is_proven() {
if let Ok(InferOk { value, obligations }) = if let Ok(InferOk { value, obligations }) =
self.infcx.instantiate_query_response_and_region_obligations( self.infcx.instantiate_query_response_and_region_obligations(
self.cause, self.cause,
@ -72,8 +72,6 @@ impl<'cx, 'gcx, 'tcx> At<'cx, 'gcx, 'tcx> {
}; };
} }
} }
_ => { /* fallthrough to error-handling code below */ }
} }
// Errors and ambiuity in dropck occur in two cases: // Errors and ambiuity in dropck occur in two cases:
@ -82,10 +80,11 @@ impl<'cx, 'gcx, 'tcx> At<'cx, 'gcx, 'tcx> {
// Either of these should have created an error before. // Either of these should have created an error before.
tcx.sess tcx.sess
.delay_span_bug(span, "dtorck encountered internal error"); .delay_span_bug(span, "dtorck encountered internal error");
return InferOk {
InferOk {
value: vec![], value: vec![],
obligations: vec![], obligations: vec![],
}; }
} }
} }
@ -102,7 +101,7 @@ impl<'tcx> DropckOutlivesResult<'tcx> {
span: Span, span: Span,
ty: Ty<'tcx>, ty: Ty<'tcx>,
) { ) {
for overflow_ty in self.overflows.iter().take(1) { if let Some(overflow_ty) = self.overflows.iter().next() {
let mut err = struct_span_err!( let mut err = struct_span_err!(
tcx.sess, tcx.sess,
span, span,
@ -228,7 +227,7 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'_, '_, 'tcx>, ty: Ty<'tcx>) ->
// (T1..Tn) and closures have same properties as T1..Tn -- // (T1..Tn) and closures have same properties as T1..Tn --
// check if *any* of those are trivial. // check if *any* of those are trivial.
ty::Tuple(ref tys) => tys.iter().cloned().all(|t| trivial_dropck_outlives(tcx, t)), ty::Tuple(ref tys) => tys.iter().all(|t| trivial_dropck_outlives(tcx, t)),
ty::Closure(def_id, ref substs) => substs ty::Closure(def_id, ref substs) => substs
.upvar_tys(def_id, tcx) .upvar_tys(def_id, tcx)
.all(|t| trivial_dropck_outlives(tcx, t)), .all(|t| trivial_dropck_outlives(tcx, t)),

View file

@ -1926,6 +1926,7 @@ pub mod tls {
/// to `value` during the call to `f`. It is restored to its previous value after. /// to `value` during the call to `f`. It is restored to its previous value after.
/// This is used to set the pointer to the new ImplicitCtxt. /// This is used to set the pointer to the new ImplicitCtxt.
#[cfg(parallel_queries)] #[cfg(parallel_queries)]
#[inline]
fn set_tlv<F: FnOnce() -> R, R>(value: usize, f: F) -> R { fn set_tlv<F: FnOnce() -> R, R>(value: usize, f: F) -> R {
rayon_core::tlv::with(value, f) rayon_core::tlv::with(value, f)
} }
@ -1933,6 +1934,7 @@ pub mod tls {
/// Gets Rayon's thread local variable which is preserved for Rayon jobs. /// Gets Rayon's thread local variable which is preserved for Rayon jobs.
/// This is used to get the pointer to the current ImplicitCtxt. /// This is used to get the pointer to the current ImplicitCtxt.
#[cfg(parallel_queries)] #[cfg(parallel_queries)]
#[inline]
fn get_tlv() -> usize { fn get_tlv() -> usize {
rayon_core::tlv::get() rayon_core::tlv::get()
} }
@ -1945,6 +1947,7 @@ pub mod tls {
/// It is restored to its previous value after. /// It is restored to its previous value after.
/// This is used to set the pointer to the new ImplicitCtxt. /// This is used to set the pointer to the new ImplicitCtxt.
#[cfg(not(parallel_queries))] #[cfg(not(parallel_queries))]
#[inline]
fn set_tlv<F: FnOnce() -> R, R>(value: usize, f: F) -> R { fn set_tlv<F: FnOnce() -> R, R>(value: usize, f: F) -> R {
let old = get_tlv(); let old = get_tlv();
let _reset = OnDrop(move || TLV.with(|tlv| tlv.set(old))); let _reset = OnDrop(move || TLV.with(|tlv| tlv.set(old)));
@ -2009,6 +2012,7 @@ pub mod tls {
} }
/// Sets `context` as the new current ImplicitCtxt for the duration of the function `f` /// Sets `context` as the new current ImplicitCtxt for the duration of the function `f`
#[inline]
pub fn enter_context<'a, 'gcx: 'tcx, 'tcx, F, R>(context: &ImplicitCtxt<'a, 'gcx, 'tcx>, pub fn enter_context<'a, 'gcx: 'tcx, 'tcx, F, R>(context: &ImplicitCtxt<'a, 'gcx, 'tcx>,
f: F) -> R f: F) -> R
where F: FnOnce(&ImplicitCtxt<'a, 'gcx, 'tcx>) -> R where F: FnOnce(&ImplicitCtxt<'a, 'gcx, 'tcx>) -> R
@ -2080,6 +2084,7 @@ pub mod tls {
} }
/// Allows access to the current ImplicitCtxt in a closure if one is available /// Allows access to the current ImplicitCtxt in a closure if one is available
#[inline]
pub fn with_context_opt<F, R>(f: F) -> R pub fn with_context_opt<F, R>(f: F) -> R
where F: for<'a, 'gcx, 'tcx> FnOnce(Option<&ImplicitCtxt<'a, 'gcx, 'tcx>>) -> R where F: for<'a, 'gcx, 'tcx> FnOnce(Option<&ImplicitCtxt<'a, 'gcx, 'tcx>>) -> R
{ {
@ -2097,6 +2102,7 @@ pub mod tls {
/// Allows access to the current ImplicitCtxt. /// Allows access to the current ImplicitCtxt.
/// Panics if there is no ImplicitCtxt available /// Panics if there is no ImplicitCtxt available
#[inline]
pub fn with_context<F, R>(f: F) -> R pub fn with_context<F, R>(f: F) -> R
where F: for<'a, 'gcx, 'tcx> FnOnce(&ImplicitCtxt<'a, 'gcx, 'tcx>) -> R where F: for<'a, 'gcx, 'tcx> FnOnce(&ImplicitCtxt<'a, 'gcx, 'tcx>) -> R
{ {
@ -2108,6 +2114,7 @@ pub mod tls {
/// with the same 'gcx lifetime as the TyCtxt passed in. /// with the same 'gcx lifetime as the TyCtxt passed in.
/// This will panic if you pass it a TyCtxt which has a different global interner from /// This will panic if you pass it a TyCtxt which has a different global interner from
/// the current ImplicitCtxt's tcx field. /// the current ImplicitCtxt's tcx field.
#[inline]
pub fn with_related_context<'a, 'gcx, 'tcx1, F, R>(tcx: TyCtxt<'a, 'gcx, 'tcx1>, f: F) -> R pub fn with_related_context<'a, 'gcx, 'tcx1, F, R>(tcx: TyCtxt<'a, 'gcx, 'tcx1>, f: F) -> R
where F: for<'b, 'tcx2> FnOnce(&ImplicitCtxt<'b, 'gcx, 'tcx2>) -> R where F: for<'b, 'tcx2> FnOnce(&ImplicitCtxt<'b, 'gcx, 'tcx2>) -> R
{ {
@ -2126,6 +2133,7 @@ pub mod tls {
/// is given an ImplicitCtxt with the same 'tcx and 'gcx lifetimes as the TyCtxt passed in. /// is given an ImplicitCtxt with the same 'tcx and 'gcx lifetimes as the TyCtxt passed in.
/// This will panic if you pass it a TyCtxt which has a different global interner or /// This will panic if you pass it a TyCtxt which has a different global interner or
/// a different local interner from the current ImplicitCtxt's tcx field. /// a different local interner from the current ImplicitCtxt's tcx field.
#[inline]
pub fn with_fully_related_context<'a, 'gcx, 'tcx, F, R>(tcx: TyCtxt<'a, 'gcx, 'tcx>, f: F) -> R pub fn with_fully_related_context<'a, 'gcx, 'tcx, F, R>(tcx: TyCtxt<'a, 'gcx, 'tcx>, f: F) -> R
where F: for<'b> FnOnce(&ImplicitCtxt<'b, 'gcx, 'tcx>) -> R where F: for<'b> FnOnce(&ImplicitCtxt<'b, 'gcx, 'tcx>) -> R
{ {
@ -2143,6 +2151,7 @@ pub mod tls {
/// Allows access to the TyCtxt in the current ImplicitCtxt. /// Allows access to the TyCtxt in the current ImplicitCtxt.
/// Panics if there is no ImplicitCtxt available /// Panics if there is no ImplicitCtxt available
#[inline]
pub fn with<F, R>(f: F) -> R pub fn with<F, R>(f: F) -> R
where F: for<'a, 'gcx, 'tcx> FnOnce(TyCtxt<'a, 'gcx, 'tcx>) -> R where F: for<'a, 'gcx, 'tcx> FnOnce(TyCtxt<'a, 'gcx, 'tcx>) -> R
{ {
@ -2151,6 +2160,7 @@ pub mod tls {
/// Allows access to the TyCtxt in the current ImplicitCtxt. /// Allows access to the TyCtxt in the current ImplicitCtxt.
/// The closure is passed None if there is no ImplicitCtxt available /// The closure is passed None if there is no ImplicitCtxt available
#[inline]
pub fn with_opt<F, R>(f: F) -> R pub fn with_opt<F, R>(f: F) -> R
where F: for<'a, 'gcx, 'tcx> FnOnce(Option<TyCtxt<'a, 'gcx, 'tcx>>) -> R where F: for<'a, 'gcx, 'tcx> FnOnce(Option<TyCtxt<'a, 'gcx, 'tcx>>) -> R
{ {

View file

@ -136,11 +136,14 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> {
Entry::Vacant(entry) => { Entry::Vacant(entry) => {
// No job entry for this query. Return a new one to be started later // No job entry for this query. Return a new one to be started later
return tls::with_related_context(tcx, |icx| { return tls::with_related_context(tcx, |icx| {
// Create the `parent` variable before `info`. This allows LLVM
// to elide the move of `info`
let parent = icx.query.clone();
let info = QueryInfo { let info = QueryInfo {
span, span,
query: Q::query(key.clone()), query: Q::query(key.clone()),
}; };
let job = Lrc::new(QueryJob::new(info, icx.query.clone())); let job = Lrc::new(QueryJob::new(info, parent));
let owner = JobOwner { let owner = JobOwner {
cache, cache,
job: job.clone(), job: job.clone(),
@ -171,6 +174,7 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> {
/// Completes the query by updating the query cache with the `result`, /// Completes the query by updating the query cache with the `result`,
/// signals the waiter and forgets the JobOwner, so it won't poison the query /// signals the waiter and forgets the JobOwner, so it won't poison the query
#[inline(always)]
pub(super) fn complete(self, result: &Q::Value, dep_node_index: DepNodeIndex) { pub(super) fn complete(self, result: &Q::Value, dep_node_index: DepNodeIndex) {
// We can move out of `self` here because we `mem::forget` it below // We can move out of `self` here because we `mem::forget` it below
let key = unsafe { ptr::read(&self.key) }; let key = unsafe { ptr::read(&self.key) };
@ -227,6 +231,8 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> {
} }
impl<'a, 'tcx, Q: QueryDescription<'tcx>> Drop for JobOwner<'a, 'tcx, Q> { impl<'a, 'tcx, Q: QueryDescription<'tcx>> Drop for JobOwner<'a, 'tcx, Q> {
#[inline(never)]
#[cold]
fn drop(&mut self) { fn drop(&mut self) {
// Poison the query so jobs waiting on it panic // Poison the query so jobs waiting on it panic
self.cache.borrow_mut().active.insert(self.key.clone(), QueryResult::Poisoned); self.cache.borrow_mut().active.insert(self.key.clone(), QueryResult::Poisoned);

View file

@ -28,7 +28,6 @@
#![feature(optin_builtin_traits)] #![feature(optin_builtin_traits)]
#![feature(nll)] #![feature(nll)]
#![feature(allow_internal_unstable)] #![feature(allow_internal_unstable)]
#![feature(vec_resize_with)]
#![feature(hash_raw_entry)] #![feature(hash_raw_entry)]
#![feature(stmt_expr_attributes)] #![feature(stmt_expr_attributes)]
#![feature(core_intrinsics)] #![feature(core_intrinsics)]
@ -113,12 +112,14 @@ pub struct OnDrop<F: Fn()>(pub F);
impl<F: Fn()> OnDrop<F> { impl<F: Fn()> OnDrop<F> {
/// Forgets the function which prevents it from running. /// Forgets the function which prevents it from running.
/// Ensure that the function owns no memory, otherwise it will be leaked. /// Ensure that the function owns no memory, otherwise it will be leaked.
#[inline]
pub fn disable(self) { pub fn disable(self) {
std::mem::forget(self); std::mem::forget(self);
} }
} }
impl<F: Fn()> Drop for OnDrop<F> { impl<F: Fn()> Drop for OnDrop<F> {
#[inline]
fn drop(&mut self) { fn drop(&mut self) {
(self.0)(); (self.0)();
} }

View file

@ -373,10 +373,14 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
for err in &mut mbcx.errors_buffer { for err in &mut mbcx.errors_buffer {
if err.is_error() { if err.is_error() {
err.level = Level::Warning; err.level = Level::Warning;
err.warn("This error has been downgraded to a warning \ err.warn(
for backwards compatibility with previous releases.\n\ "this error has been downgraded to a warning for backwards \
It represents potential unsoundness in your code.\n\ compatibility with previous releases",
This warning will become a hard error in the future."); );
err.warn(
"this represents potential undefined behavior in your code and \
this warning will become a hard error in the future",
);
} }
} }
} }

View file

@ -187,7 +187,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
} }
let layout = ecx.layout_of(mir.return_ty().subst(tcx, cid.instance.substs))?; let layout = ecx.layout_of(mir.return_ty().subst(tcx, cid.instance.substs))?;
assert!(!layout.is_unsized()); assert!(!layout.is_unsized());
let ret = ecx.allocate(layout, MemoryKind::Stack)?; let ret = ecx.allocate(layout, MemoryKind::Stack);
let name = ty::tls::with(|tcx| tcx.item_path_str(cid.instance.def_id())); let name = ty::tls::with(|tcx| tcx.item_path_str(cid.instance.def_id()));
let prom = cid.promoted.map_or(String::new(), |p| format!("::promoted[{:?}]", p)); let prom = cid.promoted.map_or(String::new(), |p| format!("::promoted[{:?}]", p));
@ -490,8 +490,8 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx>
_ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, _ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
ptr: Pointer, ptr: Pointer,
_kind: MemoryKind<Self::MemoryKinds>, _kind: MemoryKind<Self::MemoryKinds>,
) -> EvalResult<'tcx, Pointer> { ) -> Pointer {
Ok(ptr) ptr
} }
#[inline(always)] #[inline(always)]
@ -692,12 +692,16 @@ pub fn const_eval_raw_provider<'a, 'tcx>(
let err = error_to_const_error(&ecx, error); let err = error_to_const_error(&ecx, error);
// errors in statics are always emitted as fatal errors // errors in statics are always emitted as fatal errors
if tcx.is_static(def_id).is_some() { if tcx.is_static(def_id).is_some() {
let err = err.report_as_error(ecx.tcx, "could not evaluate static initializer"); let reported_err = err.report_as_error(ecx.tcx,
// check that a static never produces `TooGeneric` "could not evaluate static initializer");
// Ensure that if the above error was either `TooGeneric` or `Reported`
// an error must be reported.
if tcx.sess.err_count() == 0 { if tcx.sess.err_count() == 0 {
span_bug!(ecx.tcx.span, "static eval failure didn't emit an error: {:#?}", err); tcx.sess.delay_span_bug(err.span,
&format!("static eval failure did not emit an error: {:#?}",
reported_err));
} }
err reported_err
} else if def_id.is_local() { } else if def_id.is_local() {
// constant defined in this crate, we can figure out a lint level! // constant defined in this crate, we can figure out a lint level!
match tcx.describe_def(def_id) { match tcx.describe_def(def_id) {

View file

@ -422,7 +422,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
return_to_block: StackPopCleanup, return_to_block: StackPopCleanup,
) -> EvalResult<'tcx> { ) -> EvalResult<'tcx> {
if self.stack.len() > 1 { // FIXME should be "> 0", printing topmost frame crashes rustc... if self.stack.len() > 1 { // FIXME should be "> 0", printing topmost frame crashes rustc...
debug!("PAUSING({}) {}", self.cur_frame(), self.frame().instance); info!("PAUSING({}) {}", self.cur_frame(), self.frame().instance);
} }
::log_settings::settings().indentation += 1; ::log_settings::settings().indentation += 1;
@ -491,7 +491,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
} }
if self.stack.len() > 1 { // FIXME no check should be needed, but some instances ICE if self.stack.len() > 1 { // FIXME no check should be needed, but some instances ICE
debug!("ENTERING({}) {}", self.cur_frame(), self.frame().instance); info!("ENTERING({}) {}", self.cur_frame(), self.frame().instance);
} }
if self.stack.len() > self.tcx.sess.const_eval_stack_frame_limit { if self.stack.len() > self.tcx.sess.const_eval_stack_frame_limit {
@ -503,7 +503,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
pub(super) fn pop_stack_frame(&mut self) -> EvalResult<'tcx> { pub(super) fn pop_stack_frame(&mut self) -> EvalResult<'tcx> {
if self.stack.len() > 1 { // FIXME no check should be needed, but some instances ICE if self.stack.len() > 1 { // FIXME no check should be needed, but some instances ICE
debug!("LEAVING({}) {}", self.cur_frame(), self.frame().instance); info!("LEAVING({}) {}", self.cur_frame(), self.frame().instance);
} }
::log_settings::settings().indentation -= 1; ::log_settings::settings().indentation -= 1;
let frame = self.stack.pop().expect( let frame = self.stack.pop().expect(
@ -557,7 +557,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
} }
if self.stack.len() > 1 { // FIXME should be "> 0", printing topmost frame crashes rustc... if self.stack.len() > 1 { // FIXME should be "> 0", printing topmost frame crashes rustc...
debug!("CONTINUING({}) {}", self.cur_frame(), self.frame().instance); info!("CONTINUING({}) {}", self.cur_frame(), self.frame().instance);
} }
Ok(()) Ok(())

View file

@ -185,7 +185,7 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
ptr: Pointer, ptr: Pointer,
kind: MemoryKind<Self::MemoryKinds>, kind: MemoryKind<Self::MemoryKinds>,
) -> EvalResult<'tcx, Pointer<Self::PointerTag>>; ) -> Pointer<Self::PointerTag>;
/// Executed when evaluating the `*` operator: Following a reference. /// Executed when evaluating the `*` operator: Following a reference.
/// This has the chance to adjust the tag. It should not change anything else! /// This has the chance to adjust the tag. It should not change anything else!

View file

@ -131,10 +131,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
&mut self, &mut self,
alloc: Allocation<M::PointerTag, M::AllocExtra>, alloc: Allocation<M::PointerTag, M::AllocExtra>,
kind: MemoryKind<M::MemoryKinds>, kind: MemoryKind<M::MemoryKinds>,
) -> EvalResult<'tcx, AllocId> { ) -> AllocId {
let id = self.tcx.alloc_map.lock().reserve(); let id = self.tcx.alloc_map.lock().reserve();
self.alloc_map.insert(id, (kind, alloc)); self.alloc_map.insert(id, (kind, alloc));
Ok(id) id
} }
pub fn allocate( pub fn allocate(
@ -142,9 +142,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
size: Size, size: Size,
align: Align, align: Align,
kind: MemoryKind<M::MemoryKinds>, kind: MemoryKind<M::MemoryKinds>,
) -> EvalResult<'tcx, Pointer> { ) -> Pointer {
let extra = AllocationExtra::memory_allocated(size, &self.extra); let extra = AllocationExtra::memory_allocated(size, &self.extra);
Ok(Pointer::from(self.allocate_with(Allocation::undef(size, align, extra), kind)?)) Pointer::from(self.allocate_with(Allocation::undef(size, align, extra), kind))
} }
pub fn reallocate( pub fn reallocate(
@ -162,7 +162,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
// For simplicities' sake, we implement reallocate as "alloc, copy, dealloc". // For simplicities' sake, we implement reallocate as "alloc, copy, dealloc".
// This happens so rarely, the perf advantage is outweighed by the maintenance cost. // This happens so rarely, the perf advantage is outweighed by the maintenance cost.
let new_ptr = self.allocate(new_size, new_align, kind)?; let new_ptr = self.allocate(new_size, new_align, kind);
self.copy( self.copy(
ptr.into(), ptr.into(),
old_align, old_align,
@ -708,8 +708,13 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
relocations relocations
.iter() .iter()
.map(|&(offset, reloc)| { .map(|&(offset, reloc)| {
(offset + dest.offset - src.offset + (i * size * relocations.len() as u64), // compute offset for current repetition
reloc) let dest_offset = dest.offset + (i * size);
(
// shift offsets from source allocation to destination allocation
offset + dest_offset - src.offset,
reloc,
)
}) })
); );
} }

View file

@ -382,7 +382,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
_ => { _ => {
trace!("Forcing allocation for local of type {:?}", layout.ty); trace!("Forcing allocation for local of type {:?}", layout.ty);
Operand::Indirect( Operand::Indirect(
*self.allocate(layout, MemoryKind::Stack)? *self.allocate(layout, MemoryKind::Stack)
) )
} }
}) })

View file

@ -911,7 +911,7 @@ where
// that might e.g., be an inner field of a struct with `Scalar` layout, // that might e.g., be an inner field of a struct with `Scalar` layout,
// that has different alignment than the outer field. // that has different alignment than the outer field.
let local_layout = self.layout_of_local(&self.stack[frame], local)?; let local_layout = self.layout_of_local(&self.stack[frame], local)?;
let ptr = self.allocate(local_layout, MemoryKind::Stack)?; let ptr = self.allocate(local_layout, MemoryKind::Stack);
// We don't have to validate as we can assume the local // We don't have to validate as we can assume the local
// was already valid for its type. // was already valid for its type.
self.write_immediate_to_mplace_no_validate(value, ptr)?; self.write_immediate_to_mplace_no_validate(value, ptr)?;
@ -933,15 +933,15 @@ where
&mut self, &mut self,
layout: TyLayout<'tcx>, layout: TyLayout<'tcx>,
kind: MemoryKind<M::MemoryKinds>, kind: MemoryKind<M::MemoryKinds>,
) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { ) -> MPlaceTy<'tcx, M::PointerTag> {
if layout.is_unsized() { if layout.is_unsized() {
assert!(self.tcx.features().unsized_locals, "cannot alloc memory for unsized type"); assert!(self.tcx.features().unsized_locals, "cannot alloc memory for unsized type");
// FIXME: What should we do here? We should definitely also tag! // FIXME: What should we do here? We should definitely also tag!
Ok(MPlaceTy::dangling(layout, self)) MPlaceTy::dangling(layout, self)
} else { } else {
let ptr = self.memory.allocate(layout.size, layout.align.abi, kind)?; let ptr = self.memory.allocate(layout.size, layout.align.abi, kind);
let ptr = M::tag_new_allocation(self, ptr, kind)?; let ptr = M::tag_new_allocation(self, ptr, kind);
Ok(MPlaceTy::from_aligned_ptr(ptr, layout)) MPlaceTy::from_aligned_ptr(ptr, layout)
} }
} }

View file

@ -81,7 +81,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
} }
fn statement(&mut self, stmt: &mir::Statement<'tcx>) -> EvalResult<'tcx> { fn statement(&mut self, stmt: &mir::Statement<'tcx>) -> EvalResult<'tcx> {
debug!("{:?}", stmt); info!("{:?}", stmt);
use rustc::mir::StatementKind::*; use rustc::mir::StatementKind::*;
@ -289,7 +289,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
} }
fn terminator(&mut self, terminator: &mir::Terminator<'tcx>) -> EvalResult<'tcx> { fn terminator(&mut self, terminator: &mir::Terminator<'tcx>) -> EvalResult<'tcx> {
debug!("{:?}", terminator.kind); info!("{:?}", terminator.kind);
self.tcx.span = terminator.source_info.span; self.tcx.span = terminator.source_info.span;
self.memory.tcx.span = terminator.source_info.span; self.memory.tcx.span = terminator.source_info.span;
@ -299,7 +299,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
if !self.stack.is_empty() { if !self.stack.is_empty() {
// This should change *something* // This should change *something*
debug_assert!(self.cur_frame() != old_stack || self.frame().block != old_bb); debug_assert!(self.cur_frame() != old_stack || self.frame().block != old_bb);
debug!("// {:?}", self.frame().block); info!("// {:?}", self.frame().block);
} }
Ok(()) Ok(())
} }

View file

@ -54,7 +54,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
ptr_size * (3 + methods.len() as u64), ptr_size * (3 + methods.len() as u64),
ptr_align, ptr_align,
MemoryKind::Vtable, MemoryKind::Vtable,
)?.with_default_tag(); ).with_default_tag();
let tcx = &*self.tcx; let tcx = &*self.tcx;
let drop = ::monomorphize::resolve_drop_in_place(*tcx, ty); let drop = ::monomorphize::resolve_drop_in_place(*tcx, ty);

View file

@ -346,7 +346,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
Rvalue::Cast(kind, ref operand, _) => { Rvalue::Cast(kind, ref operand, _) => {
let (op, span) = self.eval_operand(operand, source_info)?; let (op, span) = self.eval_operand(operand, source_info)?;
self.use_ecx(source_info, |this| { self.use_ecx(source_info, |this| {
let dest = this.ecx.allocate(place_layout, MemoryKind::Stack)?; let dest = this.ecx.allocate(place_layout, MemoryKind::Stack);
this.ecx.cast(op, kind, dest.into())?; this.ecx.cast(op, kind, dest.into())?;
Ok((dest.into(), span)) Ok((dest.into(), span))
}) })

View file

@ -10,28 +10,29 @@
use std::iter; use std::iter;
use super::{LinkerFlavor, Target, TargetOptions, PanicStrategy}; use super::{LinkerFlavor, PanicStrategy, Target, TargetOptions};
pub fn target() -> Result<Target, String> { pub fn target() -> Result<Target, String> {
const PRE_LINK_ARGS: &[&str] = &[ const PRE_LINK_ARGS: &[&str] = &[
"-Wl,--as-needed", "-Wl,--as-needed",
"-Wl,-z,noexecstack", "-Wl,-z,noexecstack",
"-m64", "-m64",
"-fuse-ld=gold", "-fuse-ld=gold",
"-nostdlib", "-nostdlib",
"-shared", "-shared",
"-Wl,-e,sgx_entry", "-Wl,-e,sgx_entry",
"-Wl,-Bstatic", "-Wl,-Bstatic",
"-Wl,--gc-sections", "-Wl,--gc-sections",
"-Wl,-z,text", "-Wl,-z,text",
"-Wl,-z,norelro", "-Wl,-z,norelro",
"-Wl,--rosegment", "-Wl,--rosegment",
"-Wl,--no-undefined", "-Wl,--no-undefined",
"-Wl,--error-unresolved-symbols", "-Wl,--error-unresolved-symbols",
"-Wl,--no-undefined-version", "-Wl,--no-undefined-version",
"-Wl,-Bsymbolic", "-Wl,-Bsymbolic",
"-Wl,--export-dynamic", "-Wl,--export-dynamic",
]; ];
const EXPORT_SYMBOLS: &[&str] = &[ const EXPORT_SYMBOLS: &[&str] = &[
"sgx_entry", "sgx_entry",
"HEAP_BASE", "HEAP_BASE",
@ -41,19 +42,26 @@ pub fn target() -> Result<Target, String> {
"ENCLAVE_SIZE", "ENCLAVE_SIZE",
"CFGDATA_BASE", "CFGDATA_BASE",
"DEBUG", "DEBUG",
"EH_FRM_HDR_BASE",
"EH_FRM_HDR_SIZE",
"TEXT_BASE",
"TEXT_SIZE",
]; ];
let opts = TargetOptions { let opts = TargetOptions {
dynamic_linking: false, dynamic_linking: false,
executables: true, executables: true,
linker_is_gnu: true, linker_is_gnu: true,
max_atomic_width: Some(64), max_atomic_width: Some(64),
panic_strategy: PanicStrategy::Abort, panic_strategy: PanicStrategy::Unwind,
cpu: "x86-64".into(), cpu: "x86-64".into(),
features: "+rdrnd,+rdseed".into(), features: "+rdrnd,+rdseed".into(),
position_independent_executables: true, position_independent_executables: true,
pre_link_args: iter::once( pre_link_args: iter::once((
(LinkerFlavor::Gcc, PRE_LINK_ARGS.iter().cloned().map(String::from).collect()) LinkerFlavor::Gcc,
).collect(), PRE_LINK_ARGS.iter().cloned().map(String::from).collect(),
))
.collect(),
post_link_objects: vec!["libunwind.a".into()],
override_export_symbols: Some(EXPORT_SYMBOLS.iter().cloned().map(String::from).collect()), override_export_symbols: Some(EXPORT_SYMBOLS.iter().cloned().map(String::from).collect()),
..Default::default() ..Default::default()
}; };

View file

@ -181,6 +181,9 @@ pub struct RenderOptions {
/// A file to use as the index page at the root of the output directory. Overrides /// A file to use as the index page at the root of the output directory. Overrides
/// `enable_index_page` to be true if set. /// `enable_index_page` to be true if set.
pub index_page: Option<PathBuf>, pub index_page: Option<PathBuf>,
/// An optional path to use as the location of static files. If not set, uses combinations of
/// `../` to reach the documentation root.
pub static_root_path: Option<String>,
// Options specific to reading standalone Markdown files // Options specific to reading standalone Markdown files
@ -433,6 +436,7 @@ impl Options {
let markdown_playground_url = matches.opt_str("markdown-playground-url"); let markdown_playground_url = matches.opt_str("markdown-playground-url");
let crate_version = matches.opt_str("crate-version"); let crate_version = matches.opt_str("crate-version");
let enable_index_page = matches.opt_present("enable-index-page") || index_page.is_some(); let enable_index_page = matches.opt_present("enable-index-page") || index_page.is_some();
let static_root_path = matches.opt_str("static-root-path");
let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format); let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format);
@ -471,6 +475,7 @@ impl Options {
enable_minification, enable_minification,
enable_index_page, enable_index_page,
index_page, index_page,
static_root_path,
markdown_no_toc, markdown_no_toc,
markdown_css, markdown_css,
markdown_playground_url, markdown_playground_url,

View file

@ -26,16 +26,20 @@ pub struct Page<'a> {
pub title: &'a str, pub title: &'a str,
pub css_class: &'a str, pub css_class: &'a str,
pub root_path: &'a str, pub root_path: &'a str,
pub static_root_path: Option<&'a str>,
pub description: &'a str, pub description: &'a str,
pub keywords: &'a str, pub keywords: &'a str,
pub resource_suffix: &'a str, pub resource_suffix: &'a str,
pub extra_scripts: &'a [&'a str],
pub static_extra_scripts: &'a [&'a str],
} }
pub fn render<T: fmt::Display, S: fmt::Display>( pub fn render<T: fmt::Display, S: fmt::Display>(
dst: &mut dyn io::Write, layout: &Layout, page: &Page, sidebar: &S, t: &T, dst: &mut dyn io::Write, layout: &Layout, page: &Page, sidebar: &S, t: &T,
css_file_extension: bool, themes: &[PathBuf], extra_scripts: &[&str]) css_file_extension: bool, themes: &[PathBuf])
-> io::Result<()> -> io::Result<()>
{ {
let static_root_path = page.static_root_path.unwrap_or(page.root_path);
write!(dst, write!(dst,
"<!DOCTYPE html>\ "<!DOCTYPE html>\
<html lang=\"en\">\ <html lang=\"en\">\
@ -46,20 +50,20 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
<meta name=\"description\" content=\"{description}\">\ <meta name=\"description\" content=\"{description}\">\
<meta name=\"keywords\" content=\"{keywords}\">\ <meta name=\"keywords\" content=\"{keywords}\">\
<title>{title}</title>\ <title>{title}</title>\
<link rel=\"stylesheet\" type=\"text/css\" href=\"{root_path}normalize{suffix}.css\">\ <link rel=\"stylesheet\" type=\"text/css\" href=\"{static_root_path}normalize{suffix}.css\">\
<link rel=\"stylesheet\" type=\"text/css\" href=\"{root_path}rustdoc{suffix}.css\" \ <link rel=\"stylesheet\" type=\"text/css\" href=\"{static_root_path}rustdoc{suffix}.css\" \
id=\"mainThemeStyle\">\ id=\"mainThemeStyle\">\
{themes}\ {themes}\
<link rel=\"stylesheet\" type=\"text/css\" href=\"{root_path}dark{suffix}.css\">\ <link rel=\"stylesheet\" type=\"text/css\" href=\"{static_root_path}dark{suffix}.css\">\
<link rel=\"stylesheet\" type=\"text/css\" href=\"{root_path}light{suffix}.css\" \ <link rel=\"stylesheet\" type=\"text/css\" href=\"{static_root_path}light{suffix}.css\" \
id=\"themeStyle\">\ id=\"themeStyle\">\
<script src=\"{root_path}storage{suffix}.js\"></script>\ <script src=\"{static_root_path}storage{suffix}.js\"></script>\
<noscript><link rel=\"stylesheet\" href=\"{root_path}noscript{suffix}.css\"></noscript>\ <noscript><link rel=\"stylesheet\" href=\"{static_root_path}noscript{suffix}.css\"></noscript>\
{css_extension}\ {css_extension}\
{favicon}\ {favicon}\
{in_header}\ {in_header}\
<style type=\"text/css\">\ <style type=\"text/css\">\
#crate-search{{background-image:url(\"{root_path}down-arrow{suffix}.svg\");}}\ #crate-search{{background-image:url(\"{static_root_path}down-arrow{suffix}.svg\");}}\
</style>\ </style>\
</head>\ </head>\
<body class=\"rustdoc {css_class}\">\ <body class=\"rustdoc {css_class}\">\
@ -77,11 +81,13 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
</nav>\ </nav>\
<div class=\"theme-picker\">\ <div class=\"theme-picker\">\
<button id=\"theme-picker\" aria-label=\"Pick another theme!\">\ <button id=\"theme-picker\" aria-label=\"Pick another theme!\">\
<img src=\"{root_path}brush{suffix}.svg\" width=\"18\" alt=\"Pick another theme!\">\ <img src=\"{static_root_path}brush{suffix}.svg\" \
width=\"18\" \
alt=\"Pick another theme!\">\
</button>\ </button>\
<div id=\"theme-choices\"></div>\ <div id=\"theme-choices\"></div>\
</div>\ </div>\
<script src=\"{root_path}theme{suffix}.js\"></script>\ <script src=\"{static_root_path}theme{suffix}.js\"></script>\
<nav class=\"sub\">\ <nav class=\"sub\">\
<form class=\"search-form js-only\">\ <form class=\"search-form js-only\">\
<div class=\"search-container\">\ <div class=\"search-container\">\
@ -96,7 +102,9 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
type=\"search\">\ type=\"search\">\
</div>\ </div>\
<a id=\"settings-menu\" href=\"{root_path}settings.html\">\ <a id=\"settings-menu\" href=\"{root_path}settings.html\">\
<img src=\"{root_path}wheel{suffix}.svg\" width=\"18\" alt=\"Change settings\">\ <img src=\"{static_root_path}wheel{suffix}.svg\" \
width=\"18\" \
alt=\"Change settings\">\
</a>\ </a>\
</div>\ </div>\
</form>\ </form>\
@ -157,19 +165,23 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
window.currentCrate = \"{krate}\";\ window.currentCrate = \"{krate}\";\
</script>\ </script>\
<script src=\"{root_path}aliases.js\"></script>\ <script src=\"{root_path}aliases.js\"></script>\
<script src=\"{root_path}main{suffix}.js\"></script>\ <script src=\"{static_root_path}main{suffix}.js\"></script>\
{static_extra_scripts}\
{extra_scripts}\ {extra_scripts}\
<script defer src=\"{root_path}search-index.js\"></script>\ <script defer src=\"{root_path}search-index.js\"></script>\
</body>\ </body>\
</html>", </html>",
css_extension = if css_file_extension { css_extension = if css_file_extension {
format!("<link rel=\"stylesheet\" type=\"text/css\" href=\"{root_path}theme{suffix}.css\">", format!("<link rel=\"stylesheet\" \
root_path = page.root_path, type=\"text/css\" \
href=\"{static_root_path}theme{suffix}.css\">",
static_root_path = static_root_path,
suffix=page.resource_suffix) suffix=page.resource_suffix)
} else { } else {
String::new() String::new()
}, },
content = *t, content = *t,
static_root_path = static_root_path,
root_path = page.root_path, root_path = page.root_path,
css_class = page.css_class, css_class = page.css_class,
logo = if layout.logo.is_empty() { logo = if layout.logo.is_empty() {
@ -197,12 +209,17 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
.filter_map(|t| t.file_stem()) .filter_map(|t| t.file_stem())
.filter_map(|t| t.to_str()) .filter_map(|t| t.to_str())
.map(|t| format!(r#"<link rel="stylesheet" type="text/css" href="{}{}{}.css">"#, .map(|t| format!(r#"<link rel="stylesheet" type="text/css" href="{}{}{}.css">"#,
page.root_path, static_root_path,
t, t,
page.resource_suffix)) page.resource_suffix))
.collect::<String>(), .collect::<String>(),
suffix=page.resource_suffix, suffix=page.resource_suffix,
extra_scripts=extra_scripts.iter().map(|e| { static_extra_scripts=page.static_extra_scripts.iter().map(|e| {
format!("<script src=\"{static_root_path}{extra_script}.js\"></script>",
static_root_path=static_root_path,
extra_script=e)
}).collect::<String>(),
extra_scripts=page.extra_scripts.iter().map(|e| {
format!("<script src=\"{root_path}{extra_script}.js\"></script>", format!("<script src=\"{root_path}{extra_script}.js\"></script>",
root_path=page.root_path, root_path=page.root_path,
extra_script=e) extra_script=e)

View file

@ -140,6 +140,9 @@ struct SharedContext {
/// Suffix to be added on resource files (if suffix is "-v2" then "light.css" becomes /// Suffix to be added on resource files (if suffix is "-v2" then "light.css" becomes
/// "light-v2.css"). /// "light-v2.css").
pub resource_suffix: String, pub resource_suffix: String,
/// Optional path string to be used to load static files on output pages. If not set, uses
/// combinations of `../` to reach the documentation root.
pub static_root_path: Option<String>,
} }
impl SharedContext { impl SharedContext {
@ -506,6 +509,7 @@ pub fn run(mut krate: clean::Crate,
extension_css, extension_css,
extern_html_root_urls, extern_html_root_urls,
resource_suffix, resource_suffix,
static_root_path,
.. ..
} = options; } = options;
@ -533,6 +537,7 @@ pub fn run(mut krate: clean::Crate,
sort_modules_alphabetically, sort_modules_alphabetically,
themes, themes,
resource_suffix, resource_suffix,
static_root_path,
}; };
// If user passed in `--playground-url` arg, we fill in crate name here // If user passed in `--playground-url` arg, we fill in crate name here
@ -964,7 +969,7 @@ themePicker.onblur = handleThemeButtonsBlur;
.collect::<Vec<_>>() .collect::<Vec<_>>()
.join(","))); .join(",")));
} }
all_aliases.push(format!("ALIASES['{}'] = {{{}}};", krate.name, output)); all_aliases.push(format!("ALIASES[\"{}\"] = {{{}}};", krate.name, output));
all_aliases.sort(); all_aliases.sort();
try_err!(writeln!(&mut w, "var ALIASES = {{}};"), &dst); try_err!(writeln!(&mut w, "var ALIASES = {{}};"), &dst);
for aliases in &all_aliases { for aliases in &all_aliases {
@ -1038,7 +1043,7 @@ themePicker.onblur = handleThemeButtonsBlur;
let dst = cx.dst.join("source-files.js"); let dst = cx.dst.join("source-files.js");
let (mut all_sources, _krates) = try_err!(collect(&dst, &krate.name, "sourcesIndex"), &dst); let (mut all_sources, _krates) = try_err!(collect(&dst, &krate.name, "sourcesIndex"), &dst);
all_sources.push(format!("sourcesIndex['{}'] = {};", all_sources.push(format!("sourcesIndex[\"{}\"] = {};",
&krate.name, &krate.name,
hierarchy.to_json_string())); hierarchy.to_json_string()));
all_sources.sort(); all_sources.sort();
@ -1080,9 +1085,12 @@ themePicker.onblur = handleThemeButtonsBlur;
title: "Index of crates", title: "Index of crates",
css_class: "mod", css_class: "mod",
root_path: "./", root_path: "./",
static_root_path: cx.shared.static_root_path.deref(),
description: "List of crates", description: "List of crates",
keywords: BASIC_KEYWORDS, keywords: BASIC_KEYWORDS,
resource_suffix: &cx.shared.resource_suffix, resource_suffix: &cx.shared.resource_suffix,
extra_scripts: &[],
static_extra_scripts: &[],
}; };
krates.push(krate.name.clone()); krates.push(krate.name.clone());
krates.sort(); krates.sort();
@ -1101,7 +1109,7 @@ themePicker.onblur = handleThemeButtonsBlur;
try_err!(layout::render(&mut w, &cx.shared.layout, try_err!(layout::render(&mut w, &cx.shared.layout,
&page, &(""), &content, &page, &(""), &content,
cx.shared.css_file_extension.is_some(), cx.shared.css_file_extension.is_some(),
&cx.shared.themes, &[]), &dst); &cx.shared.themes), &dst);
try_err!(w.flush(), &dst); try_err!(w.flush(), &dst);
} }
} }
@ -1366,15 +1374,17 @@ impl<'a> SourceCollector<'a> {
title: &title, title: &title,
css_class: "source", css_class: "source",
root_path: &root_path, root_path: &root_path,
static_root_path: self.scx.static_root_path.deref(),
description: &desc, description: &desc,
keywords: BASIC_KEYWORDS, keywords: BASIC_KEYWORDS,
resource_suffix: &self.scx.resource_suffix, resource_suffix: &self.scx.resource_suffix,
extra_scripts: &["source-files"],
static_extra_scripts: &[&format!("source-script{}", self.scx.resource_suffix)],
}; };
layout::render(&mut w, &self.scx.layout, layout::render(&mut w, &self.scx.layout,
&page, &(""), &Source(contents), &page, &(""), &Source(contents),
self.scx.css_file_extension.is_some(), self.scx.css_file_extension.is_some(),
&self.scx.themes, &["source-files", &self.scx.themes)?;
&format!("source-script{}", page.resource_suffix)])?;
w.flush()?; w.flush()?;
self.scx.local_sources.insert(p.clone(), href); self.scx.local_sources.insert(p.clone(), href);
Ok(()) Ok(())
@ -1956,9 +1966,12 @@ impl Context {
title: "List of all items in this crate", title: "List of all items in this crate",
css_class: "mod", css_class: "mod",
root_path: "../", root_path: "../",
static_root_path: self.shared.static_root_path.deref(),
description: "List of all items in this crate", description: "List of all items in this crate",
keywords: BASIC_KEYWORDS, keywords: BASIC_KEYWORDS,
resource_suffix: &self.shared.resource_suffix, resource_suffix: &self.shared.resource_suffix,
extra_scripts: &[],
static_extra_scripts: &[],
}; };
let sidebar = if let Some(ref version) = cache().crate_version { let sidebar = if let Some(ref version) = cache().crate_version {
format!("<p class='location'>Crate {}</p>\ format!("<p class='location'>Crate {}</p>\
@ -1973,7 +1986,7 @@ impl Context {
try_err!(layout::render(&mut w, &self.shared.layout, try_err!(layout::render(&mut w, &self.shared.layout,
&page, &sidebar, &all, &page, &sidebar, &all,
self.shared.css_file_extension.is_some(), self.shared.css_file_extension.is_some(),
&self.shared.themes, &[]), &self.shared.themes),
&final_file); &final_file);
// Generating settings page. // Generating settings page.
@ -1993,7 +2006,7 @@ impl Context {
try_err!(layout::render(&mut w, &layout, try_err!(layout::render(&mut w, &layout,
&page, &sidebar, &settings, &page, &sidebar, &settings,
self.shared.css_file_extension.is_some(), self.shared.css_file_extension.is_some(),
&themes, &[]), &themes),
&settings_file); &settings_file);
Ok(()) Ok(())
@ -2035,10 +2048,13 @@ impl Context {
let page = layout::Page { let page = layout::Page {
css_class: tyname, css_class: tyname,
root_path: &self.root_path(), root_path: &self.root_path(),
static_root_path: self.shared.static_root_path.deref(),
title: &title, title: &title,
description: &desc, description: &desc,
keywords: &keywords, keywords: &keywords,
resource_suffix: &self.shared.resource_suffix, resource_suffix: &self.shared.resource_suffix,
extra_scripts: &[],
static_extra_scripts: &[],
}; };
{ {
@ -2051,7 +2067,7 @@ impl Context {
&Sidebar{ cx: self, item: it }, &Sidebar{ cx: self, item: it },
&Item{ cx: self, item: it }, &Item{ cx: self, item: it },
self.shared.css_file_extension.is_some(), self.shared.css_file_extension.is_some(),
&self.shared.themes, &[])?; &self.shared.themes)?;
} else { } else {
let mut url = self.root_path(); let mut url = self.root_path();
if let Some(&(ref names, ty)) = cache().paths.get(&it.def_id) { if let Some(&(ref names, ty)) = cache().paths.get(&it.def_id) {

View file

@ -25,6 +25,7 @@
#![feature(crate_visibility_modifier)] #![feature(crate_visibility_modifier)]
#![feature(const_fn)] #![feature(const_fn)]
#![feature(drain_filter)] #![feature(drain_filter)]
#![feature(inner_deref)]
#![recursion_limit="256"] #![recursion_limit="256"]
@ -338,6 +339,13 @@ fn opts() -> Vec<RustcOptGroup> {
"enable-index-page", "enable-index-page",
"To enable generation of the index page") "To enable generation of the index page")
}), }),
unstable("static-root-path", |o| {
o.optopt("",
"static-root-path",
"Path string to force loading static files from in output pages. \
If not set, uses combinations of '../' to reach the documentation root.",
"PATH")
}),
] ]
} }

View file

@ -172,6 +172,7 @@ pub struct Decoder<'a> {
} }
impl<'a> Decoder<'a> { impl<'a> Decoder<'a> {
#[inline]
pub fn new(data: &'a [u8], position: usize) -> Decoder<'a> { pub fn new(data: &'a [u8], position: usize) -> Decoder<'a> {
Decoder { Decoder {
data, data,

View file

@ -354,7 +354,7 @@ const DISPLACEMENT_THRESHOLD: usize = 128;
/// *stat += random_stat_buff(); /// *stat += random_stat_buff();
/// ``` /// ```
/// ///
/// The easiest way to use `HashMap` with a custom type as key is to derive [`Eq`] and [`Hash`]. /// The easiest way to use `HashMap` with a custom key type is to derive [`Eq`] and [`Hash`].
/// We must also derive [`PartialEq`]. /// We must also derive [`PartialEq`].
/// ///
/// [`Eq`]: ../../std/cmp/trait.Eq.html /// [`Eq`]: ../../std/cmp/trait.Eq.html

View file

@ -740,6 +740,7 @@ impl<K, V> RawTable<K, V> {
} }
} }
#[inline]
fn new_internal( fn new_internal(
capacity: usize, capacity: usize,
fallibility: Fallibility, fallibility: Fallibility,
@ -755,12 +756,14 @@ impl<K, V> RawTable<K, V> {
/// Tries to create a new raw table from a given capacity. If it cannot allocate, /// Tries to create a new raw table from a given capacity. If it cannot allocate,
/// it returns with AllocErr. /// it returns with AllocErr.
#[inline]
pub fn try_new(capacity: usize) -> Result<RawTable<K, V>, CollectionAllocErr> { pub fn try_new(capacity: usize) -> Result<RawTable<K, V>, CollectionAllocErr> {
Self::new_internal(capacity, Fallible) Self::new_internal(capacity, Fallible)
} }
/// Creates a new raw table from a given capacity. All buckets are /// Creates a new raw table from a given capacity. All buckets are
/// initially empty. /// initially empty.
#[inline]
pub fn new(capacity: usize) -> RawTable<K, V> { pub fn new(capacity: usize) -> RawTable<K, V> {
match Self::new_internal(capacity, Infallible) { match Self::new_internal(capacity, Infallible) {
Err(CollectionAllocErr::CapacityOverflow) => panic!("capacity overflow"), Err(CollectionAllocErr::CapacityOverflow) => panic!("capacity overflow"),

View file

@ -253,10 +253,10 @@ impl f32 {
unsafe { intrinsics::fmaf32(self, a, b) } unsafe { intrinsics::fmaf32(self, a, b) }
} }
/// Calculates Euclidean division, the matching method for `mod_euc`. /// Calculates Euclidean division, the matching method for `rem_euclid`.
/// ///
/// This computes the integer `n` such that /// This computes the integer `n` such that
/// `self = n * rhs + self.mod_euc(rhs)`. /// `self = n * rhs + self.rem_euclid(rhs)`.
/// In other words, the result is `self / rhs` rounded to the integer `n` /// In other words, the result is `self / rhs` rounded to the integer `n`
/// such that `self >= n * rhs`. /// such that `self >= n * rhs`.
/// ///
@ -266,14 +266,14 @@ impl f32 {
/// #![feature(euclidean_division)] /// #![feature(euclidean_division)]
/// let a: f32 = 7.0; /// let a: f32 = 7.0;
/// let b = 4.0; /// let b = 4.0;
/// assert_eq!(a.div_euc(b), 1.0); // 7.0 > 4.0 * 1.0 /// assert_eq!(a.div_euclid(b), 1.0); // 7.0 > 4.0 * 1.0
/// assert_eq!((-a).div_euc(b), -2.0); // -7.0 >= 4.0 * -2.0 /// assert_eq!((-a).div_euclid(b), -2.0); // -7.0 >= 4.0 * -2.0
/// assert_eq!(a.div_euc(-b), -1.0); // 7.0 >= -4.0 * -1.0 /// assert_eq!(a.div_euclid(-b), -1.0); // 7.0 >= -4.0 * -1.0
/// assert_eq!((-a).div_euc(-b), 2.0); // -7.0 >= -4.0 * 2.0 /// assert_eq!((-a).div_euclid(-b), 2.0); // -7.0 >= -4.0 * 2.0
/// ``` /// ```
#[inline] #[inline]
#[unstable(feature = "euclidean_division", issue = "49048")] #[unstable(feature = "euclidean_division", issue = "49048")]
pub fn div_euc(self, rhs: f32) -> f32 { pub fn div_euclid(self, rhs: f32) -> f32 {
let q = (self / rhs).trunc(); let q = (self / rhs).trunc();
if self % rhs < 0.0 { if self % rhs < 0.0 {
return if rhs > 0.0 { q - 1.0 } else { q + 1.0 } return if rhs > 0.0 { q - 1.0 } else { q + 1.0 }
@ -281,7 +281,7 @@ impl f32 {
q q
} }
/// Calculates the Euclidean modulo (self mod rhs), which is never negative. /// Calculates the least nonnegative remainder of `self (mod rhs)`.
/// ///
/// In particular, the return value `r` satisfies `0.0 <= r < rhs.abs()` in /// In particular, the return value `r` satisfies `0.0 <= r < rhs.abs()` in
/// most cases. However, due to a floating point round-off error it can /// most cases. However, due to a floating point round-off error it can
@ -289,7 +289,7 @@ impl f32 {
/// `self` is much smaller than `rhs.abs()` in magnitude and `self < 0.0`. /// `self` is much smaller than `rhs.abs()` in magnitude and `self < 0.0`.
/// This result is not an element of the function's codomain, but it is the /// This result is not an element of the function's codomain, but it is the
/// closest floating point number in the real numbers and thus fulfills the /// closest floating point number in the real numbers and thus fulfills the
/// property `self == self.div_euc(rhs) * rhs + self.mod_euc(rhs)` /// property `self == self.div_euclid(rhs) * rhs + self.rem_euclid(rhs)`
/// approximatively. /// approximatively.
/// ///
/// # Examples /// # Examples
@ -298,16 +298,16 @@ impl f32 {
/// #![feature(euclidean_division)] /// #![feature(euclidean_division)]
/// let a: f32 = 7.0; /// let a: f32 = 7.0;
/// let b = 4.0; /// let b = 4.0;
/// assert_eq!(a.mod_euc(b), 3.0); /// assert_eq!(a.rem_euclid(b), 3.0);
/// assert_eq!((-a).mod_euc(b), 1.0); /// assert_eq!((-a).rem_euclid(b), 1.0);
/// assert_eq!(a.mod_euc(-b), 3.0); /// assert_eq!(a.rem_euclid(-b), 3.0);
/// assert_eq!((-a).mod_euc(-b), 1.0); /// assert_eq!((-a).rem_euclid(-b), 1.0);
/// // limitation due to round-off error /// // limitation due to round-off error
/// assert!((-std::f32::EPSILON).mod_euc(3.0) != 0.0); /// assert!((-std::f32::EPSILON).rem_euclid(3.0) != 0.0);
/// ``` /// ```
#[inline] #[inline]
#[unstable(feature = "euclidean_division", issue = "49048")] #[unstable(feature = "euclidean_division", issue = "49048")]
pub fn mod_euc(self, rhs: f32) -> f32 { pub fn rem_euclid(self, rhs: f32) -> f32 {
let r = self % rhs; let r = self % rhs;
if r < 0.0 { if r < 0.0 {
r + rhs.abs() r + rhs.abs()

View file

@ -229,10 +229,10 @@ impl f64 {
unsafe { intrinsics::fmaf64(self, a, b) } unsafe { intrinsics::fmaf64(self, a, b) }
} }
/// Calculates Euclidean division, the matching method for `mod_euc`. /// Calculates Euclidean division, the matching method for `rem_euclid`.
/// ///
/// This computes the integer `n` such that /// This computes the integer `n` such that
/// `self = n * rhs + self.mod_euc(rhs)`. /// `self = n * rhs + self.rem_euclid(rhs)`.
/// In other words, the result is `self / rhs` rounded to the integer `n` /// In other words, the result is `self / rhs` rounded to the integer `n`
/// such that `self >= n * rhs`. /// such that `self >= n * rhs`.
/// ///
@ -242,14 +242,14 @@ impl f64 {
/// #![feature(euclidean_division)] /// #![feature(euclidean_division)]
/// let a: f64 = 7.0; /// let a: f64 = 7.0;
/// let b = 4.0; /// let b = 4.0;
/// assert_eq!(a.div_euc(b), 1.0); // 7.0 > 4.0 * 1.0 /// assert_eq!(a.div_euclid(b), 1.0); // 7.0 > 4.0 * 1.0
/// assert_eq!((-a).div_euc(b), -2.0); // -7.0 >= 4.0 * -2.0 /// assert_eq!((-a).div_euclid(b), -2.0); // -7.0 >= 4.0 * -2.0
/// assert_eq!(a.div_euc(-b), -1.0); // 7.0 >= -4.0 * -1.0 /// assert_eq!(a.div_euclid(-b), -1.0); // 7.0 >= -4.0 * -1.0
/// assert_eq!((-a).div_euc(-b), 2.0); // -7.0 >= -4.0 * 2.0 /// assert_eq!((-a).div_euclid(-b), 2.0); // -7.0 >= -4.0 * 2.0
/// ``` /// ```
#[inline] #[inline]
#[unstable(feature = "euclidean_division", issue = "49048")] #[unstable(feature = "euclidean_division", issue = "49048")]
pub fn div_euc(self, rhs: f64) -> f64 { pub fn div_euclid(self, rhs: f64) -> f64 {
let q = (self / rhs).trunc(); let q = (self / rhs).trunc();
if self % rhs < 0.0 { if self % rhs < 0.0 {
return if rhs > 0.0 { q - 1.0 } else { q + 1.0 } return if rhs > 0.0 { q - 1.0 } else { q + 1.0 }
@ -257,7 +257,7 @@ impl f64 {
q q
} }
/// Calculates the Euclidean modulo (self mod rhs), which is never negative. /// Calculates the least nonnegative remainder of `self (mod rhs)`.
/// ///
/// In particular, the return value `r` satisfies `0.0 <= r < rhs.abs()` in /// In particular, the return value `r` satisfies `0.0 <= r < rhs.abs()` in
/// most cases. However, due to a floating point round-off error it can /// most cases. However, due to a floating point round-off error it can
@ -265,7 +265,7 @@ impl f64 {
/// `self` is much smaller than `rhs.abs()` in magnitude and `self < 0.0`. /// `self` is much smaller than `rhs.abs()` in magnitude and `self < 0.0`.
/// This result is not an element of the function's codomain, but it is the /// This result is not an element of the function's codomain, but it is the
/// closest floating point number in the real numbers and thus fulfills the /// closest floating point number in the real numbers and thus fulfills the
/// property `self == self.div_euc(rhs) * rhs + self.mod_euc(rhs)` /// property `self == self.div_euclid(rhs) * rhs + self.rem_euclid(rhs)`
/// approximatively. /// approximatively.
/// ///
/// # Examples /// # Examples
@ -274,16 +274,16 @@ impl f64 {
/// #![feature(euclidean_division)] /// #![feature(euclidean_division)]
/// let a: f64 = 7.0; /// let a: f64 = 7.0;
/// let b = 4.0; /// let b = 4.0;
/// assert_eq!(a.mod_euc(b), 3.0); /// assert_eq!(a.rem_euclid(b), 3.0);
/// assert_eq!((-a).mod_euc(b), 1.0); /// assert_eq!((-a).rem_euclid(b), 1.0);
/// assert_eq!(a.mod_euc(-b), 3.0); /// assert_eq!(a.rem_euclid(-b), 3.0);
/// assert_eq!((-a).mod_euc(-b), 1.0); /// assert_eq!((-a).rem_euclid(-b), 1.0);
/// // limitation due to round-off error /// // limitation due to round-off error
/// assert!((-std::f64::EPSILON).mod_euc(3.0) != 0.0); /// assert!((-std::f64::EPSILON).rem_euclid(3.0) != 0.0);
/// ``` /// ```
#[inline] #[inline]
#[unstable(feature = "euclidean_division", issue = "49048")] #[unstable(feature = "euclidean_division", issue = "49048")]
pub fn mod_euc(self, rhs: f64) -> f64 { pub fn rem_euclid(self, rhs: f64) -> f64 {
let r = self % rhs; let r = self % rhs;
if r < 0.0 { if r < 0.0 {
r + rhs.abs() r + rhs.abs()

View file

@ -294,7 +294,7 @@ impl<R: Seek> Seek for BufReader<R> {
/// `.into_inner()` immediately after a seek yields the underlying reader /// `.into_inner()` immediately after a seek yields the underlying reader
/// at the same position. /// at the same position.
/// ///
/// To seek without discarding the internal buffer, use [`Seek::seek_relative`]. /// To seek without discarding the internal buffer, use [`BufReader::seek_relative`].
/// ///
/// See [`std::io::Seek`] for more details. /// See [`std::io::Seek`] for more details.
/// ///
@ -303,6 +303,9 @@ impl<R: Seek> Seek for BufReader<R> {
/// seeks will be performed instead of one. If the second seek returns /// seeks will be performed instead of one. If the second seek returns
/// `Err`, the underlying reader will be left at the same position it would /// `Err`, the underlying reader will be left at the same position it would
/// have if you called `seek` with `SeekFrom::Current(0)`. /// have if you called `seek` with `SeekFrom::Current(0)`.
///
/// [`BufReader::seek_relative`]: struct.BufReader.html#method.seek_relative
/// [`std::io::Seek`]: trait.Seek.html
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> { fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
let result: u64; let result: u64;
if let SeekFrom::Current(n) = pos { if let SeekFrom::Current(n) = pos {

View file

@ -225,6 +225,9 @@ impl From<ErrorKind> for Error {
/// let error = Error::from(not_found); /// let error = Error::from(not_found);
/// assert_eq!("entity not found", format!("{}", error)); /// assert_eq!("entity not found", format!("{}", error));
/// ``` /// ```
///
/// [`ErrorKind`]: ../../std/io/enum.ErrorKind.html
/// [`Error`]: ../../std/io/struct.Error.html
#[inline] #[inline]
fn from(kind: ErrorKind) -> Error { fn from(kind: ErrorKind) -> Error {
Error { Error {

View file

@ -222,6 +222,7 @@
#![no_std] #![no_std]
#![deny(missing_docs)] #![deny(missing_docs)]
#![deny(intra_doc_link_resolution_failure)]
#![deny(missing_debug_implementations)] #![deny(missing_debug_implementations)]
// Tell the compiler to link to either panic_abort or panic_unwind // Tell the compiler to link to either panic_abort or panic_unwind

View file

@ -1461,7 +1461,7 @@ impl From<String> for PathBuf {
} }
} }
#[stable(feature = "path_from_str", since = "1.26.0")] #[stable(feature = "path_from_str", since = "1.32.0")]
impl FromStr for PathBuf { impl FromStr for PathBuf {
type Err = ParseError; type Err = ParseError;

View file

@ -56,6 +56,14 @@ IMAGE_BASE:
globvar CFGDATA_BASE 8 globvar CFGDATA_BASE 8
/* Non-zero if debugging is enabled, zero otherwise */ /* Non-zero if debugging is enabled, zero otherwise */
globvar DEBUG 1 globvar DEBUG 1
/* The base address (relative to enclave start) of the enclave text section */
globvar TEXT_BASE 8
/* The size in bytes of enclacve text section */
globvar TEXT_SIZE 8
/* The base address (relative to enclave start) of the enclave EH_FRM_HDR section */
globvar EH_FRM_HDR_BASE 8
/* The size in bytes of enclacve EH_FRM_HDR section */
globvar EH_FRM_HDR_SIZE 8
.Lreentry_panic_msg: .Lreentry_panic_msg:
.asciz "Re-entered panicked enclave!" .asciz "Re-entered panicked enclave!"

View file

@ -9,14 +9,25 @@
// except according to those terms. // except according to those terms.
use num::NonZeroUsize; use num::NonZeroUsize;
use slice;
use str;
use super::waitqueue::{WaitVariable, WaitQueue, SpinMutex, NotifiedTcs, try_lock_or_false}; use super::waitqueue::{
try_lock_or_false, NotifiedTcs, SpinMutex, SpinMutexGuard, WaitQueue, WaitVariable,
};
use mem;
pub struct RWLock { pub struct RWLock {
readers: SpinMutex<WaitVariable<Option<NonZeroUsize>>>, readers: SpinMutex<WaitVariable<Option<NonZeroUsize>>>,
writer: SpinMutex<WaitVariable<bool>>, writer: SpinMutex<WaitVariable<bool>>,
} }
// Below is to check at compile time, that RWLock has size of 128 bytes.
#[allow(dead_code)]
unsafe fn rw_lock_size_assert(r: RWLock) {
mem::transmute::<RWLock, [u8; 128]>(r);
}
//unsafe impl Send for RWLock {} //unsafe impl Send for RWLock {}
//unsafe impl Sync for RWLock {} // FIXME //unsafe impl Sync for RWLock {} // FIXME
@ -24,7 +35,7 @@ impl RWLock {
pub const fn new() -> RWLock { pub const fn new() -> RWLock {
RWLock { RWLock {
readers: SpinMutex::new(WaitVariable::new(None)), readers: SpinMutex::new(WaitVariable::new(None)),
writer: SpinMutex::new(WaitVariable::new(false)) writer: SpinMutex::new(WaitVariable::new(false)),
} }
} }
@ -89,9 +100,11 @@ impl RWLock {
} }
#[inline] #[inline]
pub unsafe fn read_unlock(&self) { unsafe fn __read_unlock(
let mut rguard = self.readers.lock(); &self,
let wguard = self.writer.lock(); mut rguard: SpinMutexGuard<WaitVariable<Option<NonZeroUsize>>>,
wguard: SpinMutexGuard<WaitVariable<bool>>,
) {
*rguard.lock_var_mut() = NonZeroUsize::new(rguard.lock_var().unwrap().get() - 1); *rguard.lock_var_mut() = NonZeroUsize::new(rguard.lock_var().unwrap().get() - 1);
if rguard.lock_var().is_some() { if rguard.lock_var().is_some() {
// There are other active readers // There are other active readers
@ -107,9 +120,18 @@ impl RWLock {
} }
#[inline] #[inline]
pub unsafe fn write_unlock(&self) { pub unsafe fn read_unlock(&self) {
let rguard = self.readers.lock(); let rguard = self.readers.lock();
let wguard = self.writer.lock(); let wguard = self.writer.lock();
self.__read_unlock(rguard, wguard);
}
#[inline]
unsafe fn __write_unlock(
&self,
rguard: SpinMutexGuard<WaitVariable<Option<NonZeroUsize>>>,
wguard: SpinMutexGuard<WaitVariable<bool>>,
) {
if let Err(mut wguard) = WaitQueue::notify_one(wguard) { if let Err(mut wguard) = WaitQueue::notify_one(wguard) {
// No writers waiting, release the write lock // No writers waiting, release the write lock
*wguard.lock_var_mut() = false; *wguard.lock_var_mut() = false;
@ -128,6 +150,109 @@ impl RWLock {
} }
} }
#[inline]
pub unsafe fn write_unlock(&self) {
let rguard = self.readers.lock();
let wguard = self.writer.lock();
self.__write_unlock(rguard, wguard);
}
#[inline]
unsafe fn unlock(&self) {
let rguard = self.readers.lock();
let wguard = self.writer.lock();
if *wguard.lock_var() == true {
self.__write_unlock(rguard, wguard);
} else {
self.__read_unlock(rguard, wguard);
}
}
#[inline] #[inline]
pub unsafe fn destroy(&self) {} pub unsafe fn destroy(&self) {}
} }
const EINVAL: i32 = 22;
#[no_mangle]
pub unsafe extern "C" fn __rust_rwlock_rdlock(p: *mut RWLock) -> i32 {
if p.is_null() {
return EINVAL;
}
(*p).read();
return 0;
}
#[no_mangle]
pub unsafe extern "C" fn __rust_rwlock_wrlock(p: *mut RWLock) -> i32 {
if p.is_null() {
return EINVAL;
}
(*p).write();
return 0;
}
#[no_mangle]
pub unsafe extern "C" fn __rust_rwlock_unlock(p: *mut RWLock) -> i32 {
if p.is_null() {
return EINVAL;
}
(*p).unlock();
return 0;
}
#[no_mangle]
pub unsafe extern "C" fn __rust_print_err(m: *mut u8, s: i32) {
if s < 0 {
return;
}
let buf = slice::from_raw_parts(m as *const u8, s as _);
if let Ok(s) = str::from_utf8(&buf[..buf.iter().position(|&b| b == 0).unwrap_or(buf.len())]) {
eprint!("{}", s);
}
}
#[no_mangle]
pub unsafe extern "C" fn __rust_abort() {
::sys::abort_internal();
}
#[cfg(test)]
mod tests {
use super::*;
use core::array::FixedSizeArray;
use mem::MaybeUninit;
use {mem, ptr};
// The below test verifies that the bytes of initialized RWLock are the ones
// we use in libunwind.
// If they change we need to update src/UnwindRustSgx.h in libunwind.
#[test]
fn test_c_rwlock_initializer() {
const RWLOCK_INIT: &[u8] = &[
0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
];
let mut init = MaybeUninit::<RWLock>::zeroed();
init.set(RWLock::new());
assert_eq!(
mem::transmute::<_, [u8; 128]>(init.into_inner()).as_slice(),
RWLOCK_INIT
);
}
}

View file

@ -397,9 +397,6 @@ declare_features! (
// Multiple patterns with `|` in `if let` and `while let`. // Multiple patterns with `|` in `if let` and `while let`.
(active, if_while_or_patterns, "1.26.0", Some(48215), None), (active, if_while_or_patterns, "1.26.0", Some(48215), None),
// Allows `#[repr(packed)]` attribute on structs.
(active, repr_packed, "1.26.0", Some(33158), None),
// Allows macro invocations in `extern {}` blocks. // Allows macro invocations in `extern {}` blocks.
(active, macros_in_extern, "1.27.0", Some(49476), None), (active, macros_in_extern, "1.27.0", Some(49476), None),
@ -684,17 +681,19 @@ declare_features! (
// `extern crate foo as bar;` puts `bar` into extern prelude. // `extern crate foo as bar;` puts `bar` into extern prelude.
(accepted, extern_crate_item_prelude, "1.31.0", Some(55599), None), (accepted, extern_crate_item_prelude, "1.31.0", Some(55599), None),
// Allows use of the `:literal` macro fragment specifier (RFC 1576). // Allows use of the `:literal` macro fragment specifier (RFC 1576).
(accepted, macro_literal_matcher, "1.31.0", Some(35625), None), (accepted, macro_literal_matcher, "1.32.0", Some(35625), None),
// Integer match exhaustiveness checking (RFC 2591)
(accepted, exhaustive_integer_patterns, "1.32.0", Some(50907), None),
// Use `?` as the Kleene "at most one" operator. // Use `?` as the Kleene "at most one" operator.
(accepted, macro_at_most_once_rep, "1.32.0", Some(48075), None), (accepted, macro_at_most_once_rep, "1.32.0", Some(48075), None),
// `Self` struct constructor (RFC 2302) // `Self` struct constructor (RFC 2302)
(accepted, self_struct_ctor, "1.32.0", Some(51994), None), (accepted, self_struct_ctor, "1.32.0", Some(51994), None),
// `Self` in type definitions (RFC 2300) // `Self` in type definitions (RFC 2300)
(accepted, self_in_typedefs, "1.32.0", Some(49303), None), (accepted, self_in_typedefs, "1.32.0", Some(49303), None),
// Integer match exhaustiveness checking (RFC 2591)
(accepted, exhaustive_integer_patterns, "1.33.0", Some(50907), None),
// `use path as _;` and `extern crate c as _;` // `use path as _;` and `extern crate c as _;`
(accepted, underscore_imports, "1.33.0", Some(48216), None), (accepted, underscore_imports, "1.33.0", Some(48216), None),
// Allows `#[repr(packed(N))]` attribute on structs.
(accepted, repr_packed, "1.33.0", Some(33158), None),
); );
// If you change this, please modify `src/doc/unstable-book` as well. You must // If you change this, please modify `src/doc/unstable-book` as well. You must
@ -1588,13 +1587,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
gate_feature_post!(&self, repr_simd, attr.span, gate_feature_post!(&self, repr_simd, attr.span,
"SIMD types are experimental and possibly buggy"); "SIMD types are experimental and possibly buggy");
} }
if let Some((name, _)) = item.name_value_literal() {
if name == "packed" {
gate_feature_post!(&self, repr_packed, attr.span,
"the `#[repr(packed(n))]` attribute \
is experimental");
}
}
} }
} }
} }

View file

@ -26,10 +26,7 @@ mod macros;
cfg_if! { cfg_if! {
if #[cfg(target_env = "msvc")] { if #[cfg(target_env = "msvc")] {
// no extra unwinder support needed // no extra unwinder support needed
} else if #[cfg(any( } else if #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] {
all(target_arch = "wasm32", not(target_os = "emscripten")),
target_env = "sgx"
))] {
// no unwinder on the system! // no unwinder on the system!
} else { } else {
extern crate libc; extern crate libc;

View file

@ -13,7 +13,6 @@
// min-llvm-version 7.0 // min-llvm-version 7.0
#![crate_type = "lib"] #![crate_type = "lib"]
#![feature(repr_packed)]
#[repr(packed)] #[repr(packed)]
pub struct Packed1 { pub struct Packed1 {

View file

@ -9,7 +9,6 @@
// except according to those terms. // except according to those terms.
// run-pass // run-pass
#![feature(repr_packed)]
#![allow(non_camel_case_types)] #![allow(non_camel_case_types)]
use std::mem; use std::mem;

View file

@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
#![feature(repr_packed)]
#[repr(packed)] #[repr(packed)]
pub struct P1S5 { pub struct P1S5 {
a: u8, a: u8,

View file

@ -12,8 +12,6 @@
#![allow(dead_code)] #![allow(dead_code)]
// ignore-emscripten weird assertion? // ignore-emscripten weird assertion?
#![feature(repr_packed)]
#[repr(packed)] #[repr(packed)]
struct Foo1 { struct Foo1 {
bar: u8, bar: u8,

View file

@ -10,11 +10,8 @@
// run-pass // run-pass
#![allow(dead_code)] #![allow(dead_code)]
#![allow(stable_features)]
#![allow(unused_comparisons)] #![allow(unused_comparisons)]
#![feature(repr_packed)]
use std::mem; use std::mem;
#[repr(packed)] #[repr(packed)]

View file

@ -1,35 +1,35 @@
warning: unnecessary path disambiguator warning: unnecessary path disambiguator
--> $DIR/packed-struct-generic-size.rs:49:14 --> $DIR/packed-struct-generic-size.rs:46:14
| |
LL | check!(P1::<u8, u8>, 1, 3); LL | check!(P1::<u8, u8>, 1, 3);
| ^^ try removing `::` | ^^ try removing `::`
warning: unnecessary path disambiguator warning: unnecessary path disambiguator
--> $DIR/packed-struct-generic-size.rs:50:14 --> $DIR/packed-struct-generic-size.rs:47:14
| |
LL | check!(P1::<u64, u16>, 1, 11); LL | check!(P1::<u64, u16>, 1, 11);
| ^^ try removing `::` | ^^ try removing `::`
warning: unnecessary path disambiguator warning: unnecessary path disambiguator
--> $DIR/packed-struct-generic-size.rs:52:14 --> $DIR/packed-struct-generic-size.rs:49:14
| |
LL | check!(P2::<u8, u8>, 1, 3); LL | check!(P2::<u8, u8>, 1, 3);
| ^^ try removing `::` | ^^ try removing `::`
warning: unnecessary path disambiguator warning: unnecessary path disambiguator
--> $DIR/packed-struct-generic-size.rs:53:14 --> $DIR/packed-struct-generic-size.rs:50:14
| |
LL | check!(P2::<u64, u16>, 2, 12); LL | check!(P2::<u64, u16>, 2, 12);
| ^^ try removing `::` | ^^ try removing `::`
warning: unnecessary path disambiguator warning: unnecessary path disambiguator
--> $DIR/packed-struct-generic-size.rs:55:15 --> $DIR/packed-struct-generic-size.rs:52:15
| |
LL | check!(P4C::<u8, u8>, 1, 3); LL | check!(P4C::<u8, u8>, 1, 3);
| ^^ try removing `::` | ^^ try removing `::`
warning: unnecessary path disambiguator warning: unnecessary path disambiguator
--> $DIR/packed-struct-generic-size.rs:56:15 --> $DIR/packed-struct-generic-size.rs:53:15
| |
LL | check!(P4C::<u16, u64>, 4, 12); LL | check!(P4C::<u16, u64>, 4, 12);
| ^^ try removing `::` | ^^ try removing `::`

View file

@ -9,7 +9,6 @@
// except according to those terms. // except according to those terms.
// run-pass // run-pass
#![feature(repr_packed)]
#[repr(packed)] #[repr(packed)]
struct Foo1 { struct Foo1 {

View file

@ -13,9 +13,6 @@
#![allow(non_camel_case_types)] #![allow(non_camel_case_types)]
#![allow(non_upper_case_globals)] #![allow(non_upper_case_globals)]
#![feature(repr_packed)]
use std::mem; use std::mem;
#[repr(packed)] #[repr(packed)]

View file

@ -9,7 +9,6 @@
// except according to those terms. // except according to those terms.
// run-pass // run-pass
#![feature(repr_packed)]
use std::fmt; use std::fmt;
use std::mem; use std::mem;

View file

@ -12,8 +12,6 @@
#![allow(dead_code)] #![allow(dead_code)]
#![allow(non_camel_case_types)] #![allow(non_camel_case_types)]
#![feature(repr_packed)]
use std::mem; use std::mem;
#[repr(packed)] #[repr(packed)]

View file

@ -11,7 +11,6 @@
// run-pass // run-pass
#![allow(dead_code)] #![allow(dead_code)]
#![feature(box_syntax)] #![feature(box_syntax)]
#![feature(repr_packed)]
use std::mem; use std::mem;

View file

@ -13,7 +13,6 @@
#![allow(non_snake_case)] #![allow(non_snake_case)]
#![feature(untagged_unions)] #![feature(untagged_unions)]
#![feature(repr_packed)]
use std::mem::{size_of, size_of_val, align_of, align_of_val}; use std::mem::{size_of, size_of_val, align_of, align_of_val};

View file

@ -0,0 +1,24 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// compile-flags:-Z unstable-options --static-root-path /cache/
// @has static_root_path/struct.SomeStruct.html
// @matches - '"/cache/main\.js"'
// @!matches - '"\.\./main\.js"'
// @matches - '"\.\./search-index\.js"'
// @!matches - '"/cache/search-index\.js"'
pub struct SomeStruct;
// @has src/static_root_path/static-root-path.rs.html
// @matches - '"/cache/source-script\.js"'
// @!matches - '"\.\./\.\./source-script\.js"'
// @matches - '"\.\./\.\./source-files.js"'
// @!matches - '"/cache/source-files\.js"'

View file

@ -10,9 +10,8 @@ LL | Foo::Y(_, ref mut b) => b,
LL | *a += 1; LL | *a += 1;
| ------- borrow later used here | ------- borrow later used here
| |
= warning: This error has been downgraded to a warning for backwards compatibility with previous releases. = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
It represents potential unsoundness in your code. = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
This warning will become a hard error in the future.
error[E0503]: cannot use `y` because it was mutably borrowed error[E0503]: cannot use `y` because it was mutably borrowed
--> $DIR/borrowck-anon-fields-variant.rs:44:7 --> $DIR/borrowck-anon-fields-variant.rs:44:7

View file

@ -350,9 +350,8 @@ LL | let p: &'a u8 = &*block.current;
LL | drop(x); LL | drop(x);
| - mutable borrow later used here | - mutable borrow later used here
| |
= warning: This error has been downgraded to a warning for backwards compatibility with previous releases. = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
It represents potential unsoundness in your code. = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
This warning will become a hard error in the future.
warning[E0502]: cannot borrow `*block.current` as immutable because it is also borrowed as mutable warning[E0502]: cannot borrow `*block.current` as immutable because it is also borrowed as mutable
--> $DIR/borrowck-describe-lvalue.rs:260:33 --> $DIR/borrowck-describe-lvalue.rs:260:33
@ -365,9 +364,8 @@ LL | let p : *const u8 = &*(*block).current;
LL | drop(x); LL | drop(x);
| - mutable borrow later used here | - mutable borrow later used here
| |
= warning: This error has been downgraded to a warning for backwards compatibility with previous releases. = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
It represents potential unsoundness in your code. = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
This warning will become a hard error in the future.
error[E0382]: use of moved value: `x` error[E0382]: use of moved value: `x`
--> $DIR/borrowck-describe-lvalue.rs:318:22 --> $DIR/borrowck-describe-lvalue.rs:318:22

View file

@ -4,7 +4,6 @@ warning[E0507]: cannot move out of borrowed content
LL | (|| { let bar = foo; bar.take() })(); LL | (|| { let bar = foo; bar.take() })();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
| |
= warning: This error has been downgraded to a warning for backwards compatibility with previous releases. = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
It represents potential unsoundness in your code. = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
This warning will become a hard error in the future.

View file

@ -4,7 +4,6 @@ warning[E0507]: cannot move out of borrowed content
LL | (|| { let bar = foo; bar.take() })(); LL | (|| { let bar = foo; bar.take() })();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
| |
= warning: This error has been downgraded to a warning for backwards compatibility with previous releases. = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
It represents potential unsoundness in your code. = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
This warning will become a hard error in the future.

View file

@ -9,7 +9,6 @@
// except according to those terms. // except according to those terms.
#![allow(dead_code)] #![allow(dead_code)]
#![feature(repr_packed)]
#[repr(C)] #[repr(C)]
enum A { A } enum A { A }

View file

@ -1,47 +1,47 @@
warning[E0566]: conflicting representation hints warning[E0566]: conflicting representation hints
--> $DIR/conflicting-repr-hints.rs:20:8 --> $DIR/conflicting-repr-hints.rs:19:8
| |
LL | #[repr(C, u64)] //~ WARNING conflicting representation hints LL | #[repr(C, u64)] //~ WARNING conflicting representation hints
| ^ ^^^ | ^ ^^^
warning[E0566]: conflicting representation hints warning[E0566]: conflicting representation hints
--> $DIR/conflicting-repr-hints.rs:23:8 --> $DIR/conflicting-repr-hints.rs:22:8
| |
LL | #[repr(u32, u64)] //~ WARNING conflicting representation hints LL | #[repr(u32, u64)] //~ WARNING conflicting representation hints
| ^^^ ^^^ | ^^^ ^^^
error[E0587]: type has conflicting packed and align representation hints error[E0587]: type has conflicting packed and align representation hints
--> $DIR/conflicting-repr-hints.rs:30:1 --> $DIR/conflicting-repr-hints.rs:29:1
| |
LL | struct F(i32); //~ ERROR type has conflicting packed and align representation hints LL | struct F(i32); //~ ERROR type has conflicting packed and align representation hints
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
error[E0587]: type has conflicting packed and align representation hints error[E0587]: type has conflicting packed and align representation hints
--> $DIR/conflicting-repr-hints.rs:34:1 --> $DIR/conflicting-repr-hints.rs:33:1
| |
LL | struct G(i32); //~ ERROR type has conflicting packed and align representation hints LL | struct G(i32); //~ ERROR type has conflicting packed and align representation hints
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
error[E0587]: type has conflicting packed and align representation hints error[E0587]: type has conflicting packed and align representation hints
--> $DIR/conflicting-repr-hints.rs:38:1 --> $DIR/conflicting-repr-hints.rs:37:1
| |
LL | struct H(i32); //~ ERROR type has conflicting packed and align representation hints LL | struct H(i32); //~ ERROR type has conflicting packed and align representation hints
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
error[E0634]: type has conflicting packed representation hints error[E0634]: type has conflicting packed representation hints
--> $DIR/conflicting-repr-hints.rs:41:1 --> $DIR/conflicting-repr-hints.rs:40:1
| |
LL | struct I(i32); //~ ERROR type has conflicting packed representation hints LL | struct I(i32); //~ ERROR type has conflicting packed representation hints
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
error[E0634]: type has conflicting packed representation hints error[E0634]: type has conflicting packed representation hints
--> $DIR/conflicting-repr-hints.rs:45:1 --> $DIR/conflicting-repr-hints.rs:44:1
| |
LL | struct J(i32); //~ ERROR type has conflicting packed representation hints LL | struct J(i32); //~ ERROR type has conflicting packed representation hints
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
error[E0587]: type has conflicting packed and align representation hints error[E0587]: type has conflicting packed and align representation hints
--> $DIR/conflicting-repr-hints.rs:51:1 --> $DIR/conflicting-repr-hints.rs:50:1
| |
LL | / union X { //~ ERROR type has conflicting packed and align representation hints LL | / union X { //~ ERROR type has conflicting packed and align representation hints
LL | | i: i32 LL | | i: i32
@ -49,7 +49,7 @@ LL | | }
| |_^ | |_^
error[E0587]: type has conflicting packed and align representation hints error[E0587]: type has conflicting packed and align representation hints
--> $DIR/conflicting-repr-hints.rs:57:1 --> $DIR/conflicting-repr-hints.rs:56:1
| |
LL | / union Y { //~ ERROR type has conflicting packed and align representation hints LL | / union Y { //~ ERROR type has conflicting packed and align representation hints
LL | | i: i32 LL | | i: i32
@ -57,7 +57,7 @@ LL | | }
| |_^ | |_^
error[E0587]: type has conflicting packed and align representation hints error[E0587]: type has conflicting packed and align representation hints
--> $DIR/conflicting-repr-hints.rs:63:1 --> $DIR/conflicting-repr-hints.rs:62:1
| |
LL | / union Z { //~ ERROR type has conflicting packed and align representation hints LL | / union Z { //~ ERROR type has conflicting packed and align representation hints
LL | | i: i32 LL | | i: i32

View file

@ -199,9 +199,8 @@ LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
| |temporary value created here | |temporary value created here
| returns a reference to data owned by the current function | returns a reference to data owned by the current function
| |
= warning: This error has been downgraded to a warning for backwards compatibility with previous releases. = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
It represents potential unsoundness in your code. = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
This warning will become a hard error in the future.
error: trait bounds other than `Sized` on const fn parameters are unstable error: trait bounds other than `Sized` on const fn parameters are unstable
--> $DIR/min_const_fn.rs:147:41 --> $DIR/min_const_fn.rs:147:41

View file

@ -19,9 +19,8 @@ LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) }
| |creates a temporary which is freed while still in use | |creates a temporary which is freed while still in use
| cast requires that borrow lasts for `'static` | cast requires that borrow lasts for `'static`
| |
= warning: This error has been downgraded to a warning for backwards compatibility with previous releases. = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
It represents potential unsoundness in your code. = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
This warning will become a hard error in the future.
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View file

@ -0,0 +1,9 @@
// compile-pass
fn main() {
let _ = &[("", ""); 3];
}
const FOO: &[(&str, &str)] = &[("", ""); 3];
const BAR: &[(&str, &str); 5] = &[("", ""); 5];
const BAA: &[[&str; 12]; 11] = &[[""; 12]; 11];

View file

@ -1,18 +0,0 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[repr(packed(1))] //~ error: the `#[repr(packed(n))]` attribute is experimental
struct Foo(u64);
#[repr(C)]
#[repr(packed(1))] //~ error: the `#[repr(packed(n))]` attribute is experimental
struct Bar(u64);
fn main() {}

View file

@ -1,19 +0,0 @@
error[E0658]: the `#[repr(packed(n))]` attribute is experimental (see issue #33158)
--> $DIR/feature-gate-repr_packed.rs:11:1
|
LL | #[repr(packed(1))] //~ error: the `#[repr(packed(n))]` attribute is experimental
| ^^^^^^^^^^^^^^^^^^
|
= help: add #![feature(repr_packed)] to the crate attributes to enable
error[E0658]: the `#[repr(packed(n))]` attribute is experimental (see issue #33158)
--> $DIR/feature-gate-repr_packed.rs:15:1
|
LL | #[repr(packed(1))] //~ error: the `#[repr(packed(n))]` attribute is experimental
| ^^^^^^^^^^^^^^^^^^
|
= help: add #![feature(repr_packed)] to the crate attributes to enable
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0658`.

View file

@ -8,7 +8,6 @@ LL | &mut x
| |
= note: `FnMut` closures only have access to their captured variables while they are executing... = note: `FnMut` closures only have access to their captured variables while they are executing...
= note: ...therefore, they cannot allow references to captured variables to escape = note: ...therefore, they cannot allow references to captured variables to escape
= warning: This error has been downgraded to a warning for backwards compatibility with previous releases. = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
It represents potential unsoundness in your code. = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
This warning will become a hard error in the future.

View file

@ -10,7 +10,6 @@ LL | | }
| |
= note: `FnMut` closures only have access to their captured variables while they are executing... = note: `FnMut` closures only have access to their captured variables while they are executing...
= note: ...therefore, they cannot allow references to captured variables to escape = note: ...therefore, they cannot allow references to captured variables to escape
= warning: This error has been downgraded to a warning for backwards compatibility with previous releases. = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
It represents potential unsoundness in your code. = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
This warning will become a hard error in the future.

View file

@ -1,5 +1,5 @@
error: compilation successful error: compilation successful
--> $DIR/issue-45696-scribble-on-boxed-borrow.rs:89:1 --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:92:1
| |
LL | / fn main() { //[ast]~ ERROR compilation successful LL | / fn main() { //[ast]~ ERROR compilation successful
LL | | //[migrate]~^ ERROR compilation successful LL | | //[migrate]~^ ERROR compilation successful

View file

@ -9,12 +9,11 @@ LL | &mut *s.0 //[nll]~ ERROR borrow may still be in use when destructor run
LL | } LL | }
| - here, drop of `s` needs exclusive access to `*s.0`, because the type `Scribble<'_>` implements the `Drop` trait | - here, drop of `s` needs exclusive access to `*s.0`, because the type `Scribble<'_>` implements the `Drop` trait
| |
= warning: This error has been downgraded to a warning for backwards compatibility with previous releases. = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
It represents potential unsoundness in your code. = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
This warning will become a hard error in the future.
warning[E0713]: borrow may still be in use when destructor runs warning[E0713]: borrow may still be in use when destructor runs
--> $DIR/issue-45696-scribble-on-boxed-borrow.rs:73:5 --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:74:5
| |
LL | fn boxed_scribbled<'a>(s: Box<Scribble<'a>>) -> &'a mut u32 { LL | fn boxed_scribbled<'a>(s: Box<Scribble<'a>>) -> &'a mut u32 {
| -- lifetime `'a` defined here | -- lifetime `'a` defined here
@ -24,12 +23,11 @@ LL | &mut *(*s).0 //[nll]~ ERROR borrow may still be in use when destructor
LL | } LL | }
| - here, drop of `s` needs exclusive access to `*s.0`, because the type `Scribble<'_>` implements the `Drop` trait | - here, drop of `s` needs exclusive access to `*s.0`, because the type `Scribble<'_>` implements the `Drop` trait
| |
= warning: This error has been downgraded to a warning for backwards compatibility with previous releases. = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
It represents potential unsoundness in your code. = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
This warning will become a hard error in the future.
warning[E0713]: borrow may still be in use when destructor runs warning[E0713]: borrow may still be in use when destructor runs
--> $DIR/issue-45696-scribble-on-boxed-borrow.rs:83:5 --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:85:5
| |
LL | fn boxed_boxed_scribbled<'a>(s: Box<Box<Scribble<'a>>>) -> &'a mut u32 { LL | fn boxed_boxed_scribbled<'a>(s: Box<Box<Scribble<'a>>>) -> &'a mut u32 {
| -- lifetime `'a` defined here | -- lifetime `'a` defined here
@ -39,12 +37,11 @@ LL | &mut *(**s).0 //[nll]~ ERROR borrow may still be in use when destructor
LL | } LL | }
| - here, drop of `s` needs exclusive access to `*s.0`, because the type `Scribble<'_>` implements the `Drop` trait | - here, drop of `s` needs exclusive access to `*s.0`, because the type `Scribble<'_>` implements the `Drop` trait
| |
= warning: This error has been downgraded to a warning for backwards compatibility with previous releases. = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
It represents potential unsoundness in your code. = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
This warning will become a hard error in the future.
error: compilation successful error: compilation successful
--> $DIR/issue-45696-scribble-on-boxed-borrow.rs:89:1 --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:92:1
| |
LL | / fn main() { //[ast]~ ERROR compilation successful LL | / fn main() { //[ast]~ ERROR compilation successful
LL | | //[migrate]~^ ERROR compilation successful LL | | //[migrate]~^ ERROR compilation successful

View file

@ -10,7 +10,7 @@ LL | }
| - here, drop of `s` needs exclusive access to `*s.0`, because the type `Scribble<'_>` implements the `Drop` trait | - here, drop of `s` needs exclusive access to `*s.0`, because the type `Scribble<'_>` implements the `Drop` trait
error[E0713]: borrow may still be in use when destructor runs error[E0713]: borrow may still be in use when destructor runs
--> $DIR/issue-45696-scribble-on-boxed-borrow.rs:73:5 --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:74:5
| |
LL | fn boxed_scribbled<'a>(s: Box<Scribble<'a>>) -> &'a mut u32 { LL | fn boxed_scribbled<'a>(s: Box<Scribble<'a>>) -> &'a mut u32 {
| -- lifetime `'a` defined here | -- lifetime `'a` defined here
@ -21,7 +21,7 @@ LL | }
| - here, drop of `s` needs exclusive access to `*s.0`, because the type `Scribble<'_>` implements the `Drop` trait | - here, drop of `s` needs exclusive access to `*s.0`, because the type `Scribble<'_>` implements the `Drop` trait
error[E0713]: borrow may still be in use when destructor runs error[E0713]: borrow may still be in use when destructor runs
--> $DIR/issue-45696-scribble-on-boxed-borrow.rs:83:5 --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:85:5
| |
LL | fn boxed_boxed_scribbled<'a>(s: Box<Box<Scribble<'a>>>) -> &'a mut u32 { LL | fn boxed_boxed_scribbled<'a>(s: Box<Box<Scribble<'a>>>) -> &'a mut u32 {
| -- lifetime `'a` defined here | -- lifetime `'a` defined here

View file

@ -62,7 +62,8 @@ fn boxed_boxed_borrowed_scribble<'a>(s: Box<Box<&'a mut Scribble>>) -> &'a mut u
fn scribbled<'a>(s: Scribble<'a>) -> &'a mut u32 { fn scribbled<'a>(s: Scribble<'a>) -> &'a mut u32 {
&mut *s.0 //[nll]~ ERROR borrow may still be in use when destructor runs [E0713] &mut *s.0 //[nll]~ ERROR borrow may still be in use when destructor runs [E0713]
//[migrate]~^ WARNING borrow may still be in use when destructor runs [E0713] //[migrate]~^ WARNING borrow may still be in use when destructor runs [E0713]
//[migrate]~| WARNING This error has been downgraded to a warning for backwards compatibility //[migrate]~| WARNING this error has been downgraded to a warning for backwards compatibility
//[migrate]~| WARNING this represents potential undefined behavior in your code
} }
// This, by analogy to previous case, is *also* not okay. // This, by analogy to previous case, is *also* not okay.
@ -72,7 +73,8 @@ fn scribbled<'a>(s: Scribble<'a>) -> &'a mut u32 {
fn boxed_scribbled<'a>(s: Box<Scribble<'a>>) -> &'a mut u32 { fn boxed_scribbled<'a>(s: Box<Scribble<'a>>) -> &'a mut u32 {
&mut *(*s).0 //[nll]~ ERROR borrow may still be in use when destructor runs [E0713] &mut *(*s).0 //[nll]~ ERROR borrow may still be in use when destructor runs [E0713]
//[migrate]~^ WARNING borrow may still be in use when destructor runs [E0713] //[migrate]~^ WARNING borrow may still be in use when destructor runs [E0713]
//[migrate]~| WARNING This error has been downgraded to a warning for backwards compatibility //[migrate]~| WARNING this error has been downgraded to a warning for backwards compatibility
//[migrate]~| WARNING this represents potential undefined behavior in your code
} }
// This, by analogy to previous case, is *also* not okay. // This, by analogy to previous case, is *also* not okay.
@ -82,7 +84,8 @@ fn boxed_scribbled<'a>(s: Box<Scribble<'a>>) -> &'a mut u32 {
fn boxed_boxed_scribbled<'a>(s: Box<Box<Scribble<'a>>>) -> &'a mut u32 { fn boxed_boxed_scribbled<'a>(s: Box<Box<Scribble<'a>>>) -> &'a mut u32 {
&mut *(**s).0 //[nll]~ ERROR borrow may still be in use when destructor runs [E0713] &mut *(**s).0 //[nll]~ ERROR borrow may still be in use when destructor runs [E0713]
//[migrate]~^ WARNING borrow may still be in use when destructor runs [E0713] //[migrate]~^ WARNING borrow may still be in use when destructor runs [E0713]
//[migrate]~| WARNING This error has been downgraded to a warning for backwards compatibility //[migrate]~| WARNING this error has been downgraded to a warning for backwards compatibility
//[migrate]~| WARNING this represents potential undefined behavior in your code
} }
#[rustc_error] #[rustc_error]

View file

@ -10,9 +10,8 @@ LL | | }
| |
= note: `FnMut` closures only have access to their captured variables while they are executing... = note: `FnMut` closures only have access to their captured variables while they are executing...
= note: ...therefore, they cannot allow references to captured variables to escape = note: ...therefore, they cannot allow references to captured variables to escape
= warning: This error has been downgraded to a warning for backwards compatibility with previous releases. = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
It represents potential unsoundness in your code. = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
This warning will become a hard error in the future.
error: compilation successful error: compilation successful
--> $DIR/issue-49824.rs:18:1 --> $DIR/issue-49824.rs:18:1

View file

@ -0,0 +1,18 @@
// only-x86_64
const HUGE_SIZE: usize = !0usize / 8;
pub struct TooBigArray {
arr: [u8; HUGE_SIZE],
}
impl TooBigArray {
pub const fn new() -> Self {
TooBigArray { arr: [0x00; HUGE_SIZE], }
}
}
static MY_TOO_BIG_ARRAY_1: TooBigArray = TooBigArray::new();
static MY_TOO_BIG_ARRAY_2: [u8; HUGE_SIZE] = [0x00; HUGE_SIZE];
fn main() { }

View file

@ -0,0 +1,4 @@
error: the type `[u8; 2305843009213693951]` is too big for the current architecture
error: aborting due to previous error

View file

@ -8,9 +8,12 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
// compile-flags:-D bogus // compile-flags:-D bogus -D dead_cod
// error-pattern:unknown lint // error-pattern:unknown lint: `bogus`
// error-pattern:requested on the command line with `-D bogus` // error-pattern:requested on the command line with `-D bogus`
// error-pattern:unknown lint: `dead_cod`
// error-pattern:requested on the command line with `-D dead_cod`
// error-pattern:did you mean: `dead_code`
fn main() { } fn main() { }

View file

@ -2,6 +2,11 @@ error[E0602]: unknown lint: `bogus`
| |
= note: requested on the command line with `-D bogus` = note: requested on the command line with `-D bogus`
error: aborting due to previous error error[E0602]: unknown lint: `dead_cod`
|
= help: did you mean: `dead_code`
= note: requested on the command line with `-D dead_cod`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0602`. For more information about this error, try `rustc --explain E0602`.

View file

@ -8,6 +8,12 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
#![allow(not_a_real_lint)] //~ WARN unknown lint #![deny(unknown_lints)]
#![deny(unused)]
fn main() { let unused = (); } //~ ERROR unused variable #![allow(not_a_real_lint)] //~ ERROR unknown lint
#![deny(dead_cod)] //~ ERROR unknown lint
//~| HELP did you mean
//~| SUGGESTION dead_code
fn main() {}

View file

@ -1,23 +1,20 @@
warning: unknown lint: `not_a_real_lint` error: unknown lint: `not_a_real_lint`
--> $DIR/lint-unknown-lint.rs:11:10 --> $DIR/lint-unknown-lint.rs:13:10
| |
LL | #![allow(not_a_real_lint)] //~ WARN unknown lint LL | #![allow(not_a_real_lint)] //~ ERROR unknown lint
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^
| |
= note: #[warn(unknown_lints)] on by default
error: unused variable: `unused`
--> $DIR/lint-unknown-lint.rs:13:17
|
LL | fn main() { let unused = (); } //~ ERROR unused variable
| ^^^^^^ help: consider using `_unused` instead
|
note: lint level defined here note: lint level defined here
--> $DIR/lint-unknown-lint.rs:12:9 --> $DIR/lint-unknown-lint.rs:11:9
| |
LL | #![deny(unused)] LL | #![deny(unknown_lints)]
| ^^^^^^ | ^^^^^^^^^^^^^
= note: #[deny(unused_variables)] implied by #[deny(unused)]
error: aborting due to previous error error: unknown lint: `dead_cod`
--> $DIR/lint-unknown-lint.rs:15:9
|
LL | #![deny(dead_cod)] //~ ERROR unknown lint
| ^^^^^^^^ help: did you mean: `dead_code`
error: aborting due to 2 previous errors

View file

@ -10,11 +10,11 @@ warning: unknown lint: `DEAD_CODE`
--> $DIR/not_found.rs:18:8 --> $DIR/not_found.rs:18:8
| |
LL | #[warn(DEAD_CODE)] LL | #[warn(DEAD_CODE)]
| ^^^^^^^^^ help: lowercase the lint name: `dead_code` | ^^^^^^^^^ help: did you mean: `dead_code`
warning: unknown lint: `Warnings` warning: unknown lint: `Warnings`
--> $DIR/not_found.rs:20:8 --> $DIR/not_found.rs:20:8
| |
LL | #[deny(Warnings)] LL | #[deny(Warnings)]
| ^^^^^^^^ help: lowercase the lint name: `warnings` | ^^^^^^^^ help: did you mean: `warnings`

View file

@ -4,9 +4,8 @@ warning[E0507]: cannot move out of borrowed content
LL | (|| { let bar = foo; bar.take() })(); LL | (|| { let bar = foo; bar.take() })();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
| |
= warning: This error has been downgraded to a warning for backwards compatibility with previous releases. = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
It represents potential unsoundness in your code. = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
This warning will become a hard error in the future.
error: compilation successful error: compilation successful
--> $DIR/match-guards-always-borrow.rs:57:1 --> $DIR/match-guards-always-borrow.rs:57:1

View file

@ -21,7 +21,6 @@
#![allow(dead_code)] #![allow(dead_code)]
#![feature(start)] #![feature(start)]
#![feature(repr_packed)]
#[derive(Default)] #[derive(Default)]
#[repr(packed)] #[repr(packed)]

View file

@ -14,6 +14,11 @@
// ignore-emscripten // ignore-emscripten
// ignore-mips // ignore-mips
// ignore-mips64 // ignore-mips64
// ignore-powerpc
// ignore-powerpc64
// ignore-powerpc64le
// ignore-sparc
// ignore-sparc64
// gate-test-sse4a_target_feature // gate-test-sse4a_target_feature
// gate-test-powerpc_target_feature // gate-test-powerpc_target_feature
// gate-test-avx512_target_feature // gate-test-avx512_target_feature

View file

@ -1,5 +1,5 @@
error[E0658]: the target feature `avx512bw` is currently unstable (see issue #44839) error[E0658]: the target feature `avx512bw` is currently unstable (see issue #44839)
--> $DIR/target-feature-gate.rs:31:18 --> $DIR/target-feature-gate.rs:36:18
| |
LL | #[target_feature(enable = "avx512bw")] LL | #[target_feature(enable = "avx512bw")]
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^

View file

@ -18,9 +18,8 @@ LL | static C: &u32 = &A;
| | | |
| thread-local variables cannot be borrowed beyond the end of the function | thread-local variables cannot be borrowed beyond the end of the function
| |
= warning: This error has been downgraded to a warning for backwards compatibility with previous releases. = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
It represents potential unsoundness in your code. = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
This warning will become a hard error in the future.
error[E0625]: thread-local statics cannot be accessed at compile-time error[E0625]: thread-local statics cannot be accessed at compile-time
--> $DIR/thread-local-in-ctfe.rs:22:16 --> $DIR/thread-local-in-ctfe.rs:22:16
@ -42,9 +41,8 @@ LL | const E: &u32 = &A;
| | | |
| thread-local variables cannot be borrowed beyond the end of the function | thread-local variables cannot be borrowed beyond the end of the function
| |
= warning: This error has been downgraded to a warning for backwards compatibility with previous releases. = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
It represents potential unsoundness in your code. = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
This warning will become a hard error in the future.
error[E0625]: thread-local statics cannot be accessed at compile-time error[E0625]: thread-local statics cannot be accessed at compile-time
--> $DIR/thread-local-in-ctfe.rs:29:5 --> $DIR/thread-local-in-ctfe.rs:29:5

View file

@ -205,7 +205,7 @@ impl EarlyProps {
fn ignore_lldb(config: &Config, line: &str) -> bool { fn ignore_lldb(config: &Config, line: &str) -> bool {
if let Some(ref actual_version) = config.lldb_version { if let Some(ref actual_version) = config.lldb_version {
if line.starts_with("min-lldb-version") { if line.starts_with("min-lldb-version") {
let min_version = line.trim_right() let min_version = line.trim_end()
.rsplit(' ') .rsplit(' ')
.next() .next()
.expect("Malformed lldb version directive"); .expect("Malformed lldb version directive");
@ -228,7 +228,7 @@ impl EarlyProps {
} }
if let Some(ref actual_version) = config.llvm_version { if let Some(ref actual_version) = config.llvm_version {
if line.starts_with("min-llvm-version") { if line.starts_with("min-llvm-version") {
let min_version = line.trim_right() let min_version = line.trim_end()
.rsplit(' ') .rsplit(' ')
.next() .next()
.expect("Malformed llvm version directive"); .expect("Malformed llvm version directive");
@ -236,7 +236,7 @@ impl EarlyProps {
// version // version
&actual_version[..] < min_version &actual_version[..] < min_version
} else if line.starts_with("min-system-llvm-version") { } else if line.starts_with("min-system-llvm-version") {
let min_version = line.trim_right() let min_version = line.trim_end()
.rsplit(' ') .rsplit(' ')
.next() .next()
.expect("Malformed llvm version directive"); .expect("Malformed llvm version directive");
@ -573,14 +573,14 @@ fn iter_header(testfile: &Path, cfg: Option<&str>, it: &mut dyn FnMut(&str)) {
None => false, None => false,
}; };
if matches { if matches {
it(ln[(close_brace + 1)..].trim_left()); it(ln[(close_brace + 1)..].trim_start());
} }
} else { } else {
panic!("malformed condition directive: expected `{}foo]`, found `{}`", panic!("malformed condition directive: expected `{}foo]`, found `{}`",
comment_with_brace, ln) comment_with_brace, ln)
} }
} else if ln.starts_with(comment) { } else if ln.starts_with(comment) {
it(ln[comment.len() ..].trim_left()); it(ln[comment.len() ..].trim_start());
} }
} }
return; return;

View file

@ -1082,7 +1082,7 @@ impl<'test> TestCx<'test> {
match line { match line {
Ok(line) => { Ok(line) => {
let line = if line.starts_with("//") { let line = if line.starts_with("//") {
line[2..].trim_left() line[2..].trim_start()
} else { } else {
line.as_str() line.as_str()
}; };
@ -2146,8 +2146,8 @@ impl<'test> TestCx<'test> {
.lines() .lines()
.enumerate() .enumerate()
.filter_map(|(line_nb, line)| { .filter_map(|(line_nb, line)| {
if (line.trim_left().starts_with("pub mod ") if (line.trim_start().starts_with("pub mod ")
|| line.trim_left().starts_with("mod ")) || line.trim_start().starts_with("mod "))
&& line.ends_with(';') && line.ends_with(';')
{ {
if let Some(ref mut other_files) = other_files { if let Some(ref mut other_files) = other_files {
@ -2156,7 +2156,7 @@ impl<'test> TestCx<'test> {
None None
} else { } else {
let sline = line.split("///").last().unwrap_or(""); let sline = line.split("///").last().unwrap_or("");
let line = sline.trim_left(); let line = sline.trim_start();
if line.starts_with("```") { if line.starts_with("```") {
if ignore { if ignore {
ignore = false; ignore = false;
@ -3287,7 +3287,7 @@ fn normalize_mir_line(line: &str) -> String {
fn nocomment_mir_line(line: &str) -> &str { fn nocomment_mir_line(line: &str) -> &str {
if let Some(idx) = line.find("//") { if let Some(idx) = line.find("//") {
let (l, _) = line.split_at(idx); let (l, _) = line.split_at(idx);
l.trim_right() l.trim_end()
} else { } else {
line line
} }

View file

@ -26,7 +26,10 @@ function getNextStep(content, pos, stop) {
return pos; return pos;
} }
// Stupid function extractor based on indent. // Stupid function extractor based on indent. Doesn't support block
// comments. If someone puts a ' or an " in a block comment this
// will blow up. Template strings are not tested and might also be
// broken.
function extractFunction(content, functionName) { function extractFunction(content, functionName) {
var indent = 0; var indent = 0;
var splitter = "function " + functionName + "("; var splitter = "function " + functionName + "(";
@ -51,7 +54,14 @@ function extractFunction(content, functionName) {
continue; continue;
} }
while (pos < content.length) { while (pos < content.length) {
if (content[pos] === '"' || content[pos] === "'") { // Eat single-line comments
if (content[pos] === '/' && pos > 0 && content[pos-1] === '/') {
do {
pos += 1;
} while (pos < content.length && content[pos] !== '\n');
// Eat quoted strings
} else if (content[pos] === '"' || content[pos] === "'" || content[pos] === "`") {
var stop = content[pos]; var stop = content[pos];
var is_escaped = false; var is_escaped = false;
do { do {
@ -62,6 +72,8 @@ function extractFunction(content, functionName) {
} }
} while (pos < content.length && } while (pos < content.length &&
(content[pos] !== stop || content[pos - 1] === '\\')); (content[pos] !== stop || content[pos - 1] === '\\'));
// Otherwise, check for indent
} else if (content[pos] === '{') { } else if (content[pos] === '{') {
indent += 1; indent += 1;
} else if (content[pos] === '}') { } else if (content[pos] === '}') {