Auto merge of #65793 - Centril:rollup-v40xke9, r=Centril
Rollup of 9 pull requests Successful merges: - #62959 (Add by-value iterator for arrays ) - #65390 (Add long error explanation for E0576) - #65408 (reorder config.toml.example options and add one missing option) - #65414 (ignore uninhabited non-exhaustive variant fields) - #65666 (Deprecated proc_macro doesn't trigger warning on build library) - #65742 (Pre-expansion gate most of the things) - #65747 (Adjust the tracking issue for `untagged_unions`.) - #65763 (Changed APIT with explicit generic args span to specific arg spans) - #65775 (Fix more `ReEmpty` ICEs) Failed merges: - #65519 (trait-based structural match implementation) r? @ghost
This commit is contained in:
commit
dd2df8f97d
71 changed files with 1215 additions and 278 deletions
|
|
@ -258,10 +258,9 @@
|
|||
[rust]
|
||||
|
||||
# Whether or not to optimize the compiler and standard library.
|
||||
#
|
||||
# Note: the slowness of the non optimized compiler compiling itself usually
|
||||
# outweighs the time gains in not doing optimizations, therefore a
|
||||
# full bootstrap takes much more time with `optimize` set to false.
|
||||
# WARNING: Building with optimize = false is NOT SUPPORTED. Due to bootstrapping,
|
||||
# building without optimizations takes much longer than optimizing. Further, some platforms
|
||||
# fail to build without this optimization (c.f. #65352).
|
||||
#optimize = true
|
||||
|
||||
# Indicates that the build should be configured for debugging Rust. A
|
||||
|
|
@ -341,6 +340,9 @@
|
|||
# nightly features
|
||||
#channel = "dev"
|
||||
|
||||
# The root location of the MUSL installation directory.
|
||||
#musl-root = "..."
|
||||
|
||||
# By default the `rustc` executable is built with `-Wl,-rpath` flags on Unix
|
||||
# platforms to ensure that the compiler is usable by default from the build
|
||||
# directory (as it links to a number of dynamic libraries). This may not be
|
||||
|
|
|
|||
|
|
@ -200,16 +200,15 @@ struct Build {
|
|||
target: Vec<String>,
|
||||
cargo: Option<String>,
|
||||
rustc: Option<String>,
|
||||
low_priority: Option<bool>,
|
||||
compiler_docs: Option<bool>,
|
||||
docs: Option<bool>,
|
||||
compiler_docs: Option<bool>,
|
||||
submodules: Option<bool>,
|
||||
fast_submodules: Option<bool>,
|
||||
gdb: Option<String>,
|
||||
locked_deps: Option<bool>,
|
||||
vendor: Option<bool>,
|
||||
nodejs: Option<String>,
|
||||
python: Option<String>,
|
||||
locked_deps: Option<bool>,
|
||||
vendor: Option<bool>,
|
||||
full_bootstrap: Option<bool>,
|
||||
extended: Option<bool>,
|
||||
tools: Option<HashSet<String>>,
|
||||
|
|
@ -217,6 +216,7 @@ struct Build {
|
|||
sanitizers: Option<bool>,
|
||||
profiler: Option<bool>,
|
||||
cargo_native_static: Option<bool>,
|
||||
low_priority: Option<bool>,
|
||||
configure_args: Option<Vec<String>>,
|
||||
local_rebuild: Option<bool>,
|
||||
print_step_timings: Option<bool>,
|
||||
|
|
@ -228,11 +228,11 @@ struct Build {
|
|||
struct Install {
|
||||
prefix: Option<String>,
|
||||
sysconfdir: Option<String>,
|
||||
datadir: Option<String>,
|
||||
docdir: Option<String>,
|
||||
bindir: Option<String>,
|
||||
libdir: Option<String>,
|
||||
mandir: Option<String>,
|
||||
datadir: Option<String>,
|
||||
|
||||
// standard paths, currently unused
|
||||
infodir: Option<String>,
|
||||
|
|
@ -243,14 +243,14 @@ struct Install {
|
|||
#[derive(Deserialize, Default)]
|
||||
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
|
||||
struct Llvm {
|
||||
ccache: Option<StringOrBool>,
|
||||
ninja: Option<bool>,
|
||||
assertions: Option<bool>,
|
||||
optimize: Option<bool>,
|
||||
thin_lto: Option<bool>,
|
||||
release_debuginfo: Option<bool>,
|
||||
assertions: Option<bool>,
|
||||
ccache: Option<StringOrBool>,
|
||||
version_check: Option<bool>,
|
||||
static_libstdcpp: Option<bool>,
|
||||
ninja: Option<bool>,
|
||||
targets: Option<String>,
|
||||
experimental_targets: Option<String>,
|
||||
link_jobs: Option<u32>,
|
||||
|
|
@ -293,6 +293,7 @@ impl Default for StringOrBool {
|
|||
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
|
||||
struct Rust {
|
||||
optimize: Option<bool>,
|
||||
debug: Option<bool>,
|
||||
codegen_units: Option<u32>,
|
||||
codegen_units_std: Option<u32>,
|
||||
debug_assertions: Option<bool>,
|
||||
|
|
@ -301,25 +302,24 @@ struct Rust {
|
|||
debuginfo_level_std: Option<u32>,
|
||||
debuginfo_level_tools: Option<u32>,
|
||||
debuginfo_level_tests: Option<u32>,
|
||||
parallel_compiler: Option<bool>,
|
||||
backtrace: Option<bool>,
|
||||
incremental: Option<bool>,
|
||||
parallel_compiler: Option<bool>,
|
||||
default_linker: Option<String>,
|
||||
channel: Option<String>,
|
||||
musl_root: Option<String>,
|
||||
rpath: Option<bool>,
|
||||
verbose_tests: Option<bool>,
|
||||
optimize_tests: Option<bool>,
|
||||
codegen_tests: Option<bool>,
|
||||
ignore_git: Option<bool>,
|
||||
debug: Option<bool>,
|
||||
dist_src: Option<bool>,
|
||||
verbose_tests: Option<bool>,
|
||||
incremental: Option<bool>,
|
||||
save_toolstates: Option<String>,
|
||||
codegen_backends: Option<Vec<String>>,
|
||||
codegen_backends_dir: Option<String>,
|
||||
lld: Option<bool>,
|
||||
lldb: Option<bool>,
|
||||
llvm_tools: Option<bool>,
|
||||
lldb: Option<bool>,
|
||||
deny_warnings: Option<bool>,
|
||||
backtrace_on_ice: Option<bool>,
|
||||
verify_llvm_ir: Option<bool>,
|
||||
|
|
@ -333,13 +333,13 @@ struct Rust {
|
|||
#[derive(Deserialize, Default)]
|
||||
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
|
||||
struct TomlTarget {
|
||||
llvm_config: Option<String>,
|
||||
llvm_filecheck: Option<String>,
|
||||
cc: Option<String>,
|
||||
cxx: Option<String>,
|
||||
ar: Option<String>,
|
||||
ranlib: Option<String>,
|
||||
linker: Option<String>,
|
||||
llvm_config: Option<String>,
|
||||
llvm_filecheck: Option<String>,
|
||||
android_ndk: Option<String>,
|
||||
crt_static: Option<bool>,
|
||||
musl_root: Option<String>,
|
||||
|
|
|
|||
266
src/libcore/array/iter.rs
Normal file
266
src/libcore/array/iter.rs
Normal file
|
|
@ -0,0 +1,266 @@
|
|||
//! Defines the `IntoIter` owned iterator for arrays.
|
||||
|
||||
use crate::{
|
||||
fmt,
|
||||
iter::{ExactSizeIterator, FusedIterator, TrustedLen},
|
||||
mem::{self, MaybeUninit},
|
||||
ops::Range,
|
||||
ptr,
|
||||
};
|
||||
use super::LengthAtMost32;
|
||||
|
||||
|
||||
/// A by-value [array] iterator.
|
||||
///
|
||||
/// [array]: ../../std/primitive.array.html
|
||||
#[unstable(feature = "array_value_iter", issue = "0")]
|
||||
pub struct IntoIter<T, const N: usize>
|
||||
where
|
||||
[T; N]: LengthAtMost32,
|
||||
{
|
||||
/// This is the array we are iterating over.
|
||||
///
|
||||
/// Elements with index `i` where `alive.start <= i < alive.end` have not
|
||||
/// been yielded yet and are valid array entries. Elements with indices `i
|
||||
/// < alive.start` or `i >= alive.end` have been yielded already and must
|
||||
/// not be accessed anymore! Those dead elements might even be in a
|
||||
/// completely uninitialized state!
|
||||
///
|
||||
/// So the invariants are:
|
||||
/// - `data[alive]` is alive (i.e. contains valid elements)
|
||||
/// - `data[..alive.start]` and `data[alive.end..]` are dead (i.e. the
|
||||
/// elements were already read and must not be touched anymore!)
|
||||
data: [MaybeUninit<T>; N],
|
||||
|
||||
/// The elements in `data` that have not been yielded yet.
|
||||
///
|
||||
/// Invariants:
|
||||
/// - `alive.start <= alive.end`
|
||||
/// - `alive.end <= N`
|
||||
alive: Range<usize>,
|
||||
}
|
||||
|
||||
impl<T, const N: usize> IntoIter<T, {N}>
|
||||
where
|
||||
[T; N]: LengthAtMost32,
|
||||
{
|
||||
/// Creates a new iterator over the given `array`.
|
||||
///
|
||||
/// *Note*: this method might never get stabilized and/or removed in the
|
||||
/// future as there will likely be another, preferred way of obtaining this
|
||||
/// iterator (either via `IntoIterator` for arrays or via another way).
|
||||
#[unstable(feature = "array_value_iter", issue = "0")]
|
||||
pub fn new(array: [T; N]) -> Self {
|
||||
// The transmute here is actually safe. The docs of `MaybeUninit`
|
||||
// promise:
|
||||
//
|
||||
// > `MaybeUninit<T>` is guaranteed to have the same size and alignment
|
||||
// > as `T`.
|
||||
//
|
||||
// The docs even show a transmute from an array of `MaybeUninit<T>` to
|
||||
// an array of `T`.
|
||||
//
|
||||
// With that, this initialization satisfies the invariants.
|
||||
|
||||
// FIXME(LukasKalbertodt): actually use `mem::transmute` here, once it
|
||||
// works with const generics:
|
||||
// `mem::transmute::<[T; {N}], [MaybeUninit<T>; {N}]>(array)`
|
||||
//
|
||||
// Until then, we do it manually here. We first create a bitwise copy
|
||||
// but cast the pointer so that it is treated as a different type. Then
|
||||
// we forget `array` so that it is not dropped.
|
||||
let data = unsafe {
|
||||
let data = ptr::read(&array as *const [T; N] as *const [MaybeUninit<T>; N]);
|
||||
mem::forget(array);
|
||||
data
|
||||
};
|
||||
|
||||
Self {
|
||||
data,
|
||||
alive: 0..N,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an immutable slice of all elements that have not been yielded
|
||||
/// yet.
|
||||
fn as_slice(&self) -> &[T] {
|
||||
// This transmute is safe. As mentioned in `new`, `MaybeUninit` retains
|
||||
// the size and alignment of `T`. Furthermore, we know that all
|
||||
// elements within `alive` are properly initialized.
|
||||
let slice = &self.data[self.alive.clone()];
|
||||
unsafe {
|
||||
mem::transmute::<&[MaybeUninit<T>], &[T]>(slice)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[stable(feature = "array_value_iter_impls", since = "1.38.0")]
|
||||
impl<T, const N: usize> Iterator for IntoIter<T, {N}>
|
||||
where
|
||||
[T; N]: LengthAtMost32,
|
||||
{
|
||||
type Item = T;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.alive.start == self.alive.end {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Bump start index.
|
||||
//
|
||||
// From the check above we know that `alive.start != alive.end`.
|
||||
// Combine this with the invariant `alive.start <= alive.end`, we know
|
||||
// that `alive.start < alive.end`. Increasing `alive.start` by 1
|
||||
// maintains the invariant regarding `alive`. However, due to this
|
||||
// change, for a short time, the alive zone is not `data[alive]`
|
||||
// anymore, but `data[idx..alive.end]`.
|
||||
let idx = self.alive.start;
|
||||
self.alive.start += 1;
|
||||
|
||||
// Read the element from the array. This is safe: `idx` is an index
|
||||
// into the "alive" region of the array. Reading this element means
|
||||
// that `data[idx]` is regarded as dead now (i.e. do not touch). As
|
||||
// `idx` was the start of the alive-zone, the alive zone is now
|
||||
// `data[alive]` again, restoring all invariants.
|
||||
let out = unsafe { self.data.get_unchecked(idx).read() };
|
||||
|
||||
Some(out)
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let len = self.len();
|
||||
(len, Some(len))
|
||||
}
|
||||
|
||||
fn count(self) -> usize {
|
||||
self.len()
|
||||
}
|
||||
|
||||
fn last(mut self) -> Option<Self::Item> {
|
||||
self.next_back()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "array_value_iter_impls", since = "1.38.0")]
|
||||
impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, {N}>
|
||||
where
|
||||
[T; N]: LengthAtMost32,
|
||||
{
|
||||
fn next_back(&mut self) -> Option<Self::Item> {
|
||||
if self.alive.start == self.alive.end {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Decrease end index.
|
||||
//
|
||||
// From the check above we know that `alive.start != alive.end`.
|
||||
// Combine this with the invariant `alive.start <= alive.end`, we know
|
||||
// that `alive.start < alive.end`. As `alive.start` cannot be negative,
|
||||
// `alive.end` is at least 1, meaning that we can safely decrement it
|
||||
// by one. This also maintains the invariant `alive.start <=
|
||||
// alive.end`. However, due to this change, for a short time, the alive
|
||||
// zone is not `data[alive]` anymore, but `data[alive.start..alive.end
|
||||
// + 1]`.
|
||||
self.alive.end -= 1;
|
||||
|
||||
// Read the element from the array. This is safe: `alive.end` is an
|
||||
// index into the "alive" region of the array. Compare the previous
|
||||
// comment that states that the alive region is
|
||||
// `data[alive.start..alive.end + 1]`. Reading this element means that
|
||||
// `data[alive.end]` is regarded as dead now (i.e. do not touch). As
|
||||
// `alive.end` was the end of the alive-zone, the alive zone is now
|
||||
// `data[alive]` again, restoring all invariants.
|
||||
let out = unsafe { self.data.get_unchecked(self.alive.end).read() };
|
||||
|
||||
Some(out)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "array_value_iter_impls", since = "1.38.0")]
|
||||
impl<T, const N: usize> Drop for IntoIter<T, {N}>
|
||||
where
|
||||
[T; N]: LengthAtMost32,
|
||||
{
|
||||
fn drop(&mut self) {
|
||||
// We simply drop each element via `for_each`. This should not incur
|
||||
// any significant runtime overhead and avoids adding another `unsafe`
|
||||
// block.
|
||||
self.by_ref().for_each(drop);
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "array_value_iter_impls", since = "1.38.0")]
|
||||
impl<T, const N: usize> ExactSizeIterator for IntoIter<T, {N}>
|
||||
where
|
||||
[T; N]: LengthAtMost32,
|
||||
{
|
||||
fn len(&self) -> usize {
|
||||
// Will never underflow due to the invariant `alive.start <=
|
||||
// alive.end`.
|
||||
self.alive.end - self.alive.start
|
||||
}
|
||||
fn is_empty(&self) -> bool {
|
||||
self.alive.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "array_value_iter_impls", since = "1.38.0")]
|
||||
impl<T, const N: usize> FusedIterator for IntoIter<T, {N}>
|
||||
where
|
||||
[T; N]: LengthAtMost32,
|
||||
{}
|
||||
|
||||
// The iterator indeed reports the correct length. The number of "alive"
|
||||
// elements (that will still be yielded) is the length of the range `alive`.
|
||||
// This range is decremented in length in either `next` or `next_back`. It is
|
||||
// always decremented by 1 in those methods, but only if `Some(_)` is returned.
|
||||
#[stable(feature = "array_value_iter_impls", since = "1.38.0")]
|
||||
unsafe impl<T, const N: usize> TrustedLen for IntoIter<T, {N}>
|
||||
where
|
||||
[T; N]: LengthAtMost32,
|
||||
{}
|
||||
|
||||
#[stable(feature = "array_value_iter_impls", since = "1.38.0")]
|
||||
impl<T: Clone, const N: usize> Clone for IntoIter<T, {N}>
|
||||
where
|
||||
[T; N]: LengthAtMost32,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
unsafe {
|
||||
// This creates a new uninitialized array. Note that the `assume_init`
|
||||
// refers to the array, not the individual elements. And it is Ok if
|
||||
// the array is in an uninitialized state as all elements may be
|
||||
// uninitialized (all bit patterns are valid). Compare the
|
||||
// `MaybeUninit` docs for more information.
|
||||
let mut new_data: [MaybeUninit<T>; N] = MaybeUninit::uninit().assume_init();
|
||||
|
||||
// Clone all alive elements.
|
||||
for idx in self.alive.clone() {
|
||||
// The element at `idx` in the old array is alive, so we can
|
||||
// safely call `get_ref()`. We then clone it, and write the
|
||||
// clone into the new array.
|
||||
let clone = self.data.get_unchecked(idx).get_ref().clone();
|
||||
new_data.get_unchecked_mut(idx).write(clone);
|
||||
}
|
||||
|
||||
Self {
|
||||
data: new_data,
|
||||
alive: self.alive.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "array_value_iter_impls", since = "1.38.0")]
|
||||
impl<T: fmt::Debug, const N: usize> fmt::Debug for IntoIter<T, {N}>
|
||||
where
|
||||
[T; N]: LengthAtMost32,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
// Only print the elements that were not yielded yet: we cannot
|
||||
// access the yielded elements anymore.
|
||||
f.debug_tuple("IntoIter")
|
||||
.field(&self.as_slice())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
|
@ -14,6 +14,13 @@ use crate::hash::{Hash, self};
|
|||
use crate::marker::Unsize;
|
||||
use crate::slice::{Iter, IterMut};
|
||||
|
||||
#[cfg(not(bootstrap))]
|
||||
mod iter;
|
||||
|
||||
#[cfg(not(bootstrap))]
|
||||
#[unstable(feature = "array_value_iter", issue = "0")]
|
||||
pub use iter::IntoIter;
|
||||
|
||||
/// Utility trait implemented only on arrays of fixed size
|
||||
///
|
||||
/// This trait can be used to implement other traits on fixed-size arrays
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
use core::array::FixedSizeArray;
|
||||
use core::array::{FixedSizeArray, IntoIter};
|
||||
use core::convert::TryFrom;
|
||||
|
||||
#[test]
|
||||
|
|
@ -40,3 +40,208 @@ fn array_try_from() {
|
|||
30 31 32
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn iterator_collect() {
|
||||
let arr = [0, 1, 2, 5, 9];
|
||||
let v: Vec<_> = IntoIter::new(arr.clone()).collect();
|
||||
assert_eq!(&arr[..], &v[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iterator_rev_collect() {
|
||||
let arr = [0, 1, 2, 5, 9];
|
||||
let v: Vec<_> = IntoIter::new(arr.clone()).rev().collect();
|
||||
assert_eq!(&v[..], &[9, 5, 2, 1, 0]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iterator_nth() {
|
||||
let v = [0, 1, 2, 3, 4];
|
||||
for i in 0..v.len() {
|
||||
assert_eq!(IntoIter::new(v.clone()).nth(i).unwrap(), v[i]);
|
||||
}
|
||||
assert_eq!(IntoIter::new(v.clone()).nth(v.len()), None);
|
||||
|
||||
let mut iter = IntoIter::new(v);
|
||||
assert_eq!(iter.nth(2).unwrap(), v[2]);
|
||||
assert_eq!(iter.nth(1).unwrap(), v[4]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iterator_last() {
|
||||
let v = [0, 1, 2, 3, 4];
|
||||
assert_eq!(IntoIter::new(v).last().unwrap(), 4);
|
||||
assert_eq!(IntoIter::new([0]).last().unwrap(), 0);
|
||||
|
||||
let mut it = IntoIter::new([0, 9, 2, 4]);
|
||||
assert_eq!(it.next_back(), Some(4));
|
||||
assert_eq!(it.last(), Some(2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iterator_clone() {
|
||||
let mut it = IntoIter::new([0, 2, 4, 6, 8]);
|
||||
assert_eq!(it.next(), Some(0));
|
||||
assert_eq!(it.next_back(), Some(8));
|
||||
let mut clone = it.clone();
|
||||
assert_eq!(it.next_back(), Some(6));
|
||||
assert_eq!(clone.next_back(), Some(6));
|
||||
assert_eq!(it.next_back(), Some(4));
|
||||
assert_eq!(clone.next_back(), Some(4));
|
||||
assert_eq!(it.next(), Some(2));
|
||||
assert_eq!(clone.next(), Some(2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iterator_fused() {
|
||||
let mut it = IntoIter::new([0, 9, 2]);
|
||||
assert_eq!(it.next(), Some(0));
|
||||
assert_eq!(it.next(), Some(9));
|
||||
assert_eq!(it.next(), Some(2));
|
||||
assert_eq!(it.next(), None);
|
||||
assert_eq!(it.next(), None);
|
||||
assert_eq!(it.next(), None);
|
||||
assert_eq!(it.next(), None);
|
||||
assert_eq!(it.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iterator_len() {
|
||||
let mut it = IntoIter::new([0, 1, 2, 5, 9]);
|
||||
assert_eq!(it.size_hint(), (5, Some(5)));
|
||||
assert_eq!(it.len(), 5);
|
||||
assert_eq!(it.is_empty(), false);
|
||||
|
||||
assert_eq!(it.next(), Some(0));
|
||||
assert_eq!(it.size_hint(), (4, Some(4)));
|
||||
assert_eq!(it.len(), 4);
|
||||
assert_eq!(it.is_empty(), false);
|
||||
|
||||
assert_eq!(it.next_back(), Some(9));
|
||||
assert_eq!(it.size_hint(), (3, Some(3)));
|
||||
assert_eq!(it.len(), 3);
|
||||
assert_eq!(it.is_empty(), false);
|
||||
|
||||
// Empty
|
||||
let it = IntoIter::new([] as [String; 0]);
|
||||
assert_eq!(it.size_hint(), (0, Some(0)));
|
||||
assert_eq!(it.len(), 0);
|
||||
assert_eq!(it.is_empty(), true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iterator_count() {
|
||||
let v = [0, 1, 2, 3, 4];
|
||||
assert_eq!(IntoIter::new(v.clone()).count(), 5);
|
||||
|
||||
let mut iter2 = IntoIter::new(v);
|
||||
iter2.next();
|
||||
iter2.next();
|
||||
assert_eq!(iter2.count(), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iterator_flat_map() {
|
||||
assert!((0..5).flat_map(|i| IntoIter::new([2 * i, 2 * i + 1])).eq(0..10));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iterator_debug() {
|
||||
let arr = [0, 1, 2, 5, 9];
|
||||
assert_eq!(
|
||||
format!("{:?}", IntoIter::new(arr)),
|
||||
"IntoIter([0, 1, 2, 5, 9])",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iterator_drops() {
|
||||
use core::cell::Cell;
|
||||
|
||||
// This test makes sure the correct number of elements are dropped. The `R`
|
||||
// type is just a reference to a `Cell` that is incremented when an `R` is
|
||||
// dropped.
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Foo<'a>(&'a Cell<usize>);
|
||||
|
||||
impl Drop for Foo<'_> {
|
||||
fn drop(&mut self) {
|
||||
self.0.set(self.0.get() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
fn five(i: &Cell<usize>) -> [Foo<'_>; 5] {
|
||||
// This is somewhat verbose because `Foo` does not implement `Copy`
|
||||
// since it implements `Drop`. Consequently, we cannot write
|
||||
// `[Foo(i); 5]`.
|
||||
[Foo(i), Foo(i), Foo(i), Foo(i), Foo(i)]
|
||||
}
|
||||
|
||||
// Simple: drop new iterator.
|
||||
let i = Cell::new(0);
|
||||
{
|
||||
IntoIter::new(five(&i));
|
||||
}
|
||||
assert_eq!(i.get(), 5);
|
||||
|
||||
// Call `next()` once.
|
||||
let i = Cell::new(0);
|
||||
{
|
||||
let mut iter = IntoIter::new(five(&i));
|
||||
let _x = iter.next();
|
||||
assert_eq!(i.get(), 0);
|
||||
assert_eq!(iter.count(), 4);
|
||||
assert_eq!(i.get(), 4);
|
||||
}
|
||||
assert_eq!(i.get(), 5);
|
||||
|
||||
// Check `clone` and calling `next`/`next_back`.
|
||||
let i = Cell::new(0);
|
||||
{
|
||||
let mut iter = IntoIter::new(five(&i));
|
||||
iter.next();
|
||||
assert_eq!(i.get(), 1);
|
||||
iter.next_back();
|
||||
assert_eq!(i.get(), 2);
|
||||
|
||||
let mut clone = iter.clone();
|
||||
assert_eq!(i.get(), 2);
|
||||
|
||||
iter.next();
|
||||
assert_eq!(i.get(), 3);
|
||||
|
||||
clone.next();
|
||||
assert_eq!(i.get(), 4);
|
||||
|
||||
assert_eq!(clone.count(), 2);
|
||||
assert_eq!(i.get(), 6);
|
||||
}
|
||||
assert_eq!(i.get(), 8);
|
||||
|
||||
// Check via `nth`.
|
||||
let i = Cell::new(0);
|
||||
{
|
||||
let mut iter = IntoIter::new(five(&i));
|
||||
let _x = iter.nth(2);
|
||||
assert_eq!(i.get(), 2);
|
||||
let _y = iter.last();
|
||||
assert_eq!(i.get(), 3);
|
||||
}
|
||||
assert_eq!(i.get(), 5);
|
||||
|
||||
// Check every element.
|
||||
let i = Cell::new(0);
|
||||
for (index, _x) in IntoIter::new(five(&i)).enumerate() {
|
||||
assert_eq!(i.get(), index);
|
||||
}
|
||||
assert_eq!(i.get(), 5);
|
||||
|
||||
let i = Cell::new(0);
|
||||
for (index, _x) in IntoIter::new(five(&i)).rev().enumerate() {
|
||||
assert_eq!(i.get(), index);
|
||||
}
|
||||
assert_eq!(i.get(), 5);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#![feature(slice_partition_dedup)]
|
||||
#![feature(int_error_matching)]
|
||||
#![feature(const_fn)]
|
||||
#![feature(array_value_iter)]
|
||||
#![feature(iter_partition_in_place)]
|
||||
#![feature(iter_is_partitioned)]
|
||||
#![feature(iter_order_by)]
|
||||
|
|
|
|||
|
|
@ -178,6 +178,9 @@ impl<'a, 'b, 'tcx> TypeOutlivesDelegate<'tcx> for &'a mut ConstraintConversion<'
|
|||
a: ty::Region<'tcx>,
|
||||
b: ty::Region<'tcx>,
|
||||
) {
|
||||
if let ty::ReEmpty = a {
|
||||
return;
|
||||
}
|
||||
let b = self.to_region_vid(b);
|
||||
let a = self.to_region_vid(a);
|
||||
self.add_outlives(b, a);
|
||||
|
|
@ -190,6 +193,9 @@ impl<'a, 'b, 'tcx> TypeOutlivesDelegate<'tcx> for &'a mut ConstraintConversion<'
|
|||
a: ty::Region<'tcx>,
|
||||
bound: VerifyBound<'tcx>,
|
||||
) {
|
||||
if let ty::ReEmpty = a {
|
||||
return;
|
||||
}
|
||||
let type_test = self.verify_to_type_test(kind, a, bound);
|
||||
self.add_type_test(type_test);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -394,16 +394,6 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn is_non_exhaustive_variant<'p>(&self, pattern: &'p Pat<'tcx>) -> bool {
|
||||
match *pattern.kind {
|
||||
PatKind::Variant { adt_def, variant_index, .. } => {
|
||||
let ref variant = adt_def.variants[variant_index];
|
||||
variant.is_field_list_non_exhaustive()
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_non_exhaustive_enum(&self, ty: Ty<'tcx>) -> bool {
|
||||
match ty.kind {
|
||||
ty::Adt(adt_def, ..) => adt_def.is_variant_list_non_exhaustive(),
|
||||
|
|
@ -1252,19 +1242,12 @@ pub fn is_useful<'p, 'a, 'tcx>(
|
|||
debug!("is_useful_expand_first_col: pcx={:#?}, expanding {:#?}", pcx, v[0]);
|
||||
|
||||
if let Some(constructors) = pat_constructors(cx, v[0], pcx) {
|
||||
let is_declared_nonexhaustive = cx.is_non_exhaustive_variant(v[0]) && !cx.is_local(pcx.ty);
|
||||
debug!("is_useful - expanding constructors: {:#?}, is_declared_nonexhaustive: {:?}",
|
||||
constructors, is_declared_nonexhaustive);
|
||||
|
||||
if is_declared_nonexhaustive {
|
||||
Useful
|
||||
} else {
|
||||
split_grouped_constructors(
|
||||
cx.tcx, cx.param_env, constructors, matrix, pcx.ty, pcx.span, Some(hir_id),
|
||||
).into_iter().map(|c|
|
||||
is_useful_specialized(cx, matrix, v, c, pcx.ty, witness, hir_id)
|
||||
).find(|result| result.is_useful()).unwrap_or(NotUseful)
|
||||
}
|
||||
debug!("is_useful - expanding constructors: {:#?}", constructors);
|
||||
split_grouped_constructors(
|
||||
cx.tcx, cx.param_env, constructors, matrix, pcx.ty, pcx.span, Some(hir_id),
|
||||
).into_iter().map(|c|
|
||||
is_useful_specialized(cx, matrix, v, c, pcx.ty, witness, hir_id)
|
||||
).find(|result| result.is_useful()).unwrap_or(NotUseful)
|
||||
} else {
|
||||
debug!("is_useful - expanding wildcard");
|
||||
|
||||
|
|
@ -1548,27 +1531,30 @@ fn constructor_sub_pattern_tys<'a, 'tcx>(
|
|||
// Use T as the sub pattern type of Box<T>.
|
||||
vec![substs.type_at(0)]
|
||||
} else {
|
||||
adt.variants[ctor.variant_index_for_adt(cx, adt)].fields.iter().map(|field| {
|
||||
let variant = &adt.variants[ctor.variant_index_for_adt(cx, adt)];
|
||||
let is_non_exhaustive = variant.is_field_list_non_exhaustive() && !cx.is_local(ty);
|
||||
variant.fields.iter().map(|field| {
|
||||
let is_visible = adt.is_enum()
|
||||
|| field.vis.is_accessible_from(cx.module, cx.tcx);
|
||||
if is_visible {
|
||||
let ty = field.ty(cx.tcx, substs);
|
||||
match ty.kind {
|
||||
// If the field type returned is an array of an unknown
|
||||
// size return an TyErr.
|
||||
ty::Array(_, len)
|
||||
if len.try_eval_usize(cx.tcx, cx.param_env).is_none() =>
|
||||
cx.tcx.types.err,
|
||||
_ => ty,
|
||||
}
|
||||
} else {
|
||||
// Treat all non-visible fields as TyErr. They
|
||||
// can't appear in any other pattern from
|
||||
// this match (because they are private),
|
||||
// so their type does not matter - but
|
||||
// we don't want to know they are
|
||||
// uninhabited.
|
||||
cx.tcx.types.err
|
||||
let is_uninhabited = cx.is_uninhabited(field.ty(cx.tcx, substs));
|
||||
match (is_visible, is_non_exhaustive, is_uninhabited) {
|
||||
// Treat all uninhabited types in non-exhaustive variants as `TyErr`.
|
||||
(_, true, true) => cx.tcx.types.err,
|
||||
// Treat all non-visible fields as `TyErr`. They can't appear in any
|
||||
// other pattern from this match (because they are private), so their
|
||||
// type does not matter - but we don't want to know they are uninhabited.
|
||||
(false, ..) => cx.tcx.types.err,
|
||||
(true, ..) => {
|
||||
let ty = field.ty(cx.tcx, substs);
|
||||
match ty.kind {
|
||||
// If the field type returned is an array of an unknown
|
||||
// size return an TyErr.
|
||||
ty::Array(_, len)
|
||||
if len.try_eval_usize(cx.tcx, cx.param_env).is_none() =>
|
||||
cx.tcx.types.err,
|
||||
_ => ty,
|
||||
}
|
||||
},
|
||||
}
|
||||
}).collect()
|
||||
}
|
||||
|
|
@ -1874,15 +1860,18 @@ fn constructor_covered_by_range<'tcx>(
|
|||
}
|
||||
}
|
||||
|
||||
fn patterns_for_variant<'p, 'tcx>(
|
||||
fn patterns_for_variant<'p, 'a: 'p, 'tcx>(
|
||||
cx: &mut MatchCheckCtxt<'a, 'tcx>,
|
||||
subpatterns: &'p [FieldPat<'tcx>],
|
||||
wild_patterns: &[&'p Pat<'tcx>])
|
||||
-> SmallVec<[&'p Pat<'tcx>; 2]>
|
||||
{
|
||||
wild_patterns: &[&'p Pat<'tcx>],
|
||||
is_non_exhaustive: bool,
|
||||
) -> SmallVec<[&'p Pat<'tcx>; 2]> {
|
||||
let mut result = SmallVec::from_slice(wild_patterns);
|
||||
|
||||
for subpat in subpatterns {
|
||||
result[subpat.field.index()] = &subpat.pattern;
|
||||
if !is_non_exhaustive || !cx.is_uninhabited(subpat.pattern.ty) {
|
||||
result[subpat.field.index()] = &subpat.pattern;
|
||||
}
|
||||
}
|
||||
|
||||
debug!("patterns_for_variant({:#?}, {:#?}) = {:#?}", subpatterns, wild_patterns, result);
|
||||
|
|
@ -1916,13 +1905,14 @@ fn specialize<'p, 'a: 'p, 'tcx>(
|
|||
|
||||
PatKind::Variant { adt_def, variant_index, ref subpatterns, .. } => {
|
||||
let ref variant = adt_def.variants[variant_index];
|
||||
let is_non_exhaustive = variant.is_field_list_non_exhaustive() && !cx.is_local(pat.ty);
|
||||
Some(Variant(variant.def_id))
|
||||
.filter(|variant_constructor| variant_constructor == constructor)
|
||||
.map(|_| patterns_for_variant(subpatterns, wild_patterns))
|
||||
.map(|_| patterns_for_variant(cx, subpatterns, wild_patterns, is_non_exhaustive))
|
||||
}
|
||||
|
||||
PatKind::Leaf { ref subpatterns } => {
|
||||
Some(patterns_for_variant(subpatterns, wild_patterns))
|
||||
Some(patterns_for_variant(cx, subpatterns, wild_patterns, false))
|
||||
}
|
||||
|
||||
PatKind::Deref { ref subpattern } => {
|
||||
|
|
|
|||
|
|
@ -1797,6 +1797,31 @@ let _: <u8 as Age>::Empire; // ok!
|
|||
```
|
||||
"##,
|
||||
|
||||
E0576: r##"
|
||||
An associated item wasn't found in the given type.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0576
|
||||
trait Hello {
|
||||
type Who;
|
||||
|
||||
fn hello() -> <Self as Hello>::You; // error!
|
||||
}
|
||||
```
|
||||
|
||||
In this example, we tried to use the non-existent associated type `You` of the
|
||||
`Hello` trait. To fix this error, use an existing associated type:
|
||||
|
||||
```
|
||||
trait Hello {
|
||||
type Who;
|
||||
|
||||
fn hello() -> <Self as Hello>::Who; // ok!
|
||||
}
|
||||
```
|
||||
"##,
|
||||
|
||||
E0603: r##"
|
||||
A private item was used outside its scope.
|
||||
|
||||
|
|
@ -1925,7 +1950,6 @@ struct Foo<X = Box<Self>> {
|
|||
// E0427, merged into 530
|
||||
// E0467, removed
|
||||
// E0470, removed
|
||||
E0576,
|
||||
E0577,
|
||||
E0578,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -215,7 +215,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
/// Report error if there is an explicit type parameter when using `impl Trait`.
|
||||
fn check_impl_trait(
|
||||
tcx: TyCtxt<'_>,
|
||||
span: Span,
|
||||
seg: &hir::PathSegment,
|
||||
generics: &ty::Generics,
|
||||
) -> bool {
|
||||
|
|
@ -228,14 +227,28 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
});
|
||||
|
||||
if explicit && impl_trait {
|
||||
let spans =
|
||||
seg.generic_args().args
|
||||
.iter()
|
||||
.filter_map(|arg|
|
||||
match arg {
|
||||
GenericArg::Type(_) => Some(arg.span()),
|
||||
_ => None
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let mut err = struct_span_err! {
|
||||
tcx.sess,
|
||||
span,
|
||||
spans.clone(),
|
||||
E0632,
|
||||
"cannot provide explicit generic arguments when `impl Trait` is \
|
||||
used in argument position"
|
||||
used in argument position"
|
||||
};
|
||||
|
||||
for span in spans {
|
||||
err.span_label(span, "explicit generic argument not allowed");
|
||||
}
|
||||
|
||||
err.emit();
|
||||
}
|
||||
|
||||
|
|
@ -254,7 +267,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
let empty_args = P(hir::GenericArgs {
|
||||
args: HirVec::new(), bindings: HirVec::new(), parenthesized: false,
|
||||
});
|
||||
let suppress_mismatch = Self::check_impl_trait(tcx, span, seg, &def);
|
||||
let suppress_mismatch = Self::check_impl_trait(tcx, seg, &def);
|
||||
Self::check_generic_arg_count(
|
||||
tcx,
|
||||
span,
|
||||
|
|
|
|||
|
|
@ -220,7 +220,7 @@
|
|||
|
||||
#![cfg_attr(test, feature(print_internals, set_stdio, update_panic_count))]
|
||||
#![cfg_attr(all(target_vendor = "fortanix", target_env = "sgx"),
|
||||
feature(slice_index_methods, decl_macro, coerce_unsized,
|
||||
feature(slice_index_methods, coerce_unsized,
|
||||
sgx_platform, ptr_wrapping_offset_from))]
|
||||
#![cfg_attr(all(test, target_vendor = "fortanix", target_env = "sgx"),
|
||||
feature(fixed_size_array, maybe_uninit_extra))]
|
||||
|
|
@ -251,6 +251,7 @@
|
|||
#![feature(container_error_extra)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(custom_test_frameworks)]
|
||||
#![feature(decl_macro)]
|
||||
#![feature(doc_alias)]
|
||||
#![feature(doc_cfg)]
|
||||
#![feature(doc_keyword)]
|
||||
|
|
|
|||
|
|
@ -330,8 +330,13 @@ declare_features! (
|
|||
/// Allows exhaustive pattern matching on types that contain uninhabited types.
|
||||
(active, exhaustive_patterns, "1.13.0", Some(51085), None),
|
||||
|
||||
/// Allows untagged unions `union U { ... }`.
|
||||
(active, untagged_unions, "1.13.0", Some(32836), None),
|
||||
/// Allows `union`s to implement `Drop`. Moreover, `union`s may now include fields
|
||||
/// that don't implement `Copy` as long as they don't have any drop glue.
|
||||
/// This is checked recursively. On encountering type variable where no progress can be made,
|
||||
/// `T: Copy` is used as a substitute for "no drop glue".
|
||||
///
|
||||
/// NOTE: A limited form of `union U { ... }` was accepted in 1.19.0.
|
||||
(active, untagged_unions, "1.13.0", Some(55149), None),
|
||||
|
||||
/// Allows `#[link(..., cfg(..))]`.
|
||||
(active, link_cfg, "1.14.0", Some(37406), None),
|
||||
|
|
@ -522,13 +527,16 @@ declare_features! (
|
|||
/// Allows the definition of `const extern fn` and `const unsafe extern fn`.
|
||||
(active, const_extern_fn, "1.40.0", Some(64926), None),
|
||||
|
||||
// Allows the use of raw-dylibs (RFC 2627).
|
||||
/// Allows the use of raw-dylibs (RFC 2627).
|
||||
(active, raw_dylib, "1.40.0", Some(58713), None),
|
||||
|
||||
/// Enable accurate caller location reporting during panic (RFC 2091).
|
||||
/// Allows `#[track_caller]` to be used which provides
|
||||
/// accurate caller location reporting during panic (RFC 2091).
|
||||
(active, track_caller, "1.40.0", Some(47809), None),
|
||||
|
||||
/// Non-object safe trait objects safe to use but cannot be created in safe rust
|
||||
/// Allows making `dyn Trait` well-formed even if `Trait` is not object safe.
|
||||
/// In that case, `dyn Trait: Trait` does not hold. Moreover, coercions and
|
||||
/// casts in safe Rust to `dyn Trait` for such a `Trait` is also forbidden.
|
||||
(active, object_safe_for_dispatch, "1.40.0", Some(43561), None),
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -3,12 +3,8 @@ use super::accepted::ACCEPTED_FEATURES;
|
|||
use super::removed::{REMOVED_FEATURES, STABLE_REMOVED_FEATURES};
|
||||
use super::builtin_attrs::{AttributeGate, BUILTIN_ATTRIBUTE_MAP};
|
||||
|
||||
use crate::ast::{
|
||||
self, AssocTyConstraint, AssocTyConstraintKind, NodeId, GenericParam, GenericParamKind,
|
||||
PatKind, RangeEnd, VariantData,
|
||||
};
|
||||
use crate::ast::{self, NodeId, PatKind, VariantData};
|
||||
use crate::attr::{self, check_builtin_attribute};
|
||||
use crate::source_map::Spanned;
|
||||
use crate::edition::{ALL_EDITIONS, Edition};
|
||||
use crate::visit::{self, FnKind, Visitor};
|
||||
use crate::parse::token;
|
||||
|
|
@ -157,9 +153,6 @@ fn leveled_feature_err<'a, S: Into<MultiSpan>>(
|
|||
|
||||
}
|
||||
|
||||
const EXPLAIN_BOX_SYNTAX: &str =
|
||||
"box expression syntax is experimental; you can call `Box::new` instead";
|
||||
|
||||
pub const EXPLAIN_STMT_ATTR_SYNTAX: &str =
|
||||
"attributes on expressions are experimental";
|
||||
|
||||
|
|
@ -291,6 +284,25 @@ impl<'a> PostExpansionVisitor<'a> {
|
|||
err.emit();
|
||||
}
|
||||
}
|
||||
|
||||
fn check_gat(&self, generics: &ast::Generics, span: Span) {
|
||||
if !generics.params.is_empty() {
|
||||
gate_feature_post!(
|
||||
&self,
|
||||
generic_associated_types,
|
||||
span,
|
||||
"generic associated types are unstable"
|
||||
);
|
||||
}
|
||||
if !generics.where_clause.predicates.is_empty() {
|
||||
gate_feature_post!(
|
||||
&self,
|
||||
generic_associated_types,
|
||||
span,
|
||||
"where clauses on associated types are unstable"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
||||
|
|
@ -423,20 +435,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||
"auto traits are experimental and possibly buggy");
|
||||
}
|
||||
|
||||
ast::ItemKind::TraitAlias(..) => {
|
||||
gate_feature_post!(
|
||||
&self,
|
||||
trait_alias,
|
||||
i.span,
|
||||
"trait aliases are experimental"
|
||||
);
|
||||
}
|
||||
|
||||
ast::ItemKind::MacroDef(ast::MacroDef { legacy: false, .. }) => {
|
||||
let msg = "`macro` is experimental";
|
||||
gate_feature_post!(&self, decl_macro, i.span, msg);
|
||||
}
|
||||
|
||||
ast::ItemKind::OpaqueTy(..) => {
|
||||
gate_feature_post!(
|
||||
&self,
|
||||
|
|
@ -500,37 +498,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn visit_expr(&mut self, e: &'a ast::Expr) {
|
||||
match e.kind {
|
||||
ast::ExprKind::Box(_) => {
|
||||
gate_feature_post!(&self, box_syntax, e.span, EXPLAIN_BOX_SYNTAX);
|
||||
}
|
||||
ast::ExprKind::Type(..) => {
|
||||
// To avoid noise about type ascription in common syntax errors, only emit if it
|
||||
// is the *only* error.
|
||||
if self.parse_sess.span_diagnostic.err_count() == 0 {
|
||||
gate_feature_post!(&self, type_ascription, e.span,
|
||||
"type ascription is experimental");
|
||||
}
|
||||
}
|
||||
ast::ExprKind::TryBlock(_) => {
|
||||
gate_feature_post!(&self, try_blocks, e.span, "`try` expression is experimental");
|
||||
}
|
||||
ast::ExprKind::Block(_, opt_label) => {
|
||||
if let Some(label) = opt_label {
|
||||
gate_feature_post!(&self, label_break_value, label.ident.span,
|
||||
"labels on blocks are unstable");
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
visit::walk_expr(self, e)
|
||||
}
|
||||
|
||||
fn visit_arm(&mut self, arm: &'a ast::Arm) {
|
||||
visit::walk_arm(self, arm)
|
||||
}
|
||||
|
||||
fn visit_pat(&mut self, pattern: &'a ast::Pat) {
|
||||
match &pattern.kind {
|
||||
PatKind::Slice(pats) => {
|
||||
|
|
@ -550,25 +517,12 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||
}
|
||||
}
|
||||
}
|
||||
PatKind::Box(..) => {
|
||||
gate_feature_post!(&self, box_patterns,
|
||||
pattern.span,
|
||||
"box pattern syntax is experimental");
|
||||
}
|
||||
PatKind::Range(_, _, Spanned { node: RangeEnd::Excluded, .. }) => {
|
||||
gate_feature_post!(&self, exclusive_range_pattern, pattern.span,
|
||||
"exclusive range pattern syntax is experimental");
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
visit::walk_pat(self, pattern)
|
||||
}
|
||||
|
||||
fn visit_fn(&mut self,
|
||||
fn_kind: FnKind<'a>,
|
||||
fn_decl: &'a ast::FnDecl,
|
||||
span: Span,
|
||||
_node_id: NodeId) {
|
||||
fn visit_fn(&mut self, fn_kind: FnKind<'a>, fn_decl: &'a ast::FnDecl, span: Span, _: NodeId) {
|
||||
if let Some(header) = fn_kind.header() {
|
||||
// Stability of const fn methods are covered in
|
||||
// `visit_trait_item` and `visit_impl_item` below; this is
|
||||
|
|
@ -583,26 +537,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||
visit::walk_fn(self, fn_kind, fn_decl, span)
|
||||
}
|
||||
|
||||
fn visit_generic_param(&mut self, param: &'a GenericParam) {
|
||||
match param.kind {
|
||||
GenericParamKind::Const { .. } =>
|
||||
gate_feature_post!(&self, const_generics, param.ident.span,
|
||||
"const generics are unstable"),
|
||||
_ => {}
|
||||
}
|
||||
visit::walk_generic_param(self, param)
|
||||
}
|
||||
|
||||
fn visit_assoc_ty_constraint(&mut self, constraint: &'a AssocTyConstraint) {
|
||||
match constraint.kind {
|
||||
AssocTyConstraintKind::Bound { .. } =>
|
||||
gate_feature_post!(&self, associated_type_bounds, constraint.span,
|
||||
"associated type bounds are unstable"),
|
||||
_ => {}
|
||||
}
|
||||
visit::walk_assoc_ty_constraint(self, constraint)
|
||||
}
|
||||
|
||||
fn visit_trait_item(&mut self, ti: &'a ast::TraitItem) {
|
||||
match ti.kind {
|
||||
ast::TraitItemKind::Method(ref sig, ref block) => {
|
||||
|
|
@ -624,14 +558,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||
gate_feature_post!(&self, associated_type_defaults, ti.span,
|
||||
"associated type defaults are unstable");
|
||||
}
|
||||
if !ti.generics.params.is_empty() {
|
||||
gate_feature_post!(&self, generic_associated_types, ti.span,
|
||||
"generic associated types are unstable");
|
||||
}
|
||||
if !ti.generics.where_clause.predicates.is_empty() {
|
||||
gate_feature_post!(&self, generic_associated_types, ti.span,
|
||||
"where clauses on associated types are unstable");
|
||||
}
|
||||
self.check_gat(&ti.generics, ti.span);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
|
@ -661,27 +588,12 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||
);
|
||||
}
|
||||
ast::ImplItemKind::TyAlias(_) => {
|
||||
if !ii.generics.params.is_empty() {
|
||||
gate_feature_post!(&self, generic_associated_types, ii.span,
|
||||
"generic associated types are unstable");
|
||||
}
|
||||
if !ii.generics.where_clause.predicates.is_empty() {
|
||||
gate_feature_post!(&self, generic_associated_types, ii.span,
|
||||
"where clauses on associated types are unstable");
|
||||
}
|
||||
self.check_gat(&ii.generics, ii.span);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
visit::walk_impl_item(self, ii)
|
||||
}
|
||||
|
||||
fn visit_vis(&mut self, vis: &'a ast::Visibility) {
|
||||
if let ast::VisibilityKind::Crate(ast::CrateSugar::JustCrate) = vis.node {
|
||||
gate_feature_post!(&self, crate_visibility_modifier, vis.span,
|
||||
"`crate` visibility modifier is experimental");
|
||||
}
|
||||
visit::walk_vis(self, vis)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute],
|
||||
|
|
@ -867,6 +779,22 @@ pub fn check_crate(krate: &ast::Crate,
|
|||
gate_all!(yields, generators, "yield syntax is experimental");
|
||||
gate_all!(or_patterns, "or-patterns syntax is experimental");
|
||||
gate_all!(const_extern_fn, "`const extern fn` definitions are unstable");
|
||||
gate_all!(trait_alias, "trait aliases are experimental");
|
||||
gate_all!(associated_type_bounds, "associated type bounds are unstable");
|
||||
gate_all!(crate_visibility_modifier, "`crate` visibility modifier is experimental");
|
||||
gate_all!(const_generics, "const generics are unstable");
|
||||
gate_all!(decl_macro, "`macro` is experimental");
|
||||
gate_all!(box_patterns, "box pattern syntax is experimental");
|
||||
gate_all!(exclusive_range_pattern, "exclusive range pattern syntax is experimental");
|
||||
gate_all!(try_blocks, "`try` blocks are unstable");
|
||||
gate_all!(label_break_value, "labels on blocks are unstable");
|
||||
gate_all!(box_syntax, "box expression syntax is experimental; you can call `Box::new` instead");
|
||||
|
||||
// To avoid noise about type ascription in common syntax errors,
|
||||
// only emit if it is the *only* error. (Also check it last.)
|
||||
if parse_sess.span_diagnostic.err_count() == 0 {
|
||||
gate_all!(type_ascription, "type ascription is experimental");
|
||||
}
|
||||
|
||||
visit::walk_crate(&mut visitor, krate);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1122,6 +1122,7 @@ impl<'a> Parser<'a> {
|
|||
self.expected_tokens.push(TokenType::Keyword(kw::Crate));
|
||||
if self.is_crate_vis() {
|
||||
self.bump(); // `crate`
|
||||
self.sess.gated_spans.crate_visibility_modifier.borrow_mut().push(self.prev_span);
|
||||
return Ok(respan(self.prev_span, VisibilityKind::Crate(CrateSugar::JustCrate)));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -252,6 +252,7 @@ impl<'a> Parser<'a> {
|
|||
self.last_type_ascription = Some((self.prev_span, maybe_path));
|
||||
|
||||
lhs = self.parse_assoc_op_cast(lhs, lhs_span, ExprKind::Type)?;
|
||||
self.sess.gated_spans.type_ascription.borrow_mut().push(lhs.span);
|
||||
continue
|
||||
} else if op == AssocOp::DotDot || op == AssocOp::DotDotEq {
|
||||
// If we didn’t have to handle `x..`/`x..=`, it would be pretty easy to
|
||||
|
|
@ -453,7 +454,9 @@ impl<'a> Parser<'a> {
|
|||
self.bump();
|
||||
let e = self.parse_prefix_expr(None);
|
||||
let (span, e) = self.interpolated_or_expr_span(e)?;
|
||||
(lo.to(span), ExprKind::Box(e))
|
||||
let span = lo.to(span);
|
||||
self.sess.gated_spans.box_syntax.borrow_mut().push(span);
|
||||
(span, ExprKind::Box(e))
|
||||
}
|
||||
token::Ident(..) if self.token.is_ident_named(sym::not) => {
|
||||
// `not` is just an ordinary identifier in Rust-the-language,
|
||||
|
|
@ -1260,6 +1263,10 @@ impl<'a> Parser<'a> {
|
|||
blk_mode: BlockCheckMode,
|
||||
outer_attrs: ThinVec<Attribute>,
|
||||
) -> PResult<'a, P<Expr>> {
|
||||
if let Some(label) = opt_label {
|
||||
self.sess.gated_spans.label_break_value.borrow_mut().push(label.ident.span);
|
||||
}
|
||||
|
||||
self.expect(&token::OpenDelim(token::Brace))?;
|
||||
|
||||
let mut attrs = outer_attrs;
|
||||
|
|
@ -1646,7 +1653,9 @@ impl<'a> Parser<'a> {
|
|||
error.emit();
|
||||
Err(error)
|
||||
} else {
|
||||
Ok(self.mk_expr(span_lo.to(body.span), ExprKind::TryBlock(body), attrs))
|
||||
let span = span_lo.to(body.span);
|
||||
self.sess.gated_spans.try_blocks.borrow_mut().push(span);
|
||||
Ok(self.mk_expr(span, ExprKind::TryBlock(body), attrs))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,11 +55,15 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
|
||||
fn parse_const_param(&mut self, preceding_attrs: Vec<Attribute>) -> PResult<'a, GenericParam> {
|
||||
let lo = self.token.span;
|
||||
|
||||
self.expect_keyword(kw::Const)?;
|
||||
let ident = self.parse_ident()?;
|
||||
self.expect(&token::Colon)?;
|
||||
let ty = self.parse_ty()?;
|
||||
|
||||
self.sess.gated_spans.const_generics.borrow_mut().push(lo.to(self.prev_span));
|
||||
|
||||
Ok(GenericParam {
|
||||
ident,
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
|
|
|
|||
|
|
@ -211,7 +211,7 @@ impl<'a> Parser<'a> {
|
|||
{
|
||||
// UNSAFE TRAIT ITEM
|
||||
self.bump(); // `unsafe`
|
||||
let info = self.parse_item_trait(Unsafety::Unsafe)?;
|
||||
let info = self.parse_item_trait(lo, Unsafety::Unsafe)?;
|
||||
return self.mk_item_with_info(attrs, lo, vis, info);
|
||||
}
|
||||
|
||||
|
|
@ -289,7 +289,7 @@ impl<'a> Parser<'a> {
|
|||
&& self.is_keyword_ahead(1, &[kw::Trait]))
|
||||
{
|
||||
// TRAIT ITEM
|
||||
let info = self.parse_item_trait(Unsafety::Normal)?;
|
||||
let info = self.parse_item_trait(lo, Unsafety::Normal)?;
|
||||
return self.mk_item_with_info(attrs, lo, vis, info);
|
||||
}
|
||||
|
||||
|
|
@ -780,7 +780,7 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
|
||||
/// Parses `auto? trait Foo { ... }` or `trait Foo = Bar;`.
|
||||
fn parse_item_trait(&mut self, unsafety: Unsafety) -> PResult<'a, ItemInfo> {
|
||||
fn parse_item_trait(&mut self, lo: Span, unsafety: Unsafety) -> PResult<'a, ItemInfo> {
|
||||
// Parse optional `auto` prefix.
|
||||
let is_auto = if self.eat_keyword(kw::Auto) {
|
||||
IsAuto::Yes
|
||||
|
|
@ -793,29 +793,43 @@ impl<'a> Parser<'a> {
|
|||
let mut tps = self.parse_generics()?;
|
||||
|
||||
// Parse optional colon and supertrait bounds.
|
||||
let bounds = if self.eat(&token::Colon) {
|
||||
let had_colon = self.eat(&token::Colon);
|
||||
let span_at_colon = self.prev_span;
|
||||
let bounds = if had_colon {
|
||||
self.parse_generic_bounds(Some(self.prev_span))?
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
let span_before_eq = self.prev_span;
|
||||
if self.eat(&token::Eq) {
|
||||
// It's a trait alias.
|
||||
if had_colon {
|
||||
let span = span_at_colon.to(span_before_eq);
|
||||
self.struct_span_err(span, "bounds are not allowed on trait aliases")
|
||||
.emit();
|
||||
}
|
||||
|
||||
let bounds = self.parse_generic_bounds(None)?;
|
||||
tps.where_clause = self.parse_where_clause()?;
|
||||
self.expect(&token::Semi)?;
|
||||
|
||||
let whole_span = lo.to(self.prev_span);
|
||||
if is_auto == IsAuto::Yes {
|
||||
let msg = "trait aliases cannot be `auto`";
|
||||
self.struct_span_err(self.prev_span, msg)
|
||||
.span_label(self.prev_span, msg)
|
||||
self.struct_span_err(whole_span, msg)
|
||||
.span_label(whole_span, msg)
|
||||
.emit();
|
||||
}
|
||||
if unsafety != Unsafety::Normal {
|
||||
let msg = "trait aliases cannot be `unsafe`";
|
||||
self.struct_span_err(self.prev_span, msg)
|
||||
.span_label(self.prev_span, msg)
|
||||
self.struct_span_err(whole_span, msg)
|
||||
.span_label(whole_span, msg)
|
||||
.emit();
|
||||
}
|
||||
|
||||
self.sess.gated_spans.trait_alias.borrow_mut().push(whole_span);
|
||||
|
||||
Ok((ident, ItemKind::TraitAlias(tps, bounds), None))
|
||||
} else {
|
||||
// It's a normal trait.
|
||||
|
|
@ -1692,6 +1706,11 @@ impl<'a> Parser<'a> {
|
|||
};
|
||||
|
||||
let span = lo.to(self.prev_span);
|
||||
|
||||
if !def.legacy {
|
||||
self.sess.gated_spans.decl_macro.borrow_mut().push(span);
|
||||
}
|
||||
|
||||
Ok(Some(self.mk_item(span, ident, ItemKind::MacroDef(def), vis.clone(), attrs.to_vec())))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -324,7 +324,9 @@ impl<'a> Parser<'a> {
|
|||
self.parse_pat_ident(BindingMode::ByRef(mutbl))?
|
||||
} else if self.eat_keyword(kw::Box) {
|
||||
// Parse `box pat`
|
||||
PatKind::Box(self.parse_pat_with_range_pat(false, None)?)
|
||||
let pat = self.parse_pat_with_range_pat(false, None)?;
|
||||
self.sess.gated_spans.box_patterns.borrow_mut().push(lo.to(self.prev_span));
|
||||
PatKind::Box(pat)
|
||||
} else if self.can_be_ident_pat() {
|
||||
// Parse `ident @ pat`
|
||||
// This can give false positives and parse nullary enums,
|
||||
|
|
@ -609,6 +611,11 @@ impl<'a> Parser<'a> {
|
|||
Ok(PatKind::Mac(mac))
|
||||
}
|
||||
|
||||
fn excluded_range_end(&self, span: Span) -> RangeEnd {
|
||||
self.sess.gated_spans.exclusive_range_pattern.borrow_mut().push(span);
|
||||
RangeEnd::Excluded
|
||||
}
|
||||
|
||||
/// Parse a range pattern `$path $form $end?` where `$form = ".." | "..." | "..=" ;`.
|
||||
/// The `$path` has already been parsed and the next token is the `$form`.
|
||||
fn parse_pat_range_starting_with_path(
|
||||
|
|
@ -618,7 +625,7 @@ impl<'a> Parser<'a> {
|
|||
path: Path
|
||||
) -> PResult<'a, PatKind> {
|
||||
let (end_kind, form) = match self.token.kind {
|
||||
token::DotDot => (RangeEnd::Excluded, ".."),
|
||||
token::DotDot => (self.excluded_range_end(self.token.span), ".."),
|
||||
token::DotDotDot => (RangeEnd::Included(RangeSyntax::DotDotDot), "..."),
|
||||
token::DotDotEq => (RangeEnd::Included(RangeSyntax::DotDotEq), "..="),
|
||||
_ => panic!("can only parse `..`/`...`/`..=` for ranges (checked above)"),
|
||||
|
|
@ -641,7 +648,7 @@ impl<'a> Parser<'a> {
|
|||
} else if self.eat(&token::DotDotEq) {
|
||||
(RangeEnd::Included(RangeSyntax::DotDotEq), "..=")
|
||||
} else if self.eat(&token::DotDot) {
|
||||
(RangeEnd::Excluded, "..")
|
||||
(self.excluded_range_end(op_span), "..")
|
||||
} else {
|
||||
panic!("impossible case: we already matched on a range-operator token")
|
||||
};
|
||||
|
|
|
|||
|
|
@ -404,8 +404,9 @@ impl<'a> Parser<'a> {
|
|||
// Parse lifetime argument.
|
||||
args.push(GenericArg::Lifetime(self.expect_lifetime()));
|
||||
misplaced_assoc_ty_constraints.append(&mut assoc_ty_constraints);
|
||||
} else if self.check_ident() && self.look_ahead(1,
|
||||
|t| t == &token::Eq || t == &token::Colon) {
|
||||
} else if self.check_ident()
|
||||
&& self.look_ahead(1, |t| t == &token::Eq || t == &token::Colon)
|
||||
{
|
||||
// Parse associated type constraint.
|
||||
let lo = self.token.span;
|
||||
let ident = self.parse_ident()?;
|
||||
|
|
@ -420,7 +421,14 @@ impl<'a> Parser<'a> {
|
|||
} else {
|
||||
unreachable!();
|
||||
};
|
||||
|
||||
let span = lo.to(self.prev_span);
|
||||
|
||||
// Gate associated type bounds, e.g., `Iterator<Item: Ord>`.
|
||||
if let AssocTyConstraintKind::Bound { .. } = kind {
|
||||
self.sess.gated_spans.associated_type_bounds.borrow_mut().push(span);
|
||||
}
|
||||
|
||||
constraints.push(AssocTyConstraint {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
ident,
|
||||
|
|
|
|||
|
|
@ -30,6 +30,28 @@ crate struct GatedSpans {
|
|||
crate or_patterns: Lock<Vec<Span>>,
|
||||
/// Spans collected for gating `const_extern_fn`, e.g. `const extern fn foo`.
|
||||
crate const_extern_fn: Lock<Vec<Span>>,
|
||||
/// Spans collected for gating `trait_alias`, e.g. `trait Foo = Ord + Eq;`.
|
||||
pub trait_alias: Lock<Vec<Span>>,
|
||||
/// Spans collected for gating `associated_type_bounds`, e.g. `Iterator<Item: Ord>`.
|
||||
pub associated_type_bounds: Lock<Vec<Span>>,
|
||||
/// Spans collected for gating `crate_visibility_modifier`, e.g. `crate fn`.
|
||||
pub crate_visibility_modifier: Lock<Vec<Span>>,
|
||||
/// Spans collected for gating `const_generics`, e.g. `const N: usize`.
|
||||
pub const_generics: Lock<Vec<Span>>,
|
||||
/// Spans collected for gating `decl_macro`, e.g. `macro m() {}`.
|
||||
pub decl_macro: Lock<Vec<Span>>,
|
||||
/// Spans collected for gating `box_patterns`, e.g. `box 0`.
|
||||
pub box_patterns: Lock<Vec<Span>>,
|
||||
/// Spans collected for gating `exclusive_range_pattern`, e.g. `0..2`.
|
||||
pub exclusive_range_pattern: Lock<Vec<Span>>,
|
||||
/// Spans collected for gating `try_blocks`, e.g. `try { a? + b? }`.
|
||||
pub try_blocks: Lock<Vec<Span>>,
|
||||
/// Spans collected for gating `label_break_value`, e.g. `'label: { ... }`.
|
||||
pub label_break_value: Lock<Vec<Span>>,
|
||||
/// Spans collected for gating `box_syntax`, e.g. `box $expr`.
|
||||
pub box_syntax: Lock<Vec<Span>>,
|
||||
/// Spans collected for gating `type_ascription`, e.g. `42: usize`.
|
||||
pub type_ascription: Lock<Vec<Span>>,
|
||||
}
|
||||
|
||||
/// Info about a parsing session.
|
||||
|
|
|
|||
|
|
@ -337,6 +337,7 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> {
|
|||
// use proc_macro::bridge::client::ProcMacro;
|
||||
//
|
||||
// #[rustc_proc_macro_decls]
|
||||
// #[allow(deprecated)]
|
||||
// static DECLS: &[ProcMacro] = &[
|
||||
// ProcMacro::custom_derive($name_trait1, &[], ::$name1);
|
||||
// ProcMacro::custom_derive($name_trait2, &["attribute_name"], ::$name2);
|
||||
|
|
@ -416,6 +417,16 @@ fn mk_decls(
|
|||
).map(|mut i| {
|
||||
let attr = cx.meta_word(span, sym::rustc_proc_macro_decls);
|
||||
i.attrs.push(cx.attribute(attr));
|
||||
|
||||
let deprecated_attr = attr::mk_nested_word_item(
|
||||
Ident::new(sym::deprecated, span)
|
||||
);
|
||||
let allow_deprecated_attr = attr::mk_list_item(
|
||||
Ident::new(sym::allow, span),
|
||||
vec![deprecated_attr]
|
||||
);
|
||||
i.attrs.push(cx.attribute(allow_deprecated_attr));
|
||||
|
||||
i
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
// check-pass
|
||||
|
||||
#![feature(array_value_iter)]
|
||||
#![feature(trusted_len)]
|
||||
|
||||
use std::{
|
||||
array::IntoIter,
|
||||
fmt::Debug,
|
||||
iter::{ExactSizeIterator, FusedIterator, TrustedLen},
|
||||
};
|
||||
|
||||
pub fn yes_iterator() -> impl Iterator<Item = i32> {
|
||||
IntoIter::new([0i32; 32])
|
||||
}
|
||||
|
||||
pub fn yes_double_ended_iterator() -> impl DoubleEndedIterator {
|
||||
IntoIter::new([0i32; 32])
|
||||
}
|
||||
|
||||
pub fn yes_exact_size_iterator() -> impl ExactSizeIterator {
|
||||
IntoIter::new([0i32; 32])
|
||||
}
|
||||
|
||||
pub fn yes_fused_iterator() -> impl FusedIterator {
|
||||
IntoIter::new([0i32; 32])
|
||||
}
|
||||
|
||||
pub fn yes_trusted_len() -> impl TrustedLen {
|
||||
IntoIter::new([0i32; 32])
|
||||
}
|
||||
|
||||
pub fn yes_clone() -> impl Clone {
|
||||
IntoIter::new([0i32; 32])
|
||||
}
|
||||
|
||||
pub fn yes_debug() -> impl Debug {
|
||||
IntoIter::new([0i32; 32])
|
||||
}
|
||||
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
#![feature(array_value_iter)]
|
||||
#![feature(trusted_len)]
|
||||
|
||||
use std::{
|
||||
array::IntoIter,
|
||||
fmt::Debug,
|
||||
iter::{ExactSizeIterator, FusedIterator, TrustedLen},
|
||||
};
|
||||
|
||||
pub fn no_iterator() -> impl Iterator<Item = i32> {
|
||||
//~^ ERROR arrays only have std trait implementations for lengths 0..=32
|
||||
IntoIter::new([0i32; 33])
|
||||
//~^ ERROR arrays only have std trait implementations for lengths 0..=32
|
||||
}
|
||||
|
||||
pub fn no_double_ended_iterator() -> impl DoubleEndedIterator {
|
||||
//~^ ERROR arrays only have std trait implementations for lengths 0..=32
|
||||
IntoIter::new([0i32; 33])
|
||||
//~^ ERROR arrays only have std trait implementations for lengths 0..=32
|
||||
}
|
||||
|
||||
pub fn no_exact_size_iterator() -> impl ExactSizeIterator {
|
||||
//~^ ERROR arrays only have std trait implementations for lengths 0..=32
|
||||
IntoIter::new([0i32; 33])
|
||||
//~^ ERROR arrays only have std trait implementations for lengths 0..=32
|
||||
}
|
||||
|
||||
pub fn no_fused_iterator() -> impl FusedIterator {
|
||||
//~^ ERROR arrays only have std trait implementations for lengths 0..=32
|
||||
IntoIter::new([0i32; 33])
|
||||
//~^ ERROR arrays only have std trait implementations for lengths 0..=32
|
||||
}
|
||||
|
||||
pub fn no_trusted_len() -> impl TrustedLen {
|
||||
//~^ ERROR arrays only have std trait implementations for lengths 0..=32
|
||||
IntoIter::new([0i32; 33])
|
||||
//~^ ERROR arrays only have std trait implementations for lengths 0..=32
|
||||
}
|
||||
|
||||
pub fn no_clone() -> impl Clone {
|
||||
//~^ ERROR arrays only have std trait implementations for lengths 0..=32
|
||||
IntoIter::new([0i32; 33])
|
||||
//~^ ERROR arrays only have std trait implementations for lengths 0..=32
|
||||
}
|
||||
|
||||
pub fn no_debug() -> impl Debug {
|
||||
//~^ ERROR arrays only have std trait implementations for lengths 0..=32
|
||||
IntoIter::new([0i32; 33])
|
||||
//~^ ERROR arrays only have std trait implementations for lengths 0..=32
|
||||
}
|
||||
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
error[E0277]: arrays only have std trait implementations for lengths 0..=32
|
||||
--> $DIR/into-iter-no-impls-length-33.rs:12:5
|
||||
|
|
||||
LL | IntoIter::new([0i32; 33])
|
||||
| ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
|
||||
|
|
||||
= note: required by `std::array::IntoIter::<T, N>::new`
|
||||
|
||||
error[E0277]: arrays only have std trait implementations for lengths 0..=32
|
||||
--> $DIR/into-iter-no-impls-length-33.rs:10:25
|
||||
|
|
||||
LL | pub fn no_iterator() -> impl Iterator<Item = i32> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
|
||||
|
|
||||
= note: required because of the requirements on the impl of `std::iter::Iterator` for `std::array::IntoIter<i32, 33usize>`
|
||||
= note: the return type of a function must have a statically known size
|
||||
|
||||
error[E0277]: arrays only have std trait implementations for lengths 0..=32
|
||||
--> $DIR/into-iter-no-impls-length-33.rs:18:5
|
||||
|
|
||||
LL | IntoIter::new([0i32; 33])
|
||||
| ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
|
||||
|
|
||||
= note: required by `std::array::IntoIter::<T, N>::new`
|
||||
|
||||
error[E0277]: arrays only have std trait implementations for lengths 0..=32
|
||||
--> $DIR/into-iter-no-impls-length-33.rs:16:38
|
||||
|
|
||||
LL | pub fn no_double_ended_iterator() -> impl DoubleEndedIterator {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
|
||||
|
|
||||
= note: required because of the requirements on the impl of `std::iter::DoubleEndedIterator` for `std::array::IntoIter<i32, 33usize>`
|
||||
= note: the return type of a function must have a statically known size
|
||||
|
||||
error[E0277]: arrays only have std trait implementations for lengths 0..=32
|
||||
--> $DIR/into-iter-no-impls-length-33.rs:24:5
|
||||
|
|
||||
LL | IntoIter::new([0i32; 33])
|
||||
| ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
|
||||
|
|
||||
= note: required by `std::array::IntoIter::<T, N>::new`
|
||||
|
||||
error[E0277]: arrays only have std trait implementations for lengths 0..=32
|
||||
--> $DIR/into-iter-no-impls-length-33.rs:22:36
|
||||
|
|
||||
LL | pub fn no_exact_size_iterator() -> impl ExactSizeIterator {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
|
||||
|
|
||||
= note: required because of the requirements on the impl of `std::iter::ExactSizeIterator` for `std::array::IntoIter<i32, 33usize>`
|
||||
= note: the return type of a function must have a statically known size
|
||||
|
||||
error[E0277]: arrays only have std trait implementations for lengths 0..=32
|
||||
--> $DIR/into-iter-no-impls-length-33.rs:30:5
|
||||
|
|
||||
LL | IntoIter::new([0i32; 33])
|
||||
| ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
|
||||
|
|
||||
= note: required by `std::array::IntoIter::<T, N>::new`
|
||||
|
||||
error[E0277]: arrays only have std trait implementations for lengths 0..=32
|
||||
--> $DIR/into-iter-no-impls-length-33.rs:28:31
|
||||
|
|
||||
LL | pub fn no_fused_iterator() -> impl FusedIterator {
|
||||
| ^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
|
||||
|
|
||||
= note: required because of the requirements on the impl of `std::iter::FusedIterator` for `std::array::IntoIter<i32, 33usize>`
|
||||
= note: the return type of a function must have a statically known size
|
||||
|
||||
error[E0277]: arrays only have std trait implementations for lengths 0..=32
|
||||
--> $DIR/into-iter-no-impls-length-33.rs:36:5
|
||||
|
|
||||
LL | IntoIter::new([0i32; 33])
|
||||
| ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
|
||||
|
|
||||
= note: required by `std::array::IntoIter::<T, N>::new`
|
||||
|
||||
error[E0277]: arrays only have std trait implementations for lengths 0..=32
|
||||
--> $DIR/into-iter-no-impls-length-33.rs:34:28
|
||||
|
|
||||
LL | pub fn no_trusted_len() -> impl TrustedLen {
|
||||
| ^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
|
||||
|
|
||||
= note: required because of the requirements on the impl of `std::iter::TrustedLen` for `std::array::IntoIter<i32, 33usize>`
|
||||
= note: the return type of a function must have a statically known size
|
||||
|
||||
error[E0277]: arrays only have std trait implementations for lengths 0..=32
|
||||
--> $DIR/into-iter-no-impls-length-33.rs:42:5
|
||||
|
|
||||
LL | IntoIter::new([0i32; 33])
|
||||
| ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
|
||||
|
|
||||
= note: required by `std::array::IntoIter::<T, N>::new`
|
||||
|
||||
error[E0277]: arrays only have std trait implementations for lengths 0..=32
|
||||
--> $DIR/into-iter-no-impls-length-33.rs:40:22
|
||||
|
|
||||
LL | pub fn no_clone() -> impl Clone {
|
||||
| ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
|
||||
|
|
||||
= note: required because of the requirements on the impl of `std::clone::Clone` for `std::array::IntoIter<i32, 33usize>`
|
||||
= note: the return type of a function must have a statically known size
|
||||
|
||||
error[E0277]: arrays only have std trait implementations for lengths 0..=32
|
||||
--> $DIR/into-iter-no-impls-length-33.rs:48:5
|
||||
|
|
||||
LL | IntoIter::new([0i32; 33])
|
||||
| ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
|
||||
|
|
||||
= note: required by `std::array::IntoIter::<T, N>::new`
|
||||
|
||||
error[E0277]: arrays only have std trait implementations for lengths 0..=32
|
||||
--> $DIR/into-iter-no-impls-length-33.rs:46:22
|
||||
|
|
||||
LL | pub fn no_debug() -> impl Debug {
|
||||
| ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
|
||||
|
|
||||
= note: required because of the requirements on the impl of `std::fmt::Debug` for `std::array::IntoIter<i32, 33usize>`
|
||||
= note: the return type of a function must have a statically known size
|
||||
|
||||
error: aborting due to 14 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
error[E0658]: const generics are unstable
|
||||
--> $DIR/const-param-in-trait-ungated.rs:1:19
|
||||
--> $DIR/const-param-in-trait-ungated.rs:1:13
|
||||
|
|
||||
LL | trait Trait<const T: ()> {}
|
||||
| ^
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/44580
|
||||
= help: add `#![feature(const_generics)]` to the crate attributes to enable
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
error[E0658]: const generics are unstable
|
||||
--> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:19
|
||||
--> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:13
|
||||
|
|
||||
LL | struct B<T, const N: T>(PhantomData<[T; N]>);
|
||||
| ^
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/44580
|
||||
= help: add `#![feature(const_generics)]` to the crate attributes to enable
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
error[E0658]: const generics are unstable
|
||||
--> $DIR/issue-60263.rs:1:16
|
||||
--> $DIR/issue-60263.rs:1:10
|
||||
|
|
||||
LL | struct B<const I: u8>;
|
||||
| ^
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/44580
|
||||
= help: add `#![feature(const_generics)]` to the crate attributes to enable
|
||||
|
|
|
|||
|
|
@ -70,3 +70,7 @@ fn main() {
|
|||
// FIXME: uncomment when `impl_trait_in_bindings` feature is fixed.
|
||||
// let _: &dyn Tr1<As1: Copy> = &S1;
|
||||
}
|
||||
|
||||
macro_rules! accept_path { ($p:path) => {} }
|
||||
accept_path!(Iterator<Item: Ord>);
|
||||
//~^ ERROR associated type bounds are unstable
|
||||
|
|
|
|||
|
|
@ -115,6 +115,15 @@ LL | let _: impl Tr1<As1: Copy> = S1;
|
|||
= note: for more information, see https://github.com/rust-lang/rust/issues/52662
|
||||
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: associated type bounds are unstable
|
||||
--> $DIR/feature-gate-associated_type_bounds.rs:75:23
|
||||
|
|
||||
LL | accept_path!(Iterator<Item: Ord>);
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/52662
|
||||
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
|
||||
|
||||
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
|
||||
--> $DIR/feature-gate-associated_type_bounds.rs:54:14
|
||||
|
|
||||
|
|
@ -139,7 +148,7 @@ LL | let _: impl Tr1<As1: Copy> = S1;
|
|||
|
|
||||
= help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to 16 previous errors
|
||||
error: aborting due to 17 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0562, E0658.
|
||||
For more information about an error, try `rustc --explain E0562`.
|
||||
|
|
|
|||
|
|
@ -2,3 +2,6 @@ fn main() {
|
|||
let box x = Box::new('c'); //~ ERROR box pattern syntax is experimental
|
||||
println!("x: {}", x);
|
||||
}
|
||||
|
||||
macro_rules! accept_pat { ($p:pat) => {} }
|
||||
accept_pat!(box 0); //~ ERROR box pattern syntax is experimental
|
||||
|
|
|
|||
|
|
@ -7,6 +7,15 @@ LL | let box x = Box::new('c');
|
|||
= note: for more information, see https://github.com/rust-lang/rust/issues/29641
|
||||
= help: add `#![feature(box_patterns)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
error[E0658]: box pattern syntax is experimental
|
||||
--> $DIR/feature-gate-box_patterns.rs:7:13
|
||||
|
|
||||
LL | accept_pat!(box 0);
|
||||
| ^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29641
|
||||
= help: add `#![feature(box_patterns)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
// Test that the use of the box syntax is gated by `box_syntax` feature gate.
|
||||
|
||||
fn main() {
|
||||
#[cfg(FALSE)]
|
||||
fn foo() {
|
||||
let x = box 3;
|
||||
//~^ ERROR box expression syntax is experimental; you can call `Box::new` instead
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error[E0658]: box expression syntax is experimental; you can call `Box::new` instead
|
||||
--> $DIR/feature-gate-box_syntax.rs:4:13
|
||||
--> $DIR/feature-gate-box_syntax.rs:5:13
|
||||
|
|
||||
LL | let x = box 3;
|
||||
| ^^^^^
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
error[E0658]: const generics are unstable
|
||||
--> $DIR/feature-gate-const_generics-ptr.rs:1:22
|
||||
--> $DIR/feature-gate-const_generics-ptr.rs:1:16
|
||||
|
|
||||
LL | struct ConstFn<const F: fn()>;
|
||||
| ^
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/44580
|
||||
= help: add `#![feature(const_generics)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: const generics are unstable
|
||||
--> $DIR/feature-gate-const_generics-ptr.rs:5:23
|
||||
--> $DIR/feature-gate-const_generics-ptr.rs:5:17
|
||||
|
|
||||
LL | struct ConstPtr<const P: *const u32>;
|
||||
| ^
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/44580
|
||||
= help: add `#![feature(const_generics)]` to the crate attributes to enable
|
||||
|
|
|
|||
|
|
@ -2,4 +2,9 @@ fn foo<const X: ()>() {} //~ ERROR const generics are unstable
|
|||
|
||||
struct Foo<const X: usize>([(); X]); //~ ERROR const generics are unstable
|
||||
|
||||
macro_rules! accept_item { ($i:item) => {} }
|
||||
accept_item! {
|
||||
impl<const X: ()> A {} //~ ERROR const generics are unstable
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -1,21 +1,30 @@
|
|||
error[E0658]: const generics are unstable
|
||||
--> $DIR/feature-gate-const_generics.rs:1:14
|
||||
--> $DIR/feature-gate-const_generics.rs:1:8
|
||||
|
|
||||
LL | fn foo<const X: ()>() {}
|
||||
| ^
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/44580
|
||||
= help: add `#![feature(const_generics)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: const generics are unstable
|
||||
--> $DIR/feature-gate-const_generics.rs:3:18
|
||||
--> $DIR/feature-gate-const_generics.rs:3:12
|
||||
|
|
||||
LL | struct Foo<const X: usize>([(); X]);
|
||||
| ^
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/44580
|
||||
= help: add `#![feature(const_generics)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error[E0658]: const generics are unstable
|
||||
--> $DIR/feature-gate-const_generics.rs:7:10
|
||||
|
|
||||
LL | impl<const X: ()> A {}
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/44580
|
||||
= help: add `#![feature(const_generics)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
|
|
|||
|
|
@ -5,4 +5,7 @@ crate struct Bender { //~ ERROR `crate` visibility modifier is experimental
|
|||
water: bool,
|
||||
}
|
||||
|
||||
macro_rules! accept_vis { ($v:vis) => {} }
|
||||
accept_vis!(crate); //~ ERROR `crate` visibility modifier is experimental
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,15 @@ LL | crate struct Bender {
|
|||
= note: for more information, see https://github.com/rust-lang/rust/issues/53120
|
||||
= help: add `#![feature(crate_visibility_modifier)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
error[E0658]: `crate` visibility modifier is experimental
|
||||
--> $DIR/feature-gate-crate_visibility_modifier.rs:9:13
|
||||
|
|
||||
LL | accept_vis!(crate);
|
||||
| ^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/53120
|
||||
= help: add `#![feature(crate_visibility_modifier)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
|
|
|||
|
|
@ -2,4 +2,8 @@
|
|||
|
||||
macro m() {} //~ ERROR `macro` is experimental
|
||||
|
||||
macro_rules! accept_item { ($i:item) => {} }
|
||||
accept_item! {
|
||||
macro m() {} //~ ERROR `macro` is experimental
|
||||
}
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,15 @@ LL | macro m() {}
|
|||
= note: for more information, see https://github.com/rust-lang/rust/issues/39412
|
||||
= help: add `#![feature(decl_macro)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
error[E0658]: `macro` is experimental
|
||||
--> $DIR/feature-gate-decl_macro.rs:7:5
|
||||
|
|
||||
LL | macro m() {}
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/39412
|
||||
= help: add `#![feature(decl_macro)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
pub fn main() {
|
||||
#[cfg(FALSE)]
|
||||
fn foo() {
|
||||
match 22 {
|
||||
0 .. 3 => {} //~ ERROR exclusive range pattern syntax is experimental
|
||||
PATH .. 3 => {} //~ ERROR exclusive range pattern syntax is experimental
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,21 @@
|
|||
error[E0658]: exclusive range pattern syntax is experimental
|
||||
--> $DIR/feature-gate-exclusive-range-pattern.rs:3:9
|
||||
--> $DIR/feature-gate-exclusive-range-pattern.rs:4:11
|
||||
|
|
||||
LL | 0 .. 3 => {}
|
||||
| ^^^^^^
|
||||
| ^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/37854
|
||||
= help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
error[E0658]: exclusive range pattern syntax is experimental
|
||||
--> $DIR/feature-gate-exclusive-range-pattern.rs:5:14
|
||||
|
|
||||
LL | PATH .. 3 => {}
|
||||
| ^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/37854
|
||||
= help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
pub fn main() {
|
||||
#[cfg(FALSE)]
|
||||
pub fn foo() {
|
||||
'a: { //~ ERROR labels on blocks are unstable
|
||||
break 'a;
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error[E0658]: labels on blocks are unstable
|
||||
--> $DIR/feature-gate-label_break_value.rs:2:5
|
||||
--> $DIR/feature-gate-label_break_value.rs:3:5
|
||||
|
|
||||
LL | 'a: {
|
||||
| ^^
|
||||
|
|
|
|||
|
|
@ -1,4 +1,13 @@
|
|||
trait Foo = Default;
|
||||
//~^ ERROR trait aliases are experimental
|
||||
|
||||
macro_rules! accept_item {
|
||||
($i:item) => {}
|
||||
}
|
||||
|
||||
accept_item! {
|
||||
trait Foo = Ord + Eq;
|
||||
//~^ ERROR trait aliases are experimental
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,15 @@ LL | trait Foo = Default;
|
|||
= note: for more information, see https://github.com/rust-lang/rust/issues/41517
|
||||
= help: add `#![feature(trait_alias)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
error[E0658]: trait aliases are experimental
|
||||
--> $DIR/feature-gate-trait-alias.rs:9:5
|
||||
|
|
||||
LL | trait Foo = Ord + Eq;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/41517
|
||||
= help: add `#![feature(trait_alias)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
// compile-flags: --edition 2018
|
||||
|
||||
pub fn main() {
|
||||
let try_result: Option<_> = try { //~ ERROR `try` expression is experimental
|
||||
#[cfg(FALSE)]
|
||||
fn foo() {
|
||||
let try_result: Option<_> = try { //~ ERROR `try` blocks are unstable
|
||||
let x = 5;
|
||||
x
|
||||
};
|
||||
assert_eq!(try_result, Some(5));
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error[E0658]: `try` expression is experimental
|
||||
--> $DIR/feature-gate-try_blocks.rs:4:33
|
||||
error[E0658]: `try` blocks are unstable
|
||||
--> $DIR/feature-gate-try_blocks.rs:5:33
|
||||
|
|
||||
LL | let try_result: Option<_> = try {
|
||||
| _________________________________^
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
// Type ascription is unstable
|
||||
|
||||
fn main() {
|
||||
#[cfg(FALSE)]
|
||||
fn foo() {
|
||||
let a = 10: u8; //~ ERROR type ascription is experimental
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error[E0658]: type ascription is experimental
|
||||
--> $DIR/feature-gate-type_ascription.rs:4:13
|
||||
--> $DIR/feature-gate-type_ascription.rs:5:13
|
||||
|
|
||||
LL | let a = 10: u8;
|
||||
| ^^^^^^
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ LL | | a: String,
|
|||
LL | | }
|
||||
| |_^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/32836
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/55149
|
||||
= help: add `#![feature(untagged_unions)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: unions with non-`Copy` fields are unstable
|
||||
|
|
@ -17,7 +17,7 @@ LL | | a: T,
|
|||
LL | | }
|
||||
| |_^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/32836
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/55149
|
||||
= help: add `#![feature(untagged_unions)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: unions with `Drop` implementations are unstable
|
||||
|
|
@ -28,7 +28,7 @@ LL | | a: u8,
|
|||
LL | | }
|
||||
| |_^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/32836
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/55149
|
||||
= help: add `#![feature(untagged_unions)]` to the crate attributes to enable
|
||||
|
||||
error[E0740]: unions may not contain fields that need dropping
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position
|
||||
--> $DIR/universal-issue-48703.rs:8:5
|
||||
--> $DIR/universal-issue-48703.rs:8:11
|
||||
|
|
||||
LL | foo::<String>('a');
|
||||
| ^^^^^^^^^^^^^
|
||||
| ^^^^^^ explicit generic argument not allowed
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position
|
||||
--> $DIR/universal-turbofish-in-method-issue-50950.rs:14:9
|
||||
--> $DIR/universal-turbofish-in-method-issue-50950.rs:14:24
|
||||
|
|
||||
LL | evt.handle_event::<TestEvent, fn(TestEvent)>(|_evt| {
|
||||
| ^^^^^^^^^^^^
|
||||
| ^^^^^^^^^ ^^^^^^^^^^^^^ explicit generic argument not allowed
|
||||
| |
|
||||
| explicit generic argument not allowed
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -6,3 +6,4 @@ LL | <Dst as From<Self>>::Dst
|
|||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0576`.
|
||||
|
|
|
|||
|
|
@ -6,3 +6,4 @@ LL | fn a(&self) -> <Self as A>::X;
|
|||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0576`.
|
||||
|
|
|
|||
|
|
@ -6,3 +6,4 @@ LL | <<i32 as Copy>::foobar as Trait>::foo();
|
|||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0576`.
|
||||
|
|
|
|||
18
src/test/ui/nll/empty-type-predicate-2.rs
Normal file
18
src/test/ui/nll/empty-type-predicate-2.rs
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
// Regression test for #65553
|
||||
//
|
||||
// `D::Error:` is lowered to `D::Error: ReEmpty` - check that we don't ICE in
|
||||
// NLL for the unexpected region.
|
||||
|
||||
// check-pass
|
||||
|
||||
trait Deserializer {
|
||||
type Error;
|
||||
}
|
||||
|
||||
fn d1<D: Deserializer>() where D::Error: {}
|
||||
|
||||
fn d2<D: Deserializer>() {
|
||||
d1::<D>();
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -3,9 +3,9 @@
|
|||
// `dyn T:` is lowered to `dyn T: ReEmpty` - check that we don't ICE in NLL for
|
||||
// the unexpected region.
|
||||
|
||||
// build-pass (FIXME(62277): could be check-pass?)
|
||||
// check-pass
|
||||
|
||||
trait T {}
|
||||
fn f() where dyn T: {}
|
||||
|
||||
fn main() {}
|
||||
fn main() { f(); }
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
// check-pass
|
||||
|
||||
#![feature(or_patterns)]
|
||||
#![feature(box_patterns)]
|
||||
|
||||
fn main() {}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ fn main() {
|
|||
match 0 {
|
||||
(.. PAT) => {}
|
||||
//~^ ERROR `..X` range patterns are not supported
|
||||
//~| ERROR exclusive range pattern syntax is experimental
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,17 +4,8 @@ error: `..X` range patterns are not supported
|
|||
LL | (.. PAT) => {}
|
||||
| ^^^^^^ help: try using the minimum value for the type: `MIN..PAT`
|
||||
|
||||
error[E0658]: exclusive range pattern syntax is experimental
|
||||
--> $DIR/pat-tuple-4.rs:5:10
|
||||
|
|
||||
LL | (.. PAT) => {}
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/37854
|
||||
= help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pat-tuple-4.rs:11:30
|
||||
--> $DIR/pat-tuple-4.rs:10:30
|
||||
|
|
||||
LL | const RECOVERY_WITNESS: () = 0;
|
||||
| ^ expected (), found integer
|
||||
|
|
@ -22,7 +13,6 @@ LL | const RECOVERY_WITNESS: () = 0;
|
|||
= note: expected type `()`
|
||||
found type `{integer}`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0308, E0658.
|
||||
For more information about an error, try `rustc --explain E0308`.
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
|
|
|||
|
|
@ -5,10 +5,10 @@ LL | (PAT ..) => {}
|
|||
| ^^^^^^ help: try using the maximum value for the type: `PAT..MAX`
|
||||
|
||||
error[E0658]: exclusive range pattern syntax is experimental
|
||||
--> $DIR/pat-tuple-5.rs:5:10
|
||||
--> $DIR/pat-tuple-5.rs:5:14
|
||||
|
|
||||
LL | (PAT ..) => {}
|
||||
| ^^^^^^
|
||||
| ^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/37854
|
||||
= help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
// check-pass
|
||||
|
||||
#![feature(box_patterns)]
|
||||
|
||||
fn main() {}
|
||||
|
||||
macro_rules! accept_pat {
|
||||
|
|
|
|||
16
src/test/ui/proc-macro/proc-macro-deprecated-attr.rs
Normal file
16
src/test/ui/proc-macro/proc-macro-deprecated-attr.rs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
// check-pass
|
||||
// force-host
|
||||
// no-prefer-dynamic
|
||||
|
||||
#![deny(deprecated)]
|
||||
|
||||
#![crate_type = "proc-macro"]
|
||||
|
||||
extern crate proc_macro;
|
||||
use proc_macro::*;
|
||||
|
||||
#[proc_macro]
|
||||
#[deprecated(since = "1.0.0", note = "test")]
|
||||
pub fn test_compile_without_warning_with_deprecated(_: TokenStream) -> TokenStream {
|
||||
TokenStream::new()
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
// aux-build:uninhabited.rs
|
||||
#![deny(unreachable_patterns)]
|
||||
#![feature(never_type)]
|
||||
#![feature(non_exhaustive)]
|
||||
|
||||
extern crate uninhabited;
|
||||
|
||||
use uninhabited::PartiallyInhabitedVariants;
|
||||
|
||||
// This test checks a redundant/useless pattern of a non-exhaustive enum/variant is still
|
||||
// warned against.
|
||||
|
||||
pub fn foo(x: PartiallyInhabitedVariants) {
|
||||
match x {
|
||||
PartiallyInhabitedVariants::Struct { .. } => {},
|
||||
PartiallyInhabitedVariants::Struct { .. } => {},
|
||||
//~^ ERROR unreachable pattern
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
error: unreachable pattern
|
||||
--> $DIR/issue-65157-repeated-match-arm.rs:16:9
|
||||
|
|
||||
LL | PartiallyInhabitedVariants::Struct { .. } => {},
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: lint level defined here
|
||||
--> $DIR/issue-65157-repeated-match-arm.rs:2:9
|
||||
|
|
||||
LL | #![deny(unreachable_patterns)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
@ -1,20 +1,20 @@
|
|||
error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position
|
||||
--> $DIR/synthetic-param.rs:20:5
|
||||
--> $DIR/synthetic-param.rs:20:12
|
||||
|
|
||||
LL | func::<u8>(42);
|
||||
| ^^^^^^^^^^
|
||||
| ^^ explicit generic argument not allowed
|
||||
|
||||
error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position
|
||||
--> $DIR/synthetic-param.rs:23:5
|
||||
--> $DIR/synthetic-param.rs:23:17
|
||||
|
|
||||
LL | Foo::func::<u8>(42);
|
||||
| ^^^^^^^^^^^^^^^
|
||||
| ^^ explicit generic argument not allowed
|
||||
|
||||
error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position
|
||||
--> $DIR/synthetic-param.rs:26:5
|
||||
--> $DIR/synthetic-param.rs:26:23
|
||||
|
|
||||
LL | Bar::<i8>::func::<u8>(42);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^ explicit generic argument not allowed
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -4,4 +4,7 @@ trait Foo {}
|
|||
auto trait A = Foo; //~ ERROR trait aliases cannot be `auto`
|
||||
unsafe trait B = Foo; //~ ERROR trait aliases cannot be `unsafe`
|
||||
|
||||
trait C: Ord = Eq; //~ ERROR bounds are not allowed on trait aliases
|
||||
trait D: = Eq; //~ ERROR bounds are not allowed on trait aliases
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,26 @@
|
|||
error: trait aliases cannot be `auto`
|
||||
--> $DIR/trait-alias-syntax-fail.rs:4:19
|
||||
--> $DIR/trait-alias-syntax-fail.rs:4:1
|
||||
|
|
||||
LL | auto trait A = Foo;
|
||||
| ^ trait aliases cannot be `auto`
|
||||
| ^^^^^^^^^^^^^^^^^^^ trait aliases cannot be `auto`
|
||||
|
||||
error: trait aliases cannot be `unsafe`
|
||||
--> $DIR/trait-alias-syntax-fail.rs:5:21
|
||||
--> $DIR/trait-alias-syntax-fail.rs:5:1
|
||||
|
|
||||
LL | unsafe trait B = Foo;
|
||||
| ^ trait aliases cannot be `unsafe`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ trait aliases cannot be `unsafe`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: bounds are not allowed on trait aliases
|
||||
--> $DIR/trait-alias-syntax-fail.rs:7:8
|
||||
|
|
||||
LL | trait C: Ord = Eq;
|
||||
| ^^^^^
|
||||
|
||||
error: bounds are not allowed on trait aliases
|
||||
--> $DIR/trait-alias-syntax-fail.rs:8:8
|
||||
|
|
||||
LL | trait D: = Eq;
|
||||
| ^
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -30,5 +30,5 @@ LL | let _ = |a, b: _| -> _ { 0 };
|
|||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0282, E0412, E0425, E0433.
|
||||
Some errors have detailed explanations: E0282, E0412, E0425, E0433, E0576.
|
||||
For more information about an error, try `rustc --explain E0282`.
|
||||
|
|
|
|||
|
|
@ -200,5 +200,5 @@ LL | <u8 as Dr>::X::N;
|
|||
|
||||
error: aborting due to 32 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0223, E0433, E0575, E0599.
|
||||
Some errors have detailed explanations: E0223, E0433, E0575, E0576, E0599.
|
||||
For more information about an error, try `rustc --explain E0223`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue