Auto merge of #59050 - Centril:rollup, r=Centril

Rollup of 13 pull requests

Successful merges:

 - #58518 (Use early unwraps instead of bubbling up errors just to unwrap in the end)
 - #58626 (rustdoc: add option to calculate "documentation coverage")
 - #58629 (rust-lldb: fix crash when printing empty string)
 - #58660 (MaybeUninit: add read_initialized, add examples)
 - #58670 (fixes rust-lang#52482)
 - #58676 (look for python2 symlinks before bootstrap python)
 - #58679 (Refactor passes and pass execution to be more parallel)
 - #58750 (Make `Unique::as_ptr`, `NonNull::dangling` and `NonNull::cast` const)
 - #58762 (Mention `unwind(aborts)` in diagnostics for `#[unwind]`)
 - #58924 (Add as_slice() to slice::IterMut and vec::Drain)
 - #58990 (Actually publish miri in the manifest)
 - #59018 (std: Delete a by-definition spuriously failing test)
 - #59045 (Expose new_sub_parser_from_file)

Failed merges:

r? @ghost
This commit is contained in:
bors 2019-03-09 18:22:05 +00:00
commit 26b4cb4848
86 changed files with 1399 additions and 395 deletions

View File

@ -164,6 +164,9 @@
# Python interpreter to use for various tasks throughout the build, notably
# rustdoc tests, the lldb python interpreter, and some dist bits and pieces.
# Note that Python 2 is currently required.
#
# Defaults to python2.7, then python2. If neither executable can be found, then
# it defaults to the Python interpreter used to execute x.py.
#python = "python2.7"
# Force Cargo to check that Cargo.lock describes the precise dependency

View File

@ -34,15 +34,17 @@ impl Finder {
fn maybe_have<S: AsRef<OsStr>>(&mut self, cmd: S) -> Option<PathBuf> {
let cmd: OsString = cmd.as_ref().into();
let path = self.path.clone();
let path = &self.path;
self.cache.entry(cmd.clone()).or_insert_with(|| {
for path in env::split_paths(&path) {
for path in env::split_paths(path) {
let target = path.join(&cmd);
let mut cmd_alt = cmd.clone();
cmd_alt.push(".exe");
if target.is_file() || // some/path/git
target.with_extension("exe").exists() || // some/path/git.exe
target.join(&cmd_alt).exists() { // some/path/git/git.exe
let mut cmd_exe = cmd.clone();
cmd_exe.push(".exe");
if target.is_file() // some/path/git
|| path.join(&cmd_exe).exists() // some/path/git.exe
|| target.join(&cmd_exe).exists() // some/path/git/git.exe
{
return Some(target);
}
}
@ -107,9 +109,9 @@ pub fn check(build: &mut Build) {
}
build.config.python = build.config.python.take().map(|p| cmd_finder.must_have(p))
.or_else(|| env::var_os("BOOTSTRAP_PYTHON").map(PathBuf::from)) // set by bootstrap.py
.or_else(|| cmd_finder.maybe_have("python2.7"))
.or_else(|| cmd_finder.maybe_have("python2"))
.or_else(|| env::var_os("BOOTSTRAP_PYTHON").map(PathBuf::from)) // set by bootstrap.py
.or_else(|| Some(cmd_finder.must_have("python")));
build.config.nodejs = build.config.nodejs.take().map(|p| cmd_finder.must_have(p))

View File

@ -53,7 +53,7 @@ For example, in the following code:
```rust
/// Does the thing.
pub fn do_the_thing(_: SomeType) {
println!("Let's do the thing!");
println!("Let's do the thing!");
}
/// Token you use to [`do_the_thing`].
@ -66,15 +66,15 @@ target out also works:
```rust
pub mod some_module {
/// Token you use to do the thing.
pub struct SomeStruct;
/// Token you use to do the thing.
pub struct SomeStruct;
}
/// Does the thing. Requires one [`SomeStruct`] for the thing to work.
///
/// [`SomeStruct`]: some_module::SomeStruct
pub fn do_the_thing(_: some_module::SomeStruct) {
println!("Let's do the thing!");
println!("Let's do the thing!");
}
```
@ -428,3 +428,30 @@ $ rustdoc src/lib.rs --test -Z unstable-options --persist-doctests target/rustdo
This flag allows you to keep doctest executables around after they're compiled or run.
Usually, rustdoc will immediately discard a compiled doctest after it's been tested, but
with this option, you can keep those binaries around for farther testing.
### `--show-coverage`: calculate the percentage of items with documentation
Using this flag looks like this:
```bash
$ rustdoc src/lib.rs -Z unstable-options --show-coverage
```
If you want to determine how many items in your crate are documented, pass this flag to rustdoc.
When it receives this flag, it will count the public items in your crate that have documentation,
and print out the counts and a percentage instead of generating docs.
Some methodology notes about what rustdoc counts in this metric:
* Rustdoc will only count items from your crate (i.e. items re-exported from other crates don't
count).
* Docs written directly onto inherent impl blocks are not counted, even though their doc comments
are displayed, because the common pattern in Rust code is to write all inherent methods into the
same impl block.
* Items in a trait implementation are not counted, as those impls will inherit any docs from the
trait itself.
* By default, only public items are counted. To count private items as well, pass
`--document-private-items` at the same time.
Public items that are not documented can be seen with the built-in `missing_docs` lint. Private
items that are not documented can be seen with Clippy's `missing_docs_in_private_items` lint.

View File

@ -290,6 +290,8 @@ def print_array_of_values(array_name, data_ptr_val, length, internal_dict):
def read_utf8_string(ptr_val, byte_count):
if byte_count == 0:
return '""'
error = lldb.SBError()
process = ptr_val.get_wrapped_value().GetProcess()
data = process.ReadMemory(ptr_val.as_integer(), byte_count, error)

View File

@ -2468,6 +2468,25 @@ impl<T: fmt::Debug> fmt::Debug for Drain<'_, T> {
}
}
impl<'a, T> Drain<'a, T> {
/// Returns the remaining items of this iterator as a slice.
///
/// # Examples
///
/// ```
/// # #![feature(vec_drain_as_slice)]
/// let mut vec = vec!['a', 'b', 'c'];
/// let mut drain = vec.drain(..);
/// assert_eq!(drain.as_slice(), &['a', 'b', 'c']);
/// let _ = drain.next().unwrap();
/// assert_eq!(drain.as_slice(), &['b', 'c']);
/// ```
#[unstable(feature = "vec_drain_as_slice", reason = "recently added", issue = "58957")]
pub fn as_slice(&self) -> &[T] {
self.iter.as_slice()
}
}
#[stable(feature = "drain", since = "1.6.0")]
unsafe impl<T: Sync> Sync for Drain<'_, T> {}
#[stable(feature = "drain", since = "1.6.0")]

View File

@ -15,6 +15,7 @@ fn float_to_decimal_common_exact<T>(fmt: &mut Formatter, num: &T,
// FIXME(#53491): Technically, this is calling `get_mut` on an uninitialized
// `MaybeUninit` (here and elsewhere in this file). Revisit this once
// we decided whether that is valid or not.
// Using `freeze` is *not enough*; `flt2dec::Part` is an enum!
let formatted = flt2dec::to_exact_fixed_str(flt2dec::strategy::grisu::format_exact,
*num, sign, precision,
false, buf.get_mut(), parts.get_mut());
@ -33,6 +34,7 @@ fn float_to_decimal_common_shortest<T>(fmt: &mut Formatter, num: &T,
// enough for f32 and f64
let mut buf = MaybeUninit::<[u8; flt2dec::MAX_SIG_DIGITS]>::uninitialized();
let mut parts = MaybeUninit::<[flt2dec::Part; 4]>::uninitialized();
// FIXME(#53491)
let formatted = flt2dec::to_shortest_str(flt2dec::strategy::grisu::format_shortest, *num,
sign, precision, false, buf.get_mut(),
parts.get_mut());
@ -71,6 +73,7 @@ fn float_to_exponential_common_exact<T>(fmt: &mut Formatter, num: &T,
unsafe {
let mut buf = MaybeUninit::<[u8; 1024]>::uninitialized(); // enough for f32 and f64
let mut parts = MaybeUninit::<[flt2dec::Part; 6]>::uninitialized();
// FIXME(#53491)
let formatted = flt2dec::to_exact_exp_str(flt2dec::strategy::grisu::format_exact,
*num, sign, precision,
upper, buf.get_mut(), parts.get_mut());
@ -90,6 +93,7 @@ fn float_to_exponential_common_shortest<T>(fmt: &mut Formatter,
// enough for f32 and f64
let mut buf = MaybeUninit::<[u8; flt2dec::MAX_SIG_DIGITS]>::uninitialized();
let mut parts = MaybeUninit::<[flt2dec::Part; 6]>::uninitialized();
// FIXME(#53491)
let formatted = flt2dec::to_shortest_exp_str(flt2dec::strategy::grisu::format_shortest,
*num, sign, (0, 0), upper,
buf.get_mut(), parts.get_mut());

View File

@ -1043,7 +1043,7 @@ impl<T: ?Sized> DerefMut for ManuallyDrop<T> {
}
}
/// A newtype to construct uninitialized instances of `T`.
/// A wrapper to construct uninitialized instances of `T`.
///
/// The compiler, in general, assumes that variables are properly initialized
/// at their respective type. For example, a variable of reference type must
@ -1057,33 +1057,43 @@ impl<T: ?Sized> DerefMut for ManuallyDrop<T> {
/// use std::mem::{self, MaybeUninit};
///
/// let x: &i32 = unsafe { mem::zeroed() }; // undefined behavior!
/// // equivalent code with `MaybeUninit`
/// // The equivalent code with `MaybeUninit<&i32>`:
/// let x: &i32 = unsafe { MaybeUninit::zeroed().into_initialized() }; // undefined behavior!
/// ```
///
/// This is exploited by the compiler for various optimizations, such as eliding
/// run-time checks and optimizing `enum` layout.
///
/// Not initializing memory at all (instead of zero-initializing it) causes the same
/// issue: after all, the initial value of the variable might just happen to be
/// one that violates the invariant. Moreover, uninitialized memory is special
/// in that the compiler knows that it does not have a fixed value. This makes
/// it undefined behavior to have uninitialized data in a variable even if that
/// variable has otherwise no restrictions about which values are valid:
/// Similarly, entirely uninitialized memory may have any content, while a `bool` must
/// always be `true` or `false`. Hence, creating an uninitialized `bool` is undefined behavior:
///
/// ```rust,no_run
/// #![feature(maybe_uninit)]
/// use std::mem::{self, MaybeUninit};
///
/// let b: bool = unsafe { mem::uninitialized() }; // undefined behavior!
/// // The equivalent code with `MaybeUninit<bool>`:
/// let b: bool = unsafe { MaybeUninit::uninitialized().into_initialized() }; // undefined behavior!
/// ```
///
/// Moreover, uninitialized memory is special in that the compiler knows that
/// it does not have a fixed value. This makes it undefined behavior to have
/// uninitialized data in a variable even if that variable has an integer type,
/// which otherwise can hold any bit pattern:
///
/// ```rust,no_run
/// #![feature(maybe_uninit)]
/// use std::mem::{self, MaybeUninit};
///
/// let x: i32 = unsafe { mem::uninitialized() }; // undefined behavior!
/// // equivalent code with `MaybeUninit`
/// // The equivalent code with `MaybeUninit<i32>`:
/// let x: i32 = unsafe { MaybeUninit::uninitialized().into_initialized() }; // undefined behavior!
/// ```
/// (Notice that the rules around uninitialized integers are not finalized yet, but
/// until they are, it is advisable to avoid them.)
///
/// `MaybeUninit` serves to enable unsafe code to deal with uninitialized data:
/// it is a signal to the compiler indicating that the data here might *not*
/// `MaybeUninit<T>` serves to enable unsafe code to deal with uninitialized data.
/// It is a signal to the compiler indicating that the data here might *not*
/// be initialized:
///
/// ```rust
@ -1091,7 +1101,7 @@ impl<T: ?Sized> DerefMut for ManuallyDrop<T> {
/// use std::mem::MaybeUninit;
///
/// // Create an explicitly uninitialized reference. The compiler knows that data inside
/// // a `MaybeUninit` may be invalid, and hence this is not UB:
/// // a `MaybeUninit<T>` may be invalid, and hence this is not UB:
/// let mut x = MaybeUninit::<&i32>::uninitialized();
/// // Set it to a valid value.
/// x.set(&0);
@ -1100,20 +1110,30 @@ impl<T: ?Sized> DerefMut for ManuallyDrop<T> {
/// let x = unsafe { x.into_initialized() };
/// ```
///
/// The compiler then knows to not optimize this code.
/// The compiler then knows to not make any incorrect assumptions or optimizations on this code.
// FIXME before stabilizing, explain how to initialize a struct field-by-field.
#[allow(missing_debug_implementations)]
#[unstable(feature = "maybe_uninit", issue = "53491")]
// NOTE after stabilizing `MaybeUninit` proceed to deprecate `mem::{uninitialized,zeroed}`
#[derive(Copy)]
// NOTE after stabilizing `MaybeUninit` proceed to deprecate `mem::uninitialized`.
pub union MaybeUninit<T> {
uninit: (),
value: ManuallyDrop<T>,
}
#[unstable(feature = "maybe_uninit", issue = "53491")]
impl<T: Copy> Clone for MaybeUninit<T> {
#[inline(always)]
fn clone(&self) -> Self {
// Not calling T::clone(), we cannot know if we are initialized enough for that.
*self
}
}
impl<T> MaybeUninit<T> {
/// Create a new `MaybeUninit` initialized with the given value.
/// Create a new `MaybeUninit<T>` initialized with the given value.
///
/// Note that dropping a `MaybeUninit` will never call `T`'s drop code.
/// Note that dropping a `MaybeUninit<T>` will never call `T`'s drop code.
/// It is your responsibility to make sure `T` gets dropped if it got initialized.
#[unstable(feature = "maybe_uninit", issue = "53491")]
#[inline(always)]
@ -1121,9 +1141,9 @@ impl<T> MaybeUninit<T> {
MaybeUninit { value: ManuallyDrop::new(val) }
}
/// Creates a new `MaybeUninit` in an uninitialized state.
/// Creates a new `MaybeUninit<T>` in an uninitialized state.
///
/// Note that dropping a `MaybeUninit` will never call `T`'s drop code.
/// Note that dropping a `MaybeUninit<T>` will never call `T`'s drop code.
/// It is your responsibility to make sure `T` gets dropped if it got initialized.
#[unstable(feature = "maybe_uninit", issue = "53491")]
#[inline(always)]
@ -1131,14 +1151,43 @@ impl<T> MaybeUninit<T> {
MaybeUninit { uninit: () }
}
/// Creates a new `MaybeUninit` in an uninitialized state, with the memory being
/// Creates a new `MaybeUninit<T>` in an uninitialized state, with the memory being
/// filled with `0` bytes. It depends on `T` whether that already makes for
/// proper initialization. For example, `MaybeUninit<usize>::zeroed()` is initialized,
/// but `MaybeUninit<&'static i32>::zeroed()` is not because references must not
/// be null.
///
/// Note that dropping a `MaybeUninit` will never call `T`'s drop code.
/// Note that dropping a `MaybeUninit<T>` will never call `T`'s drop code.
/// It is your responsibility to make sure `T` gets dropped if it got initialized.
///
/// # Example
///
/// Correct usage of this function: initializing a struct with zero, where all
/// fields of the struct can hold the bit-pattern 0 as a valid value.
///
/// ```rust
/// #![feature(maybe_uninit)]
/// use std::mem::MaybeUninit;
///
/// let x = MaybeUninit::<(u8, bool)>::zeroed();
/// let x = unsafe { x.into_initialized() };
/// assert_eq!(x, (0, false));
/// ```
///
/// *Incorrect* usage of this function: initializing a struct with zero, where some fields
/// cannot hold 0 as a valid value.
///
/// ```rust,no_run
/// #![feature(maybe_uninit)]
/// use std::mem::MaybeUninit;
///
/// enum NotZero { One = 1, Two = 2 };
///
/// let x = MaybeUninit::<(u8, NotZero)>::zeroed();
/// let x = unsafe { x.into_initialized() };
/// // Inside a pair, we create a `NotZero` that does not have a valid discriminant.
/// // This is undefined behavior.
/// ```
#[unstable(feature = "maybe_uninit", issue = "53491")]
#[inline]
pub fn zeroed() -> MaybeUninit<T> {
@ -1149,9 +1198,10 @@ impl<T> MaybeUninit<T> {
u
}
/// Sets the value of the `MaybeUninit`. This overwrites any previous value without dropping it.
/// For your convenience, this also returns a mutable reference to the (now safely initialized)
/// contents of `self`.
/// Sets the value of the `MaybeUninit<T>`. This overwrites any previous value
/// without dropping it, so be careful not to use this twice unless you want to
/// skip running the destructor. For your convenience, this also returns a mutable
/// reference to the (now safely initialized) contents of `self`.
#[unstable(feature = "maybe_uninit", issue = "53491")]
#[inline(always)]
pub fn set(&mut self, val: T) -> &mut T {
@ -1162,7 +1212,35 @@ impl<T> MaybeUninit<T> {
}
/// Gets a pointer to the contained value. Reading from this pointer or turning it
/// into a reference will be undefined behavior unless the `MaybeUninit` is initialized.
/// into a reference is undefined behavior unless the `MaybeUninit<T>` is initialized.
///
/// # Examples
///
/// Correct usage of this method:
///
/// ```rust
/// #![feature(maybe_uninit)]
/// use std::mem::MaybeUninit;
///
/// let mut x = MaybeUninit::<Vec<u32>>::uninitialized();
/// unsafe { x.as_mut_ptr().write(vec![0,1,2]); }
/// // Create a reference into the `MaybeUninit<T>`. This is okay because we initialized it.
/// let x_vec = unsafe { &*x.as_ptr() };
/// assert_eq!(x_vec.len(), 3);
/// ```
///
/// *Incorrect* usage of this method:
///
/// ```rust,no_run
/// #![feature(maybe_uninit)]
/// use std::mem::MaybeUninit;
///
/// let x = MaybeUninit::<Vec<u32>>::uninitialized();
/// let x_vec = unsafe { &*x.as_ptr() };
/// // We have created a reference to an uninitialized vector! This is undefined behavior.
/// ```
/// (Notice that the rules around references to uninitialized data are not finalized yet, but
/// until they are, it is advisable to avoid them.)
#[unstable(feature = "maybe_uninit", issue = "53491")]
#[inline(always)]
pub fn as_ptr(&self) -> *const T {
@ -1170,22 +1248,77 @@ impl<T> MaybeUninit<T> {
}
/// Gets a mutable pointer to the contained value. Reading from this pointer or turning it
/// into a reference will be undefined behavior unless the `MaybeUninit` is initialized.
/// into a reference is undefined behavior unless the `MaybeUninit<T>` is initialized.
///
/// # Examples
///
/// Correct usage of this method:
///
/// ```rust
/// #![feature(maybe_uninit)]
/// use std::mem::MaybeUninit;
///
/// let mut x = MaybeUninit::<Vec<u32>>::uninitialized();
/// unsafe { x.as_mut_ptr().write(vec![0,1,2]); }
/// // Create a reference into the `MaybeUninit<Vec<u32>>`.
/// // This is okay because we initialized it.
/// let x_vec = unsafe { &mut *x.as_mut_ptr() };
/// x_vec.push(3);
/// assert_eq!(x_vec.len(), 4);
/// ```
///
/// *Incorrect* usage of this method:
///
/// ```rust,no_run
/// #![feature(maybe_uninit)]
/// use std::mem::MaybeUninit;
///
/// let mut x = MaybeUninit::<Vec<u32>>::uninitialized();
/// let x_vec = unsafe { &mut *x.as_mut_ptr() };
/// // We have created a reference to an uninitialized vector! This is undefined behavior.
/// ```
/// (Notice that the rules around references to uninitialized data are not finalized yet, but
/// until they are, it is advisable to avoid them.)
#[unstable(feature = "maybe_uninit", issue = "53491")]
#[inline(always)]
pub fn as_mut_ptr(&mut self) -> *mut T {
unsafe { &mut *self.value as *mut T }
}
/// Extracts the value from the `MaybeUninit` container. This is a great way
/// Extracts the value from the `MaybeUninit<T>` container. This is a great way
/// to ensure that the data will get dropped, because the resulting `T` is
/// subject to the usual drop handling.
///
/// # Safety
///
/// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized
/// It is up to the caller to guarantee that the `MaybeUninit<T>` really is in an initialized
/// state. Calling this when the content is not yet fully initialized causes undefined
/// behavior.
///
/// # Examples
///
/// Correct usage of this method:
///
/// ```rust
/// #![feature(maybe_uninit)]
/// use std::mem::MaybeUninit;
///
/// let mut x = MaybeUninit::<bool>::uninitialized();
/// unsafe { x.as_mut_ptr().write(true); }
/// let x_init = unsafe { x.into_initialized() };
/// assert_eq!(x_init, true);
/// ```
///
/// *Incorrect* usage of this method:
///
/// ```rust,no_run
/// #![feature(maybe_uninit)]
/// use std::mem::MaybeUninit;
///
/// let x = MaybeUninit::<Vec<u32>>::uninitialized();
/// let x_init = unsafe { x.into_initialized() };
/// // `x` had not been initialized yet, so this last line caused undefined behavior.
/// ```
#[unstable(feature = "maybe_uninit", issue = "53491")]
#[inline(always)]
pub unsafe fn into_initialized(self) -> T {
@ -1193,11 +1326,73 @@ impl<T> MaybeUninit<T> {
ManuallyDrop::into_inner(self.value)
}
/// Reads the value from the `MaybeUninit<T>` container. The resulting `T` is subject
/// to the usual drop handling.
///
/// Whenever possible, it is preferrable to use [`into_initialized`] instead, which
/// prevents duplicating the content of the `MaybeUninit<T>`.
///
/// # Safety
///
/// It is up to the caller to guarantee that the `MaybeUninit<T>` really is in an initialized
/// state. Calling this when the content is not yet fully initialized causes undefined
/// behavior.
///
/// Moreover, this leaves a copy of the same data behind in the `MaybeUninit<T>`. When using
/// multiple copies of the data (by calling `read_initialized` multiple times, or first
/// calling `read_initialized` and then [`into_initialized`]), it is your responsibility
/// to ensure that that data may indeed be duplicated.
///
/// [`into_initialized`]: #method.into_initialized
///
/// # Examples
///
/// Correct usage of this method:
///
/// ```rust
/// #![feature(maybe_uninit)]
/// use std::mem::MaybeUninit;
///
/// let mut x = MaybeUninit::<u32>::uninitialized();
/// x.set(13);
/// let x1 = unsafe { x.read_initialized() };
/// // `u32` is `Copy`, so we may read multiple times.
/// let x2 = unsafe { x.read_initialized() };
/// assert_eq!(x1, x2);
///
/// let mut x = MaybeUninit::<Option<Vec<u32>>>::uninitialized();
/// x.set(None);
/// let x1 = unsafe { x.read_initialized() };
/// // Duplicating a `None` value is okay, so we may read multiple times.
/// let x2 = unsafe { x.read_initialized() };
/// assert_eq!(x1, x2);
/// ```
///
/// *Incorrect* usage of this method:
///
/// ```rust,no_run
/// #![feature(maybe_uninit)]
/// use std::mem::MaybeUninit;
///
/// let mut x = MaybeUninit::<Option<Vec<u32>>>::uninitialized();
/// x.set(Some(vec![0,1,2]));
/// let x1 = unsafe { x.read_initialized() };
/// let x2 = unsafe { x.read_initialized() };
/// // We now created two copies of the same vector, leading to a double-free when
/// // they both get dropped!
/// ```
#[unstable(feature = "maybe_uninit", issue = "53491")]
#[inline(always)]
pub unsafe fn read_initialized(&self) -> T {
intrinsics::panic_if_uninhabited::<T>();
self.as_ptr().read()
}
/// Gets a reference to the contained value.
///
/// # Safety
///
/// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized
/// It is up to the caller to guarantee that the `MaybeUninit<T>` really is in an initialized
/// state. Calling this when the content is not yet fully initialized causes undefined
/// behavior.
#[unstable(feature = "maybe_uninit_ref", issue = "53491")]
@ -1210,7 +1405,7 @@ impl<T> MaybeUninit<T> {
///
/// # Safety
///
/// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized
/// It is up to the caller to guarantee that the `MaybeUninit<T>` really is in an initialized
/// state. Calling this when the content is not yet fully initialized causes undefined
/// behavior.
// FIXME(#53491): We currently rely on the above being incorrect, i.e., we have references

View File

@ -301,7 +301,7 @@ pub unsafe fn swap<T>(x: *mut T, y: *mut T) {
// Perform the swap
copy_nonoverlapping(x, tmp.as_mut_ptr(), 1);
copy(y, x, 1); // `x` and `y` may overlap
copy_nonoverlapping(tmp.get_ref(), y, 1);
copy_nonoverlapping(tmp.as_ptr(), y, 1);
}
/// Swaps `count * size_of::<T>()` bytes between the two regions of memory
@ -2790,7 +2790,7 @@ impl<T: ?Sized> Unique<T> {
}
/// Acquires the underlying `*mut` pointer.
pub fn as_ptr(self) -> *mut T {
pub const fn as_ptr(self) -> *mut T {
self.pointer as *mut T
}
@ -2903,7 +2903,8 @@ impl<T: Sized> NonNull<T> {
/// some other means.
#[stable(feature = "nonnull", since = "1.25.0")]
#[inline]
pub fn dangling() -> Self {
#[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_ptr_nonnull"))]
pub const fn dangling() -> Self {
unsafe {
let ptr = mem::align_of::<T>() as *mut T;
NonNull::new_unchecked(ptr)
@ -2966,7 +2967,8 @@ impl<T: ?Sized> NonNull<T> {
/// Cast to a pointer of another type
#[stable(feature = "nonnull_cast", since = "1.27.0")]
#[inline]
pub fn cast<U>(self) -> NonNull<U> {
#[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_ptr_nonnull"))]
pub const fn cast<U>(self) -> NonNull<U> {
unsafe {
NonNull::new_unchecked(self.as_ptr() as *mut U)
}

View File

@ -3288,6 +3288,34 @@ impl<'a, T> IterMut<'a, T> {
pub fn into_slice(self) -> &'a mut [T] {
unsafe { from_raw_parts_mut(self.ptr, len!(self)) }
}
/// Views the underlying data as a subslice of the original data.
///
/// To avoid creating `&mut [T]` references that alias, the returned slice
/// borrows its lifetime from the iterator the method is applied on.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// # #![feature(slice_iter_mut_as_slice)]
/// let mut slice: &mut [usize] = &mut [1, 2, 3];
///
/// // First, we get the iterator:
/// let mut iter = slice.iter_mut();
/// // So if we check what the `as_slice` method returns here, we have "[1, 2, 3]":
/// assert_eq!(iter.as_slice(), &[1, 2, 3]);
///
/// // Next, we move to the second element of the slice:
/// iter.next();
/// // Now `as_slice` returns "[2, 3]":
/// assert_eq!(iter.as_slice(), &[2, 3]);
/// ```
#[unstable(feature = "slice_iter_mut_as_slice", reason = "recently added", issue = "58957")]
pub fn as_slice(&self) -> &[T] {
self.make_slice()
}
}
iterator!{struct IterMut -> *mut T, &'a mut T, mut, {mut}, {}}

View File

@ -456,6 +456,7 @@ define_dep_nodes!( <'tcx>
[eval_always] CoherenceInherentImplOverlapCheck,
[] CoherenceCheckTrait(DefId),
[eval_always] PrivacyAccessLevels(CrateNum),
[eval_always] CheckPrivateInPublic(CrateNum),
[eval_always] Analysis(CrateNum),
// Represents the MIR for a fn; also used as the task node for

View File

@ -344,12 +344,6 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckAttrVisitor<'a, 'tcx> {
}
}
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
for &module in tcx.hir().krate().modules.keys() {
tcx.ensure().check_mod_attrs(tcx.hir().local_def_id(module));
}
}
fn is_c_like_enum(item: &hir::Item) -> bool {
if let hir::ItemKind::Enum(ref def, _) = item.node {
for variant in &def.variants {

View File

@ -30,7 +30,7 @@ use syntax::util::parser::ExprPrecedence;
use crate::ty::AdtKind;
use crate::ty::query::Providers;
use rustc_data_structures::sync::{ParallelIterator, par_iter, Send, Sync};
use rustc_data_structures::sync::{par_for_each_in, Send, Sync};
use rustc_data_structures::thin_vec::ThinVec;
use rustc_macros::HashStable;
@ -779,15 +779,15 @@ impl Crate {
where V: itemlikevisit::ParItemLikeVisitor<'hir> + Sync + Send
{
parallel!({
par_iter(&self.items).for_each(|(_, item)| {
par_for_each_in(&self.items, |(_, item)| {
visitor.visit_item(item);
});
}, {
par_iter(&self.trait_items).for_each(|(_, trait_item)| {
par_for_each_in(&self.trait_items, |(_, trait_item)| {
visitor.visit_trait_item(trait_item);
});
}, {
par_iter(&self.impl_items).for_each(|(_, impl_item)| {
par_for_each_in(&self.impl_items, |(_, impl_item)| {
visitor.visit_impl_item(impl_item);
});
});

View File

@ -10,12 +10,6 @@ use syntax_pos::Span;
use crate::hir::intravisit::{self, Visitor, NestedVisitorMap};
use crate::hir;
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
for &module in tcx.hir().krate().modules.keys() {
tcx.ensure().check_mod_intrinsics(tcx.hir().local_def_id(module));
}
}
fn check_mod_intrinsics<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
tcx.hir().visit_item_likes_in_module(
module_def_id,

View File

@ -185,12 +185,6 @@ fn check_mod_liveness<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
tcx.hir().visit_item_likes_in_module(module_def_id, &mut IrMaps::new(tcx).as_deep_visitor());
}
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
for &module in tcx.hir().krate().modules.keys() {
tcx.ensure().check_mod_liveness(tcx.hir().local_def_id(module));
}
}
pub fn provide(providers: &mut Providers<'_>) {
*providers = Providers {
check_mod_liveness,

View File

@ -456,12 +456,6 @@ impl<'a, 'tcx> Index<'tcx> {
}
}
pub fn check_unstable_api_usage<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
for &module in tcx.hir().krate().modules.keys() {
tcx.ensure().check_mod_unstable_api_usage(tcx.hir().local_def_id(module));
}
}
/// Cross-references the feature names of unstable APIs with enabled
/// features and possibly prints errors.
fn check_mod_unstable_api_usage<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {

View File

@ -41,7 +41,7 @@ use crate::ty::steal::Steal;
use crate::ty::subst::{UserSubsts, UnpackedKind};
use crate::ty::{BoundVar, BindingMode};
use crate::ty::CanonicalPolyFnSig;
use crate::util::nodemap::{DefIdMap, DefIdSet, ItemLocalMap};
use crate::util::nodemap::{DefIdMap, DefIdSet, ItemLocalMap, ItemLocalSet};
use crate::util::nodemap::{FxHashMap, FxHashSet};
use errors::DiagnosticBuilder;
use rustc_data_structures::interner::HashInterner;
@ -409,9 +409,9 @@ pub struct TypeckTables<'tcx> {
/// MIR construction and hence is not serialized to metadata.
fru_field_types: ItemLocalMap<Vec<Ty<'tcx>>>,
/// Maps a cast expression to its kind. This is keyed on the
/// *from* expression of the cast, not the cast itself.
cast_kinds: ItemLocalMap<ty::cast::CastKind>,
/// For every coercion cast we add the HIR node ID of the cast
/// expression to this set.
coercion_casts: ItemLocalSet,
/// Set of trait imports actually used in the method resolution.
/// This is used for warning unused imports. During type
@ -456,7 +456,7 @@ impl<'tcx> TypeckTables<'tcx> {
closure_kind_origins: Default::default(),
liberated_fn_sigs: Default::default(),
fru_field_types: Default::default(),
cast_kinds: Default::default(),
coercion_casts: Default::default(),
used_trait_imports: Lrc::new(Default::default()),
tainted_by_errors: false,
free_region_map: Default::default(),
@ -718,19 +718,19 @@ impl<'tcx> TypeckTables<'tcx> {
}
}
pub fn cast_kinds(&self) -> LocalTableInContext<'_, ty::cast::CastKind> {
LocalTableInContext {
local_id_root: self.local_id_root,
data: &self.cast_kinds
}
pub fn is_coercion_cast(&self, hir_id: hir::HirId) -> bool {
validate_hir_id_for_typeck_tables(self.local_id_root, hir_id, true);
self.coercion_casts.contains(&hir_id.local_id)
}
pub fn cast_kinds_mut(&mut self) -> LocalTableInContextMut<'_, ty::cast::CastKind> {
LocalTableInContextMut {
local_id_root: self.local_id_root,
data: &mut self.cast_kinds
}
pub fn set_coercion_cast(&mut self, id: ItemLocalId) {
self.coercion_casts.insert(id);
}
pub fn coercion_casts(&self) -> &ItemLocalSet {
&self.coercion_casts
}
}
impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for TypeckTables<'gcx> {
@ -753,7 +753,7 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for TypeckTables<'gcx> {
ref liberated_fn_sigs,
ref fru_field_types,
ref cast_kinds,
ref coercion_casts,
ref used_trait_imports,
tainted_by_errors,
@ -798,7 +798,7 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for TypeckTables<'gcx> {
closure_kind_origins.hash_stable(hcx, hasher);
liberated_fn_sigs.hash_stable(hcx, hasher);
fru_field_types.hash_stable(hcx, hasher);
cast_kinds.hash_stable(hcx, hasher);
coercion_casts.hash_stable(hcx, hasher);
used_trait_imports.hash_stable(hcx, hasher);
tainted_by_errors.hash_stable(hcx, hasher);
free_region_map.hash_stable(hcx, hasher);

View File

@ -369,6 +369,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::privacy_access_levels<'tcx> {
}
}
impl<'tcx> QueryDescription<'tcx> for queries::check_private_in_public<'tcx> {
fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
"checking for private elements in public interfaces".into()
}
}
impl<'tcx> QueryDescription<'tcx> for queries::typeck_item_bodies<'tcx> {
fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
"type-checking all item bodies".into()

View File

@ -350,8 +350,9 @@ define_queries! { <'tcx>
[] fn check_match: CheckMatch(DefId)
-> Result<(), ErrorReported>,
/// Performs the privacy check and computes "access levels".
/// Performs part of the privacy check and computes "access levels".
[] fn privacy_access_levels: PrivacyAccessLevels(CrateNum) -> Lrc<AccessLevels>,
[] fn check_private_in_public: CheckPrivateInPublic(CrateNum) -> (),
},
Other {

View File

@ -1251,6 +1251,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
force!(crate_inherent_impls_overlap_check, LOCAL_CRATE)
},
DepKind::PrivacyAccessLevels => { force!(privacy_access_levels, LOCAL_CRATE); }
DepKind::CheckPrivateInPublic => { force!(check_private_in_public, LOCAL_CRATE); }
DepKind::MirBuilt => { force!(mir_built, def_id!()); }
DepKind::MirConstQualif => { force!(mir_const_qualif, def_id!()); }
DepKind::MirConst => { force!(mir_const, def_id!()); }

View File

@ -49,36 +49,36 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
constant: Result<ty::Const<'tcx>, ErrorHandled>,
) -> (Bx::Value, Ty<'tcx>) {
constant
.and_then(|c| {
.map(|c| {
let field_ty = c.ty.builtin_index().unwrap();
let fields = match c.ty.sty {
ty::Array(_, n) => n.unwrap_usize(bx.tcx()),
ref other => bug!("invalid simd shuffle type: {}", other),
};
let values: Result<Vec<_>, ErrorHandled> = (0..fields).map(|field| {
let values: Vec<_> = (0..fields).map(|field| {
let field = const_field(
bx.tcx(),
ty::ParamEnv::reveal_all(),
None,
mir::Field::new(field as usize),
c,
)?;
);
if let Some(prim) = field.val.try_to_scalar() {
let layout = bx.layout_of(field_ty);
let scalar = match layout.abi {
layout::Abi::Scalar(ref x) => x,
_ => bug!("from_const: invalid ByVal layout: {:#?}", layout)
};
Ok(bx.scalar_to_backend(
bx.scalar_to_backend(
prim, scalar,
bx.immediate_backend_type(layout),
))
)
} else {
bug!("simd shuffle field {:?}", field)
}
}).collect();
let llval = bx.const_struct(&values?, false);
Ok((llval, c.ty))
let llval = bx.const_struct(&values, false);
(llval, c.ty)
})
.unwrap_or_else(|_| {
bx.tcx().sess.span_err(

View File

@ -65,6 +65,7 @@ cfg_if! {
}
use std::ops::Add;
use std::panic::{resume_unwind, catch_unwind, AssertUnwindSafe};
#[derive(Debug)]
pub struct Atomic<T: Copy>(Cell<T>);
@ -130,7 +131,21 @@ cfg_if! {
#[macro_export]
macro_rules! parallel {
($($blocks:tt),*) => {
$($blocks)*;
// We catch panics here ensuring that all the blocks execute.
// This makes behavior consistent with the parallel compiler.
let mut panic = None;
$(
if let Err(p) = ::std::panic::catch_unwind(
::std::panic::AssertUnwindSafe(|| $blocks)
) {
if panic.is_none() {
panic = Some(p);
}
}
)*
if let Some(panic) = panic {
::std::panic::resume_unwind(panic);
}
}
}
@ -140,6 +155,26 @@ cfg_if! {
t.into_iter()
}
pub fn par_for_each_in<T: IntoIterator>(
t: T,
for_each:
impl Fn(<<T as IntoIterator>::IntoIter as Iterator>::Item) + Sync + Send
) {
// We catch panics here ensuring that all the loop iterations execute.
// This makes behavior consistent with the parallel compiler.
let mut panic = None;
t.into_iter().for_each(|i| {
if let Err(p) = catch_unwind(AssertUnwindSafe(|| for_each(i))) {
if panic.is_none() {
panic = Some(p);
}
}
});
if let Some(panic) = panic {
resume_unwind(panic);
}
}
pub type MetadataRef = OwningRef<Box<dyn Erased>, [u8]>;
pub use std::rc::Rc as Lrc;
@ -278,23 +313,26 @@ cfg_if! {
use std::thread;
pub use rayon::{join, scope};
/// Runs a list of blocks in parallel. The first block is executed immediately on
/// the current thread. Use that for the longest running block.
#[macro_export]
macro_rules! parallel {
(impl [$($c:tt,)*] [$block:tt $(, $rest:tt)*]) => {
parallel!(impl [$block, $($c,)*] [$($rest),*])
(impl $fblock:tt [$($c:tt,)*] [$block:tt $(, $rest:tt)*]) => {
parallel!(impl $fblock [$block, $($c,)*] [$($rest),*])
};
(impl [$($blocks:tt,)*] []) => {
(impl $fblock:tt [$($blocks:tt,)*] []) => {
::rustc_data_structures::sync::scope(|s| {
$(
s.spawn(|_| $blocks);
)*
$fblock;
})
};
($($blocks:tt),*) => {
// Reverse the order of the blocks since Rayon executes them in reverse order
($fblock:tt, $($blocks:tt),*) => {
// Reverse the order of the later blocks since Rayon executes them in reverse order
// when using a single thread. This ensures the execution order matches that
// of a single threaded rustc
parallel!(impl [] [$($blocks),*]);
parallel!(impl $fblock [] [$($blocks),*]);
};
}
@ -307,6 +345,15 @@ cfg_if! {
t.into_par_iter()
}
pub fn par_for_each_in<T: IntoParallelIterator>(
t: T,
for_each: impl Fn(
<<T as IntoParallelIterator>::Iter as ParallelIterator>::Item
) + Sync + Send
) {
t.into_par_iter().for_each(for_each)
}
pub type MetadataRef = OwningRef<Box<dyn Erased + Send + Sync>, [u8]>;
/// This makes locks panic if they are already held.

View File

@ -21,7 +21,7 @@ use rustc_borrowck as borrowck;
use rustc_codegen_utils::codegen_backend::CodegenBackend;
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::stable_hasher::StableHasher;
use rustc_data_structures::sync::Lrc;
use rustc_data_structures::sync::{Lrc, ParallelIterator, par_iter};
use rustc_incremental;
use rustc_metadata::creader::CrateLoader;
use rustc_metadata::cstore::{self, CStore};
@ -191,51 +191,50 @@ fn analysis<'tcx>(
let sess = tcx.sess;
parallel!({
time(sess, "looking for entry point", || {
middle::entry::find_entry_point(tcx)
});
time(sess, "misc checking 1", || {
parallel!({
time(sess, "looking for entry point", || {
middle::entry::find_entry_point(tcx)
});
time(sess, "looking for plugin registrar", || {
plugin::build::find_plugin_registrar(tcx)
});
time(sess, "looking for plugin registrar", || {
plugin::build::find_plugin_registrar(tcx)
});
time(sess, "looking for derive registrar", || {
proc_macro_decls::find(tcx)
});
}, {
time(sess, "loop checking", || loops::check_crate(tcx));
}, {
time(sess, "attribute checking", || {
hir::check_attr::check_crate(tcx)
});
}, {
time(sess, "stability checking", || {
stability::check_unstable_api_usage(tcx)
time(sess, "looking for derive registrar", || {
proc_macro_decls::find(tcx)
});
}, {
par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
tcx.ensure().check_mod_loops(tcx.hir().local_def_id(module));
tcx.ensure().check_mod_attrs(tcx.hir().local_def_id(module));
tcx.ensure().check_mod_unstable_api_usage(tcx.hir().local_def_id(module));
});
});
});
// passes are timed inside typeck
typeck::check_crate(tcx)?;
time(sess, "misc checking", || {
time(sess, "misc checking 2", || {
parallel!({
time(sess, "rvalue promotion", || {
rvalue_promotion::check_crate(tcx)
time(sess, "rvalue promotion + match checking", || {
tcx.par_body_owners(|def_id| {
tcx.ensure().const_is_rvalue_promotable_to_static(def_id);
tcx.ensure().check_match(def_id);
});
});
}, {
time(sess, "intrinsic checking", || {
middle::intrinsicck::check_crate(tcx)
});
}, {
time(sess, "match checking", || mir::matchck_crate(tcx));
}, {
// this must run before MIR dump, because
// "not all control paths return a value" is reported here.
//
// maybe move the check to a MIR pass?
time(sess, "liveness checking", || {
middle::liveness::check_crate(tcx)
time(sess, "liveness checking + intrinsic checking", || {
par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
// this must run before MIR dump, because
// "not all control paths return a value" is reported here.
//
// maybe move the check to a MIR pass?
tcx.ensure().check_mod_liveness(tcx.hir().local_def_id(module));
tcx.ensure().check_mod_intrinsics(tcx.hir().local_def_id(module));
});
});
});
});
@ -276,19 +275,30 @@ fn analysis<'tcx>(
return Err(ErrorReported);
}
time(sess, "misc checking", || {
time(sess, "misc checking 3", || {
parallel!({
time(sess, "privacy checking", || {
rustc_privacy::check_crate(tcx)
time(sess, "privacy access levels", || {
tcx.ensure().privacy_access_levels(LOCAL_CRATE);
});
parallel!({
time(sess, "private in public", || {
tcx.ensure().check_private_in_public(LOCAL_CRATE);
});
}, {
time(sess, "death checking", || middle::dead::check_crate(tcx));
}, {
time(sess, "unused lib feature checking", || {
stability::check_unused_or_stable_features(tcx)
});
}, {
time(sess, "lint checking", || lint::check_crate(tcx));
});
}, {
time(sess, "death checking", || middle::dead::check_crate(tcx));
}, {
time(sess, "unused lib feature checking", || {
stability::check_unused_or_stable_features(tcx)
time(sess, "privacy checking modules", || {
par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
tcx.ensure().check_mod_privacy(tcx.hir().local_def_id(module));
});
});
}, {
time(sess, "lint checking", || lint::check_crate(tcx));
});
});

View File

@ -579,6 +579,10 @@ fn should_abort_on_panic<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
// Not callable from C, so we can safely unwind through these
if abi == Abi::Rust || abi == Abi::RustCall { return false; }
// Validate `#[unwind]` syntax regardless of platform-specific panic strategy
let attrs = &tcx.get_attrs(fn_def_id);
let unwind_attr = attr::find_unwind_attr(Some(tcx.sess.diagnostic()), attrs);
// We never unwind, so it's not relevant to stop an unwind
if tcx.sess.panic_strategy() != PanicStrategy::Unwind { return false; }
@ -587,8 +591,7 @@ fn should_abort_on_panic<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
// This is a special case: some functions have a C abi but are meant to
// unwind anyway. Don't stop them.
let attrs = &tcx.get_attrs(fn_def_id);
match attr::find_unwind_attr(Some(tcx.sess.diagnostic()), attrs) {
match unwind_attr {
None => true,
Some(UnwindAttr::Allowed) => false,
Some(UnwindAttr::Aborts) => true,

View File

@ -466,45 +466,42 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx>
}
/// Projects to a field of a (variant of a) const.
// this function uses `unwrap` copiously, because an already validated constant must have valid
// fields and can thus never fail outside of compiler bugs
pub fn const_field<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
variant: Option<VariantIdx>,
field: mir::Field,
value: ty::Const<'tcx>,
) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> {
) -> ty::Const<'tcx> {
trace!("const_field: {:?}, {:?}", field, value);
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env);
let result = (|| {
// get the operand again
let op = ecx.const_to_op(value, None)?;
// downcast
let down = match variant {
None => op,
Some(variant) => ecx.operand_downcast(op, variant)?
};
// then project
let field = ecx.operand_field(down, field.index() as u64)?;
// and finally move back to the const world, always normalizing because
// this is not called for statics.
op_to_const(&ecx, field)
})();
result.map_err(|error| {
let err = error_to_const_error(&ecx, error);
err.report_as_error(ecx.tcx, "could not access field of constant");
ErrorHandled::Reported
})
// get the operand again
let op = ecx.const_to_op(value, None).unwrap();
// downcast
let down = match variant {
None => op,
Some(variant) => ecx.operand_downcast(op, variant).unwrap(),
};
// then project
let field = ecx.operand_field(down, field.index() as u64).unwrap();
// and finally move back to the const world, always normalizing because
// this is not called for statics.
op_to_const(&ecx, field).unwrap()
}
// this function uses `unwrap` copiously, because an already validated constant must have valid
// fields and can thus never fail outside of compiler bugs
pub fn const_variant_index<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
val: ty::Const<'tcx>,
) -> EvalResult<'tcx, VariantIdx> {
) -> VariantIdx {
trace!("const_variant_index: {:?}", val);
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env);
let op = ecx.const_to_op(val, None)?;
Ok(ecx.read_discriminant(op)?.1)
let op = ecx.const_to_op(val, None).unwrap();
ecx.read_discriminant(op).unwrap().1
}
pub fn error_to_const_error<'a, 'mir, 'tcx>(

View File

@ -8,7 +8,6 @@ use rustc::hir::def::{Def, CtorKind};
use rustc::mir::interpret::{GlobalId, ErrorHandled, ConstValue};
use rustc::ty::{self, AdtKind, Ty};
use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability};
use rustc::ty::cast::CastKind as TyCastKind;
use rustc::ty::subst::{InternalSubsts, SubstsRef};
use rustc::hir;
use rustc::hir::def_id::LocalDefId;
@ -655,11 +654,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
// Check to see if this cast is a "coercion cast", where the cast is actually done
// using a coercion (or is a no-op).
let cast = if let Some(&TyCastKind::CoercionCast) =
cx.tables()
.cast_kinds()
.get(source.hir_id)
{
let cast = if cx.tables().is_coercion_cast(source.hir_id) {
// Convert the lexpr to a vexpr.
ExprKind::Use { source: source.to_ref() }
} else {

View File

@ -440,13 +440,7 @@ impl<'tcx> Constructor<'tcx> {
assert!(!adt.is_enum());
VariantIdx::new(0)
}
&ConstantValue(c) => {
crate::const_eval::const_variant_index(
cx.tcx,
cx.param_env,
c,
).unwrap()
},
&ConstantValue(c) => crate::const_eval::const_variant_index(cx.tcx, cx.param_env, c),
_ => bug!("bad constructor {:?} for adt {:?}", self, adt)
}
}

View File

@ -27,13 +27,6 @@ use std::slice;
use syntax::ptr::P;
use syntax_pos::{Span, DUMMY_SP, MultiSpan};
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
for def_id in tcx.body_owners() {
tcx.ensure().check_match(def_id);
}
tcx.sess.abort_if_errors();
}
pub(crate) fn check_match<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId,

View File

@ -3,7 +3,6 @@
mod _match;
mod check_match;
pub use self::check_match::check_crate;
pub(crate) use self::check_match::check_match;
use crate::const_eval::{const_field, const_variant_index};
@ -937,10 +936,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
debug!("const_to_pat: cv={:#?} id={:?}", cv, id);
let adt_subpattern = |i, variant_opt| {
let field = Field::new(i);
let val = const_field(
self.tcx, self.param_env,
variant_opt, field, cv,
).expect("field access failed");
let val = const_field(self.tcx, self.param_env, variant_opt, field, cv);
self.const_to_pat(instance, val, id, span)
};
let adt_subpatterns = |n, variant_opt| {
@ -979,9 +975,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
PatternKind::Wild
}
ty::Adt(adt_def, substs) if adt_def.is_enum() => {
let variant_index = const_variant_index(
self.tcx, self.param_env, cv
).expect("const_variant_index failed");
let variant_index = const_variant_index(self.tcx, self.param_env, cv);
let subpatterns = adt_subpatterns(
adt_def.variants[variant_index].fields.len(),
Some(variant_index),

View File

@ -54,7 +54,6 @@ pub mod interpret;
pub mod monomorphize;
pub mod const_eval;
pub use hair::pattern::check_crate as matchck_crate;
use rustc::ty::query::Providers;
pub fn provide(providers: &mut Providers<'_>) {

View File

@ -45,12 +45,6 @@ struct CheckLoopVisitor<'a, 'hir: 'a> {
cx: Context,
}
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
for &module in tcx.hir().krate().modules.keys() {
tcx.ensure().check_mod_loops(tcx.hir().local_def_id(module));
}
}
fn check_mod_loops<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
tcx.hir().visit_item_likes_in_module(module_def_id, &mut CheckLoopVisitor {
sess: &tcx.sess,

View File

@ -14,7 +14,7 @@
// - It's not possible to take the address of a static item with unsafe interior. This is enforced
// by borrowck::gather_loans
use rustc::ty::cast::CastKind;
use rustc::ty::cast::CastTy;
use rustc::hir::def::{Def, CtorKind};
use rustc::hir::def_id::DefId;
use rustc::middle::expr_use_visitor as euv;
@ -39,13 +39,6 @@ pub fn provide(providers: &mut Providers<'_>) {
};
}
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
for &body_id in &tcx.hir().krate().body_ids {
let def_id = tcx.hir().body_owner_def_id(body_id);
tcx.const_is_rvalue_promotable_to_static(def_id);
}
}
fn const_is_rvalue_promotable_to_static<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId)
-> bool
@ -318,15 +311,12 @@ fn check_expr_kind<'a, 'tcx>(
hir::ExprKind::Cast(ref from, _) => {
let expr_promotability = v.check_expr(from);
debug!("Checking const cast(id={})", from.hir_id);
match v.tables.cast_kinds().get(from.hir_id) {
None => {
v.tcx.sess.delay_span_bug(e.span, "no kind for cast");
NotPromotable
},
Some(&CastKind::PtrAddrCast) | Some(&CastKind::FnPtrAddrCast) => {
NotPromotable
}
_ => expr_promotability
let cast_in = CastTy::from_ty(v.tables.expr_ty(from));
let cast_out = CastTy::from_ty(v.tables.expr_ty(e));
match (cast_in, cast_out) {
(Some(CastTy::FnPtr), Some(CastTy::Int(_))) |
(Some(CastTy::Ptr(_)), Some(CastTy::Int(_))) => NotPromotable,
(_, _) => expr_promotability
}
}
hir::ExprKind::Path(ref qpath) => {

View File

@ -1766,19 +1766,15 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx>
pub fn provide(providers: &mut Providers<'_>) {
*providers = Providers {
privacy_access_levels,
check_private_in_public,
check_mod_privacy,
..*providers
};
}
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Lrc<AccessLevels> {
tcx.privacy_access_levels(LOCAL_CRATE)
}
fn check_mod_privacy<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
let empty_tables = ty::TypeckTables::empty(None);
// Check privacy of names not checked in previous compilation stages.
let mut visitor = NamePrivacyVisitor {
tcx,
@ -1809,18 +1805,6 @@ fn privacy_access_levels<'tcx>(
) -> Lrc<AccessLevels> {
assert_eq!(krate, LOCAL_CRATE);
let krate = tcx.hir().krate();
for &module in krate.modules.keys() {
tcx.ensure().check_mod_privacy(tcx.hir().local_def_id(module));
}
let private_crates: FxHashSet<CrateNum> = tcx.sess.opts.extern_private.iter()
.flat_map(|c| {
tcx.crates().iter().find(|&&krate| &tcx.crate_name(krate) == c).cloned()
}).collect();
// Build up a set of all exported items in the AST. This is a set of all
// items which are reachable from external crates based on visibility.
let mut visitor = EmbargoVisitor {
@ -1830,7 +1814,7 @@ fn privacy_access_levels<'tcx>(
changed: false,
};
loop {
intravisit::walk_crate(&mut visitor, krate);
intravisit::walk_crate(&mut visitor, tcx.hir().krate());
if visitor.changed {
visitor.changed = false;
} else {
@ -1839,36 +1823,46 @@ fn privacy_access_levels<'tcx>(
}
visitor.update(hir::CRATE_HIR_ID, Some(AccessLevel::Public));
{
let mut visitor = ObsoleteVisiblePrivateTypesVisitor {
tcx,
access_levels: &visitor.access_levels,
in_variant: false,
old_error_set: Default::default(),
};
intravisit::walk_crate(&mut visitor, krate);
let has_pub_restricted = {
let mut pub_restricted_visitor = PubRestrictedVisitor {
tcx,
has_pub_restricted: false
};
intravisit::walk_crate(&mut pub_restricted_visitor, krate);
pub_restricted_visitor.has_pub_restricted
};
// Check for private types and traits in public interfaces.
let mut visitor = PrivateItemsInPublicInterfacesVisitor {
tcx,
has_pub_restricted,
old_error_set: &visitor.old_error_set,
private_crates
};
krate.visit_all_item_likes(&mut DeepVisitor::new(&mut visitor));
}
Lrc::new(visitor.access_levels)
}
fn check_private_in_public<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, krate: CrateNum) {
assert_eq!(krate, LOCAL_CRATE);
let access_levels = tcx.privacy_access_levels(LOCAL_CRATE);
let krate = tcx.hir().krate();
let mut visitor = ObsoleteVisiblePrivateTypesVisitor {
tcx,
access_levels: &access_levels,
in_variant: false,
old_error_set: Default::default(),
};
intravisit::walk_crate(&mut visitor, krate);
let has_pub_restricted = {
let mut pub_restricted_visitor = PubRestrictedVisitor {
tcx,
has_pub_restricted: false
};
intravisit::walk_crate(&mut pub_restricted_visitor, krate);
pub_restricted_visitor.has_pub_restricted
};
let private_crates: FxHashSet<CrateNum> = tcx.sess.opts.extern_private.iter()
.flat_map(|c| {
tcx.crates().iter().find(|&&krate| &tcx.crate_name(krate) == c).cloned()
}).collect();
// Check for private types and traits in public interfaces.
let mut visitor = PrivateItemsInPublicInterfacesVisitor {
tcx,
has_pub_restricted,
old_error_set: &visitor.old_error_set,
private_crates
};
krate.visit_all_item_likes(&mut DeepVisitor::new(&mut visitor));
}
__build_diagnostic_array! { librustc_privacy, DIAGNOSTICS }

View File

@ -428,13 +428,12 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
} else if self.try_coercion_cast(fcx) {
self.trivial_cast_lint(fcx);
debug!(" -> CoercionCast");
fcx.tables.borrow_mut().cast_kinds_mut().insert(self.expr.hir_id,
CastKind::CoercionCast);
fcx.tables.borrow_mut().set_coercion_cast(self.expr.hir_id.local_id);
} else {
match self.do_check(fcx) {
Ok(k) => {
debug!(" -> {:?}", k);
fcx.tables.borrow_mut().cast_kinds_mut().insert(self.expr.hir_id, k);
}
Err(e) => self.report_cast_error(fcx, e),
};

View File

@ -694,15 +694,7 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CheckItemTypesVisitor<'a, 'tcx> {
pub fn check_wf_new<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Result<(), ErrorReported> {
tcx.sess.track_errors(|| {
let mut visit = wfcheck::CheckTypeWellFormedVisitor::new(tcx);
tcx.hir().krate().visit_all_item_likes(&mut visit);
})
}
pub fn check_item_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Result<(), ErrorReported> {
tcx.sess.track_errors(|| {
for &module in tcx.hir().krate().modules.keys() {
tcx.ensure().check_mod_item_types(tcx.hir().local_def_id(module));
}
tcx.hir().krate().par_visit_all_item_likes(&mut visit);
})
}
@ -710,10 +702,6 @@ fn check_mod_item_types<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId)
tcx.hir().visit_item_likes_in_module(module_def_id, &mut CheckItemTypesVisitor { tcx });
}
pub fn check_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Result<(), ErrorReported> {
tcx.typeck_item_bodies(LOCAL_CRATE)
}
fn typeck_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum)
-> Result<(), ErrorReported>
{

View File

@ -15,7 +15,7 @@ use syntax::feature_gate::{self, GateIssue};
use syntax_pos::Span;
use errors::{DiagnosticBuilder, DiagnosticId};
use rustc::hir::itemlikevisit::ItemLikeVisitor;
use rustc::hir::itemlikevisit::ParItemLikeVisitor;
use rustc::hir;
/// Helper type of a temporary returned by `.for_item(...)`.
@ -1061,20 +1061,20 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
}
}
impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CheckTypeWellFormedVisitor<'a, 'tcx> {
fn visit_item(&mut self, i: &'tcx hir::Item) {
impl<'a, 'tcx> ParItemLikeVisitor<'tcx> for CheckTypeWellFormedVisitor<'a, 'tcx> {
fn visit_item(&self, i: &'tcx hir::Item) {
debug!("visit_item: {:?}", i);
let def_id = self.tcx.hir().local_def_id_from_hir_id(i.hir_id);
self.tcx.ensure().check_item_well_formed(def_id);
}
fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
fn visit_trait_item(&self, trait_item: &'tcx hir::TraitItem) {
debug!("visit_trait_item: {:?}", trait_item);
let def_id = self.tcx.hir().local_def_id_from_hir_id(trait_item.hir_id);
self.tcx.ensure().check_trait_item_well_formed(def_id);
}
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
fn visit_impl_item(&self, impl_item: &'tcx hir::ImplItem) {
debug!("visit_impl_item: {:?}", impl_item);
let def_id = self.tcx.hir().local_def_id_from_hir_id(impl_item.hir_id);
self.tcx.ensure().check_impl_item_well_formed(def_id);

View File

@ -50,7 +50,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
wbcx.visit_liberated_fn_sigs();
wbcx.visit_fru_field_types();
wbcx.visit_opaque_types(body.value.span);
wbcx.visit_cast_types();
wbcx.visit_coercion_casts();
wbcx.visit_free_region_map();
wbcx.visit_user_provided_tys();
wbcx.visit_user_provided_sigs();
@ -355,19 +355,13 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
}
}
fn visit_cast_types(&mut self) {
fn visit_coercion_casts(&mut self) {
let fcx_tables = self.fcx.tables.borrow();
let fcx_cast_kinds = fcx_tables.cast_kinds();
let fcx_coercion_casts = fcx_tables.coercion_casts();
debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root);
let mut self_cast_kinds = self.tables.cast_kinds_mut();
let common_local_id_root = fcx_tables.local_id_root.unwrap();
for (&local_id, &cast_kind) in fcx_cast_kinds.iter() {
let hir_id = hir::HirId {
owner: common_local_id_root.index,
local_id,
};
self_cast_kinds.insert(hir_id, cast_kind);
for local_id in fcx_coercion_casts {
self.tables.set_coercion_cast(*local_id);
}
}

View File

@ -141,9 +141,7 @@ fn coherent_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
for &impl_id in impls {
check_impl_overlap(tcx, impl_id);
}
use rustc::util::common::time;
time(tcx.sess, "builtin::check_trait checking", ||
builtin::check_trait(tcx, def_id));
builtin::check_trait(tcx, def_id);
}
pub fn check_coherence<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {

View File

@ -56,12 +56,6 @@ struct OnlySelfBounds(bool);
///////////////////////////////////////////////////////////////////////////
// Main entry point
pub fn collect_item_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
for &module in tcx.hir().krate().modules.keys() {
tcx.ensure().collect_mod_item_types(tcx.hir().local_def_id(module));
}
}
fn collect_mod_item_types<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
tcx.hir().visit_item_likes_in_module(
module_def_id,

View File

@ -322,8 +322,11 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
// this ensures that later parts of type checking can assume that items
// have valid types and not error
tcx.sess.track_errors(|| {
time(tcx.sess, "type collecting", ||
collect::collect_item_types(tcx));
time(tcx.sess, "type collecting", || {
for &module in tcx.hir().krate().modules.keys() {
tcx.ensure().collect_mod_item_types(tcx.hir().local_def_id(module));
}
});
})?;
if tcx.features().rustc_attrs {
@ -352,9 +355,15 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
time(tcx.sess, "wf checking", || check::check_wf_new(tcx))?;
time(tcx.sess, "item-types checking", || check::check_item_types(tcx))?;
time(tcx.sess, "item-types checking", || {
tcx.sess.track_errors(|| {
for &module in tcx.hir().krate().modules.keys() {
tcx.ensure().check_mod_item_types(tcx.hir().local_def_id(module));
}
})
})?;
time(tcx.sess, "item-bodies checking", || check::check_item_bodies(tcx))?;
time(tcx.sess, "item-bodies checking", || tcx.typeck_item_bodies(LOCAL_CRATE))?;
check_unused::check_crate(tcx);
check_for_entry_fn(tcx);

View File

@ -85,6 +85,9 @@ pub struct Options {
/// Whether to display warnings during doc generation or while gathering doctests. By default,
/// all non-rustdoc-specific lints are allowed when generating docs.
pub display_warnings: bool,
/// Whether to run the `calculate-doc-coverage` pass, which counts the number of public items
/// with and without documentation.
pub show_coverage: bool,
// Options that alter generated documentation pages
@ -128,6 +131,7 @@ impl fmt::Debug for Options {
.field("default_passes", &self.default_passes)
.field("manual_passes", &self.manual_passes)
.field("display_warnings", &self.display_warnings)
.field("show_coverage", &self.show_coverage)
.field("crate_version", &self.crate_version)
.field("render_options", &self.render_options)
.finish()
@ -224,6 +228,18 @@ impl Options {
for &name in passes::DEFAULT_PRIVATE_PASSES {
println!("{:>20}", name);
}
if nightly_options::is_nightly_build() {
println!("\nPasses run with `--show-coverage`:");
for &name in passes::DEFAULT_COVERAGE_PASSES {
println!("{:>20}", name);
}
println!("\nPasses run with `--show-coverage --document-private-items`:");
for &name in passes::PRIVATE_COVERAGE_PASSES {
println!("{:>20}", name);
}
}
return Err(0);
}
@ -413,9 +429,16 @@ impl Options {
}
});
let show_coverage = matches.opt_present("show-coverage");
let document_private = matches.opt_present("document-private-items");
let default_passes = if matches.opt_present("no-defaults") {
passes::DefaultPassOption::None
} else if matches.opt_present("document-private-items") {
} else if show_coverage && document_private {
passes::DefaultPassOption::PrivateCoverage
} else if show_coverage {
passes::DefaultPassOption::Coverage
} else if document_private {
passes::DefaultPassOption::Private
} else {
passes::DefaultPassOption::Default
@ -463,6 +486,7 @@ impl Options {
default_passes,
manual_passes,
display_warnings,
show_coverage,
crate_version,
persist_doctests,
render_options: RenderOptions {

View File

@ -617,10 +617,13 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
info!("Executing passes");
for pass in &passes {
match passes::find_pass(pass).map(|p| p.pass) {
Some(pass) => krate = pass(krate, &ctxt),
None => error!("unknown pass {}, skipping", *pass),
for pass_name in &passes {
match passes::find_pass(pass_name).map(|p| p.pass) {
Some(pass) => {
debug!("running pass {}", pass_name);
krate = pass(krate, &ctxt);
}
None => error!("unknown pass {}, skipping", *pass_name),
}
}

View File

@ -15,7 +15,7 @@ use crate::clean;
/// module headings. If you are adding to this enum and want to ensure that the sidebar also prints
/// a heading, edit the listing in `html/render.rs`, function `sidebar_module`. This uses an
/// ordering based on a helper function inside `item_module`, in the same file.
#[derive(Copy, PartialEq, Clone, Debug)]
#[derive(Copy, PartialEq, Eq, Clone, Debug, PartialOrd, Ord)]
pub enum ItemType {
Module = 0,
ExternCrate = 1,

View File

@ -348,6 +348,11 @@ fn opts() -> Vec<RustcOptGroup> {
"generate-redirect-pages",
"Generate extra pages to support legacy URLs and tool links")
}),
unstable("show-coverage", |o| {
o.optflag("",
"show-coverage",
"calculate percentage of public items with documentation")
}),
]
}
@ -392,7 +397,14 @@ fn main_args(args: &[String]) -> isize {
let diag_opts = (options.error_format,
options.debugging_options.treat_err_as_bug,
options.debugging_options.ui_testing);
let show_coverage = options.show_coverage;
rust_input(options, move |out| {
if show_coverage {
// if we ran coverage, bail early, we don't need to also generate docs at this point
// (also we didn't load in any of the useful passes)
return rustc_driver::EXIT_SUCCESS;
}
let Output { krate, passes, renderinfo, renderopts } = out;
info!("going to format");
let (error_format, treat_err_as_bug, ui_testing) = diag_opts;

View File

@ -0,0 +1,166 @@
use crate::clean;
use crate::core::DocContext;
use crate::fold::{self, DocFolder};
use crate::passes::Pass;
use syntax::attr;
use syntax_pos::FileName;
use std::collections::BTreeMap;
use std::ops;
pub const CALCULATE_DOC_COVERAGE: Pass = Pass {
name: "calculate-doc-coverage",
pass: calculate_doc_coverage,
description: "counts the number of items with and without documentation",
};
fn calculate_doc_coverage(krate: clean::Crate, _: &DocContext<'_, '_, '_>) -> clean::Crate {
let mut calc = CoverageCalculator::default();
let krate = calc.fold_crate(krate);
calc.print_results();
krate
}
#[derive(Default, Copy, Clone)]
struct ItemCount {
total: u64,
with_docs: u64,
}
impl ItemCount {
fn count_item(&mut self, has_docs: bool) {
self.total += 1;
if has_docs {
self.with_docs += 1;
}
}
fn percentage(&self) -> Option<f64> {
if self.total > 0 {
Some((self.with_docs as f64 * 100.0) / self.total as f64)
} else {
None
}
}
}
impl ops::Sub for ItemCount {
type Output = Self;
fn sub(self, rhs: Self) -> Self {
ItemCount {
total: self.total - rhs.total,
with_docs: self.with_docs - rhs.with_docs,
}
}
}
impl ops::AddAssign for ItemCount {
fn add_assign(&mut self, rhs: Self) {
self.total += rhs.total;
self.with_docs += rhs.with_docs;
}
}
#[derive(Default)]
struct CoverageCalculator {
items: BTreeMap<FileName, ItemCount>,
}
impl CoverageCalculator {
fn print_results(&self) {
let mut total = ItemCount::default();
fn print_table_line() {
println!("+-{0:->35}-+-{0:->10}-+-{0:->10}-+-{0:->10}-+", "");
}
fn print_table_record(name: &str, count: ItemCount, percentage: f64) {
println!("| {:<35} | {:>10} | {:>10} | {:>9.1}% |",
name, count.with_docs, count.total, percentage);
}
print_table_line();
println!("| {:<35} | {:>10} | {:>10} | {:>10} |",
"File", "Documented", "Total", "Percentage");
print_table_line();
for (file, &count) in &self.items {
if let Some(percentage) = count.percentage() {
let mut name = file.to_string();
// if a filename is too long, shorten it so we don't blow out the table
// FIXME(misdreavus): this needs to count graphemes, and probably also track
// double-wide characters...
if name.len() > 35 {
name = "...".to_string() + &name[name.len()-32..];
}
print_table_record(&name, count, percentage);
total += count;
}
}
print_table_line();
print_table_record("Total", total, total.percentage().unwrap_or(0.0));
print_table_line();
}
}
impl fold::DocFolder for CoverageCalculator {
fn fold_item(&mut self, i: clean::Item) -> Option<clean::Item> {
let has_docs = !i.attrs.doc_strings.is_empty();
match i.inner {
_ if !i.def_id.is_local() => {
// non-local items are skipped because they can be out of the users control,
// especially in the case of trait impls, which rustdoc eagerly inlines
return Some(i);
}
clean::StrippedItem(..) => {
// don't count items in stripped modules
return Some(i);
}
clean::ImportItem(..) | clean::ExternCrateItem(..) => {
// docs on `use` and `extern crate` statements are not displayed, so they're not
// worth counting
return Some(i);
}
clean::ImplItem(ref impl_)
if attr::contains_name(&i.attrs.other_attrs, "automatically_derived")
|| impl_.synthetic || impl_.blanket_impl.is_some() =>
{
// built-in derives get the `#[automatically_derived]` attribute, and
// synthetic/blanket impls are made up by rustdoc and can't be documented
// FIXME(misdreavus): need to also find items that came out of a derive macro
return Some(i);
}
clean::ImplItem(ref impl_) => {
if let Some(ref tr) = impl_.trait_ {
debug!("impl {:#} for {:#} in {}", tr, impl_.for_, i.source.filename);
// don't count trait impls, the missing-docs lint doesn't so we shouldn't
// either
return Some(i);
} else {
// inherent impls *can* be documented, and those docs show up, but in most
// cases it doesn't make sense, as all methods on a type are in one single
// impl block
debug!("impl {:#} in {}", impl_.for_, i.source.filename);
}
}
_ => {
debug!("counting {} {:?} in {}", i.type_(), i.name, i.source.filename);
self.items.entry(i.source.filename.clone())
.or_default()
.count_item(has_docs);
}
}
self.fold_item_recur(i)
}
}

View File

@ -45,6 +45,9 @@ pub use self::collect_trait_impls::COLLECT_TRAIT_IMPLS;
mod check_code_block_syntax;
pub use self::check_code_block_syntax::CHECK_CODE_BLOCK_SYNTAX;
mod calculate_doc_coverage;
pub use self::calculate_doc_coverage::CALCULATE_DOC_COVERAGE;
/// A single pass over the cleaned documentation.
///
/// Runs in the compiler context, so it has access to types and traits and the like.
@ -67,6 +70,7 @@ pub const PASSES: &'static [Pass] = &[
COLLECT_INTRA_DOC_LINKS,
CHECK_CODE_BLOCK_SYNTAX,
COLLECT_TRAIT_IMPLS,
CALCULATE_DOC_COVERAGE,
];
/// The list of passes run by default.
@ -94,12 +98,29 @@ pub const DEFAULT_PRIVATE_PASSES: &[&str] = &[
"propagate-doc-cfg",
];
/// The list of default passes run when `--doc-coverage` is passed to rustdoc.
pub const DEFAULT_COVERAGE_PASSES: &'static [&'static str] = &[
"collect-trait-impls",
"strip-hidden",
"strip-private",
"calculate-doc-coverage",
];
/// The list of default passes run when `--doc-coverage --document-private-items` is passed to
/// rustdoc.
pub const PRIVATE_COVERAGE_PASSES: &'static [&'static str] = &[
"collect-trait-impls",
"calculate-doc-coverage",
];
/// A shorthand way to refer to which set of passes to use, based on the presence of
/// `--no-defaults` or `--document-private-items`.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum DefaultPassOption {
Default,
Private,
Coverage,
PrivateCoverage,
None,
}
@ -108,6 +129,8 @@ pub fn defaults(default_set: DefaultPassOption) -> &'static [&'static str] {
match default_set {
DefaultPassOption::Default => DEFAULT_PASSES,
DefaultPassOption::Private => DEFAULT_PRIVATE_PASSES,
DefaultPassOption::Coverage => DEFAULT_COVERAGE_PASSES,
DefaultPassOption::PrivateCoverage => PRIVATE_COVERAGE_PASSES,
DefaultPassOption::None => &[],
}
}

View File

@ -1742,21 +1742,6 @@ mod tests {
})
}
#[test]
fn connect_timeout_unbound() {
// bind and drop a socket to track down a "probably unassigned" port
let socket = TcpListener::bind("127.0.0.1:0").unwrap();
let addr = socket.local_addr().unwrap();
drop(socket);
let timeout = Duration::from_secs(1);
let e = TcpStream::connect_timeout(&addr, timeout).unwrap_err();
assert!(e.kind() == io::ErrorKind::ConnectionRefused ||
e.kind() == io::ErrorKind::TimedOut ||
e.kind() == io::ErrorKind::Other,
"bad error: {} {:?}", e, e.kind());
}
#[test]
fn connect_timeout_valid() {
let listener = TcpListener::bind("127.0.0.1:0").unwrap();

View File

@ -7,7 +7,7 @@ use crate::parse::ParseSess;
use errors::{Applicability, Handler};
use syntax_pos::{symbol::Symbol, Span};
use super::{list_contains_name, mark_used, MetaItemKind};
use super::{mark_used, MetaItemKind};
enum AttrError {
MultipleItem(Name),
@ -79,40 +79,26 @@ pub enum UnwindAttr {
/// Determine what `#[unwind]` attribute is present in `attrs`, if any.
pub fn find_unwind_attr(diagnostic: Option<&Handler>, attrs: &[Attribute]) -> Option<UnwindAttr> {
let syntax_error = |attr: &Attribute| {
mark_used(attr);
diagnostic.map(|d| {
span_err!(d, attr.span, E0633, "malformed `#[unwind]` attribute");
});
None
};
attrs.iter().fold(None, |ia, attr| {
if attr.path != "unwind" {
return ia;
}
let meta = match attr.meta() {
Some(meta) => meta.node,
None => return ia,
};
match meta {
MetaItemKind::Word => {
syntax_error(attr)
}
MetaItemKind::List(ref items) => {
mark_used(attr);
if items.len() != 1 {
syntax_error(attr)
} else if list_contains_name(&items[..], "allowed") {
Some(UnwindAttr::Allowed)
} else if list_contains_name(&items[..], "aborts") {
Some(UnwindAttr::Aborts)
} else {
syntax_error(attr)
if attr.check_name("unwind") {
if let Some(meta) = attr.meta() {
if let MetaItemKind::List(items) = meta.node {
if items.len() == 1 {
if items[0].check_name("allowed") {
return Some(UnwindAttr::Allowed);
} else if items[0].check_name("aborts") {
return Some(UnwindAttr::Aborts);
}
}
diagnostic.map(|d| {
span_err!(d, attr.span, E0633, "malformed `#[unwind]` attribute");
});
}
}
_ => ia,
}
ia
})
}

View File

@ -1176,7 +1176,7 @@ pub const BUILTIN_ATTRIBUTES: &[(&str, AttributeType, AttributeTemplate, Attribu
"dropck_eyepatch",
"may_dangle has unstable semantics and may be removed in the future",
cfg_fn!(dropck_eyepatch))),
("unwind", Whitelisted, template!(List: "allowed"), Gated(Stability::Unstable,
("unwind", Whitelisted, template!(List: "allowed|aborts"), Gated(Stability::Unstable,
"unwind_attributes",
"#[unwind] is experimental",
cfg_fn!(unwind_attributes))),

View File

@ -185,7 +185,7 @@ pub fn maybe_new_parser_from_file<'a>(sess: &'a ParseSess, path: &Path)
/// Given a session, a crate config, a path, and a span, add
/// the file at the given path to the source_map, and return a parser.
/// On an error, use the given span as the source of the problem.
crate fn new_sub_parser_from_file<'a>(sess: &'a ParseSess,
pub fn new_sub_parser_from_file<'a>(sess: &'a ParseSess,
path: &Path,
directory_ownership: DirectoryOwnership,
module_name: Option<String>,

View File

@ -0,0 +1,35 @@
// ignore-windows failing on win32 bot
// ignore-android: FIXME(#10381)
// compile-flags:-g
// min-gdb-version: 7.7
// min-lldb-version: 310
// === GDB TESTS ===================================================================================
// gdb-command: run
// gdb-command: print empty_string
// gdb-check:$1 = ""
// gdb-command: print empty_str
// gdb-check:$2 = ""
// === LLDB TESTS ==================================================================================
// lldb-command: run
// lldb-command: fr v empty_string
// lldb-check:[...]empty_string = ""
// lldb-command: fr v empty_str
// lldb-check:[...]empty_str = ""
fn main() {
let empty_string = String::new();
let empty_str = "";
zzz(); // #break
}
fn zzz() {}

View File

@ -0,0 +1,17 @@
// run-pass
#![feature(const_ptr_nonnull)]
use std::ptr::NonNull;
const DANGLING: NonNull<u32> = NonNull::dangling();
const CASTED: NonNull<u32> = NonNull::cast(NonNull::<i32>::dangling());
fn ident<T>(ident: T) -> T {
ident
}
pub fn main() {
assert_eq!(DANGLING, ident(NonNull::dangling()));
assert_eq!(CASTED, ident(NonNull::dangling()));
}

View File

@ -0,0 +1,15 @@
// run-pass
#![feature(ptr_internals)]
use std::ptr::Unique;
const PTR: *mut u32 = Unique::empty().as_ptr();
fn ident<T>(ident: T) -> T {
ident
}
pub fn main() {
assert_eq!(PTR, ident(Unique::<u32>::empty().as_ptr()));
}

View File

@ -0,0 +1,50 @@
// compile-flags:-Z unstable-options --show-coverage
// compile-pass
#![feature(extern_types)]
//! Make sure to have some docs on your crate root
/// This struct is documented, but its fields are not.
///
/// However, one field is private, so it shouldn't show in the total.
pub struct SomeStruct {
pub some_field: usize,
other_field: usize,
}
impl SomeStruct {
/// Method with docs
pub fn this_fn(&self) {}
// Method without docs
pub fn other_method(&self) {}
}
// struct without docs
pub struct OtherStruct;
// function with no docs
pub fn some_fn() {}
/// Function with docs
pub fn other_fn() {}
pub enum SomeEnum {
/// Some of these variants are documented...
VarOne,
/// ...but some of them are not.
VarTwo,
// (like this one)
VarThree,
}
/// There's a macro here, too
#[macro_export]
macro_rules! some_macro {
() => {};
}
extern {
pub type ExternType;
}

View File

@ -0,0 +1,7 @@
+-------------------------------------+------------+------------+------------+
| File | Documented | Total | Percentage |
+-------------------------------------+------------+------------+------------+
| ...est/rustdoc-ui/coverage/basic.rs | 7 | 14 | 50.0% |
+-------------------------------------+------------+------------+------------+
| Total | 7 | 14 | 50.0% |
+-------------------------------------+------------+------------+------------+

View File

@ -0,0 +1,4 @@
// compile-flags:-Z unstable-options --show-coverage
// compile-pass
// an empty crate still has one item to document: the crate root

View File

@ -0,0 +1,7 @@
+-------------------------------------+------------+------------+------------+
| File | Documented | Total | Percentage |
+-------------------------------------+------------+------------+------------+
| ...est/rustdoc-ui/coverage/empty.rs | 0 | 1 | 0.0% |
+-------------------------------------+------------+------------+------------+
| Total | 0 | 1 | 0.0% |
+-------------------------------------+------------+------------+------------+

View File

@ -0,0 +1,22 @@
// compile-flags:-Z unstable-options --show-coverage
// compile-pass
//! (remember the crate root is still a module)
/// so check out this enum here
pub enum ThisEnum {
/// this variant has some weird stuff going on
VarOne {
/// like, it has some named fields inside
field_one: usize,
// (these show up as struct fields)
field_two: usize,
},
/// here's another variant for you
VarTwo(String),
// but not all of them need to be documented as thoroughly
VarThree,
}
/// uninhabited enums? sure, let's throw one of those around
pub enum OtherEnum {}

View File

@ -0,0 +1,7 @@
+-------------------------------------+------------+------------+------------+
| File | Documented | Total | Percentage |
+-------------------------------------+------------+------------+------------+
| ...est/rustdoc-ui/coverage/enums.rs | 6 | 8 | 75.0% |
+-------------------------------------+------------+------------+------------+
| Total | 6 | 8 | 75.0% |
+-------------------------------------+------------+------------+------------+

View File

@ -0,0 +1,15 @@
// compile-flags:-Z unstable-options --show-coverage
// compile-pass
#![feature(doc_keyword)]
//! the features only used in std also have entries in the table, so make sure those get pulled out
//! properly as well
/// woo, check it out, we can write our own primitive docs lol
#[doc(primitive="unit")]
mod prim_unit {}
/// keywords? sure, pile them on
#[doc(keyword="where")]
mod where_keyword {}

View File

@ -0,0 +1,8 @@
+-------------------------------------+------------+------------+------------+
| File | Documented | Total | Percentage |
+-------------------------------------+------------+------------+------------+
| ...st/rustdoc-ui/coverage/exotic.rs | 1 | 1 | 100.0% |
| <anon> | 2 | 2 | 100.0% |
+-------------------------------------+------------+------------+------------+
| Total | 3 | 3 | 100.0% |
+-------------------------------------+------------+------------+------------+

View File

@ -0,0 +1,21 @@
// compile-flags:-Z unstable-options --show-coverage --document-private-items
// compile-pass
#![allow(unused)]
//! when `--document-private-items` is passed, nothing is safe. everything must have docs or your
//! score will suffer the consequences
mod this_mod {
fn private_fn() {}
}
/// See, our public items have docs!
pub struct SomeStruct {
/// Look, all perfectly documented!
pub field: usize,
other: usize,
}
/// Nothing shady going on here. Just a bunch of well-documented code. (cough)
pub fn public_fn() {}

View File

@ -0,0 +1,7 @@
+-------------------------------------+------------+------------+------------+
| File | Documented | Total | Percentage |
+-------------------------------------+------------+------------+------------+
| ...t/rustdoc-ui/coverage/private.rs | 4 | 7 | 57.1% |
+-------------------------------------+------------+------------+------------+
| Total | 4 | 7 | 57.1% |
+-------------------------------------+------------+------------+------------+

View File

@ -0,0 +1,23 @@
// compile-flags:-Z unstable-options --show-coverage
// compile-pass
//! gotta make sure we can count statics and consts correctly, too
/// static like electricity, right?
pub static THIS_STATIC: usize = 0;
/// (it's not electricity, is it)
pub const THIS_CONST: usize = 1;
/// associated consts show up separately, but let's throw them in as well
pub trait SomeTrait {
/// just like that, yeah
const ASSOC_CONST: usize;
}
pub struct SomeStruct;
impl SomeStruct {
/// wait, structs can have them too, can't forget those
pub const ASSOC_CONST: usize = 100;
}

View File

@ -0,0 +1,7 @@
+-------------------------------------+------------+------------+------------+
| File | Documented | Total | Percentage |
+-------------------------------------+------------+------------+------------+
| ...oc-ui/coverage/statics-consts.rs | 6 | 7 | 85.7% |
+-------------------------------------+------------+------------+------------+
| Total | 6 | 7 | 85.7% |
+-------------------------------------+------------+------------+------------+

View File

@ -0,0 +1,37 @@
// compile-flags:-Z unstable-options --show-coverage
// compile-pass
#![feature(trait_alias)]
/// look at this trait right here
pub trait ThisTrait {
/// that's a trait all right
fn right_here(&self);
/// even the provided functions show up as trait methods
fn aww_yeah(&self) {}
/// gotta check those associated types, they're slippery
type SomeType;
}
/// so what happens if we take some struct...
pub struct SomeStruct;
/// ...and slap this trait on it?
impl ThisTrait for SomeStruct {
/// nothing! trait impls are totally ignored in this calculation, sorry.
fn right_here(&self) {}
type SomeType = String;
}
/// but what about those aliases? i hear they're pretty exotic
pub trait MyAlias = ThisTrait + Send + Sync;
// FIXME(58624): once rustdoc can process existential types, we need to make sure they're counted
// /// woah, getting all existential in here
// pub existential type ThisExists: ThisTrait;
//
// /// why don't we get a little more concrete
// pub fn defines() -> ThisExists { SomeStruct {} }

View File

@ -0,0 +1,7 @@
+-------------------------------------+------------+------------+------------+
| File | Documented | Total | Percentage |
+-------------------------------------+------------+------------+------------+
| ...st/rustdoc-ui/coverage/traits.rs | 6 | 7 | 85.7% |
+-------------------------------------+------------+------------+------------+
| Total | 6 | 7 | 85.7% |
+-------------------------------------+------------+------------+------------+

View File

@ -0,0 +1,25 @@
error[E0716]: temporary value dropped while borrowed
--> $DIR/const-ptr-nonnull.rs:4:37
|
LL | let x: &'static NonNull<u32> = &(NonNull::dangling());
| --------------------- ^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
| |
| type annotation requires that borrow lasts for `'static`
...
LL | }
| - temporary value is freed at the end of this statement
error[E0716]: temporary value dropped while borrowed
--> $DIR/const-ptr-nonnull.rs:9:37
|
LL | let x: &'static NonNull<u32> = &(non_null.cast());
| --------------------- ^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
| |
| type annotation requires that borrow lasts for `'static`
LL | //~^ ERROR borrowed value does not live long enough
LL | }
| - temporary value is freed at the end of this statement
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0716`.

View File

@ -0,0 +1,11 @@
use std::ptr::NonNull;
fn main() {
let x: &'static NonNull<u32> = &(NonNull::dangling());
//~^ ERROR borrowed value does not live long enough
let mut i: i32 = 10;
let non_null = NonNull::new(&mut i).unwrap();
let x: &'static NonNull<u32> = &(non_null.cast());
//~^ ERROR borrowed value does not live long enough
}

View File

@ -0,0 +1,25 @@
error[E0597]: borrowed value does not live long enough
--> $DIR/const-ptr-nonnull.rs:4:37
|
LL | let x: &'static NonNull<u32> = &(NonNull::dangling());
| ^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
...
LL | }
| - temporary value only lives until here
|
= note: borrowed value must be valid for the static lifetime...
error[E0597]: borrowed value does not live long enough
--> $DIR/const-ptr-nonnull.rs:9:37
|
LL | let x: &'static NonNull<u32> = &(non_null.cast());
| ^^^^^^^^^^^^^^^^^ temporary value does not live long enough
LL | //~^ ERROR borrowed value does not live long enough
LL | }
| - temporary value only lives until here
|
= note: borrowed value must be valid for the static lifetime...
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0597`.

View File

@ -0,0 +1,14 @@
error[E0716]: temporary value dropped while borrowed
--> $DIR/const-ptr-unique.rs:8:33
|
LL | let x: &'static *mut u32 = &(unique.as_ptr());
| ----------------- ^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
| |
| type annotation requires that borrow lasts for `'static`
LL | //~^ ERROR borrowed value does not live long enough
LL | }
| - temporary value is freed at the end of this statement
error: aborting due to previous error
For more information about this error, try `rustc --explain E0716`.

View File

@ -0,0 +1,10 @@
#![feature(ptr_internals)]
use std::ptr::Unique;
fn main() {
let mut i: u32 = 10;
let unique = Unique::new(&mut i).unwrap();
let x: &'static *mut u32 = &(unique.as_ptr());
//~^ ERROR borrowed value does not live long enough
}

View File

@ -0,0 +1,14 @@
error[E0597]: borrowed value does not live long enough
--> $DIR/const-ptr-unique.rs:8:33
|
LL | let x: &'static *mut u32 = &(unique.as_ptr());
| ^^^^^^^^^^^^^^^^^ temporary value does not live long enough
LL | //~^ ERROR borrowed value does not live long enough
LL | }
| - temporary value only lives until here
|
= note: borrowed value must be valid for the static lifetime...
error: aborting due to previous error
For more information about this error, try `rustc --explain E0597`.

View File

@ -8,6 +8,7 @@ struct NoData<T>;
impl<T> Foo for T where NoData<T>: Foo {
//~^ ERROR: overflow evaluating the requirement
fn answer(self) {
//~^ ERROR: overflow evaluating the requirement
let val: NoData<T> = NoData;
}
}

View File

@ -12,6 +12,7 @@ error[E0275]: overflow evaluating the requirement `NoData<NoData<NoData<NoData<N
LL | / impl<T> Foo for T where NoData<T>: Foo {
LL | | //~^ ERROR: overflow evaluating the requirement
LL | | fn answer(self) {
LL | | //~^ ERROR: overflow evaluating the requirement
LL | | let val: NoData<T> = NoData;
LL | | }
LL | | }
@ -87,7 +88,86 @@ note: required by `Foo`
LL | trait Foo {
| ^^^^^^^^^
error: aborting due to 2 previous errors
error[E0275]: overflow evaluating the requirement `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Foo`
--> $DIR/issue-20413.rs:10:3
|
LL | / fn answer(self) {
LL | | //~^ ERROR: overflow evaluating the requirement
LL | | let val: NoData<T> = NoData;
LL | | }
| |___^
|
= help: consider adding a `#![recursion_limit="128"]` attribute to your crate
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<T>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<T>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<T>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<T>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<T>`
note: required by `Foo`
--> $DIR/issue-20413.rs:1:1
|
LL | trait Foo {
| ^^^^^^^^^
error: aborting due to 3 previous errors
Some errors occurred: E0275, E0392.
For more information about an error, try `rustc --explain E0275`.

View File

@ -7,6 +7,7 @@ struct FooStruct;
impl Foo for FooStruct {
//~^ ERROR overflow evaluating the requirement `<FooStruct as Foo>::A`
type A = <FooStruct as Foo>::A;
//~^ ERROR overflow evaluating the requirement `<FooStruct as Foo>::A`
}
fn main() {}

View File

@ -4,6 +4,12 @@ error[E0275]: overflow evaluating the requirement `<FooStruct as Foo>::A`
LL | impl Foo for FooStruct {
| ^^^
error: aborting due to previous error
error[E0275]: overflow evaluating the requirement `<FooStruct as Foo>::A`
--> $DIR/issue-21946.rs:9:5
|
LL | type A = <FooStruct as Foo>::A;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0275`.

View File

@ -7,6 +7,7 @@ struct GetNext<T: Next> { t: T }
impl<T: Next> Next for GetNext<T> {
//~^ ERROR overflow evaluating the requirement
type Next = <GetNext<T> as Next>::Next;
//~^ ERROR overflow evaluating the requirement
}
fn main() {}

View File

@ -4,6 +4,12 @@ error[E0275]: overflow evaluating the requirement `<GetNext<T> as Next>::Next`
LL | impl<T: Next> Next for GetNext<T> {
| ^^^^
error: aborting due to previous error
error[E0275]: overflow evaluating the requirement `<GetNext<T> as Next>::Next`
--> $DIR/issue-23122-1.rs:9:5
|
LL | type Next = <GetNext<T> as Next>::Next;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0275`.

View File

@ -7,6 +7,7 @@ struct GetNext<T: Next> { t: T }
impl<T: Next> Next for GetNext<T> {
//~^ ERROR overflow evaluating the requirement
type Next = <GetNext<T::Next> as Next>::Next;
//~^ ERROR overflow evaluating the requirement
}
fn main() {}

View File

@ -7,6 +7,15 @@ LL | impl<T: Next> Next for GetNext<T> {
= help: consider adding a `#![recursion_limit="128"]` attribute to your crate
= note: required because of the requirements on the impl of `Next` for `GetNext<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>`
error: aborting due to previous error
error[E0275]: overflow evaluating the requirement `<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next: std::marker::Sized`
--> $DIR/issue-23122-2.rs:9:5
|
LL | type Next = <GetNext<T::Next> as Next>::Next;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider adding a `#![recursion_limit="128"]` attribute to your crate
= note: required because of the requirements on the impl of `Next` for `GetNext<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0275`.

View File

@ -0,0 +1,11 @@
#![feature(unwind_attributes)]
#[unwind]
//~^ ERROR attribute must be of the form
extern "C" fn f1() {}
#[unwind = ""]
//~^ ERROR attribute must be of the form
extern "C" fn f2() {}
fn main() {}

View File

@ -0,0 +1,14 @@
error: attribute must be of the form `#[unwind(allowed|aborts)]`
--> $DIR/malformed-unwind-1.rs:3:1
|
LL | #[unwind]
| ^^^^^^^^^
error: attribute must be of the form `#[unwind(allowed|aborts)]`
--> $DIR/malformed-unwind-1.rs:7:1
|
LL | #[unwind = ""]
| ^^^^^^^^^^^^^^
error: aborting due to 2 previous errors

View File

@ -0,0 +1,11 @@
#![feature(unwind_attributes)]
#[unwind(allowed, aborts)]
//~^ ERROR malformed `#[unwind]` attribute
extern "C" fn f1() {}
#[unwind(unsupported)]
//~^ ERROR malformed `#[unwind]` attribute
extern "C" fn f2() {}
fn main() {}

View File

@ -0,0 +1,15 @@
error[E0633]: malformed `#[unwind]` attribute
--> $DIR/malformed-unwind-2.rs:3:1
|
LL | #[unwind(allowed, aborts)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0633]: malformed `#[unwind]` attribute
--> $DIR/malformed-unwind-2.rs:7:1
|
LL | #[unwind(unsupported)]
| ^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0633`.

View File

@ -1,3 +1,21 @@
error[E0446]: private type `m::Priv` in public interface
--> $DIR/private-inferred-type.rs:61:36
|
LL | struct Priv;
| - `m::Priv` declared as private
...
LL | impl TraitWithAssocTy for u8 { type AssocTy = Priv; }
| ^^^^^^^^^^^^^^^^^^^^ can't leak private type
error[E0446]: private type `adjust::S2` in public interface
--> $DIR/private-inferred-type.rs:83:9
|
LL | struct S2;
| - `adjust::S2` declared as private
...
LL | type Target = S2Alias; //~ ERROR private type `adjust::S2` in public interface
| ^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
error: type `m::Priv` is private
--> $DIR/private-inferred-type.rs:97:9
|
@ -202,24 +220,6 @@ error: type `m::Priv` is private
LL | match a { //~ ERROR type `m::Priv` is private
| ^
error[E0446]: private type `m::Priv` in public interface
--> $DIR/private-inferred-type.rs:61:36
|
LL | struct Priv;
| - `m::Priv` declared as private
...
LL | impl TraitWithAssocTy for u8 { type AssocTy = Priv; }
| ^^^^^^^^^^^^^^^^^^^^ can't leak private type
error[E0446]: private type `adjust::S2` in public interface
--> $DIR/private-inferred-type.rs:83:9
|
LL | struct S2;
| - `adjust::S2` declared as private
...
LL | type Target = S2Alias; //~ ERROR private type `adjust::S2` in public interface
| ^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
error: aborting due to 33 previous errors
For more information about this error, try `rustc --explain E0446`.

View File

@ -358,6 +358,7 @@ impl Builder {
self.package("rust-src", &mut manifest.pkg, &["*"]);
self.package("rls-preview", &mut manifest.pkg, HOSTS);
self.package("clippy-preview", &mut manifest.pkg, HOSTS);
self.package("miri", &mut manifest.pkg, HOSTS);
self.package("rustfmt-preview", &mut manifest.pkg, HOSTS);
self.package("rust-analysis", &mut manifest.pkg, TARGETS);
self.package("llvm-tools-preview", &mut manifest.pkg, TARGETS);
@ -375,7 +376,7 @@ impl Builder {
&["rustc", "cargo", "rust-std", "rust-mingw",
"rust-docs", "rustfmt-preview", "clippy-preview",
"rls-preview", "rust-src", "llvm-tools-preview",
"lldb-preview", "rust-analysis"]);
"lldb-preview", "rust-analysis", "miri"]);
manifest.renames.insert("rls".to_owned(), Rename { to: "rls-preview".to_owned() });
manifest.renames.insert("rustfmt".to_owned(), Rename { to: "rustfmt-preview".to_owned() });
@ -422,6 +423,7 @@ impl Builder {
// weren't built
extensions.extend(vec![
Component { pkg: "clippy-preview".to_string(), target: host.to_string() },
Component { pkg: "miri".to_string(), target: host.to_string() },
Component { pkg: "rls-preview".to_string(), target: host.to_string() },
Component { pkg: "rustfmt-preview".to_string(), target: host.to_string() },
Component { pkg: "llvm-tools-preview".to_string(), target: host.to_string() },