mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-09 05:23:07 +00:00
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:
commit
26b4cb4848
@ -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
|
||||
|
@ -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))
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
|
@ -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")]
|
||||
|
@ -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());
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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}, {}}
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
});
|
||||
});
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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()
|
||||
|
@ -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 {
|
||||
|
@ -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!()); }
|
||||
|
@ -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(
|
||||
|
@ -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.
|
||||
|
@ -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));
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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>(
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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),
|
||||
|
@ -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<'_>) {
|
||||
|
@ -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,
|
||||
|
@ -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) => {
|
||||
|
@ -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 }
|
||||
|
@ -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),
|
||||
};
|
||||
|
@ -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>
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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>) {
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
166
src/librustdoc/passes/calculate_doc_coverage.rs
Normal file
166
src/librustdoc/passes/calculate_doc_coverage.rs
Normal 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)
|
||||
}
|
||||
}
|
@ -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 => &[],
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -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))),
|
||||
|
@ -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>,
|
||||
|
35
src/test/debuginfo/empty-string.rs
Normal file
35
src/test/debuginfo/empty-string.rs
Normal 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() {}
|
17
src/test/run-pass/consts/const-ptr-nonnull.rs
Normal file
17
src/test/run-pass/consts/const-ptr-nonnull.rs
Normal 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()));
|
||||
}
|
15
src/test/run-pass/consts/const-ptr-unique.rs
Normal file
15
src/test/run-pass/consts/const-ptr-unique.rs
Normal 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()));
|
||||
}
|
50
src/test/rustdoc-ui/coverage/basic.rs
Normal file
50
src/test/rustdoc-ui/coverage/basic.rs
Normal 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;
|
||||
}
|
7
src/test/rustdoc-ui/coverage/basic.stdout
Normal file
7
src/test/rustdoc-ui/coverage/basic.stdout
Normal file
@ -0,0 +1,7 @@
|
||||
+-------------------------------------+------------+------------+------------+
|
||||
| File | Documented | Total | Percentage |
|
||||
+-------------------------------------+------------+------------+------------+
|
||||
| ...est/rustdoc-ui/coverage/basic.rs | 7 | 14 | 50.0% |
|
||||
+-------------------------------------+------------+------------+------------+
|
||||
| Total | 7 | 14 | 50.0% |
|
||||
+-------------------------------------+------------+------------+------------+
|
4
src/test/rustdoc-ui/coverage/empty.rs
Normal file
4
src/test/rustdoc-ui/coverage/empty.rs
Normal 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
|
7
src/test/rustdoc-ui/coverage/empty.stdout
Normal file
7
src/test/rustdoc-ui/coverage/empty.stdout
Normal file
@ -0,0 +1,7 @@
|
||||
+-------------------------------------+------------+------------+------------+
|
||||
| File | Documented | Total | Percentage |
|
||||
+-------------------------------------+------------+------------+------------+
|
||||
| ...est/rustdoc-ui/coverage/empty.rs | 0 | 1 | 0.0% |
|
||||
+-------------------------------------+------------+------------+------------+
|
||||
| Total | 0 | 1 | 0.0% |
|
||||
+-------------------------------------+------------+------------+------------+
|
22
src/test/rustdoc-ui/coverage/enums.rs
Normal file
22
src/test/rustdoc-ui/coverage/enums.rs
Normal 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 {}
|
7
src/test/rustdoc-ui/coverage/enums.stdout
Normal file
7
src/test/rustdoc-ui/coverage/enums.stdout
Normal file
@ -0,0 +1,7 @@
|
||||
+-------------------------------------+------------+------------+------------+
|
||||
| File | Documented | Total | Percentage |
|
||||
+-------------------------------------+------------+------------+------------+
|
||||
| ...est/rustdoc-ui/coverage/enums.rs | 6 | 8 | 75.0% |
|
||||
+-------------------------------------+------------+------------+------------+
|
||||
| Total | 6 | 8 | 75.0% |
|
||||
+-------------------------------------+------------+------------+------------+
|
15
src/test/rustdoc-ui/coverage/exotic.rs
Normal file
15
src/test/rustdoc-ui/coverage/exotic.rs
Normal 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 {}
|
8
src/test/rustdoc-ui/coverage/exotic.stdout
Normal file
8
src/test/rustdoc-ui/coverage/exotic.stdout
Normal 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% |
|
||||
+-------------------------------------+------------+------------+------------+
|
21
src/test/rustdoc-ui/coverage/private.rs
Normal file
21
src/test/rustdoc-ui/coverage/private.rs
Normal 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() {}
|
7
src/test/rustdoc-ui/coverage/private.stdout
Normal file
7
src/test/rustdoc-ui/coverage/private.stdout
Normal file
@ -0,0 +1,7 @@
|
||||
+-------------------------------------+------------+------------+------------+
|
||||
| File | Documented | Total | Percentage |
|
||||
+-------------------------------------+------------+------------+------------+
|
||||
| ...t/rustdoc-ui/coverage/private.rs | 4 | 7 | 57.1% |
|
||||
+-------------------------------------+------------+------------+------------+
|
||||
| Total | 4 | 7 | 57.1% |
|
||||
+-------------------------------------+------------+------------+------------+
|
23
src/test/rustdoc-ui/coverage/statics-consts.rs
Normal file
23
src/test/rustdoc-ui/coverage/statics-consts.rs
Normal 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;
|
||||
}
|
7
src/test/rustdoc-ui/coverage/statics-consts.stdout
Normal file
7
src/test/rustdoc-ui/coverage/statics-consts.stdout
Normal file
@ -0,0 +1,7 @@
|
||||
+-------------------------------------+------------+------------+------------+
|
||||
| File | Documented | Total | Percentage |
|
||||
+-------------------------------------+------------+------------+------------+
|
||||
| ...oc-ui/coverage/statics-consts.rs | 6 | 7 | 85.7% |
|
||||
+-------------------------------------+------------+------------+------------+
|
||||
| Total | 6 | 7 | 85.7% |
|
||||
+-------------------------------------+------------+------------+------------+
|
37
src/test/rustdoc-ui/coverage/traits.rs
Normal file
37
src/test/rustdoc-ui/coverage/traits.rs
Normal 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 {} }
|
7
src/test/rustdoc-ui/coverage/traits.stdout
Normal file
7
src/test/rustdoc-ui/coverage/traits.stdout
Normal file
@ -0,0 +1,7 @@
|
||||
+-------------------------------------+------------+------------+------------+
|
||||
| File | Documented | Total | Percentage |
|
||||
+-------------------------------------+------------+------------+------------+
|
||||
| ...st/rustdoc-ui/coverage/traits.rs | 6 | 7 | 85.7% |
|
||||
+-------------------------------------+------------+------------+------------+
|
||||
| Total | 6 | 7 | 85.7% |
|
||||
+-------------------------------------+------------+------------+------------+
|
25
src/test/ui/consts/const-ptr-nonnull.nll.stderr
Normal file
25
src/test/ui/consts/const-ptr-nonnull.nll.stderr
Normal 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`.
|
11
src/test/ui/consts/const-ptr-nonnull.rs
Normal file
11
src/test/ui/consts/const-ptr-nonnull.rs
Normal 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
|
||||
}
|
25
src/test/ui/consts/const-ptr-nonnull.stderr
Normal file
25
src/test/ui/consts/const-ptr-nonnull.stderr
Normal 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`.
|
14
src/test/ui/consts/const-ptr-unique.nll.stderr
Normal file
14
src/test/ui/consts/const-ptr-unique.nll.stderr
Normal 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`.
|
10
src/test/ui/consts/const-ptr-unique.rs
Normal file
10
src/test/ui/consts/const-ptr-unique.rs
Normal 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
|
||||
}
|
14
src/test/ui/consts/const-ptr-unique.stderr
Normal file
14
src/test/ui/consts/const-ptr-unique.stderr
Normal 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`.
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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`.
|
||||
|
@ -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() {}
|
||||
|
@ -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`.
|
||||
|
@ -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() {}
|
||||
|
@ -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`.
|
||||
|
@ -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() {}
|
||||
|
@ -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`.
|
||||
|
11
src/test/ui/malformed/malformed-unwind-1.rs
Normal file
11
src/test/ui/malformed/malformed-unwind-1.rs
Normal 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() {}
|
14
src/test/ui/malformed/malformed-unwind-1.stderr
Normal file
14
src/test/ui/malformed/malformed-unwind-1.stderr
Normal 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
|
||||
|
11
src/test/ui/malformed/malformed-unwind-2.rs
Normal file
11
src/test/ui/malformed/malformed-unwind-2.rs
Normal 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() {}
|
15
src/test/ui/malformed/malformed-unwind-2.stderr
Normal file
15
src/test/ui/malformed/malformed-unwind-2.stderr
Normal 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`.
|
@ -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`.
|
||||
|
@ -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() },
|
||||
|
Loading…
Reference in New Issue
Block a user