dependencies = [
"graphviz 0.0.0",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc 0.0.0",
"rustc_data_structures 0.0.0",
"rustc_fs_util 0.0.0",
"rustc_resolve 0.0.0",
"rustc_traits 0.0.0",
"rustc_typeck 0.0.0",
- "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serialize 0.0.0",
"smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
"syntax 0.0.0",
test::Miri,
test::Clippy,
test::CompiletestTest,
- test::RustdocJS,
+ test::RustdocJSStd,
+ test::RustdocJSNotStd,
test::RustdocTheme,
// Run bootstrap close to the end as it's unlikely to fail
test::Bootstrap,
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
-pub struct RustdocJS {
+pub struct RustdocJSStd {
pub host: Interned<String>,
pub target: Interned<String>,
}
-impl Step for RustdocJS {
+impl Step for RustdocJSStd {
type Output = ();
const DEFAULT: bool = true;
const ONLY_HOSTS: bool = true;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
- run.path("src/test/rustdoc-js")
+ run.path("src/test/rustdoc-js-std")
}
fn make_run(run: RunConfig<'_>) {
- run.builder.ensure(RustdocJS {
+ run.builder.ensure(RustdocJSStd {
host: run.host,
target: run.target,
});
fn run(self, builder: &Builder<'_>) {
if let Some(ref nodejs) = builder.config.nodejs {
let mut command = Command::new(nodejs);
- command.args(&["src/tools/rustdoc-js/tester.js", &*self.host]);
+ command.args(&["src/tools/rustdoc-js-std/tester.js", &*self.host]);
builder.ensure(crate::doc::Std {
target: self.target,
stage: builder.top_stage,
});
builder.run(&mut command);
+ } else {
+ builder.info(
+ "No nodejs found, skipping \"src/test/rustdoc-js-std\" tests"
+ );
+ }
+ }
+}
+
+#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
+pub struct RustdocJSNotStd {
+ pub host: Interned<String>,
+ pub target: Interned<String>,
+ pub compiler: Compiler,
+}
+
+impl Step for RustdocJSNotStd {
+ type Output = ();
+ const DEFAULT: bool = true;
+ const ONLY_HOSTS: bool = true;
+
+ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+ run.path("src/test/rustdoc-js")
+ }
+
+ fn make_run(run: RunConfig<'_>) {
+ let compiler = run.builder.compiler(run.builder.top_stage, run.host);
+ run.builder.ensure(RustdocJSNotStd {
+ host: run.host,
+ target: run.target,
+ compiler,
+ });
+ }
+
+ fn run(self, builder: &Builder<'_>) {
+ if builder.config.nodejs.is_some() {
+ builder.ensure(Compiletest {
+ compiler: self.compiler,
+ target: self.target,
+ mode: "js-doc-test",
+ suite: "rustdoc-js",
+ path: None,
+ compare_mode: None,
+ });
} else {
builder.info(
"No nodejs found, skipping \"src/test/rustdoc-js\" tests"
.arg(builder.sysroot_libdir(compiler, target));
cmd.arg("--rustc-path").arg(builder.rustc(compiler));
- let is_rustdoc_ui = suite.ends_with("rustdoc-ui");
+ let is_rustdoc = suite.ends_with("rustdoc-ui") || suite.ends_with("rustdoc-js");
// Avoid depending on rustdoc when we don't need it.
if mode == "rustdoc"
|| (mode == "run-make" && suite.ends_with("fulldeps"))
- || (mode == "ui" && is_rustdoc_ui)
+ || (mode == "ui" && is_rustdoc)
+ || mode == "js-doc-test"
{
cmd.arg("--rustdoc-path")
.arg(builder.rustdoc(compiler.host));
cmd.arg("--nodejs").arg(nodejs);
}
- let mut flags = if is_rustdoc_ui {
+ let mut flags = if is_rustdoc {
Vec::new()
} else {
vec!["-Crpath".to_string()]
};
- if !is_rustdoc_ui {
+ if !is_rustdoc {
if builder.config.rust_optimize_tests {
flags.push("-O".to_string());
}
}
#[stable(feature = "box_from_slice", since = "1.17.0")]
-impl<'a, T: Copy> From<&'a [T]> for Box<[T]> {
+impl<T: Copy> From<&[T]> for Box<[T]> {
/// Converts a `&[T]` into a `Box<[T]>`
///
/// This conversion allocates on the heap
///
/// println!("{:?}", boxed_slice);
/// ```
- fn from(slice: &'a [T]) -> Box<[T]> {
+ fn from(slice: &[T]) -> Box<[T]> {
let mut boxed = unsafe { RawVec::with_capacity(slice.len()).into_box() };
boxed.copy_from_slice(slice);
boxed
}
#[stable(feature = "box_from_slice", since = "1.17.0")]
-impl<'a> From<&'a str> for Box<str> {
+impl From<&str> for Box<str> {
/// Converts a `&str` into a `Box<str>`
///
/// This conversion allocates on the heap
/// println!("{}", boxed);
/// ```
#[inline]
- fn from(s: &'a str) -> Box<str> {
+ fn from(s: &str) -> Box<str> {
unsafe { from_boxed_utf8_unchecked(Box::from(s.as_bytes())) }
}
}
}
#[stable(feature = "shared_from_slice", since = "1.21.0")]
-impl<'a, T: Clone> From<&'a [T]> for Rc<[T]> {
+impl<T: Clone> From<&[T]> for Rc<[T]> {
#[inline]
fn from(v: &[T]) -> Rc<[T]> {
<Self as RcFromSlice<T>>::from_slice(v)
}
#[stable(feature = "shared_from_slice", since = "1.21.0")]
-impl<'a> From<&'a str> for Rc<str> {
+impl From<&str> for Rc<str> {
#[inline]
fn from(v: &str) -> Rc<str> {
let rc = Rc::<[u8]>::from(v.as_bytes());
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a> From<&'a str> for String {
+impl From<&str> for String {
#[inline]
- fn from(s: &'a str) -> String {
+ fn from(s: &str) -> String {
s.to_owned()
}
}
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T: Clone> From<&'a [T]> for Vec<T> {
+impl<T: Clone> From<&[T]> for Vec<T> {
#[cfg(not(test))]
- fn from(s: &'a [T]) -> Vec<T> {
+ fn from(s: &[T]) -> Vec<T> {
s.to_vec()
}
#[cfg(test)]
- fn from(s: &'a [T]) -> Vec<T> {
+ fn from(s: &[T]) -> Vec<T> {
crate::slice::to_vec(s)
}
}
#[stable(feature = "vec_from_mut", since = "1.19.0")]
-impl<'a, T: Clone> From<&'a mut [T]> for Vec<T> {
+impl<T: Clone> From<&mut [T]> for Vec<T> {
#[cfg(not(test))]
- fn from(s: &'a mut [T]) -> Vec<T> {
+ fn from(s: &mut [T]) -> Vec<T> {
s.to_vec()
}
#[cfg(test)]
- fn from(s: &'a mut [T]) -> Vec<T> {
+ fn from(s: &mut [T]) -> Vec<T> {
crate::slice::to_vec(s)
}
}
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a> From<&'a str> for Vec<u8> {
- fn from(s: &'a str) -> Vec<u8> {
+impl From<&str> for Vec<u8> {
+ fn from(s: &str) -> Vec<u8> {
From::from(s.as_bytes())
}
}
}
#[stable(feature = "try_from", since = "1.34.0")]
- impl<'a, T> TryFrom<&'a [T]> for [T; $N] where T: Copy {
+ impl<T> TryFrom<&[T]> for [T; $N] where T: Copy {
type Error = TryFromSliceError;
fn try_from(slice: &[T]) -> Result<[T; $N], TryFromSliceError> {
// & pointers
#[stable(feature = "rust1", since = "1.0.0")]
- impl<'a, 'b, A: ?Sized, B: ?Sized> PartialEq<&'b B> for &'a A where A: PartialEq<B> {
+ impl<A: ?Sized, B: ?Sized> PartialEq<&B> for &A where A: PartialEq<B> {
#[inline]
- fn eq(&self, other: & &'b B) -> bool { PartialEq::eq(*self, *other) }
+ fn eq(&self, other: & &B) -> bool { PartialEq::eq(*self, *other) }
#[inline]
- fn ne(&self, other: & &'b B) -> bool { PartialEq::ne(*self, *other) }
+ fn ne(&self, other: & &B) -> bool { PartialEq::ne(*self, *other) }
}
#[stable(feature = "rust1", since = "1.0.0")]
- impl<'a, 'b, A: ?Sized, B: ?Sized> PartialOrd<&'b B> for &'a A where A: PartialOrd<B> {
+ impl<A: ?Sized, B: ?Sized> PartialOrd<&B> for &A where A: PartialOrd<B> {
#[inline]
- fn partial_cmp(&self, other: &&'b B) -> Option<Ordering> {
+ fn partial_cmp(&self, other: &&B) -> Option<Ordering> {
PartialOrd::partial_cmp(*self, *other)
}
#[inline]
- fn lt(&self, other: & &'b B) -> bool { PartialOrd::lt(*self, *other) }
+ fn lt(&self, other: & &B) -> bool { PartialOrd::lt(*self, *other) }
#[inline]
- fn le(&self, other: & &'b B) -> bool { PartialOrd::le(*self, *other) }
+ fn le(&self, other: & &B) -> bool { PartialOrd::le(*self, *other) }
#[inline]
- fn ge(&self, other: & &'b B) -> bool { PartialOrd::ge(*self, *other) }
+ fn ge(&self, other: & &B) -> bool { PartialOrd::ge(*self, *other) }
#[inline]
- fn gt(&self, other: & &'b B) -> bool { PartialOrd::gt(*self, *other) }
+ fn gt(&self, other: & &B) -> bool { PartialOrd::gt(*self, *other) }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<A: ?Sized> Ord for &A where A: Ord {
// &mut pointers
#[stable(feature = "rust1", since = "1.0.0")]
- impl<'a, 'b, A: ?Sized, B: ?Sized> PartialEq<&'b mut B> for &'a mut A where A: PartialEq<B> {
+ impl<A: ?Sized, B: ?Sized> PartialEq<&mut B> for &mut A where A: PartialEq<B> {
#[inline]
- fn eq(&self, other: &&'b mut B) -> bool { PartialEq::eq(*self, *other) }
+ fn eq(&self, other: &&mut B) -> bool { PartialEq::eq(*self, *other) }
#[inline]
- fn ne(&self, other: &&'b mut B) -> bool { PartialEq::ne(*self, *other) }
+ fn ne(&self, other: &&mut B) -> bool { PartialEq::ne(*self, *other) }
}
#[stable(feature = "rust1", since = "1.0.0")]
- impl<'a, 'b, A: ?Sized, B: ?Sized> PartialOrd<&'b mut B> for &'a mut A where A: PartialOrd<B> {
+ impl<A: ?Sized, B: ?Sized> PartialOrd<&mut B> for &mut A where A: PartialOrd<B> {
#[inline]
- fn partial_cmp(&self, other: &&'b mut B) -> Option<Ordering> {
+ fn partial_cmp(&self, other: &&mut B) -> Option<Ordering> {
PartialOrd::partial_cmp(*self, *other)
}
#[inline]
- fn lt(&self, other: &&'b mut B) -> bool { PartialOrd::lt(*self, *other) }
+ fn lt(&self, other: &&mut B) -> bool { PartialOrd::lt(*self, *other) }
#[inline]
- fn le(&self, other: &&'b mut B) -> bool { PartialOrd::le(*self, *other) }
+ fn le(&self, other: &&mut B) -> bool { PartialOrd::le(*self, *other) }
#[inline]
- fn ge(&self, other: &&'b mut B) -> bool { PartialOrd::ge(*self, *other) }
+ fn ge(&self, other: &&mut B) -> bool { PartialOrd::ge(*self, *other) }
#[inline]
- fn gt(&self, other: &&'b mut B) -> bool { PartialOrd::gt(*self, *other) }
+ fn gt(&self, other: &&mut B) -> bool { PartialOrd::gt(*self, *other) }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<A: ?Sized> Ord for &mut A where A: Ord {
impl<A: ?Sized> Eq for &mut A where A: Eq {}
#[stable(feature = "rust1", since = "1.0.0")]
- impl<'a, 'b, A: ?Sized, B: ?Sized> PartialEq<&'b mut B> for &'a A where A: PartialEq<B> {
+ impl<A: ?Sized, B: ?Sized> PartialEq<&mut B> for &A where A: PartialEq<B> {
#[inline]
- fn eq(&self, other: &&'b mut B) -> bool { PartialEq::eq(*self, *other) }
+ fn eq(&self, other: &&mut B) -> bool { PartialEq::eq(*self, *other) }
#[inline]
- fn ne(&self, other: &&'b mut B) -> bool { PartialEq::ne(*self, *other) }
+ fn ne(&self, other: &&mut B) -> bool { PartialEq::ne(*self, *other) }
}
#[stable(feature = "rust1", since = "1.0.0")]
- impl<'a, 'b, A: ?Sized, B: ?Sized> PartialEq<&'b B> for &'a mut A where A: PartialEq<B> {
+ impl<A: ?Sized, B: ?Sized> PartialEq<&B> for &mut A where A: PartialEq<B> {
#[inline]
- fn eq(&self, other: &&'b B) -> bool { PartialEq::eq(*self, *other) }
+ fn eq(&self, other: &&B) -> bool { PartialEq::eq(*self, *other) }
#[inline]
- fn ne(&self, other: &&'b B) -> bool { PartialEq::ne(*self, *other) }
+ fn ne(&self, other: &&B) -> bool { PartialEq::ne(*self, *other) }
}
}
/// An attempted conversion that consumes `self`, which may or may not be
/// expensive.
///
-/// Library authors should not directly implement this trait, but should prefer
-/// implementing the [`TryFrom`] trait, which offers greater flexibility and
-/// provides an equivalent `TryInto` implementation for free, thanks to a
-/// blanket implementation in the standard library. For more information on this,
-/// see the documentation for [`Into`].
+/// Library authors should usually not directly implement this trait,
+/// but should prefer implementing the [`TryFrom`] trait, which offers
+/// greater flexibility and provides an equivalent `TryInto`
+/// implementation for free, thanks to a blanket implementation in the
+/// standard library. For more information on this, see the
+/// documentation for [`Into`].
+///
+/// # Implementing `TryInto`
+///
+/// This suffers the same restrictions and reasoning as implementing
+/// [`Into`], see there for details.
///
/// [`TryFrom`]: trait.TryFrom.html
/// [`Into`]: trait.Into.html
fn try_into(self) -> Result<T, Self::Error>;
}
-/// Attempt to construct `Self` via a conversion.
+/// Simple and safe type conversions that may fail in a controlled
+/// way under some circumstances. It is the reciprocal of [`TryInto`].
+///
+/// This is useful when you are doing a type conversion that may
+/// trivially succeed but may also need special handling.
+/// For example, there is no way to convert an `i64` into an `i32`
+/// using the [`From`] trait, because an `i64` may contain a value
+/// that an `i32` cannot represent and so the conversion would lose data.
+/// This might be handled by truncating the `i64` to an `i32` (essentially
+/// giving the `i64`'s value modulo `i32::MAX`) or by simply returning
+/// `i32::MAX`, or by some other method. The `From` trait is intended
+/// for perfect conversions, so the `TryFrom` trait informs the
+/// programmer when a type conversion could go bad and lets them
+/// decide how to handle it.
+///
+/// # Generic Implementations
+///
+/// - `TryFrom<T> for U` implies [`TryInto<U>`]` for T`
+/// - [`try_from`] is reflexive, which means that `TryFrom<T> for T`
+/// is implemented and cannot fail -- the associated `Error` type for
+/// calling `T::try_from()` on a value of type `T` is `Infallible`.
+/// When the `!` type is stablized `Infallible` and `!` will be
+/// equivalent.
+///
+/// # Examples
+///
+/// As described, [`i32`] implements `TryFrom<i64>`:
+///
+/// ```
+/// use std::convert::TryFrom;
+///
+/// let big_number = 1_000_000_000_000i64;
+/// // Silently truncates `big_number`, requires detecting
+/// // and handling the truncation after the fact.
+/// let smaller_number = big_number as i32;
+/// assert_eq!(smaller_number, -727379968);
+///
+/// // Returns an error because `big_number` is too big to
+/// // fit in an `i32`.
+/// let try_smaller_number = i32::try_from(big_number);
+/// assert!(try_smaller_number.is_err());
+///
+/// // Returns `Ok(3)`.
+/// let try_successful_smaller_number = i32::try_from(3);
+/// assert!(try_successful_smaller_number.is_ok());
+/// ```
+///
+/// [`try_from`]: trait.TryFrom.html#tymethod.try_from
+/// [`TryInto`]: trait.TryInto.html
#[stable(feature = "try_from", since = "1.34.0")]
pub trait TryFrom<T>: Sized {
/// The type returned in the event of a conversion error.
}
#[$attr]
- impl<'a> $imp<&'a $u> for $t {
+ impl $imp<&$u> for $t {
type Output = <$t as $imp<$u>>::Output;
#[inline]
- fn $method(self, other: &'a $u) -> <$t as $imp<$u>>::Output {
+ fn $method(self, other: &$u) -> <$t as $imp<$u>>::Output {
$imp::$method(self, *other)
}
}
#[$attr]
- impl<'a, 'b> $imp<&'a $u> for &'b $t {
+ impl $imp<&$u> for &$t {
type Output = <$t as $imp<$u>>::Output;
#[inline]
- fn $method(self, other: &'a $u) -> <$t as $imp<$u>>::Output {
+ fn $method(self, other: &$u) -> <$t as $imp<$u>>::Output {
$imp::$method(*self, *other)
}
}
};
(impl $imp:ident, $method:ident for $t:ty, $u:ty, #[$attr:meta]) => {
#[$attr]
- impl<'a> $imp<&'a $u> for $t {
+ impl $imp<&$u> for $t {
#[inline]
- fn $method(&mut self, other: &'a $u) {
+ fn $method(&mut self, other: &$u) {
$imp::$method(self, *other);
}
}
```
use std::convert::TryInto;
-fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " {
+fn read_le_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " {
let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">());
*input = rest;
- ", stringify!($SelfT), "::from_be_bytes(int_bytes.try_into().unwrap())
+ ", stringify!($SelfT), "::from_le_bytes(int_bytes.try_into().unwrap())
}
```"),
#[stable(feature = "int_to_from_bytes", since = "1.32.0")]
```
use std::convert::TryInto;
-fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " {
+fn read_ne_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " {
let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">());
*input = rest;
- ", stringify!($SelfT), "::from_be_bytes(int_bytes.try_into().unwrap())
+ ", stringify!($SelfT), "::from_ne_bytes(int_bytes.try_into().unwrap())
}
```"),
#[stable(feature = "int_to_from_bytes", since = "1.32.0")]
```
use std::convert::TryInto;
-fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " {
+fn read_le_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " {
let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">());
*input = rest;
- ", stringify!($SelfT), "::from_be_bytes(int_bytes.try_into().unwrap())
+ ", stringify!($SelfT), "::from_le_bytes(int_bytes.try_into().unwrap())
}
```"),
#[stable(feature = "int_to_from_bytes", since = "1.32.0")]
```
use std::convert::TryInto;
-fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " {
+fn read_ne_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " {
let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">());
*input = rest;
- ", stringify!($SelfT), "::from_be_bytes(int_bytes.try_into().unwrap())
+ ", stringify!($SelfT), "::from_ne_bytes(int_bytes.try_into().unwrap())
}
```"),
#[stable(feature = "int_to_from_bytes", since = "1.32.0")]
impl TryFrom<$source> for $target {
type Error = TryFromIntError;
+ /// Try to create the target number type from a source
+ /// number type. This returns an error if the source value
+ /// is outside of the range of the target type.
#[inline]
fn try_from(value: $source) -> Result<Self, Self::Error> {
Ok(value as $target)
impl TryFrom<$source> for $target {
type Error = TryFromIntError;
+ /// Try to create the target number type from a source
+ /// number type. This returns an error if the source value
+ /// is outside of the range of the target type.
#[inline]
fn try_from(u: $source) -> Result<$target, TryFromIntError> {
if u >= 0 {
impl TryFrom<$source> for $target {
type Error = TryFromIntError;
+ /// Try to create the target number type from a source
+ /// number type. This returns an error if the source value
+ /// is outside of the range of the target type.
#[inline]
fn try_from(u: $source) -> Result<$target, TryFromIntError> {
if u > (<$target>::max_value() as $source) {
impl TryFrom<$source> for $target {
type Error = TryFromIntError;
+ /// Try to create the target number type from a source
+ /// number type. This returns an error if the source value
+ /// is outside of the range of the target type.
#[inline]
fn try_from(u: $source) -> Result<$target, TryFromIntError> {
let min = <$target>::min_value() as $source;
/// Used as a [slicing index], `RangeFull` produces the full array as a slice.
///
/// ```
-/// let arr = [0, 1, 2, 3];
-/// assert_eq!(arr[ .. ], [0,1,2,3]); // RangeFull
-/// assert_eq!(arr[ ..3], [0,1,2 ]);
-/// assert_eq!(arr[1.. ], [ 1,2,3]);
-/// assert_eq!(arr[1..3], [ 1,2 ]);
+/// let arr = [0, 1, 2, 3, 4];
+/// assert_eq!(arr[ .. ], [0,1,2,3,4]); // RangeFull
+/// assert_eq!(arr[ .. 3], [0,1,2 ]);
+/// assert_eq!(arr[ ..=3], [0,1,2,3 ]);
+/// assert_eq!(arr[1.. ], [ 1,2,3,4]);
+/// assert_eq!(arr[1.. 3], [ 1,2 ]);
+/// assert_eq!(arr[1..=3], [ 1,2,3 ]);
/// ```
///
/// [`IntoIterator`]: ../iter/trait.Iterator.html
/// assert_eq!((3..5), std::ops::Range { start: 3, end: 5 });
/// assert_eq!(3 + 4 + 5, (3..6).sum());
///
-/// let arr = ['a', 'b', 'c', 'd'];
-/// assert_eq!(arr[ .. ], ['a', 'b', 'c', 'd']);
-/// assert_eq!(arr[ ..3], ['a', 'b', 'c', ]);
-/// assert_eq!(arr[1.. ], [ 'b', 'c', 'd']);
-/// assert_eq!(arr[1..3], [ 'b', 'c' ]); // Range
+/// let arr = [0, 1, 2, 3, 4];
+/// assert_eq!(arr[ .. ], [0,1,2,3,4]);
+/// assert_eq!(arr[ .. 3], [0,1,2 ]);
+/// assert_eq!(arr[ ..=3], [0,1,2,3 ]);
+/// assert_eq!(arr[1.. ], [ 1,2,3,4]);
+/// assert_eq!(arr[1.. 3], [ 1,2 ]); // Range
+/// assert_eq!(arr[1..=3], [ 1,2,3 ]);
/// ```
#[doc(alias = "..")]
#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186
/// assert_eq!((2..), std::ops::RangeFrom { start: 2 });
/// assert_eq!(2 + 3 + 4, (2..).take(3).sum());
///
-/// let arr = [0, 1, 2, 3];
-/// assert_eq!(arr[ .. ], [0,1,2,3]);
-/// assert_eq!(arr[ ..3], [0,1,2 ]);
-/// assert_eq!(arr[1.. ], [ 1,2,3]); // RangeFrom
-/// assert_eq!(arr[1..3], [ 1,2 ]);
+/// let arr = [0, 1, 2, 3, 4];
+/// assert_eq!(arr[ .. ], [0,1,2,3,4]);
+/// assert_eq!(arr[ .. 3], [0,1,2 ]);
+/// assert_eq!(arr[ ..=3], [0,1,2,3 ]);
+/// assert_eq!(arr[1.. ], [ 1,2,3,4]); // RangeFrom
+/// assert_eq!(arr[1.. 3], [ 1,2 ]);
+/// assert_eq!(arr[1..=3], [ 1,2,3 ]);
/// ```
///
/// [`Iterator`]: ../iter/trait.IntoIterator.html
/// elements before the index indicated by `end`.
///
/// ```
-/// let arr = [0, 1, 2, 3];
-/// assert_eq!(arr[ .. ], [0,1,2,3]);
-/// assert_eq!(arr[ ..3], [0,1,2 ]); // RangeTo
-/// assert_eq!(arr[1.. ], [ 1,2,3]);
-/// assert_eq!(arr[1..3], [ 1,2 ]);
+/// let arr = [0, 1, 2, 3, 4];
+/// assert_eq!(arr[ .. ], [0,1,2,3,4]);
+/// assert_eq!(arr[ .. 3], [0,1,2 ]); // RangeTo
+/// assert_eq!(arr[ ..=3], [0,1,2,3 ]);
+/// assert_eq!(arr[1.. ], [ 1,2,3,4]);
+/// assert_eq!(arr[1.. 3], [ 1,2 ]);
+/// assert_eq!(arr[1..=3], [ 1,2,3 ]);
/// ```
///
/// [`IntoIterator`]: ../iter/trait.Iterator.html
/// assert_eq!((3..=5), std::ops::RangeInclusive::new(3, 5));
/// assert_eq!(3 + 4 + 5, (3..=5).sum());
///
-/// let arr = [0, 1, 2, 3];
-/// assert_eq!(arr[ ..=2], [0,1,2 ]);
-/// assert_eq!(arr[1..=2], [ 1,2 ]); // RangeInclusive
+/// let arr = [0, 1, 2, 3, 4];
+/// assert_eq!(arr[ .. ], [0,1,2,3,4]);
+/// assert_eq!(arr[ .. 3], [0,1,2 ]);
+/// assert_eq!(arr[ ..=3], [0,1,2,3 ]);
+/// assert_eq!(arr[1.. ], [ 1,2,3,4]);
+/// assert_eq!(arr[1.. 3], [ 1,2 ]);
+/// assert_eq!(arr[1..=3], [ 1,2,3 ]); // RangeInclusive
/// ```
#[doc(alias = "..=")]
#[derive(Clone)] // not Copy -- see #27186
/// array elements up to and including the index indicated by `end`.
///
/// ```
-/// let arr = [0, 1, 2, 3];
-/// assert_eq!(arr[ ..=2], [0,1,2 ]); // RangeToInclusive
-/// assert_eq!(arr[1..=2], [ 1,2 ]);
+/// let arr = [0, 1, 2, 3, 4];
+/// assert_eq!(arr[ .. ], [0,1,2,3,4]);
+/// assert_eq!(arr[ .. 3], [0,1,2 ]);
+/// assert_eq!(arr[ ..=3], [0,1,2,3 ]); // RangeToInclusive
+/// assert_eq!(arr[1.. ], [ 1,2,3,4]);
+/// assert_eq!(arr[1.. 3], [ 1,2 ]);
+/// assert_eq!(arr[1..=3], [ 1,2,3 ]);
/// ```
///
/// [`IntoIterator`]: ../iter/trait.Iterator.html
#[stable(feature = "collections_range", since = "1.28.0")]
/// `RangeBounds` is implemented by Rust's built-in range types, produced
-/// by range syntax like `..`, `a..`, `..b` or `c..d`.
+/// by range syntax like `..`, `a..`, `..b`, `..=c`, `d..e`, or `f..=g`.
pub trait RangeBounds<T: ?Sized> {
/// Start index bound.
///
}
#[unstable(feature = "ptr_internals", issue = "0")]
-impl<'a, T: ?Sized> From<&'a mut T> for Unique<T> {
- fn from(reference: &'a mut T) -> Self {
+impl<T: ?Sized> From<&mut T> for Unique<T> {
+ fn from(reference: &mut T) -> Self {
unsafe { Unique { pointer: reference as *mut T, _marker: PhantomData } }
}
}
#[unstable(feature = "ptr_internals", issue = "0")]
-impl<'a, T: ?Sized> From<&'a T> for Unique<T> {
- fn from(reference: &'a T) -> Self {
+impl<T: ?Sized> From<&T> for Unique<T> {
+ fn from(reference: &T) -> Self {
unsafe { Unique { pointer: reference as *const T, _marker: PhantomData } }
}
}
}
#[stable(feature = "nonnull", since = "1.25.0")]
-impl<'a, T: ?Sized> From<&'a mut T> for NonNull<T> {
+impl<T: ?Sized> From<&mut T> for NonNull<T> {
#[inline]
- fn from(reference: &'a mut T) -> Self {
+ fn from(reference: &mut T) -> Self {
unsafe { NonNull { pointer: reference as *mut T } }
}
}
#[stable(feature = "nonnull", since = "1.25.0")]
-impl<'a, T: ?Sized> From<&'a T> for NonNull<T> {
+impl<T: ?Sized> From<&T> for NonNull<T> {
#[inline]
- fn from(reference: &'a T) -> Self {
+ fn from(reference: &T) -> Self {
unsafe { NonNull { pointer: reference as *const T } }
}
}
/// let res: Result<Vec<u32>, &'static str> = v.iter().map(|x: &u32|
/// x.checked_add(1).ok_or("Overflow!")
/// ).collect();
- /// assert!(res == Ok(vec![2, 3]));
+ /// assert_eq!(res, Ok(vec![2, 3]));
/// ```
#[inline]
fn from_iter<I: IntoIterator<Item=Result<A, E>>>(iter: I) -> Result<V, E> {
// Formatting integers should select the right implementation based off
// the type of the argument. Also, hex/octal/binary should be defined
// for integers, but they shouldn't emit the negative sign.
- assert!(format!("{}", 1isize) == "1");
- assert!(format!("{}", 1i8) == "1");
- assert!(format!("{}", 1i16) == "1");
- assert!(format!("{}", 1i32) == "1");
- assert!(format!("{}", 1i64) == "1");
- assert!(format!("{}", -1isize) == "-1");
- assert!(format!("{}", -1i8) == "-1");
- assert!(format!("{}", -1i16) == "-1");
- assert!(format!("{}", -1i32) == "-1");
- assert!(format!("{}", -1i64) == "-1");
- assert!(format!("{:?}", 1isize) == "1");
- assert!(format!("{:?}", 1i8) == "1");
- assert!(format!("{:?}", 1i16) == "1");
- assert!(format!("{:?}", 1i32) == "1");
- assert!(format!("{:?}", 1i64) == "1");
- assert!(format!("{:b}", 1isize) == "1");
- assert!(format!("{:b}", 1i8) == "1");
- assert!(format!("{:b}", 1i16) == "1");
- assert!(format!("{:b}", 1i32) == "1");
- assert!(format!("{:b}", 1i64) == "1");
- assert!(format!("{:x}", 1isize) == "1");
- assert!(format!("{:x}", 1i8) == "1");
- assert!(format!("{:x}", 1i16) == "1");
- assert!(format!("{:x}", 1i32) == "1");
- assert!(format!("{:x}", 1i64) == "1");
- assert!(format!("{:X}", 1isize) == "1");
- assert!(format!("{:X}", 1i8) == "1");
- assert!(format!("{:X}", 1i16) == "1");
- assert!(format!("{:X}", 1i32) == "1");
- assert!(format!("{:X}", 1i64) == "1");
- assert!(format!("{:o}", 1isize) == "1");
- assert!(format!("{:o}", 1i8) == "1");
- assert!(format!("{:o}", 1i16) == "1");
- assert!(format!("{:o}", 1i32) == "1");
- assert!(format!("{:o}", 1i64) == "1");
+ assert_eq!(format!("{}", 1isize), "1");
+ assert_eq!(format!("{}", 1i8), "1");
+ assert_eq!(format!("{}", 1i16), "1");
+ assert_eq!(format!("{}", 1i32), "1");
+ assert_eq!(format!("{}", 1i64), "1");
+ assert_eq!(format!("{}", -1isize), "-1");
+ assert_eq!(format!("{}", -1i8), "-1");
+ assert_eq!(format!("{}", -1i16), "-1");
+ assert_eq!(format!("{}", -1i32), "-1");
+ assert_eq!(format!("{}", -1i64), "-1");
+ assert_eq!(format!("{:?}", 1isize), "1");
+ assert_eq!(format!("{:?}", 1i8), "1");
+ assert_eq!(format!("{:?}", 1i16), "1");
+ assert_eq!(format!("{:?}", 1i32), "1");
+ assert_eq!(format!("{:?}", 1i64), "1");
+ assert_eq!(format!("{:b}", 1isize), "1");
+ assert_eq!(format!("{:b}", 1i8), "1");
+ assert_eq!(format!("{:b}", 1i16), "1");
+ assert_eq!(format!("{:b}", 1i32), "1");
+ assert_eq!(format!("{:b}", 1i64), "1");
+ assert_eq!(format!("{:x}", 1isize), "1");
+ assert_eq!(format!("{:x}", 1i8), "1");
+ assert_eq!(format!("{:x}", 1i16), "1");
+ assert_eq!(format!("{:x}", 1i32), "1");
+ assert_eq!(format!("{:x}", 1i64), "1");
+ assert_eq!(format!("{:X}", 1isize), "1");
+ assert_eq!(format!("{:X}", 1i8), "1");
+ assert_eq!(format!("{:X}", 1i16), "1");
+ assert_eq!(format!("{:X}", 1i32), "1");
+ assert_eq!(format!("{:X}", 1i64), "1");
+ assert_eq!(format!("{:o}", 1isize), "1");
+ assert_eq!(format!("{:o}", 1i8), "1");
+ assert_eq!(format!("{:o}", 1i16), "1");
+ assert_eq!(format!("{:o}", 1i32), "1");
+ assert_eq!(format!("{:o}", 1i64), "1");
- assert!(format!("{}", 1usize) == "1");
- assert!(format!("{}", 1u8) == "1");
- assert!(format!("{}", 1u16) == "1");
- assert!(format!("{}", 1u32) == "1");
- assert!(format!("{}", 1u64) == "1");
- assert!(format!("{:?}", 1usize) == "1");
- assert!(format!("{:?}", 1u8) == "1");
- assert!(format!("{:?}", 1u16) == "1");
- assert!(format!("{:?}", 1u32) == "1");
- assert!(format!("{:?}", 1u64) == "1");
- assert!(format!("{:b}", 1usize) == "1");
- assert!(format!("{:b}", 1u8) == "1");
- assert!(format!("{:b}", 1u16) == "1");
- assert!(format!("{:b}", 1u32) == "1");
- assert!(format!("{:b}", 1u64) == "1");
- assert!(format!("{:x}", 1usize) == "1");
- assert!(format!("{:x}", 1u8) == "1");
- assert!(format!("{:x}", 1u16) == "1");
- assert!(format!("{:x}", 1u32) == "1");
- assert!(format!("{:x}", 1u64) == "1");
- assert!(format!("{:X}", 1usize) == "1");
- assert!(format!("{:X}", 1u8) == "1");
- assert!(format!("{:X}", 1u16) == "1");
- assert!(format!("{:X}", 1u32) == "1");
- assert!(format!("{:X}", 1u64) == "1");
- assert!(format!("{:o}", 1usize) == "1");
- assert!(format!("{:o}", 1u8) == "1");
- assert!(format!("{:o}", 1u16) == "1");
- assert!(format!("{:o}", 1u32) == "1");
- assert!(format!("{:o}", 1u64) == "1");
+ assert_eq!(format!("{}", 1usize), "1");
+ assert_eq!(format!("{}", 1u8), "1");
+ assert_eq!(format!("{}", 1u16), "1");
+ assert_eq!(format!("{}", 1u32), "1");
+ assert_eq!(format!("{}", 1u64), "1");
+ assert_eq!(format!("{:?}", 1usize), "1");
+ assert_eq!(format!("{:?}", 1u8), "1");
+ assert_eq!(format!("{:?}", 1u16), "1");
+ assert_eq!(format!("{:?}", 1u32), "1");
+ assert_eq!(format!("{:?}", 1u64), "1");
+ assert_eq!(format!("{:b}", 1usize), "1");
+ assert_eq!(format!("{:b}", 1u8), "1");
+ assert_eq!(format!("{:b}", 1u16), "1");
+ assert_eq!(format!("{:b}", 1u32), "1");
+ assert_eq!(format!("{:b}", 1u64), "1");
+ assert_eq!(format!("{:x}", 1usize), "1");
+ assert_eq!(format!("{:x}", 1u8), "1");
+ assert_eq!(format!("{:x}", 1u16), "1");
+ assert_eq!(format!("{:x}", 1u32), "1");
+ assert_eq!(format!("{:x}", 1u64), "1");
+ assert_eq!(format!("{:X}", 1usize), "1");
+ assert_eq!(format!("{:X}", 1u8), "1");
+ assert_eq!(format!("{:X}", 1u16), "1");
+ assert_eq!(format!("{:X}", 1u32), "1");
+ assert_eq!(format!("{:X}", 1u64), "1");
+ assert_eq!(format!("{:o}", 1usize), "1");
+ assert_eq!(format!("{:o}", 1u8), "1");
+ assert_eq!(format!("{:o}", 1u16), "1");
+ assert_eq!(format!("{:o}", 1u32), "1");
+ assert_eq!(format!("{:o}", 1u64), "1");
// Test a larger number
- assert!(format!("{:b}", 55) == "110111");
- assert!(format!("{:o}", 55) == "67");
- assert!(format!("{}", 55) == "55");
- assert!(format!("{:x}", 55) == "37");
- assert!(format!("{:X}", 55) == "37");
+ assert_eq!(format!("{:b}", 55), "110111");
+ assert_eq!(format!("{:o}", 55), "67");
+ assert_eq!(format!("{}", 55), "55");
+ assert_eq!(format!("{:x}", 55), "37");
+ assert_eq!(format!("{:X}", 55), "37");
}
#[test]
fn test_format_int_zero() {
- assert!(format!("{}", 0) == "0");
- assert!(format!("{:?}", 0) == "0");
- assert!(format!("{:b}", 0) == "0");
- assert!(format!("{:o}", 0) == "0");
- assert!(format!("{:x}", 0) == "0");
- assert!(format!("{:X}", 0) == "0");
+ assert_eq!(format!("{}", 0), "0");
+ assert_eq!(format!("{:?}", 0), "0");
+ assert_eq!(format!("{:b}", 0), "0");
+ assert_eq!(format!("{:o}", 0), "0");
+ assert_eq!(format!("{:x}", 0), "0");
+ assert_eq!(format!("{:X}", 0), "0");
- assert!(format!("{}", 0u32) == "0");
- assert!(format!("{:?}", 0u32) == "0");
- assert!(format!("{:b}", 0u32) == "0");
- assert!(format!("{:o}", 0u32) == "0");
- assert!(format!("{:x}", 0u32) == "0");
- assert!(format!("{:X}", 0u32) == "0");
+ assert_eq!(format!("{}", 0u32), "0");
+ assert_eq!(format!("{:?}", 0u32), "0");
+ assert_eq!(format!("{:b}", 0u32), "0");
+ assert_eq!(format!("{:o}", 0u32), "0");
+ assert_eq!(format!("{:x}", 0u32), "0");
+ assert_eq!(format!("{:X}", 0u32), "0");
}
#[test]
fn test_format_int_flags() {
- assert!(format!("{:3}", 1) == " 1");
- assert!(format!("{:>3}", 1) == " 1");
- assert!(format!("{:>+3}", 1) == " +1");
- assert!(format!("{:<3}", 1) == "1 ");
- assert!(format!("{:#}", 1) == "1");
- assert!(format!("{:#x}", 10) == "0xa");
- assert!(format!("{:#X}", 10) == "0xA");
- assert!(format!("{:#5x}", 10) == " 0xa");
- assert!(format!("{:#o}", 10) == "0o12");
- assert!(format!("{:08x}", 10) == "0000000a");
- assert!(format!("{:8x}", 10) == " a");
- assert!(format!("{:<8x}", 10) == "a ");
- assert!(format!("{:>8x}", 10) == " a");
- assert!(format!("{:#08x}", 10) == "0x00000a");
- assert!(format!("{:08}", -10) == "-0000010");
- assert!(format!("{:x}", !0u8) == "ff");
- assert!(format!("{:X}", !0u8) == "FF");
- assert!(format!("{:b}", !0u8) == "11111111");
- assert!(format!("{:o}", !0u8) == "377");
- assert!(format!("{:#x}", !0u8) == "0xff");
- assert!(format!("{:#X}", !0u8) == "0xFF");
- assert!(format!("{:#b}", !0u8) == "0b11111111");
- assert!(format!("{:#o}", !0u8) == "0o377");
+ assert_eq!(format!("{:3}", 1), " 1");
+ assert_eq!(format!("{:>3}", 1), " 1");
+ assert_eq!(format!("{:>+3}", 1), " +1");
+ assert_eq!(format!("{:<3}", 1), "1 ");
+ assert_eq!(format!("{:#}", 1), "1");
+ assert_eq!(format!("{:#x}", 10), "0xa");
+ assert_eq!(format!("{:#X}", 10), "0xA");
+ assert_eq!(format!("{:#5x}", 10), " 0xa");
+ assert_eq!(format!("{:#o}", 10), "0o12");
+ assert_eq!(format!("{:08x}", 10), "0000000a");
+ assert_eq!(format!("{:8x}", 10), " a");
+ assert_eq!(format!("{:<8x}", 10), "a ");
+ assert_eq!(format!("{:>8x}", 10), " a");
+ assert_eq!(format!("{:#08x}", 10), "0x00000a");
+ assert_eq!(format!("{:08}", -10), "-0000010");
+ assert_eq!(format!("{:x}", !0u8), "ff");
+ assert_eq!(format!("{:X}", !0u8), "FF");
+ assert_eq!(format!("{:b}", !0u8), "11111111");
+ assert_eq!(format!("{:o}", !0u8), "377");
+ assert_eq!(format!("{:#x}", !0u8), "0xff");
+ assert_eq!(format!("{:#X}", !0u8), "0xFF");
+ assert_eq!(format!("{:#b}", !0u8), "0b11111111");
+ assert_eq!(format!("{:#o}", !0u8), "0o377");
}
#[test]
fn test_format_int_sign_padding() {
- assert!(format!("{:+5}", 1) == " +1");
- assert!(format!("{:+5}", -1) == " -1");
- assert!(format!("{:05}", 1) == "00001");
- assert!(format!("{:05}", -1) == "-0001");
- assert!(format!("{:+05}", 1) == "+0001");
- assert!(format!("{:+05}", -1) == "-0001");
+ assert_eq!(format!("{:+5}", 1), " +1");
+ assert_eq!(format!("{:+5}", -1), " -1");
+ assert_eq!(format!("{:05}", 1), "00001");
+ assert_eq!(format!("{:05}", -1), "-0001");
+ assert_eq!(format!("{:+05}", 1), "+0001");
+ assert_eq!(format!("{:+05}", -1), "-0001");
}
#[test]
fn test_format_int_twos_complement() {
- use core::{i8, i16, i32, i64};
- assert!(format!("{}", i8::MIN) == "-128");
- assert!(format!("{}", i16::MIN) == "-32768");
- assert!(format!("{}", i32::MIN) == "-2147483648");
- assert!(format!("{}", i64::MIN) == "-9223372036854775808");
+ use core::{i16, i32, i64, i8};
+ assert_eq!(format!("{}", i8::MIN), "-128");
+ assert_eq!(format!("{}", i16::MIN), "-32768");
+ assert_eq!(format!("{}", i32::MIN), "-2147483648");
+ assert_eq!(format!("{}", i64::MIN), "-9223372036854775808");
}
#[test]
fn test_format_debug_hex() {
- assert!(format!("{:02x?}", b"Foo\0") == "[46, 6f, 6f, 00]");
- assert!(format!("{:02X?}", b"Foo\0") == "[46, 6F, 6F, 00]");
+ assert_eq!(format!("{:02x?}", b"Foo\0"), "[46, 6f, 6f, 00]");
+ assert_eq!(format!("{:02X?}", b"Foo\0"), "[46, 6F, 6F, 00]");
}
"ambiguous associated items"
}
+declare_lint! {
+ pub NESTED_IMPL_TRAIT,
+ Warn,
+ "nested occurrence of `impl Trait` type"
+}
+
/// Does nothing as a lint pass, but registers some `Lint`s
/// that are used by other parts of the compiler.
#[derive(Copy, Clone)]
parser::ILL_FORMED_ATTRIBUTE_INPUT,
DEPRECATED_IN_FUTURE,
AMBIGUOUS_ASSOCIATED_ITEMS,
+ NESTED_IMPL_TRAIT,
)
}
}
ElidedLifetimesInPaths(usize, Span, bool, Span, String),
UnknownCrateTypes(Span, String, String),
UnusedImports(String, Vec<(Span, String)>),
+ NestedImplTrait { outer_impl_trait_span: Span, inner_impl_trait_span: Span },
}
impl BuiltinLintDiagnostics {
);
}
}
+ BuiltinLintDiagnostics::NestedImplTrait {
+ outer_impl_trait_span, inner_impl_trait_span
+ } => {
+ db.span_label(outer_impl_trait_span, "outer `impl Trait`");
+ db.span_label(inner_impl_trait_span, "nested `impl Trait` here");
+ }
}
}
}
}
}
- // This method exercises the `in_scope_traits_map` query for all possible
- // values so that we have their fingerprints available in the DepGraph.
- // This is only required as long as we still use the old dependency tracking
- // which needs to have the fingerprints of all input nodes beforehand.
- pub fn precompute_in_scope_traits_hashes(self) {
- for &def_index in self.trait_map.keys() {
- self.in_scope_traits_map(def_index);
- }
- }
-
pub fn serialize_query_result_cache<E>(self,
encoder: &mut E)
-> Result<(), E::Error>
//! # Debug Info Module
//!
//! This module serves the purpose of generating debug symbols. We use LLVM's
-//! [source level debugging](http://!llvm.org/docs/SourceLevelDebugging.html)
+//! [source level debugging](https://llvm.org/docs/SourceLevelDebugging.html)
//! features for generating the debug information. The general principle is
//! this:
//!
//! Given the right metadata in the LLVM IR, the LLVM code generator is able to
//! create DWARF debug symbols for the given code. The
-//! [metadata](http://!llvm.org/docs/LangRef.html#metadata-type) is structured
+//! [metadata](https://llvm.org/docs/LangRef.html#metadata-type) is structured
//! much like DWARF *debugging information entries* (DIE), representing type
//! information such as datatype layout, function signatures, block layout,
//! variable location and scope information, etc. It is the purpose of this
//!
//! As the exact format of metadata trees may change between different LLVM
//! versions, we now use LLVM
-//! [DIBuilder](http://!llvm.org/docs/doxygen/html/classllvm_1_1DIBuilder.html)
+//! [DIBuilder](https://llvm.org/docs/doxygen/html/classllvm_1_1DIBuilder.html)
//! to create metadata where possible. This will hopefully ease the adaption of
//! this module to future LLVM versions.
//!
[dependencies]
graphviz = { path = "../libgraphviz" }
log = "0.4"
-rand = "0.5"
+rand = "0.6"
rustc = { path = "../librustc" }
rustc_data_structures = { path = "../librustc_data_structures" }
serialize = { path = "../libserialize" }
}
tcx.allocate_metadata_dep_nodes();
- tcx.precompute_in_scope_traits_hashes();
}
type WorkProductMap = FxHashMap<WorkProductId, WorkProduct>;
log = "0.4"
rustc-rayon = "0.1.1"
smallvec = { version = "0.6.7", features = ["union", "may_dangle"] }
-scoped-tls = { version = "0.1.1", features = ["nightly"] }
+scoped-tls = "1.0"
syntax = { path = "../libsyntax" }
syntax_ext = { path = "../libsyntax_ext" }
syntax_pos = { path = "../libsyntax_pos" }
reference: "issue #57593 <https://github.com/rust-lang/rust/issues/57593>",
edition: None,
},
+ FutureIncompatibleInfo {
+ id: LintId::of(NESTED_IMPL_TRAIT),
+ reference: "issue #59014 <https://github.com/rust-lang/rust/issues/59014>",
+ edition: None,
+ },
]);
// Register renamed and removed lints.
use rustc::ty::layout::{Integer, IntegerExt, Size};
use syntax::attr::{SignedInt, UnsignedInt};
use rustc::hir::RangeEnd;
+use rustc::mir::interpret::truncate;
use std::mem;
ty::Int(ity) => {
// FIXME(49937): refactor these bit manipulations into interpret.
let size = Integer::from_attr(&tcx, SignedInt(ity)).size();
- let max = !0u128 >> (128 - size.bits());
+ let max = truncate(u128::max_value(), size);
let bias = 1u128 << (size.bits() - 1);
(Some((0, max, size)), bias)
}
ty::Uint(uty) => {
// FIXME(49937): refactor these bit manipulations into interpret.
let size = Integer::from_attr(&tcx, UnsignedInt(uty)).size();
- let max = !0u128 >> (128 - size.bits());
+ let max = truncate(u128::max_value(), size);
(Some((0, max, size)), 0)
}
_ => (None, 0),
use std::mem;
use syntax::print::pprust;
use rustc::lint;
+use rustc::lint::builtin::{BuiltinLintDiagnostics, NESTED_IMPL_TRAIT};
use rustc::session::Session;
use rustc_data_structures::fx::FxHashMap;
use syntax::ast::*;
use errors::Applicability;
use log::debug;
+#[derive(Copy, Clone, Debug)]
+struct OuterImplTrait {
+ span: Span,
+
+ /// rust-lang/rust#57979: a bug in original implementation caused
+ /// us to fail sometimes to record an outer `impl Trait`.
+ /// Therefore, in order to reliably issue a warning (rather than
+ /// an error) in the *precise* places where we are newly injecting
+ /// the diagnostic, we have to distinguish between the places
+ /// where the outer `impl Trait` has always been recorded, versus
+ /// the places where it has only recently started being recorded.
+ only_recorded_since_pull_request_57730: bool,
+}
+
+impl OuterImplTrait {
+ /// This controls whether we should downgrade the nested impl
+ /// trait diagnostic to a warning rather than an error, based on
+ /// whether the outer impl trait had been improperly skipped in
+ /// earlier implementations of the analysis on the stable
+ /// compiler.
+ fn should_warn_instead_of_error(&self) -> bool {
+ self.only_recorded_since_pull_request_57730
+ }
+}
+
struct AstValidator<'a> {
session: &'a Session,
has_proc_macro_decls: bool,
// Used to ban nested `impl Trait`, e.g., `impl Into<impl Debug>`.
// Nested `impl Trait` _is_ allowed in associated type position,
// e.g `impl Iterator<Item=impl Debug>`
- outer_impl_trait: Option<Span>,
+ outer_impl_trait: Option<OuterImplTrait>,
// Used to ban `impl Trait` in path projections like `<impl Iterator>::Item`
// or `Foo::Bar<impl Trait>`
is_impl_trait_banned: bool,
+
+ // rust-lang/rust#57979: the ban of nested `impl Trait` was buggy
+ // until PRs #57730 and #57981 landed: it would jump directly to
+ // walk_ty rather than visit_ty (or skip recurring entirely for
+ // impl trait in projections), and thus miss some cases. We track
+ // whether we should downgrade to a warning for short-term via
+ // these booleans.
+ warning_period_57979_didnt_record_next_impl_trait: bool,
+ warning_period_57979_impl_trait_in_proj: bool,
}
impl<'a> AstValidator<'a> {
+ fn with_impl_trait_in_proj_warning<T>(&mut self, v: bool, f: impl FnOnce(&mut Self) -> T) -> T {
+ let old = mem::replace(&mut self.warning_period_57979_impl_trait_in_proj, v);
+ let ret = f(self);
+ self.warning_period_57979_impl_trait_in_proj = old;
+ ret
+ }
+
fn with_banned_impl_trait(&mut self, f: impl FnOnce(&mut Self)) {
let old = mem::replace(&mut self.is_impl_trait_banned, true);
f(self);
self.is_impl_trait_banned = old;
}
- fn with_impl_trait(&mut self, outer_impl_trait: Option<Span>, f: impl FnOnce(&mut Self)) {
- let old = mem::replace(&mut self.outer_impl_trait, outer_impl_trait);
+ fn with_impl_trait(&mut self, outer: Option<OuterImplTrait>, f: impl FnOnce(&mut Self)) {
+ let old = mem::replace(&mut self.outer_impl_trait, outer);
f(self);
self.outer_impl_trait = old;
}
+ fn visit_assoc_type_binding_from_generic_args(&mut self, type_binding: &'a TypeBinding) {
+ // rust-lang/rust#57979: bug in old visit_generic_args called
+ // walk_ty rather than visit_ty, skipping outer `impl Trait`
+ // if it happened to occur at `type_binding.ty`
+ if let TyKind::ImplTrait(..) = type_binding.ty.node {
+ self.warning_period_57979_didnt_record_next_impl_trait = true;
+ }
+ self.visit_assoc_type_binding(type_binding);
+ }
+
+ fn visit_ty_from_generic_args(&mut self, ty: &'a Ty) {
+ // rust-lang/rust#57979: bug in old visit_generic_args called
+ // walk_ty rather than visit_ty, skippping outer `impl Trait`
+ // if it happened to occur at `ty`
+ if let TyKind::ImplTrait(..) = ty.node {
+ self.warning_period_57979_didnt_record_next_impl_trait = true;
+ }
+ self.visit_ty(ty);
+ }
+
+ fn outer_impl_trait(&mut self, span: Span) -> OuterImplTrait {
+ let only_recorded_since_pull_request_57730 =
+ self.warning_period_57979_didnt_record_next_impl_trait;
+
+ // (this flag is designed to be set to true and then only
+ // reach the construction point for the outer impl trait once,
+ // so its safe and easiest to unconditionally reset it to
+ // false)
+ self.warning_period_57979_didnt_record_next_impl_trait = false;
+
+ OuterImplTrait {
+ span, only_recorded_since_pull_request_57730,
+ }
+ }
+
// Mirrors visit::walk_ty, but tracks relevant state
fn walk_ty(&mut self, t: &'a Ty) {
match t.node {
TyKind::ImplTrait(..) => {
- self.with_impl_trait(Some(t.span), |this| visit::walk_ty(this, t))
+ let outer_impl_trait = self.outer_impl_trait(t.span);
+ self.with_impl_trait(Some(outer_impl_trait), |this| visit::walk_ty(this, t))
}
TyKind::Path(ref qself, ref path) => {
// We allow these:
}
TyKind::ImplTrait(_, ref bounds) => {
if self.is_impl_trait_banned {
- struct_span_err!(self.session, ty.span, E0667,
- "`impl Trait` is not allowed in path parameters").emit();
+ if self.warning_period_57979_impl_trait_in_proj {
+ self.session.buffer_lint(
+ NESTED_IMPL_TRAIT, ty.id, ty.span,
+ "`impl Trait` is not allowed in path parameters");
+ } else {
+ struct_span_err!(self.session, ty.span, E0667,
+ "`impl Trait` is not allowed in path parameters").emit();
+ }
}
if let Some(outer_impl_trait) = self.outer_impl_trait {
- struct_span_err!(self.session, ty.span, E0666,
- "nested `impl Trait` is not allowed")
- .span_label(outer_impl_trait, "outer `impl Trait`")
- .span_label(ty.span, "nested `impl Trait` here")
- .emit();
-
+ if outer_impl_trait.should_warn_instead_of_error() {
+ self.session.buffer_lint_with_diagnostic(
+ NESTED_IMPL_TRAIT, ty.id, ty.span,
+ "nested `impl Trait` is not allowed",
+ BuiltinLintDiagnostics::NestedImplTrait {
+ outer_impl_trait_span: outer_impl_trait.span,
+ inner_impl_trait_span: ty.span,
+ });
+ } else {
+ struct_span_err!(self.session, ty.span, E0666,
+ "nested `impl Trait` is not allowed")
+ .span_label(outer_impl_trait.span, "outer `impl Trait`")
+ .span_label(ty.span, "nested `impl Trait` here")
+ .emit();
+ }
}
+
if !bounds.iter()
.any(|b| if let GenericBound::Trait(..) = *b { true } else { false }) {
self.err_handler().span_err(ty.span, "at least one trait must be specified");
}
+
+ self.with_impl_trait_in_proj_warning(true, |this| this.walk_ty(ty));
+ return;
}
_ => {}
}
GenericArg::Const(..) => ParamKindOrd::Const,
}, arg.span(), None)
}), GenericPosition::Arg, generic_args.span());
+
// Type bindings such as `Item=impl Debug` in `Iterator<Item=Debug>`
// are allowed to contain nested `impl Trait`.
self.with_impl_trait(None, |this| {
- walk_list!(this, visit_assoc_type_binding, &data.bindings);
+ walk_list!(this, visit_assoc_type_binding_from_generic_args, &data.bindings);
});
}
GenericArgs::Parenthesized(ref data) => {
if let Some(ref type_) = data.output {
// `-> Foo` syntax is essentially an associated type binding,
// so it is also allowed to contain nested `impl Trait`.
- self.with_impl_trait(None, |this| this.visit_ty(type_));
+ self.with_impl_trait(None, |this| this.visit_ty_from_generic_args(type_));
}
}
}
has_global_allocator: false,
outer_impl_trait: None,
is_impl_trait_banned: false,
+ warning_period_57979_didnt_record_next_impl_trait: false,
+ warning_period_57979_impl_trait_in_proj: false,
};
visit::walk_crate(&mut validator, krate);
debug!("compare_const_impl(impl_trait_ref={:?})", impl_trait_ref);
tcx.infer_ctxt().enter(|infcx| {
- let param_env = ty::ParamEnv::empty();
+ let param_env = tcx.param_env(impl_c.def_id);
let inh = Inherited::new(infcx, impl_c.def_id);
let infcx = &inh.infcx;
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, 'b, T, S> BitOr<&'b HashSet<T, S>> for &'a HashSet<T, S>
+impl<T, S> BitOr<&HashSet<T, S>> for &HashSet<T, S>
where T: Eq + Hash + Clone,
S: BuildHasher + Default
{
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, 'b, T, S> BitAnd<&'b HashSet<T, S>> for &'a HashSet<T, S>
+impl<T, S> BitAnd<&HashSet<T, S>> for &HashSet<T, S>
where T: Eq + Hash + Clone,
S: BuildHasher + Default
{
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, 'b, T, S> BitXor<&'b HashSet<T, S>> for &'a HashSet<T, S>
+impl<T, S> BitXor<&HashSet<T, S>> for &HashSet<T, S>
where T: Eq + Hash + Clone,
S: BuildHasher + Default
{
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, 'b, T, S> Sub<&'b HashSet<T, S>> for &'a HashSet<T, S>
+impl<T, S> Sub<&HashSet<T, S>> for &HashSet<T, S>
where T: Eq + Hash + Clone,
S: BuildHasher + Default
{
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, 'b> From<&'b str> for Box<dyn Error + Send + Sync + 'a> {
+impl<'a> From<&str> for Box<dyn Error + Send + Sync + 'a> {
/// Converts a [`str`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
///
/// # Examples
/// assert!(
/// mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
/// ```
- fn from(err: &'b str) -> Box<dyn Error + Send + Sync + 'a> {
+ fn from(err: &str) -> Box<dyn Error + Send + Sync + 'a> {
From::from(String::from(err))
}
}
#[stable(feature = "string_box_error", since = "1.6.0")]
-impl<'a> From<&'a str> for Box<dyn Error> {
+impl From<&str> for Box<dyn Error> {
/// Converts a [`str`] into a box of dyn [`Error`].
///
/// # Examples
/// let a_boxed_error = Box::<Error>::from(a_str_error);
/// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
/// ```
- fn from(err: &'a str) -> Box<dyn Error> {
+ fn from(err: &str) -> Box<dyn Error> {
From::from(String::from(err))
}
}
}
#[stable(feature = "box_from_c_str", since = "1.17.0")]
-impl<'a> From<&'a CStr> for Box<CStr> {
- fn from(s: &'a CStr) -> Box<CStr> {
+impl From<&CStr> for Box<CStr> {
+ fn from(s: &CStr) -> Box<CStr> {
let boxed: Box<[u8]> = Box::from(s.to_bytes_with_nul());
unsafe { Box::from_raw(Box::into_raw(boxed) as *mut CStr) }
}
}
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
-impl<'a> From<&'a CStr> for Arc<CStr> {
+impl From<&CStr> for Arc<CStr> {
#[inline]
fn from(s: &CStr) -> Arc<CStr> {
let arc: Arc<[u8]> = Arc::from(s.to_bytes_with_nul());
}
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
-impl<'a> From<&'a CStr> for Rc<CStr> {
+impl From<&CStr> for Rc<CStr> {
#[inline]
fn from(s: &CStr) -> Rc<CStr> {
let rc: Rc<[u8]> = Rc::from(s.to_bytes_with_nul());
}
#[stable(feature = "cstring_asref", since = "1.7.0")]
-impl<'a> From<&'a CStr> for CString {
- fn from(s: &'a CStr) -> CString {
+impl From<&CStr> for CString {
+ fn from(s: &CStr) -> CString {
s.to_owned()
}
}
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T: ?Sized + AsRef<OsStr>> From<&'a T> for OsString {
- fn from(s: &'a T) -> OsString {
+impl<T: ?Sized + AsRef<OsStr>> From<&T> for OsString {
+ fn from(s: &T) -> OsString {
s.as_ref().to_os_string()
}
}
}
#[stable(feature = "os_str_str_ref_eq", since = "1.29.0")]
-impl<'a> PartialEq<&'a str> for OsString {
- fn eq(&self, other: &&'a str) -> bool {
+impl PartialEq<&str> for OsString {
+ fn eq(&self, other: &&str) -> bool {
**self == **other
}
}
}
#[stable(feature = "box_from_os_str", since = "1.17.0")]
-impl<'a> From<&'a OsStr> for Box<OsStr> {
- fn from(s: &'a OsStr) -> Box<OsStr> {
+impl From<&OsStr> for Box<OsStr> {
+ fn from(s: &OsStr) -> Box<OsStr> {
let rw = Box::into_raw(s.inner.into_box()) as *mut OsStr;
unsafe { Box::from_raw(rw) }
}
}
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
-impl<'a> From<&'a OsStr> for Arc<OsStr> {
+impl From<&OsStr> for Arc<OsStr> {
#[inline]
fn from(s: &OsStr) -> Arc<OsStr> {
let arc = s.inner.into_arc();
}
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
-impl<'a> From<&'a OsStr> for Rc<OsStr> {
+impl From<&OsStr> for Rc<OsStr> {
#[inline]
fn from(s: &OsStr) -> Rc<OsStr> {
let rc = s.inner.into_rc();
}
#[stable(feature = "box_from_path", since = "1.17.0")]
-impl<'a> From<&'a Path> for Box<Path> {
- fn from(path: &'a Path) -> Box<Path> {
+impl From<&Path> for Box<Path> {
+ fn from(path: &Path) -> Box<Path> {
let boxed: Box<OsStr> = path.inner.into();
let rw = Box::into_raw(boxed) as *mut Path;
unsafe { Box::from_raw(rw) }
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T: ?Sized + AsRef<OsStr>> From<&'a T> for PathBuf {
- fn from(s: &'a T) -> PathBuf {
+impl<T: ?Sized + AsRef<OsStr>> From<&T> for PathBuf {
+ fn from(s: &T) -> PathBuf {
PathBuf::from(s.as_ref().to_os_string())
}
}
}
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
-impl<'a> From<&'a Path> for Arc<Path> {
+impl From<&Path> for Arc<Path> {
/// Converts a Path into a Rc by copying the Path data into a new Rc buffer.
#[inline]
fn from(s: &Path) -> Arc<Path> {
}
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
-impl<'a> From<&'a Path> for Rc<Path> {
+impl From<&Path> for Rc<Path> {
/// Converts a Path into a Rc by copying the Path data into a new Rc buffer.
#[inline]
fn from(s: &Path) -> Rc<Path> {
}
}
-impl<'a> TryFrom<&'a str> for LookupHost {
+impl TryFrom<&str> for LookupHost {
type Error = io::Error;
- fn try_from(_v: &'a str) -> io::Result<LookupHost> {
+ fn try_from(_v: &str) -> io::Result<LookupHost> {
unsupported()
}
}
}
}
-impl<'a> TryFrom<&'a str> for LookupHost {
+impl TryFrom<&str> for LookupHost {
type Error = io::Error;
fn try_from(s: &str) -> io::Result<LookupHost> {
}
}
-impl<'a> TryFrom<&'a str> for LookupHost {
+impl TryFrom<&str> for LookupHost {
type Error = io::Error;
- fn try_from(v: &'a str) -> io::Result<LookupHost> {
+ fn try_from(v: &str) -> io::Result<LookupHost> {
LookupHost::new(v.to_owned())
}
}
unsafe impl Send for LookupHost {}
- impl<'a> TryFrom<&'a str> for LookupHost {
+ impl TryFrom<&str> for LookupHost {
type Error = io::Error;
- fn try_from(_v: &'a str) -> io::Result<LookupHost> {
+ fn try_from(_v: &str) -> io::Result<LookupHost> {
unimpl!();
}
}
}
}
-impl<'a> TryFrom<&'a str> for LookupHost {
+impl TryFrom<&str> for LookupHost {
type Error = io::Error;
- fn try_from(_v: &'a str) -> io::Result<LookupHost> {
+ fn try_from(_v: &str) -> io::Result<LookupHost> {
unsupported()
}
}
}
}
-impl<'a> TryFrom<&'a str> for LookupHost {
+impl TryFrom<&str> for LookupHost {
type Error = io::Error;
fn try_from(s: &str) -> io::Result<LookupHost> {
// If the character is an ident start not followed by another single
// quote, then this is a lifetime name:
- if ident_start(Some(c2)) && !self.ch_is('\'') {
+ if (ident_start(Some(c2)) || c2.is_numeric()) && !self.ch_is('\'') {
while ident_continue(self.ch) {
self.bump();
}
// lifetimes shouldn't end with a single quote
// if we find one, then this is an invalid character literal
if self.ch_is('\'') {
- self.err_span_(start_with_quote, self.next_pos,
- "character literal may only contain one codepoint");
+ self.err_span_(
+ start_with_quote,
+ self.next_pos,
+ "character literal may only contain one codepoint");
self.bump();
return Ok(token::Literal(token::Err(Symbol::intern("??")), None))
self.mk_ident(&format!("'{}", lifetime_name))
});
+ if c2.is_numeric() {
+ // this is a recovered lifetime written `'1`, error but accept it
+ self.err_span_(
+ start_with_quote,
+ self.pos,
+ "lifetimes cannot start with a number",
+ );
+ }
+
return Ok(token::Lifetime(ident));
}
res
}
+/// Determine whether `c` is a valid start for an ident.
fn ident_start(c: Option<char>) -> bool {
let c = match c {
Some(c) => c,
--- /dev/null
+const QUERY = '&';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std', 'name': 'reference' },
+ ],
+};
--- /dev/null
+// ignore-order
+
+const QUERY = '+';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std::ops', 'name': 'AddAssign' },
+ { 'path': 'std::ops', 'name': 'Add' },
+ ],
+};
--- /dev/null
+const QUERY = '!';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std', 'name': 'never' },
+ ],
+};
--- /dev/null
+// ignore-order
+
+const QUERY = '[';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std', 'name': 'slice' },
+ { 'path': 'std::ops', 'name': 'IndexMut' },
+ { 'path': 'std::ops', 'name': 'Index' },
+ ],
+};
--- /dev/null
+const QUERY = 'String';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std::string', 'name': 'String' },
+ { 'path': 'std::ffi', 'name': 'CString' },
+ { 'path': 'std::ffi', 'name': 'OsString' },
+ ],
+ 'in_args': [
+ { 'path': 'std::str', 'name': 'eq' },
+ ],
+ 'returned': [
+ { 'path': 'std::string::String', 'name': 'add' },
+ ],
+};
--- /dev/null
+// ignore-order
+
+const QUERY = 'is_nan';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std::f32', 'name': 'is_nan' },
+ { 'path': 'std::f64', 'name': 'is_nan' },
+ { 'path': 'std::option::Option', 'name': 'is_none' },
+ ],
+};
--- /dev/null
+const QUERY = 'enum:Option';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std::option', 'name': 'Option' },
+ ],
+};
--- /dev/null
+// exact-check
+
+const QUERY = 'hashmap';
+const FILTER_CRATE = 'core';
+
+const EXPECTED = {
+ 'others': [
+ ],
+};
--- /dev/null
+const QUERY = 'fn:forget';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std::mem', 'name': 'forget' },
+ { 'path': 'std::fmt', 'name': 'format' },
+ ],
+};
--- /dev/null
+const QUERY = 'from_u';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std::char', 'name': 'from_u32' },
+ { 'path': 'std::str', 'name': 'from_utf8' },
+ { 'path': 'std::string::String', 'name': 'from_utf8' },
+ ],
+};
--- /dev/null
+// ignore-order
+
+const QUERY = 'fn';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std', 'name': 'fn', ty: 15 }, // 15 is for primitive types
+ { 'path': 'std', 'name': 'fn', ty: 21 }, // 21 is for keywords
+ ],
+};
--- /dev/null
+// ignore-order
+
+const QUERY = 'panic';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std', 'name': 'panic', ty: 14 }, // 15 is for macros
+ { 'path': 'std', 'name': 'panic', ty: 0 }, // 0 is for modules
+ ],
+};
--- /dev/null
+const QUERY = 'macro:print';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std', 'name': 'print' },
+ { 'path': 'std', 'name': 'eprint' },
+ { 'path': 'std', 'name': 'println' },
+ { 'path': 'std', 'name': 'eprintln' },
+ ],
+};
--- /dev/null
+const QUERY = 'str,u8';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std', 'name': 'str' },
+ { 'path': 'std', 'name': 'u8' },
+ { 'path': 'std::ffi', 'name': 'CStr' },
+ ],
+};
--- /dev/null
+const QUERY = '!';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std', 'name': 'never' },
+ ],
+};
--- /dev/null
+const QUERY = '"error"';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std', 'name': 'error' },
+ { 'path': 'std::fmt', 'name': 'Error' },
+ { 'path': 'std::io', 'name': 'Error' },
+ ],
+ 'in_args': [],
+ 'returned': [
+ { 'path': 'std::fmt::LowerExp', 'name': 'fmt' },
+ ],
+};
--- /dev/null
+// should-fail
+
+const QUERY = 'fn';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std', 'name': 'fn', ty: 14 },
+ ],
+};
--- /dev/null
+const QUERY = 'String::from_ut';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std::string::String', 'name': 'from_utf8' },
+ { 'path': 'std::string::String', 'name': 'from_utf8' },
+ { 'path': 'std::string::String', 'name': 'from_utf8_lossy' },
+ { 'path': 'std::string::String', 'name': 'from_utf16_lossy' },
+ { 'path': 'std::string::String', 'name': 'from_utf8_unchecked' },
+ ],
+};
--- /dev/null
+const QUERY = 'struct:Vec';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std::vec', 'name': 'Vec' },
+ { 'path': 'std::collections', 'name': 'VecDeque' },
+ ],
+};
--- /dev/null
+const QUERY = 'Vec::new';
+
+const EXPECTED = {
+ 'others': [
+ { 'path': 'std::vec::Vec', 'name': 'new' },
+ { 'path': 'std::vec::Vec', 'name': 'ne' },
+ ],
+};
+++ /dev/null
-const QUERY = '&';
-
-const EXPECTED = {
- 'others': [
- { 'path': 'std', 'name': 'reference' },
- ],
-};
+++ /dev/null
-// ignore-order
-
-const QUERY = '+';
-
-const EXPECTED = {
- 'others': [
- { 'path': 'std::ops', 'name': 'AddAssign' },
- { 'path': 'std::ops', 'name': 'Add' },
- ],
-};
+++ /dev/null
-const QUERY = '!';
-
-const EXPECTED = {
- 'others': [
- { 'path': 'std', 'name': 'never' },
- ],
-};
+++ /dev/null
-// ignore-order
-
-const QUERY = '[';
-
-const EXPECTED = {
- 'others': [
- { 'path': 'std', 'name': 'slice' },
- { 'path': 'std::ops', 'name': 'IndexMut' },
- { 'path': 'std::ops', 'name': 'Index' },
- ],
-};
-const QUERY = 'String';
+const QUERY = 'Fo';
const EXPECTED = {
'others': [
- { 'path': 'std::string', 'name': 'String' },
- { 'path': 'std::ffi', 'name': 'CString' },
- { 'path': 'std::ffi', 'name': 'OsString' },
- ],
- 'in_args': [
- { 'path': 'std::str', 'name': 'eq' },
- ],
- 'returned': [
- { 'path': 'std::string::String', 'name': 'add' },
+ { 'path': 'basic', 'name': 'Foo' },
],
};
--- /dev/null
+/// Foo
+pub struct Foo;
+++ /dev/null
-// ignore-order
-
-const QUERY = 'is_nan';
-
-const EXPECTED = {
- 'others': [
- { 'path': 'std::f32', 'name': 'is_nan' },
- { 'path': 'std::f64', 'name': 'is_nan' },
- { 'path': 'std::option::Option', 'name': 'is_none' },
- ],
-};
+++ /dev/null
-const QUERY = 'enum:Option';
-
-const EXPECTED = {
- 'others': [
- { 'path': 'std::option', 'name': 'Option' },
- ],
-};
+++ /dev/null
-// exact-check
-
-const QUERY = 'hashmap';
-const FILTER_CRATE = 'core';
-
-const EXPECTED = {
- 'others': [
- ],
-};
+++ /dev/null
-const QUERY = 'fn:forget';
-
-const EXPECTED = {
- 'others': [
- { 'path': 'std::mem', 'name': 'forget' },
- { 'path': 'std::fmt', 'name': 'format' },
- ],
-};
+++ /dev/null
-const QUERY = 'from_u';
-
-const EXPECTED = {
- 'others': [
- { 'path': 'std::char', 'name': 'from_u32' },
- { 'path': 'std::str', 'name': 'from_utf8' },
- { 'path': 'std::string::String', 'name': 'from_utf8' },
- ],
-};
+++ /dev/null
-// ignore-order
-
-const QUERY = 'fn';
-
-const EXPECTED = {
- 'others': [
- { 'path': 'std', 'name': 'fn', ty: 15 }, // 15 is for primitive types
- { 'path': 'std', 'name': 'fn', ty: 21 }, // 21 is for keywords
- ],
-};
+++ /dev/null
-// ignore-order
-
-const QUERY = 'panic';
-
-const EXPECTED = {
- 'others': [
- { 'path': 'std', 'name': 'panic', ty: 14 }, // 15 is for macros
- { 'path': 'std', 'name': 'panic', ty: 0 }, // 0 is for modules
- ],
-};
+++ /dev/null
-const QUERY = 'macro:print';
-
-const EXPECTED = {
- 'others': [
- { 'path': 'std', 'name': 'print' },
- { 'path': 'std', 'name': 'eprint' },
- { 'path': 'std', 'name': 'println' },
- { 'path': 'std', 'name': 'eprintln' },
- ],
-};
+++ /dev/null
-const QUERY = 'str,u8';
-
-const EXPECTED = {
- 'others': [
- { 'path': 'std', 'name': 'str' },
- { 'path': 'std', 'name': 'u8' },
- { 'path': 'std::ffi', 'name': 'CStr' },
- ],
-};
+++ /dev/null
-const QUERY = '!';
-
-const EXPECTED = {
- 'others': [
- { 'path': 'std', 'name': 'never' },
- ],
-};
+++ /dev/null
-const QUERY = '"error"';
-
-const EXPECTED = {
- 'others': [
- { 'path': 'std', 'name': 'error' },
- { 'path': 'std::fmt', 'name': 'Error' },
- { 'path': 'std::io', 'name': 'Error' },
- ],
- 'in_args': [],
- 'returned': [
- { 'path': 'std::fmt::LowerExp', 'name': 'fmt' },
- ],
-};
+++ /dev/null
-// should-fail
-
-const QUERY = 'fn';
-
-const EXPECTED = {
- 'others': [
- { 'path': 'std', 'name': 'fn', ty: 14 },
- ],
-};
+++ /dev/null
-const QUERY = 'String::from_ut';
-
-const EXPECTED = {
- 'others': [
- { 'path': 'std::string::String', 'name': 'from_utf8' },
- { 'path': 'std::string::String', 'name': 'from_utf8' },
- { 'path': 'std::string::String', 'name': 'from_utf8_lossy' },
- { 'path': 'std::string::String', 'name': 'from_utf16_lossy' },
- { 'path': 'std::string::String', 'name': 'from_utf8_unchecked' },
- ],
-};
+++ /dev/null
-const QUERY = 'struct:Vec';
-
-const EXPECTED = {
- 'others': [
- { 'path': 'std::vec', 'name': 'Vec' },
- { 'path': 'std::collections', 'name': 'VecDeque' },
- ],
-};
+++ /dev/null
-const QUERY = 'Vec::new';
-
-const EXPECTED = {
- 'others': [
- { 'path': 'std::vec::Vec', 'name': 'new' },
- { 'path': 'std::vec::Vec', 'name': 'ne' },
- ],
-};
impl<T: Foo> Bar for T {
const FROM: &'static str = "foo";
- //~^ ERROR the trait bound `T: Foo` is not satisfied [E0277]
+ //~^ ERROR implemented const `FROM` has an incompatible type for trait [E0326]
}
fn main() {}
-error[E0277]: the trait bound `T: Foo` is not satisfied
- --> $DIR/associated-const-generic-obligations.rs:14:5
+error[E0326]: implemented const `FROM` has an incompatible type for trait
+ --> $DIR/associated-const-generic-obligations.rs:14:17
|
+LL | const FROM: Self::Out;
+ | --------- type in trait
+...
LL | const FROM: &'static str = "foo";
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `T`
+ | ^^^^^^^^^^^^ expected associated type, found reference
|
- = help: consider adding a `where T: Foo` bound
+ = note: expected type `<T as Foo>::Out`
+ found type `&'static str`
error: aborting due to previous error
-For more information about this error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0326`.
--- /dev/null
+// compile-pass
+
+trait ConstDefault {
+ const DEFAULT: Self;
+}
+
+trait Foo: Sized {}
+
+trait FooExt: Foo {
+ type T: ConstDefault;
+}
+
+trait Bar<F: FooExt> {
+ const T: F::T;
+}
+
+impl<F: FooExt> Bar<F> for () {
+ const T: F::T = <F::T as ConstDefault>::DEFAULT;
+}
+
+fn main() {}
--- /dev/null
+fn foo() -> i32 {
+ 0
+}
+
+fn main() {
+ let x: i32 = {
+ //~^ ERROR mismatched types
+ foo(); //~ HELP consider removing this semicolon
+ };
+}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/block-expression-remove-semicolon.rs:6:18
+ |
+LL | let x: i32 = {
+ | __________________^
+LL | |
+LL | | foo();
+ | | - help: consider removing this semicolon
+LL | | };
+ | |_____^ expected i32, found ()
+ |
+ = note: expected type `i32`
+ found type `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
--- /dev/null
+// run-pass
+
+#![feature(nll)]
+
+enum Nat {
+ S(Box<Nat>),
+ Z
+}
+fn test(x: &mut Nat) {
+ let mut p = &mut *x;
+ loop {
+ match p {
+ &mut Nat::Z => break,
+ &mut Nat::S(ref mut n) => p = &mut *n
+ }
+ }
+}
+
+fn main() {}
--- /dev/null
+// rust-lang/rust#57979 : the initial support for `impl Trait` didn't
+// properly check syntax hidden behind an associated type projection,
+// but it did catch *some cases*. This is checking that we continue to
+// properly emit errors for those, even with the new
+// future-incompatibility warnings.
+//
+// issue-57979-nested-impl-trait-in-assoc-proj.rs shows the main case
+// that we were previously failing to catch.
+
+struct Deeper<T>(T);
+
+mod allowed {
+ #![allow(nested_impl_trait)]
+
+ pub trait Foo<T> { }
+ pub trait Bar { }
+ pub trait Quux { type Assoc; }
+ pub fn demo(_: impl Quux<Assoc=super::Deeper<impl Foo<impl Bar>>>) { }
+ //~^ ERROR nested `impl Trait` is not allowed
+}
+
+mod warned {
+ #![warn(nested_impl_trait)]
+
+ pub trait Foo<T> { }
+ pub trait Bar { }
+ pub trait Quux { type Assoc; }
+ pub fn demo(_: impl Quux<Assoc=super::Deeper<impl Foo<impl Bar>>>) { }
+ //~^ ERROR nested `impl Trait` is not allowed
+}
+
+mod denied {
+ #![deny(nested_impl_trait)]
+
+ pub trait Foo<T> { }
+ pub trait Bar { }
+ pub trait Quux { type Assoc; }
+ pub fn demo(_: impl Quux<Assoc=super::Deeper<impl Foo<impl Bar>>>) { }
+ //~^ ERROR nested `impl Trait` is not allowed
+}
+
+fn main() { }
--- /dev/null
+error[E0666]: nested `impl Trait` is not allowed
+ --> $DIR/issue-57979-deeply-nested-impl-trait-in-assoc-proj.rs:18:59
+ |
+LL | pub fn demo(_: impl Quux<Assoc=super::Deeper<impl Foo<impl Bar>>>) { }
+ | ---------^^^^^^^^-
+ | | |
+ | | nested `impl Trait` here
+ | outer `impl Trait`
+
+error[E0666]: nested `impl Trait` is not allowed
+ --> $DIR/issue-57979-deeply-nested-impl-trait-in-assoc-proj.rs:28:59
+ |
+LL | pub fn demo(_: impl Quux<Assoc=super::Deeper<impl Foo<impl Bar>>>) { }
+ | ---------^^^^^^^^-
+ | | |
+ | | nested `impl Trait` here
+ | outer `impl Trait`
+
+error[E0666]: nested `impl Trait` is not allowed
+ --> $DIR/issue-57979-deeply-nested-impl-trait-in-assoc-proj.rs:38:59
+ |
+LL | pub fn demo(_: impl Quux<Assoc=super::Deeper<impl Foo<impl Bar>>>) { }
+ | ---------^^^^^^^^-
+ | | |
+ | | nested `impl Trait` here
+ | outer `impl Trait`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0666`.
--- /dev/null
+// rust-lang/rust#57979 : the initial support for `impl Trait` didn't
+// properly check syntax hidden behind an associated type projection.
+// Here we test behavior of occurrences of `impl Trait` within a path
+// component in that context.
+
+mod allowed {
+ #![allow(nested_impl_trait)]
+
+ pub trait Bar { }
+ pub trait Quux<T> { type Assoc; }
+ pub fn demo(_: impl Quux<(), Assoc=<() as Quux<impl Bar>>::Assoc>) { }
+ impl<T> Quux<T> for () { type Assoc = u32; }
+}
+
+mod warned {
+ #![warn(nested_impl_trait)]
+
+ pub trait Bar { }
+ pub trait Quux<T> { type Assoc; }
+ pub fn demo(_: impl Quux<(), Assoc=<() as Quux<impl Bar>>::Assoc>) { }
+ //~^ WARN `impl Trait` is not allowed in path parameters
+ //~| WARN will become a hard error in a future release!
+ impl<T> Quux<T> for () { type Assoc = u32; }
+}
+
+mod denied {
+ #![deny(nested_impl_trait)]
+
+ pub trait Bar { }
+ pub trait Quux<T> { type Assoc; }
+ pub fn demo(_: impl Quux<(), Assoc=<() as Quux<impl Bar>>::Assoc>) { }
+ //~^ ERROR `impl Trait` is not allowed in path parameters
+ //~| WARN will become a hard error in a future release!
+ impl<T> Quux<T> for () { type Assoc = u32; }
+}
+
+fn main() { }
--- /dev/null
+warning: `impl Trait` is not allowed in path parameters
+ --> $DIR/issue-57979-impl-trait-in-path.rs:20:52
+ |
+LL | pub fn demo(_: impl Quux<(), Assoc=<() as Quux<impl Bar>>::Assoc>) { }
+ | ^^^^^^^^
+ |
+note: lint level defined here
+ --> $DIR/issue-57979-impl-trait-in-path.rs:16:13
+ |
+LL | #![warn(nested_impl_trait)]
+ | ^^^^^^^^^^^^^^^^^
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #59014 <https://github.com/rust-lang/rust/issues/59014>
+
+error: `impl Trait` is not allowed in path parameters
+ --> $DIR/issue-57979-impl-trait-in-path.rs:31:52
+ |
+LL | pub fn demo(_: impl Quux<(), Assoc=<() as Quux<impl Bar>>::Assoc>) { }
+ | ^^^^^^^^
+ |
+note: lint level defined here
+ --> $DIR/issue-57979-impl-trait-in-path.rs:27:13
+ |
+LL | #![deny(nested_impl_trait)]
+ | ^^^^^^^^^^^^^^^^^
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #59014 <https://github.com/rust-lang/rust/issues/59014>
+
+error: aborting due to previous error
+
--- /dev/null
+// rust-lang/rust#57979 : the initial support for `impl Trait` didn't
+// properly check syntax hidden behind an associated type projection.
+// Here we test behavior of occurrences of `impl Trait` within an
+// `impl Trait` in that context.
+
+mod allowed {
+ #![allow(nested_impl_trait)]
+
+ pub trait Foo<T> { }
+ pub trait Bar { }
+ pub trait Quux { type Assoc; }
+ pub fn demo(_: impl Quux<Assoc=impl Foo<impl Bar>>) { }
+}
+
+mod warned {
+ #![warn(nested_impl_trait)]
+
+ pub trait Foo<T> { }
+ pub trait Bar { }
+ pub trait Quux { type Assoc; }
+ pub fn demo(_: impl Quux<Assoc=impl Foo<impl Bar>>) { }
+ //~^ WARN nested `impl Trait` is not allowed
+ //~| WARN will become a hard error in a future release!
+}
+
+mod denied {
+ #![deny(nested_impl_trait)]
+
+ pub trait Foo<T> { }
+ pub trait Bar { }
+ pub trait Quux { type Assoc; }
+ pub fn demo(_: impl Quux<Assoc=impl Foo<impl Bar>>) { }
+ //~^ ERROR nested `impl Trait` is not allowed
+ //~| WARN will become a hard error in a future release!
+}
+
+fn main() { }
--- /dev/null
+warning: nested `impl Trait` is not allowed
+ --> $DIR/issue-57979-nested-impl-trait-in-assoc-proj.rs:21:45
+ |
+LL | pub fn demo(_: impl Quux<Assoc=impl Foo<impl Bar>>) { }
+ | ---------^^^^^^^^-
+ | | |
+ | | nested `impl Trait` here
+ | outer `impl Trait`
+ |
+note: lint level defined here
+ --> $DIR/issue-57979-nested-impl-trait-in-assoc-proj.rs:16:13
+ |
+LL | #![warn(nested_impl_trait)]
+ | ^^^^^^^^^^^^^^^^^
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #59014 <https://github.com/rust-lang/rust/issues/59014>
+
+error: nested `impl Trait` is not allowed
+ --> $DIR/issue-57979-nested-impl-trait-in-assoc-proj.rs:32:45
+ |
+LL | pub fn demo(_: impl Quux<Assoc=impl Foo<impl Bar>>) { }
+ | ---------^^^^^^^^-
+ | | |
+ | | nested `impl Trait` here
+ | outer `impl Trait`
+ |
+note: lint level defined here
+ --> $DIR/issue-57979-nested-impl-trait-in-assoc-proj.rs:27:13
+ |
+LL | #![deny(nested_impl_trait)]
+ | ^^^^^^^^^^^^^^^^^
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #59014 <https://github.com/rust-lang/rust/issues/59014>
+
+error: aborting due to previous error
+
--- /dev/null
+// run-pass
+
+pub trait Foo<T> {
+ fn foo(self) -> T;
+}
+
+impl<'a, T> Foo<T> for &'a str where &'a str: Into<T> {
+ fn foo(self) -> T {
+ panic!();
+ }
+}
+
+fn main() {}
--- /dev/null
+// run-pass
+
+pub struct Bar<T> {
+ items: Vec<&'static str>,
+ inner: T,
+}
+
+pub trait IntoBar<T> {
+ fn into_bar(self) -> Bar<T>;
+}
+
+impl<'a, T> IntoBar<T> for &'a str where &'a str: Into<T> {
+ fn into_bar(self) -> Bar<T> {
+ Bar {
+ items: Vec::new(),
+ inner: self.into(),
+ }
+ }
+}
+
+fn main() {}
--- /dev/null
+// run-pass
+
+pub struct Item {
+ _inner: &'static str,
+}
+
+pub struct Bar<T> {
+ items: Vec<Item>,
+ inner: T,
+}
+
+pub trait IntoBar<T> {
+ fn into_bar(self) -> Bar<T>;
+}
+
+impl<'a, T> IntoBar<T> for &'a str where &'a str: Into<T> {
+ fn into_bar(self) -> Bar<T> {
+ Bar {
+ items: Vec::new(),
+ inner: self.into(),
+ }
+ }
+}
+
+fn main() {}
--- /dev/null
+error[E0515]: cannot return value referencing function parameter
+ --> $DIR/issue-26619.rs:7:76
+ |
+LL | for s in vec!["1|2".to_string()].into_iter().filter_map(|ref line| self.make_entry(line)) {
+ | -------- ^^^^^^^^^^^^^^^^^^^^^ returns a value referencing data owned by the current function
+ | |
+ | function parameter borrowed here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0515`.
--- /dev/null
+#![feature(slice_patterns)]
+
+pub struct History<'a> { pub _s: &'a str }
+
+impl<'a> History<'a> {
+ pub fn get_page(&self) {
+ for s in vec!["1|2".to_string()].into_iter().filter_map(|ref line| self.make_entry(line)) {
+ //~^ ERROR borrowed value does not live long enough
+ println!("{:?}", s);
+ }
+ }
+
+ fn make_entry(&self, s: &'a String) -> Option<&str> {
+ let parts: Vec<_> = s.split('|').collect();
+ println!("{:?} -> {:?}", s, parts);
+
+ if let [commit, ..] = &parts[..] { Some(commit) } else { None }
+ }
+}
+
+fn main() {
+ let h = History{ _s: "" };
+ h.get_page();
+}
--- /dev/null
+error[E0597]: borrowed value does not live long enough
+ --> $DIR/issue-26619.rs:7:66
+ |
+LL | for s in vec!["1|2".to_string()].into_iter().filter_map(|ref line| self.make_entry(line)) {
+ | ^^^^^^^^ -- temporary value needs to live until here
+ | | |
+ | | temporary value dropped here while still borrowed
+ | temporary value does not live long enough
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
--- /dev/null
+// run-pass
+
+#![feature(decl_macro)]
+
+pub struct Foo {
+ bar: u32,
+}
+pub macro pattern($a:pat) {
+ Foo { bar: $a }
+}
+
+fn main() {
+ match (Foo { bar: 3 }) {
+ pattern!(3) => println!("Test OK"),
+ _ => unreachable!(),
+ }
+}
--- /dev/null
+// run-pass
+
+use std::marker::PhantomData;
+
+fn main() {
+ let _arr = [1; <Multiply<Five, Five>>::VAL];
+}
+
+trait TypeVal<T> {
+ const VAL: T;
+}
+
+struct Five;
+
+impl TypeVal<usize> for Five {
+ const VAL: usize = 5;
+}
+
+struct Multiply<N, M> {
+ _n: PhantomData<N>,
+ _m: PhantomData<M>,
+}
+
+impl<N, M> TypeVal<usize> for Multiply<N, M>
+ where N: TypeVal<usize>,
+ M: TypeVal<usize>,
+{
+ const VAL: usize = N::VAL * M::VAL;
+}
--- /dev/null
+#![feature(use_extern_macros)]
+trait Foo {}
+#[derive(Foo::Anything)] //~ ERROR failed to resolve: partially resolved path in a derive macro
+struct S;
--- /dev/null
+error[E0433]: failed to resolve: partially resolved path in a derive macro
+ --> $DIR/issue-46101.rs:3:10
+ |
+LL | #[derive(Foo::Anything)]
+ | ^^^^^^^^^^^^^ partially resolved path in a derive macro
+
+error[E0601]: `main` function not found in crate `issue_46101`
+ |
+ = note: consider adding a `main` function to `$DIR/issue-46101.rs`
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0433, E0601.
+For more information about an error, try `rustc --explain E0433`.
--- /dev/null
+use std::marker::PhantomData;
+
+trait DistributedIterator {
+ fn reduce(self)
+ where
+ Self: Sized,
+ {
+ unreachable!()
+ }
+}
+
+trait DistributedIteratorMulti<Source> {
+ type Item;
+}
+
+struct Connect<I>(PhantomData<fn(I)>);
+impl<I: for<'a> DistributedIteratorMulti<&'a ()>> DistributedIterator for Connect<I> where {}
+
+struct Cloned<Source>(PhantomData<fn(Source)>);
+impl<'a, Source> DistributedIteratorMulti<&'a Source> for Cloned<&'a Source> {
+ type Item = ();
+}
+
+struct Map<I, F> {
+ i: I,
+ f: F,
+}
+impl<I: DistributedIteratorMulti<Source>, F, Source> DistributedIteratorMulti<Source> for Map<I, F>
+where
+ F: A<<I as DistributedIteratorMulti<Source>>::Item>,
+{
+ type Item = ();
+}
+
+trait A<B> {}
+
+struct X;
+impl A<()> for X {}
+
+fn multi<I>(_reducer: I)
+where
+ I: for<'a> DistributedIteratorMulti<&'a ()>,
+{
+ DistributedIterator::reduce(Connect::<I>(PhantomData))
+}
+
+fn main() {
+ multi(Map { //~ ERROR implementation of `DistributedIteratorMulti` is not general enough
+ i: Cloned(PhantomData),
+ f: X,
+ });
+}
--- /dev/null
+error: implementation of `DistributedIteratorMulti` is not general enough
+ --> $DIR/issue-55731.rs:48:5
+ |
+LL | multi(Map {
+ | ^^^^^
+ |
+ = note: `DistributedIteratorMulti<&'0 ()>` would have to be implemented for the type `Cloned<&()>`, for any lifetime `'0`
+ = note: but `DistributedIteratorMulti<&'1 ()>` is actually implemented for the type `Cloned<&'1 ()>`, for some specific lifetime `'1`
+
+error: aborting due to previous error
+
--- /dev/null
+// run-pass
+
+use std::cell::UnsafeCell;
+use std::collections::HashMap;
+
+struct OnceCell<T> {
+ _value: UnsafeCell<Option<T>>,
+}
+
+impl<T> OnceCell<T> {
+ const INIT: OnceCell<T> = OnceCell {
+ _value: UnsafeCell::new(None),
+ };
+}
+
+pub fn crash<K, T>() {
+ let _ = OnceCell::<HashMap<K, T>>::INIT;
+}
+
+fn main() {}
+++ /dev/null
-// Regression test for #57979. This situation is meant to be an error.
-// As noted in the issue thread, we decided to forbid nested impl
-// trait of this kind:
-//
-// ```rust
-// fn foo() -> impl Foo<impl Bar> { .. }
-// ```
-//
-// Basically there are two hidden variables here, let's call them `X`
-// and `Y`, and we must prove that:
-//
-// ```
-// X: Foo<Y>
-// Y: Bar
-// ```
-//
-// However, the user is only giving us the return type `X`. It's true
-// that in some cases, we can infer `Y` from `X`, because `X` only
-// implements `Foo` for one type (and indeed the compiler does
-// inference of this kind), but I do recall that we intended to forbid
-// this -- in part because such inference is fragile, and there is not
-// necessarily a way for the user to be more explicit should the
-// inference fail (so you could get stuck with no way to port your
-// code forward if, for example, more impls are added to an existing
-// type).
-//
-// The same seems to apply in this situation. Here there are three impl traits, so we have
-//
-// ```
-// X: IntoIterator<Item = Y>
-// Y: Borrow<Data<Z>>
-// Z: AsRef<[u8]>
-// ```
-
-use std::borrow::Borrow;
-
-pub struct Data<TBody>(TBody);
-
-pub fn collect(_: impl IntoIterator<Item = impl Borrow<Data<impl AsRef<[u8]>>>>) {
- //~^ ERROR
- unimplemented!()
-}
+++ /dev/null
-error[E0666]: nested `impl Trait` is not allowed
- --> $DIR/issue-57979.rs:39:61
- |
-LL | pub fn collect(_: impl IntoIterator<Item = impl Borrow<Data<impl AsRef<[u8]>>>>) {
- | -----------------^^^^^^^^^^^^^^^^--
- | | |
- | | nested `impl Trait` here
- | outer `impl Trait`
-
-error[E0601]: `main` function not found in crate `issue_57979`
- |
- = note: consider adding a `main` function to `$DIR/issue-57979.rs`
-
-error: aborting due to 2 previous errors
-
-Some errors occurred: E0601, E0666.
-For more information about an error, try `rustc --explain E0601`.
const AC: Option<&'b str>;
}
-struct OKStruct { }
+struct OKStruct1 { }
-impl<'a: 'b, 'b> Anything<'a, 'b> for OKStruct {
+impl<'a: 'b, 'b> Anything<'a, 'b> for OKStruct1 {
const AC: Option<&'b str> = None;
}
-struct FailStruct1 { }
+struct FailStruct { }
-impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct1 {
+impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct {
const AC: Option<&'c str> = None;
//~^ ERROR: mismatched types
}
-struct FailStruct2 { }
+struct OKStruct2 { }
-impl<'a: 'b, 'b> Anything<'a, 'b> for FailStruct2 {
+impl<'a: 'b, 'b> Anything<'a, 'b> for OKStruct2 {
const AC: Option<&'a str> = None;
- //~^ ERROR: mismatched types
}
fn main() {}
note: the lifetime 'c as defined on the impl at 20:18...
--> $DIR/trait-associated-constant.rs:20:18
|
-LL | impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct1 {
+LL | impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct {
| ^^
note: ...does not necessarily outlive the lifetime 'b as defined on the impl at 20:14
--> $DIR/trait-associated-constant.rs:20:14
|
-LL | impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct1 {
+LL | impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct {
| ^^
-error[E0308]: mismatched types
- --> $DIR/trait-associated-constant.rs:28:5
- |
-LL | const AC: Option<&'a str> = None;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
- |
- = note: expected type `std::option::Option<&'b str>`
- found type `std::option::Option<&'a str>`
-note: the lifetime 'a as defined on the impl at 27:6...
- --> $DIR/trait-associated-constant.rs:27:6
- |
-LL | impl<'a: 'b, 'b> Anything<'a, 'b> for FailStruct2 {
- | ^^
-note: ...does not necessarily outlive the lifetime 'b as defined on the impl at 27:14
- --> $DIR/trait-associated-constant.rs:27:14
- |
-LL | impl<'a: 'b, 'b> Anything<'a, 'b> for FailStruct2 {
- | ^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.
--- /dev/null
+struct S<'1> { s: &'1 usize }
+//~^ ERROR lifetimes cannot start with a number
+//~| ERROR lifetimes cannot start with a number
+fn main() {
+ // verify that the parse error doesn't stop type checking
+ let x: usize = "";
+ //~^ ERROR mismatched types
+}
--- /dev/null
+error: lifetimes cannot start with a number
+ --> $DIR/numeric-lifetime.rs:1:10
+ |
+LL | struct S<'1> { s: &'1 usize }
+ | ^^
+
+error: lifetimes cannot start with a number
+ --> $DIR/numeric-lifetime.rs:1:20
+ |
+LL | struct S<'1> { s: &'1 usize }
+ | ^^
+
+error[E0308]: mismatched types
+ --> $DIR/numeric-lifetime.rs:6:20
+ |
+LL | let x: usize = "";
+ | ^^ expected usize, found reference
+ |
+ = note: expected type `usize`
+ found type `&'static str`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
--- /dev/null
+// run-pass
+
+fn main() {
+ let x = Box::new(0);
+ assert_eq!(0, *x + { drop(x); let _ = Box::new(main); 0 });
+}
Incremental,
RunMake,
Ui,
+ JsDocTest,
MirOpt,
}
"incremental" => Ok(Incremental),
"run-make" => Ok(RunMake),
"ui" => Ok(Ui),
+ "js-doc-test" => Ok(JsDocTest),
"mir-opt" => Ok(MirOpt),
_ => Err(()),
}
Incremental => "incremental",
RunMake => "run-make",
Ui => "ui",
+ JsDocTest => "js-doc-test",
MirOpt => "mir-opt",
};
fmt::Display::fmt(s, f)
use crate::common::{Codegen, CodegenUnits, DebugInfoBoth, DebugInfoGdb, DebugInfoLldb, Rustdoc};
use crate::common::{CompileFail, Pretty, RunFail, RunPass, RunPassValgrind};
use crate::common::{Config, TestPaths};
-use crate::common::{Incremental, MirOpt, RunMake, Ui};
+use crate::common::{Incremental, MirOpt, RunMake, Ui, JsDocTest};
use diff;
use crate::errors::{self, Error, ErrorKind};
use filetime::FileTime;
RunMake => self.run_rmake_test(),
RunPass | Ui => self.run_ui_test(),
MirOpt => self.run_mir_opt_test(),
+ JsDocTest => self.run_js_doc_test(),
}
}
match self.config.mode {
CompileFail => self.props.compile_pass,
RunPass => true,
+ JsDocTest => true,
Ui => self.props.compile_pass,
Incremental => {
let revision = self.revision
}
fn make_compile_args(&self, input_file: &Path, output_file: TargetLocation) -> Command {
- let is_rustdoc = self.config.src_base.ends_with("rustdoc-ui");
+ let is_rustdoc = self.config.src_base.ends_with("rustdoc-ui") ||
+ self.config.src_base.ends_with("rustdoc-js");
let mut rustc = if !is_rustdoc {
Command::new(&self.config.rustc_path)
} else {
rustc.arg(dir_opt);
}
RunFail | RunPassValgrind | Pretty | DebugInfoBoth | DebugInfoGdb | DebugInfoLldb
- | Codegen | Rustdoc | RunMake | CodegenUnits => {
+ | Codegen | Rustdoc | RunMake | CodegenUnits | JsDocTest => {
// do not use JSON output
}
}
fs::remove_dir(path)
}
+ fn run_js_doc_test(&self) {
+ if let Some(nodejs) = &self.config.nodejs {
+ let out_dir = self.output_base_dir();
+
+ self.document(&out_dir);
+
+ let root = self.config.find_rust_src_root().unwrap();
+ let res = self.cmd2procres(
+ Command::new(&nodejs)
+ .arg(root.join("src/tools/rustdoc-js/tester.js"))
+ .arg(out_dir.parent().expect("no parent"))
+ .arg(&self.testpaths.file.file_stem().expect("couldn't get file stem")),
+ );
+ if !res.status.success() {
+ self.fatal_proc_rec("rustdoc-js test failed!", &res);
+ }
+ } else {
+ self.fatal("no nodeJS");
+ }
+ }
+
fn run_ui_test(&self) {
// if the user specified a format in the ui test
// print the output to the stderr file, otherwise extract
--- /dev/null
+const fs = require('fs');
+
+const TEST_FOLDER = 'src/test/rustdoc-js-std/';
+
+function getNextStep(content, pos, stop) {
+ while (pos < content.length && content[pos] !== stop &&
+ (content[pos] === ' ' || content[pos] === '\t' || content[pos] === '\n')) {
+ pos += 1;
+ }
+ if (pos >= content.length) {
+ return null;
+ }
+ if (content[pos] !== stop) {
+ return pos * -1;
+ }
+ return pos;
+}
+
+// Stupid function extractor based on indent. Doesn't support block
+// comments. If someone puts a ' or an " in a block comment this
+// will blow up. Template strings are not tested and might also be
+// broken.
+function extractFunction(content, functionName) {
+ var indent = 0;
+ var splitter = "function " + functionName + "(";
+
+ while (true) {
+ var start = content.indexOf(splitter);
+ if (start === -1) {
+ break;
+ }
+ var pos = start;
+ while (pos < content.length && content[pos] !== ')') {
+ pos += 1;
+ }
+ if (pos >= content.length) {
+ break;
+ }
+ pos = getNextStep(content, pos + 1, '{');
+ if (pos === null) {
+ break;
+ } else if (pos < 0) {
+ content = content.slice(-pos);
+ continue;
+ }
+ while (pos < content.length) {
+ // Eat single-line comments
+ if (content[pos] === '/' && pos > 0 && content[pos-1] === '/') {
+ do {
+ pos += 1;
+ } while (pos < content.length && content[pos] !== '\n');
+
+ // Eat quoted strings
+ } else if (content[pos] === '"' || content[pos] === "'" || content[pos] === "`") {
+ var stop = content[pos];
+ var is_escaped = false;
+ do {
+ if (content[pos] === '\\') {
+ pos += 2;
+ } else {
+ pos += 1;
+ }
+ } while (pos < content.length &&
+ (content[pos] !== stop || content[pos - 1] === '\\'));
+
+ // Otherwise, check for indent
+ } else if (content[pos] === '{') {
+ indent += 1;
+ } else if (content[pos] === '}') {
+ indent -= 1;
+ if (indent === 0) {
+ return content.slice(start, pos + 1);
+ }
+ }
+ pos += 1;
+ }
+ content = content.slice(start + 1);
+ }
+ return null;
+}
+
+// Stupid function extractor for array.
+function extractArrayVariable(content, arrayName) {
+ var splitter = "var " + arrayName;
+ while (true) {
+ var start = content.indexOf(splitter);
+ if (start === -1) {
+ break;
+ }
+ var pos = getNextStep(content, start, '=');
+ if (pos === null) {
+ break;
+ } else if (pos < 0) {
+ content = content.slice(-pos);
+ continue;
+ }
+ pos = getNextStep(content, pos, '[');
+ if (pos === null) {
+ break;
+ } else if (pos < 0) {
+ content = content.slice(-pos);
+ continue;
+ }
+ while (pos < content.length) {
+ if (content[pos] === '"' || content[pos] === "'") {
+ var stop = content[pos];
+ do {
+ if (content[pos] === '\\') {
+ pos += 2;
+ } else {
+ pos += 1;
+ }
+ } while (pos < content.length &&
+ (content[pos] !== stop || content[pos - 1] === '\\'));
+ } else if (content[pos] === ']' &&
+ pos + 1 < content.length &&
+ content[pos + 1] === ';') {
+ return content.slice(start, pos + 2);
+ }
+ pos += 1;
+ }
+ content = content.slice(start + 1);
+ }
+ return null;
+}
+
+// Stupid function extractor for variable.
+function extractVariable(content, varName) {
+ var splitter = "var " + varName;
+ while (true) {
+ var start = content.indexOf(splitter);
+ if (start === -1) {
+ break;
+ }
+ var pos = getNextStep(content, start, '=');
+ if (pos === null) {
+ break;
+ } else if (pos < 0) {
+ content = content.slice(-pos);
+ continue;
+ }
+ while (pos < content.length) {
+ if (content[pos] === '"' || content[pos] === "'") {
+ var stop = content[pos];
+ do {
+ if (content[pos] === '\\') {
+ pos += 2;
+ } else {
+ pos += 1;
+ }
+ } while (pos < content.length &&
+ (content[pos] !== stop || content[pos - 1] === '\\'));
+ } else if (content[pos] === ';') {
+ return content.slice(start, pos + 1);
+ }
+ pos += 1;
+ }
+ content = content.slice(start + 1);
+ }
+ return null;
+}
+
+function loadContent(content) {
+ var Module = module.constructor;
+ var m = new Module();
+ m._compile(content, "tmp.js");
+ m.exports.ignore_order = content.indexOf("\n// ignore-order\n") !== -1 ||
+ content.startsWith("// ignore-order\n");
+ m.exports.exact_check = content.indexOf("\n// exact-check\n") !== -1 ||
+ content.startsWith("// exact-check\n");
+ m.exports.should_fail = content.indexOf("\n// should-fail\n") !== -1 ||
+ content.startsWith("// should-fail\n");
+ return m.exports;
+}
+
+function readFile(filePath) {
+ return fs.readFileSync(filePath, 'utf8');
+}
+
+function loadThings(thingsToLoad, kindOfLoad, funcToCall, fileContent) {
+ var content = '';
+ for (var i = 0; i < thingsToLoad.length; ++i) {
+ var tmp = funcToCall(fileContent, thingsToLoad[i]);
+ if (tmp === null) {
+ console.error('unable to find ' + kindOfLoad + ' "' + thingsToLoad[i] + '"');
+ process.exit(1);
+ }
+ content += tmp;
+ content += 'exports.' + thingsToLoad[i] + ' = ' + thingsToLoad[i] + ';';
+ }
+ return content;
+}
+
+function lookForEntry(entry, data) {
+ for (var i = 0; i < data.length; ++i) {
+ var allGood = true;
+ for (var key in entry) {
+ if (!entry.hasOwnProperty(key)) {
+ continue;
+ }
+ var value = data[i][key];
+ // To make our life easier, if there is a "parent" type, we add it to the path.
+ if (key === 'path' && data[i]['parent'] !== undefined) {
+ if (value.length > 0) {
+ value += '::' + data[i]['parent']['name'];
+ } else {
+ value = data[i]['parent']['name'];
+ }
+ }
+ if (value !== entry[key]) {
+ allGood = false;
+ break;
+ }
+ }
+ if (allGood === true) {
+ return i;
+ }
+ }
+ return null;
+}
+
+function findFile(dir, name, extension) {
+ var entries = fs.readdirSync(dir);
+ for (var i = 0; i < entries.length; ++i) {
+ var entry = entries[i];
+ var file_type = fs.statSync(dir + entry);
+ if (file_type.isDirectory()) {
+ continue;
+ }
+ if (entry.startsWith(name) && entry.endsWith(extension)) {
+ return entry;
+ }
+ }
+ return null;
+}
+
+function readFileMatching(dir, name, extension) {
+ if (dir.endsWith("/") === false) {
+ dir += "/";
+ }
+ var f = findFile(dir, name, extension);
+ if (f === null) {
+ return "";
+ }
+ return readFile(dir + f);
+}
+
+function main(argv) {
+ if (argv.length !== 3) {
+ console.error("Expected toolchain to check as argument (for example \
+ 'x86_64-apple-darwin')");
+ return 1;
+ }
+ var toolchain = argv[2];
+
+ var mainJs = readFileMatching("build/" + toolchain + "/doc/", "main", ".js");
+ var ALIASES = readFileMatching("build/" + toolchain + "/doc/", "aliases", ".js");
+ var searchIndex = readFileMatching("build/" + toolchain + "/doc/",
+ "search-index", ".js").split("\n");
+ if (searchIndex[searchIndex.length - 1].length === 0) {
+ searchIndex.pop();
+ }
+ searchIndex.pop();
+ searchIndex = loadContent(searchIndex.join("\n") + '\nexports.searchIndex = searchIndex;');
+ finalJS = "";
+
+ var arraysToLoad = ["itemTypes"];
+ var variablesToLoad = ["MAX_LEV_DISTANCE", "MAX_RESULTS",
+ "GENERICS_DATA", "NAME", "INPUTS_DATA", "OUTPUT_DATA",
+ "TY_PRIMITIVE", "TY_KEYWORD",
+ "levenshtein_row2"];
+ // execQuery first parameter is built in getQuery (which takes in the search input).
+ // execQuery last parameter is built in buildIndex.
+ // buildIndex requires the hashmap from search-index.
+ var functionsToLoad = ["buildHrefAndPath", "pathSplitter", "levenshtein", "validateResult",
+ "getQuery", "buildIndex", "execQuery", "execSearch"];
+
+ finalJS += 'window = { "currentCrate": "std" };\n';
+ finalJS += 'var rootPath = "../";\n';
+ finalJS += ALIASES;
+ finalJS += loadThings(arraysToLoad, 'array', extractArrayVariable, mainJs);
+ finalJS += loadThings(variablesToLoad, 'variable', extractVariable, mainJs);
+ finalJS += loadThings(functionsToLoad, 'function', extractFunction, mainJs);
+
+ var loaded = loadContent(finalJS);
+ var index = loaded.buildIndex(searchIndex.searchIndex);
+
+ var errors = 0;
+
+ fs.readdirSync(TEST_FOLDER).forEach(function(file) {
+ var loadedFile = loadContent(readFile(TEST_FOLDER + file) +
+ 'exports.QUERY = QUERY;exports.EXPECTED = EXPECTED;');
+ const expected = loadedFile.EXPECTED;
+ const query = loadedFile.QUERY;
+ const filter_crate = loadedFile.FILTER_CRATE;
+ const ignore_order = loadedFile.ignore_order;
+ const exact_check = loadedFile.exact_check;
+ const should_fail = loadedFile.should_fail;
+ var results = loaded.execSearch(loaded.getQuery(query), index);
+ process.stdout.write('Checking "' + file + '" ... ');
+ var error_text = [];
+ for (var key in expected) {
+ if (!expected.hasOwnProperty(key)) {
+ continue;
+ }
+ if (!results.hasOwnProperty(key)) {
+ error_text.push('==> Unknown key "' + key + '"');
+ break;
+ }
+ var entry = expected[key];
+ var prev_pos = -1;
+ for (var i = 0; i < entry.length; ++i) {
+ var entry_pos = lookForEntry(entry[i], results[key]);
+ if (entry_pos === null) {
+ error_text.push("==> Result not found in '" + key + "': '" +
+ JSON.stringify(entry[i]) + "'");
+ } else if (exact_check === true && prev_pos + 1 !== entry_pos) {
+ error_text.push("==> Exact check failed at position " + (prev_pos + 1) + ": " +
+ "expected '" + JSON.stringify(entry[i]) + "' but found '" +
+ JSON.stringify(results[key][i]) + "'");
+ } else if (ignore_order === false && entry_pos < prev_pos) {
+ error_text.push("==> '" + JSON.stringify(entry[i]) + "' was supposed to be " +
+ " before '" + JSON.stringify(results[key][entry_pos]) + "'");
+ } else {
+ prev_pos = entry_pos;
+ }
+ }
+ }
+ if (error_text.length === 0 && should_fail === true) {
+ errors += 1;
+ console.error("FAILED");
+ console.error("==> Test was supposed to fail but all items were found...");
+ } else if (error_text.length !== 0 && should_fail === false) {
+ errors += 1;
+ console.error("FAILED");
+ console.error(error_text.join("\n"));
+ } else {
+ console.log("OK");
+ }
+ });
+ return errors;
+}
+
+process.exit(main(process.argv));
const fs = require('fs');
+const { spawnSync } = require('child_process');
const TEST_FOLDER = 'src/test/rustdoc-js/';
return null;
}
-function main(argv) {
- if (argv.length !== 3) {
- console.error("Expected toolchain to check as argument (for example 'x86_64-apple-darwin'");
- return 1;
- }
- var toolchain = argv[2];
-
- var mainJs = readFile("build/" + toolchain + "/doc/main.js");
- var ALIASES = readFile("build/" + toolchain + "/doc/aliases.js");
- var searchIndex = readFile("build/" + toolchain + "/doc/search-index.js").split("\n");
+function load_files(out_folder, crate) {
+ var mainJs = readFile(out_folder + "/main.js");
+ var ALIASES = readFile(out_folder + "/aliases.js");
+ var searchIndex = readFile(out_folder + "/search-index.js").split("\n");
if (searchIndex[searchIndex.length - 1].length === 0) {
searchIndex.pop();
}
var functionsToLoad = ["buildHrefAndPath", "pathSplitter", "levenshtein", "validateResult",
"getQuery", "buildIndex", "execQuery", "execSearch"];
- finalJS += 'window = { "currentCrate": "std" };\n';
+ finalJS += 'window = { "currentCrate": "' + crate + '" };\n';
finalJS += 'var rootPath = "../";\n';
finalJS += ALIASES;
finalJS += loadThings(arraysToLoad, 'array', extractArrayVariable, mainJs);
finalJS += loadThings(functionsToLoad, 'function', extractFunction, mainJs);
var loaded = loadContent(finalJS);
- var index = loaded.buildIndex(searchIndex.searchIndex);
+ return [loaded, loaded.buildIndex(searchIndex.searchIndex)];
+}
+
+function main(argv) {
+ if (argv.length < 4) {
+ console.error("USAGE: node tester.js OUT_FOLDER [TESTS]");
+ return 1;
+ }
+ if (argv[2].substr(-1) !== "/") {
+ argv[2] += "/";
+ }
+ const out_folder = argv[2];
var errors = 0;
- fs.readdirSync(TEST_FOLDER).forEach(function(file) {
- var loadedFile = loadContent(readFile(TEST_FOLDER + file) +
+ for (var j = 3; j < argv.length; ++j) {
+ const test_name = argv[j];
+
+ process.stdout.write('Checking "' + test_name + '" ... ');
+ if (!fs.existsSync(TEST_FOLDER + test_name + ".js")) {
+ errors += 1;
+ console.error("FAILED");
+ console.error("==> Missing '" + test_name + ".js' file...");
+ continue;
+ }
+
+ const test_out_folder = out_folder + test_name;
+
+ var [loaded, index] = load_files(test_out_folder, test_name);
+ var loadedFile = loadContent(readFile(TEST_FOLDER + test_name + ".js") +
'exports.QUERY = QUERY;exports.EXPECTED = EXPECTED;');
const expected = loadedFile.EXPECTED;
const query = loadedFile.QUERY;
const exact_check = loadedFile.exact_check;
const should_fail = loadedFile.should_fail;
var results = loaded.execSearch(loaded.getQuery(query), index);
- process.stdout.write('Checking "' + file + '" ... ');
var error_text = [];
for (var key in expected) {
if (!expected.hasOwnProperty(key)) {
} else {
console.log("OK");
}
- });
+ }
return errors;
}